# typed-csv A TypeScript library for typed CSV data with inline schema validation using a TypeScript-like syntax with `;` instead of `,`. ## Installation ```bash npm install typed-csv ``` ## Usage ### Basic Example ```typescript import { defineSchema } from 'typed-csv'; // Define a schema const stringSchema = defineSchema('string'); const numberSchema = defineSchema('number'); const booleanSchema = defineSchema('boolean'); // Parse values const name = stringSchema.parse('hello'); // "hello" const age = numberSchema.parse('42'); // 42 const active = booleanSchema.parse('true'); // true // Validate parsed values stringSchema.validator(name); // true numberSchema.validator(name); // false ``` ### Tuples ```typescript const tupleSchema = defineSchema('[string; number; boolean]'); const value1 = tupleSchema.parse('[hello; 42; true]'); // ["hello", 42, true] tupleSchema.validator(value1); // true tupleSchema.validator(['a', 'b', true]); // false (second element should be number) ``` ### Arrays ```typescript // Array syntax: Type[] const stringArray = defineSchema('string[]'); const numberArray = defineSchema('number[]'); const names = stringArray.parse('[alice; bob; charlie]'); // ["alice", "bob", "charlie"] const numbers = numberArray.parse('[1; 2; 3; 4; 5]'); // [1, 2, 3, 4, 5] ``` ### Array of Tuples ```typescript const schema = defineSchema('[string; number][]'); const data = schema.parse('[[a; 1]; [b; 2]; [c; 3]]'); // [["a", 1], ["b", 2], ["c", 3]] ``` ### Escaping Special Characters Use `\` to escape special characters `;`, `[`, `]`, and `\` in string values: ```typescript const schema = defineSchema('string'); const value1 = schema.parse('hello\\;world'); // "hello;world" const value2 = schema.parse('hello\\[world'); // "hello[world" const value3 = schema.parse('hello\\\\world'); // "hello\\world" // In tuples const tupleSchema = defineSchema('[string; string]'); const tuple = tupleSchema.parse('hello\\;world; test'); // ["hello;world", "test"] ``` ### String Identifiers Any identifier (including hyphens) is treated as a string schema: ```typescript const schema = defineSchema('word-smith'); const value = schema.parse('word-smith'); // "word-smith" ``` ## API ### `defineSchema(schemaString: string): ParsedSchema` Parses a schema string and returns an object with: - `schema`: The parsed schema AST - `validator`: A function to validate values against the schema - `parse`: A function to parse value strings ### `parseSchema(schemaString: string): Schema` Parses a schema string and returns the schema AST. ### `parseValue(schema: Schema, valueString: string): unknown` Parses a value string according to the given schema. ### `createValidator(schema: Schema): (value: unknown) => boolean` Creates a validation function for the given schema. ### `schemaToTypeString(schema: Schema): string` Converts a schema AST back to a human-readable type string. ### `ParseError` Error class thrown for invalid schema syntax. ### Types The following TypeScript types are exported: - `Schema` — union of all schema AST node types - `ParsedSchema` — the return type of `defineSchema()` - `PrimitiveSchema`, `TupleSchema`, `ArraySchema` — AST node types - `ReferenceSchema`, `ReverseReferenceSchema` — reference AST node types - `StringLiteralSchema`, `UnionSchema` — literal and union AST node types ## Schema Syntax | Type | Schema | Example Value | |------|--------|---------------| | String | `string` or `identifier` | `hello` | | Int | `int` | `42` | | Float | `float` | `3.14` | | Number | `number` | `42` or `3.14` | > **Note:** `int`, `float`, and `number` all collapse to the `number` type in generated TypeScript declarations (`schemaToTypeString`). The distinction is preserved at parse time — `int` rejects non-integer values while `float`/`number` accept them. | Boolean | `boolean` | `true` or `false` | | Tuple | `[Type1; Type2; ...]` | `[hello; 42; true]` | | Array | `Type[]` | `[1; 2; 3]` | | Array of Tuples | `[Type1; Type2][]` | `[[a; 1]; [b; 2]]` | | Union | `Type1 \| Type2` | `hello` or `42` (reference members tried first) | | String Literal | `'on' \| 'off'` or `"red"` | `on` or `off` | | Reference | `@tablename` or `@tablename[]` | (resolved at CSV load time) | | Reverse Reference | `~tablename(fk)` | (resolved at CSV load time) | ## Notes - Semicolons `;` are used as separators instead of commas `,` - Tuple and array values **must** be wrapped in brackets `[]` (e.g. `[a; b]`) - `[single]` is a 1-tuple, not an array — use `Type[]` for arrays - In a union, **reference members are tried before non-reference members** (e.g. `@users | string` resolves `1` to the user object, falling back to a plain string when the reference doesn't match) - Special characters can be escaped with backslash: `\;`, `\[`, `\]`, `\\` - Empty arrays/tuples are not allowed - In CSV schema rows, double-quoted string literals like `"active" | "inactive"` are handled automatically by the loader; avoid commas inside string literals (use single-quoted literals like `'a,b'` for those) - For CSV loading with reference resolution, see [csv-loader.md](./csv-loader.md) ## Migration from 1.x Version 2.0.0 introduces breaking changes to the schema DSL: 1. **Composite values must be fully bracketed.** Tuple and array values now always require `[]` — `[a; 1]; [b; 2]` is no longer accepted; write `[[a; 1]; [b; 2]]`. 2. **The `[Type][]` array form is removed.** Use `Type[]` (e.g. `[string; number][]` instead of `[[string; number]][]`). 3. **`[single]` is now a 1-tuple, not an array.** Use `Type[]` for single-element arrays. 4. **Union resolution prefers reference members.** In a union containing references, reference members are tried before non-reference members regardless of author order (see the notes above). 5. **Schema cells may be fully quoted.** Double-quoted string literals like `"active" | "inactive"` in a CSV schema row are handled automatically by the loader. ```javascript // rspack.config.js module.exports = { module: { rules: [ { test: /\.schema\.csv$/, use: 'typed-csv/csv-loader', }, ], }, }; ``` ## License ISC