npm package: @origints/csv
Description: CSV parsing and navigation for Origins with full lineage tracking
Latest version: 0.3.2

# @origints/csv

> CSV parsing and navigation for Origins with full lineage tracking.

---

## Features

- Parse CSV with RFC 4180 support (quoted fields, embedded newlines)
- Header row detection and column-by-name access
- Lazy row and column iteration via generators
- Type coercion (number, boolean) on demand
- JSON conversion with customizable options
- Custom delimiters, quote characters, comments, and trim
- Integrates with Origins transform registry

---

## Installation

```bash
npm install @origints/csv @origints/core
```

---

## Usage with Planner

### Extract values from specific cells

```ts
import { Planner, loadFile, run } from '@origints/core'
import { parseCsv } from '@origints/csv'

const plan = new Planner()
  .in(loadFile('users.csv'))
  .mapIn(parseCsv({ header: true }))
  .emit((out, $) =>
    out
      .add('firstName', $.row(0).col('name').string())
      .add('firstAge', $.row(0).col('age').number())
  )
  .compile()

const result = await run(plan, { readFile, registry })
// result.value: { firstName: 'Alice', firstAge: 30 }
```

### Iterate over all rows

Use `rows()` to extract data from every row as an array:

```ts
// users.csv:
// name,age,active
// Alice,30,true
// Bob,25,false

const plan = new Planner()
  .in(loadFile('users.csv'))
  .mapIn(parseCsv({ header: true }))
  .emit((out, $) =>
    out.add(
      'users',
      $.rows(row => ({
        kind: 'object',
        properties: {
          name: row.col('name').string(),
          age: row.col('age').number(),
          active: row.col('active').boolean(),
        },
      }))
    )
  )
  .compile()

const result = await run(plan, { readFile, registry })
// result.value: {
//   users: [
//     { name: 'Alice', age: 30, active: true },
//     { name: 'Bob', age: 25, active: false },
//   ]
// }
```

### Index-based access (headerless CSV)

```ts
const plan = new Planner()
  .in(loadFile('data.csv'))
  .mapIn(parseCsv())
  .emit((out, $) =>
    out.add(
      'pairs',
      $.rows(row => ({
        kind: 'object',
        properties: {
          key: row.at(0).string(),
          value: row.at(1).string(),
        },
      }))
    )
  )
  .compile()
```

### Combine CSV with other data sources

```ts
const plan = new Planner()
  .in(loadFile('employees.csv'))
  .mapIn(parseCsv({ header: true }))
  .emit((out, $) =>
    out.add(
      'employees',
      $.rows(row => row.col('name').string())
    )
  )
  .in(loadFile('config.json'))
  .mapIn(parseJson())
  .emit((out, $) => out.add('department', $.get('department').string()))
  .compile()
```

### Standalone usage (without Planner)

For direct CSV navigation and manipulation:

```ts
import { parseCsvText, CsvTable } from '@origints/csv'

const table = parseCsvText(
  'name,age,email\nAlice,30,alice@example.com\nBob,25,bob@example.com',
  {
    header: true,
  }
)

// Access rows
const row = table.row(0)
if (row.ok) {
  console.log(row.value.col('name')) // ok: 'Alice'
  console.log(row.value.fieldAsNumber('age')) // ok: 30
}

// Lazy iteration
for (const row of table) {
  const email = row.col('email')
  if (email.ok) console.log(email.value)
}

// Column extraction
for (const name of table.column('name')) {
  console.log(name)
}

// Direct cell access
const cell = table.cell(1, 'email')
if (cell.ok) console.log(cell.value) // 'bob@example.com'

// Bulk materialization
const records = table.asRecords()
if (records.ok) console.log(records.value)
// [{ name: 'Alice', age: '30', ... }, { name: 'Bob', age: '25', ... }]
```

### Type coercion

```ts
const row = table.row(0)
if (row.ok) {
  const age = row.value.fieldAsNumber('age')
  if (age.ok) console.log(age.value) // 30

  const active = row.value.fieldAsBoolean('active')
  if (active.ok) console.log(active.value) // true
}
```

### JSON conversion

```ts
import { parseCsvText, toJson } from '@origints/csv'

const table = parseCsvText(csvString, { header: true })

// Convert to JSON with type coercion
const json = toJson(table, {
  parseNumbers: true,
  parseBooleans: true,
  emptyAsNull: true,
})
if (json.ok) console.log(json.value)
// [{ name: 'Alice', age: 30, active: true }, ...]
```

### Parse options

```ts
parseCsvText(input, {
  header: true, // First row is header
  delimiter: ';', // Field delimiter (default: ',')
  quoteChar: '"', // Quote character (default: '"')
  escapeChar: '"', // Escape character (default: '"')
  skipEmptyLines: true, // Skip blank rows
  trimFields: true, // Trim whitespace from fields
  comment: '#', // Lines starting with this char are skipped
})
```

---

## API

| Export                                                                   | Description                                           |
| ------------------------------------------------------------------------ | ----------------------------------------------------- |
| `parseCsv(options?)`                                                     | Create a transform AST for use with `Planner.mapIn()` |
| `parseCsvText(input, options?)`                                          | Parse CSV string directly (standalone)                |
| `parseCsvImpl`                                                           | Sync transform implementation (string input)          |
| `parseCsvAsyncImpl`                                                      | Async transform implementation (string or stream)     |
| `registerCsvTransforms(registry)`                                        | Register all CSV transforms with a registry           |
| `CsvTable`                                                               | Root table with row/column/cell access                |
| `CsvRow`                                                                 | Row wrapper with field access and type coercion       |
| `toJson(table, options?)`                                                | Convert CsvTable to JSON                              |
| `toJsonValue(table)`                                                     | Convert CsvTable to JSON with defaults                |
| `ok`, `parseFail`, `typeFail`, `missingFail`, `boundsFail`, `headerFail` | Result helpers                                        |
| `formatCsvPath`                                                          | Format path for display                               |

---

## License

MIT