velocious 1.0.552 → 1.0.555

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 (117) hide show
  1. package/README.md +2 -0
  2. package/build/background-jobs/status-reporter.js +15 -2
  3. package/build/background-jobs/worker.js +5 -1
  4. package/build/frontend-models/base.js +105 -47
  5. package/build/frontend-models/transport-deadline.js +66 -0
  6. package/build/src/background-jobs/status-reporter.d.ts +3 -1
  7. package/build/src/background-jobs/status-reporter.d.ts.map +1 -1
  8. package/build/src/background-jobs/status-reporter.js +16 -3
  9. package/build/src/background-jobs/worker.d.ts.map +1 -1
  10. package/build/src/background-jobs/worker.js +6 -2
  11. package/build/src/frontend-models/base.d.ts +10 -1
  12. package/build/src/frontend-models/base.d.ts.map +1 -1
  13. package/build/src/frontend-models/base.js +71 -26
  14. package/build/src/frontend-models/transport-deadline.d.ts +26 -0
  15. package/build/src/frontend-models/transport-deadline.d.ts.map +1 -0
  16. package/build/src/frontend-models/transport-deadline.js +61 -0
  17. package/build/src/testing/factory/association-declaration.d.ts +37 -0
  18. package/build/src/testing/factory/association-declaration.d.ts.map +1 -0
  19. package/build/src/testing/factory/association-declaration.js +41 -0
  20. package/build/src/testing/factory/declarations.d.ts +190 -0
  21. package/build/src/testing/factory/declarations.d.ts.map +1 -0
  22. package/build/src/testing/factory/declarations.js +98 -0
  23. package/build/src/testing/factory/definition-builder.d.ts +132 -0
  24. package/build/src/testing/factory/definition-builder.d.ts.map +1 -0
  25. package/build/src/testing/factory/definition-builder.js +417 -0
  26. package/build/src/testing/factory/errors.d.ts +62 -0
  27. package/build/src/testing/factory/errors.d.ts.map +1 -0
  28. package/build/src/testing/factory/errors.js +67 -0
  29. package/build/src/testing/factory/evaluation-context.d.ts +95 -0
  30. package/build/src/testing/factory/evaluation-context.d.ts.map +1 -0
  31. package/build/src/testing/factory/evaluation-context.js +175 -0
  32. package/build/src/testing/factory/events.d.ts +21 -0
  33. package/build/src/testing/factory/events.d.ts.map +1 -0
  34. package/build/src/testing/factory/events.js +26 -0
  35. package/build/src/testing/factory/factory-definition.d.ts +39 -0
  36. package/build/src/testing/factory/factory-definition.d.ts.map +1 -0
  37. package/build/src/testing/factory/factory-definition.js +35 -0
  38. package/build/src/testing/factory/factory-registry.d.ts +263 -0
  39. package/build/src/testing/factory/factory-registry.d.ts.map +1 -0
  40. package/build/src/testing/factory/factory-registry.js +438 -0
  41. package/build/src/testing/factory/factory-runner.d.ts +179 -0
  42. package/build/src/testing/factory/factory-runner.d.ts.map +1 -0
  43. package/build/src/testing/factory/factory-runner.js +266 -0
  44. package/build/src/testing/factory/index.d.ts +18 -0
  45. package/build/src/testing/factory/index.d.ts.map +1 -0
  46. package/build/src/testing/factory/index.js +21 -0
  47. package/build/src/testing/factory/linter.d.ts +55 -0
  48. package/build/src/testing/factory/linter.d.ts.map +1 -0
  49. package/build/src/testing/factory/linter.js +106 -0
  50. package/build/src/testing/factory/model-contract.d.ts +11 -0
  51. package/build/src/testing/factory/model-contract.d.ts.map +1 -0
  52. package/build/src/testing/factory/model-contract.js +26 -0
  53. package/build/src/testing/factory/node/load-definitions.d.ts +24 -0
  54. package/build/src/testing/factory/node/load-definitions.d.ts.map +1 -0
  55. package/build/src/testing/factory/node/load-definitions.js +87 -0
  56. package/build/src/testing/factory/sequence.d.ts +73 -0
  57. package/build/src/testing/factory/sequence.d.ts.map +1 -0
  58. package/build/src/testing/factory/sequence.js +78 -0
  59. package/build/src/testing/factory/strategies/attributes-for.d.ts +21 -0
  60. package/build/src/testing/factory/strategies/attributes-for.d.ts.map +1 -0
  61. package/build/src/testing/factory/strategies/attributes-for.js +22 -0
  62. package/build/src/testing/factory/strategies/base.d.ts +101 -0
  63. package/build/src/testing/factory/strategies/base.d.ts.map +1 -0
  64. package/build/src/testing/factory/strategies/base.js +191 -0
  65. package/build/src/testing/factory/strategies/build.d.ts +20 -0
  66. package/build/src/testing/factory/strategies/build.d.ts.map +1 -0
  67. package/build/src/testing/factory/strategies/build.js +34 -0
  68. package/build/src/testing/factory/strategies/create.d.ts +32 -0
  69. package/build/src/testing/factory/strategies/create.d.ts.map +1 -0
  70. package/build/src/testing/factory/strategies/create.js +57 -0
  71. package/build/src/testing/factory/trait-definition.d.ts +22 -0
  72. package/build/src/testing/factory/trait-definition.d.ts.map +1 -0
  73. package/build/src/testing/factory/trait-definition.js +22 -0
  74. package/build/testing/factory/association-declaration.js +50 -0
  75. package/build/testing/factory/declarations.js +110 -0
  76. package/build/testing/factory/definition-builder.js +476 -0
  77. package/build/testing/factory/errors.js +79 -0
  78. package/build/testing/factory/evaluation-context.js +199 -0
  79. package/build/testing/factory/events.js +30 -0
  80. package/build/testing/factory/factory-definition.js +41 -0
  81. package/build/testing/factory/factory-registry.js +501 -0
  82. package/build/testing/factory/factory-runner.js +296 -0
  83. package/build/testing/factory/index.js +24 -0
  84. package/build/testing/factory/linter.js +119 -0
  85. package/build/testing/factory/model-contract.js +31 -0
  86. package/build/testing/factory/node/load-definitions.js +103 -0
  87. package/build/testing/factory/sequence.js +91 -0
  88. package/build/testing/factory/strategies/attributes-for.js +24 -0
  89. package/build/testing/factory/strategies/base.js +209 -0
  90. package/build/testing/factory/strategies/build.js +42 -0
  91. package/build/testing/factory/strategies/create.js +68 -0
  92. package/build/testing/factory/trait-definition.js +24 -0
  93. package/build/tsconfig.tsbuildinfo +1 -1
  94. package/package.json +1 -1
  95. package/src/background-jobs/status-reporter.js +15 -2
  96. package/src/background-jobs/worker.js +5 -1
  97. package/src/frontend-models/base.js +105 -47
  98. package/src/frontend-models/transport-deadline.js +66 -0
  99. package/src/testing/factory/association-declaration.js +50 -0
  100. package/src/testing/factory/declarations.js +110 -0
  101. package/src/testing/factory/definition-builder.js +476 -0
  102. package/src/testing/factory/errors.js +79 -0
  103. package/src/testing/factory/evaluation-context.js +199 -0
  104. package/src/testing/factory/events.js +30 -0
  105. package/src/testing/factory/factory-definition.js +41 -0
  106. package/src/testing/factory/factory-registry.js +501 -0
  107. package/src/testing/factory/factory-runner.js +296 -0
  108. package/src/testing/factory/index.js +24 -0
  109. package/src/testing/factory/linter.js +119 -0
  110. package/src/testing/factory/model-contract.js +31 -0
  111. package/src/testing/factory/node/load-definitions.js +103 -0
  112. package/src/testing/factory/sequence.js +91 -0
  113. package/src/testing/factory/strategies/attributes-for.js +24 -0
  114. package/src/testing/factory/strategies/base.js +209 -0
  115. package/src/testing/factory/strategies/build.js +42 -0
  116. package/src/testing/factory/strategies/create.js +68 -0
  117. package/src/testing/factory/trait-definition.js +24 -0
@@ -0,0 +1,501 @@
1
+ // @ts-check
2
+
3
+ import {DuplicateDefinitionError, RegistryBusyError, UndefinedSequenceError} from "./errors.js"
4
+ import AttributesForStrategy from "./strategies/attributes-for.js"
5
+ import BuildStrategy from "./strategies/build.js"
6
+ import CreateStrategy from "./strategies/create.js"
7
+ import DefinitionSession from "./definition-builder.js"
8
+ import FactoryEventEmitter from "./events.js"
9
+ import FactoryLinter from "./linter.js"
10
+ import FactoryRunner from "./factory-runner.js"
11
+ import {isPlainObject} from "is-plain-object"
12
+
13
+ /**
14
+ * Normalizes a strategy invocation's variadic tail into ordered trait names plus
15
+ * a single final overrides object (`strategy(name, ...traits, overrides?)`).
16
+ * @param {Array<?>} args - Arguments after the factory name (and count for lists).
17
+ * @returns {{traits: string[], overrides: Record<string, ?>}} - Normalized invocation.
18
+ */
19
+ function normalizeInvocationArgs(args) {
20
+ /** @type {string[]} */
21
+ const traits = []
22
+ /** @type {Record<string, ?>} */
23
+ let overrides = {}
24
+ let sawOverrides = false
25
+
26
+ for (const arg of args) {
27
+ if (typeof arg === "string" && !sawOverrides) {
28
+ traits.push(arg)
29
+ } else if (isPlainObject(arg) && !sawOverrides) {
30
+ overrides = arg
31
+ sawOverrides = true
32
+ } else if (arg !== undefined) {
33
+ throw new TypeError(`Invalid factory invocation argument: ${String(arg)}. Expected trait names then a single final overrides object.`)
34
+ }
35
+ }
36
+
37
+ return {traits, overrides}
38
+ }
39
+
40
+ /**
41
+ * Owns all factories, traits, sequences, callbacks and construction defaults for
42
+ * one isolated scope, and exposes the strategy entry points. Registry mutation is
43
+ * setup-time only and is rejected while evaluations are active.
44
+ */
45
+ export default class FactoryRegistry {
46
+ /** Builds an empty registry with the built-in strategies installed. */
47
+ constructor() {
48
+ /** @type {Map<string, import("./factory-definition.js").default>} - Factories and aliases. */
49
+ this._factories = new Map()
50
+
51
+ /** @type {Map<string, import("./trait-definition.js").default>} - Global traits. */
52
+ this._globalTraits = new Map()
53
+
54
+ /** @type {Map<string, import("./sequence.js").default>} - Global sequences and aliases. */
55
+ this._sequences = new Map()
56
+
57
+ /** @type {Map<string, Map<string, import("./sequence.js").default>>} - Factory-scoped sequences. */
58
+ this._factorySequences = new Map()
59
+
60
+ /** @type {import("./declarations.js").Declaration[]} - Registry-level default declarations. */
61
+ this._globalDeclarations = []
62
+
63
+ /** @type {number} - In-flight evaluation count (mutation guard). */
64
+ this._activeEvaluations = 0
65
+
66
+ /** @type {FactoryRunner} - Plan compiler. */
67
+ this._runner = new FactoryRunner(this)
68
+
69
+ /** @type {FactoryEventEmitter} - Debug/performance event emitter. */
70
+ this._events = new FactoryEventEmitter()
71
+
72
+ /** @type {{attributesFor: AttributesForStrategy, build: BuildStrategy, create: CreateStrategy}} - Installed strategies. */
73
+ this._strategies = {
74
+ attributesFor: new AttributesForStrategy(),
75
+ build: new BuildStrategy(),
76
+ create: new CreateStrategy()
77
+ }
78
+ }
79
+
80
+ /**
81
+ * Registers factories/traits/sequences/callbacks via a builder callback.
82
+ * @param {(builder: object) => void} callback - The definition callback.
83
+ * @returns {this} - This registry (for chaining).
84
+ */
85
+ define(callback) {
86
+ this._assertNotEvaluating("define")
87
+ new DefinitionSession(this).run(callback)
88
+
89
+ return this
90
+ }
91
+
92
+ /**
93
+ * Reopens existing factories to append/override declarations, recompiling each
94
+ * into a fresh immutable definition. Rejected while evaluations are active.
95
+ * @param {(builder: object) => void} callback - The modify callback.
96
+ * @returns {this} - This registry (for chaining).
97
+ */
98
+ modify(callback) {
99
+ this._assertNotEvaluating("modify")
100
+ new DefinitionSession(this).runModify(callback)
101
+
102
+ return this
103
+ }
104
+
105
+ /**
106
+ * Lints factories/traits, aggregating every failure. Create-strategy cases roll
107
+ * back their database writes.
108
+ * @param {object} [options] - Lint options (factories, traits, strategy).
109
+ * @returns {Promise<void>} - Resolves when all cases pass; rejects with an aggregate otherwise.
110
+ */
111
+ async lint(options) {
112
+ return await new FactoryLinter(this).lint(options)
113
+ }
114
+
115
+ /**
116
+ * Subscribes to factory debug events (`start`, `success`, `failure`).
117
+ * @param {string} event - Event name.
118
+ * @param {(payload: {invocationId: string, factory: string, strategy: string, traits: string[], durationMs?: number, error?: ?}) => void} handler - Event handler.
119
+ * @returns {this} - This registry (for chaining).
120
+ */
121
+ on(event, handler) {
122
+ this._events.on(event, handler)
123
+
124
+ return this
125
+ }
126
+
127
+ /**
128
+ * Unsubscribes a previously-registered event handler.
129
+ * @param {string} event - Event name.
130
+ * @param {(payload: ?) => void} handler - Event handler to remove.
131
+ * @returns {this} - This registry (for chaining).
132
+ */
133
+ off(event, handler) {
134
+ this._events.off(event, handler)
135
+
136
+ return this
137
+ }
138
+
139
+ /**
140
+ * Resolves attributes without constructing a model or building associations.
141
+ * @param {string} factoryName - Factory name.
142
+ * @param {Array<?>} args - Trait names then an optional overrides object.
143
+ * @returns {Promise<Record<string, ?>>} - The resolved attributes.
144
+ */
145
+ async attributesFor(factoryName, ...args) {
146
+ const {traits, overrides} = normalizeInvocationArgs(args)
147
+
148
+ return await this._runFactory({factoryName, traits, overrides, strategy: "attributesFor"})
149
+ }
150
+
151
+ /**
152
+ * Builds an unsaved record graph.
153
+ * @param {string} factoryName - Factory name.
154
+ * @param {Array<?>} args - Trait names then an optional overrides object.
155
+ * @returns {Promise<?>} - The built record.
156
+ */
157
+ async build(factoryName, ...args) {
158
+ const {traits, overrides} = normalizeInvocationArgs(args)
159
+
160
+ return await this._runFactory({factoryName, traits, overrides, strategy: "build"})
161
+ }
162
+
163
+ /**
164
+ * Builds and persists a record graph.
165
+ * @param {string} factoryName - Factory name.
166
+ * @param {Array<?>} args - Trait names then an optional overrides object.
167
+ * @returns {Promise<?>} - The persisted record.
168
+ */
169
+ async create(factoryName, ...args) {
170
+ const {traits, overrides} = normalizeInvocationArgs(args)
171
+
172
+ return await this._runFactory({factoryName, traits, overrides, strategy: "create"})
173
+ }
174
+
175
+ /**
176
+ * Resolves attributes for a list of records sequentially.
177
+ * @param {string} factoryName - Factory name.
178
+ * @param {number} count - Number of entries.
179
+ * @param {Array<?>} args - Trait names then an optional overrides object.
180
+ * @returns {Promise<Array<Record<string, ?>>>} - The resolved attribute objects.
181
+ */
182
+ async attributesForList(factoryName, count, ...args) {
183
+ return await this._runList("attributesFor", factoryName, count, args)
184
+ }
185
+
186
+ /**
187
+ * Builds a list of unsaved records sequentially.
188
+ * @param {string} factoryName - Factory name.
189
+ * @param {number} count - Number of records.
190
+ * @param {Array<?>} args - Trait names then an optional overrides object.
191
+ * @returns {Promise<Array<?>>} - The built records.
192
+ */
193
+ async buildList(factoryName, count, ...args) {
194
+ return await this._runList("build", factoryName, count, args)
195
+ }
196
+
197
+ /**
198
+ * Creates a list of persisted records sequentially.
199
+ * @param {string} factoryName - Factory name.
200
+ * @param {number} count - Number of records.
201
+ * @param {Array<?>} args - Trait names then an optional overrides object.
202
+ * @returns {Promise<Array<?>>} - The persisted records.
203
+ */
204
+ async createList(factoryName, count, ...args) {
205
+ return await this._runList("create", factoryName, count, args)
206
+ }
207
+
208
+ /**
209
+ * Resolves attributes for exactly two records.
210
+ * @param {string} factoryName - Factory name.
211
+ * @param {Array<?>} args - Trait names then an optional overrides object.
212
+ * @returns {Promise<Array<Record<string, ?>>>} - The two resolved attribute objects.
213
+ */
214
+ async attributesForPair(factoryName, ...args) {
215
+ return await this._runList("attributesFor", factoryName, 2, args)
216
+ }
217
+
218
+ /**
219
+ * Builds exactly two unsaved records.
220
+ * @param {string} factoryName - Factory name.
221
+ * @param {Array<?>} args - Trait names then an optional overrides object.
222
+ * @returns {Promise<Array<?>>} - The two built records.
223
+ */
224
+ async buildPair(factoryName, ...args) {
225
+ return await this._runList("build", factoryName, 2, args)
226
+ }
227
+
228
+ /**
229
+ * Creates exactly two persisted records.
230
+ * @param {string} factoryName - Factory name.
231
+ * @param {Array<?>} args - Trait names then an optional overrides object.
232
+ * @returns {Promise<Array<?>>} - The two persisted records.
233
+ */
234
+ async createPair(factoryName, ...args) {
235
+ return await this._runList("create", factoryName, 2, args)
236
+ }
237
+
238
+ /**
239
+ * Advances a sequence and returns its formatted value.
240
+ * @param {string} sequenceName - Sequence name.
241
+ * @returns {Promise<?>} - The formatted value.
242
+ */
243
+ async generate(sequenceName) {
244
+ return await this._generateScoped(sequenceName, [])
245
+ }
246
+
247
+ /**
248
+ * Advances a sequence `count` times and returns the formatted values.
249
+ * @param {string} sequenceName - Sequence name.
250
+ * @param {number} count - Number of values.
251
+ * @returns {Promise<Array<?>>} - The formatted values.
252
+ */
253
+ async generateList(sequenceName, count) {
254
+ /** @type {Array<?>} */
255
+ const values = []
256
+
257
+ for (let index = 0; index < count; index++) {
258
+ values.push(await this._generateScoped(sequenceName, []))
259
+ }
260
+
261
+ return values
262
+ }
263
+
264
+ /**
265
+ * Returns the next raw value a global sequence would allocate without consuming it.
266
+ * @param {string} sequenceName - Sequence name.
267
+ * @returns {number} - The upcoming raw value.
268
+ */
269
+ peekSequence(sequenceName) {
270
+ return this._resolveGlobalSequence(sequenceName).peek()
271
+ }
272
+
273
+ /**
274
+ * Sets the next value a global sequence will allocate.
275
+ * @param {string} sequenceName - Sequence name.
276
+ * @param {number} value - Next raw value.
277
+ * @returns {void}
278
+ */
279
+ setSequence(sequenceName, value) {
280
+ this._assertNotEvaluating("setSequence")
281
+ this._resolveGlobalSequence(sequenceName).set(value)
282
+ }
283
+
284
+ /**
285
+ * Rewinds a single global sequence to its initial value.
286
+ * @param {string} sequenceName - Sequence name.
287
+ * @returns {void}
288
+ */
289
+ rewindSequence(sequenceName) {
290
+ this._assertNotEvaluating("rewindSequence")
291
+ this._resolveGlobalSequence(sequenceName).rewind()
292
+ }
293
+
294
+ /**
295
+ * Rewinds every global and factory-scoped sequence to its initial value while
296
+ * leaving all definitions intact.
297
+ * @returns {void}
298
+ */
299
+ rewindSequences() {
300
+ this._assertNotEvaluating("rewindSequences")
301
+
302
+ for (const sequence of new Set(this._sequences.values())) sequence.rewind()
303
+
304
+ for (const scope of this._factorySequences.values()) {
305
+ for (const sequence of new Set(scope.values())) sequence.rewind()
306
+ }
307
+ }
308
+
309
+ /**
310
+ * Clears all definitions, traits, sequences and registry defaults, restoring an
311
+ * empty registry with the built-in strategies.
312
+ * @returns {void}
313
+ */
314
+ reset() {
315
+ this._assertNotEvaluating("reset")
316
+ this._factories.clear()
317
+ this._globalTraits.clear()
318
+ this._sequences.clear()
319
+ this._factorySequences.clear()
320
+ this._globalDeclarations = []
321
+ this._events = new FactoryEventEmitter()
322
+ }
323
+
324
+ /**
325
+ * Runs `count` sequential strategy invocations.
326
+ * @param {"attributesFor" | "build" | "create"} strategy - Strategy name.
327
+ * @param {string} factoryName - Factory name.
328
+ * @param {number} count - Number of entries.
329
+ * @param {Array<?>} args - Trait names then an optional overrides object.
330
+ * @returns {Promise<Array<?>>} - The results.
331
+ */
332
+ async _runList(strategy, factoryName, count, args) {
333
+ const {traits, overrides} = normalizeInvocationArgs(args)
334
+ /** @type {Array<?>} */
335
+ const results = []
336
+
337
+ for (let index = 0; index < count; index++) {
338
+ results.push(await this._runFactory({factoryName, traits, overrides, strategy}))
339
+ }
340
+
341
+ return results
342
+ }
343
+
344
+ /**
345
+ * Compiles and runs a factory invocation under a strategy, tracking active
346
+ * evaluations for the mutation guard.
347
+ * @param {object} args - Options.
348
+ * @param {string} args.factoryName - Factory name.
349
+ * @param {string[]} args.traits - Ordered traits.
350
+ * @param {Record<string, ?>} args.overrides - Overrides.
351
+ * @param {"attributesFor" | "build" | "create"} args.strategy - Strategy name.
352
+ * @returns {Promise<?>} - The strategy result.
353
+ */
354
+ async _runFactory({factoryName, traits, overrides, strategy}) {
355
+ this._activeEvaluations += 1
356
+
357
+ const invocationId = this._events.nextInvocationId()
358
+ const startedAt = Date.now()
359
+
360
+ try {
361
+ this._events.emit("start", {invocationId, factory: factoryName, strategy, traits})
362
+
363
+ const plan = this._runner.compile(factoryName, traits, overrides)
364
+ const result = await this._strategies[strategy].run({registry: this, plan})
365
+
366
+ this._events.emit("success", {invocationId, factory: factoryName, strategy, traits, durationMs: Date.now() - startedAt})
367
+
368
+ return result
369
+ } catch (error) {
370
+ this._events.emit("failure", {invocationId, factory: factoryName, strategy, traits, durationMs: Date.now() - startedAt, error})
371
+
372
+ throw error
373
+ } finally {
374
+ this._activeEvaluations -= 1
375
+ }
376
+ }
377
+
378
+ /**
379
+ * Registers an immutable factory definition and its aliases.
380
+ * @param {import("./factory-definition.js").default} definition - Compiled factory.
381
+ * @returns {void}
382
+ */
383
+ _registerFactoryDefinition(definition) {
384
+ for (const name of [definition.name, ...definition.aliases]) {
385
+ if (this._factories.has(name)) {
386
+ throw new DuplicateDefinitionError(`Factory "${name}" is already registered`)
387
+ }
388
+ }
389
+
390
+ for (const name of [definition.name, ...definition.aliases]) {
391
+ this._factories.set(name, definition)
392
+ }
393
+ }
394
+
395
+ /**
396
+ * Replaces an existing factory definition (and its aliases) with a recompiled
397
+ * one. Used by `modify`; no duplicate check because it intentionally overwrites.
398
+ * @param {import("./factory-definition.js").default} definition - Recompiled factory.
399
+ * @returns {void}
400
+ */
401
+ _replaceFactoryDefinition(definition) {
402
+ for (const name of [definition.name, ...definition.aliases]) {
403
+ this._factories.set(name, definition)
404
+ }
405
+ }
406
+
407
+ /**
408
+ * Registers a global trait.
409
+ * @param {import("./trait-definition.js").default} trait - Compiled trait.
410
+ * @returns {void}
411
+ */
412
+ _registerGlobalTrait(trait) {
413
+ if (this._globalTraits.has(trait.name)) {
414
+ throw new DuplicateDefinitionError(`Trait "${trait.name}" is already registered`)
415
+ }
416
+
417
+ this._globalTraits.set(trait.name, trait)
418
+ }
419
+
420
+ /**
421
+ * Registers a sequence (and its aliases) either globally or under a factory scope.
422
+ * @param {import("./sequence.js").default} sequence - Sequence instance.
423
+ * @param {string | null} factoryScope - Factory name to scope under, or null for global.
424
+ * @returns {void}
425
+ */
426
+ _registerSequence(sequence, factoryScope) {
427
+ /** @type {Map<string, import("./sequence.js").default>} */
428
+ let target
429
+
430
+ if (factoryScope) {
431
+ if (!this._factorySequences.has(factoryScope)) this._factorySequences.set(factoryScope, new Map())
432
+ target = /** @type {Map<string, import("./sequence.js").default>} */ (this._factorySequences.get(factoryScope))
433
+ } else {
434
+ target = this._sequences
435
+ }
436
+
437
+ for (const name of [sequence.name, ...sequence.aliases]) {
438
+ if (target.has(name)) {
439
+ throw new DuplicateDefinitionError(`Sequence "${name}" is already registered${factoryScope ? ` for factory "${factoryScope}"` : ""}`)
440
+ }
441
+ }
442
+
443
+ for (const name of [sequence.name, ...sequence.aliases]) {
444
+ target.set(name, sequence)
445
+ }
446
+ }
447
+
448
+ /**
449
+ * Appends a registry-level default declaration (callbacks/construction defaults).
450
+ * @param {import("./declarations.js").Declaration} declaration - Declaration to add.
451
+ * @returns {void}
452
+ */
453
+ _addGlobalDeclaration(declaration) {
454
+ this._globalDeclarations.push(declaration)
455
+ }
456
+
457
+ /**
458
+ * Resolves a sequence name against a factory scope chain (child first) then the
459
+ * global scope and advances it.
460
+ * @param {string} sequenceName - Sequence name.
461
+ * @param {string[]} chainNames - Inheritance chain names (child last).
462
+ * @returns {Promise<?>} - The formatted value.
463
+ */
464
+ async _generateScoped(sequenceName, chainNames) {
465
+ for (let index = chainNames.length - 1; index >= 0; index--) {
466
+ const scope = this._factorySequences.get(chainNames[index])
467
+
468
+ if (scope && scope.has(sequenceName)) {
469
+ return await /** @type {import("./sequence.js").default} */ (scope.get(sequenceName)).next()
470
+ }
471
+ }
472
+
473
+ return await this._resolveGlobalSequence(sequenceName).next()
474
+ }
475
+
476
+ /**
477
+ * Resolves a global sequence by name.
478
+ * @param {string} sequenceName - Sequence name.
479
+ * @returns {import("./sequence.js").default} - The sequence.
480
+ */
481
+ _resolveGlobalSequence(sequenceName) {
482
+ const sequence = this._sequences.get(sequenceName)
483
+
484
+ if (!sequence) {
485
+ throw new UndefinedSequenceError(`No sequence registered called "${sequenceName}"`)
486
+ }
487
+
488
+ return sequence
489
+ }
490
+
491
+ /**
492
+ * Rejects setup-time mutation while evaluations are active.
493
+ * @param {string} operation - Operation name, for the error message.
494
+ * @returns {void}
495
+ */
496
+ _assertNotEvaluating(operation) {
497
+ if (this._activeEvaluations > 0) {
498
+ throw new RegistryBusyError(`Cannot ${operation} while factory evaluations are active. Registry mutation is setup-time only.`)
499
+ }
500
+ }
501
+ }