json-schema-contract-compiler
v0.1.0
Published
JSON Schema contract compiler - generates TypeScript types and validators
Downloads
6
Maintainers
Readme
json-schema-contract-compiler
A JSON Schema contract compiler that generates TypeScript types and validators at build time.
Why?
Traditional schema validation libraries interpret schemas at runtime. This compiler takes a different approach: compile once, import types, call a function.
| Approach | Bundle Size | Runtime Cost | Type Safety | |----------|-------------|--------------|-------------| | Runtime (Zod, Ajv) | Library + schema | Parse + validate | Inferred | | Compile-time | Generated code only | Validate only | Generated |
The result is near-zero runtime overhead, fast TypeScript builds, and small bundles.
Installation
npm install json-schema-contract-compilerQuick Start
1. Create a JSON Schema
// schemas/user.json
{
"$id": "User",
"type": "object",
"properties": {
"id": { "type": "string" },
"email": { "type": "string", "format": "email" },
"age": { "type": "integer", "minimum": 0 }
},
"required": ["id", "email"]
}2. Compile
npx jsc compile -o ./generated ./schemas/user.json3. Use the Generated Code
import type { User } from './generated/user';
import { isUser, parseUser } from './generated/user.js';
// Type guard (returns boolean)
if (isUser(data)) {
console.log(data.email); // TypeScript knows this is valid
}
// Parser (throws on invalid input)
try {
const user = parseUser(data);
console.log(user.email);
} catch (err) {
console.error(err.path, err.message);
}CLI Reference
jsc compile [options] <files...>
Options:
-o, --out-dir <dir> Output directory (required)
-e, --emit <what> What to emit: types, validators, all (default: all)
-m, --module <format> Module format: esm, cjs (default: esm)
-s, --strict Error on unsupported keywords
-v, --verbose Verbose output
-w, --watch Watch modeExamples
# Compile all schemas in a directory
jsc compile -o ./generated ./schemas/*.json
# Generate only TypeScript types
jsc compile -o ./types --emit types ./schemas/user.json
# Generate CommonJS modules
jsc compile -o ./dist -m cjs ./schemas/*.json
# Watch mode for development
jsc compile -o ./generated -w ./schemas/*.jsonGenerated Output
For each schema file, the compiler generates:
| File | Contents |
|------|----------|
| <name>.d.ts | TypeScript type definitions |
| <name>.js | isX() type guards + parseX() parsers |
Type Guards (isX)
Fast boolean checks that return true if valid, false otherwise.
function isUser(value: unknown): value is UserParsers (parseX)
Validators that return the typed value or throw ValidationError.
function parseUser(value: unknown): UserThe ValidationError includes structured information:
{
message: "/email: Invalid email format",
path: "/email",
expected: "email",
received: "not-an-email"
}Supported JSON Schema Features
Types
string,number,integer,boolean,null,object,array- Type unions:
{ "type": ["string", "null"] }
String Constraints
minLength,maxLengthpattern(regex)format: email, uuid, date-time, date, time, uri, hostname, ipv4, ipv6
Number Constraints
minimum,maximumexclusiveMinimum,exclusiveMaximummultipleOf
Object Constraints
properties,requiredadditionalProperties(boolean or schema)
Array Constraints
items(single schema for all items)prefixItems(tuple validation)minItems,maxItems
Composition
oneOf(discriminated unions supported viax-discriminator)enum,const
References
$ref(local references only:#/$defs/Name)$defs/definitions
Extensions
x-brand
Create branded/opaque types:
{
"type": "string",
"x-brand": "UserId"
}Generates: string & { readonly __brand: "UserId" }
x-discriminator
Optimize union validation with a discriminator property:
{
"oneOf": [
{ "properties": { "type": { "const": "dog" }, "bark": { "type": "boolean" } } },
{ "properties": { "type": { "const": "cat" }, "meow": { "type": "boolean" } } }
],
"x-discriminator": "type"
}x-coerce
Enable type coercion in parsers:
{
"type": "number",
"x-coerce": true
}With coercion, parseX("42") returns 42 instead of throwing.
x-doc
Add JSDoc comments to generated types:
{
"type": "string",
"x-doc": "The user's unique identifier"
}Runtime Library
The package exports a minimal runtime library for advanced use cases:
import {
ValidationError,
registerRefinement,
refine,
isEmail,
isUUID,
// ... other format validators
} from 'json-schema-contract-compiler';Custom Refinements
Register custom validation logic:
import { registerRefinement } from 'json-schema-contract-compiler';
registerRefinement('positiveNumber', (value) => {
return typeof value === 'number' && value > 0;
});Then use in your schema:
{
"type": "number",
"x-refinement": "positiveNumber"
}Comparison with Alternatives
| Feature | json-schema-contract-compiler | Zod | Ajv | |---------|-----------------|-----|-----| | Runtime overhead | Minimal | Medium | Low | | Bundle size impact | ~0 (generated) | ~12KB | ~30KB | | TypeScript types | Generated | Inferred | Separate | | Schema format | JSON Schema | Custom DSL | JSON Schema | | Build step required | Yes | No | No |
License
MIT
