@joakimbugge/typeorm-seeder 0.5.0 → 0.6.0
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 +85 -9
- package/dist/index.cjs +41 -37
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +77 -46
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +77 -46
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +38 -34
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -173,6 +173,53 @@ If a factory needs to query the database, the `dataSource` you provide in option
|
|
|
173
173
|
role!: Role
|
|
174
174
|
```
|
|
175
175
|
|
|
176
|
+
> [!TIP]
|
|
177
|
+
> For anything more complex than a simple lookup — such as picking a random element from a result set — prefer the [`values` option](#overriding-seeded-values) instead. It keeps that logic in the call site rather than the entity decorator.
|
|
178
|
+
|
|
179
|
+
### Overriding seeded values
|
|
180
|
+
|
|
181
|
+
Pass a `values` map to inject specific values after all `@Seed` factories have run:
|
|
182
|
+
|
|
183
|
+
```ts
|
|
184
|
+
const booking = await seed(Booking).create({ values: { status: 'confirmed' } })
|
|
185
|
+
// status is set even if Booking has no @Seed on it
|
|
186
|
+
|
|
187
|
+
const booking = await seed(Booking).save({ dataSource, values: { user, status: 'confirmed' } })
|
|
188
|
+
|
|
189
|
+
const bookings = await seed(Booking).createMany(5, { values: { user } })
|
|
190
|
+
// all 5 get the same user
|
|
191
|
+
|
|
192
|
+
const bookings = await seed(Booking).saveMany(5, { dataSource, values: { user } })
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
`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
|
+
|
|
197
|
+
> [!NOTE]
|
|
198
|
+
> `values` are applied **after** all `@Seed` factories have finished, so they are never visible on `self` inside a factory callback.
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
### Depending on earlier properties
|
|
203
|
+
|
|
204
|
+
Properties are seeded in declaration order. Each factory receives the partially-built entity as its second argument (`self`), so a property can read any value that was seeded above it:
|
|
205
|
+
|
|
206
|
+
```ts
|
|
207
|
+
@Entity()
|
|
208
|
+
class Event {
|
|
209
|
+
@Seed(() => faker.date.past())
|
|
210
|
+
@Column()
|
|
211
|
+
beginDate!: Date
|
|
212
|
+
|
|
213
|
+
@Seed((_, self: Event) => faker.date.future({ refDate: self.beginDate }))
|
|
214
|
+
@Column()
|
|
215
|
+
endDate!: Date
|
|
216
|
+
}
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
Annotating `self` with the entity class (`self: Event` above) gives full type inference and autocompletion. Without the annotation `self` is typed as `any`, so property access still works — the annotation is only needed for type safety.
|
|
220
|
+
|
|
221
|
+
Properties declared *below* the current property are not yet set and will be `undefined` on `self` at that point.
|
|
222
|
+
|
|
176
223
|
---
|
|
177
224
|
|
|
178
225
|
## Seeder suites
|
|
@@ -210,21 +257,22 @@ Circular dependencies between seeders are detected at runtime and throw an error
|
|
|
210
257
|
|
|
211
258
|
## Seeding without `@Seed()`
|
|
212
259
|
|
|
213
|
-
`@Seed()` is a convenience — it is not required.
|
|
260
|
+
`@Seed()` is a convenience — it is not required. Complex seeding logic that would clutter entity decorators belongs in the seeder suite instead. Use the [`values` option](#overriding-seeded-values) to inject the result at call time, keeping your entities simple:
|
|
214
261
|
|
|
215
262
|
```ts
|
|
216
|
-
@Seeder()
|
|
217
|
-
class
|
|
263
|
+
@Seeder({ dependencies: [UserSeeder] })
|
|
264
|
+
class BookingSeeder implements SeederInterface {
|
|
218
265
|
async run({ dataSource }: SeedContext): Promise<void> {
|
|
219
|
-
await dataSource!.getRepository(User).
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
266
|
+
const users = await dataSource!.getRepository(User).find()
|
|
267
|
+
const user = faker.helpers.arrayElement(users)
|
|
268
|
+
|
|
269
|
+
// user is resolved here and injected — Booking stays simple
|
|
270
|
+
await seed(Booking).saveMany(10, { dataSource, values: { user } })
|
|
223
271
|
}
|
|
224
272
|
}
|
|
225
273
|
```
|
|
226
274
|
|
|
227
|
-
|
|
275
|
+
If you need full control — inserting specific rows, running raw queries, or using TypeORM's `EntityManager` — the `dataSource` from `SeedContext` gives you direct access to any TypeORM API.
|
|
228
276
|
|
|
229
277
|
---
|
|
230
278
|
|
|
@@ -326,11 +374,23 @@ Property decorator. Marks a property for automatic seeding.
|
|
|
326
374
|
|
|
327
375
|
| Signature | Behaviour |
|
|
328
376
|
|---|---|
|
|
329
|
-
| `@Seed(factory)` | Calls `factory(context)` and assigns the result |
|
|
377
|
+
| `@Seed(factory)` | Calls `factory(context, self)` and assigns the result |
|
|
330
378
|
| `@Seed(factory, options)` | Same, with additional options |
|
|
331
379
|
| `@Seed(options)` | Relation seed with options (e.g. `count`) |
|
|
332
380
|
| `@Seed()` | Bare relation seed — auto-creates one related entity |
|
|
333
381
|
|
|
382
|
+
**`SeedFactory<T, TEntity>`**
|
|
383
|
+
|
|
384
|
+
```ts
|
|
385
|
+
type SeedFactory<T = unknown, TEntity = any> = (context: SeedContext, self: TEntity) => T | Promise<T>
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
`self` is the entity instance as it exists when the factory runs — properties declared above this one are already populated, properties below are `undefined`. Annotate `self` with the entity class to get type inference:
|
|
389
|
+
|
|
390
|
+
```ts
|
|
391
|
+
@Seed((_, self: MyEntity) => ...)
|
|
392
|
+
```
|
|
393
|
+
|
|
334
394
|
**`SeedOptions`**
|
|
335
395
|
|
|
336
396
|
| Property | Type | Description |
|
|
@@ -359,6 +419,22 @@ seed([Author, Book]).save(options): Promise<[Author, Book]>
|
|
|
359
419
|
seed([Author, Book]).saveMany(count, options): Promise<[Author[], Book[]]>
|
|
360
420
|
```
|
|
361
421
|
|
|
422
|
+
**`CreateOptions<T>`** — passed to `create()` and `createMany()` on the single-class form
|
|
423
|
+
|
|
424
|
+
| Property | Type | Description |
|
|
425
|
+
|---|---|---|
|
|
426
|
+
| `dataSource` | `DataSource?` | Forwarded to factory functions via `SeedContext`. |
|
|
427
|
+
| `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. |
|
|
429
|
+
|
|
430
|
+
**`SaveOptions<T>`** — passed to `save()` and `saveMany()` on the single-class form
|
|
431
|
+
|
|
432
|
+
| Property | Type | Description |
|
|
433
|
+
|---|---|---|
|
|
434
|
+
| `dataSource` | `DataSource` | Required. Active TypeORM data source used to persist entities. |
|
|
435
|
+
| `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. |
|
|
437
|
+
|
|
362
438
|
---
|
|
363
439
|
|
|
364
440
|
### `@Seeder(options?)`
|
package/dist/index.cjs
CHANGED
|
@@ -69,7 +69,7 @@ function getClassHierarchy(target) {
|
|
|
69
69
|
* 3. Bare relation decorators (`@Seed()` without a factory) — skipped when `relations` is `false`,
|
|
70
70
|
* and also skipped for any related class already present in the ancestor chain (circular guard).
|
|
71
71
|
*/
|
|
72
|
-
async function
|
|
72
|
+
async function createOne(EntityClass, context) {
|
|
73
73
|
const instance = new EntityClass();
|
|
74
74
|
const ancestors = getAncestors(context);
|
|
75
75
|
const childContext = withAncestor(context, EntityClass);
|
|
@@ -86,7 +86,7 @@ async function createOneSeed(EntityClass, context) {
|
|
|
86
86
|
if (seededProperties.has(embedded.propertyName)) continue;
|
|
87
87
|
const EmbeddedClass = embedded.type();
|
|
88
88
|
if (getSeeds(EmbeddedClass).length > 0) {
|
|
89
|
-
record[embedded.propertyName] = await
|
|
89
|
+
record[embedded.propertyName] = await createOne(EmbeddedClass, context);
|
|
90
90
|
seededProperties.add(embedded.propertyName);
|
|
91
91
|
}
|
|
92
92
|
}
|
|
@@ -97,38 +97,39 @@ async function createOneSeed(EntityClass, context) {
|
|
|
97
97
|
if (!relation || typeof relation.type !== "function") continue;
|
|
98
98
|
const RelatedClass = relation.type();
|
|
99
99
|
if (ancestors.has(RelatedClass)) continue;
|
|
100
|
-
if (relation.relationType === "one-to-many" || relation.relationType === "many-to-many") record[propertyKey] = await
|
|
100
|
+
if (relation.relationType === "one-to-many" || relation.relationType === "many-to-many") record[propertyKey] = await createMany(RelatedClass, {
|
|
101
101
|
count: options.count ?? 1,
|
|
102
102
|
...childContext
|
|
103
103
|
});
|
|
104
|
-
else record[propertyKey] = await
|
|
104
|
+
else record[propertyKey] = await createOne(RelatedClass, childContext);
|
|
105
105
|
seededProperties.add(propertyKey);
|
|
106
106
|
}
|
|
107
107
|
return instance;
|
|
108
108
|
}
|
|
109
|
-
async function
|
|
109
|
+
async function create(classOrClasses, options = {}) {
|
|
110
110
|
if (Array.isArray(classOrClasses)) {
|
|
111
111
|
const effectiveContext = {
|
|
112
112
|
relations: false,
|
|
113
|
-
...
|
|
113
|
+
...options
|
|
114
114
|
};
|
|
115
|
-
return await Promise.all(classOrClasses.map((cls) =>
|
|
115
|
+
return await Promise.all(classOrClasses.map((cls) => createOne(cls, effectiveContext)));
|
|
116
116
|
}
|
|
117
|
-
const
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
return entity;
|
|
117
|
+
const { values, ...context } = options;
|
|
118
|
+
const instance = await createOne(classOrClasses, context);
|
|
119
|
+
if (values) Object.assign(instance, values);
|
|
120
|
+
return instance;
|
|
122
121
|
}
|
|
123
|
-
async function
|
|
122
|
+
async function createMany(classOrClasses, { count, values, ...context }) {
|
|
124
123
|
if (Array.isArray(classOrClasses)) {
|
|
125
124
|
const effectiveContext = {
|
|
126
125
|
relations: false,
|
|
127
126
|
...context
|
|
128
127
|
};
|
|
129
|
-
return await Promise.all(classOrClasses.map((cls) => Promise.all(Array.from({ length: count }, () =>
|
|
128
|
+
return await Promise.all(classOrClasses.map((cls) => Promise.all(Array.from({ length: count }, () => createOne(cls, effectiveContext)))));
|
|
130
129
|
}
|
|
131
|
-
|
|
130
|
+
const instances = await Promise.all(Array.from({ length: count }, () => createOne(classOrClasses, context)));
|
|
131
|
+
if (values) instances.forEach((e) => Object.assign(e, values));
|
|
132
|
+
return instances;
|
|
132
133
|
}
|
|
133
134
|
//#endregion
|
|
134
135
|
//#region src/seed/persist.ts
|
|
@@ -178,40 +179,43 @@ function enableCascadeInsert(EntityClass, dataSource) {
|
|
|
178
179
|
function restoreCascade(states) {
|
|
179
180
|
for (const { relation, original } of states) relation.isCascadeInsert = original;
|
|
180
181
|
}
|
|
181
|
-
async function
|
|
182
|
+
async function save(classOrClasses, options) {
|
|
182
183
|
if (Array.isArray(classOrClasses)) {
|
|
183
184
|
const effectiveOptions = {
|
|
184
185
|
relations: false,
|
|
185
186
|
...options,
|
|
186
187
|
count: 1
|
|
187
188
|
};
|
|
188
|
-
return await Promise.all(classOrClasses.map((cls) =>
|
|
189
|
+
return await Promise.all(classOrClasses.map((cls) => saveBatch(cls, effectiveOptions).then(([entity]) => entity)));
|
|
189
190
|
}
|
|
190
|
-
const [entity] = await
|
|
191
|
+
const [entity] = await saveBatch(classOrClasses, {
|
|
191
192
|
...options,
|
|
192
193
|
count: 1
|
|
193
194
|
});
|
|
194
195
|
return entity;
|
|
195
196
|
}
|
|
196
|
-
async function
|
|
197
|
+
async function saveMany(classOrClasses, options) {
|
|
197
198
|
if (Array.isArray(classOrClasses)) {
|
|
198
199
|
const effectiveOptions = {
|
|
199
200
|
relations: false,
|
|
200
201
|
...options
|
|
201
202
|
};
|
|
202
|
-
return await Promise.all(classOrClasses.map((cls) =>
|
|
203
|
+
return await Promise.all(classOrClasses.map((cls) => saveBatch(cls, effectiveOptions)));
|
|
203
204
|
}
|
|
204
|
-
return await
|
|
205
|
+
return await saveBatch(classOrClasses, options);
|
|
205
206
|
}
|
|
206
207
|
/**
|
|
207
|
-
* Creates and persists `count` instances of a single entity class
|
|
208
|
+
* Creates and persists `count` instances of a single entity class in one batched
|
|
209
|
+
* `repository.save()` call. Batching is intentional — it is more efficient than
|
|
210
|
+
* saving each instance individually, as TypeORM can consolidate the inserts.
|
|
211
|
+
*
|
|
208
212
|
* Enables cascade inserts on every entity class in the object graph before saving,
|
|
209
213
|
* then restores the original flags — regardless of whether the save succeeds or fails.
|
|
210
214
|
*/
|
|
211
|
-
async function
|
|
215
|
+
async function saveBatch(EntityClass, options) {
|
|
212
216
|
const { count, dataSource } = options;
|
|
213
217
|
if (count === 0) return [];
|
|
214
|
-
const entities = await
|
|
218
|
+
const entities = await createMany(EntityClass, options);
|
|
215
219
|
const visited = /* @__PURE__ */ new Set();
|
|
216
220
|
const states = entities.flatMap((entity) => collectEntityClasses(entity, visited)).flatMap((cls) => enableCascadeInsert(cls, dataSource));
|
|
217
221
|
try {
|
|
@@ -226,13 +230,13 @@ function seed(classOrClasses) {
|
|
|
226
230
|
if (Array.isArray(classOrClasses)) {
|
|
227
231
|
const classes = classOrClasses;
|
|
228
232
|
return {
|
|
229
|
-
create: (context) =>
|
|
230
|
-
save: (options) =>
|
|
231
|
-
createMany: (count, context) =>
|
|
233
|
+
create: (context) => create(classes, context),
|
|
234
|
+
save: (options) => save(classes, options),
|
|
235
|
+
createMany: (count, context) => createMany(classes, {
|
|
232
236
|
count,
|
|
233
237
|
...context
|
|
234
238
|
}),
|
|
235
|
-
saveMany: (count, options) =>
|
|
239
|
+
saveMany: (count, options) => saveMany(classes, {
|
|
236
240
|
count,
|
|
237
241
|
...options
|
|
238
242
|
})
|
|
@@ -240,13 +244,13 @@ function seed(classOrClasses) {
|
|
|
240
244
|
}
|
|
241
245
|
const EntityClass = classOrClasses;
|
|
242
246
|
return {
|
|
243
|
-
create: (
|
|
244
|
-
save: (options) =>
|
|
245
|
-
createMany: (count,
|
|
247
|
+
create: (options) => create(EntityClass, options),
|
|
248
|
+
save: (options) => save(EntityClass, options),
|
|
249
|
+
createMany: (count, options) => createMany(EntityClass, {
|
|
246
250
|
count,
|
|
247
|
-
...
|
|
251
|
+
...options
|
|
248
252
|
}),
|
|
249
|
-
saveMany: (count, options) =>
|
|
253
|
+
saveMany: (count, options) => saveMany(EntityClass, {
|
|
250
254
|
count,
|
|
251
255
|
...options
|
|
252
256
|
})
|
|
@@ -357,11 +361,11 @@ async function runSeeders(seeders, options = {}) {
|
|
|
357
361
|
//#endregion
|
|
358
362
|
exports.Seed = Seed;
|
|
359
363
|
exports.Seeder = Seeder;
|
|
360
|
-
exports.
|
|
361
|
-
exports.
|
|
364
|
+
exports.create = create;
|
|
365
|
+
exports.createMany = createMany;
|
|
362
366
|
exports.runSeeders = runSeeders;
|
|
363
|
-
exports.
|
|
364
|
-
exports.
|
|
367
|
+
exports.save = save;
|
|
368
|
+
exports.saveMany = saveMany;
|
|
365
369
|
exports.seed = seed;
|
|
366
370
|
|
|
367
371
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -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 * @example\n * @Seed(() => faker.date.past())\n * beginDate!: Date\n *\n * @Seed((_, self) => faker.date.future({ refDate: (self as MyEntity).beginDate }))\n * endDate!: Date\n */\nexport type SeedFactory<T = unknown> = (\n context: SeedContext,\n self: EntityInstance,\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(factory: SeedFactory): PropertyDecorator;\n/** Marks a property with a factory callback and additional options. */\nexport function Seed(factory: SeedFactory, options: SeedOptions): 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 { getSeeds } from './registry.js';\nimport type {\n EntityConstructor,\n EntityInstance,\n MapToInstanceArrays,\n MapToInstances,\n SeedContext,\n} from './registry.js';\n\n/** Options for {@link createManySeed}. Extends {@link SeedContext} with a required instance count. */\nexport interface CreateManySeedOptions extends SeedContext {\n count: number;\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 createOneSeed<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 createOneSeed(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 createManySeed(RelatedClass, {\n count: options.count ?? 1,\n ...childContext,\n });\n } else {\n record[propertyKey] = await createOneSeed(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 createSeed<T extends EntityInstance>(\n EntityClass: EntityConstructor<T>,\n context?: SeedContext,\n): Promise<T>;\nexport async function createSeed<T extends readonly EntityConstructor[]>(\n EntityClasses: [...T],\n context?: SeedContext,\n): Promise<MapToInstances<T>>;\nexport async function createSeed<T extends EntityInstance>(\n classOrClasses: EntityConstructor<T> | readonly EntityConstructor[],\n context: SeedContext = {},\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) => createOneSeed(cls, effectiveContext)),\n )) as EntityInstance[];\n }\n\n const [entity] = await createManySeed(classOrClasses as EntityConstructor<T>, {\n count: 1,\n ...context,\n });\n\n return entity!;\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 createManySeed<T extends EntityInstance>(\n EntityClass: EntityConstructor<T>,\n options: CreateManySeedOptions,\n): Promise<T[]>;\nexport async function createManySeed<T extends readonly EntityConstructor[]>(\n EntityClasses: [...T],\n options: CreateManySeedOptions,\n): Promise<MapToInstanceArrays<T>>;\nexport async function createManySeed<T extends EntityInstance>(\n classOrClasses: EntityConstructor<T> | readonly EntityConstructor[],\n { count, ...context }: CreateManySeedOptions,\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 }, () => createOneSeed(cls, effectiveContext))),\n ),\n )) as EntityInstance[][];\n }\n\n return await Promise.all(\n Array.from({ length: count }, () =>\n createOneSeed(classOrClasses as EntityConstructor<T>, context),\n ),\n );\n}\n","import { type DataSource } from 'typeorm';\n\nimport { createManySeed } from './creator.js';\nimport type {\n EntityConstructor,\n EntityInstance,\n MapToInstanceArrays,\n MapToInstances,\n SeedContext,\n} from './registry.js';\n\n/** Options for {@link saveSeed}. Extends {@link SeedContext} with a required DataSource. */\nexport interface SaveSeedOptions extends SeedContext {\n dataSource: DataSource;\n}\n\n/** Options for {@link saveManySeed}. Extends {@link SaveSeedOptions} with a required instance count. */\nexport interface SaveManySeedOptions extends SaveSeedOptions {\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 * Delegates to {@link saveManySeed} with `count: 1` and unwraps the result.\n */\nexport async function saveSeed<T extends EntityInstance>(\n EntityClass: EntityConstructor<T>,\n options: SaveSeedOptions,\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 saveSeed<T extends readonly EntityConstructor[]>(\n EntityClasses: [...T],\n options: SaveSeedOptions,\n): Promise<MapToInstances<T>>;\nexport async function saveSeed<T extends EntityInstance>(\n classOrClasses: EntityConstructor<T> | readonly EntityConstructor[],\n options: SaveSeedOptions,\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 saveManySeed(cls, effectiveOptions).then(([entity]) => entity!),\n ),\n )) as EntityInstance[];\n }\n\n const [entity] = await saveManySeed(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 saveSeed} for each entity.\n */\nexport async function saveManySeed<T extends EntityInstance>(\n EntityClass: EntityConstructor<T>,\n options: SaveManySeedOptions,\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 saveManySeed<T extends readonly EntityConstructor[]>(\n EntityClasses: [...T],\n options: SaveManySeedOptions,\n): Promise<MapToInstanceArrays<T>>;\nexport async function saveManySeed<T extends EntityInstance>(\n classOrClasses: EntityConstructor<T> | readonly EntityConstructor[],\n options: SaveManySeedOptions,\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) => saveManySeedOne(cls, effectiveOptions)),\n )) as EntityInstance[][];\n }\n\n return await saveManySeedOne(classOrClasses as EntityConstructor<T>, options);\n}\n\n/**\n * Creates and persists `count` instances of a single entity class.\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 saveManySeedOne<T extends EntityInstance>(\n EntityClass: EntityConstructor<T>,\n options: SaveManySeedOptions,\n): Promise<T[]> {\n const { count, dataSource } = options;\n\n if (count === 0) {\n return [];\n }\n\n const entities = await createManySeed(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 { createManySeed, createSeed } from './creator.js';\nimport { saveManySeed, saveSeed } from './persist.js';\nimport type {\n EntityConstructor,\n EntityInstance,\n MapToInstanceArrays,\n MapToInstances,\n SeedContext,\n} from './registry.js';\nimport type { SaveSeedOptions } from './persist.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?: SeedContext): Promise<T>;\n /** Creates and persists a single instance. */\n save(options: SaveSeedOptions): Promise<T>;\n /** Creates multiple instances in memory without persisting. */\n createMany(count: number, context?: SeedContext): Promise<T[]>;\n /** Creates and persists multiple instances. */\n saveMany(count: number, options: SaveSeedOptions): 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: SaveSeedOptions): 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: SaveSeedOptions): 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 createSeed(classes as [...typeof classes], context) as Promise<\n MapToInstances<typeof classes>\n >,\n save: (options: SaveSeedOptions) =>\n saveSeed(classes as [...typeof classes], options) as Promise<\n MapToInstances<typeof classes>\n >,\n createMany: (count: number, context?: SeedContext) =>\n createManySeed(classes as [...typeof classes], { count, ...context }) as Promise<\n MapToInstanceArrays<typeof classes>\n >,\n saveMany: (count: number, options: SaveSeedOptions) =>\n saveManySeed(classes as [...typeof classes], { count, ...options }) as Promise<\n MapToInstanceArrays<typeof classes>\n >,\n };\n }\n\n const EntityClass = classOrClasses as EntityConstructor<T>;\n\n return {\n create: (context?: SeedContext) => createSeed(EntityClass, context),\n save: (options: SaveSeedOptions) => saveSeed(EntityClass, options),\n createMany: (count: number, context?: SeedContext) =>\n createManySeed(EntityClass, { count, ...context }),\n saveMany: (count: number, options: SaveSeedOptions) =>\n saveManySeed(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} 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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"}
|