@joakimbugge/typeorm-seeder 0.6.0 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,6 +2,9 @@
2
2
 
3
3
  Decorator-based entity seeding for TypeORM. Annotate your entity properties with `@Seed()`, then create or persist fully populated entity graphs with a single function call — including relations, embedded types, and circular guards. Organise complex seeding scenarios into `@Seeder` classes with declared dependencies that are automatically ordered and executed for you.
4
4
 
5
+ [![CI](https://github.com/joakimbugge/to-seeder/actions/workflows/ci.yml/badge.svg)](https://github.com/joakimbugge/to-seeder/actions/workflows/ci.yml)
6
+ [![Coverage](https://codecov.io/gh/joakimbugge/to-seeder/branch/main/graph/badge.svg)](https://codecov.io/gh/joakimbugge/to-seeder)
7
+
5
8
  Coded by AI. Reviewed by humans.
6
9
 
7
10
  ---
@@ -9,12 +12,20 @@ Coded by AI. Reviewed by humans.
9
12
  - [Installation](#installation)
10
13
  - [Decorating entities](#decorating-entities)
11
14
  - [Seeding entities](#seeding-entities)
15
+ - [Saving](#saving)
16
+ - [Without saving](#without-saving)
17
+ - [Multiple entity types at once](#multiple-entity-types-at-once)
18
+ - [Skipping relations](#skipping-relations)
19
+ - [Passing a DataSource to factories](#passing-a-datasource-to-factories)
20
+ - [Overriding seeded values](#overriding-seeded-values)
21
+ - [Depending on earlier properties](#depending-on-earlier-properties)
12
22
  - [Seeder suites](#seeder-suites)
13
23
  - [Seeding without `@Seed()`](#seeding-without-seed)
14
24
  - [Logging](#logging)
15
25
  - [Hooks](#hooks)
16
26
  - [Skipping seeders](#skipping-seeders)
17
27
  - [Running seed scripts](#running-seed-scripts)
28
+ - [TypeScript execution](#typescript-execution)
18
29
  - [API reference](#api-reference)
19
30
 
20
31
  ---
@@ -181,21 +192,34 @@ role!: Role
181
192
  Pass a `values` map to inject specific values after all `@Seed` factories have run:
182
193
 
183
194
  ```ts
195
+ // Status is set even if Booking has no @Seed on it
184
196
  const booking = await seed(Booking).create({ values: { status: 'confirmed' } })
185
- // status is set even if Booking has no @Seed on it
186
-
187
197
  const booking = await seed(Booking).save({ dataSource, values: { user, status: 'confirmed' } })
188
-
198
+ // All 5 get the same user
189
199
  const bookings = await seed(Booking).createMany(5, { values: { user } })
190
- // all 5 get the same user
191
-
192
200
  const bookings = await seed(Booking).saveMany(5, { dataSource, values: { user } })
193
201
  ```
194
202
 
203
+ Each property in `values` can also be a factory function — it is called once per entity, so every instance can receive a unique generated value:
204
+
205
+ ```ts
206
+ const bookings = await seed(Booking).saveMany(10, {
207
+ dataSource,
208
+ values: {
209
+ // Unique per booking
210
+ price: () => faker.number.float({ min: 10, max: 500 }),
211
+ // Same for all
212
+ status: 'confirmed',
213
+ },
214
+ })
215
+ ```
216
+
217
+ Factory entries in `values` receive the same `(context, self)` arguments as `@Seed` factories, so you can read already-applied properties from `self` or query the database via `context.dataSource`.
218
+
195
219
  `values` wins unconditionally: if a property has a `@Seed` factory, the factory still runs but its result is overwritten. `values` also works for properties with no `@Seed` decorator at all.
196
220
 
197
221
  > [!NOTE]
198
- > `values` are applied **after** all `@Seed` factories have finished, so they are never visible on `self` inside a factory callback.
222
+ > `values` are applied **after** all `@Seed` factories have finished, so they are never visible on `self` inside a `@Seed` factory callback.
199
223
 
200
224
  ---
201
225
 
@@ -425,7 +449,7 @@ seed([Author, Book]).saveMany(count, options): Promise<[Author[], Book[]]>
425
449
  |---|---|---|
426
450
  | `dataSource` | `DataSource?` | Forwarded to factory functions via `SeedContext`. |
427
451
  | `relations` | `boolean?` | Set to `false` to skip relation seeding. Defaults to `true`. |
428
- | `values` | `Partial<T>?` | Property values applied after all `@Seed` factories have run. Wins unconditionally — factories still execute but their output is overwritten. Also works for properties with no `@Seed` decorator. |
452
+ | `values` | `SeedValues<T>?` | Property values applied after all `@Seed` factories have run. Each entry can be a static value or a factory called once per entity. Wins unconditionally — `@Seed` factories still execute but their output is overwritten. Also works for properties with no `@Seed` decorator. |
429
453
 
430
454
  **`SaveOptions<T>`** — passed to `save()` and `saveMany()` on the single-class form
431
455
 
@@ -433,7 +457,7 @@ seed([Author, Book]).saveMany(count, options): Promise<[Author[], Book[]]>
433
457
  |---|---|---|
434
458
  | `dataSource` | `DataSource` | Required. Active TypeORM data source used to persist entities. |
435
459
  | `relations` | `boolean?` | Set to `false` to skip relation seeding. Defaults to `true`. |
436
- | `values` | `Partial<T>?` | Property values applied after seeding and before persisting. Wins unconditionally — factories still execute but their output is overwritten. Also works for properties with no `@Seed` decorator. |
460
+ | `values` | `SeedValues<T>?` | Property values applied after seeding and before persisting. Each entry can be a static value or a factory called once per entity. Wins unconditionally — `@Seed` factories still execute but their output is overwritten. Also works for properties with no `@Seed` decorator. |
437
461
 
438
462
  ---
439
463
 
package/dist/index.cjs CHANGED
@@ -42,6 +42,18 @@ function Seed(factoryOrOptions, options) {
42
42
  function getAncestors(context) {
43
43
  return context._ancestors ?? /* @__PURE__ */ new Set();
44
44
  }
45
+ /**
46
+ * Applies a {@link SeedValues} map to an instance.
47
+ * Factory entries are called once per instance so each entity can get unique values.
48
+ */
49
+ async function applyValues(instance, values, context) {
50
+ const record = instance;
51
+ for (const key of Object.keys(values)) {
52
+ const value = values[key];
53
+ if (typeof value === "function") record[key] = await value(context, instance);
54
+ else record[key] = value;
55
+ }
56
+ }
45
57
  /** Returns a new context with `cls` added to the ancestor set, used to detect circular relation chains. */
46
58
  function withAncestor(context, cls) {
47
59
  const ancestors = getAncestors(context);
@@ -116,7 +128,7 @@ async function create(classOrClasses, options = {}) {
116
128
  }
117
129
  const { values, ...context } = options;
118
130
  const instance = await createOne(classOrClasses, context);
119
- if (values) Object.assign(instance, values);
131
+ if (values) await applyValues(instance, values, context);
120
132
  return instance;
121
133
  }
122
134
  async function createMany(classOrClasses, { count, values, ...context }) {
@@ -128,7 +140,7 @@ async function createMany(classOrClasses, { count, values, ...context }) {
128
140
  return await Promise.all(classOrClasses.map((cls) => Promise.all(Array.from({ length: count }, () => createOne(cls, effectiveContext)))));
129
141
  }
130
142
  const instances = await Promise.all(Array.from({ length: count }, () => createOne(classOrClasses, context)));
131
- if (values) instances.forEach((e) => Object.assign(e, values));
143
+ if (values) await Promise.all(instances.map((instance) => applyValues(instance, values, context)));
132
144
  return instances;
133
145
  }
134
146
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["registry","DepGraph"],"sources":["../src/seed/registry.ts","../src/seed/decorator.ts","../src/seed/creator.ts","../src/seed/persist.ts","../src/seed/builder.ts","../src/seeder/registry.ts","../src/seeder/decorator.ts","../src/seeder/runner.ts"],"sourcesContent":["import type { DataSource } from 'typeorm';\n\n/** An entity instance — any class-based object managed by TypeORM. */\nexport type EntityInstance = object;\n\n/** A constructor that produces an entity instance. */\nexport type EntityConstructor<T extends EntityInstance = EntityInstance> = new () => T;\n\n/** Context passed through a seed operation. Available inside factory callbacks and `SeederInterface.run`. */\nexport interface SeedContext {\n /**\n * The TypeORM DataSource. Automatically set by `save`/`saveMany` calls.\n * Also available in factory callbacks — useful for looking up existing\n * entities instead of creating new ones:\n *\n * @example\n * @Seed(async ({ dataSource }) => dataSource.getRepository(Role).findOneByOrFail({ name: 'admin' }))\n * role!: Role\n */\n dataSource?: DataSource;\n /**\n * Set to `false` to skip automatic relation seeding. Scalar and embedded\n * properties are still seeded; only relation properties decorated with a\n * bare `@Seed()` are skipped. Useful when you want to create flat entities\n * and wire relations yourself.\n *\n * @default true\n */\n relations?: boolean;\n}\n\n/**\n * Factory callback passed to `@Seed`. Receives the seed context and the partially built entity.\n *\n * Properties are seeded sequentially in declaration order, so any property declared above the\n * current one is already set on `self` and can be read to derive the current value.\n *\n * Annotate `self` with the entity class to get full type inference — TypeScript infers\n * `TEntity` from the annotation, so no cast is needed:\n *\n * @example\n * @Seed(() => faker.date.past())\n * beginDate!: Date\n *\n * @Seed((_, self: MyEntity) => faker.date.future({ refDate: self.beginDate }))\n * endDate!: Date\n */\nexport type SeedFactory<T = unknown, TEntity = any> = (\n context: SeedContext,\n self: TEntity,\n) => T | Promise<T>;\n\n/** Options for the `@Seed` decorator. */\nexport interface SeedOptions {\n /**\n * Number of related entities to create. Only meaningful on one-to-many and\n * many-to-many relation properties. Ignored on scalar and single-entity relations.\n */\n count?: number;\n}\n\nexport interface SeedEntry {\n propertyKey: string | symbol;\n /** Undefined when @Seed is used without a factory (i.e. bare relation seed). */\n factory: SeedFactory | undefined;\n options: SeedOptions;\n}\n\nexport type MapToInstances<T extends readonly EntityConstructor[]> = {\n [K in keyof T]: T[K] extends EntityConstructor<infer I> ? I : never;\n};\n\nexport type MapToInstanceArrays<T extends readonly EntityConstructor[]> = {\n [K in keyof T]: T[K] extends EntityConstructor<infer I> ? I[] : never;\n};\n\n// Keyed by the entity class constructor.\nconst registry = new Map<Function, SeedEntry[]>();\n\n/** Registers a seed entry for the given class constructor. Called internally by the `@Seed` decorator. */\nexport function registerSeed(target: Function, entry: SeedEntry): void {\n const entries = registry.get(target) ?? [];\n\n entries.push(entry);\n registry.set(target, entries);\n}\n\n/**\n * Returns all seed entries for the given class, including those inherited from\n * parent classes. Parent entries come first, preserving declaration order.\n */\nexport function getSeeds(target: Function): SeedEntry[] {\n const entries: SeedEntry[] = [];\n let current: Function = target;\n\n while (current && current !== Function.prototype) {\n const own = registry.get(current);\n\n if (own) {\n entries.unshift(...own);\n }\n\n current = Object.getPrototypeOf(current) as Function;\n }\n\n return entries;\n}\n","import { registerSeed } from './registry.js';\nimport type { SeedFactory, SeedOptions } from './registry.js';\n\n/**\n * Marks a relation property for auto-seeding.\n *\n * The related entity class is inferred from TypeORM metadata. One instance is created\n * and recursively seeded (including its own `@Seed` properties).\n *\n * Circular back-references are broken automatically: if the related class is already\n * being seeded higher up in the same call chain, the property is left `undefined`.\n * TypeORM treats `undefined` as \"don't touch this column\" rather than setting it to null.\n */\nexport function Seed(): PropertyDecorator;\n/**\n * Marks a relation property for auto-seeding with options.\n *\n * Use `count` on one-to-many and many-to-many properties to control how many\n * related entities are created. Ignored for one-to-one and many-to-one.\n *\n * @example\n * @Seed({ count: 3 })\n * @OneToMany(() => Book, (b) => b.author)\n * books!: Book[]\n */\nexport function Seed(options: SeedOptions): PropertyDecorator;\n/**\n * Marks a property with a factory callback.\n *\n * The factory receives the current {@link SeedContext} and can return any value,\n * including a `Promise`. Use this for scalar properties or when you need full\n * control over how a related entity is resolved.\n *\n * @example\n * @Seed(() => faker.internet.email())\n * email!: string\n *\n * @example\n * // Look up an existing entity instead of creating a new one\n * @Seed(async ({ dataSource }) => dataSource.getRepository(Role).findOneByOrFail({ name: 'admin' }))\n * role!: Role\n */\nexport function Seed<TEntity = any>(factory: SeedFactory<unknown, TEntity>): PropertyDecorator;\n/** Marks a property with a factory callback and additional options. */\nexport function Seed<TEntity = any>(\n factory: SeedFactory<unknown, TEntity>,\n options: SeedOptions,\n): PropertyDecorator;\nexport function Seed(\n factoryOrOptions?: SeedFactory | SeedOptions,\n options?: SeedOptions,\n): PropertyDecorator {\n const factory = typeof factoryOrOptions === 'function' ? factoryOrOptions : undefined;\n const opts: SeedOptions =\n (typeof factoryOrOptions === 'object' ? factoryOrOptions : options) ?? {};\n\n return (target, propertyKey) => {\n registerSeed(target.constructor as Function, { propertyKey, factory, options: opts });\n };\n}\n","import { getMetadataArgsStorage } from 'typeorm';\nimport type {\n EntityConstructor,\n EntityInstance,\n MapToInstanceArrays,\n MapToInstances,\n SeedContext,\n} from './registry.js';\nimport { getSeeds } from './registry.js';\n\n/**\n * Options for {@link create} and {@link createMany} on the single-class form.\n * Extends {@link SeedContext} with a typed `values` override map.\n */\nexport interface CreateOptions<T extends EntityInstance> extends SeedContext {\n /**\n * Property values to apply after all `@Seed` factories have run.\n * Wins unconditionally — factories still execute but their output is overwritten.\n * Also works for properties that have no `@Seed` decorator.\n *\n * @example\n * const user = await dataSource.getRepository(User).findOneByOrFail({ name: 'Alice' })\n * const post = await seed(Post).create({ values: { author: user } })\n */\n values?: Partial<T>;\n}\n\n/** Options for {@link createMany}. Extends {@link SeedContext} with a required instance count. */\nexport interface CreateManyOptions<T extends EntityInstance = EntityInstance> extends SeedContext {\n count: number;\n values?: Partial<T>;\n}\n\n// Internal extension of SeedContext — never exposed in the public API.\ninterface InternalContext extends SeedContext {\n _ancestors: Set<Function>;\n}\n\n/** Extracts the ancestor set from an internal context, returning an empty set for external callers. */\nfunction getAncestors(context: SeedContext): Set<Function> {\n return (context as InternalContext)._ancestors ?? new Set();\n}\n\n/** Returns a new context with `cls` added to the ancestor set, used to detect circular relation chains. */\nfunction withAncestor(context: SeedContext, cls: Function): InternalContext {\n const ancestors = getAncestors(context);\n\n return { ...context, _ancestors: new Set([...ancestors, cls]) };\n}\n\n/** Walks the prototype chain and returns all classes from `target` up to (but not including) `Function.prototype`. */\nfunction getClassHierarchy(target: Function): Function[] {\n const hierarchy: Function[] = [];\n let current: Function = target;\n\n while (current && current !== Function.prototype) {\n hierarchy.push(current);\n current = Object.getPrototypeOf(current) as Function;\n }\n\n return hierarchy;\n}\n\n/**\n * Creates one fully populated instance of `EntityClass` in memory.\n *\n * Runs in three steps:\n * 1. Factory-decorated properties (`@Seed(factory)`) — run first, in declaration order.\n * 2. Embedded types (`@Embedded`) — auto-seeded if the embedded class has any `@Seed` entries.\n * 3. Bare relation decorators (`@Seed()` without a factory) — skipped when `relations` is `false`,\n * and also skipped for any related class already present in the ancestor chain (circular guard).\n */\nasync function createOne<T extends EntityInstance>(\n EntityClass: EntityConstructor<T>,\n context: SeedContext,\n): Promise<T> {\n const instance = new EntityClass();\n const ancestors = getAncestors(context);\n const childContext = withAncestor(context, EntityClass);\n const storage = getMetadataArgsStorage();\n const relations = storage.filterRelations(getClassHierarchy(EntityClass));\n const seededProperties = new Set<string | symbol>();\n const record = instance as Record<string | symbol, unknown>;\n\n // Step 1: Run @Seed entries that have an explicit factory.\n for (const { propertyKey, factory } of getSeeds(EntityClass)) {\n if (!factory) {\n continue;\n }\n\n record[propertyKey] = await factory(context, instance);\n seededProperties.add(propertyKey);\n }\n\n // Step 2: Auto-seed TypeORM embedded properties not already covered by Step 1.\n for (const embedded of storage.filterEmbeddeds(EntityClass)) {\n if (seededProperties.has(embedded.propertyName)) {\n continue;\n }\n\n const EmbeddedClass = embedded.type() as EntityConstructor;\n\n if (getSeeds(EmbeddedClass).length > 0) {\n record[embedded.propertyName] = await createOne(EmbeddedClass, context);\n seededProperties.add(embedded.propertyName);\n }\n }\n\n // Step 3: Auto-seed @Seed entries without a factory (relation seeds).\n // Uses the ancestor guard to cut circular chains: if the related class is\n // already being seeded higher up in this call chain, the property is left\n // undefined rather than triggering infinite recursion.\n // Skipped entirely when context.relations === false.\n if (context.relations === false) {\n return instance;\n }\n\n for (const { propertyKey, factory, options } of getSeeds(EntityClass)) {\n if (factory || seededProperties.has(propertyKey)) {\n continue;\n }\n\n const relation = relations.find((r) => r.propertyName === String(propertyKey));\n\n if (!relation || typeof relation.type !== 'function') {\n continue;\n }\n\n const RelatedClass = (relation.type as () => Function)() as EntityConstructor;\n\n if (ancestors.has(RelatedClass)) {\n continue;\n }\n\n const isArray =\n relation.relationType === 'one-to-many' || relation.relationType === 'many-to-many';\n\n if (isArray) {\n record[propertyKey] = await createMany(RelatedClass, {\n count: options.count ?? 1,\n ...childContext,\n });\n } else {\n record[propertyKey] = await createOne(RelatedClass, childContext);\n }\n\n seededProperties.add(propertyKey);\n }\n\n return instance;\n}\n\n/**\n * Creates one entity instance in memory without persisting it.\n *\n * When passed an array of classes, relation seeding is disabled by default\n * (pass `relations: true` in the context to override). Returns a tuple of\n * instances in the same order as the input array.\n */\nexport async function create<T extends EntityInstance>(\n EntityClass: EntityConstructor<T>,\n options?: CreateOptions<T>,\n): Promise<T>;\nexport async function create<T extends readonly EntityConstructor[]>(\n EntityClasses: [...T],\n context?: SeedContext,\n): Promise<MapToInstances<T>>;\nexport async function create<T extends EntityInstance>(\n classOrClasses: EntityConstructor<T> | readonly EntityConstructor[],\n options: CreateOptions<T> = {},\n): Promise<T | EntityInstance[]> {\n if (Array.isArray(classOrClasses)) {\n const effectiveContext: SeedContext = { relations: false, ...options };\n\n return (await Promise.all(\n (classOrClasses as EntityConstructor[]).map((cls) => createOne(cls, effectiveContext)),\n )) as EntityInstance[];\n }\n\n const { values, ...context } = options as CreateOptions<T>;\n const instance = await createOne(classOrClasses as EntityConstructor<T>, context);\n\n if (values) {\n Object.assign(instance, values);\n }\n\n return instance;\n}\n\n/**\n * Creates multiple entity instances in memory without persisting them.\n *\n * When passed an array of classes, returns a tuple of arrays — one per class — each\n * containing `count` instances. Relation seeding is disabled by default for the\n * array variant; pass `relations: true` in the options to override.\n */\nexport async function createMany<T extends EntityInstance>(\n EntityClass: EntityConstructor<T>,\n options: CreateManyOptions<T>,\n): Promise<T[]>;\nexport async function createMany<T extends readonly EntityConstructor[]>(\n EntityClasses: [...T],\n options: CreateManyOptions,\n): Promise<MapToInstanceArrays<T>>;\nexport async function createMany<T extends EntityInstance>(\n classOrClasses: EntityConstructor<T> | readonly EntityConstructor[],\n { count, values, ...context }: CreateManyOptions<T>,\n): Promise<T[] | EntityInstance[][]> {\n if (Array.isArray(classOrClasses)) {\n const effectiveContext: SeedContext = { relations: false, ...context };\n\n return (await Promise.all(\n (classOrClasses as EntityConstructor[]).map((cls) =>\n Promise.all(Array.from({ length: count }, () => createOne(cls, effectiveContext))),\n ),\n )) as EntityInstance[][];\n }\n\n const instances = await Promise.all(\n Array.from({ length: count }, () => createOne(classOrClasses as EntityConstructor<T>, context)),\n );\n\n if (values) {\n instances.forEach((e) => Object.assign(e, values));\n }\n\n return instances;\n}\n","import { type DataSource } from 'typeorm';\nimport { createMany } from './creator.js';\nimport type {\n EntityConstructor,\n EntityInstance,\n MapToInstanceArrays,\n MapToInstances,\n SeedContext,\n} from './registry.js';\n\n/** Options for {@link save}. Extends {@link SeedContext} with a required DataSource. */\nexport interface SaveOptions<T extends EntityInstance = EntityInstance> extends SeedContext {\n dataSource: DataSource;\n /**\n * Property values to apply to each entity after seeding and before persisting.\n * Wins unconditionally over `@Seed` factory output — the factory still runs,\n * but its result is overwritten. Also works for properties that have no `@Seed`\n * decorator at all.\n *\n * @example\n * const users = await dataSource.getRepository(User).find()\n * const user = faker.helpers.arrayElement(users)\n * await seed(Booking).saveMany(10, { dataSource, values: { user } })\n */\n values?: Partial<T>;\n}\n\n/** Options for {@link saveMany}. Extends {@link SaveOptions} with a required instance count. */\nexport interface SaveManyOptions<T extends EntityInstance = EntityInstance> extends SaveOptions<T> {\n count: number;\n}\n\ntype RelationMetadata = DataSource extends { getMetadata(...args: never[]): infer M }\n ? M extends { relations: Array<infer R> }\n ? R\n : never\n : never;\n\ninterface CascadeState {\n relation: RelationMetadata;\n original: boolean;\n}\n\n/**\n * Walks an entity object graph and collects every unique entity class encountered.\n * Used to discover all entity classes that need cascade-insert temporarily enabled\n * before saving so that the full in-memory graph is persisted in one shot.\n */\nfunction collectEntityClasses(entity: EntityInstance, visited = new Set<Function>()): Function[] {\n const EntityClass = entity.constructor as Function;\n\n if (visited.has(EntityClass)) {\n return [];\n }\n\n visited.add(EntityClass);\n\n const classes: Function[] = [EntityClass];\n\n for (const value of Object.values(entity)) {\n if (Array.isArray(value)) {\n for (const item of value) {\n if (item && typeof item === 'object' && item.constructor !== Object) {\n classes.push(...collectEntityClasses(item, visited));\n }\n }\n } else if (value && typeof value === 'object' && value.constructor !== Object) {\n classes.push(...collectEntityClasses(value as EntityInstance, visited));\n }\n }\n\n return classes;\n}\n\n/**\n * Temporarily enables `isCascadeInsert` on every TypeORM relation for the given class.\n * Returns the previous flag values so they can be restored after saving.\n *\n * This is necessary because the seeder builds the full object graph in memory before\n * calling `save()`. Without cascade inserts, TypeORM would only persist the root entity\n * and ignore any nested relations that weren't already configured with `cascade: true`.\n *\n * Classes not registered as TypeORM entities (e.g. embedded value objects) are silently skipped.\n */\nfunction enableCascadeInsert(EntityClass: Function, dataSource: DataSource): CascadeState[] {\n const states: CascadeState[] = [];\n\n try {\n const relations = dataSource.getMetadata(EntityClass).relations;\n\n for (const relation of relations) {\n states.push({ relation, original: relation.isCascadeInsert });\n relation.isCascadeInsert = true;\n }\n } catch {\n // Class is not registered as an entity with this DataSource (e.g. embedded class).\n }\n\n return states;\n}\n\n/**\n * Restores `isCascadeInsert` flags to their original values.\n * Always called in a `finally` block to guarantee cleanup even when saving throws.\n */\nfunction restoreCascade(states: CascadeState[]): void {\n for (const { relation, original } of states) {\n relation.isCascadeInsert = original;\n }\n}\n\n/**\n * Creates and persists a seed entity and all its seeded relations.\n */\nexport async function save<T extends EntityInstance>(\n EntityClass: EntityConstructor<T>,\n options: SaveOptions<T>,\n): Promise<T>;\n/**\n * Creates and persists one instance of each entity class in the array.\n * Relation seeding is disabled by default; pass `relations: true` to override.\n */\nexport async function save<T extends readonly EntityConstructor[]>(\n EntityClasses: [...T],\n options: SaveOptions,\n): Promise<MapToInstances<T>>;\nexport async function save<T extends EntityInstance>(\n classOrClasses: EntityConstructor<T> | readonly EntityConstructor[],\n options: SaveOptions<T>,\n): Promise<T | EntityInstance[]> {\n if (Array.isArray(classOrClasses)) {\n const effectiveOptions = { relations: false, ...options, count: 1 };\n\n return (await Promise.all(\n (classOrClasses as EntityConstructor[]).map((cls) =>\n saveBatch(cls, effectiveOptions).then(([entity]) => entity!),\n ),\n )) as EntityInstance[];\n }\n\n const [entity] = await saveBatch(classOrClasses as EntityConstructor<T>, {\n ...options,\n count: 1,\n });\n\n return entity!;\n}\n\n/**\n * Creates and persists multiple seed entities of the same class.\n * Applies the same logic as {@link save} for each entity.\n */\nexport async function saveMany<T extends EntityInstance>(\n EntityClass: EntityConstructor<T>,\n options: SaveManyOptions<T>,\n): Promise<T[]>;\n/**\n * Creates and persists multiple instances of each entity class in the array.\n * Relation seeding is disabled by default; pass `relations: true` to override.\n */\nexport async function saveMany<T extends readonly EntityConstructor[]>(\n EntityClasses: [...T],\n options: SaveManyOptions,\n): Promise<MapToInstanceArrays<T>>;\nexport async function saveMany<T extends EntityInstance>(\n classOrClasses: EntityConstructor<T> | readonly EntityConstructor[],\n options: SaveManyOptions<T>,\n): Promise<T[] | EntityInstance[][]> {\n if (Array.isArray(classOrClasses)) {\n const effectiveOptions = { relations: false, ...options };\n\n return (await Promise.all(\n (classOrClasses as EntityConstructor[]).map((cls) => saveBatch(cls, effectiveOptions)),\n )) as EntityInstance[][];\n }\n\n return await saveBatch(classOrClasses as EntityConstructor<T>, options);\n}\n\n/**\n * Creates and persists `count` instances of a single entity class in one batched\n * `repository.save()` call. Batching is intentional — it is more efficient than\n * saving each instance individually, as TypeORM can consolidate the inserts.\n *\n * Enables cascade inserts on every entity class in the object graph before saving,\n * then restores the original flags — regardless of whether the save succeeds or fails.\n */\nasync function saveBatch<T extends EntityInstance>(\n EntityClass: EntityConstructor<T>,\n options: SaveManyOptions<T>,\n): Promise<T[]> {\n const { count, dataSource } = options;\n\n if (count === 0) {\n return [];\n }\n\n const entities = await createMany(EntityClass, options);\n\n const visited = new Set<Function>();\n const states = entities\n .flatMap((entity) => collectEntityClasses(entity, visited))\n .flatMap((cls) => enableCascadeInsert(cls, dataSource));\n\n try {\n return (await dataSource.getRepository(EntityClass).save(entities)) as T[];\n } finally {\n restoreCascade(states);\n }\n}\n","import type { CreateOptions } from './creator.js';\nimport { create, createMany } from './creator.js';\nimport type { SaveManyOptions, SaveOptions } from './persist.js';\nimport { save, saveMany } from './persist.js';\nimport type {\n EntityConstructor,\n EntityInstance,\n MapToInstanceArrays,\n MapToInstances,\n SeedContext,\n} from './registry.js';\n\nexport type { CreateOptions } from './creator.js';\n\n/** Seed builder for a single entity class. Returned by {@link seed} when passed one class. */\ninterface SingleSeed<T extends EntityInstance> {\n /** Creates a single instance in memory without persisting. */\n create(context?: CreateOptions<T>): Promise<T>;\n /** Creates and persists a single instance. */\n save(options: SaveOptions<T>): Promise<T>;\n /** Creates multiple instances in memory without persisting. */\n createMany(count: number, context?: CreateOptions<T>): Promise<T[]>;\n /** Creates and persists multiple instances. */\n saveMany(count: number, options: SaveOptions<T>): Promise<T[]>;\n}\n\n/**\n * Seed builder for multiple entity classes. Returned by {@link seed} when passed an array.\n * Each method returns a tuple of instances in the same order as the input array.\n * Relation seeding is disabled by default; pass `relations: true` in the context to enable it.\n */\ninterface MultiSeed<T extends readonly EntityConstructor[]> {\n /** Creates one instance of each class in memory without persisting. */\n create(context?: SeedContext): Promise<MapToInstances<T>>;\n /** Creates and persists one instance of each class. */\n save(options: SaveOptions): Promise<MapToInstances<T>>;\n /** Creates `count` instances of each class in memory without persisting. */\n createMany(count: number, context?: SeedContext): Promise<MapToInstanceArrays<T>>;\n /** Creates and persists `count` instances of each class. */\n saveMany(count: number, options: SaveOptions): Promise<MapToInstanceArrays<T>>;\n}\n\n/**\n * Entry point for creating and persisting seed data.\n *\n * Pass a single entity class to get a {@link SingleSeed} builder, or an array of classes\n * to get a {@link MultiSeed} builder that operates on all of them at once.\n *\n * @example\n * // Create one Author in memory (no DB)\n * const author = await seed(Author).create()\n *\n * @example\n * // Persist one Author with all its seeded relations\n * const author = await seed(Author).save({ dataSource })\n *\n * @example\n * // Persist 10 Authors\n * const authors = await seed(Author).saveMany(10, { dataSource })\n *\n * @example\n * // Create multiple entity classes at once (relations disabled by default)\n * const [user, post] = await seed([User, Post]).create()\n */\nexport function seed<T extends EntityInstance>(EntityClass: EntityConstructor<T>): SingleSeed<T>;\nexport function seed<T extends readonly EntityConstructor[]>(EntityClasses: [...T]): MultiSeed<T>;\nexport function seed<T extends EntityInstance>(\n classOrClasses: EntityConstructor<T> | readonly EntityConstructor[],\n): SingleSeed<T> | MultiSeed<readonly EntityConstructor[]> {\n if (Array.isArray(classOrClasses)) {\n const classes = classOrClasses as readonly EntityConstructor[];\n\n return {\n create: (context?: SeedContext) =>\n create(classes as [...typeof classes], context) as Promise<MapToInstances<typeof classes>>,\n save: (options: SaveOptions) =>\n save(classes as [...typeof classes], options) as Promise<MapToInstances<typeof classes>>,\n createMany: (count: number, context?: SeedContext) =>\n createMany(classes as [...typeof classes], { count, ...context }) as Promise<\n MapToInstanceArrays<typeof classes>\n >,\n saveMany: (count: number, options: SaveOptions) =>\n saveMany(\n classes as [...typeof classes],\n { count, ...options } as SaveManyOptions,\n ) as Promise<MapToInstanceArrays<typeof classes>>,\n };\n }\n\n const EntityClass = classOrClasses as EntityConstructor<T>;\n\n return {\n create: (options?: CreateOptions<T>) => create(EntityClass, options),\n save: (options: SaveOptions<T>) => save(EntityClass, options),\n createMany: (count: number, options?: CreateOptions<T>) =>\n createMany(EntityClass, { count, ...options }),\n saveMany: (count: number, options: SaveOptions<T>) =>\n saveMany(EntityClass, { count, ...options }),\n };\n}\n","interface SeederMeta {\n dependencies: Function[];\n}\n\nconst registry = new WeakMap<Function, SeederMeta>();\n\n/** Registers seeder metadata for the given class constructor. Called internally by the `@Seeder` decorator. */\nexport function registerSeeder(target: Function, meta: SeederMeta): void {\n registry.set(target, meta);\n}\n\n/** Returns the metadata registered for the given seeder class, or `undefined` if not registered. */\nexport function getSeederMeta(target: Function): SeederMeta | undefined {\n return registry.get(target);\n}\n","import { registerSeeder } from './registry.js';\nimport type { SeedContext } from '../seed/registry.js';\n\n/**\n * Interface that seeder classes must implement.\n *\n * The `run` method receives the seed context (which includes the DataSource when\n * called via `runSeeders`) and performs the seeding logic — typically by calling\n * `seed().save()` or other seeding utilities.\n */\nexport interface SeederInterface {\n run(context: SeedContext): Promise<void>;\n}\n\n/** Configuration options for the {@link Seeder} decorator. */\nexport interface SeederOptions {\n /**\n * Seeder classes that must complete before this one runs.\n * Resolved transitively — dependencies of dependencies are included automatically.\n * {@link runSeeders} topologically sorts the full set and detects circular dependencies.\n */\n dependencies?: (new () => SeederInterface)[];\n}\n\n/**\n * Marks a class as a seeder and registers its dependency metadata.\n *\n * Classes decorated with `@Seeder` can be passed to {@link runSeeders}, which resolves\n * all transitive dependencies, sorts them topologically, and executes them in order.\n *\n * @example\n * @Seeder({ dependencies: [UserSeeder] })\n * class PostSeeder implements SeederInterface {\n * async run(ctx: SeedContext) {\n * await seed(Post).saveMany(50, ctx)\n * }\n * }\n */\nexport function Seeder(options: SeederOptions = {}): ClassDecorator {\n return (target) => {\n registerSeeder(target, { dependencies: options.dependencies ?? [] });\n };\n}\n","import { DepGraph } from 'dependency-graph';\nimport { getSeederMeta } from './registry.js';\nimport type { SeederInterface } from './decorator.js';\nimport type { SeedContext } from '../seed/registry.js';\n\n/** Constructor type for a class decorated with `@Seeder`. */\nexport type SeederCtor = new () => SeederInterface;\n\n/** Options for {@link runSeeders}. Extends {@link SeedContext} with lifecycle hooks and logging control. */\nexport interface RunSeedersOptions extends SeedContext {\n /**\n * Enable console logging for each seeder. Set to `false` to silence output,\n * e.g. when using callbacks to handle logging yourself.\n *\n * @default true\n */\n logging?: boolean;\n /** Called before each seeder runs, in execution order. */\n onBefore?: (seeder: SeederCtor) => void | Promise<void>;\n /** Called after each seeder completes successfully, with the time it took in milliseconds. */\n onAfter?: (seeder: SeederCtor, durationMs: number) => void | Promise<void>;\n /** Called when a seeder throws. The error is re-thrown after this callback returns. */\n onError?: (seeder: SeederCtor, error: unknown) => void | Promise<void>;\n /** Called for each seeder before it runs. Return `true` to skip it entirely. */\n skip?: (seeder: SeederCtor) => boolean | Promise<boolean>;\n}\n\n/**\n * Topologically sorts the given seeders and all their transitive dependencies.\n * BFS walks from the roots to collect all nodes, then dependency edges are wired and\n * the graph is sorted so that every dependency precedes the seeders that depend on it.\n * Throws a descriptive error if a circular dependency is detected.\n */\nfunction topoSort(roots: SeederCtor[]): SeederCtor[] {\n const graph = new DepGraph<SeederCtor>();\n const byName = new Map<string, SeederCtor>();\n\n // Collect all nodes transitively via BFS and register them in the graph.\n const visited = new Set<SeederCtor>();\n const queue: SeederCtor[] = [...roots];\n\n while (queue.length > 0) {\n const node = queue.shift()!;\n\n if (visited.has(node)) {\n continue;\n }\n\n visited.add(node);\n graph.addNode(node.name, node);\n byName.set(node.name, node);\n\n for (const dep of (getSeederMeta(node)?.dependencies ?? []) as SeederCtor[]) {\n queue.push(dep);\n }\n }\n\n // Wire up the dependency edges.\n for (const node of visited) {\n for (const dep of (getSeederMeta(node)?.dependencies ?? []) as SeederCtor[]) {\n graph.addDependency(node.name, dep.name);\n }\n }\n\n try {\n return graph.overallOrder().map((name) => byName.get(name)!);\n } catch (err) {\n if (err && typeof err === 'object' && 'cyclePath' in err) {\n const path = (err as { cyclePath: string[] }).cyclePath.join(' → ');\n throw new Error(`Circular dependency detected among seeders: ${path}`);\n }\n\n throw err;\n }\n}\n\n/**\n * Runs the given seeders (and all their transitive dependencies) in dependency order.\n *\n * Each seeder is instantiated, its `run` method is called with the context derived\n * from `options`, and lifecycle hooks (`onBefore`, `onAfter`, `onError`) are called\n * around it. Errors are re-thrown after `onError` returns.\n *\n * @example\n * await runSeeders([PostSeeder], { dataSource })\n *\n * @example\n * // With lifecycle hooks and no console output\n * await runSeeders([PostSeeder], {\n * dataSource,\n * logging: false,\n * onAfter: (seeder, ms) => console.log(`${seeder.name} done in ${ms}ms`),\n * })\n */\nexport async function runSeeders(\n seeders: SeederCtor[],\n options: RunSeedersOptions = {},\n): Promise<void> {\n const { logging = true, onBefore, onAfter, onError, skip, ...context } = options;\n\n for (const SeederClass of topoSort(seeders)) {\n if (await skip?.(SeederClass)) {\n continue;\n }\n\n if (logging) {\n console.log(`[${SeederClass.name}] Starting...`);\n }\n\n await onBefore?.(SeederClass);\n\n const start = Date.now();\n\n try {\n await new SeederClass().run(context);\n } catch (err) {\n const durationMs = Date.now() - start;\n\n if (logging) {\n console.error(`[${SeederClass.name}] Failed after ${durationMs}ms`);\n }\n\n await onError?.(SeederClass, err);\n throw err;\n }\n\n const durationMs = Date.now() - start;\n\n if (logging) {\n console.log(`[${SeederClass.name}] Done in ${durationMs}ms`);\n }\n\n await onAfter?.(SeederClass, durationMs);\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":["registry","DepGraph"],"sources":["../src/seed/registry.ts","../src/seed/decorator.ts","../src/seed/creator.ts","../src/seed/persist.ts","../src/seed/builder.ts","../src/seeder/registry.ts","../src/seeder/decorator.ts","../src/seeder/runner.ts"],"sourcesContent":["import type { DataSource } from 'typeorm';\n\n/** An entity instance — any class-based object managed by TypeORM. */\nexport type EntityInstance = object;\n\n/** A constructor that produces an entity instance. */\nexport type EntityConstructor<T extends EntityInstance = EntityInstance> = new () => T;\n\n/** Context passed through a seed operation. Available inside factory callbacks and `SeederInterface.run`. */\nexport interface SeedContext {\n /**\n * The TypeORM DataSource. Automatically set by `save`/`saveMany` calls.\n * Also available in factory callbacks — useful for looking up existing\n * entities instead of creating new ones:\n *\n * @example\n * @Seed(async ({ dataSource }) => dataSource.getRepository(Role).findOneByOrFail({ name: 'admin' }))\n * role!: Role\n */\n dataSource?: DataSource;\n /**\n * Set to `false` to skip automatic relation seeding. Scalar and embedded\n * properties are still seeded; only relation properties decorated with a\n * bare `@Seed()` are skipped. Useful when you want to create flat entities\n * and wire relations yourself.\n *\n * @default true\n */\n relations?: boolean;\n}\n\n/**\n * Factory callback passed to `@Seed`. Receives the seed context and the partially built entity.\n *\n * Properties are seeded sequentially in declaration order, so any property declared above the\n * current one is already set on `self` and can be read to derive the current value.\n *\n * Annotate `self` with the entity class to get full type inference — TypeScript infers\n * `TEntity` from the annotation, so no cast is needed:\n *\n * @example\n * @Seed(() => faker.date.past())\n * beginDate!: Date\n *\n * @Seed((_, self: MyEntity) => faker.date.future({ refDate: self.beginDate }))\n * endDate!: Date\n */\nexport type SeedFactory<T = unknown, TEntity = any> = (\n context: SeedContext,\n self: TEntity,\n) => T | Promise<T>;\n\n/** Options for the `@Seed` decorator. */\nexport interface SeedOptions {\n /**\n * Number of related entities to create. Only meaningful on one-to-many and\n * many-to-many relation properties. Ignored on scalar and single-entity relations.\n */\n count?: number;\n}\n\nexport interface SeedEntry {\n propertyKey: string | symbol;\n /** Undefined when @Seed is used without a factory (i.e. bare relation seed). */\n factory: SeedFactory | undefined;\n options: SeedOptions;\n}\n\nexport type MapToInstances<T extends readonly EntityConstructor[]> = {\n [K in keyof T]: T[K] extends EntityConstructor<infer I> ? I : never;\n};\n\nexport type MapToInstanceArrays<T extends readonly EntityConstructor[]> = {\n [K in keyof T]: T[K] extends EntityConstructor<infer I> ? I[] : never;\n};\n\n// Keyed by the entity class constructor.\nconst registry = new Map<Function, SeedEntry[]>();\n\n/** Registers a seed entry for the given class constructor. Called internally by the `@Seed` decorator. */\nexport function registerSeed(target: Function, entry: SeedEntry): void {\n const entries = registry.get(target) ?? [];\n\n entries.push(entry);\n registry.set(target, entries);\n}\n\n/**\n * Returns all seed entries for the given class, including those inherited from\n * parent classes. Parent entries come first, preserving declaration order.\n */\nexport function getSeeds(target: Function): SeedEntry[] {\n const entries: SeedEntry[] = [];\n let current: Function = target;\n\n while (current && current !== Function.prototype) {\n const own = registry.get(current);\n\n if (own) {\n entries.unshift(...own);\n }\n\n current = Object.getPrototypeOf(current) as Function;\n }\n\n return entries;\n}\n","import { registerSeed } from './registry.js';\nimport type { SeedFactory, SeedOptions } from './registry.js';\n\n/**\n * Marks a relation property for auto-seeding.\n *\n * The related entity class is inferred from TypeORM metadata. One instance is created\n * and recursively seeded (including its own `@Seed` properties).\n *\n * Circular back-references are broken automatically: if the related class is already\n * being seeded higher up in the same call chain, the property is left `undefined`.\n * TypeORM treats `undefined` as \"don't touch this column\" rather than setting it to null.\n */\nexport function Seed(): PropertyDecorator;\n/**\n * Marks a relation property for auto-seeding with options.\n *\n * Use `count` on one-to-many and many-to-many properties to control how many\n * related entities are created. Ignored for one-to-one and many-to-one.\n *\n * @example\n * @Seed({ count: 3 })\n * @OneToMany(() => Book, (b) => b.author)\n * books!: Book[]\n */\nexport function Seed(options: SeedOptions): PropertyDecorator;\n/**\n * Marks a property with a factory callback.\n *\n * The factory receives the current {@link SeedContext} and can return any value,\n * including a `Promise`. Use this for scalar properties or when you need full\n * control over how a related entity is resolved.\n *\n * @example\n * @Seed(() => faker.internet.email())\n * email!: string\n *\n * @example\n * // Look up an existing entity instead of creating a new one\n * @Seed(async ({ dataSource }) => dataSource.getRepository(Role).findOneByOrFail({ name: 'admin' }))\n * role!: Role\n */\nexport function Seed<TEntity = any>(factory: SeedFactory<unknown, TEntity>): PropertyDecorator;\n/** Marks a property with a factory callback and additional options. */\nexport function Seed<TEntity = any>(\n factory: SeedFactory<unknown, TEntity>,\n options: SeedOptions,\n): PropertyDecorator;\nexport function Seed(\n factoryOrOptions?: SeedFactory | SeedOptions,\n options?: SeedOptions,\n): PropertyDecorator {\n const factory = typeof factoryOrOptions === 'function' ? factoryOrOptions : undefined;\n const opts: SeedOptions =\n (typeof factoryOrOptions === 'object' ? factoryOrOptions : options) ?? {};\n\n return (target, propertyKey) => {\n registerSeed(target.constructor as Function, { propertyKey, factory, options: opts });\n };\n}\n","import { getMetadataArgsStorage } from 'typeorm';\nimport type {\n EntityConstructor,\n EntityInstance,\n MapToInstanceArrays,\n MapToInstances,\n SeedContext,\n SeedFactory,\n} from './registry.js';\nimport { getSeeds } from './registry.js';\n\n/**\n * A map of property overrides for seeded entities.\n * Each property can be either a static value or a {@link SeedFactory} that is called\n * once per entity — enabling unique random values across each created instance.\n *\n * @example\n * // All 10 bookings get a unique random price\n * await seed(Booking).saveMany(10, {\n * dataSource,\n * values: { price: () => faker.number.float({ min: 10, max: 500 }) },\n * })\n */\nexport type SeedValues<T extends EntityInstance> = {\n [K in keyof T]?: T[K] | SeedFactory<T[K], T>;\n};\n\n/**\n * Options for {@link create} and {@link createMany} on the single-class form.\n * Extends {@link SeedContext} with a typed `values` override map.\n */\nexport interface CreateOptions<T extends EntityInstance> extends SeedContext {\n /**\n * Property values to apply after all `@Seed` factories have run.\n * Wins unconditionally — factories still execute but their output is overwritten.\n * Also works for properties that have no `@Seed` decorator.\n *\n * @example\n * const user = await dataSource.getRepository(User).findOneByOrFail({ name: 'Alice' })\n * const post = await seed(Post).create({ values: { author: user } })\n */\n values?: SeedValues<T>;\n}\n\n/** Options for {@link createMany}. Extends {@link SeedContext} with a required instance count. */\nexport interface CreateManyOptions<T extends EntityInstance = EntityInstance> extends SeedContext {\n count: number;\n values?: SeedValues<T>;\n}\n\n// Internal extension of SeedContext — never exposed in the public API.\ninterface InternalContext extends SeedContext {\n _ancestors: Set<Function>;\n}\n\n/** Extracts the ancestor set from an internal context, returning an empty set for external callers. */\nfunction getAncestors(context: SeedContext): Set<Function> {\n return (context as InternalContext)._ancestors ?? new Set();\n}\n\n/**\n * Applies a {@link SeedValues} map to an instance.\n * Factory entries are called once per instance so each entity can get unique values.\n */\nasync function applyValues<T extends EntityInstance>(\n instance: T,\n values: SeedValues<T>,\n context: SeedContext,\n): Promise<void> {\n const record = instance as Record<string | symbol, unknown>;\n\n for (const key of Object.keys(values) as (keyof T & string)[]) {\n const value = values[key];\n\n if (typeof value === 'function') {\n record[key] = await (value as SeedFactory)(context, instance);\n } else {\n record[key] = value;\n }\n }\n}\n\n/** Returns a new context with `cls` added to the ancestor set, used to detect circular relation chains. */\nfunction withAncestor(context: SeedContext, cls: Function): InternalContext {\n const ancestors = getAncestors(context);\n\n return { ...context, _ancestors: new Set([...ancestors, cls]) };\n}\n\n/** Walks the prototype chain and returns all classes from `target` up to (but not including) `Function.prototype`. */\nfunction getClassHierarchy(target: Function): Function[] {\n const hierarchy: Function[] = [];\n let current: Function = target;\n\n while (current && current !== Function.prototype) {\n hierarchy.push(current);\n current = Object.getPrototypeOf(current) as Function;\n }\n\n return hierarchy;\n}\n\n/**\n * Creates one fully populated instance of `EntityClass` in memory.\n *\n * Runs in three steps:\n * 1. Factory-decorated properties (`@Seed(factory)`) — run first, in declaration order.\n * 2. Embedded types (`@Embedded`) — auto-seeded if the embedded class has any `@Seed` entries.\n * 3. Bare relation decorators (`@Seed()` without a factory) — skipped when `relations` is `false`,\n * and also skipped for any related class already present in the ancestor chain (circular guard).\n */\nasync function createOne<T extends EntityInstance>(\n EntityClass: EntityConstructor<T>,\n context: SeedContext,\n): Promise<T> {\n const instance = new EntityClass();\n const ancestors = getAncestors(context);\n const childContext = withAncestor(context, EntityClass);\n const storage = getMetadataArgsStorage();\n const relations = storage.filterRelations(getClassHierarchy(EntityClass));\n const seededProperties = new Set<string | symbol>();\n const record = instance as Record<string | symbol, unknown>;\n\n // Step 1: Run @Seed entries that have an explicit factory.\n for (const { propertyKey, factory } of getSeeds(EntityClass)) {\n if (!factory) {\n continue;\n }\n\n record[propertyKey] = await factory(context, instance);\n seededProperties.add(propertyKey);\n }\n\n // Step 2: Auto-seed TypeORM embedded properties not already covered by Step 1.\n for (const embedded of storage.filterEmbeddeds(EntityClass)) {\n if (seededProperties.has(embedded.propertyName)) {\n continue;\n }\n\n const EmbeddedClass = embedded.type() as EntityConstructor;\n\n if (getSeeds(EmbeddedClass).length > 0) {\n record[embedded.propertyName] = await createOne(EmbeddedClass, context);\n seededProperties.add(embedded.propertyName);\n }\n }\n\n // Step 3: Auto-seed @Seed entries without a factory (relation seeds).\n // Uses the ancestor guard to cut circular chains: if the related class is\n // already being seeded higher up in this call chain, the property is left\n // undefined rather than triggering infinite recursion.\n // Skipped entirely when context.relations === false.\n if (context.relations === false) {\n return instance;\n }\n\n for (const { propertyKey, factory, options } of getSeeds(EntityClass)) {\n if (factory || seededProperties.has(propertyKey)) {\n continue;\n }\n\n const relation = relations.find((r) => r.propertyName === String(propertyKey));\n\n if (!relation || typeof relation.type !== 'function') {\n continue;\n }\n\n const RelatedClass = (relation.type as () => Function)() as EntityConstructor;\n\n if (ancestors.has(RelatedClass)) {\n continue;\n }\n\n const isArray =\n relation.relationType === 'one-to-many' || relation.relationType === 'many-to-many';\n\n if (isArray) {\n record[propertyKey] = await createMany(RelatedClass, {\n count: options.count ?? 1,\n ...childContext,\n });\n } else {\n record[propertyKey] = await createOne(RelatedClass, childContext);\n }\n\n seededProperties.add(propertyKey);\n }\n\n return instance;\n}\n\n/**\n * Creates one entity instance in memory without persisting it.\n *\n * When passed an array of classes, relation seeding is disabled by default\n * (pass `relations: true` in the context to override). Returns a tuple of\n * instances in the same order as the input array.\n */\nexport async function create<T extends EntityInstance>(\n EntityClass: EntityConstructor<T>,\n options?: CreateOptions<T>,\n): Promise<T>;\nexport async function create<T extends readonly EntityConstructor[]>(\n EntityClasses: [...T],\n context?: SeedContext,\n): Promise<MapToInstances<T>>;\nexport async function create<T extends EntityInstance>(\n classOrClasses: EntityConstructor<T> | readonly EntityConstructor[],\n options: CreateOptions<T> = {},\n): Promise<T | EntityInstance[]> {\n if (Array.isArray(classOrClasses)) {\n const effectiveContext: SeedContext = { relations: false, ...options };\n\n return (await Promise.all(\n (classOrClasses as EntityConstructor[]).map((cls) => createOne(cls, effectiveContext)),\n )) as EntityInstance[];\n }\n\n const { values, ...context } = options as CreateOptions<T>;\n const instance = await createOne(classOrClasses as EntityConstructor<T>, context);\n\n if (values) {\n await applyValues(instance, values, context);\n }\n\n return instance;\n}\n\n/**\n * Creates multiple entity instances in memory without persisting them.\n *\n * When passed an array of classes, returns a tuple of arrays — one per class — each\n * containing `count` instances. Relation seeding is disabled by default for the\n * array variant; pass `relations: true` in the options to override.\n */\nexport async function createMany<T extends EntityInstance>(\n EntityClass: EntityConstructor<T>,\n options: CreateManyOptions<T>,\n): Promise<T[]>;\nexport async function createMany<T extends readonly EntityConstructor[]>(\n EntityClasses: [...T],\n options: CreateManyOptions,\n): Promise<MapToInstanceArrays<T>>;\nexport async function createMany<T extends EntityInstance>(\n classOrClasses: EntityConstructor<T> | readonly EntityConstructor[],\n { count, values, ...context }: CreateManyOptions<T>,\n): Promise<T[] | EntityInstance[][]> {\n if (Array.isArray(classOrClasses)) {\n const effectiveContext: SeedContext = { relations: false, ...context };\n\n return (await Promise.all(\n (classOrClasses as EntityConstructor[]).map((cls) =>\n Promise.all(Array.from({ length: count }, () => createOne(cls, effectiveContext))),\n ),\n )) as EntityInstance[][];\n }\n\n const instances = await Promise.all(\n Array.from({ length: count }, () => createOne(classOrClasses as EntityConstructor<T>, context)),\n );\n\n if (values) {\n await Promise.all(instances.map((instance) => applyValues(instance, values, context)));\n }\n\n return instances;\n}\n","import { type DataSource } from 'typeorm';\nimport { createMany } from './creator.js';\nimport type { SeedValues } from './creator.js';\nimport type {\n EntityConstructor,\n EntityInstance,\n MapToInstanceArrays,\n MapToInstances,\n SeedContext,\n} from './registry.js';\n\n/** Options for {@link save}. Extends {@link SeedContext} with a required DataSource. */\nexport interface SaveOptions<T extends EntityInstance = EntityInstance> extends SeedContext {\n dataSource: DataSource;\n /**\n * Property values to apply to each entity after seeding and before persisting.\n * Wins unconditionally over `@Seed` factory output — the factory still runs,\n * but its result is overwritten. Also works for properties that have no `@Seed`\n * decorator at all.\n *\n * @example\n * const users = await dataSource.getRepository(User).find()\n * const user = faker.helpers.arrayElement(users)\n * await seed(Booking).saveMany(10, { dataSource, values: { user } })\n */\n values?: SeedValues<T>;\n}\n\n/** Options for {@link saveMany}. Extends {@link SaveOptions} with a required instance count. */\nexport interface SaveManyOptions<T extends EntityInstance = EntityInstance> extends SaveOptions<T> {\n count: number;\n}\n\ntype RelationMetadata = DataSource extends { getMetadata(...args: never[]): infer M }\n ? M extends { relations: Array<infer R> }\n ? R\n : never\n : never;\n\ninterface CascadeState {\n relation: RelationMetadata;\n original: boolean;\n}\n\n/**\n * Walks an entity object graph and collects every unique entity class encountered.\n * Used to discover all entity classes that need cascade-insert temporarily enabled\n * before saving so that the full in-memory graph is persisted in one shot.\n */\nfunction collectEntityClasses(entity: EntityInstance, visited = new Set<Function>()): Function[] {\n const EntityClass = entity.constructor as Function;\n\n if (visited.has(EntityClass)) {\n return [];\n }\n\n visited.add(EntityClass);\n\n const classes: Function[] = [EntityClass];\n\n for (const value of Object.values(entity)) {\n if (Array.isArray(value)) {\n for (const item of value) {\n if (item && typeof item === 'object' && item.constructor !== Object) {\n classes.push(...collectEntityClasses(item, visited));\n }\n }\n } else if (value && typeof value === 'object' && value.constructor !== Object) {\n classes.push(...collectEntityClasses(value as EntityInstance, visited));\n }\n }\n\n return classes;\n}\n\n/**\n * Temporarily enables `isCascadeInsert` on every TypeORM relation for the given class.\n * Returns the previous flag values so they can be restored after saving.\n *\n * This is necessary because the seeder builds the full object graph in memory before\n * calling `save()`. Without cascade inserts, TypeORM would only persist the root entity\n * and ignore any nested relations that weren't already configured with `cascade: true`.\n *\n * Classes not registered as TypeORM entities (e.g. embedded value objects) are silently skipped.\n */\nfunction enableCascadeInsert(EntityClass: Function, dataSource: DataSource): CascadeState[] {\n const states: CascadeState[] = [];\n\n try {\n const relations = dataSource.getMetadata(EntityClass).relations;\n\n for (const relation of relations) {\n states.push({ relation, original: relation.isCascadeInsert });\n relation.isCascadeInsert = true;\n }\n } catch {\n // Class is not registered as an entity with this DataSource (e.g. embedded class).\n }\n\n return states;\n}\n\n/**\n * Restores `isCascadeInsert` flags to their original values.\n * Always called in a `finally` block to guarantee cleanup even when saving throws.\n */\nfunction restoreCascade(states: CascadeState[]): void {\n for (const { relation, original } of states) {\n relation.isCascadeInsert = original;\n }\n}\n\n/**\n * Creates and persists a seed entity and all its seeded relations.\n */\nexport async function save<T extends EntityInstance>(\n EntityClass: EntityConstructor<T>,\n options: SaveOptions<T>,\n): Promise<T>;\n/**\n * Creates and persists one instance of each entity class in the array.\n * Relation seeding is disabled by default; pass `relations: true` to override.\n */\nexport async function save<T extends readonly EntityConstructor[]>(\n EntityClasses: [...T],\n options: SaveOptions,\n): Promise<MapToInstances<T>>;\nexport async function save<T extends EntityInstance>(\n classOrClasses: EntityConstructor<T> | readonly EntityConstructor[],\n options: SaveOptions<T>,\n): Promise<T | EntityInstance[]> {\n if (Array.isArray(classOrClasses)) {\n const effectiveOptions = { relations: false, ...options, count: 1 };\n\n return (await Promise.all(\n (classOrClasses as EntityConstructor[]).map((cls) =>\n saveBatch(cls, effectiveOptions).then(([entity]) => entity!),\n ),\n )) as EntityInstance[];\n }\n\n const [entity] = await saveBatch(classOrClasses as EntityConstructor<T>, {\n ...options,\n count: 1,\n });\n\n return entity!;\n}\n\n/**\n * Creates and persists multiple seed entities of the same class.\n * Applies the same logic as {@link save} for each entity.\n */\nexport async function saveMany<T extends EntityInstance>(\n EntityClass: EntityConstructor<T>,\n options: SaveManyOptions<T>,\n): Promise<T[]>;\n/**\n * Creates and persists multiple instances of each entity class in the array.\n * Relation seeding is disabled by default; pass `relations: true` to override.\n */\nexport async function saveMany<T extends readonly EntityConstructor[]>(\n EntityClasses: [...T],\n options: SaveManyOptions,\n): Promise<MapToInstanceArrays<T>>;\nexport async function saveMany<T extends EntityInstance>(\n classOrClasses: EntityConstructor<T> | readonly EntityConstructor[],\n options: SaveManyOptions<T>,\n): Promise<T[] | EntityInstance[][]> {\n if (Array.isArray(classOrClasses)) {\n const effectiveOptions = { relations: false, ...options };\n\n return (await Promise.all(\n (classOrClasses as EntityConstructor[]).map((cls) => saveBatch(cls, effectiveOptions)),\n )) as EntityInstance[][];\n }\n\n return await saveBatch(classOrClasses as EntityConstructor<T>, options);\n}\n\n/**\n * Creates and persists `count` instances of a single entity class in one batched\n * `repository.save()` call. Batching is intentional — it is more efficient than\n * saving each instance individually, as TypeORM can consolidate the inserts.\n *\n * Enables cascade inserts on every entity class in the object graph before saving,\n * then restores the original flags — regardless of whether the save succeeds or fails.\n */\nasync function saveBatch<T extends EntityInstance>(\n EntityClass: EntityConstructor<T>,\n options: SaveManyOptions<T>,\n): Promise<T[]> {\n const { count, dataSource } = options;\n\n if (count === 0) {\n return [];\n }\n\n const entities = await createMany(EntityClass, options);\n\n const visited = new Set<Function>();\n const states = entities\n .flatMap((entity) => collectEntityClasses(entity, visited))\n .flatMap((cls) => enableCascadeInsert(cls, dataSource));\n\n try {\n return (await dataSource.getRepository(EntityClass).save(entities)) as T[];\n } finally {\n restoreCascade(states);\n }\n}\n","import type { CreateOptions } from './creator.js';\nimport { create, createMany } from './creator.js';\nimport type { SaveManyOptions, SaveOptions } from './persist.js';\nimport { save, saveMany } from './persist.js';\nimport type {\n EntityConstructor,\n EntityInstance,\n MapToInstanceArrays,\n MapToInstances,\n SeedContext,\n} from './registry.js';\n\nexport type { CreateOptions } from './creator.js';\n\n/** Seed builder for a single entity class. Returned by {@link seed} when passed one class. */\ninterface SingleSeed<T extends EntityInstance> {\n /** Creates a single instance in memory without persisting. */\n create(context?: CreateOptions<T>): Promise<T>;\n /** Creates and persists a single instance. */\n save(options: SaveOptions<T>): Promise<T>;\n /** Creates multiple instances in memory without persisting. */\n createMany(count: number, context?: CreateOptions<T>): Promise<T[]>;\n /** Creates and persists multiple instances. */\n saveMany(count: number, options: SaveOptions<T>): Promise<T[]>;\n}\n\n/**\n * Seed builder for multiple entity classes. Returned by {@link seed} when passed an array.\n * Each method returns a tuple of instances in the same order as the input array.\n * Relation seeding is disabled by default; pass `relations: true` in the context to enable it.\n */\ninterface MultiSeed<T extends readonly EntityConstructor[]> {\n /** Creates one instance of each class in memory without persisting. */\n create(context?: SeedContext): Promise<MapToInstances<T>>;\n /** Creates and persists one instance of each class. */\n save(options: SaveOptions): Promise<MapToInstances<T>>;\n /** Creates `count` instances of each class in memory without persisting. */\n createMany(count: number, context?: SeedContext): Promise<MapToInstanceArrays<T>>;\n /** Creates and persists `count` instances of each class. */\n saveMany(count: number, options: SaveOptions): Promise<MapToInstanceArrays<T>>;\n}\n\n/**\n * Entry point for creating and persisting seed data.\n *\n * Pass a single entity class to get a {@link SingleSeed} builder, or an array of classes\n * to get a {@link MultiSeed} builder that operates on all of them at once.\n *\n * @example\n * // Create one Author in memory (no DB)\n * const author = await seed(Author).create()\n *\n * @example\n * // Persist one Author with all its seeded relations\n * const author = await seed(Author).save({ dataSource })\n *\n * @example\n * // Persist 10 Authors\n * const authors = await seed(Author).saveMany(10, { dataSource })\n *\n * @example\n * // Create multiple entity classes at once (relations disabled by default)\n * const [user, post] = await seed([User, Post]).create()\n */\nexport function seed<T extends EntityInstance>(EntityClass: EntityConstructor<T>): SingleSeed<T>;\nexport function seed<T extends readonly EntityConstructor[]>(EntityClasses: [...T]): MultiSeed<T>;\nexport function seed<T extends EntityInstance>(\n classOrClasses: EntityConstructor<T> | readonly EntityConstructor[],\n): SingleSeed<T> | MultiSeed<readonly EntityConstructor[]> {\n if (Array.isArray(classOrClasses)) {\n const classes = classOrClasses as readonly EntityConstructor[];\n\n return {\n create: (context?: SeedContext) =>\n create(classes as [...typeof classes], context) as Promise<MapToInstances<typeof classes>>,\n save: (options: SaveOptions) =>\n save(classes as [...typeof classes], options) as Promise<MapToInstances<typeof classes>>,\n createMany: (count: number, context?: SeedContext) =>\n createMany(classes as [...typeof classes], { count, ...context }) as Promise<\n MapToInstanceArrays<typeof classes>\n >,\n saveMany: (count: number, options: SaveOptions) =>\n saveMany(\n classes as [...typeof classes],\n { count, ...options } as SaveManyOptions,\n ) as Promise<MapToInstanceArrays<typeof classes>>,\n };\n }\n\n const EntityClass = classOrClasses as EntityConstructor<T>;\n\n return {\n create: (options?: CreateOptions<T>) => create(EntityClass, options),\n save: (options: SaveOptions<T>) => save(EntityClass, options),\n createMany: (count: number, options?: CreateOptions<T>) =>\n createMany(EntityClass, { count, ...options }),\n saveMany: (count: number, options: SaveOptions<T>) =>\n saveMany(EntityClass, { count, ...options }),\n };\n}\n","interface SeederMeta {\n dependencies: Function[];\n}\n\nconst registry = new WeakMap<Function, SeederMeta>();\n\n/** Registers seeder metadata for the given class constructor. Called internally by the `@Seeder` decorator. */\nexport function registerSeeder(target: Function, meta: SeederMeta): void {\n registry.set(target, meta);\n}\n\n/** Returns the metadata registered for the given seeder class, or `undefined` if not registered. */\nexport function getSeederMeta(target: Function): SeederMeta | undefined {\n return registry.get(target);\n}\n","import { registerSeeder } from './registry.js';\nimport type { SeedContext } from '../seed/registry.js';\n\n/**\n * Interface that seeder classes must implement.\n *\n * The `run` method receives the seed context (which includes the DataSource when\n * called via `runSeeders`) and performs the seeding logic — typically by calling\n * `seed().save()` or other seeding utilities.\n */\nexport interface SeederInterface {\n run(context: SeedContext): Promise<void>;\n}\n\n/** Configuration options for the {@link Seeder} decorator. */\nexport interface SeederOptions {\n /**\n * Seeder classes that must complete before this one runs.\n * Resolved transitively — dependencies of dependencies are included automatically.\n * {@link runSeeders} topologically sorts the full set and detects circular dependencies.\n */\n dependencies?: (new () => SeederInterface)[];\n}\n\n/**\n * Marks a class as a seeder and registers its dependency metadata.\n *\n * Classes decorated with `@Seeder` can be passed to {@link runSeeders}, which resolves\n * all transitive dependencies, sorts them topologically, and executes them in order.\n *\n * @example\n * @Seeder({ dependencies: [UserSeeder] })\n * class PostSeeder implements SeederInterface {\n * async run(ctx: SeedContext) {\n * await seed(Post).saveMany(50, ctx)\n * }\n * }\n */\nexport function Seeder(options: SeederOptions = {}): ClassDecorator {\n return (target) => {\n registerSeeder(target, { dependencies: options.dependencies ?? [] });\n };\n}\n","import { DepGraph } from 'dependency-graph';\nimport { getSeederMeta } from './registry.js';\nimport type { SeederInterface } from './decorator.js';\nimport type { SeedContext } from '../seed/registry.js';\n\n/** Constructor type for a class decorated with `@Seeder`. */\nexport type SeederCtor = new () => SeederInterface;\n\n/** Options for {@link runSeeders}. Extends {@link SeedContext} with lifecycle hooks and logging control. */\nexport interface RunSeedersOptions extends SeedContext {\n /**\n * Enable console logging for each seeder. Set to `false` to silence output,\n * e.g. when using callbacks to handle logging yourself.\n *\n * @default true\n */\n logging?: boolean;\n /** Called before each seeder runs, in execution order. */\n onBefore?: (seeder: SeederCtor) => void | Promise<void>;\n /** Called after each seeder completes successfully, with the time it took in milliseconds. */\n onAfter?: (seeder: SeederCtor, durationMs: number) => void | Promise<void>;\n /** Called when a seeder throws. The error is re-thrown after this callback returns. */\n onError?: (seeder: SeederCtor, error: unknown) => void | Promise<void>;\n /** Called for each seeder before it runs. Return `true` to skip it entirely. */\n skip?: (seeder: SeederCtor) => boolean | Promise<boolean>;\n}\n\n/**\n * Topologically sorts the given seeders and all their transitive dependencies.\n * BFS walks from the roots to collect all nodes, then dependency edges are wired and\n * the graph is sorted so that every dependency precedes the seeders that depend on it.\n * Throws a descriptive error if a circular dependency is detected.\n */\nfunction topoSort(roots: SeederCtor[]): SeederCtor[] {\n const graph = new DepGraph<SeederCtor>();\n const byName = new Map<string, SeederCtor>();\n\n // Collect all nodes transitively via BFS and register them in the graph.\n const visited = new Set<SeederCtor>();\n const queue: SeederCtor[] = [...roots];\n\n while (queue.length > 0) {\n const node = queue.shift()!;\n\n if (visited.has(node)) {\n continue;\n }\n\n visited.add(node);\n graph.addNode(node.name, node);\n byName.set(node.name, node);\n\n for (const dep of (getSeederMeta(node)?.dependencies ?? []) as SeederCtor[]) {\n queue.push(dep);\n }\n }\n\n // Wire up the dependency edges.\n for (const node of visited) {\n for (const dep of (getSeederMeta(node)?.dependencies ?? []) as SeederCtor[]) {\n graph.addDependency(node.name, dep.name);\n }\n }\n\n try {\n return graph.overallOrder().map((name) => byName.get(name)!);\n } catch (err) {\n if (err && typeof err === 'object' && 'cyclePath' in err) {\n const path = (err as { cyclePath: string[] }).cyclePath.join(' → ');\n throw new Error(`Circular dependency detected among seeders: ${path}`);\n }\n\n throw err;\n }\n}\n\n/**\n * Runs the given seeders (and all their transitive dependencies) in dependency order.\n *\n * Each seeder is instantiated, its `run` method is called with the context derived\n * from `options`, and lifecycle hooks (`onBefore`, `onAfter`, `onError`) are called\n * around it. Errors are re-thrown after `onError` returns.\n *\n * @example\n * await runSeeders([PostSeeder], { dataSource })\n *\n * @example\n * // With lifecycle hooks and no console output\n * await runSeeders([PostSeeder], {\n * dataSource,\n * logging: false,\n * onAfter: (seeder, ms) => console.log(`${seeder.name} done in ${ms}ms`),\n * })\n */\nexport async function runSeeders(\n seeders: SeederCtor[],\n options: RunSeedersOptions = {},\n): Promise<void> {\n const { logging = true, onBefore, onAfter, onError, skip, ...context } = options;\n\n for (const SeederClass of topoSort(seeders)) {\n if (await skip?.(SeederClass)) {\n continue;\n }\n\n if (logging) {\n console.log(`[${SeederClass.name}] Starting...`);\n }\n\n await onBefore?.(SeederClass);\n\n const start = Date.now();\n\n try {\n await new SeederClass().run(context);\n } catch (err) {\n const durationMs = Date.now() - start;\n\n if (logging) {\n console.error(`[${SeederClass.name}] Failed after ${durationMs}ms`);\n }\n\n await onError?.(SeederClass, err);\n throw err;\n }\n\n const durationMs = Date.now() - start;\n\n if (logging) {\n console.log(`[${SeederClass.name}] Done in ${durationMs}ms`);\n }\n\n await onAfter?.(SeederClass, durationMs);\n }\n}\n"],"mappings":"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"}
package/dist/index.d.cts CHANGED
@@ -106,6 +106,19 @@ declare function Seed<TEntity = any>(factory: SeedFactory<unknown, TEntity>): Pr
106
106
  declare function Seed<TEntity = any>(factory: SeedFactory<unknown, TEntity>, options: SeedOptions): PropertyDecorator;
107
107
  //#endregion
108
108
  //#region src/seed/creator.d.ts
109
+ /**
110
+ * A map of property overrides for seeded entities.
111
+ * Each property can be either a static value or a {@link SeedFactory} that is called
112
+ * once per entity — enabling unique random values across each created instance.
113
+ *
114
+ * @example
115
+ * // All 10 bookings get a unique random price
116
+ * await seed(Booking).saveMany(10, {
117
+ * dataSource,
118
+ * values: { price: () => faker.number.float({ min: 10, max: 500 }) },
119
+ * })
120
+ */
121
+ type SeedValues<T extends EntityInstance> = { [K in keyof T]?: T[K] | SeedFactory<T[K], T> };
109
122
  /**
110
123
  * Options for {@link create} and {@link createMany} on the single-class form.
111
124
  * Extends {@link SeedContext} with a typed `values` override map.
@@ -120,12 +133,12 @@ interface CreateOptions<T extends EntityInstance> extends SeedContext {
120
133
  * const user = await dataSource.getRepository(User).findOneByOrFail({ name: 'Alice' })
121
134
  * const post = await seed(Post).create({ values: { author: user } })
122
135
  */
123
- values?: Partial<T>;
136
+ values?: SeedValues<T>;
124
137
  }
125
138
  /** Options for {@link createMany}. Extends {@link SeedContext} with a required instance count. */
126
139
  interface CreateManyOptions<T extends EntityInstance = EntityInstance> extends SeedContext {
127
140
  count: number;
128
- values?: Partial<T>;
141
+ values?: SeedValues<T>;
129
142
  }
130
143
  /**
131
144
  * Creates one entity instance in memory without persisting it.
@@ -161,7 +174,7 @@ interface SaveOptions<T extends EntityInstance = EntityInstance> extends SeedCon
161
174
  * const user = faker.helpers.arrayElement(users)
162
175
  * await seed(Booking).saveMany(10, { dataSource, values: { user } })
163
176
  */
164
- values?: Partial<T>;
177
+ values?: SeedValues<T>;
165
178
  }
166
179
  /** Options for {@link saveMany}. Extends {@link SaveOptions} with a required instance count. */
167
180
  interface SaveManyOptions<T extends EntityInstance = EntityInstance> extends SaveOptions<T> {
@@ -316,5 +329,5 @@ interface RunSeedersOptions extends SeedContext {
316
329
  */
317
330
  declare function runSeeders(seeders: SeederCtor[], options?: RunSeedersOptions): Promise<void>;
318
331
  //#endregion
319
- export { type CreateManyOptions, type CreateOptions, type EntityConstructor, type EntityInstance, type RunSeedersOptions, type SaveManyOptions, type SaveOptions, Seed, type SeedContext, type SeedEntry, type SeedFactory, type SeedOptions, Seeder, type SeederCtor, type SeederInterface, type SeederOptions, create, createMany, runSeeders, save, saveMany, seed };
332
+ export { type CreateManyOptions, type CreateOptions, type EntityConstructor, type EntityInstance, type RunSeedersOptions, type SaveManyOptions, type SaveOptions, Seed, type SeedContext, type SeedEntry, type SeedFactory, type SeedOptions, type SeedValues, Seeder, type SeederCtor, type SeederInterface, type SeederOptions, create, createMany, runSeeders, save, saveMany, seed };
320
333
  //# sourceMappingURL=index.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.cts","names":[],"sources":["../src/seed/registry.ts","../src/seed/decorator.ts","../src/seed/creator.ts","../src/seed/persist.ts","../src/seed/builder.ts","../src/seeder/decorator.ts","../src/seeder/runner.ts"],"mappings":"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"}
1
+ {"version":3,"file":"index.d.cts","names":[],"sources":["../src/seed/registry.ts","../src/seed/decorator.ts","../src/seed/creator.ts","../src/seed/persist.ts","../src/seed/builder.ts","../src/seeder/decorator.ts","../src/seeder/runner.ts"],"mappings":"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"}
package/dist/index.d.mts CHANGED
@@ -106,6 +106,19 @@ declare function Seed<TEntity = any>(factory: SeedFactory<unknown, TEntity>): Pr
106
106
  declare function Seed<TEntity = any>(factory: SeedFactory<unknown, TEntity>, options: SeedOptions): PropertyDecorator;
107
107
  //#endregion
108
108
  //#region src/seed/creator.d.ts
109
+ /**
110
+ * A map of property overrides for seeded entities.
111
+ * Each property can be either a static value or a {@link SeedFactory} that is called
112
+ * once per entity — enabling unique random values across each created instance.
113
+ *
114
+ * @example
115
+ * // All 10 bookings get a unique random price
116
+ * await seed(Booking).saveMany(10, {
117
+ * dataSource,
118
+ * values: { price: () => faker.number.float({ min: 10, max: 500 }) },
119
+ * })
120
+ */
121
+ type SeedValues<T extends EntityInstance> = { [K in keyof T]?: T[K] | SeedFactory<T[K], T> };
109
122
  /**
110
123
  * Options for {@link create} and {@link createMany} on the single-class form.
111
124
  * Extends {@link SeedContext} with a typed `values` override map.
@@ -120,12 +133,12 @@ interface CreateOptions<T extends EntityInstance> extends SeedContext {
120
133
  * const user = await dataSource.getRepository(User).findOneByOrFail({ name: 'Alice' })
121
134
  * const post = await seed(Post).create({ values: { author: user } })
122
135
  */
123
- values?: Partial<T>;
136
+ values?: SeedValues<T>;
124
137
  }
125
138
  /** Options for {@link createMany}. Extends {@link SeedContext} with a required instance count. */
126
139
  interface CreateManyOptions<T extends EntityInstance = EntityInstance> extends SeedContext {
127
140
  count: number;
128
- values?: Partial<T>;
141
+ values?: SeedValues<T>;
129
142
  }
130
143
  /**
131
144
  * Creates one entity instance in memory without persisting it.
@@ -161,7 +174,7 @@ interface SaveOptions<T extends EntityInstance = EntityInstance> extends SeedCon
161
174
  * const user = faker.helpers.arrayElement(users)
162
175
  * await seed(Booking).saveMany(10, { dataSource, values: { user } })
163
176
  */
164
- values?: Partial<T>;
177
+ values?: SeedValues<T>;
165
178
  }
166
179
  /** Options for {@link saveMany}. Extends {@link SaveOptions} with a required instance count. */
167
180
  interface SaveManyOptions<T extends EntityInstance = EntityInstance> extends SaveOptions<T> {
@@ -316,5 +329,5 @@ interface RunSeedersOptions extends SeedContext {
316
329
  */
317
330
  declare function runSeeders(seeders: SeederCtor[], options?: RunSeedersOptions): Promise<void>;
318
331
  //#endregion
319
- export { type CreateManyOptions, type CreateOptions, type EntityConstructor, type EntityInstance, type RunSeedersOptions, type SaveManyOptions, type SaveOptions, Seed, type SeedContext, type SeedEntry, type SeedFactory, type SeedOptions, Seeder, type SeederCtor, type SeederInterface, type SeederOptions, create, createMany, runSeeders, save, saveMany, seed };
332
+ export { type CreateManyOptions, type CreateOptions, type EntityConstructor, type EntityInstance, type RunSeedersOptions, type SaveManyOptions, type SaveOptions, Seed, type SeedContext, type SeedEntry, type SeedFactory, type SeedOptions, type SeedValues, Seeder, type SeederCtor, type SeederInterface, type SeederOptions, create, createMany, runSeeders, save, saveMany, seed };
320
333
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/seed/registry.ts","../src/seed/decorator.ts","../src/seed/creator.ts","../src/seed/persist.ts","../src/seed/builder.ts","../src/seeder/decorator.ts","../src/seeder/runner.ts"],"mappings":"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"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/seed/registry.ts","../src/seed/decorator.ts","../src/seed/creator.ts","../src/seed/persist.ts","../src/seed/builder.ts","../src/seeder/decorator.ts","../src/seeder/runner.ts"],"mappings":";;;;KAGY,cAAA;AAAZ;AAAA,KAGY,iBAAA,WAA4B,cAAA,GAAiB,cAAA,cAA4B,CAAA;;UAGpE,WAAA;EANS;AAG1B;;;;;;;;EAaE,UAAA,GAAa,UAAA;EAbyB;;;;;AAGxC;;;EAmBE,SAAA;AAAA;;;;;AAmBF;;;;;;;;;;;;KAAY,WAAA,gCACV,OAAA,EAAS,WAAA,EACT,IAAA,EAAM,OAAA,KACH,CAAA,GAAI,OAAA,CAAQ,CAAA;;UAGA,WAAA;EAJf;;;;EASA,KAAA;AAAA;AAAA,UAGe,SAAA;EACf,WAAA;;EAEA,OAAA,EAAS,WAAA;EACT,OAAA,EAAS,WAAA;AAAA;AAAA,KAGC,cAAA,oBAAkC,iBAAA,oBAChC,CAAA,GAAI,CAAA,CAAE,CAAA,UAAW,iBAAA,YAA6B,CAAA;AAAA,KAGhD,mBAAA,oBAAuC,iBAAA,oBACrC,CAAA,GAAI,CAAA,CAAE,CAAA,UAAW,iBAAA,YAA6B,CAAA;;;;;AAtE5D;;;;;AAGA;;;iBCOgB,IAAA,CAAA,GAAQ,iBAAA;;;;;;;;;;;ADJxB;iBCgBgB,IAAA,CAAK,OAAA,EAAS,WAAA,GAAc,iBAAA;;;;;;;;ADsB5C;;;;;;;;;iBCLgB,IAAA,eAAA,CAAoB,OAAA,EAAS,WAAA,UAAqB,OAAA,IAAW,iBAAA;;iBAE7D,IAAA,eAAA,CACd,OAAA,EAAS,WAAA,UAAqB,OAAA,GAC9B,OAAA,EAAS,WAAA,GACR,iBAAA;;;;;AD5CH;;;;;AAGA;;;;;KEiBY,UAAA,WAAqB,cAAA,kBACnB,CAAA,IAAK,CAAA,CAAE,CAAA,IAAK,WAAA,CAAY,CAAA,CAAE,CAAA,GAAI,CAAA;;;;;UAO3B,aAAA,WAAwB,cAAA,UAAwB,WAAA;EFzBqB;AAGtF;;;;;;;;EEgCE,MAAA,GAAS,UAAA,CAAW,CAAA;AAAA;;UAIL,iBAAA,WAA4B,cAAA,GAAiB,cAAA,UAAwB,WAAA;EACpF,KAAA;EACA,MAAA,GAAS,UAAA,CAAW,CAAA;AAAA;;;;;;;;iBAuJA,MAAA,WAAiB,cAAA,CAAA,CACrC,WAAA,EAAa,iBAAA,CAAkB,CAAA,GAC/B,OAAA,GAAU,aAAA,CAAc,CAAA,IACvB,OAAA,CAAQ,CAAA;AAAA,iBACW,MAAA,oBAA0B,iBAAA,GAAA,CAC9C,aAAA,MAAmB,CAAA,GACnB,OAAA,GAAU,WAAA,GACT,OAAA,CAAQ,cAAA,CAAe,CAAA;;;;;;;AFxJ1B;iBEsLsB,UAAA,WAAqB,cAAA,CAAA,CACzC,WAAA,EAAa,iBAAA,CAAkB,CAAA,GAC/B,OAAA,EAAS,iBAAA,CAAkB,CAAA,IAC1B,OAAA,CAAQ,CAAA;AAAA,iBACW,UAAA,oBAA8B,iBAAA,GAAA,CAClD,aAAA,MAAmB,CAAA,GACnB,OAAA,EAAS,iBAAA,GACR,OAAA,CAAQ,mBAAA,CAAoB,CAAA;;;AF/O/B;AAAA,UGSiB,WAAA,WAAsB,cAAA,GAAiB,cAAA,UAAwB,WAAA;EAC9E,UAAA,EAAY,UAAA;EHVY;;AAG1B;;;;;;;;;EGmBE,MAAA,GAAS,UAAA,CAAW,CAAA;AAAA;;UAIL,eAAA,WAA0B,cAAA,GAAiB,cAAA,UAAwB,WAAA,CAAY,CAAA;EAC9F,KAAA;AAAA;;;;iBAqFoB,IAAA,WAAe,cAAA,CAAA,CACnC,WAAA,EAAa,iBAAA,CAAkB,CAAA,GAC/B,OAAA,EAAS,WAAA,CAAY,CAAA,IACpB,OAAA,CAAQ,CAAA;;;;;iBAKW,IAAA,oBAAwB,iBAAA,GAAA,CAC5C,aAAA,MAAmB,CAAA,GACnB,OAAA,EAAS,WAAA,GACR,OAAA,CAAQ,cAAA,CAAe,CAAA;;;;;iBA2BJ,QAAA,WAAmB,cAAA,CAAA,CACvC,WAAA,EAAa,iBAAA,CAAkB,CAAA,GAC/B,OAAA,EAAS,eAAA,CAAgB,CAAA,IACxB,OAAA,CAAQ,CAAA;;;;;iBAKW,QAAA,oBAA4B,iBAAA,GAAA,CAChD,aAAA,MAAmB,CAAA,GACnB,OAAA,EAAS,eAAA,GACR,OAAA,CAAQ,mBAAA,CAAoB,CAAA;;;;UCrJrB,UAAA,WAAqB,cAAA;EJZL;EIcxB,MAAA,CAAO,OAAA,GAAU,aAAA,CAAc,CAAA,IAAK,OAAA,CAAQ,CAAA;EJXlC;EIaV,IAAA,CAAK,OAAA,EAAS,WAAA,CAAY,CAAA,IAAK,OAAA,CAAQ,CAAA;EJbZ;EIe3B,UAAA,CAAW,KAAA,UAAe,OAAA,GAAU,aAAA,CAAc,CAAA,IAAK,OAAA,CAAQ,CAAA;EJfR;EIiBvD,QAAA,CAAS,KAAA,UAAe,OAAA,EAAS,WAAA,CAAY,CAAA,IAAK,OAAA,CAAQ,CAAA;AAAA;;;;;;UAQlD,SAAA,oBAA6B,iBAAA;EJzB+C;EI2BpF,MAAA,CAAO,OAAA,GAAU,WAAA,GAAc,OAAA,CAAQ,cAAA,CAAe,CAAA;EJxB5B;EI0B1B,IAAA,CAAK,OAAA,EAAS,WAAA,GAAc,OAAA,CAAQ,cAAA,CAAe,CAAA;EJhB5B;EIkBvB,UAAA,CAAW,KAAA,UAAe,OAAA,GAAU,WAAA,GAAc,OAAA,CAAQ,mBAAA,CAAoB,CAAA;EJlBjE;EIoBb,QAAA,CAAS,KAAA,UAAe,OAAA,EAAS,WAAA,GAAc,OAAA,CAAQ,mBAAA,CAAoB,CAAA;AAAA;;AJQ7E;;;;;;;;;;;;;;;;;;;;;iBIiBgB,IAAA,WAAe,cAAA,CAAA,CAAgB,WAAA,EAAa,iBAAA,CAAkB,CAAA,IAAK,UAAA,CAAW,CAAA;AAAA,iBAC9E,IAAA,oBAAwB,iBAAA,GAAA,CAAqB,aAAA,MAAmB,CAAA,IAAK,SAAA,CAAU,CAAA;;;;;AJ9D/F;;;;;UKOiB,eAAA;EACf,GAAA,CAAI,OAAA,EAAS,WAAA,GAAc,OAAA;AAAA;;UAIZ,aAAA;ELToE;;;;;EKenF,YAAA,cAA0B,eAAA;AAAA;;;ALZ5B;;;;;;;;;AAsCA;;;iBKTgB,MAAA,CAAO,OAAA,GAAS,aAAA,GAAqB,cAAA;;;;KChCzC,UAAA,aAAuB,eAAA;;UAGlB,iBAAA,SAA0B,WAAA;ENNjB;;AAG1B;;;;EMUE,OAAA;ENVmF;EMYnF,QAAA,IAAY,MAAA,EAAQ,UAAA,YAAsB,OAAA;ENZ0C;EMcpF,OAAA,IAAW,MAAA,EAAQ,UAAA,EAAY,UAAA,oBAA8B,OAAA;ENdvB;EMgBtC,OAAA,IAAW,MAAA,EAAQ,UAAA,EAAY,KAAA,qBAA0B,OAAA;ENhB0B;EMkBnF,IAAA,IAAQ,MAAA,EAAQ,UAAA,eAAyB,OAAA;AAAA;ANf3C;;;;;;;;;AAsCA;;;;;;;;;AAtCA,iBMqFsB,UAAA,CACpB,OAAA,EAAS,UAAA,IACT,OAAA,GAAS,iBAAA,GACR,OAAA"}
package/dist/index.mjs CHANGED
@@ -41,6 +41,18 @@ function Seed(factoryOrOptions, options) {
41
41
  function getAncestors(context) {
42
42
  return context._ancestors ?? /* @__PURE__ */ new Set();
43
43
  }
44
+ /**
45
+ * Applies a {@link SeedValues} map to an instance.
46
+ * Factory entries are called once per instance so each entity can get unique values.
47
+ */
48
+ async function applyValues(instance, values, context) {
49
+ const record = instance;
50
+ for (const key of Object.keys(values)) {
51
+ const value = values[key];
52
+ if (typeof value === "function") record[key] = await value(context, instance);
53
+ else record[key] = value;
54
+ }
55
+ }
44
56
  /** Returns a new context with `cls` added to the ancestor set, used to detect circular relation chains. */
45
57
  function withAncestor(context, cls) {
46
58
  const ancestors = getAncestors(context);
@@ -115,7 +127,7 @@ async function create(classOrClasses, options = {}) {
115
127
  }
116
128
  const { values, ...context } = options;
117
129
  const instance = await createOne(classOrClasses, context);
118
- if (values) Object.assign(instance, values);
130
+ if (values) await applyValues(instance, values, context);
119
131
  return instance;
120
132
  }
121
133
  async function createMany(classOrClasses, { count, values, ...context }) {
@@ -127,7 +139,7 @@ async function createMany(classOrClasses, { count, values, ...context }) {
127
139
  return await Promise.all(classOrClasses.map((cls) => Promise.all(Array.from({ length: count }, () => createOne(cls, effectiveContext)))));
128
140
  }
129
141
  const instances = await Promise.all(Array.from({ length: count }, () => createOne(classOrClasses, context)));
130
- if (values) instances.forEach((e) => Object.assign(e, values));
142
+ if (values) await Promise.all(instances.map((instance) => applyValues(instance, values, context)));
131
143
  return instances;
132
144
  }
133
145
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["registry"],"sources":["../src/seed/registry.ts","../src/seed/decorator.ts","../src/seed/creator.ts","../src/seed/persist.ts","../src/seed/builder.ts","../src/seeder/registry.ts","../src/seeder/decorator.ts","../src/seeder/runner.ts"],"sourcesContent":["import type { DataSource } from 'typeorm';\n\n/** An entity instance — any class-based object managed by TypeORM. */\nexport type EntityInstance = object;\n\n/** A constructor that produces an entity instance. */\nexport type EntityConstructor<T extends EntityInstance = EntityInstance> = new () => T;\n\n/** Context passed through a seed operation. Available inside factory callbacks and `SeederInterface.run`. */\nexport interface SeedContext {\n /**\n * The TypeORM DataSource. Automatically set by `save`/`saveMany` calls.\n * Also available in factory callbacks — useful for looking up existing\n * entities instead of creating new ones:\n *\n * @example\n * @Seed(async ({ dataSource }) => dataSource.getRepository(Role).findOneByOrFail({ name: 'admin' }))\n * role!: Role\n */\n dataSource?: DataSource;\n /**\n * Set to `false` to skip automatic relation seeding. Scalar and embedded\n * properties are still seeded; only relation properties decorated with a\n * bare `@Seed()` are skipped. Useful when you want to create flat entities\n * and wire relations yourself.\n *\n * @default true\n */\n relations?: boolean;\n}\n\n/**\n * Factory callback passed to `@Seed`. Receives the seed context and the partially built entity.\n *\n * Properties are seeded sequentially in declaration order, so any property declared above the\n * current one is already set on `self` and can be read to derive the current value.\n *\n * Annotate `self` with the entity class to get full type inference — TypeScript infers\n * `TEntity` from the annotation, so no cast is needed:\n *\n * @example\n * @Seed(() => faker.date.past())\n * beginDate!: Date\n *\n * @Seed((_, self: MyEntity) => faker.date.future({ refDate: self.beginDate }))\n * endDate!: Date\n */\nexport type SeedFactory<T = unknown, TEntity = any> = (\n context: SeedContext,\n self: TEntity,\n) => T | Promise<T>;\n\n/** Options for the `@Seed` decorator. */\nexport interface SeedOptions {\n /**\n * Number of related entities to create. Only meaningful on one-to-many and\n * many-to-many relation properties. Ignored on scalar and single-entity relations.\n */\n count?: number;\n}\n\nexport interface SeedEntry {\n propertyKey: string | symbol;\n /** Undefined when @Seed is used without a factory (i.e. bare relation seed). */\n factory: SeedFactory | undefined;\n options: SeedOptions;\n}\n\nexport type MapToInstances<T extends readonly EntityConstructor[]> = {\n [K in keyof T]: T[K] extends EntityConstructor<infer I> ? I : never;\n};\n\nexport type MapToInstanceArrays<T extends readonly EntityConstructor[]> = {\n [K in keyof T]: T[K] extends EntityConstructor<infer I> ? I[] : never;\n};\n\n// Keyed by the entity class constructor.\nconst registry = new Map<Function, SeedEntry[]>();\n\n/** Registers a seed entry for the given class constructor. Called internally by the `@Seed` decorator. */\nexport function registerSeed(target: Function, entry: SeedEntry): void {\n const entries = registry.get(target) ?? [];\n\n entries.push(entry);\n registry.set(target, entries);\n}\n\n/**\n * Returns all seed entries for the given class, including those inherited from\n * parent classes. Parent entries come first, preserving declaration order.\n */\nexport function getSeeds(target: Function): SeedEntry[] {\n const entries: SeedEntry[] = [];\n let current: Function = target;\n\n while (current && current !== Function.prototype) {\n const own = registry.get(current);\n\n if (own) {\n entries.unshift(...own);\n }\n\n current = Object.getPrototypeOf(current) as Function;\n }\n\n return entries;\n}\n","import { registerSeed } from './registry.js';\nimport type { SeedFactory, SeedOptions } from './registry.js';\n\n/**\n * Marks a relation property for auto-seeding.\n *\n * The related entity class is inferred from TypeORM metadata. One instance is created\n * and recursively seeded (including its own `@Seed` properties).\n *\n * Circular back-references are broken automatically: if the related class is already\n * being seeded higher up in the same call chain, the property is left `undefined`.\n * TypeORM treats `undefined` as \"don't touch this column\" rather than setting it to null.\n */\nexport function Seed(): PropertyDecorator;\n/**\n * Marks a relation property for auto-seeding with options.\n *\n * Use `count` on one-to-many and many-to-many properties to control how many\n * related entities are created. Ignored for one-to-one and many-to-one.\n *\n * @example\n * @Seed({ count: 3 })\n * @OneToMany(() => Book, (b) => b.author)\n * books!: Book[]\n */\nexport function Seed(options: SeedOptions): PropertyDecorator;\n/**\n * Marks a property with a factory callback.\n *\n * The factory receives the current {@link SeedContext} and can return any value,\n * including a `Promise`. Use this for scalar properties or when you need full\n * control over how a related entity is resolved.\n *\n * @example\n * @Seed(() => faker.internet.email())\n * email!: string\n *\n * @example\n * // Look up an existing entity instead of creating a new one\n * @Seed(async ({ dataSource }) => dataSource.getRepository(Role).findOneByOrFail({ name: 'admin' }))\n * role!: Role\n */\nexport function Seed<TEntity = any>(factory: SeedFactory<unknown, TEntity>): PropertyDecorator;\n/** Marks a property with a factory callback and additional options. */\nexport function Seed<TEntity = any>(\n factory: SeedFactory<unknown, TEntity>,\n options: SeedOptions,\n): PropertyDecorator;\nexport function Seed(\n factoryOrOptions?: SeedFactory | SeedOptions,\n options?: SeedOptions,\n): PropertyDecorator {\n const factory = typeof factoryOrOptions === 'function' ? factoryOrOptions : undefined;\n const opts: SeedOptions =\n (typeof factoryOrOptions === 'object' ? factoryOrOptions : options) ?? {};\n\n return (target, propertyKey) => {\n registerSeed(target.constructor as Function, { propertyKey, factory, options: opts });\n };\n}\n","import { getMetadataArgsStorage } from 'typeorm';\nimport type {\n EntityConstructor,\n EntityInstance,\n MapToInstanceArrays,\n MapToInstances,\n SeedContext,\n} from './registry.js';\nimport { getSeeds } from './registry.js';\n\n/**\n * Options for {@link create} and {@link createMany} on the single-class form.\n * Extends {@link SeedContext} with a typed `values` override map.\n */\nexport interface CreateOptions<T extends EntityInstance> extends SeedContext {\n /**\n * Property values to apply after all `@Seed` factories have run.\n * Wins unconditionally — factories still execute but their output is overwritten.\n * Also works for properties that have no `@Seed` decorator.\n *\n * @example\n * const user = await dataSource.getRepository(User).findOneByOrFail({ name: 'Alice' })\n * const post = await seed(Post).create({ values: { author: user } })\n */\n values?: Partial<T>;\n}\n\n/** Options for {@link createMany}. Extends {@link SeedContext} with a required instance count. */\nexport interface CreateManyOptions<T extends EntityInstance = EntityInstance> extends SeedContext {\n count: number;\n values?: Partial<T>;\n}\n\n// Internal extension of SeedContext — never exposed in the public API.\ninterface InternalContext extends SeedContext {\n _ancestors: Set<Function>;\n}\n\n/** Extracts the ancestor set from an internal context, returning an empty set for external callers. */\nfunction getAncestors(context: SeedContext): Set<Function> {\n return (context as InternalContext)._ancestors ?? new Set();\n}\n\n/** Returns a new context with `cls` added to the ancestor set, used to detect circular relation chains. */\nfunction withAncestor(context: SeedContext, cls: Function): InternalContext {\n const ancestors = getAncestors(context);\n\n return { ...context, _ancestors: new Set([...ancestors, cls]) };\n}\n\n/** Walks the prototype chain and returns all classes from `target` up to (but not including) `Function.prototype`. */\nfunction getClassHierarchy(target: Function): Function[] {\n const hierarchy: Function[] = [];\n let current: Function = target;\n\n while (current && current !== Function.prototype) {\n hierarchy.push(current);\n current = Object.getPrototypeOf(current) as Function;\n }\n\n return hierarchy;\n}\n\n/**\n * Creates one fully populated instance of `EntityClass` in memory.\n *\n * Runs in three steps:\n * 1. Factory-decorated properties (`@Seed(factory)`) — run first, in declaration order.\n * 2. Embedded types (`@Embedded`) — auto-seeded if the embedded class has any `@Seed` entries.\n * 3. Bare relation decorators (`@Seed()` without a factory) — skipped when `relations` is `false`,\n * and also skipped for any related class already present in the ancestor chain (circular guard).\n */\nasync function createOne<T extends EntityInstance>(\n EntityClass: EntityConstructor<T>,\n context: SeedContext,\n): Promise<T> {\n const instance = new EntityClass();\n const ancestors = getAncestors(context);\n const childContext = withAncestor(context, EntityClass);\n const storage = getMetadataArgsStorage();\n const relations = storage.filterRelations(getClassHierarchy(EntityClass));\n const seededProperties = new Set<string | symbol>();\n const record = instance as Record<string | symbol, unknown>;\n\n // Step 1: Run @Seed entries that have an explicit factory.\n for (const { propertyKey, factory } of getSeeds(EntityClass)) {\n if (!factory) {\n continue;\n }\n\n record[propertyKey] = await factory(context, instance);\n seededProperties.add(propertyKey);\n }\n\n // Step 2: Auto-seed TypeORM embedded properties not already covered by Step 1.\n for (const embedded of storage.filterEmbeddeds(EntityClass)) {\n if (seededProperties.has(embedded.propertyName)) {\n continue;\n }\n\n const EmbeddedClass = embedded.type() as EntityConstructor;\n\n if (getSeeds(EmbeddedClass).length > 0) {\n record[embedded.propertyName] = await createOne(EmbeddedClass, context);\n seededProperties.add(embedded.propertyName);\n }\n }\n\n // Step 3: Auto-seed @Seed entries without a factory (relation seeds).\n // Uses the ancestor guard to cut circular chains: if the related class is\n // already being seeded higher up in this call chain, the property is left\n // undefined rather than triggering infinite recursion.\n // Skipped entirely when context.relations === false.\n if (context.relations === false) {\n return instance;\n }\n\n for (const { propertyKey, factory, options } of getSeeds(EntityClass)) {\n if (factory || seededProperties.has(propertyKey)) {\n continue;\n }\n\n const relation = relations.find((r) => r.propertyName === String(propertyKey));\n\n if (!relation || typeof relation.type !== 'function') {\n continue;\n }\n\n const RelatedClass = (relation.type as () => Function)() as EntityConstructor;\n\n if (ancestors.has(RelatedClass)) {\n continue;\n }\n\n const isArray =\n relation.relationType === 'one-to-many' || relation.relationType === 'many-to-many';\n\n if (isArray) {\n record[propertyKey] = await createMany(RelatedClass, {\n count: options.count ?? 1,\n ...childContext,\n });\n } else {\n record[propertyKey] = await createOne(RelatedClass, childContext);\n }\n\n seededProperties.add(propertyKey);\n }\n\n return instance;\n}\n\n/**\n * Creates one entity instance in memory without persisting it.\n *\n * When passed an array of classes, relation seeding is disabled by default\n * (pass `relations: true` in the context to override). Returns a tuple of\n * instances in the same order as the input array.\n */\nexport async function create<T extends EntityInstance>(\n EntityClass: EntityConstructor<T>,\n options?: CreateOptions<T>,\n): Promise<T>;\nexport async function create<T extends readonly EntityConstructor[]>(\n EntityClasses: [...T],\n context?: SeedContext,\n): Promise<MapToInstances<T>>;\nexport async function create<T extends EntityInstance>(\n classOrClasses: EntityConstructor<T> | readonly EntityConstructor[],\n options: CreateOptions<T> = {},\n): Promise<T | EntityInstance[]> {\n if (Array.isArray(classOrClasses)) {\n const effectiveContext: SeedContext = { relations: false, ...options };\n\n return (await Promise.all(\n (classOrClasses as EntityConstructor[]).map((cls) => createOne(cls, effectiveContext)),\n )) as EntityInstance[];\n }\n\n const { values, ...context } = options as CreateOptions<T>;\n const instance = await createOne(classOrClasses as EntityConstructor<T>, context);\n\n if (values) {\n Object.assign(instance, values);\n }\n\n return instance;\n}\n\n/**\n * Creates multiple entity instances in memory without persisting them.\n *\n * When passed an array of classes, returns a tuple of arrays — one per class — each\n * containing `count` instances. Relation seeding is disabled by default for the\n * array variant; pass `relations: true` in the options to override.\n */\nexport async function createMany<T extends EntityInstance>(\n EntityClass: EntityConstructor<T>,\n options: CreateManyOptions<T>,\n): Promise<T[]>;\nexport async function createMany<T extends readonly EntityConstructor[]>(\n EntityClasses: [...T],\n options: CreateManyOptions,\n): Promise<MapToInstanceArrays<T>>;\nexport async function createMany<T extends EntityInstance>(\n classOrClasses: EntityConstructor<T> | readonly EntityConstructor[],\n { count, values, ...context }: CreateManyOptions<T>,\n): Promise<T[] | EntityInstance[][]> {\n if (Array.isArray(classOrClasses)) {\n const effectiveContext: SeedContext = { relations: false, ...context };\n\n return (await Promise.all(\n (classOrClasses as EntityConstructor[]).map((cls) =>\n Promise.all(Array.from({ length: count }, () => createOne(cls, effectiveContext))),\n ),\n )) as EntityInstance[][];\n }\n\n const instances = await Promise.all(\n Array.from({ length: count }, () => createOne(classOrClasses as EntityConstructor<T>, context)),\n );\n\n if (values) {\n instances.forEach((e) => Object.assign(e, values));\n }\n\n return instances;\n}\n","import { type DataSource } from 'typeorm';\nimport { createMany } from './creator.js';\nimport type {\n EntityConstructor,\n EntityInstance,\n MapToInstanceArrays,\n MapToInstances,\n SeedContext,\n} from './registry.js';\n\n/** Options for {@link save}. Extends {@link SeedContext} with a required DataSource. */\nexport interface SaveOptions<T extends EntityInstance = EntityInstance> extends SeedContext {\n dataSource: DataSource;\n /**\n * Property values to apply to each entity after seeding and before persisting.\n * Wins unconditionally over `@Seed` factory output — the factory still runs,\n * but its result is overwritten. Also works for properties that have no `@Seed`\n * decorator at all.\n *\n * @example\n * const users = await dataSource.getRepository(User).find()\n * const user = faker.helpers.arrayElement(users)\n * await seed(Booking).saveMany(10, { dataSource, values: { user } })\n */\n values?: Partial<T>;\n}\n\n/** Options for {@link saveMany}. Extends {@link SaveOptions} with a required instance count. */\nexport interface SaveManyOptions<T extends EntityInstance = EntityInstance> extends SaveOptions<T> {\n count: number;\n}\n\ntype RelationMetadata = DataSource extends { getMetadata(...args: never[]): infer M }\n ? M extends { relations: Array<infer R> }\n ? R\n : never\n : never;\n\ninterface CascadeState {\n relation: RelationMetadata;\n original: boolean;\n}\n\n/**\n * Walks an entity object graph and collects every unique entity class encountered.\n * Used to discover all entity classes that need cascade-insert temporarily enabled\n * before saving so that the full in-memory graph is persisted in one shot.\n */\nfunction collectEntityClasses(entity: EntityInstance, visited = new Set<Function>()): Function[] {\n const EntityClass = entity.constructor as Function;\n\n if (visited.has(EntityClass)) {\n return [];\n }\n\n visited.add(EntityClass);\n\n const classes: Function[] = [EntityClass];\n\n for (const value of Object.values(entity)) {\n if (Array.isArray(value)) {\n for (const item of value) {\n if (item && typeof item === 'object' && item.constructor !== Object) {\n classes.push(...collectEntityClasses(item, visited));\n }\n }\n } else if (value && typeof value === 'object' && value.constructor !== Object) {\n classes.push(...collectEntityClasses(value as EntityInstance, visited));\n }\n }\n\n return classes;\n}\n\n/**\n * Temporarily enables `isCascadeInsert` on every TypeORM relation for the given class.\n * Returns the previous flag values so they can be restored after saving.\n *\n * This is necessary because the seeder builds the full object graph in memory before\n * calling `save()`. Without cascade inserts, TypeORM would only persist the root entity\n * and ignore any nested relations that weren't already configured with `cascade: true`.\n *\n * Classes not registered as TypeORM entities (e.g. embedded value objects) are silently skipped.\n */\nfunction enableCascadeInsert(EntityClass: Function, dataSource: DataSource): CascadeState[] {\n const states: CascadeState[] = [];\n\n try {\n const relations = dataSource.getMetadata(EntityClass).relations;\n\n for (const relation of relations) {\n states.push({ relation, original: relation.isCascadeInsert });\n relation.isCascadeInsert = true;\n }\n } catch {\n // Class is not registered as an entity with this DataSource (e.g. embedded class).\n }\n\n return states;\n}\n\n/**\n * Restores `isCascadeInsert` flags to their original values.\n * Always called in a `finally` block to guarantee cleanup even when saving throws.\n */\nfunction restoreCascade(states: CascadeState[]): void {\n for (const { relation, original } of states) {\n relation.isCascadeInsert = original;\n }\n}\n\n/**\n * Creates and persists a seed entity and all its seeded relations.\n */\nexport async function save<T extends EntityInstance>(\n EntityClass: EntityConstructor<T>,\n options: SaveOptions<T>,\n): Promise<T>;\n/**\n * Creates and persists one instance of each entity class in the array.\n * Relation seeding is disabled by default; pass `relations: true` to override.\n */\nexport async function save<T extends readonly EntityConstructor[]>(\n EntityClasses: [...T],\n options: SaveOptions,\n): Promise<MapToInstances<T>>;\nexport async function save<T extends EntityInstance>(\n classOrClasses: EntityConstructor<T> | readonly EntityConstructor[],\n options: SaveOptions<T>,\n): Promise<T | EntityInstance[]> {\n if (Array.isArray(classOrClasses)) {\n const effectiveOptions = { relations: false, ...options, count: 1 };\n\n return (await Promise.all(\n (classOrClasses as EntityConstructor[]).map((cls) =>\n saveBatch(cls, effectiveOptions).then(([entity]) => entity!),\n ),\n )) as EntityInstance[];\n }\n\n const [entity] = await saveBatch(classOrClasses as EntityConstructor<T>, {\n ...options,\n count: 1,\n });\n\n return entity!;\n}\n\n/**\n * Creates and persists multiple seed entities of the same class.\n * Applies the same logic as {@link save} for each entity.\n */\nexport async function saveMany<T extends EntityInstance>(\n EntityClass: EntityConstructor<T>,\n options: SaveManyOptions<T>,\n): Promise<T[]>;\n/**\n * Creates and persists multiple instances of each entity class in the array.\n * Relation seeding is disabled by default; pass `relations: true` to override.\n */\nexport async function saveMany<T extends readonly EntityConstructor[]>(\n EntityClasses: [...T],\n options: SaveManyOptions,\n): Promise<MapToInstanceArrays<T>>;\nexport async function saveMany<T extends EntityInstance>(\n classOrClasses: EntityConstructor<T> | readonly EntityConstructor[],\n options: SaveManyOptions<T>,\n): Promise<T[] | EntityInstance[][]> {\n if (Array.isArray(classOrClasses)) {\n const effectiveOptions = { relations: false, ...options };\n\n return (await Promise.all(\n (classOrClasses as EntityConstructor[]).map((cls) => saveBatch(cls, effectiveOptions)),\n )) as EntityInstance[][];\n }\n\n return await saveBatch(classOrClasses as EntityConstructor<T>, options);\n}\n\n/**\n * Creates and persists `count` instances of a single entity class in one batched\n * `repository.save()` call. Batching is intentional — it is more efficient than\n * saving each instance individually, as TypeORM can consolidate the inserts.\n *\n * Enables cascade inserts on every entity class in the object graph before saving,\n * then restores the original flags — regardless of whether the save succeeds or fails.\n */\nasync function saveBatch<T extends EntityInstance>(\n EntityClass: EntityConstructor<T>,\n options: SaveManyOptions<T>,\n): Promise<T[]> {\n const { count, dataSource } = options;\n\n if (count === 0) {\n return [];\n }\n\n const entities = await createMany(EntityClass, options);\n\n const visited = new Set<Function>();\n const states = entities\n .flatMap((entity) => collectEntityClasses(entity, visited))\n .flatMap((cls) => enableCascadeInsert(cls, dataSource));\n\n try {\n return (await dataSource.getRepository(EntityClass).save(entities)) as T[];\n } finally {\n restoreCascade(states);\n }\n}\n","import type { CreateOptions } from './creator.js';\nimport { create, createMany } from './creator.js';\nimport type { SaveManyOptions, SaveOptions } from './persist.js';\nimport { save, saveMany } from './persist.js';\nimport type {\n EntityConstructor,\n EntityInstance,\n MapToInstanceArrays,\n MapToInstances,\n SeedContext,\n} from './registry.js';\n\nexport type { CreateOptions } from './creator.js';\n\n/** Seed builder for a single entity class. Returned by {@link seed} when passed one class. */\ninterface SingleSeed<T extends EntityInstance> {\n /** Creates a single instance in memory without persisting. */\n create(context?: CreateOptions<T>): Promise<T>;\n /** Creates and persists a single instance. */\n save(options: SaveOptions<T>): Promise<T>;\n /** Creates multiple instances in memory without persisting. */\n createMany(count: number, context?: CreateOptions<T>): Promise<T[]>;\n /** Creates and persists multiple instances. */\n saveMany(count: number, options: SaveOptions<T>): Promise<T[]>;\n}\n\n/**\n * Seed builder for multiple entity classes. Returned by {@link seed} when passed an array.\n * Each method returns a tuple of instances in the same order as the input array.\n * Relation seeding is disabled by default; pass `relations: true` in the context to enable it.\n */\ninterface MultiSeed<T extends readonly EntityConstructor[]> {\n /** Creates one instance of each class in memory without persisting. */\n create(context?: SeedContext): Promise<MapToInstances<T>>;\n /** Creates and persists one instance of each class. */\n save(options: SaveOptions): Promise<MapToInstances<T>>;\n /** Creates `count` instances of each class in memory without persisting. */\n createMany(count: number, context?: SeedContext): Promise<MapToInstanceArrays<T>>;\n /** Creates and persists `count` instances of each class. */\n saveMany(count: number, options: SaveOptions): Promise<MapToInstanceArrays<T>>;\n}\n\n/**\n * Entry point for creating and persisting seed data.\n *\n * Pass a single entity class to get a {@link SingleSeed} builder, or an array of classes\n * to get a {@link MultiSeed} builder that operates on all of them at once.\n *\n * @example\n * // Create one Author in memory (no DB)\n * const author = await seed(Author).create()\n *\n * @example\n * // Persist one Author with all its seeded relations\n * const author = await seed(Author).save({ dataSource })\n *\n * @example\n * // Persist 10 Authors\n * const authors = await seed(Author).saveMany(10, { dataSource })\n *\n * @example\n * // Create multiple entity classes at once (relations disabled by default)\n * const [user, post] = await seed([User, Post]).create()\n */\nexport function seed<T extends EntityInstance>(EntityClass: EntityConstructor<T>): SingleSeed<T>;\nexport function seed<T extends readonly EntityConstructor[]>(EntityClasses: [...T]): MultiSeed<T>;\nexport function seed<T extends EntityInstance>(\n classOrClasses: EntityConstructor<T> | readonly EntityConstructor[],\n): SingleSeed<T> | MultiSeed<readonly EntityConstructor[]> {\n if (Array.isArray(classOrClasses)) {\n const classes = classOrClasses as readonly EntityConstructor[];\n\n return {\n create: (context?: SeedContext) =>\n create(classes as [...typeof classes], context) as Promise<MapToInstances<typeof classes>>,\n save: (options: SaveOptions) =>\n save(classes as [...typeof classes], options) as Promise<MapToInstances<typeof classes>>,\n createMany: (count: number, context?: SeedContext) =>\n createMany(classes as [...typeof classes], { count, ...context }) as Promise<\n MapToInstanceArrays<typeof classes>\n >,\n saveMany: (count: number, options: SaveOptions) =>\n saveMany(\n classes as [...typeof classes],\n { count, ...options } as SaveManyOptions,\n ) as Promise<MapToInstanceArrays<typeof classes>>,\n };\n }\n\n const EntityClass = classOrClasses as EntityConstructor<T>;\n\n return {\n create: (options?: CreateOptions<T>) => create(EntityClass, options),\n save: (options: SaveOptions<T>) => save(EntityClass, options),\n createMany: (count: number, options?: CreateOptions<T>) =>\n createMany(EntityClass, { count, ...options }),\n saveMany: (count: number, options: SaveOptions<T>) =>\n saveMany(EntityClass, { count, ...options }),\n };\n}\n","interface SeederMeta {\n dependencies: Function[];\n}\n\nconst registry = new WeakMap<Function, SeederMeta>();\n\n/** Registers seeder metadata for the given class constructor. Called internally by the `@Seeder` decorator. */\nexport function registerSeeder(target: Function, meta: SeederMeta): void {\n registry.set(target, meta);\n}\n\n/** Returns the metadata registered for the given seeder class, or `undefined` if not registered. */\nexport function getSeederMeta(target: Function): SeederMeta | undefined {\n return registry.get(target);\n}\n","import { registerSeeder } from './registry.js';\nimport type { SeedContext } from '../seed/registry.js';\n\n/**\n * Interface that seeder classes must implement.\n *\n * The `run` method receives the seed context (which includes the DataSource when\n * called via `runSeeders`) and performs the seeding logic — typically by calling\n * `seed().save()` or other seeding utilities.\n */\nexport interface SeederInterface {\n run(context: SeedContext): Promise<void>;\n}\n\n/** Configuration options for the {@link Seeder} decorator. */\nexport interface SeederOptions {\n /**\n * Seeder classes that must complete before this one runs.\n * Resolved transitively — dependencies of dependencies are included automatically.\n * {@link runSeeders} topologically sorts the full set and detects circular dependencies.\n */\n dependencies?: (new () => SeederInterface)[];\n}\n\n/**\n * Marks a class as a seeder and registers its dependency metadata.\n *\n * Classes decorated with `@Seeder` can be passed to {@link runSeeders}, which resolves\n * all transitive dependencies, sorts them topologically, and executes them in order.\n *\n * @example\n * @Seeder({ dependencies: [UserSeeder] })\n * class PostSeeder implements SeederInterface {\n * async run(ctx: SeedContext) {\n * await seed(Post).saveMany(50, ctx)\n * }\n * }\n */\nexport function Seeder(options: SeederOptions = {}): ClassDecorator {\n return (target) => {\n registerSeeder(target, { dependencies: options.dependencies ?? [] });\n };\n}\n","import { DepGraph } from 'dependency-graph';\nimport { getSeederMeta } from './registry.js';\nimport type { SeederInterface } from './decorator.js';\nimport type { SeedContext } from '../seed/registry.js';\n\n/** Constructor type for a class decorated with `@Seeder`. */\nexport type SeederCtor = new () => SeederInterface;\n\n/** Options for {@link runSeeders}. Extends {@link SeedContext} with lifecycle hooks and logging control. */\nexport interface RunSeedersOptions extends SeedContext {\n /**\n * Enable console logging for each seeder. Set to `false` to silence output,\n * e.g. when using callbacks to handle logging yourself.\n *\n * @default true\n */\n logging?: boolean;\n /** Called before each seeder runs, in execution order. */\n onBefore?: (seeder: SeederCtor) => void | Promise<void>;\n /** Called after each seeder completes successfully, with the time it took in milliseconds. */\n onAfter?: (seeder: SeederCtor, durationMs: number) => void | Promise<void>;\n /** Called when a seeder throws. The error is re-thrown after this callback returns. */\n onError?: (seeder: SeederCtor, error: unknown) => void | Promise<void>;\n /** Called for each seeder before it runs. Return `true` to skip it entirely. */\n skip?: (seeder: SeederCtor) => boolean | Promise<boolean>;\n}\n\n/**\n * Topologically sorts the given seeders and all their transitive dependencies.\n * BFS walks from the roots to collect all nodes, then dependency edges are wired and\n * the graph is sorted so that every dependency precedes the seeders that depend on it.\n * Throws a descriptive error if a circular dependency is detected.\n */\nfunction topoSort(roots: SeederCtor[]): SeederCtor[] {\n const graph = new DepGraph<SeederCtor>();\n const byName = new Map<string, SeederCtor>();\n\n // Collect all nodes transitively via BFS and register them in the graph.\n const visited = new Set<SeederCtor>();\n const queue: SeederCtor[] = [...roots];\n\n while (queue.length > 0) {\n const node = queue.shift()!;\n\n if (visited.has(node)) {\n continue;\n }\n\n visited.add(node);\n graph.addNode(node.name, node);\n byName.set(node.name, node);\n\n for (const dep of (getSeederMeta(node)?.dependencies ?? []) as SeederCtor[]) {\n queue.push(dep);\n }\n }\n\n // Wire up the dependency edges.\n for (const node of visited) {\n for (const dep of (getSeederMeta(node)?.dependencies ?? []) as SeederCtor[]) {\n graph.addDependency(node.name, dep.name);\n }\n }\n\n try {\n return graph.overallOrder().map((name) => byName.get(name)!);\n } catch (err) {\n if (err && typeof err === 'object' && 'cyclePath' in err) {\n const path = (err as { cyclePath: string[] }).cyclePath.join(' → ');\n throw new Error(`Circular dependency detected among seeders: ${path}`);\n }\n\n throw err;\n }\n}\n\n/**\n * Runs the given seeders (and all their transitive dependencies) in dependency order.\n *\n * Each seeder is instantiated, its `run` method is called with the context derived\n * from `options`, and lifecycle hooks (`onBefore`, `onAfter`, `onError`) are called\n * around it. Errors are re-thrown after `onError` returns.\n *\n * @example\n * await runSeeders([PostSeeder], { dataSource })\n *\n * @example\n * // With lifecycle hooks and no console output\n * await runSeeders([PostSeeder], {\n * dataSource,\n * logging: false,\n * onAfter: (seeder, ms) => console.log(`${seeder.name} done in ${ms}ms`),\n * })\n */\nexport async function runSeeders(\n seeders: SeederCtor[],\n options: RunSeedersOptions = {},\n): Promise<void> {\n const { logging = true, onBefore, onAfter, onError, skip, ...context } = options;\n\n for (const SeederClass of topoSort(seeders)) {\n if (await skip?.(SeederClass)) {\n continue;\n }\n\n if (logging) {\n console.log(`[${SeederClass.name}] Starting...`);\n }\n\n await onBefore?.(SeederClass);\n\n const start = Date.now();\n\n try {\n await new SeederClass().run(context);\n } catch (err) {\n const durationMs = Date.now() - start;\n\n if (logging) {\n console.error(`[${SeederClass.name}] Failed after ${durationMs}ms`);\n }\n\n await onError?.(SeederClass, err);\n throw err;\n }\n\n const durationMs = Date.now() - start;\n\n if (logging) {\n console.log(`[${SeederClass.name}] Done in ${durationMs}ms`);\n }\n\n await onAfter?.(SeederClass, durationMs);\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["registry"],"sources":["../src/seed/registry.ts","../src/seed/decorator.ts","../src/seed/creator.ts","../src/seed/persist.ts","../src/seed/builder.ts","../src/seeder/registry.ts","../src/seeder/decorator.ts","../src/seeder/runner.ts"],"sourcesContent":["import type { DataSource } from 'typeorm';\n\n/** An entity instance — any class-based object managed by TypeORM. */\nexport type EntityInstance = object;\n\n/** A constructor that produces an entity instance. */\nexport type EntityConstructor<T extends EntityInstance = EntityInstance> = new () => T;\n\n/** Context passed through a seed operation. Available inside factory callbacks and `SeederInterface.run`. */\nexport interface SeedContext {\n /**\n * The TypeORM DataSource. Automatically set by `save`/`saveMany` calls.\n * Also available in factory callbacks — useful for looking up existing\n * entities instead of creating new ones:\n *\n * @example\n * @Seed(async ({ dataSource }) => dataSource.getRepository(Role).findOneByOrFail({ name: 'admin' }))\n * role!: Role\n */\n dataSource?: DataSource;\n /**\n * Set to `false` to skip automatic relation seeding. Scalar and embedded\n * properties are still seeded; only relation properties decorated with a\n * bare `@Seed()` are skipped. Useful when you want to create flat entities\n * and wire relations yourself.\n *\n * @default true\n */\n relations?: boolean;\n}\n\n/**\n * Factory callback passed to `@Seed`. Receives the seed context and the partially built entity.\n *\n * Properties are seeded sequentially in declaration order, so any property declared above the\n * current one is already set on `self` and can be read to derive the current value.\n *\n * Annotate `self` with the entity class to get full type inference — TypeScript infers\n * `TEntity` from the annotation, so no cast is needed:\n *\n * @example\n * @Seed(() => faker.date.past())\n * beginDate!: Date\n *\n * @Seed((_, self: MyEntity) => faker.date.future({ refDate: self.beginDate }))\n * endDate!: Date\n */\nexport type SeedFactory<T = unknown, TEntity = any> = (\n context: SeedContext,\n self: TEntity,\n) => T | Promise<T>;\n\n/** Options for the `@Seed` decorator. */\nexport interface SeedOptions {\n /**\n * Number of related entities to create. Only meaningful on one-to-many and\n * many-to-many relation properties. Ignored on scalar and single-entity relations.\n */\n count?: number;\n}\n\nexport interface SeedEntry {\n propertyKey: string | symbol;\n /** Undefined when @Seed is used without a factory (i.e. bare relation seed). */\n factory: SeedFactory | undefined;\n options: SeedOptions;\n}\n\nexport type MapToInstances<T extends readonly EntityConstructor[]> = {\n [K in keyof T]: T[K] extends EntityConstructor<infer I> ? I : never;\n};\n\nexport type MapToInstanceArrays<T extends readonly EntityConstructor[]> = {\n [K in keyof T]: T[K] extends EntityConstructor<infer I> ? I[] : never;\n};\n\n// Keyed by the entity class constructor.\nconst registry = new Map<Function, SeedEntry[]>();\n\n/** Registers a seed entry for the given class constructor. Called internally by the `@Seed` decorator. */\nexport function registerSeed(target: Function, entry: SeedEntry): void {\n const entries = registry.get(target) ?? [];\n\n entries.push(entry);\n registry.set(target, entries);\n}\n\n/**\n * Returns all seed entries for the given class, including those inherited from\n * parent classes. Parent entries come first, preserving declaration order.\n */\nexport function getSeeds(target: Function): SeedEntry[] {\n const entries: SeedEntry[] = [];\n let current: Function = target;\n\n while (current && current !== Function.prototype) {\n const own = registry.get(current);\n\n if (own) {\n entries.unshift(...own);\n }\n\n current = Object.getPrototypeOf(current) as Function;\n }\n\n return entries;\n}\n","import { registerSeed } from './registry.js';\nimport type { SeedFactory, SeedOptions } from './registry.js';\n\n/**\n * Marks a relation property for auto-seeding.\n *\n * The related entity class is inferred from TypeORM metadata. One instance is created\n * and recursively seeded (including its own `@Seed` properties).\n *\n * Circular back-references are broken automatically: if the related class is already\n * being seeded higher up in the same call chain, the property is left `undefined`.\n * TypeORM treats `undefined` as \"don't touch this column\" rather than setting it to null.\n */\nexport function Seed(): PropertyDecorator;\n/**\n * Marks a relation property for auto-seeding with options.\n *\n * Use `count` on one-to-many and many-to-many properties to control how many\n * related entities are created. Ignored for one-to-one and many-to-one.\n *\n * @example\n * @Seed({ count: 3 })\n * @OneToMany(() => Book, (b) => b.author)\n * books!: Book[]\n */\nexport function Seed(options: SeedOptions): PropertyDecorator;\n/**\n * Marks a property with a factory callback.\n *\n * The factory receives the current {@link SeedContext} and can return any value,\n * including a `Promise`. Use this for scalar properties or when you need full\n * control over how a related entity is resolved.\n *\n * @example\n * @Seed(() => faker.internet.email())\n * email!: string\n *\n * @example\n * // Look up an existing entity instead of creating a new one\n * @Seed(async ({ dataSource }) => dataSource.getRepository(Role).findOneByOrFail({ name: 'admin' }))\n * role!: Role\n */\nexport function Seed<TEntity = any>(factory: SeedFactory<unknown, TEntity>): PropertyDecorator;\n/** Marks a property with a factory callback and additional options. */\nexport function Seed<TEntity = any>(\n factory: SeedFactory<unknown, TEntity>,\n options: SeedOptions,\n): PropertyDecorator;\nexport function Seed(\n factoryOrOptions?: SeedFactory | SeedOptions,\n options?: SeedOptions,\n): PropertyDecorator {\n const factory = typeof factoryOrOptions === 'function' ? factoryOrOptions : undefined;\n const opts: SeedOptions =\n (typeof factoryOrOptions === 'object' ? factoryOrOptions : options) ?? {};\n\n return (target, propertyKey) => {\n registerSeed(target.constructor as Function, { propertyKey, factory, options: opts });\n };\n}\n","import { getMetadataArgsStorage } from 'typeorm';\nimport type {\n EntityConstructor,\n EntityInstance,\n MapToInstanceArrays,\n MapToInstances,\n SeedContext,\n SeedFactory,\n} from './registry.js';\nimport { getSeeds } from './registry.js';\n\n/**\n * A map of property overrides for seeded entities.\n * Each property can be either a static value or a {@link SeedFactory} that is called\n * once per entity — enabling unique random values across each created instance.\n *\n * @example\n * // All 10 bookings get a unique random price\n * await seed(Booking).saveMany(10, {\n * dataSource,\n * values: { price: () => faker.number.float({ min: 10, max: 500 }) },\n * })\n */\nexport type SeedValues<T extends EntityInstance> = {\n [K in keyof T]?: T[K] | SeedFactory<T[K], T>;\n};\n\n/**\n * Options for {@link create} and {@link createMany} on the single-class form.\n * Extends {@link SeedContext} with a typed `values` override map.\n */\nexport interface CreateOptions<T extends EntityInstance> extends SeedContext {\n /**\n * Property values to apply after all `@Seed` factories have run.\n * Wins unconditionally — factories still execute but their output is overwritten.\n * Also works for properties that have no `@Seed` decorator.\n *\n * @example\n * const user = await dataSource.getRepository(User).findOneByOrFail({ name: 'Alice' })\n * const post = await seed(Post).create({ values: { author: user } })\n */\n values?: SeedValues<T>;\n}\n\n/** Options for {@link createMany}. Extends {@link SeedContext} with a required instance count. */\nexport interface CreateManyOptions<T extends EntityInstance = EntityInstance> extends SeedContext {\n count: number;\n values?: SeedValues<T>;\n}\n\n// Internal extension of SeedContext — never exposed in the public API.\ninterface InternalContext extends SeedContext {\n _ancestors: Set<Function>;\n}\n\n/** Extracts the ancestor set from an internal context, returning an empty set for external callers. */\nfunction getAncestors(context: SeedContext): Set<Function> {\n return (context as InternalContext)._ancestors ?? new Set();\n}\n\n/**\n * Applies a {@link SeedValues} map to an instance.\n * Factory entries are called once per instance so each entity can get unique values.\n */\nasync function applyValues<T extends EntityInstance>(\n instance: T,\n values: SeedValues<T>,\n context: SeedContext,\n): Promise<void> {\n const record = instance as Record<string | symbol, unknown>;\n\n for (const key of Object.keys(values) as (keyof T & string)[]) {\n const value = values[key];\n\n if (typeof value === 'function') {\n record[key] = await (value as SeedFactory)(context, instance);\n } else {\n record[key] = value;\n }\n }\n}\n\n/** Returns a new context with `cls` added to the ancestor set, used to detect circular relation chains. */\nfunction withAncestor(context: SeedContext, cls: Function): InternalContext {\n const ancestors = getAncestors(context);\n\n return { ...context, _ancestors: new Set([...ancestors, cls]) };\n}\n\n/** Walks the prototype chain and returns all classes from `target` up to (but not including) `Function.prototype`. */\nfunction getClassHierarchy(target: Function): Function[] {\n const hierarchy: Function[] = [];\n let current: Function = target;\n\n while (current && current !== Function.prototype) {\n hierarchy.push(current);\n current = Object.getPrototypeOf(current) as Function;\n }\n\n return hierarchy;\n}\n\n/**\n * Creates one fully populated instance of `EntityClass` in memory.\n *\n * Runs in three steps:\n * 1. Factory-decorated properties (`@Seed(factory)`) — run first, in declaration order.\n * 2. Embedded types (`@Embedded`) — auto-seeded if the embedded class has any `@Seed` entries.\n * 3. Bare relation decorators (`@Seed()` without a factory) — skipped when `relations` is `false`,\n * and also skipped for any related class already present in the ancestor chain (circular guard).\n */\nasync function createOne<T extends EntityInstance>(\n EntityClass: EntityConstructor<T>,\n context: SeedContext,\n): Promise<T> {\n const instance = new EntityClass();\n const ancestors = getAncestors(context);\n const childContext = withAncestor(context, EntityClass);\n const storage = getMetadataArgsStorage();\n const relations = storage.filterRelations(getClassHierarchy(EntityClass));\n const seededProperties = new Set<string | symbol>();\n const record = instance as Record<string | symbol, unknown>;\n\n // Step 1: Run @Seed entries that have an explicit factory.\n for (const { propertyKey, factory } of getSeeds(EntityClass)) {\n if (!factory) {\n continue;\n }\n\n record[propertyKey] = await factory(context, instance);\n seededProperties.add(propertyKey);\n }\n\n // Step 2: Auto-seed TypeORM embedded properties not already covered by Step 1.\n for (const embedded of storage.filterEmbeddeds(EntityClass)) {\n if (seededProperties.has(embedded.propertyName)) {\n continue;\n }\n\n const EmbeddedClass = embedded.type() as EntityConstructor;\n\n if (getSeeds(EmbeddedClass).length > 0) {\n record[embedded.propertyName] = await createOne(EmbeddedClass, context);\n seededProperties.add(embedded.propertyName);\n }\n }\n\n // Step 3: Auto-seed @Seed entries without a factory (relation seeds).\n // Uses the ancestor guard to cut circular chains: if the related class is\n // already being seeded higher up in this call chain, the property is left\n // undefined rather than triggering infinite recursion.\n // Skipped entirely when context.relations === false.\n if (context.relations === false) {\n return instance;\n }\n\n for (const { propertyKey, factory, options } of getSeeds(EntityClass)) {\n if (factory || seededProperties.has(propertyKey)) {\n continue;\n }\n\n const relation = relations.find((r) => r.propertyName === String(propertyKey));\n\n if (!relation || typeof relation.type !== 'function') {\n continue;\n }\n\n const RelatedClass = (relation.type as () => Function)() as EntityConstructor;\n\n if (ancestors.has(RelatedClass)) {\n continue;\n }\n\n const isArray =\n relation.relationType === 'one-to-many' || relation.relationType === 'many-to-many';\n\n if (isArray) {\n record[propertyKey] = await createMany(RelatedClass, {\n count: options.count ?? 1,\n ...childContext,\n });\n } else {\n record[propertyKey] = await createOne(RelatedClass, childContext);\n }\n\n seededProperties.add(propertyKey);\n }\n\n return instance;\n}\n\n/**\n * Creates one entity instance in memory without persisting it.\n *\n * When passed an array of classes, relation seeding is disabled by default\n * (pass `relations: true` in the context to override). Returns a tuple of\n * instances in the same order as the input array.\n */\nexport async function create<T extends EntityInstance>(\n EntityClass: EntityConstructor<T>,\n options?: CreateOptions<T>,\n): Promise<T>;\nexport async function create<T extends readonly EntityConstructor[]>(\n EntityClasses: [...T],\n context?: SeedContext,\n): Promise<MapToInstances<T>>;\nexport async function create<T extends EntityInstance>(\n classOrClasses: EntityConstructor<T> | readonly EntityConstructor[],\n options: CreateOptions<T> = {},\n): Promise<T | EntityInstance[]> {\n if (Array.isArray(classOrClasses)) {\n const effectiveContext: SeedContext = { relations: false, ...options };\n\n return (await Promise.all(\n (classOrClasses as EntityConstructor[]).map((cls) => createOne(cls, effectiveContext)),\n )) as EntityInstance[];\n }\n\n const { values, ...context } = options as CreateOptions<T>;\n const instance = await createOne(classOrClasses as EntityConstructor<T>, context);\n\n if (values) {\n await applyValues(instance, values, context);\n }\n\n return instance;\n}\n\n/**\n * Creates multiple entity instances in memory without persisting them.\n *\n * When passed an array of classes, returns a tuple of arrays — one per class — each\n * containing `count` instances. Relation seeding is disabled by default for the\n * array variant; pass `relations: true` in the options to override.\n */\nexport async function createMany<T extends EntityInstance>(\n EntityClass: EntityConstructor<T>,\n options: CreateManyOptions<T>,\n): Promise<T[]>;\nexport async function createMany<T extends readonly EntityConstructor[]>(\n EntityClasses: [...T],\n options: CreateManyOptions,\n): Promise<MapToInstanceArrays<T>>;\nexport async function createMany<T extends EntityInstance>(\n classOrClasses: EntityConstructor<T> | readonly EntityConstructor[],\n { count, values, ...context }: CreateManyOptions<T>,\n): Promise<T[] | EntityInstance[][]> {\n if (Array.isArray(classOrClasses)) {\n const effectiveContext: SeedContext = { relations: false, ...context };\n\n return (await Promise.all(\n (classOrClasses as EntityConstructor[]).map((cls) =>\n Promise.all(Array.from({ length: count }, () => createOne(cls, effectiveContext))),\n ),\n )) as EntityInstance[][];\n }\n\n const instances = await Promise.all(\n Array.from({ length: count }, () => createOne(classOrClasses as EntityConstructor<T>, context)),\n );\n\n if (values) {\n await Promise.all(instances.map((instance) => applyValues(instance, values, context)));\n }\n\n return instances;\n}\n","import { type DataSource } from 'typeorm';\nimport { createMany } from './creator.js';\nimport type { SeedValues } from './creator.js';\nimport type {\n EntityConstructor,\n EntityInstance,\n MapToInstanceArrays,\n MapToInstances,\n SeedContext,\n} from './registry.js';\n\n/** Options for {@link save}. Extends {@link SeedContext} with a required DataSource. */\nexport interface SaveOptions<T extends EntityInstance = EntityInstance> extends SeedContext {\n dataSource: DataSource;\n /**\n * Property values to apply to each entity after seeding and before persisting.\n * Wins unconditionally over `@Seed` factory output — the factory still runs,\n * but its result is overwritten. Also works for properties that have no `@Seed`\n * decorator at all.\n *\n * @example\n * const users = await dataSource.getRepository(User).find()\n * const user = faker.helpers.arrayElement(users)\n * await seed(Booking).saveMany(10, { dataSource, values: { user } })\n */\n values?: SeedValues<T>;\n}\n\n/** Options for {@link saveMany}. Extends {@link SaveOptions} with a required instance count. */\nexport interface SaveManyOptions<T extends EntityInstance = EntityInstance> extends SaveOptions<T> {\n count: number;\n}\n\ntype RelationMetadata = DataSource extends { getMetadata(...args: never[]): infer M }\n ? M extends { relations: Array<infer R> }\n ? R\n : never\n : never;\n\ninterface CascadeState {\n relation: RelationMetadata;\n original: boolean;\n}\n\n/**\n * Walks an entity object graph and collects every unique entity class encountered.\n * Used to discover all entity classes that need cascade-insert temporarily enabled\n * before saving so that the full in-memory graph is persisted in one shot.\n */\nfunction collectEntityClasses(entity: EntityInstance, visited = new Set<Function>()): Function[] {\n const EntityClass = entity.constructor as Function;\n\n if (visited.has(EntityClass)) {\n return [];\n }\n\n visited.add(EntityClass);\n\n const classes: Function[] = [EntityClass];\n\n for (const value of Object.values(entity)) {\n if (Array.isArray(value)) {\n for (const item of value) {\n if (item && typeof item === 'object' && item.constructor !== Object) {\n classes.push(...collectEntityClasses(item, visited));\n }\n }\n } else if (value && typeof value === 'object' && value.constructor !== Object) {\n classes.push(...collectEntityClasses(value as EntityInstance, visited));\n }\n }\n\n return classes;\n}\n\n/**\n * Temporarily enables `isCascadeInsert` on every TypeORM relation for the given class.\n * Returns the previous flag values so they can be restored after saving.\n *\n * This is necessary because the seeder builds the full object graph in memory before\n * calling `save()`. Without cascade inserts, TypeORM would only persist the root entity\n * and ignore any nested relations that weren't already configured with `cascade: true`.\n *\n * Classes not registered as TypeORM entities (e.g. embedded value objects) are silently skipped.\n */\nfunction enableCascadeInsert(EntityClass: Function, dataSource: DataSource): CascadeState[] {\n const states: CascadeState[] = [];\n\n try {\n const relations = dataSource.getMetadata(EntityClass).relations;\n\n for (const relation of relations) {\n states.push({ relation, original: relation.isCascadeInsert });\n relation.isCascadeInsert = true;\n }\n } catch {\n // Class is not registered as an entity with this DataSource (e.g. embedded class).\n }\n\n return states;\n}\n\n/**\n * Restores `isCascadeInsert` flags to their original values.\n * Always called in a `finally` block to guarantee cleanup even when saving throws.\n */\nfunction restoreCascade(states: CascadeState[]): void {\n for (const { relation, original } of states) {\n relation.isCascadeInsert = original;\n }\n}\n\n/**\n * Creates and persists a seed entity and all its seeded relations.\n */\nexport async function save<T extends EntityInstance>(\n EntityClass: EntityConstructor<T>,\n options: SaveOptions<T>,\n): Promise<T>;\n/**\n * Creates and persists one instance of each entity class in the array.\n * Relation seeding is disabled by default; pass `relations: true` to override.\n */\nexport async function save<T extends readonly EntityConstructor[]>(\n EntityClasses: [...T],\n options: SaveOptions,\n): Promise<MapToInstances<T>>;\nexport async function save<T extends EntityInstance>(\n classOrClasses: EntityConstructor<T> | readonly EntityConstructor[],\n options: SaveOptions<T>,\n): Promise<T | EntityInstance[]> {\n if (Array.isArray(classOrClasses)) {\n const effectiveOptions = { relations: false, ...options, count: 1 };\n\n return (await Promise.all(\n (classOrClasses as EntityConstructor[]).map((cls) =>\n saveBatch(cls, effectiveOptions).then(([entity]) => entity!),\n ),\n )) as EntityInstance[];\n }\n\n const [entity] = await saveBatch(classOrClasses as EntityConstructor<T>, {\n ...options,\n count: 1,\n });\n\n return entity!;\n}\n\n/**\n * Creates and persists multiple seed entities of the same class.\n * Applies the same logic as {@link save} for each entity.\n */\nexport async function saveMany<T extends EntityInstance>(\n EntityClass: EntityConstructor<T>,\n options: SaveManyOptions<T>,\n): Promise<T[]>;\n/**\n * Creates and persists multiple instances of each entity class in the array.\n * Relation seeding is disabled by default; pass `relations: true` to override.\n */\nexport async function saveMany<T extends readonly EntityConstructor[]>(\n EntityClasses: [...T],\n options: SaveManyOptions,\n): Promise<MapToInstanceArrays<T>>;\nexport async function saveMany<T extends EntityInstance>(\n classOrClasses: EntityConstructor<T> | readonly EntityConstructor[],\n options: SaveManyOptions<T>,\n): Promise<T[] | EntityInstance[][]> {\n if (Array.isArray(classOrClasses)) {\n const effectiveOptions = { relations: false, ...options };\n\n return (await Promise.all(\n (classOrClasses as EntityConstructor[]).map((cls) => saveBatch(cls, effectiveOptions)),\n )) as EntityInstance[][];\n }\n\n return await saveBatch(classOrClasses as EntityConstructor<T>, options);\n}\n\n/**\n * Creates and persists `count` instances of a single entity class in one batched\n * `repository.save()` call. Batching is intentional — it is more efficient than\n * saving each instance individually, as TypeORM can consolidate the inserts.\n *\n * Enables cascade inserts on every entity class in the object graph before saving,\n * then restores the original flags — regardless of whether the save succeeds or fails.\n */\nasync function saveBatch<T extends EntityInstance>(\n EntityClass: EntityConstructor<T>,\n options: SaveManyOptions<T>,\n): Promise<T[]> {\n const { count, dataSource } = options;\n\n if (count === 0) {\n return [];\n }\n\n const entities = await createMany(EntityClass, options);\n\n const visited = new Set<Function>();\n const states = entities\n .flatMap((entity) => collectEntityClasses(entity, visited))\n .flatMap((cls) => enableCascadeInsert(cls, dataSource));\n\n try {\n return (await dataSource.getRepository(EntityClass).save(entities)) as T[];\n } finally {\n restoreCascade(states);\n }\n}\n","import type { CreateOptions } from './creator.js';\nimport { create, createMany } from './creator.js';\nimport type { SaveManyOptions, SaveOptions } from './persist.js';\nimport { save, saveMany } from './persist.js';\nimport type {\n EntityConstructor,\n EntityInstance,\n MapToInstanceArrays,\n MapToInstances,\n SeedContext,\n} from './registry.js';\n\nexport type { CreateOptions } from './creator.js';\n\n/** Seed builder for a single entity class. Returned by {@link seed} when passed one class. */\ninterface SingleSeed<T extends EntityInstance> {\n /** Creates a single instance in memory without persisting. */\n create(context?: CreateOptions<T>): Promise<T>;\n /** Creates and persists a single instance. */\n save(options: SaveOptions<T>): Promise<T>;\n /** Creates multiple instances in memory without persisting. */\n createMany(count: number, context?: CreateOptions<T>): Promise<T[]>;\n /** Creates and persists multiple instances. */\n saveMany(count: number, options: SaveOptions<T>): Promise<T[]>;\n}\n\n/**\n * Seed builder for multiple entity classes. Returned by {@link seed} when passed an array.\n * Each method returns a tuple of instances in the same order as the input array.\n * Relation seeding is disabled by default; pass `relations: true` in the context to enable it.\n */\ninterface MultiSeed<T extends readonly EntityConstructor[]> {\n /** Creates one instance of each class in memory without persisting. */\n create(context?: SeedContext): Promise<MapToInstances<T>>;\n /** Creates and persists one instance of each class. */\n save(options: SaveOptions): Promise<MapToInstances<T>>;\n /** Creates `count` instances of each class in memory without persisting. */\n createMany(count: number, context?: SeedContext): Promise<MapToInstanceArrays<T>>;\n /** Creates and persists `count` instances of each class. */\n saveMany(count: number, options: SaveOptions): Promise<MapToInstanceArrays<T>>;\n}\n\n/**\n * Entry point for creating and persisting seed data.\n *\n * Pass a single entity class to get a {@link SingleSeed} builder, or an array of classes\n * to get a {@link MultiSeed} builder that operates on all of them at once.\n *\n * @example\n * // Create one Author in memory (no DB)\n * const author = await seed(Author).create()\n *\n * @example\n * // Persist one Author with all its seeded relations\n * const author = await seed(Author).save({ dataSource })\n *\n * @example\n * // Persist 10 Authors\n * const authors = await seed(Author).saveMany(10, { dataSource })\n *\n * @example\n * // Create multiple entity classes at once (relations disabled by default)\n * const [user, post] = await seed([User, Post]).create()\n */\nexport function seed<T extends EntityInstance>(EntityClass: EntityConstructor<T>): SingleSeed<T>;\nexport function seed<T extends readonly EntityConstructor[]>(EntityClasses: [...T]): MultiSeed<T>;\nexport function seed<T extends EntityInstance>(\n classOrClasses: EntityConstructor<T> | readonly EntityConstructor[],\n): SingleSeed<T> | MultiSeed<readonly EntityConstructor[]> {\n if (Array.isArray(classOrClasses)) {\n const classes = classOrClasses as readonly EntityConstructor[];\n\n return {\n create: (context?: SeedContext) =>\n create(classes as [...typeof classes], context) as Promise<MapToInstances<typeof classes>>,\n save: (options: SaveOptions) =>\n save(classes as [...typeof classes], options) as Promise<MapToInstances<typeof classes>>,\n createMany: (count: number, context?: SeedContext) =>\n createMany(classes as [...typeof classes], { count, ...context }) as Promise<\n MapToInstanceArrays<typeof classes>\n >,\n saveMany: (count: number, options: SaveOptions) =>\n saveMany(\n classes as [...typeof classes],\n { count, ...options } as SaveManyOptions,\n ) as Promise<MapToInstanceArrays<typeof classes>>,\n };\n }\n\n const EntityClass = classOrClasses as EntityConstructor<T>;\n\n return {\n create: (options?: CreateOptions<T>) => create(EntityClass, options),\n save: (options: SaveOptions<T>) => save(EntityClass, options),\n createMany: (count: number, options?: CreateOptions<T>) =>\n createMany(EntityClass, { count, ...options }),\n saveMany: (count: number, options: SaveOptions<T>) =>\n saveMany(EntityClass, { count, ...options }),\n };\n}\n","interface SeederMeta {\n dependencies: Function[];\n}\n\nconst registry = new WeakMap<Function, SeederMeta>();\n\n/** Registers seeder metadata for the given class constructor. Called internally by the `@Seeder` decorator. */\nexport function registerSeeder(target: Function, meta: SeederMeta): void {\n registry.set(target, meta);\n}\n\n/** Returns the metadata registered for the given seeder class, or `undefined` if not registered. */\nexport function getSeederMeta(target: Function): SeederMeta | undefined {\n return registry.get(target);\n}\n","import { registerSeeder } from './registry.js';\nimport type { SeedContext } from '../seed/registry.js';\n\n/**\n * Interface that seeder classes must implement.\n *\n * The `run` method receives the seed context (which includes the DataSource when\n * called via `runSeeders`) and performs the seeding logic — typically by calling\n * `seed().save()` or other seeding utilities.\n */\nexport interface SeederInterface {\n run(context: SeedContext): Promise<void>;\n}\n\n/** Configuration options for the {@link Seeder} decorator. */\nexport interface SeederOptions {\n /**\n * Seeder classes that must complete before this one runs.\n * Resolved transitively — dependencies of dependencies are included automatically.\n * {@link runSeeders} topologically sorts the full set and detects circular dependencies.\n */\n dependencies?: (new () => SeederInterface)[];\n}\n\n/**\n * Marks a class as a seeder and registers its dependency metadata.\n *\n * Classes decorated with `@Seeder` can be passed to {@link runSeeders}, which resolves\n * all transitive dependencies, sorts them topologically, and executes them in order.\n *\n * @example\n * @Seeder({ dependencies: [UserSeeder] })\n * class PostSeeder implements SeederInterface {\n * async run(ctx: SeedContext) {\n * await seed(Post).saveMany(50, ctx)\n * }\n * }\n */\nexport function Seeder(options: SeederOptions = {}): ClassDecorator {\n return (target) => {\n registerSeeder(target, { dependencies: options.dependencies ?? [] });\n };\n}\n","import { DepGraph } from 'dependency-graph';\nimport { getSeederMeta } from './registry.js';\nimport type { SeederInterface } from './decorator.js';\nimport type { SeedContext } from '../seed/registry.js';\n\n/** Constructor type for a class decorated with `@Seeder`. */\nexport type SeederCtor = new () => SeederInterface;\n\n/** Options for {@link runSeeders}. Extends {@link SeedContext} with lifecycle hooks and logging control. */\nexport interface RunSeedersOptions extends SeedContext {\n /**\n * Enable console logging for each seeder. Set to `false` to silence output,\n * e.g. when using callbacks to handle logging yourself.\n *\n * @default true\n */\n logging?: boolean;\n /** Called before each seeder runs, in execution order. */\n onBefore?: (seeder: SeederCtor) => void | Promise<void>;\n /** Called after each seeder completes successfully, with the time it took in milliseconds. */\n onAfter?: (seeder: SeederCtor, durationMs: number) => void | Promise<void>;\n /** Called when a seeder throws. The error is re-thrown after this callback returns. */\n onError?: (seeder: SeederCtor, error: unknown) => void | Promise<void>;\n /** Called for each seeder before it runs. Return `true` to skip it entirely. */\n skip?: (seeder: SeederCtor) => boolean | Promise<boolean>;\n}\n\n/**\n * Topologically sorts the given seeders and all their transitive dependencies.\n * BFS walks from the roots to collect all nodes, then dependency edges are wired and\n * the graph is sorted so that every dependency precedes the seeders that depend on it.\n * Throws a descriptive error if a circular dependency is detected.\n */\nfunction topoSort(roots: SeederCtor[]): SeederCtor[] {\n const graph = new DepGraph<SeederCtor>();\n const byName = new Map<string, SeederCtor>();\n\n // Collect all nodes transitively via BFS and register them in the graph.\n const visited = new Set<SeederCtor>();\n const queue: SeederCtor[] = [...roots];\n\n while (queue.length > 0) {\n const node = queue.shift()!;\n\n if (visited.has(node)) {\n continue;\n }\n\n visited.add(node);\n graph.addNode(node.name, node);\n byName.set(node.name, node);\n\n for (const dep of (getSeederMeta(node)?.dependencies ?? []) as SeederCtor[]) {\n queue.push(dep);\n }\n }\n\n // Wire up the dependency edges.\n for (const node of visited) {\n for (const dep of (getSeederMeta(node)?.dependencies ?? []) as SeederCtor[]) {\n graph.addDependency(node.name, dep.name);\n }\n }\n\n try {\n return graph.overallOrder().map((name) => byName.get(name)!);\n } catch (err) {\n if (err && typeof err === 'object' && 'cyclePath' in err) {\n const path = (err as { cyclePath: string[] }).cyclePath.join(' → ');\n throw new Error(`Circular dependency detected among seeders: ${path}`);\n }\n\n throw err;\n }\n}\n\n/**\n * Runs the given seeders (and all their transitive dependencies) in dependency order.\n *\n * Each seeder is instantiated, its `run` method is called with the context derived\n * from `options`, and lifecycle hooks (`onBefore`, `onAfter`, `onError`) are called\n * around it. Errors are re-thrown after `onError` returns.\n *\n * @example\n * await runSeeders([PostSeeder], { dataSource })\n *\n * @example\n * // With lifecycle hooks and no console output\n * await runSeeders([PostSeeder], {\n * dataSource,\n * logging: false,\n * onAfter: (seeder, ms) => console.log(`${seeder.name} done in ${ms}ms`),\n * })\n */\nexport async function runSeeders(\n seeders: SeederCtor[],\n options: RunSeedersOptions = {},\n): Promise<void> {\n const { logging = true, onBefore, onAfter, onError, skip, ...context } = options;\n\n for (const SeederClass of topoSort(seeders)) {\n if (await skip?.(SeederClass)) {\n continue;\n }\n\n if (logging) {\n console.log(`[${SeederClass.name}] Starting...`);\n }\n\n await onBefore?.(SeederClass);\n\n const start = Date.now();\n\n try {\n await new SeederClass().run(context);\n } catch (err) {\n const durationMs = Date.now() - start;\n\n if (logging) {\n console.error(`[${SeederClass.name}] Failed after ${durationMs}ms`);\n }\n\n await onError?.(SeederClass, err);\n throw err;\n }\n\n const durationMs = Date.now() - start;\n\n if (logging) {\n console.log(`[${SeederClass.name}] Done in ${durationMs}ms`);\n }\n\n await onAfter?.(SeederClass, durationMs);\n }\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@joakimbugge/typeorm-seeder",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "description": "Decorator-based seeder library for TypeORM",
5
5
  "repository": {
6
6
  "type": "git",
@@ -34,6 +34,7 @@
34
34
  "typecheck": "tsc --noEmit",
35
35
  "test": "vitest",
36
36
  "test:run": "vitest run",
37
+ "test:cov": "vitest run --coverage",
37
38
  "lint": "oxlint src tests",
38
39
  "lint:fix": "oxlint --fix src tests",
39
40
  "fmt": "oxfmt src tests",