Generate validation schemas from Mikro-ORM entities. Supports TypeBox, Zod, Valibot, ArkType, Effect, io-ts, Yup, and more.
- 🏗️ Entity Type Generation: Converts Mikro-ORM entity classes to TypeScript types
- 🔄 Multiple Validation Libraries: Supports TypeBox, Zod, Valibot, ArkType, Effect, io-ts, Yup, and more
- 🎯 Smart Type Resolution: Automatically resolves entity references depending on the relation graph between entities and sorts them by dependency order
- 🔄 Circular Reference Handling: Automatically breaks circular references to avoid infinite recursion
- 🔄 Partial Types: Generates partial types for entities with optional properties
- 📦 Collection Handling: Handles
Collection<T>andArray<T>with proper type mapping
npm install --save-dev mikro-typeboxThe package includes a command-line interface for easy usage:
Generate typebox schema from ./src/entities to ./src/entity-validators.ts
npx mikro-typebox generateGenerate Zod schema from ./src/entities to ./src/entity-validators.ts
npx mikro-typebox generate --target zodGenerate Valibot schema from ./src/models to ./src/validators.ts
npx mikro-typebox generate --target valibot --entities ./src/models --output ./src/validators.ts-e, --entities <path>: Directory containing entity files (default:./src/entities)-o, --output <file>: Output file path (default:./src/entity-validators.ts)--no-write: Print the code to the console instead of writing to a file (default: writes to a file)-t, --target <library>: Target validation library (default:typebox)--partials,--no-partials: Generate partial types instead of inline primary key references (default:truefortypebox)
typebox- TypeBox (default)zod- Zodvalibot- Valibotarktype- ArkTypeeffect- Effectio-ts- io-tsyup- Yupjson-schema- JSON Schemajavascript- JavaScripttypescript- TypeScriptvalue- Value
You can also use the API to generate validation schemas programmatically.
Generates validation schemas from Mikro-ORM entities.
options.entitiesDir(optional): Directory containing the entity files (default:"./src/entities")options.outputFile(optional): File path to write the generated code (default:"./src/entity-validators.ts")options.write(optional): Whether to write the code to a file (default:true)options.targetValidationLibrary(optional): Target validation library (default:"typebox")options.partials(optional): Whether to generate partial types instead of inline primary key references (default:truefortypebox)
Converts Mikro-ORM entity code to TypeScript types.
code: The entity code as a stringentityIdTypes(optional): Map of entity names to their ID types
Processes multiple entity files and generates types with proper entity ID replacement.
fileContents: Array of entity file contents as strings
import { generateEntityValidator } from "mikro-typebox";
// Generate for TypeBox
await generateEntityValidator({
entitiesDir: "./src/entities",
outputFile: "./src/validators.ts",
write: true,
partials: true,
});
// Generate for Zod
const zodCode = await generateEntityValidator({
entitiesDir: "./src/entities",
targetValidationLibrary: "zod",
outputFile: "./src/zod-validators.ts",
write: true,
});
// Generate for Valibot
const valibotCode = await generateEntityValidator({
entitiesDir: "./src/entities",
targetValidationLibrary: "valibot",
outputFile: "./src/valibot-validators.ts",
write: true,
});Given a Mikro-ORM entity file like this:
// src/entities/User.ts
import {
Entity,
PrimaryKey,
Property,
Collection,
OneToMany,
} from "@mikro-orm/core";
import { Book } from "./Book";
@Entity()
export class User {
@PrimaryKey()
id!: number;
@Property()
name!: string;
@Property()
email!: string;
@OneToMany(() => Book, (book) => book.author)
books = new Collection<Book>(this);
constructor({ name, email }: User) {
this.name = name;
this.email = email;
}
}
// src/entities/Book.ts
import { Entity, PrimaryKey, Property, ManyToOne } from "@mikro-orm/core";
import { User } from "./User";
@Entity()
export class Book {
@PrimaryKey()
id!: number;
@Property()
title!: string;
@ManyToOne(() => User)
author!: User;
constructor({ title, author }: Book) {
this.title = title;
this.author = author;
}
}And then generate validation schemas (e.g., with TypeBox):
import { Type, Static, TSchema } from "@sinclair/typebox";
export namespace schema {
export type Collection<T extends TSchema> = Static<
ReturnType<typeof Collection<T>>
>;
export const Collection = <T extends TSchema>(T: T) =>
Type.Object(
{},
{
additionalProperties: T,
},
);
export type Book = Static<typeof Book>;
export const Book = Type.Object({
id: Type.Number(),
title: Type.String(),
author: schema.PartialUser,
});
export type PartialBook = Static<typeof PartialBook>;
export const PartialBook = Type.Object({
id: Type.Number(),
title: Type.Optional(Type.String()),
author: Type.Optional(schema.PartialUser),
});
export type User = Static<typeof User>;
export const User = Type.Object({
id: Type.Number(),
name: Type.String(),
email: Type.String(),
books: Type.Union([
Collection(
Type.Object({
id: Type.Number(),
}),
),
Type.Array(
Type.Object({
id: Type.Number(),
}),
),
]),
});
export type PartialUser = Static<typeof PartialUser>;
export const PartialUser = Type.Object({
id: Type.Number(),
name: Type.Optional(Type.String()),
email: Type.Optional(Type.String()),
books: Type.Optional(
Type.Union([
Collection(
Type.Object({
id: Type.Number(),
}),
),
Type.Array(
Type.Object({
id: Type.Number(),
}),
),
]),
),
});
}or for Zod
import { z } from "zod";
export type schema_Book = z.infer<typeof schema_Book>;
export const schema_Book = z.object({
id: z.number(),
title: z.string(),
author: z.object({
id: z.number(),
}),
});
export type schema_User = z.infer<typeof schema_User>;
export const schema_User = z.object({
id: z.number(),
name: z.string(),
email: z.string(),
books: z.union([
z.object({}),
z.array(
z.object({
id: z.number(),
}),
),
]),
});import { generateEntityTypes, generateEntityFileTypes } from "mikro-typebox";
// Process a single entity file
const entityCode = `
import { Entity, PrimaryKey, Property } from '@mikro-orm/core';
@Entity()
export class Product {
@PrimaryKey()
id!: number;
@Property()
name!: string;
}
`;
const types = generateEntityTypes(entityCode);
console.log(types);
// Output: export type Product = { id: number; name: string; };
// Process multiple entity files
const fileContents = [entityCode, anotherEntityCode];
const allTypes = generateEntityFileTypes(fileContents);- Entity Discovery: Scans entity files for classes decorated with
@Entity() - Type Extraction: Extracts property types and relationships from entity classes
- ID Type Resolution: Replaces entity references with their primary key types
- Collection Conversion: Converts
Collection<T>toArray<T>with proper type mapping - Code Cleanup: Removes Mikro-ORM specific imports, decorators, and method calls
- Schema Generation: Converts TypeScript types to validation schemas using the target library
Apache-2.0, Copyright (c) 2025 Amin Yara