Skip to content

Add ajv/standalone as a JS emit target #42

Description

@alltheseas

Summary

schemata-codegen already preprocesses schemas via emit-ajv.ts (stripping $schema, $id, errorMessage) into AJV-ready JSON files. ajv/standalone can extend this pipeline one step further — pre-compiling those JSON schemas into standalone JS validator modules that require no AJV runtime.

Related: nostrability/schemata#141


Motivation

Today, JS consumers of the AJV-preprocessed schemas still need to:

import Ajv from 'ajv';                    // ~150KB runtime
const ajv = new Ajv();
const validate = ajv.compile(schema);      // compile at startup

With standalone codegen as a new emit target:

import validate from './kind-1.validator.js';  // no AJV runtime, no compile step

Proposed Integration

New pipeline stage

emit-ajv.ts → kind-N.json → ajv/standalone → kind-N.validator.js + kind-N.validator.d.ts
  • New CLI flag: --ajv-standalone (and/or fold into --all)
  • Output: a directory of pre-compiled .js + .d.ts validator modules, one per kind, plus an index
  • Output format options: CJS or ESM (matching schemata-codegen's existing ES module setup)

Build-time only

ajv and ajv-formats become dev dependencies of schemata-codegen (used during generation), not runtime dependencies of the output.


Benefits

1. Zero-runtime JS validators from full JSON Schema

The hand-coded validators cover 74% of patterns natively. Standalone AJV validators are compiled directly from the JSON Schemas — covering 100% of JSON Schema semantics including contains, if/then/else, nested allOf, and format keywords. No AJV runtime shipped to consumers.

2. Equivalence testing reference

Standalone validators serve as a full-spec reference implementation to test hand-coded validators against. This slots naturally into the existing fuzz-equivalence.test.ts framework — run the same inputs through both, any divergence reveals a codegen bug or schema ambiguity.

3. Dual-validator strategy (aligns with CODEGEN-VS-VALIDATORS.md)

Layer Tool Use case
Production runtime Hand-coded validators (codegen) Hot path — zero deps, 13 languages
CI / conformance AJV standalone validators Full JSON Schema compliance, JS/TS only
Development AJV with allErrors + ajv-errors Rich error messages for debugging

Standalone codegen makes the "CI / conformance" layer shippable without an AJV runtime dependency.

4. CSP compliance

No new Function() at runtime — important for browser extensions, Electron apps, and strict web environments common in Nostr clients.

5. Startup performance

No runtime compilation of 177+ schemas. Validators are ready to call on import.


Scope & Limitations

  • JS/TS only — does not affect the 12 other language emitters
  • Complementary, not a replacement — hand-coded validators remain the lightweight production path across all languages
  • Does not change schema authoring — consumes the same preprocessed output from emit-ajv.ts

Implementation Notes

  • ajv-cli already supports ajv compile -s schema.json -o validator.js — could be used directly or via the programmatic standaloneCode() API
  • If ajv-errors is adopted in schemata (Evaluate AJV plugins to enhance schema validation schemata#141), the standalone validators would include custom error messages for free
  • ajv-formats integration needed for schemas using format: "uri" etc.

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions