A TypeScript library for creating strongly typed mock data factories. Built on Faker.js with advanced composition patterns, database persistence, fixture caching, and optional Zod and JSON Schema integration.
If you find interface-forge helpful, please consider sponsoring the development:
Your support helps maintain and improve this library for the community! 🚀
- 🔒 Type-Safe: Full TypeScript support with compile-time validation
- 🚀 Zero Learning Curve: Extends Faker.js - all Faker methods work out of the box
- 🔄 Advanced Composition: Build complex object relationships with
compose()andextend() - 🗄️ Database Integration: Built-in persistence with Mongoose, Prisma, TypeORM adapters
- 📁 Fixture Caching: Cache generated data for consistent test scenarios
- 📐 Schema Integration: Generate data directly from Zod or JSON Schema with validation
- 🔗 Hooks & Transforms: Pre/post-build data transformation and validation
- 🎲 Deterministic: Seed generators for reproducible test data
📚 Complete Documentation | 📂 Examples
# npm pnpm add --save-dev interface-forge # yarn yarn add --dev interface-forge # pnpm pnpm add --save-dev interface-forge # For Zod integration (optional) pnpm add zod # For JSON Schema integration (optional) pnpm add ajv ajv-formats # For GraphQL integration (optional) pnpm add graphql
import { Factory } from 'interface-forge'; interface User { id: string; name: string; email: string; age: number; } const userFactory = new Factory<User>((faker) => ({ id: faker.string.uuid(), name: faker.person.fullName(), email: faker.internet.email(), age: faker.number.int({ min: 18, max: 65 }), })); // Generate single object const user = userFactory.build(); // Generate multiple objects const users = userFactory.batch(5); // Override properties const admin = userFactory.build({ name: 'Admin User' });
import { z } from 'zod/v4'; import { ZodFactory } from 'interface-forge/zod'; const userSchema = z.object({ id: z.string().uuid(), name: z.string().min(2), email: z.string().email(), age: z.number().min(18).max(65), }); const userFactory = new ZodFactory(userSchema); const user = userFactory.build(); // Automatically validates against schema
import { JsonSchemaFactory } from 'interface-forge/json-schema'; const userSchema = { type: 'object', required: ['id', 'email'], properties: { id: { type: 'string', format: 'uuid' }, email: { type: 'string', format: 'email' }, }, } as const; const userFactory = new JsonSchemaFactory(userSchema); const user = userFactory.build(); // Automatically validates with AJV
import { createGraphQLFactories } from 'interface-forge/graphql'; const sdl = ` type User { id: ID!, name: String!, roles: [Role!]! } type Post { author: User!, title: String } enum Role { ADMIN USER } scalar DateTime `; const factories = createGraphQLFactories(sdl, { customScalarGenerators: { DateTime: () => '2026-01-01T00:00:00Z' }, }); const post = factories.Post?.build();
import { MongooseAdapter } from './adapters/mongoose'; const userFactory = new Factory<User>(factoryFn).withAdapter( new MongooseAdapter(UserModel), ); // Create and save to database const user = await userFactory.create(); const users = await userFactory.createMany(10);
const enhancedUserFactory = userFactory.compose<EnhancedUser>({ profile: profileFactory, // Use another factory posts: postFactory.batch(3), // Generate related data isActive: true, // Static values });
build()/buildAsync()- Generate single objectsbatch()/batchAsync()- Generate multiple objectsextend()- Create factory variationscompose()- Combine multiple factoriescreate()/createMany()- Database persistence
beforeBuild()- Transform data before generationafterBuild()- Transform data after generation- Full async support for external API calls
factory.use(fn, ...args)- Defer a function call until the object is built- Async lazy values work with
buildAsync()andbatchAsync():
const UserFactory = new Factory<User>((factory) => ({ id: factory.string.uuid(), token: factory.use(async () => await generateToken()), })); const user = await UserFactory.buildAsync();
- Sync lazy values work with
build(); if an async lazy value reachesbuild()orbatch(), a clearConfigurationErrortells you to usebuildAsync().
factory.preset(name, values)- Register named partial overrides on a factory- Apply one or more presets via
{ presets: ['first', 'second'] }inbuild()/batch(); later presets override earlier ones and explicit kwargs override all presets:
const userFactory = new Factory<User>((faker) => ({ name: faker.person.fullName(), role: 'user', })).preset('admin', { role: 'admin' }); const admin = userFactory.build(undefined, { presets: ['admin'] });
factory.constraints.min/.max/.between- Constrain generated numbers (clamped)factory.constraints.pattern- Regenerate until a string matches a regexfactory.constraints.custom- Regenerate until a predicate accepts the valuefactory.constraints.unique- Factory-local uniqueness across builds and batch items, tracked per field- Retry-based helpers throw a
ConstraintError(withfield,constraint,attempts) once the attempt limit is reached:
const orderFactory = new Factory<Order>((faker) => ({ id: factory.constraints.unique('id', () => faker.string.uuid()), total: factory.constraints.between(1, 500, () => faker.number.float({ min: 0, max: 1000 })), }));
FactoryOutput<F>- Extract the output type of any factoryextend()has two overloads: a full-override factory function (returning the complete extended type) or an added-fields factory function returning only the new fields, which yieldsFactory<T & Added>; the base fields are preserved automatically.
import { expectTypeOf } from 'expect-type'; import type { FactoryOutput } from 'interface-forge'; const adminFactory = userFactory.extend((factory) => ({ permissions: ['read', 'write'], })); type Admin = User & { permissions: string[] }; expectTypeOf<FactoryOutput<typeof adminFactory>>().toEqualTypeOf<Admin>();
- Cache generated data for consistent tests
- Signature validation for factory changes
- Node.js only (browser fallback available)
CycleGenerator- Predictable value cyclingSampleGenerator- Random sampling without repeatsfactory.sequence.increment()- Incrementing numeric sequencesfactory.sequence.template()- Template-based string sequencesfactory.sequence.date()- Date/time sequences
- Getting Started
- Core Concepts
- Zod Integration
- JSON Schema Integration
- Advanced Features
- API Reference
All examples are available in the ./examples directory:
| Feature | Example |
|---|---|
| Basic Usage | 01-basic-usage.ts |
| Factory Composition | 02-advanced-composition.ts |
| Testing Integration | 03-testing-examples.ts |
| Zod Schemas | 07-zod-basic.ts |
| Database Persistence | adapters/ |
We welcome contributions! Please read our contributing guidelines.
MIT License - see LICENSE for details.