Refactor union resolution to explicitly try reference members before non-reference members. This replaces the previous error-message-based fallback with a deterministic, structural approach. - Update `parseValueWithReferences` and `resolveNestedReferences` to partition members by reference presence. - Update documentation in `README.md`, `AGENTS.md`, and `syntax-rework-plan.md` to reflect this behavior.
44 lines
3.3 KiB
Markdown
44 lines
3.3 KiB
Markdown
# AGENTS.md
|
|
|
|
## Commands
|
|
|
|
- **Build:** `npm run build` (tsup, CJS + ESM + d.ts for all entry points)
|
|
- **Test:** `npm run test` (vitest run) | `npm run test:watch` (vitest watch)
|
|
- **Type check:** `npm run typecheck`
|
|
- **Run a single test:** `npx vitest run -t "test name pattern"`
|
|
|
|
No linter or formatter is configured. No CI pipeline exists.
|
|
|
|
## Architecture
|
|
|
|
Single-package TypeScript library with two runtime entry points:
|
|
|
|
- **`typed-csv`** (`src/index.ts`) — core schema parser, value parser, and validator
|
|
- `src/parser.ts` — `parseSchema()` turns schema strings into AST (`Schema` type)
|
|
- `src/validator.ts` — `parseValue()` and `createValidator()` operate on the AST
|
|
- `src/types.ts` — union type `Schema = Primitive | Tuple | Array | Reference | StringLiteral | Union`
|
|
|
|
- **`typed-csv/csv-loader`** (`src/csv-loader/loader.ts`) — CSV loader with `@table` reference resolution
|
|
- `loader.ts` — `parseCsv()` (eager resolution) and `csvToModule()` (accessor-based output with lazy resolution); `resolveReferences: false` mode stores IDs instead of resolved objects
|
|
- `webpack.ts`, `rollup.ts`, `esbuild.ts` — bundler plugin wrappers around `csvToModule`
|
|
|
|
Build produces separate bundles per entry point (see `tsup.config.ts`). The csv-loader entries externalize `csv-parse`, `@rspack/core`, `esbuild`, and `rollup`.
|
|
|
|
## Key conventions
|
|
|
|
- Schema syntax uses **semicolons** (`;`) as separators, not commas
|
|
- Unknown identifiers throw a `ParseError` — only recognized keywords (`string`, `number`, `int`, `float`, `boolean`) and string literals (`"on"`, `'off'`) are valid types
|
|
- 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
|
|
- `@tablename` / `@tablename[]` are reference schemas resolved at CSV load time
|
|
- `csvToModule()` emits accessor functions (`getData()`) for tables with references, and static JSON for tables without; bundler loaders all use `csvToModule`
|
|
- `parseCsv({ resolveReferences: false })` stores reference IDs instead of resolved objects — used by `csvToModule` to emit import-based lazy resolution
|
|
- References can appear nested inside tuples, arrays, and unions; the loader resolves them recursively
|
|
|
|
## Gotchas
|
|
|
|
- **Circular references** between CSV tables are supported in `csvToModule` output via accessor-based lazy resolution. `parseCsv()` with `resolveReferences: true` (default) still detects and throws on circular references via an in-progress loading set.
|
|
- **Run `npm run typecheck` before committing** to catch type errors.
|
|
- **Union member ordering** — In unions containing references, **reference members are tried before non-reference members** (regardless of author order), so `@users | string` resolves `1` to the user object and falls back to a plain string only when the reference doesn't match. `parseValue` (no references) still tries members in author order; the first that parses wins.
|
|
- **csv-parse quote handling** — Double-quoted schema values like `"active" | "inactive"` in CSV rows confuse the csv-parse library. Use single-quoted string literals (`'on' | 'off'`) or unquoted identifiers in the schema row of CSV data when possible.
|
|
- **Module imports use `.js` extension** — source files import from `../index.js` etc. (ESM convention), not `../index.ts`.
|