@amritk/generate-examples
v0.5.0
Published
Generate fast-check arbitraries and example values from JSON Schemas.
Maintainers
Readme
@amritk/generate-examples
Programmatic API for generating fast-check arbitraries and example values from JSON Schemas.
Overview
@amritk/generate-examples turns a JSON Schema into test data. Where the
other mjst generators give you code that consumes data at runtime (parsers,
validators, types), this one closes the loop by giving you data to exercise
that code with.
Each generated file exports:
- A TypeScript
typedefinition for the schema - A
fast-checkarbitrary (FooArbitrary) that produces schema-valid values — ideal for property-based testing - A concrete, self-contained example value (
fooExample) — ideal for fixtures, seeds, and documentation
An index.ts barrel re-exports everything.
[!NOTE] The generated arbitraries import
fast-check, so consumers need it installed (npm i -D fast-check). An arbitrary whose schema uses a keyword nofc.*combinator captures on its own (if/then/else,not, exclusiveoneOf, and the presence-gated object keywords) also imports@amritk/runtime-validatorsfor a post-generation validating filter; files that need no such filter don't. The staticfooExamplevalues have no runtime dependencies.
Installation
npm install @amritk/generate-examples
# or
pnpm add @amritk/generate-examples
# or
yarn add @amritk/generate-examples
# or
bun add @amritk/generate-examplesUsage
import { buildExampleSchema } from '@amritk/generate-examples'
const schema = {
type: 'object',
properties: {
id: { type: 'string', format: 'uuid' },
age: { type: 'integer', minimum: 0 },
},
required: ['id'],
} as const
const files = await buildExampleSchema(schema, 'User')
// → [{ filename: 'user.ts', content: '...' }, { filename: 'index.ts', content: '...' }]The generated user.ts looks like:
import * as fc from 'fast-check'
export type User = { id: string; age?: number }
export const UserArbitrary: fc.Arbitrary<User> = fc.record(
{ "id": fc.uuid(), "age": fc.integer({ min: 0 }) },
{ requiredKeys: ["id"] },
)
export const userExample: User = { "id": "00000000-0000-0000-0000-000000000000", "age": 0 }Use the arbitrary in a property test:
import { test, fc } from '@fast-check/vitest'
import { UserArbitrary } from './generated'
import { parseUser } from './parsers'
test.prop([UserArbitrary])('parseUser round-trips any valid User', (user) => {
expect(parseUser(user)).toEqual(user)
})…or grab the static example as a fixture:
import { userExample } from './generated'
const res = await fetch('/users', { method: 'POST', body: JSON.stringify(userExample) })Lower-level API
| Export | Description |
|:---|:---|
| buildExampleSchema(schema, rootName, suffix?) | Walks the $ref graph and returns a GeneratedFile[] (one file per schema + an index.ts). |
| generateArbitrary(schema, typeName, suffix?) | Returns the export const …Arbitrary source for a single schema node. |
| generateExampleConst(schema, typeName, rootSchema?) | Returns the export const …Example source for a single schema node. |
| deriveExample(schema, rootSchema?) | Returns a concrete, schema-valid JavaScript value (no code-generation). |
| serializeValue(value) | Serializes a derived value to a TypeScript source expression (handles Date/bigint). |
Supported keywords
type — including multi-type unions like ['string', 'null'] —
(string/number/integer/boolean/null/array/object), properties,
required, items, minItems/maxItems, uniqueItems,
minLength/maxLength, pattern, format (email, uuid, uri/url,
date, date-time, time, hostname, ipv4, ipv6), minimum/maximum,
exclusiveMinimum/exclusiveMaximum, multipleOf, enum (filtered by sibling
constraints), const, minProperties/maxProperties, patternProperties,
propertyNames, dependentRequired, dependentSchemas, contains,
oneOf/anyOf, if/then/else, not, $ref, and the x-mjst extension
(Date, bigint). if/then/else, not, and oneOf exclusivity are
enforced by validating generated candidates against the schema and
retrying/rejecting. Unsupported constructs degrade to fc.anything() in
arbitraries and null in static examples.
[!TIP] A static example constrained only by
patternis not guaranteed to match the pattern — reach for the arbitrary when pattern fidelity matters.
