Skip to content

Latest commit

 

History

History
81 lines (68 loc) · 3.8 KB

File metadata and controls

81 lines (68 loc) · 3.8 KB

AGENTS.md — orientation for coding agents

This file is for AI coding agents (and humans who like density) working on @imqueue/validation. It captures how the codebase is built, tested and structured, plus the invariants that are easy to get wrong. Read it before making changes. For contribution process/terms see CONTRIBUTING.md; for end-user docs see the README and https://imqueue.org/.

What this is

@imqueue/validation is the input-validation layer of the @imqueue framework: Zod-backed, field- and method-level validation exposed as native (TC39) decorators (@validate, @validatable, @validated, plus schemaOf). It is used by @imqueue/rpc services and by code generated by @imqueue/pg-prisma to validate RPC inputs.

Toolchain & invariants (do not fight these)

  • ESM only, "type": "module". Use import, not require(). Import sibling modules with the .js extension (NodeNext resolves it to the .ts source), e.g. import { validate } from './validate.js'.
  • TypeScript, module/moduleResolution: nodenext, target: es2024, verbatimModuleSyntax: true, isolatedModules: true, strict: true. Use import type / import { type X } for type-only imports.
  • Node ≥ 22.12.
  • Native TC39 decorators — the code relies on the standard decorator emit, not experimentalDecorators and not reflect-metadata. Do not enable experimentalDecorators; it changes decorator semantics and would break the buffer/seal mechanism.
  • Single runtime dependency: zod. Do not add heavyweight deps; this package is meant to stay small.
  • Lint/format: oxlint + oxfmt. Run npm run format before committing; CI checks npm run format:check.
  • Build emits .js/.d.ts/.js.map next to sources; these are gitignored, not committed (build runs clean-compiled first). Never commit compiled output.
  • removeComments is intentionally false — downstream tooling relies on doc-blocks surviving compilation. Keep it that way.

Commands

npm install
npm run build          # clean-compiled + tsc (emits alongside sources)
npm test               # build + node:test over every test/**/*.spec.js
npm run lint           # oxlint
npm run format         # oxfmt (write)  |  npm run format:check (verify)
npm run test-coverage  # tests + experimental coverage summary
npm run test-lcov      # writes coverage/lcov.info

Layout

Path Role
index.ts Public entry: export * from './src/index.js'
src/index.ts Barrel re-exporting the public API
src/validate.ts The whole implementation: @validate, @validatable, @validated, schemaOf, and the Validator type.
test/** node:test specs (*.spec.ts, run compiled).

Behavioural invariants

  • Field decorators buffer; the class decorator seals. TC39 metadata (Symbol.metadata) is not reliably populated by esbuild/tsx, so @validate writes into a module-level buffer and @validatable() moves that buffer into a WeakMap registry keyed by the class. This is safe only because field decorators run before the class decorator and class bodies evaluate sequentially — do not introduce async between them or reorder.
  • A class field decorated with @validate requires the class to be @validatable() for schemaOf to see it.
  • Validators resolve lazily. A @validatable class used as a validator is resolved via schemaOf on first use, so classes can reference each other regardless of definition order.
  • Invalid input throws the raw ZodError (which surfaces to the RPC caller). Do not wrap or swallow it.

License

GPL-3.0. Commercial licensing for closed-source products: https://imqueue.com/.