Implement loader-side escaping for the schema row to prevent `csv-parse` from misinterpreting double-quoted string literals (e.g., `"active" | "inactive"`) as field delimiters.
179 lines
5.0 KiB
Markdown
179 lines
5.0 KiB
Markdown
# 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` |
|
|
| 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)
|
|
|
|
```javascript
|
|
// rspack.config.js
|
|
module.exports = {
|
|
module: {
|
|
rules: [
|
|
{
|
|
test: /\.schema\.csv$/,
|
|
use: 'typed-csv/csv-loader',
|
|
},
|
|
],
|
|
},
|
|
};
|
|
```
|
|
|
|
## License
|
|
|
|
ISC
|