NestboltNestbolt

@nestbolt/factory

Quick Start

Get up and running with @nestbolt/factory in five minutes -- define a factory, register the module, and generate test data.

This guide walks through a complete working example: defining a factory, registering the module, creating a seeder, and generating data.

1. Define Your Entity

A standard TypeORM entity -- nothing special is required:

import { Entity, PrimaryGeneratedColumn, Column } from "typeorm";

@Entity("users")
export class User {
  @PrimaryGeneratedColumn("uuid")
  id!: string;

  @Column()
  name!: string;

  @Column()
  email!: string;

  @Column({ default: "user" })
  role!: string;
}

2. Define a Factory

Extend BaseFactory<T> and implement the entity getter and definition() method. The definition() method receives a Faker instance and returns default attributes:

import { BaseFactory } from "@nestbolt/factory";
import type { Faker } from "@faker-js/faker";
import { User } from "./entities/user.entity";

export class UserFactory extends BaseFactory<User> {
  get entity() {
    return User;
  }

  definition(faker: Faker): Partial<User> {
    return {
      name: faker.person.fullName(),
      email: faker.internet.email(),
      role: "user",
    };
  }

  admin(): Partial<User> {
    return { role: "admin" };
  }
}

3. Register the Module

Import FactoryModule in your root AppModule and call forRoot() with your factory classes. The module registers globally, so you only need to import it once.

import { Module } from "@nestjs/common";
import { TypeOrmModule } from "@nestjs/typeorm";
import { FactoryModule } from "@nestbolt/factory";
import { User } from "./entities/user.entity";
import { UserFactory } from "./factories/user.factory";

@Module({
  imports: [
    TypeOrmModule.forRoot({
      type: "postgres",
      host: "localhost",
      port: 5432,
      database: "myapp",
      entities: [User],
      synchronize: true, // development only
    }),
    FactoryModule.forRoot({
      factories: [UserFactory],
    }),
  ],
})
export class AppModule {}

4. Use in Your Code

Inject FactoryService and use the fluent builder API:

import { Injectable } from "@nestjs/common";
import { FactoryService } from "@nestbolt/factory";
import { UserFactory } from "./factories/user.factory";

@Injectable()
export class SeedService {
  constructor(private readonly factory: FactoryService) {}

  async seed() {
    // Create 10 regular users
    await this.factory.use(UserFactory).count(10).create();

    // Create 2 admin users
    await this.factory.use(UserFactory).state("admin").count(2).create();

    // Make an entity without persisting
    const user = await this.factory.use(UserFactory).make();
  }
}

5. Define a Seeder (Optional)

Seeders let you organize your data generation into reusable, ordered classes:

import type { Seeder, FactoryService } from "@nestbolt/factory";
import { UserFactory } from "./factories/user.factory";

export class DatabaseSeeder implements Seeder {
  order = 0; // lower runs first

  async run(factory: FactoryService): Promise<void> {
    await factory.use(UserFactory).count(10).create();
    await factory.use(UserFactory).state("admin").count(2).create();
  }
}

Register the seeder and run it:

// In module configuration
FactoryModule.forRoot({
  factories: [UserFactory],
  seeders: [DatabaseSeeder],
});

// In your service
await factoryService.seed(); // runs all seeders sorted by order

6. Test It

Create a simple controller to trigger seeding:

import { Controller, Post, HttpCode } from "@nestjs/common";
import { FactoryService } from "@nestbolt/factory";

@Controller("seed")
export class SeedController {
  constructor(private readonly factory: FactoryService) {}

  @Post()
  @HttpCode(200)
  async seed() {
    await this.factory.seed();
    return { message: "Database seeded successfully" };
  }
}

Then trigger it:

curl -X POST http://localhost:3000/seed
{ "message": "Database seeded successfully" }

What Happened Behind the Scenes

  1. FactoryModule.forRoot() registered your factory classes and made FactoryService available globally.
  2. factoryService.use(UserFactory) looked up the registered UserFactory and returned a FactoryBuilder<User>.
  3. .count(10) configured the builder to generate 10 entities.
  4. .state("admin") applied the admin() state method, overriding the role field.
  5. .create() called definition() for each entity, applied states and overrides, instantiated User objects, and persisted them via TypeORM's Repository.save().

Next Steps

  • Configuration -- all module options including async configuration and Faker seeds.
  • Defining Factories -- lifecycle hooks, state methods, and best practices.
  • Factory Builder -- full builder API with make, create, override, sequence, and callbacks.
  • Seeders -- organize data generation with ordered, composable seeder classes.