### Running Interface-Forge Examples Source: https://github.com/goldziher/interface-forge/blob/main/docs/docs/examples.md Provides the command-line instructions to clone the repository, install dependencies, and run a basic example. This is the starting point for testing the library locally. ```bash git clone https://github.com/Goldziher/interface-forge.git cd interface-forge && pnpm install npx tsx examples/01-basic-usage.ts ``` -------------------------------- ### Install and Start Development Server Source: https://github.com/goldziher/interface-forge/blob/main/docs/README.md Installs project dependencies and starts the local development server. The site will be available at http://localhost:3000/interface-forge/. ```bash pnpm install pnpm start ``` -------------------------------- ### Install Interface-Forge and Dependencies Source: https://github.com/goldziher/interface-forge/blob/main/examples/README.md Install Interface-Forge and Zod for Zod integration examples. ```bash # Install dependencies npm install interface-forge # For Zod examples, also install Zod npm install zod ``` -------------------------------- ### Run TypeScript Examples Source: https://github.com/goldziher/interface-forge/blob/main/examples/README.md Execute Interface-Forge examples using tsx or by compiling and running. ```bash # Run with TypeScript npx tsx examples/01-basic-usage.ts # Or compile and run npx tsc examples/01-basic-usage.ts --outDir dist node dist/01-basic-usage.js ``` -------------------------------- ### Install Optional Zod Integration Source: https://github.com/goldziher/interface-forge/blob/main/docs/docs/getting-started/installation.md Install zod if you plan to use the Zod integration with Interface Forge. ```bash pnpm add zod ``` -------------------------------- ### Install Interface Forge Source: https://github.com/goldziher/interface-forge/blob/main/docs/docs/getting-started/installation.md Use this command to add Interface Forge to your project. ```bash pnpm add interface-forge ``` -------------------------------- ### Install Interface-Forge Source: https://github.com/goldziher/interface-forge/blob/main/README.md Install Interface-Forge and its optional Zod dependency using npm, yarn, or pnpm. ```bash # npm npm install --save-dev interface-forge # yarn yarn add --dev interface-forge # pnpm pnpm add --save-dev interface-forge # For Zod integration (optional) npm install zod ``` -------------------------------- ### Quick Start: Set Default Adapter and Create Objects Source: https://github.com/goldziher/interface-forge/blob/main/docs/docs/advanced/persistence.md Set a default persistence adapter for a factory and then create single or multiple objects that will be automatically saved to the database. ```typescript import { Factory } from 'interface-forge'; // Set default adapter const userFactory = new Factory(factoryFn).withAdapter( new MongooseAdapter(UserModel), ); // Create and save to database const user = await userFactory.create(); const users = await userFactory.createMany(10); ``` -------------------------------- ### Install Peer Dependency: Faker JS Source: https://github.com/goldziher/interface-forge/blob/main/docs/docs/getting-started/installation.md Interface Forge requires @faker-js/faker. Install it if you don't have it. ```bash pnpm add @faker-js/faker ``` -------------------------------- ### Database Seeding with Factory Source: https://github.com/goldziher/interface-forge/blob/main/docs/docs/advanced/persistence.md Example of seeding a database by creating multiple related objects using the factory, including nested loops for dependent data. ```typescript async function seedDatabase() { // Create admins const admins = await userFactory.createMany(3, { role: 'admin', isActive: true, }); // Create users for each admin for (const admin of admins) { await userFactory.createMany(10, { managerId: admin.id, role: 'user', }); } } ``` -------------------------------- ### Run Development Server on Different Port Source: https://github.com/goldziher/interface-forge/blob/main/docs/README.md Starts the development server on a different port if the default port 3000 is already in use. ```bash pnpm start -- --port 3001 ``` -------------------------------- ### Import ZodFactory for Zod Integration Source: https://github.com/goldziher/interface-forge/blob/main/examples/README.md Import the ZodFactory from the separate entry point for Zod-related examples. ```typescript import { ZodFactory } from 'interface-forge/zod'; ``` -------------------------------- ### Storybook Integration for User Components Source: https://github.com/goldziher/interface-forge/blob/main/docs/docs/advanced/fixtures.md Use fixtures in Storybook to provide consistent data for UI components. This example demonstrates creating stories for a UserCard component with different user fixture data. ```typescript // UserCard.stories.ts const factory = new Factory(factoryFn, { fixtures: { basePath: './.storybook/fixtures' }, }); export const Default: StoryObj = { args: { user: factory.build({}, { generateFixture: 'default-user' }), }, }; export const Admin: StoryObj = { args: { user: factory.build( { role: 'admin' }, { generateFixture: 'admin-user' }, ), }, }; ``` -------------------------------- ### E-commerce Order Schema with Custom Handlers Source: https://github.com/goldziher/interface-forge/blob/main/docs/docs/schema/custom-handlers.md This example demonstrates defining an e-commerce order schema with custom handlers for a processor function and a validation function. The ZodFunction handler simulates a payment processor with a 90% success rate, and the ZodCustom handler validates the order amount and currency. ```typescript const orderSchema = z.object({ id: z.string().uuid(), processor: z .function() .args( z.object({ amount: z.number(), currency: z.string(), }), ) .returns( z.promise( z.object({ success: z.boolean(), transactionId: z.string().optional(), }), ), ), validate: z.custom<(order: any) => boolean>(), }); const factory = new ZodFactory(orderSchema).withTypeHandlers({ ZodFunction: () => async (payment) => ({ success: Math.random() > 0.1, // 90% success rate transactionId: Math.random().toString(36), }), ZodCustom: () => (order) => { return order.amount > 0 && order.currency?.length === 3; }, }); const order = factory.build(); const result = await order.processor({ amount: 100, currency: 'USD' }); ``` -------------------------------- ### Async Composition with Async Factories Source: https://github.com/goldziher/interface-forge/blob/main/docs/docs/core/composition.md Compose factories that involve asynchronous operations. This example demonstrates composing a standard `userFactory` with an `asyncProfileFactory` and using `buildAsync` to create the object. ```typescript const userFactory = new Factory(async (faker) => ({ id: faker.string.uuid(), name: faker.person.fullName(), })); const composedFactory = userFactory.compose({ profile: asyncProfileFactory, isActive: true, }); // Use buildAsync for async composition const user = await composedFactory.buildAsync(); ``` -------------------------------- ### Vitest/Jest Integration for User API Tests Source: https://github.com/goldziher/interface-forge/blob/main/docs/docs/advanced/fixtures.md Integrate fixtures into Vitest or Jest tests to ensure consistent user data across test runs. This example shows how to build user data with a specific fixture name for testing. ```typescript describe('User API', () => { const factory = new Factory(factoryFn, { fixtures: { basePath: './test-fixtures' }, }); it('should handle user registration', () => { const userData = factory.build( {}, { generateFixture: 'registration-test', }, ); // Consistent data across test runs expect(userData.email).toMatch(/@/); }); }); ``` -------------------------------- ### Compose Factories for Type-Safe Merging Source: https://github.com/goldziher/interface-forge/blob/main/docs/docs/core/composition.md Merge multiple factory definitions while maintaining type safety. This example composes `userFactory` and `contactFactory` into a `fullUserFactory`. ```typescript interface User { id: string; name: string; } interface ContactInfo { email: string; phone: string; } interface FullUser extends User, ContactInfo { isVerified: boolean; } const userFactory = new Factory((faker) => ({ id: faker.string.uuid(), name: faker.person.fullName(), })); const contactFactory = new Factory((faker) => ({ email: faker.internet.email(), phone: faker.phone.number(), })); // Compose factories const fullUserFactory = userFactory.compose({ email: contactFactory.build().email, phone: contactFactory.build().phone, isVerified: true, }); ``` -------------------------------- ### Performance Tip: Reuse Factory Instance Source: https://github.com/goldziher/interface-forge/blob/main/docs/docs/schema/custom-handlers.md Avoid recreating the `ZodFactory` instance on each build if handlers are consistently applied. Reusing the factory instance with registered handlers improves performance by preventing repeated handler setup. ```typescript // ❌ Recreates handlers on each build function generateData() { return new ZodFactory(schema) .withTypeHandler('ZodFunction', expensiveHandler) .build(); } // ✅ Reuse factory with handlers const factory = new ZodFactory(schema).withTypeHandler( 'ZodFunction', expensiveHandler, ); function generateData() { return factory.build(); } ``` -------------------------------- ### Composition with Relationships for Object Graphs Source: https://github.com/goldziher/interface-forge/blob/main/docs/docs/core/composition.md Build complex object graphs by composing factories that include relationships to other factories. This example defines a `teamFactory` with nested `userFactory` and `projectFactory` compositions. ```typescript const teamFactory = userFactory.compose({ name: faker.company.name(), manager: userFactory, members: () => userFactory.batch(faker.number.int({ min: 3, max: 8 })), project: projectFactory, }); ``` -------------------------------- ### Context-Aware Handler for ZodLazy Source: https://github.com/goldziher/interface-forge/blob/main/docs/docs/schema/custom-handlers.md Create context-aware handlers for `ZodLazy` types, utilizing the `currentDepth` parameter to control recursive generation. This example limits nesting depth. ```typescript const factory = new ZodFactory(recursiveSchema).withTypeHandler( 'ZodLazy', (schema, generator, currentDepth) => { // Depth-aware generation const shouldNest = currentDepth < 2; return { id: generator.factory.string.uuid(), level: currentDepth, children: shouldNest ? [factory.build(), factory.build()] : undefined, }; }, ); ``` -------------------------------- ### Nested Composition for Hierarchies Source: https://github.com/goldziher/interface-forge/blob/main/docs/docs/core/composition.md Build complex object hierarchies by composing factories multiple times. This example shows a progression from a base `personFactory` to `employee`, `manager`, and `executive` factories. ```typescript // Base → Employee → Manager → Executive const personFactory = new Factory(personFn); const employeeFactory = personFactory.compose({ /* employee props */ }); const managerFactory = employeeFactory.compose({ /* manager props */ }); const executiveFactory = managerFactory.compose({ /* executive props */ }); ``` -------------------------------- ### Sample Random Non-Repeating Values Source: https://context7.com/goldziher/interface-forge/llms.txt Use sample() to get an infinite generator that randomly picks from an iterable, guaranteeing no two consecutive values are identical. Useful for statuses or priorities. ```typescript import { Factory } from 'interface-forge'; interface Task { id: string; title: string; status: string; priority: string; } const TaskFactory = new Factory((faker) => ({ id: faker.string.uuid(), title: faker.lorem.sentence(), status: 'todo', priority: 'medium', })); const statuses = ['todo', 'in-progress', 'done', 'blocked']; const priorities = ['low', 'medium', 'high', 'critical']; const statusSampler = TaskFactory.sample(statuses); const prioritySampler = TaskFactory.sample(priorities); const VariedTaskFactory = new Factory((faker) => ({ id: faker.string.uuid(), title: faker.lorem.sentence(), status: statusSampler.next().value, // random, never consecutive duplicate priority: prioritySampler.next().value, })); const tasks = VariedTaskFactory.batch(8); // statuses are random but e.g. never ['todo', 'todo', ...] ``` -------------------------------- ### Build and Serve Documentation Source: https://github.com/goldziher/interface-forge/blob/main/docs/README.md Builds the documentation for production and previews the build locally. ```bash pnpm build pnpm serve ``` -------------------------------- ### Project Structure Overview Source: https://github.com/goldziher/interface-forge/blob/main/docs/README.md Illustrates the directory structure of the Interface Forge project. ```bash docs/ docs/ # Documentation content getting-started/ # Getting started guides guides/ # Usage guides key-concepts/ # Core concepts api/ # API documentation (generated) src/ # Custom components and pages components/ # React components css/ # Global styles pages/ # Custom pages (homepage) static/ # Static assets docusaurus.config.ts # Docusaurus configuration ``` -------------------------------- ### Factory Class Usage Source: https://context7.com/goldziher/interface-forge/llms.txt Demonstrates the basic usage of the Factory class to create typed mock data for a User interface, including building single objects, batches, and applying overrides. ```APIDOC ## Factory Class ### Description The `Factory` class is the primary abstraction for creating typed mock data. It accepts a factory function that receives a Faker instance, the iteration index, and any overrides. It returns a plain object matching the generic type `T`. ### Usage ```typescript import { Factory } from 'interface-forge'; interface User { id: string; name: string; email: string; age: number; isActive: boolean; createdAt: Date; } const UserFactory = new Factory((faker) => ({ id: faker.string.uuid(), name: faker.person.fullName(), email: faker.internet.email(), age: faker.number.int({ min: 18, max: 80 }), isActive: faker.datatype.boolean(), createdAt: faker.date.past(), })); // Single object const user = UserFactory.build(); // => { id: '...', name: 'Jane Doe', email: '...', age: 34, isActive: true, createdAt: Date } // Batch of 5 const users = UserFactory.batch(5); // Partial overrides const admin = UserFactory.build({ name: 'Admin User', isActive: true }); // Batch with shared overrides const activeUsers = UserFactory.batch(3, { isActive: true }); // Batch with per-item overrides (cycles if array is shorter than size) const mixed = UserFactory.batch(4, [ { isActive: true }, { isActive: false }, ]); ``` ``` -------------------------------- ### Build Documentation Without Minification Source: https://github.com/goldziher/interface-forge/blob/main/docs/README.md Builds the documentation without minification, which can be useful for checking for broken links. ```bash pnpm build -- --no-minify ``` -------------------------------- ### Custom Handler for ZodFunction Source: https://github.com/goldziher/interface-forge/blob/main/docs/docs/schema/custom-handlers.md Register a custom handler for ZodFunction types to control how function schemas are generated. This example provides a mock processor function. ```typescript const schema = z.object({ id: z.string(), processor: z.function().args(z.string()).returns(z.string()), }); const factory = new ZodFactory(schema).withTypeHandler( 'ZodFunction', () => (input: string) => `processed: ${input}`, ); ``` -------------------------------- ### Using Multiple Adapters for Different Databases Source: https://github.com/goldziher/interface-forge/blob/main/docs/docs/advanced/persistence.md Demonstrates how to use multiple persistence adapters within a service to save objects to different databases. ```typescript class UserService { constructor( private mongoAdapter: MongooseAdapter, private postgresAdapter: PrismaAdapter, ) {} async createInMongo(userData: Partial) { return userFactory.create(userData, { adapter: this.mongoAdapter, }); } async createInPostgres(userData: Partial) { return userFactory.create(userData, { adapter: this.postgresAdapter, }); } } ``` -------------------------------- ### Basic Factory Creation in TypeScript Source: https://github.com/goldziher/interface-forge/blob/main/docs/docs/examples.md Demonstrates how to create a basic factory for generating user objects with faker.js. Use this for simple mock data generation. ```typescript import { Factory } from 'interface-forge'; interface User { id: string; name: string; email: string; } const userFactory = new Factory((faker) => ({ id: faker.string.uuid(), name: faker.person.fullName(), email: faker.internet.email(), })); const user = userFactory.build(); const users = userFactory.batch(5); ``` -------------------------------- ### Custom Handler for ZodCustom Source: https://github.com/goldziher/interface-forge/blob/main/docs/docs/schema/custom-handlers.md Define a custom handler for ZodCustom types to generate specific data structures for user-defined types. This example generates version and tags for a CustomMetadata interface. ```typescript interface CustomMetadata { version: string; tags: string[]; } const schema = z.object({ id: z.string(), metadata: z.custom(), }); const factory = new ZodFactory(schema).withTypeHandler( 'ZodCustom', (schema, generator) => ({ version: generator.factory.system.semver(), tags: generator.factory.helpers.arrayElements(['tag1', 'tag2']), }), ); ``` -------------------------------- ### Basic Factory Usage Source: https://github.com/goldziher/interface-forge/blob/main/docs/docs/api.md Demonstrates building a single object and a batch of objects using a defined Factory. The `build` method generates one item, while `batch` generates an array of items. ```typescript const userFactory = new Factory((faker) => ({ id: faker.string.uuid(), name: faker.person.fullName(), })); const user = userFactory.build(); const users = userFactory.batch(5); ``` -------------------------------- ### Dynamic Fixture Paths for Scenarios and Environments Source: https://github.com/goldziher/interface-forge/blob/main/docs/docs/advanced/fixtures.md Implement dynamic fixture paths for different scenarios or environments. This allows for more flexible fixture management by generating paths based on input parameters. ```typescript class UserFactory extends Factory { buildForScenario(scenario: string) { return this.build( {}, { generateFixture: `scenarios/${scenario}`, }, ); } buildForEnvironment(env: string) { return this.build( {}, { generateFixture: `environments/${env}/user`, fixtures: { basePath: `./fixtures/${env}` }, }, ); } } ``` -------------------------------- ### Implement Lifecycle Hooks with beforeBuild() and afterBuild() Source: https://context7.com/goldziher/interface-forge/llms.txt Use `beforeBuild()` to transform parameters before instance generation and `afterBuild()` to transform the generated instance. Both support synchronous and asynchronous functions and can be chained. ```typescript import { Factory } from 'interface-forge'; interface User { id: string; username: string; email: string; role: 'user' | 'admin' | 'guest'; isActive: boolean; } const UserFactory = new Factory((faker) => ({ id: faker.string.uuid(), username: '', email: '', role: 'user', isActive: true, })) .beforeBuild((params) => { // Derive email from username or vice-versa if (params.username && !params.email) { params.email = `${params.username}@example.com`; } else if (!params.username && params.email) { [params.username] = params.email.split('@'); } else if (!params.username && !params.email) { const name = `user_${Date.now()}`; params.username = name; params.email = `${name}@example.com`; } return params; }) .afterBuild((user) => { // Normalize casing user.email = user.email.toLowerCase(); user.username = user.username.toLowerCase(); return user; }); const u1 = UserFactory.build({ username: 'JohnDoe' }); // => { ..., username: 'johndoe', email: 'johndoe@example.com' } const u2 = UserFactory.build({ email: 'Jane.Smith@company.com' }); // => { ..., username: 'jane.smith', email: 'jane.smith@company.com' } // Async afterBuild hook — requires buildAsync() const ValidatingFactory = new Factory((faker) => ({ id: faker.string.uuid(), username: faker.internet.username(), email: faker.internet.email(), role: 'user', isActive: false, })).afterBuild(async (user) => { const isUnique = await checkUsernameUnique(user.username); // hypothetical async check if (!isUnique) throw new Error('Username taken'); user.isActive = true; return user; }); const validUser = await ValidatingFactory.buildAsync(); ``` -------------------------------- ### Version Control for Fixtures Source: https://github.com/goldziher/interface-forge/blob/main/docs/docs/advanced/fixtures.md Manage fixture files using version control. Include common fixtures in Git and exclude environment-specific or sensitive development fixtures. ```gitignore __fixtures__/ # Include in git dev-fixtures/ # Exclude development-only ``` -------------------------------- ### Implement Database Persistence Adapters Source: https://context7.com/goldziher/interface-forge/llms.txt Implement `PersistenceAdapter` for databases like Mongoose or Prisma. Attach the adapter using `withAdapter()` to a factory for saving generated objects. ```typescript import { Factory, PersistenceAdapter } from 'interface-forge'; import mongoose from 'mongoose'; // Mongoose adapter implementation class MongooseAdapter implements PersistenceAdapter { constructor(private model: mongoose.Model) {} async create(data: T): Promise { return this.model.create(data); } async createMany(data: T[]): Promise { return this.model.insertMany(data) as unknown as T[]; } } // Prisma adapter implementation class PrismaAdapter implements PersistenceAdapter { constructor(private prisma: any, private modelName: string) {} async create(data: T): Promise { return this.prisma[this.modelName].create({ data }); } async createMany(data: T[]): Promise { return Promise.all(data.map((item) => this.create(item))); } } interface User { id: string; name: string; email: string; } const userFactory = new Factory((faker) => ({ id: faker.string.uuid(), name: faker.person.fullName(), email: faker.internet.email(), })); // Attach default adapter const factoryWithDb = userFactory.withAdapter(new MongooseAdapter(UserModel)); // Persist single user const user = await factoryWithDb.create(); // Persist with overrides const admin = await factoryWithDb.create({ name: 'Admin' }); // Persist 10 users const users = await factoryWithDb.createMany(10); // Persist with cycling overrides const mixed = await factoryWithDb.createMany(6, [ { role: 'admin' }, { role: 'user' }, { role: 'guest' }, ]); // One-off adapter (no default set) const user2 = await userFactory.create( { name: 'Jane' }, { adapter: new PrismaAdapter(prisma, 'user') }, ); // Transactional creation await prisma.$transaction(async (tx) => { const adapter = new PrismaAdapter(tx, 'user'); await userFactory.createMany(5, { isActive: true }, { adapter }); }); ``` -------------------------------- ### Configure Factory Behavior with Options Source: https://github.com/goldziher/interface-forge/blob/main/docs/docs/core/factory-basics.md Customize factory behavior by passing an options object during initialization. Options include `maxDepth` for controlling nested object generation, `locale` for Faker's language settings, and `fixtures` for managing fixture file generation. ```typescript const factory = new Factory(factoryFn, { maxDepth: 5, // Depth limiting locale: 'en', // Faker locale fixtures: { // Fixture configuration basePath: './fixtures', validateSignature: true, }, }); ``` -------------------------------- ### Basic Factory Creation Source: https://github.com/goldziher/interface-forge/blob/main/examples/README.md Instantiate a Factory with a function that returns your data structure, using Faker methods for data generation. ```typescript const MyFactory = new Factory((faker) => ({ // Use faker methods to generate data })); ``` -------------------------------- ### Hooks Integration with Persistence Source: https://github.com/goldziher/interface-forge/blob/main/docs/docs/advanced/persistence.md Demonstrates how to integrate factory hooks (beforeBuild, afterBuild) with persistence operations, allowing data manipulation and side effects before and after saving to the database. ```typescript const factory = userFactory .withAdapter(adapter) .beforeBuild((data) => { data.email = data.email?.toLowerCase(); return data; }) .afterBuild(async (user) => { await sendWelcomeEmail(user.email); return user; }); // Hooks execute during create operations const user = await factory.create(); ``` -------------------------------- ### buildAsync() - Async Instance Generation Source: https://context7.com/goldziher/interface-forge/llms.txt Supports asynchronous factory functions and asynchronous hooks for generating typed instances. Returns a Promise that resolves to the generated instance. ```APIDOC ## buildAsync() — Async Instance Generation ### Description Supports async factory functions and async hooks. Returns a `Promise`. ### Usage ```typescript import { Factory } from 'interface-forge'; interface ApiToken { userId: string; token: string; expiresAt: Date; } async function generateSecureToken(): Promise { // Simulate async token generation await new Promise((r) => setTimeout(r, 5)); return `tok_${crypto.randomUUID()}`; } const ApiTokenFactory = new Factory(async (faker) => ({ userId: faker.string.uuid(), token: await generateSecureToken(), expiresAt: faker.date.future(), })); const token = await ApiTokenFactory.buildAsync(); // => { userId: '...', token: 'tok_...', expiresAt: Date } const tokens = await ApiTokenFactory.batchAsync(3); ``` ``` -------------------------------- ### Clear Cache and Rebuild Documentation Source: https://github.com/goldziher/interface-forge/blob/main/docs/README.md Clears the project cache and rebuilds the documentation. This can help resolve build issues. ```bash pnpm clear pnpm build ``` -------------------------------- ### Efficient Factory Reuse in Composition Source: https://github.com/goldziher/interface-forge/blob/main/docs/docs/core/composition.md Demonstrates the best practice of reusing factory instances in compositions for better performance. Avoid creating new factory instances within `compose` calls. ```typescript // ❌ Inefficient const bad = userFactory.compose({ profile: new Factory(profileFn), // New instance each build }); // ✅ Efficient const profileFactory = new Factory(profileFn); const good = userFactory.compose({ profile: profileFactory, // Reused instance }); ``` -------------------------------- ### Configure Fixture Generation Options Source: https://github.com/goldziher/interface-forge/blob/main/docs/docs/advanced/fixtures.md Configure fixture generation with options like `basePath`, `directory`, `validateSignature`, `useSubdirectory`, and `includeSource`. This allows customization of where and how fixtures are stored and validated. ```typescript const factory = new Factory(factoryFn, { fixtures: { basePath: './test-fixtures', // Base directory directory: 'users', // Subdirectory name validateSignature: true, // Check for changes useSubdirectory: true, // Use nested folders includeSource: true, // Include function source in signature }, generateFixture: 'default', // Default fixture name }); ``` -------------------------------- ### Factory Integration with SampleGenerator Source: https://github.com/goldziher/interface-forge/blob/main/docs/docs/core/generators.md Integrate SampleGenerator with factory methods like `sample()` to provide a set of templates from which to build objects, ensuring variety in specific fields. ```typescript const sampledFactory = userFactory.sample( [{ role: 'admin' }, { role: 'user' }], (template, faker) => ({ ...userFactory.build(), role: template.role, }), ); ``` -------------------------------- ### build() - Synchronous Instance Generation Source: https://context7.com/goldziher/interface-forge/llms.txt Generates a single typed instance synchronously, merging factory defaults with provided overrides. This method throws an error if the factory function or hooks are asynchronous. ```APIDOC ## build() - Synchronous Instance Generation ### Description Generates a single typed instance synchronously, merging factory defaults with any provided overrides. Throws `ConfigurationError` if the factory function or any registered hook is async (use `buildAsync()` instead). ### Usage ```typescript import { Factory } from 'interface-forge'; interface Person { name: string; age: number; canVote: boolean; canDrive: boolean; } // Context-aware factory: kwargs are available inside the factory function const PersonFactory = new Factory((faker, _iteration, kwargs) => { const age = kwargs?.age ?? faker.number.int({ min: 0, max: 80 }); return { name: kwargs?.name ?? faker.person.fullName(), age, canVote: age >= 18, canDrive: age >= 16, }; }); const child = PersonFactory.build({ age: 10 }); // => { name: '...', age: 10, canVote: false, canDrive: false } const adult = PersonFactory.build({ age: 25 }); // => { name: '...', age: 25, canVote: true, canDrive: true } ``` ``` -------------------------------- ### Define a User Interface and Factory Source: https://github.com/goldziher/interface-forge/blob/main/docs/docs/getting-started/basic-usage.md Define the structure of your data with an interface and then create a factory for it. The factory uses a faker instance to generate values for each field. ```typescript import { Factory } from 'interface-forge'; interface User { id: string; name: string; email: string; age: number; } const userFactory = new Factory((faker) => ({ id: faker.string.uuid(), name: faker.person.fullName(), email: faker.internet.email(), age: faker.number.int({ min: 18, max: 65 }), })); ``` -------------------------------- ### Create a Factory Instance Source: https://github.com/goldziher/interface-forge/blob/main/docs/docs/api.md Instantiate a Factory to generate type-safe mock data. Requires a factory function that accepts a faker instance and returns an object of the specified type. ```typescript import { Factory } from 'interface-forge'; const userFactory = new Factory((faker) => ({ id: faker.string.uuid(), name: faker.person.fullName(), email: faker.internet.email(), })); ``` -------------------------------- ### Configure Deterministic Disk Caching with Fixtures Source: https://context7.com/goldziher/interface-forge/llms.txt Configure fixtures to serialize generated data to JSON files for deterministic test data. Signature validation detects factory changes and triggers regeneration. This feature is Node.js only. ```typescript import { Factory, FixtureConfiguration } from 'interface-forge'; interface User { id: string; name: string; email: string; role: string; } const fixtureConfig: FixtureConfiguration = { basePath: './test-fixtures', // defaults to process.cwd() directory: 'users', // defaults to '__fixtures__' validateSignature: true, // regenerate when factory changes useSubdirectory: true, // store in subdirectory includeSource: true, // hash factory source }; const UserFactory = new Factory( (faker) => ({ id: faker.string.uuid(), name: faker.person.fullName(), email: faker.internet.email(), role: 'user', }), { fixtures: fixtureConfig }, ); // First call: generates & writes ./test-fixtures/users/admin-user.json // Subsequent calls: reads from disk (fast) const admin = UserFactory.build( { role: 'admin' }, { generateFixture: 'admin-user' }, ); // Auto-path based on factory name + timestamp const autoFixture = UserFactory.build({}, { generateFixture: true }); // Vitest / Jest integration describe('User API', () => { it('processes registration', () => { const userData = UserFactory.build( {}, { generateFixture: 'registration-test' }, ); expect(userData.email).toMatch(/@/); // same data every test run }); }); // Error handling try { const user = UserFactory.build({}, { generateFixture: 'user' }); } catch (error) { if (error instanceof FixtureValidationError) { // Factory changed — delete fixture file and re-run } if (error instanceof FixtureError) { // I/O error or browser environment } } ``` -------------------------------- ### Define and Use a Basic User Factory Source: https://context7.com/goldziher/interface-forge/llms.txt Define a UserFactory using the Factory class, specifying the User interface. Generate single objects, batches, or instances with overrides. Batch generation supports shared or per-item overrides. ```typescript import { Factory } from 'interface-forge'; interface User { id: string; name: string; email: string; age: number; isActive: boolean; createdAt: Date; } const UserFactory = new Factory((faker) => ({ id: faker.string.uuid(), name: faker.person.fullName(), email: faker.internet.email(), age: faker.number.int({ min: 18, max: 80 }), isActive: faker.datatype.boolean(), createdAt: faker.date.past(), })); // Single object const user = UserFactory.build(); // => { id: '...', name: 'Jane Doe', email: '...', age: 34, isActive: true, createdAt: Date } // Batch of 5 const users = UserFactory.batch(5); // Partial overrides const admin = UserFactory.build({ name: 'Admin User', isActive: true }); // Batch with shared overrides const activeUsers = UserFactory.batch(3, { isActive: true }); // Batch with per-item overrides (cycles if array is shorter than size) const mixed = UserFactory.batch(4, [ { isActive: true }, { isActive: false }, ]); ``` -------------------------------- ### Factory Class Methods Source: https://github.com/goldziher/interface-forge/blob/main/docs/docs/api.md Methods available on the Factory class for generating mock data. ```APIDOC ## Factory Class Methods ### Description Methods for generating single or multiple objects, handling asynchronous operations, and customizing factory behavior. ### Methods - `build(overrides?)`: Generate a single object with optional overrides. - `batch(count, overrides?)`: Generate an array of objects with optional overrides. - `buildAsync(overrides?)`: Asynchronously generate a single object. - `batchAsync(count, overrides?)`: Asynchronously generate an array of objects. - `use(definition)`: Update the factory's definition. - `extend(additions)`: Extend the factory with additional fields. - `compose(composition)`: Compose the factory with other factories or values. - `beforeBuild(hook)`: Add a hook to execute before an object is built. - `afterBuild(hook)`: Add a hook to execute after an object is built. - `create(overrides?, options?)`: Generate and persist a single object. - `createMany(count, overrides?, options?)`: Generate and persist multiple objects. - `withAdapter(adapter)`: Set a persistence adapter for the factory. ``` -------------------------------- ### PrismaAdapter Implementation Source: https://github.com/goldziher/interface-forge/blob/main/docs/docs/advanced/persistence.md Implements the PersistenceAdapter interface for databases managed by Prisma. Requires a PrismaClient instance and the model name. ```typescript import { PrismaClient } from '@prisma/client'; class PrismaAdapter implements PersistenceAdapter { constructor( private prisma: PrismaClient, private model: keyof PrismaClient, ) {} async create(data: T): Promise { return (this.prisma[this.model] as any).create({ data }); } async createMany(data: T[]): Promise { const results = await Promise.all( data.map((item) => this.create(item)), ); return results; } } // Usage const adapter = new PrismaAdapter(prisma, 'user'); ``` -------------------------------- ### Implement Generation Hooks with `beforeBuild()` and `afterBuild()` Source: https://github.com/goldziher/interface-forge/blob/main/docs/docs/core/factory-basics.md Utilize `beforeBuild()` to transform data before it's generated and `afterBuild()` to modify the generated object after creation. Hooks are essential for data normalization, adding computed fields, or performing side effects. ```typescript const factory = new Factory(factoryFn) .beforeBuild((data) => { // Normalize email if (data.email) { data.email = data.email.toLowerCase(); } return data; }) .afterBuild((user) => { // Add computed field user.displayName = `${user.name} (${user.email})`; return user; }); ``` -------------------------------- ### Generate Batches of Objects with Factory Source: https://github.com/goldziher/interface-forge/blob/main/docs/docs/core/factory-basics.md Employ `batch()` for synchronous and `batchAsync()` for asynchronous generation of multiple objects. You can specify the number of objects and provide overrides, including an array of overrides for cycling through different configurations. ```typescript // Simple batch const users = userFactory.batch(10); ``` ```typescript // With overrides const admins = userFactory.batch(5, { isAdmin: true }); ``` ```typescript // Cycling overrides const mixedUsers = userFactory.batch(6, [ { role: 'admin' }, { role: 'user' }, { role: 'guest' }, ]); ``` -------------------------------- ### Transactional Persistence with Prisma Source: https://github.com/goldziher/interface-forge/blob/main/docs/docs/advanced/persistence.md Implements a transactional adapter for Prisma, allowing multiple create operations to be grouped within a single database transaction. ```typescript import { PrismaClient } from '@prisma/client'; class TransactionalAdapter implements PersistenceAdapter { constructor( private prisma: PrismaClient, private model: keyof PrismaClient, private transaction?: any, ) {} async create(data: T): Promise { const client = this.transaction || this.prisma; return (client[this.model] as any).create({ data }); } } // Usage with transaction await prisma.$transaction(async (tx) => { const adapter = new TransactionalAdapter(prisma, 'user', tx); const users = await userFactory.createMany(5, {}, { adapter }); // All users created in same transaction }); ``` -------------------------------- ### Environment-Specific Fixture Paths Source: https://github.com/goldziher/interface-forge/blob/main/docs/docs/advanced/fixtures.md Configure fixture paths dynamically based on the current environment (e.g., NODE_ENV). This allows for different fixture sets for development, testing, or production. ```typescript fixtures: { basePath: `./fixtures/${process.env.NODE_ENV}`; } ``` -------------------------------- ### Build Single Objects with Factory Source: https://github.com/goldziher/interface-forge/blob/main/docs/docs/core/factory-basics.md Use `build()` for synchronous object generation and `buildAsync()` for asynchronous operations, such as when the factory function or hooks are asynchronous. Both methods accept optional override objects to customize generated properties. ```typescript // Synchronous const user = userFactory.build(); const customUser = userFactory.build({ name: 'John' }); ``` ```typescript // Asynchronous (for async factory functions or hooks) const user = await userFactory.buildAsync(); ``` -------------------------------- ### Basic Zod Schema Mock Data Generation Source: https://github.com/goldziher/interface-forge/blob/main/docs/docs/schema/zod-integration.md Instantiate ZodFactory with a Zod schema to generate valid mock data. The generated data automatically passes schema validation. Use `build()` for a single item and `batch()` for multiple. ```typescript 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().int().min(18).max(65), }); const userFactory = new ZodFactory(userSchema); // Generated data automatically passes schema validation const user = userFactory.build(); const users = userFactory.batch(5); ``` -------------------------------- ### Build Typed Instances with Contextual Overrides Source: https://context7.com/goldziher/interface-forge/llms.txt Create a PersonFactory that uses provided keyword arguments (kwargs) for age and name, with defaults from Faker.js. This factory demonstrates how to build instances with specific overrides, determining derived properties like canVote and canDrive. ```typescript import { Factory } from 'interface-forge'; interface Person { name: string; age: number; canVote: boolean; canDrive: boolean; } // Context-aware factory: kwargs are available inside the factory function const PersonFactory = new Factory((faker, _iteration, kwargs) => { const age = kwargs?.age ?? faker.number.int({ min: 0, max: 80 }); return { name: kwargs?.name ?? faker.person.fullName(), age, canVote: age >= 18, canDrive: age >= 16, }; }); const child = PersonFactory.build({ age: 10 }); // => { name: '...', age: 10, canVote: false, canDrive: false } const adult = PersonFactory.build({ age: 25 }); // => { name: '...', age: 25, canVote: true, canDrive: true } ``` -------------------------------- ### Persistence with Adapters Source: https://github.com/goldziher/interface-forge/blob/main/docs/docs/api.md Integrate Interface Forge with a persistence layer using adapters. The `withAdapter` method configures the factory to use a specific adapter, such as Mongoose, for creating and persisting data. ```typescript const factory = userFactory.withAdapter(new MongooseAdapter(UserModel)); const user = await factory.create(); ``` -------------------------------- ### Utility Classes Source: https://github.com/goldziher/interface-forge/blob/main/docs/docs/api.md Description of utility classes available in Interface Forge. ```APIDOC ## Utility Classes ### Ref **Description**: Represents a lazy reference to a value, useful for creating circular dependencies or delayed initializations. ### CycleGenerator **Description**: Generates values by cycling through a provided array. ### SampleGenerator **Description**: Generates values by randomly sampling from a provided array. ``` -------------------------------- ### Generate Arrays of Instances with batch() and batchAsync() Source: https://context7.com/goldziher/interface-forge/llms.txt Use `batch()` to create arrays of objects, applying a single override to all or cycling through an array of overrides. `batchAsync()` supports asynchronous generation. ```typescript import { Factory } from 'interface-forge'; interface Order { id: string; status: 'pending' | 'shipped' | 'delivered'; amount: number; } const OrderFactory = new Factory((faker) => ({ id: faker.string.uuid(), status: faker.helpers.arrayElement(['pending', 'shipped', 'delivered']), amount: faker.number.float({ min: 10, max: 500, fractionDigits: 2 }), })); // 10 orders, all pending const pendingOrders = OrderFactory.batch(10, { status: 'pending' }); // 6 orders cycling through statuses const cycledOrders = OrderFactory.batch(6, [ { status: 'pending' }, { status: 'shipped' }, { status: 'delivered' }, ]); // => [pending, shipped, delivered, pending, shipped, delivered] // Async batch const asyncOrders = await OrderFactory.batchAsync(5); ``` -------------------------------- ### Basic Factory Creation Source: https://github.com/goldziher/interface-forge/blob/main/README.md Define a TypeScript interface and create a basic factory using Interface-Forge to generate mock data. Faker.js methods can be used directly within the factory function. ```typescript import { Factory } from 'interface-forge'; interface User { id: string; name: string; email: string; age: number; } const userFactory = new Factory((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' }); ``` -------------------------------- ### TypeORMAdapter Implementation Source: https://github.com/goldziher/interface-forge/blob/main/docs/docs/advanced/persistence.md Implements the PersistenceAdapter interface for databases managed by TypeORM. Requires a TypeORM Repository instance. ```typescript import { Repository } from 'typeorm'; class TypeORMAdapter implements PersistenceAdapter { constructor(private repository: Repository) {} async create(data: T): Promise { const entity = this.repository.create(data); return this.repository.save(entity); } async createMany(data: T[]): Promise { const entities = this.repository.create(data); return this.repository.save(entities); } } ``` -------------------------------- ### Generate Single Mock Object Source: https://github.com/goldziher/interface-forge/blob/main/docs/docs/getting-started/basic-usage.md Use the `build()` method on a factory to generate a single mock object. The generated object conforms to the interface defined for the factory. ```typescript const user = userFactory.build(); // { id: '...', name: 'John Doe', email: 'john@example.com', age: 32 } ``` -------------------------------- ### Combining CycleGenerator and SampleGenerator Source: https://github.com/goldziher/interface-forge/blob/main/docs/docs/core/generators.md Combine CycleGenerator and SampleGenerator to create more complex data generation patterns. This allows for varied and sequential data points within a single factory. ```typescript const priorityGen = new CycleGenerator(['low', 'medium', 'high']); const categoryGen = new SampleGenerator(['bug', 'feature', 'enhancement']); const ticketFactory = new Factory((faker) => ({ id: faker.string.uuid(), priority: priorityGen.next(), category: categoryGen.next(), })); ``` -------------------------------- ### Enable Fixtures with Custom or Auto-Generated Paths Source: https://github.com/goldziher/interface-forge/blob/main/docs/docs/advanced/fixtures.md Enable fixtures by providing a custom name or setting `generateFixture` to true for auto-generated paths. This caches generated data for consistent test runs. ```typescript // Enable fixtures with custom path const user = userFactory.build({}, { generateFixture: 'test-user' }); // Enable with auto-generated path const user = userFactory.build({}, { generateFixture: true }); // Configure at factory level const factory = new Factory(factoryFn, { generateFixture: 'default-user', }); ``` -------------------------------- ### Generating Data for Zod Arrays and Sets Source: https://github.com/goldziher/interface-forge/blob/main/docs/docs/schema/zod-integration.md Supports generating mock data for arrays, sets, and records defined in Zod schemas, respecting constraints like minimum and maximum lengths. ```typescript const teamSchema = z.object({ name: z.string(), members: z.array(userSchema).min(3).max(10), tags: z.set(z.string()), metadata: z.record(z.string(), z.unknown()), }); // Example usage would involve creating a ZodFactory with this schema ``` -------------------------------- ### Fixture Error Handling with Fallback Source: https://github.com/goldziher/interface-forge/blob/main/docs/docs/advanced/fixtures.md Implement error handling for fixture generation. If a specific fixture fails to generate (e.g., `FixtureError`), provide a fallback mechanism to generate a default fixture. ```typescript try { return factory.build({}, { generateFixture: 'user' }); } catch (error) { if (error instanceof FixtureError) { return factory.build(); // Fallback } throw error; } ``` -------------------------------- ### Context-Aware Generation with `kwargs` Source: https://github.com/goldziher/interface-forge/blob/main/docs/docs/core/factory-basics.md Enable context-aware data generation by utilizing the `kwargs` parameter in the factory function. This allows you to pass runtime values like `age` or `id` to influence the generation of other properties, such as `underAge` or `driversLicense`. ```typescript const userFactory = new Factory((faker, iteration, kwargs) => { // Use provided age or generate one const age = kwargs?.age ?? faker.number.int({ min: 18, max: 80 }); return { id: kwargs?.id ?? faker.string.uuid(), name: kwargs?.name ?? faker.person.fullName(), age, // Context-aware: underAge depends on the actual age used underAge: age < 18, // Conditional generation based on age driversLicense: age >= 16 ? faker.string.alphanumeric(8) : null, }; }); // Generates consistent data const minor = userFactory.build({ age: 16 }); // { age: 16, underAge: true, driversLicense: null, ... } const adult = userFactory.build({ age: 25 }); // { age: 25, underAge: false, driversLicense: "A1B2C3D4", ... } ``` -------------------------------- ### Define Factory for Dates Source: https://github.com/goldziher/interface-forge/blob/main/docs/docs/getting-started/basic-usage.md Create a factory that generates `Date` objects and calculates related fields like duration. This demonstrates handling date-related data generation. ```typescript interface Event { id: string; title: string; startDate: Date; endDate: Date; duration: number; } const eventFactory = new Factory((faker) => { const start = faker.date.future(); const duration = faker.number.int({ min: 1, max: 8 }); const end = new Date(start.getTime() + duration * 60 * 60 * 1000); return { id: faker.string.uuid(), title: faker.company.catchPhrase(), startDate: start, endDate: end, duration, }; }); ``` -------------------------------- ### Control Field Generation with `.describe()` and Generators Source: https://context7.com/goldziher/interface-forge/llms.txt Use `.describe()` on schema fields and provide matching `generators` in the `ZodFactory` options to control how specific fields are generated. This allows for custom, predictable values for fields like IDs or SKUs. ```typescript import { z } from 'zod/v4'; import { ZodFactory } from 'interface-forge/zod'; const OrderSchema = z.object({ id: z.string().uuid().describe('orderId'), sku: z.string().describe('productSku'), amount: z.number(), }); const orderFactory = new ZodFactory(OrderSchema, { generators: { orderId: () => `ORD-${Date.now()}`, productSku: () => `SKU-${Math.random().toString(36).slice(2, 8).toUpperCase()}`, }, }); const order = orderFactory.build(); // order.id => 'ORD-1720000000000' // order.sku => 'SKU-A3F9K2' // order.amount => auto-generated number ```