Skip to content

@origints/csv

CSV parsing with RFC 4180 support, optional header row, predicate-based column lookup, and row filtering.

Terminal window
npm install @origints/csv @origints/core
  • RFC 4180 support (quoted fields, embedded newlines)
  • Header row support and column-by-name access
  • Predicate-based column lookup (colWhere)
  • Row filtering (rowsWhere) and row search (findRow)
  • Type coercion (number, boolean) on demand
  • Custom delimiters, quote characters, comments, and trim
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 }
const plan = new Planner()
.in(loadFile('users.csv'))
.mapIn(parseCsv({ header: true }))
.emit((out, $) =>
out.add(
'users',
$.rows(row => ({
name: row.col('name').string(),
age: row.col('age').number(),
active: row.col('active').boolean(),
}))
)
)
.compile()

Find a column by matching its header:

import { col } from '@origints/csv'
$.rows(row => ({
revenue: row.colWhere(col.contains('Revenue')).number(),
name: row.colWhere(col.equals('Company Name')).string(),
}))
import { rowCol, col } from '@origints/csv'
$.rowsWhere(rowCol('status', col.equals('active')), row => ({
name: row.col('name').string(),
dept: row.colWhere(col.contains('department')).string(),
}))
import { rowCol, col } from '@origints/csv'
$.findRow(rowCol('id', col.equals('ABC-123')))
.col('email')
.string()
import { col } from '@origints/csv'
col.equals('Revenue') // exact match (case-sensitive by default)
col.contains('rev') // substring (case-insensitive by default)
col.startsWith('Total') // prefix (case-insensitive by default)
col.endsWith('USD') // suffix (case-insensitive by default)
col.matches(/^Q[1-4] \d{4}$/) // regex
col.isEmpty() // empty string
col.isNotEmpty() // non-empty
// Composition
col.contains('revenue').and(col.startsWith('total'))
col.equals('A').or(col.equals('B'))
col.isEmpty().not()

Scope-aware predicates resolve variable values at runtime. Use with forEach for data-driven column lookup:

import { col } from '@origints/csv'
col.equalsRef('varName') // exact match against bound variable
col.containsRef('varName') // substring match (case-insensitive)
col.startsWithRef('varName', ['path']) // prefix match with path navigation
import { forEach, literal } from '@origints/core'
import { col } from '@origints/csv'
forEach(
literal(['Revenue', 'Cost']),
'colName',
$.rows(row => row.colWhere(col.equalsRef('colName')).number())
)

Composition works normally:

col.equalsRef('a').or(col.startsWithRef('b'))

Note: colWhere caches are automatically bypassed for scope-dependent predicates (equalsRef, containsRef, startsWithRef).

import { parseCsvText } from '@origints/csv'
const table = parseCsvText('name,age\nAlice,30\nBob,25', { header: true })
for (const row of table) {
const name = row.col('name')
if (name.ok) console.log(name.value)
}
ExportDescription
parseCsv(options?)Transform AST for Planner.mapIn()
parseCsvText(input, options?)Parse CSV string directly
registerCsvTransforms(registry)Register CSV transforms
CsvTableTable with row/column/cell access
CsvRowRow with field access and type coercion
toJson(table, options?)Convert to JSON
colString predicate factory
col.equalsRef, col.containsRef, col.startsWithRefDynamic string predicate factories
rowCol, rowAtRow predicate factories

MIT