@anil-labs/factory 0.1.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.
Files changed (98) hide show
  1. package/CHANGELOG.md +54 -0
  2. package/LICENSE +21 -0
  3. package/README.md +371 -0
  4. package/dist/builders/index.d.cts +40 -0
  5. package/dist/builders/index.d.ts +40 -0
  6. package/dist/chunks/faker-BOtDMmjd.cjs +1430 -0
  7. package/dist/chunks/faker-BOtDMmjd.cjs.map +1 -0
  8. package/dist/chunks/faker-BlEhpR26.mjs +1287 -0
  9. package/dist/chunks/faker-BlEhpR26.mjs.map +1 -0
  10. package/dist/chunks/persist-DcARfeC-.cjs +134 -0
  11. package/dist/chunks/persist-DcARfeC-.cjs.map +1 -0
  12. package/dist/chunks/persist-ZGX3NWMF.mjs +117 -0
  13. package/dist/chunks/persist-ZGX3NWMF.mjs.map +1 -0
  14. package/dist/core/collection.d.cts +41 -0
  15. package/dist/core/collection.d.ts +41 -0
  16. package/dist/core/factory.d.cts +115 -0
  17. package/dist/core/factory.d.ts +115 -0
  18. package/dist/core/index.d.cts +6 -0
  19. package/dist/core/index.d.ts +6 -0
  20. package/dist/core/registry.d.cts +20 -0
  21. package/dist/core/registry.d.ts +20 -0
  22. package/dist/core/sequence.d.cts +36 -0
  23. package/dist/core/sequence.d.ts +36 -0
  24. package/dist/core/types.d.cts +47 -0
  25. package/dist/core/types.d.ts +47 -0
  26. package/dist/faker/color.d.cts +22 -0
  27. package/dist/faker/color.d.ts +22 -0
  28. package/dist/faker/commerce.d.cts +21 -0
  29. package/dist/faker/commerce.d.ts +21 -0
  30. package/dist/faker/company.d.cts +20 -0
  31. package/dist/faker/company.d.ts +20 -0
  32. package/dist/faker/datatype.d.cts +16 -0
  33. package/dist/faker/datatype.d.ts +16 -0
  34. package/dist/faker/date.d.cts +29 -0
  35. package/dist/faker/date.d.ts +29 -0
  36. package/dist/faker/faker.d.cts +82 -0
  37. package/dist/faker/faker.d.ts +82 -0
  38. package/dist/faker/finance.d.cts +25 -0
  39. package/dist/faker/finance.d.ts +25 -0
  40. package/dist/faker/helpers.d.cts +52 -0
  41. package/dist/faker/helpers.d.ts +52 -0
  42. package/dist/faker/image.d.cts +22 -0
  43. package/dist/faker/image.d.ts +22 -0
  44. package/dist/faker/index.d.cts +21 -0
  45. package/dist/faker/index.d.ts +21 -0
  46. package/dist/faker/internet.d.cts +33 -0
  47. package/dist/faker/internet.d.ts +33 -0
  48. package/dist/faker/locale.d.cts +26 -0
  49. package/dist/faker/locale.d.ts +26 -0
  50. package/dist/faker/location.d.cts +30 -0
  51. package/dist/faker/location.d.ts +30 -0
  52. package/dist/faker/lorem.d.cts +26 -0
  53. package/dist/faker/lorem.d.ts +26 -0
  54. package/dist/faker/number.d.cts +31 -0
  55. package/dist/faker/number.d.ts +31 -0
  56. package/dist/faker/person.d.cts +29 -0
  57. package/dist/faker/person.d.ts +29 -0
  58. package/dist/faker/regex.d.cts +19 -0
  59. package/dist/faker/regex.d.ts +19 -0
  60. package/dist/faker/string.d.cts +33 -0
  61. package/dist/faker/string.d.ts +33 -0
  62. package/dist/faker/system.d.cts +29 -0
  63. package/dist/faker/system.d.ts +29 -0
  64. package/dist/faker.cjs +26 -0
  65. package/dist/faker.mjs +3 -0
  66. package/dist/index.cjs +635 -0
  67. package/dist/index.cjs.map +1 -0
  68. package/dist/index.d.cts +37 -0
  69. package/dist/index.d.ts +37 -0
  70. package/dist/index.mjs +596 -0
  71. package/dist/index.mjs.map +1 -0
  72. package/dist/locales/en.cjs +351 -0
  73. package/dist/locales/en.cjs.map +1 -0
  74. package/dist/locales/en.d.cts +11 -0
  75. package/dist/locales/en.d.ts +11 -0
  76. package/dist/locales/en.mjs +350 -0
  77. package/dist/locales/en.mjs.map +1 -0
  78. package/dist/locales/types.d.cts +30 -0
  79. package/dist/locales/types.d.ts +30 -0
  80. package/dist/persist/console.d.cts +15 -0
  81. package/dist/persist/console.d.ts +15 -0
  82. package/dist/persist/http.d.cts +42 -0
  83. package/dist/persist/http.d.ts +42 -0
  84. package/dist/persist/index.d.cts +5 -0
  85. package/dist/persist/index.d.ts +5 -0
  86. package/dist/persist/memory.d.cts +26 -0
  87. package/dist/persist/memory.d.ts +26 -0
  88. package/dist/persist.cjs +5 -0
  89. package/dist/persist.mjs +2 -0
  90. package/dist/prng/index.d.cts +5 -0
  91. package/dist/prng/index.d.ts +5 -0
  92. package/dist/prng/mulberry32.d.cts +19 -0
  93. package/dist/prng/mulberry32.d.ts +19 -0
  94. package/dist/prng/types.d.cts +23 -0
  95. package/dist/prng/types.d.ts +23 -0
  96. package/dist/snapshot/index.d.cts +16 -0
  97. package/dist/snapshot/index.d.ts +16 -0
  98. package/package.json +136 -0
package/dist/index.cjs ADDED
@@ -0,0 +1,635 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_faker = require("./chunks/faker-BOtDMmjd.cjs");
3
+ const require_locales_en = require("./locales/en.cjs");
4
+ const require_persist = require("./chunks/persist-DcARfeC-.cjs");
5
+ //#region src/core/collection.ts
6
+ /**
7
+ * Immutable iterable wrapper around an array, with Laravel-style helpers.
8
+ *
9
+ * @example
10
+ * ```ts
11
+ * const users = new Collection(userArray)
12
+ * users.where(u => u.active).count()
13
+ * users.pluck('email').toArray()
14
+ * for (const u of users) console.log(u.name)
15
+ * ```
16
+ */
17
+ var Collection = class Collection {
18
+ /** Underlying frozen items. */
19
+ items;
20
+ constructor(items = []) {
21
+ this.items = Object.freeze([...items]);
22
+ }
23
+ /** Number of items. */
24
+ count() {
25
+ return this.items.length;
26
+ }
27
+ /** True when there are no items. */
28
+ isEmpty() {
29
+ return this.items.length === 0;
30
+ }
31
+ /** Run `fn` for each item; returns the collection for chaining. */
32
+ each(fn) {
33
+ this.items.forEach(fn);
34
+ return this;
35
+ }
36
+ /** Project to a new collection via `fn`. */
37
+ map(fn) {
38
+ return new Collection(this.items.map(fn));
39
+ }
40
+ /** Pluck a single field across all items. */
41
+ pluck(key) {
42
+ return new Collection(this.items.map((item) => item[key]));
43
+ }
44
+ /** Filter to items matching `predicate`. */
45
+ where(predicate) {
46
+ return new Collection(this.items.filter(predicate));
47
+ }
48
+ /** First item matching predicate (or first overall if no predicate). */
49
+ first(predicate) {
50
+ if (!predicate) return this.items[0];
51
+ return this.items.find(predicate);
52
+ }
53
+ /** Last item in the collection. */
54
+ last() {
55
+ return this.items[this.items.length - 1];
56
+ }
57
+ /** Sort by a key or comparator, returning a new collection. */
58
+ sortBy(key, direction = "asc") {
59
+ return new Collection([...this.items].sort((a, b) => {
60
+ const av = a[key];
61
+ const bv = b[key];
62
+ if (av === bv) return 0;
63
+ const cmp = av < bv ? -1 : 1;
64
+ return direction === "asc" ? cmp : -cmp;
65
+ }));
66
+ }
67
+ /** Group items into a `Map` keyed by `fn`. */
68
+ groupBy(fn) {
69
+ const out = /* @__PURE__ */ new Map();
70
+ for (const item of this.items) {
71
+ const key = fn(item);
72
+ const bucket = out.get(key);
73
+ if (bucket) bucket.push(item);
74
+ else out.set(key, [item]);
75
+ }
76
+ return out;
77
+ }
78
+ /** Reduce to a single value. */
79
+ reduce(fn, initial) {
80
+ return this.items.reduce(fn, initial);
81
+ }
82
+ /** Plain-array view (a copy — the collection's storage is frozen). */
83
+ toArray() {
84
+ return [...this.items];
85
+ }
86
+ [Symbol.iterator]() {
87
+ return this.items[Symbol.iterator]();
88
+ }
89
+ };
90
+ //#endregion
91
+ //#region src/core/sequence.ts
92
+ /**
93
+ * Cycle through a list of attribute patches across generated items.
94
+ *
95
+ * @example
96
+ * ```ts
97
+ * factory.sequence([{ role: 'admin' }, { role: 'editor' }]).count(4).make()
98
+ * // → admin, editor, admin, editor
99
+ *
100
+ * factory.sequence([({ index }) => ({ name: `User ${index}` })]).count(3).make()
101
+ * // → User 0, User 1, User 2
102
+ * ```
103
+ */
104
+ var Sequence = class Sequence {
105
+ cursor = 0;
106
+ entries;
107
+ constructor(entries) {
108
+ if (entries.length === 0) throw new Error("[Sequence] At least one entry is required.");
109
+ this.entries = [...entries];
110
+ }
111
+ /** Resolve the next patch, cycling when exhausted. */
112
+ next() {
113
+ const entry = this.entries[this.cursor % this.entries.length] ?? (() => {
114
+ throw new Error("[Sequence] unreachable: empty entries");
115
+ })();
116
+ const info = {
117
+ index: this.cursor,
118
+ count: this.cursor + 1
119
+ };
120
+ this.cursor++;
121
+ return typeof entry === "function" ? entry(info) : entry;
122
+ }
123
+ /** Reset the cursor to 0. */
124
+ reset() {
125
+ this.cursor = 0;
126
+ return this;
127
+ }
128
+ /** Current cursor position (zero-based). */
129
+ get currentIndex() {
130
+ return this.cursor;
131
+ }
132
+ /** Return a fresh sequence with the same entries but cursor reset. */
133
+ clone() {
134
+ return new Sequence([...this.entries]);
135
+ }
136
+ };
137
+ /** Functional shorthand for `new Sequence(entries)`. */
138
+ function sequence(entries) {
139
+ return new Sequence(entries);
140
+ }
141
+ //#endregion
142
+ //#region src/core/factory.ts
143
+ /**
144
+ * Laravel-inspired model factory for TypeScript. Immutable fluent chain — every
145
+ * method returns a new factory, never mutating the original.
146
+ *
147
+ * @example
148
+ * ```ts
149
+ * interface User { id: number; name: string; email: string; active: boolean }
150
+ *
151
+ * const UserFactory = defineFactory<User>(({ seq, faker }) => ({
152
+ * id: seq,
153
+ * name: faker.person.fullName(),
154
+ * email: faker.internet.email(),
155
+ * active: true,
156
+ * }))
157
+ * .state('admin', { role: 'admin' })
158
+ * .state('inactive', { active: false })
159
+ *
160
+ * UserFactory.make() // single User
161
+ * UserFactory.count(5).make() // User[]
162
+ * UserFactory.state('admin').make() // with admin overrides
163
+ * await UserFactory.persist(...).create()
164
+ * ```
165
+ */
166
+ var Factory = class Factory {
167
+ /** @internal */ definition;
168
+ /** @internal */ internals;
169
+ /** @internal — use {@link defineFactory} or {@link Factory.define} instead. */
170
+ constructor(definition, internals) {
171
+ this.definition = definition;
172
+ this.internals = internals;
173
+ }
174
+ /** Create a new factory. Mirrors Laravel's `Factory::new()`. */
175
+ static define(definition, persist) {
176
+ return new Factory(definition, {
177
+ faker: require_faker.faker,
178
+ count: 1,
179
+ overrides: {},
180
+ states: /* @__PURE__ */ new Map(),
181
+ activeStates: [],
182
+ sequences: [],
183
+ fieldSequences: /* @__PURE__ */ new Map(),
184
+ afterMaking: [],
185
+ afterCreating: [],
186
+ hasRelations: [],
187
+ hasAttachedRelations: [],
188
+ recycle: /* @__PURE__ */ new Map(),
189
+ persist: persist ?? null,
190
+ ownsFaker: false
191
+ });
192
+ }
193
+ /** Internal: build a copy with a single field replaced. */
194
+ clone(patch) {
195
+ const next = {
196
+ faker: this.internals.faker,
197
+ count: this.internals.count,
198
+ overrides: this.internals.overrides,
199
+ states: new Map(this.internals.states),
200
+ activeStates: [...this.internals.activeStates],
201
+ sequences: this.internals.sequences.map((s) => s.clone()),
202
+ fieldSequences: new Map(this.internals.fieldSequences),
203
+ afterMaking: [...this.internals.afterMaking],
204
+ afterCreating: [...this.internals.afterCreating],
205
+ hasRelations: [...this.internals.hasRelations],
206
+ hasAttachedRelations: [...this.internals.hasAttachedRelations],
207
+ recycle: new Map(this.internals.recycle),
208
+ persist: this.internals.persist,
209
+ ownsFaker: this.internals.ownsFaker,
210
+ ...patch
211
+ };
212
+ return new Factory(this.definition, next);
213
+ }
214
+ /** Set how many items will be built on the next terminal call. */
215
+ count(n) {
216
+ if (!Number.isInteger(n) || n < 0) throw new Error(`[Factory] count(n): expected a non-negative integer, got ${String(n)}.`);
217
+ return this.clone({ count: n });
218
+ }
219
+ /** Alias of {@link count} — matches Laravel's `->times()`. */
220
+ times(n) {
221
+ return this.count(n);
222
+ }
223
+ /** Merge inline overrides into every built item. */
224
+ with(overrides) {
225
+ return this.clone({ overrides: {
226
+ ...this.internals.overrides,
227
+ ...overrides
228
+ } });
229
+ }
230
+ /**
231
+ * Register a named state OR activate a previously-registered state.
232
+ *
233
+ * - Two-arg form (`state(name, value)`) **registers** the state.
234
+ * - One-arg form (`state(name)`) **activates** it.
235
+ * - One-arg with a Sequence (`state(seq)`) attaches a sequence as a state.
236
+ */
237
+ state(arg1, value) {
238
+ if (arg1 instanceof Sequence) return this.clone({ sequences: [...this.internals.sequences, arg1.clone()] });
239
+ if (value !== void 0) {
240
+ const states = new Map(this.internals.states);
241
+ states.set(arg1, value);
242
+ return this.clone({ states });
243
+ }
244
+ if (!this.internals.states.has(arg1)) throw new Error(`[Factory] Unknown state "${arg1}". Register it first via .state("${arg1}", ...).`);
245
+ return this.clone({ activeStates: [...this.internals.activeStates, arg1] });
246
+ }
247
+ /** Bulk-register multiple states. */
248
+ states(map) {
249
+ const states = new Map(this.internals.states);
250
+ for (const [name, value] of Object.entries(map)) states.set(name, value);
251
+ return this.clone({ states });
252
+ }
253
+ /** Cycle values through one field across generated items. */
254
+ fieldSequence(field, values) {
255
+ const fieldSequences = new Map(this.internals.fieldSequences);
256
+ fieldSequences.set(field, values);
257
+ return this.clone({ fieldSequences });
258
+ }
259
+ /** Attach a sequence of attribute patches. */
260
+ sequence(entries) {
261
+ const seq = new Sequence(entries);
262
+ return this.clone({ sequences: [...this.internals.sequences, seq] });
263
+ }
264
+ /** Attach child records under `key` (one-to-many). */
265
+ has(childFactory, key) {
266
+ return this.clone({ hasRelations: [...this.internals.hasRelations, {
267
+ kind: "has",
268
+ factory: childFactory,
269
+ count: childFactory.internals.count,
270
+ key
271
+ }] });
272
+ }
273
+ /**
274
+ * Set a foreign-key field by either resolving from another factory
275
+ * (eager — built once), a plain object (used directly), or a lazy callback
276
+ * (built per-item).
277
+ */
278
+ for(parent, foreignKey, resolver) {
279
+ let resolved;
280
+ if (typeof parent === "function") resolved = parent();
281
+ else if (parent instanceof Factory) resolved = parent.makeOne();
282
+ else resolved = parent;
283
+ const patch = resolver ? resolver(resolved) : { [foreignKey]: resolved["id"] };
284
+ return this.with(patch);
285
+ }
286
+ /** Attach related records with pivot/intermediate data (many-to-many). */
287
+ hasAttached(childFactory, key, pivot = {}) {
288
+ return this.clone({ hasAttachedRelations: [...this.internals.hasAttachedRelations, {
289
+ kind: "hasAttached",
290
+ factory: childFactory,
291
+ count: childFactory.internals.count,
292
+ key,
293
+ pivot
294
+ }] });
295
+ }
296
+ /** Add models to the recycle pool keyed by `key`. */
297
+ recycle(models, key) {
298
+ const list = Array.isArray(models) ? models : [models];
299
+ const next = new Map(this.internals.recycle);
300
+ next.set(key, list);
301
+ return this.clone({ recycle: next });
302
+ }
303
+ /** Pick a random recycled model from `key`, or undefined. */
304
+ getRecycled(key) {
305
+ const pool = this.internals.recycle.get(key);
306
+ if (!pool || pool.length === 0) return void 0;
307
+ return pool[this.internals.faker.rawPrng().int(0, pool.length - 1)];
308
+ }
309
+ /** Register a hook fired after each item is built. */
310
+ afterMaking(fn) {
311
+ return this.clone({ afterMaking: [...this.internals.afterMaking, fn] });
312
+ }
313
+ /** Register a hook fired after each item is persisted via `create()`. */
314
+ afterCreating(fn) {
315
+ return this.clone({ afterCreating: [...this.internals.afterCreating, fn] });
316
+ }
317
+ /** Set or replace the persistence callback used by `create()`. */
318
+ persist(fn) {
319
+ return this.clone({ persist: fn });
320
+ }
321
+ /**
322
+ * Bind this factory to its own private `Faker` instance, seeded as given.
323
+ * Useful when one factory in a suite must be deterministic without
324
+ * affecting the shared default faker.
325
+ */
326
+ seed(seed) {
327
+ const own = new require_faker.Faker({ seed });
328
+ return this.clone({
329
+ faker: own,
330
+ ownsFaker: true
331
+ });
332
+ }
333
+ /** Set the locale on this factory's faker (creates one if it was shared). */
334
+ locale(name) {
335
+ const own = this.internals.ownsFaker ? this.internals.faker : new require_faker.Faker({ seed: this.internals.faker.currentSeed() });
336
+ own.locale(name);
337
+ return this.clone({
338
+ faker: own,
339
+ ownsFaker: true
340
+ });
341
+ }
342
+ /** Build a single item (ignoring `count`). */
343
+ makeOne() {
344
+ const item = this.buildOne(0);
345
+ this.fireAfterMakingSync([item]);
346
+ return item;
347
+ }
348
+ /** Build `count` items. */
349
+ makeMany() {
350
+ const items = this.buildMany();
351
+ this.fireAfterMakingSync(items);
352
+ return items;
353
+ }
354
+ /**
355
+ * Build — single item when `count === 1`, array otherwise.
356
+ * Use {@link makeOne} / {@link makeMany} when you need a specific shape.
357
+ */
358
+ make() {
359
+ return this.internals.count === 1 ? this.makeOne() : this.makeMany();
360
+ }
361
+ /** Raw attribute objects with the same shape as `make()`. */
362
+ raw() {
363
+ return this.make();
364
+ }
365
+ /** Build and return as a {@link Collection}. */
366
+ collect() {
367
+ return new Collection(this.makeMany());
368
+ }
369
+ /**
370
+ * Build and persist via the registered persistence callback.
371
+ * Returns single item when `count === 1`, array otherwise.
372
+ */
373
+ async create() {
374
+ const persist = this.internals.persist;
375
+ if (!persist) throw new Error("[Factory] create(): no persistence callback registered. Use .persist(fn) or pass one to defineFactory().");
376
+ const items = this.buildMany();
377
+ await this.runHooks(items, this.internals.afterMaking);
378
+ const persisted = await Promise.all(items.map((item) => Promise.resolve(persist(item))));
379
+ await this.runHooks(persisted, this.internals.afterCreating);
380
+ return this.internals.count === 1 ? persisted[0] : persisted;
381
+ }
382
+ /** Always-array variant of {@link create}. */
383
+ async createMany() {
384
+ const result = await this.create();
385
+ return Array.isArray(result) ? result : [result];
386
+ }
387
+ buildOne(index) {
388
+ const ctx = {
389
+ seq: index + 1,
390
+ faker: this.internals.faker
391
+ };
392
+ let item = this.definition(ctx);
393
+ for (const stateName of this.internals.activeStates) {
394
+ const state = this.internals.states.get(stateName);
395
+ if (!state) continue;
396
+ item = {
397
+ ...item,
398
+ ...typeof state === "function" ? state(item, ctx) : state
399
+ };
400
+ }
401
+ for (const sequence of this.internals.sequences) item = {
402
+ ...item,
403
+ ...sequence.next()
404
+ };
405
+ for (const [field, values] of this.internals.fieldSequences) {
406
+ const value = values[index % values.length];
407
+ item = {
408
+ ...item,
409
+ [field]: value
410
+ };
411
+ }
412
+ item = {
413
+ ...item,
414
+ ...this.internals.overrides
415
+ };
416
+ for (const rel of this.internals.hasRelations) {
417
+ const children = rel.factory.count(rel.count).make();
418
+ const arr = Array.isArray(children) ? children : [children];
419
+ item = {
420
+ ...item,
421
+ [rel.key]: arr
422
+ };
423
+ }
424
+ for (const rel of this.internals.hasAttachedRelations) {
425
+ const children = rel.factory.count(rel.count).make();
426
+ const withPivot = (Array.isArray(children) ? children : [children]).map((child) => {
427
+ const pivotData = typeof rel.pivot === "function" ? rel.pivot(item, child) : rel.pivot;
428
+ return {
429
+ ...child,
430
+ pivot: pivotData
431
+ };
432
+ });
433
+ item = {
434
+ ...item,
435
+ [rel.key]: withPivot
436
+ };
437
+ }
438
+ return item;
439
+ }
440
+ buildMany() {
441
+ const out = [];
442
+ for (let i = 0; i < this.internals.count; i++) out.push(this.buildOne(i));
443
+ return out;
444
+ }
445
+ /**
446
+ * Fire afterMaking hooks for the sync build path (`make`/`makeOne`/`makeMany`/
447
+ * `collect`). Async hooks are kicked off without awaiting — use {@link create}
448
+ * if you need guaranteed sequencing.
449
+ */
450
+ fireAfterMakingSync(items) {
451
+ for (let i = 0; i < items.length; i++) {
452
+ const item = items[i];
453
+ if (item === void 0) continue;
454
+ for (const hook of this.internals.afterMaking) {
455
+ const r = hook(item, i);
456
+ if (r instanceof Promise) r.catch(swallow);
457
+ }
458
+ }
459
+ }
460
+ async runHooks(items, hooks) {
461
+ for (let i = 0; i < items.length; i++) {
462
+ const item = items[i];
463
+ if (item === void 0) continue;
464
+ for (const hook of hooks) await hook(item, i);
465
+ }
466
+ }
467
+ };
468
+ function swallow() {}
469
+ /** Functional alias for `Factory.define()`. */
470
+ function defineFactory(definition, persist) {
471
+ return Factory.define(definition, persist);
472
+ }
473
+ //#endregion
474
+ //#region src/core/registry.ts
475
+ /**
476
+ * Process-global registry that lets you look up factories by name.
477
+ * Mirrors how Laravel resolves `UserFactory` from `User::factory()`.
478
+ *
479
+ * @example
480
+ * ```ts
481
+ * FactoryRegistry.register('User', UserFactory)
482
+ * const f = FactoryRegistry.resolve<User>('User')
483
+ * f.count(5).make()
484
+ * ```
485
+ */
486
+ var FactoryRegistry = {
487
+ register(name, factory) {
488
+ registry.set(name, factory);
489
+ },
490
+ resolve(name) {
491
+ const f = registry.get(name);
492
+ if (!f) throw new Error(`[FactoryRegistry] No factory registered as "${name}". Registered: ${[...registry.keys()].join(", ")}`);
493
+ return f;
494
+ },
495
+ has(name) {
496
+ return registry.has(name);
497
+ },
498
+ unregister(name) {
499
+ return registry.delete(name);
500
+ },
501
+ clear() {
502
+ registry.clear();
503
+ },
504
+ names() {
505
+ return [...registry.keys()];
506
+ }
507
+ };
508
+ var registry = /* @__PURE__ */ new Map();
509
+ //#endregion
510
+ //#region src/builders/index.ts
511
+ /**
512
+ * Pick one value from `choices` at call time. Reads from the default faker.
513
+ * Use inside factory definitions to express "any of these".
514
+ *
515
+ * @example
516
+ * ```ts
517
+ * defineFactory<User>(({ faker }) => ({
518
+ * role: oneOf(['admin', 'editor', 'viewer']),
519
+ * }))
520
+ * ```
521
+ */
522
+ function oneOf(choices) {
523
+ return require_faker.faker.helpers.arrayElement(choices);
524
+ }
525
+ /**
526
+ * Return `value` with probability `chance`, else `undefined`. Useful for
527
+ * optional fields.
528
+ *
529
+ * @example
530
+ * ```ts
531
+ * { bio: maybe(faker.lorem.sentence(), 0.6) }
532
+ * ```
533
+ */
534
+ function maybe(value, chance = .5) {
535
+ return require_faker.faker.helpers.maybe(value, chance);
536
+ }
537
+ /**
538
+ * Build an array of length `[min, max]` (inclusive) by calling `fn(index)`.
539
+ * If only `min` is given, the length is exactly `min`.
540
+ *
541
+ * @example
542
+ * ```ts
543
+ * { tags: array(2, 5, () => faker.lorem.word()) }
544
+ * ```
545
+ */
546
+ function array(min, maxOrFn, fn) {
547
+ if (typeof maxOrFn === "function") return Array.from({ length: min }, (_, i) => maxOrFn(i));
548
+ if (!fn) throw new Error("[builders] array(min, max, fn): missing builder function.");
549
+ const length = require_faker.faker.helpers.arrayElement(Array.from({ length: maxOrFn - min + 1 }, (_, i) => min + i));
550
+ return Array.from({ length }, (_, i) => fn(i));
551
+ }
552
+ /**
553
+ * Defer evaluation until the value is actually read. Inside factory
554
+ * definitions you rarely need this (the definition is a function already),
555
+ * but it's useful for sequence entries and state values.
556
+ */
557
+ function lazy(fn) {
558
+ return { resolve: fn };
559
+ }
560
+ //#endregion
561
+ //#region src/snapshot/index.ts
562
+ /**
563
+ * Snapshot helpers.
564
+ *
565
+ * The package doesn't write files itself — it just normalises payloads so
566
+ * test runners (vitest, jest) can snapshot them deterministically.
567
+ *
568
+ * @example
569
+ * ```ts
570
+ * import { snapshot } from '@anil-labs/factory'
571
+ *
572
+ * const items = UserFactory.seed(42).count(3).make()
573
+ * expect(snapshot(items)).toMatchSnapshot()
574
+ * ```
575
+ */
576
+ /** Recursively normalise dates, undefineds, and key order so snapshots are stable. */
577
+ function snapshot(value) {
578
+ return normalise(value);
579
+ }
580
+ function normalise(value) {
581
+ if (value === null || value === void 0) return value;
582
+ if (value instanceof Date) return {
583
+ __type: "Date",
584
+ value: value.toISOString()
585
+ };
586
+ if (Array.isArray(value)) return value.map(normalise);
587
+ if (typeof value === "object") {
588
+ const out = {};
589
+ for (const key of Object.keys(value).sort()) out[key] = normalise(value[key]);
590
+ return out;
591
+ }
592
+ return value;
593
+ }
594
+ //#endregion
595
+ exports.Collection = Collection;
596
+ exports.Color = require_faker.Color;
597
+ exports.Commerce = require_faker.Commerce;
598
+ exports.Company = require_faker.Company;
599
+ exports.Datatype = require_faker.Datatype;
600
+ exports.DateGen = require_faker.DateGen;
601
+ exports.Factory = Factory;
602
+ exports.FactoryRegistry = FactoryRegistry;
603
+ exports.Faker = require_faker.Faker;
604
+ exports.Finance = require_faker.Finance;
605
+ exports.Helpers = require_faker.Helpers;
606
+ exports.Image = require_faker.Image;
607
+ exports.Internet = require_faker.Internet;
608
+ exports.LocaleRef = require_faker.LocaleRef;
609
+ exports.Location = require_faker.Location;
610
+ exports.Lorem = require_faker.Lorem;
611
+ exports.Mulberry32 = require_faker.Mulberry32;
612
+ exports.NumberGen = require_faker.NumberGen;
613
+ exports.Person = require_faker.Person;
614
+ exports.Sequence = Sequence;
615
+ exports.StringGen = require_faker.StringGen;
616
+ exports.System = require_faker.System;
617
+ exports.array = array;
618
+ exports.consolePersist = require_persist.consolePersist;
619
+ exports.createPrng = require_faker.createPrng;
620
+ exports.defineFactory = defineFactory;
621
+ exports.en = require_locales_en.en;
622
+ exports.faker = require_faker.faker;
623
+ exports.generateFromRegex = require_faker.generateFromRegex;
624
+ exports.getLocale = require_faker.getLocale;
625
+ exports.httpPersist = require_persist.httpPersist;
626
+ exports.lazy = lazy;
627
+ exports.listLocales = require_faker.listLocales;
628
+ exports.maybe = maybe;
629
+ exports.memoryPersist = require_persist.memoryPersist;
630
+ exports.oneOf = oneOf;
631
+ exports.registerLocale = require_faker.registerLocale;
632
+ exports.sequence = sequence;
633
+ exports.snapshot = snapshot;
634
+
635
+ //# sourceMappingURL=index.cjs.map