zod-to-mini-converter
v1.0.0
Published
Zero-dependency mini schema DSL with converters to Zod code, JSON Schema, TypeScript types, validator, and mock data generator
Maintainers
Readme
zod-to-mini-converter
Zero-dependency mini schema DSL with five converters:
| Converter | Output |
|---|---|
| toZodCode | Zod schema source code string |
| toJsonSchema | JSON Schema draft-07 object |
| toTypeString | TypeScript type string |
| validate | Runtime validation with structured errors |
| mockValue | Deterministic mock / fixture data |
Define schemas once in the mini DSL, generate everything from it.
npm install zod-to-mini-converterQuick start
import { s, toZodCode, toJsonSchema, toTypeString, validate, mockValue } from 'zod-to-mini-converter';
const UserSchema = s.object({
id: s.string({ uuid: true }),
name: s.string({ min: 1, max: 100 }),
email: s.string({ email: true }),
age: s.number({ int: true, min: 0, optional: true }),
role: s.enum(['admin', 'user', 'guest']),
tags: s.array(s.string()),
createdAt: s.date(),
});toZodCode
Generate a Zod schema as a code string — paste it into any TypeScript project.
console.log(toZodCode(UserSchema, 'UserSchema'));const UserSchema = z.object({
id: z.string().uuid(),
name: z.string().min(1).max(100),
email: z.string().email(),
age: z.number().int().min(0).optional(),
role: z.enum(["admin", "user", "guest"]),
tags: z.array(z.string()),
createdAt: z.date(),
});Works for all schema types:
toZodCode(s.string({ email: true, optional: true }))
// z.string().email().optional()
toZodCode(s.union(s.string(), s.number()))
// z.union([z.string(), z.number()])
toZodCode(s.tuple([s.string(), s.number(), s.boolean()]))
// z.tuple([z.string(), z.number(), z.boolean()])
toZodCode(s.record(s.number()))
// z.record(z.string(), z.number())toJsonSchema
Generate a JSON Schema draft-07 object:
const jsonSchema = toJsonSchema(UserSchema, { title: 'User' });{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "User",
"type": "object",
"properties": {
"id": { "type": "string", "format": "uuid" },
"name": { "type": "string", "minLength": 1, "maxLength": 100 },
"email": { "type": "string", "format": "email" },
"age": { "type": "integer", "minimum": 0 },
"role": { "enum": ["admin", "user", "guest"] },
"tags": { "type": "array", "items": { "type": "string" } },
"createdAt": { "type": "string", "format": "date-time" }
},
"required": ["id", "name", "email", "role", "tags", "createdAt"]
}toTypeString
Generate a TypeScript type as a string — useful for code generation:
console.log(toTypeString(UserSchema, 'User'));type User = {
id: string;
name: string;
email: string;
age?: number;
role: "admin" | "user" | "guest";
tags: string[];
createdAt: Date;
};validate
Runtime validation with path-aware structured errors — no Zod needed:
const { valid, errors } = validate(UserSchema, {
id: 'not-a-uuid',
name: '',
email: 'notanemail',
role: 'superadmin',
tags: [42],
});
// valid → false
// errors → [
// { path: 'id', code: 'invalid_string', message: 'Invalid UUID' },
// { path: 'name', code: 'too_small', message: 'Min length 1' },
// { path: 'email', code: 'invalid_string', message: 'Invalid email' },
// { path: 'role', code: 'invalid_enum_value', message: 'Expected one of: "admin", "user", "guest"' },
// { path: 'tags[0]', code: 'invalid_type', message: 'Expected string, got number' },
// ]Nested paths:
validate(s.object({ address: s.object({ zip: s.string({ min: 5 }) }) }), {
address: { zip: '123' }
});
// errors → [{ path: 'address.zip', code: 'too_small', message: 'Min length 5' }]mockValue
Generate deterministic mock data — useful for tests and Storybook:
mockValue(UserSchema)
// {
// id: '10000000-1000-4000-8000-100000000001',
// name: 'lorem',
// email: '[email protected]',
// role: 'admin',
// tags: ['lorem', 'ipsum'],
// createdAt: Date(2021-02-01),
// }
// Different seed → different values
mockValue(UserSchema, 3)
// { name: 'sit', email: '[email protected]', role: 'guest', ... }Schema reference
Primitives
s.string()
s.string({ min: 1, max: 100 })
s.string({ email: true })
s.string({ url: true })
s.string({ uuid: true })
s.string({ regex: /^\d{4}$/ })
s.string({ startsWith: 'https://', endsWith: '.json' })
s.string({ trim: true, toLowerCase: true })
s.number()
s.number({ int: true })
s.number({ min: 0, max: 100 })
s.number({ positive: true })
s.number({ nonnegative: true })
s.number({ multipleOf: 5 })
s.boolean()
s.date()
s.date({ min: '2020-01-01', max: '2099-12-31' })
s.any()
s.unknown()
s.null()
s.never()Literals & enums
s.literal('active')
s.literal(42)
s.literal(true)
s.enum(['draft', 'published', 'archived'])Optional / nullable / defaults
s.string({ optional: true }) // T | undefined
s.string({ nullable: true }) // T | null
s.string({ nullish: true }) // T | null | undefined
s.string({ default: 'hello' }) // .default('hello') in Zod
s.number({ optional: true, default: 0 })Complex types
s.array(s.string())
s.array(s.number(), { min: 1, max: 10 })
s.array(s.string(), { nonempty: true })
s.object({
name: s.string(),
meta: s.object({ createdAt: s.date() }),
}, { strict: true })
s.record(s.number()) // Record<string, number>
s.record(s.string(), s.number()) // (key schema, value schema)
s.tuple([s.string(), s.number()])
s.tuple([s.string(), s.number()], { rest: s.boolean() })
s.union(s.string(), s.number(), s.boolean())
s.intersection(s.object({ a: s.string() }), s.object({ b: s.number() }))
s.map(s.string(), s.number())
s.set(s.string())
s.promise(s.string())CommonJS
const { s, toZodCode, toJsonSchema, toTypeString, validate, mockValue } = require('zod-to-mini-converter');License
MIT
