npm package: @paranoidninja/nestjs-typeorm-faker
Description: A utility to facilitate defining TypeORM mock entity generators for NestJS
Author: Ahmed Osama Ibrahim
Latest version: 1.1.1

# `nestjs-typeorm-faker`

`nestjs-typeorm-faker` is a NestJS wrapper around [`@paranoidninja/typeorm-faker`](https://www.npmjs.com/package/@paranoidninja/typeorm-faker), designed for test suites.

It focuses on two things:

1. Registering TypeORM entity fakers as Nest providers inside test modules.
2. Resolving typed faker instances via Nest DI tokens per entity + datasource.

Under the hood, each faker config callback also receives Nest's `ModuleRef`, which lets a faker resolve other Nest providers from the active testing context.

## Why this package

When NestJS tests need many entity variants, manual object setup becomes repetitive and inconsistent.
This wrapper gives you:

- Nest-native provider registration for entity fakers.
- Entity-based DI token lookup via `getFakerToken`.
- Support for default and named TypeORM data sources.
- Access to Nest testing context from faker config functions through `ModuleRef`.
- Full access to base faker capabilities (`buildOne`, `buildMany`, `createOne`, `createMany`, overrides, relation handling) through `EntityFaker`.

## Installation

```bash
npm install @paranoidninja/nestjs-typeorm-faker
```

Typical dependencies used in Nest + TypeORM tests:

```bash
npm install @nestjs/common @nestjs/typeorm typeorm @paranoidninja/typeorm-faker
npm install -D @nestjs/testing @faker-js/faker better-sqlite3
```

## Quick start

```ts
import { faker } from "@faker-js/faker";
import { Test } from "@nestjs/testing";
import { getRepositoryToken, TypeOrmModule } from "@nestjs/typeorm";
import {
  EntityFaker,
  getFakerToken,
  registerFakerAndGetProvider,
} from "@paranoidninja/nestjs-typeorm-faker";
import { Column, Entity, PrimaryGeneratedColumn, Repository } from "typeorm";

@Entity()
class User {
  @PrimaryGeneratedColumn()
  id!: number;

  @Column()
  firstName!: string;

  @Column()
  lastName!: string;
}

const userFakerProvider = registerFakerAndGetProvider(User, {
  firstName: () => faker.person.firstName(),
  lastName: () => faker.person.lastName(),
});

const moduleRef = await Test.createTestingModule({
  imports: [
    TypeOrmModule.forRoot({
      type: "better-sqlite3",
      database: ":memory:",
      entities: [User],
      synchronize: true,
    }),
    TypeOrmModule.forFeature([User]),
  ],
  providers: [userFakerProvider],
}).compile();

const userFaker = moduleRef.get<EntityFaker<User>>(getFakerToken(User));
const userRepo = moduleRef.get<Repository<User>>(getRepositoryToken(User));

const builtUser = await userFaker.buildOne(); // not persisted
const savedUser = await userFaker.createOne(); // persisted
const savedUsers = await userFaker.createMany(3); // persisted array
```

## How it works in Nest context

This package wraps the base `typeorm-faker` registration flow in a Nest provider factory:

- TypeORM `DataSource` is injected from `@nestjs/typeorm`
- Nest `ModuleRef` is injected from `@nestjs/core`
- The resulting faker is registered as a Nest provider token per `entity + datasource`

That means your faker field generators can use the active Nest testing module as context instead of relying on global state or manual wiring.

## Core API

### `registerFakerAndGetProvider(entityClass, config, dataSourceName?)`

Creates a Nest provider that registers a faker for an entity against the injected TypeORM `DataSource`.

```ts
const userFakerProvider = registerFakerAndGetProvider(User, {
  firstName: () => faker.person.firstName(),
  lastName: () => faker.person.lastName(),
});
```

- `entityClass`: TypeORM entity class
- `config`: Nest-aware field generator config. Each callback can receive the base faker input plus `{ moduleRef }`
- `dataSourceName` (optional): datasource name, defaults to `"default"`

Example with Nest context:

```ts
const testEntityFakerProvider = registerFakerAndGetProvider(TestEntity, {
  text: () => faker.lorem.text(),
  nestedEntity: async ({ moduleRef }) => {
    const nestedEntityFaker = moduleRef.get<EntityFaker<NestedEntity>>(
      getFakerToken(NestedEntity),
    );

    return nestedEntityFaker.buildOne();
  },
});
```

### `getFakerToken(entityClass, dataSourceName?)`

Returns the Nest DI token (`symbol`) for a previously registered entity faker.

```ts
const userFaker = moduleRef.get<EntityFaker<User>>(getFakerToken(User));
```

Throws if no faker token is found for the provided entity + datasource name.

### Re-exports

This package re-exports:

- `EntityFaker`
- `FakerConfig`

from `@paranoidninja/typeorm-faker`.

## Usage examples

### Build test entities without persistence

```ts
const user = await userFaker.buildOne({
  firstName: "FixedName",
});
```

### Create persisted rows for integration tests

```ts
const before = await userRepo.count();
await userFaker.createOne();
const after = await userRepo.count();
```

### Named datasource in tests

Use the same datasource name when registering provider and resolving token.

```ts
const analyticsUserFakerProvider = registerFakerAndGetProvider(
  User,
  {
    firstName: () => faker.person.firstName(),
    lastName: () => faker.person.lastName(),
  },
  "analytics",
);

const analyticsUserFaker = moduleRef.get<EntityFaker<User>>(
  getFakerToken(User, "analytics"),
);
```

### Resolve other fakers or providers via `ModuleRef`

Because faker callbacks receive Nest's `ModuleRef`, you can compose fakers with other fakers or any provider already registered in the same module.

```ts
@Entity()
class NestedEntity {
  @PrimaryGeneratedColumn()
  id!: number;

  @Column()
  name!: string;
}

@Entity()
class TestEntity {
  @PrimaryGeneratedColumn()
  id!: number;

  @ManyToOne(() => NestedEntity)
  nestedEntity?: NestedEntity;
}

const nestedEntityFakerProvider = registerFakerAndGetProvider(NestedEntity, {
  name: () => faker.person.fullName(),
});

const testEntityFakerProvider = registerFakerAndGetProvider(TestEntity, {
  nestedEntity: ({ moduleRef }) => {
    const nestedEntityFaker = moduleRef.get<EntityFaker<NestedEntity>>(
      getFakerToken(NestedEntity),
    );

    return nestedEntityFaker.buildOne();
  },
});
```

This is useful when:

- one entity faker depends on another entity faker
- faker logic needs an existing Nest provider
- test setup should stay inside the Nest DI graph instead of passing dependencies around manually

### Use base package features through `EntityFaker`

`EntityFaker` instances returned by this wrapper support the base package API, including:

- `buildOne`, `buildMany`
- `createOne`, `createMany`
- Literal/function overrides
- Relation dependency persistence behavior from the base package

## Notes

- Intended for test environments (unit/integration/e2e).
- Faker tokens are tracked by `datasourceName + entityClass`.
- `getFakerToken` requires that provider registration has already happened.
- Faker config callbacks run with Nest context and can resolve providers through `ModuleRef`.
- Underlying faker registration rules and behavior come from `@paranoidninja/typeorm-faker`.

## Development

```bash
npm run build
npm test
```

## License

MIT