Files
inline-schema/README.md
T
hypercross 641af7341a perf(csv-loader): optimize reverse reference resolution
Implement a reverse lookup cache to avoid re-filtering the entire
referenced table for every row during reverse reference resolution.
This improves performance from O(N*M) to O(N+M) where N is the number
of rows in the current table and M is the number of rows in the
referenced table.

Also update documentation to reflect the new union resolution
behavior and migration notes for version 2.0.0.
2026-08-06 10:27:18 +08:00

191 lines
6.1 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` |
> **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