Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,10 +181,18 @@ With the scripts integrated in the `package.json` file, now you could run 2 diff
```typescript
@Schema()
export class User extends Document {
// Generates a consistent UUID based on the index of the generated data.
// Useful during development when you want to have a consistent ID.
@Factory((_, __, index) => uuidv5(index.toString(), this.name))
@Prop({ required: true })
id: string;

@Factory((faker) => faker.helpers.arrayElement(["male", "female"]))
@Prop({ required: true })
gender: string;

// Using the context, you could access the previously generated value.
// generates a first name based on the gender.
@Factory((faker, ctx) => faker.person.firstName(ctx.gender))
@Prop({ required: true })
firstName: string;
Expand Down
11 changes: 8 additions & 3 deletions lib/decorators/factory.decorator.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
import { FactoryMetadataStorage } from '../storages/factory.metadata.storage';
import { Faker } from '@faker-js/faker';
import { FactoryMetadataStorage } from "../storages/factory.metadata.storage";
import { Faker } from "@faker-js/faker";

type BaseType = string | number | Date | Buffer | boolean | Record<string, any>;
export type FactoryValue = BaseType | Array<BaseType>;
export type FactoryValueGenerator = (faker?: Faker, ctx?: Record<string, any>) => FactoryValue;
export type FactoryValueGenerator = (
faker?: Faker,
ctx?: Record<string, any>,
// @ts-ignore - Added to support the index parameter with backwards compatibility
index: number
) => FactoryValue;

export function Factory(arg: FactoryValueGenerator | FactoryValue) {
return (target: Record<string, any>, propertyKey: string | symbol): void => {
Expand Down
22 changes: 13 additions & 9 deletions lib/factory/data.factory.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { Type } from '@nestjs/common';
import { Factory, PropertyMetadata } from '../interfaces';
import { FactoryValue } from '../decorators/factory.decorator';
import { FactoryMetadataStorage } from '../storages/factory.metadata.storage';
import { faker } from '@faker-js/faker';
import { Type } from "@nestjs/common";
import { Factory, PropertyMetadata } from "../interfaces";
import { FactoryValue } from "../decorators/factory.decorator";
import { FactoryMetadataStorage } from "../storages/factory.metadata.storage";
import { faker } from "@faker-js/faker";

export class DataFactory {
static createForClass(target: Type<unknown>): Factory {
Expand All @@ -16,7 +16,10 @@ export class DataFactory {
FactoryMetadataStorage.getPropertyMetadatasByTarget(target);

return {
generate: (count: number, values: Record<string, any> = {}): Record<string, FactoryValue>[] => {
generate: (
count: number,
values: Record<string, any> = {}
): Record<string, FactoryValue>[] => {
const ret = Array<Record<string, FactoryValue>>();
for (let i = 0; i < count; i++) {
ret.push(this.generate(properties, values));
Expand All @@ -28,12 +31,13 @@ export class DataFactory {

private static generate(
properties: PropertyMetadata[],
values: Record<string, any>,
values: Record<string, any>
): Record<string, FactoryValue> {
const ctx = { ...values };
return properties.reduce(
(r, p) => ({
[p.propertyKey]: ctx[p.propertyKey] = typeof p.arg === 'function' ? p.arg(faker, ctx) : p.arg,
(r, p, index) => ({
[p.propertyKey]: (ctx[p.propertyKey] =
typeof p.arg === "function" ? p.arg(faker, ctx, index) : p.arg),
...r,
}),
{}
Expand Down
2 changes: 1 addition & 1 deletion sample/src/schemas/user.schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export class User extends Document {

// If you pass predefined values to the `generate` function, you will be
// able to access it in the context.
@Factory((faker, ctx) => `${faker.location.streetAddress()} ${ctx.zipCode}`)
@Factory((faker, ctx, index) => `${faker.location.streetAddress()} ${ctx.zipCode} ${index}`)
@Prop({ required: true })
address: string;
}
Expand Down