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,191 @@
1
+ // @ts-check
2
+ import * as inflection from "inflection";
3
+ import { assertModelClass } from "../model-contract.js";
4
+ import { ModelContractError } from "../errors.js";
5
+ import EvaluationContext from "../evaluation-context.js";
6
+ /**
7
+ * Shared behaviour for the build/create/attributesFor strategies: evaluation
8
+ * context creation, deterministic callback execution, guaranteed `afterAll`
9
+ * cleanup, record construction (default and `initializeWith`), and association
10
+ * wiring through public relationship reflection.
11
+ */
12
+ export default class BaseStrategy {
13
+ /**
14
+ * Creates an evaluation context for a plan.
15
+ * @param {import("../factory-registry.js").default} registry - Owning registry.
16
+ * @param {import("../factory-runner.js").CompiledPlan} plan - Compiled plan.
17
+ * @param {"attributesFor" | "build" | "create"} strategyName - Strategy name.
18
+ * @returns {EvaluationContext} - The context.
19
+ */
20
+ _newContext(registry, plan, strategyName) {
21
+ return new EvaluationContext({ registry, plan, strategy: strategyName });
22
+ }
23
+ /**
24
+ * Builds the callback `context` object: evaluated transients exposed as plain
25
+ * properties (no Proxy) plus the named evaluator methods.
26
+ * @param {EvaluationContext} context - Evaluation context.
27
+ * @param {Record<string, ?>} transients - Evaluated transient values.
28
+ * @returns {Record<string, ?>} - The callback context.
29
+ */
30
+ _callbackContext(context, transients) {
31
+ return Object.assign({}, transients, context.contextFor([]));
32
+ }
33
+ /**
34
+ * Runs every deduped callback for an event in declaration order.
35
+ * @param {EvaluationContext} context - Evaluation context.
36
+ * @param {import("../factory-runner.js").CompiledPlan} plan - Compiled plan.
37
+ * @param {string} event - Event name (e.g. "afterCreate").
38
+ * @param {{record: ?, transients: Record<string, ?>, strategy: string}} state - Current record/transients/strategy.
39
+ * @returns {Promise<void>} - Resolves when all callbacks complete.
40
+ */
41
+ async _runCallbacks(context, plan, event, state) {
42
+ const callbacks = plan.callbacks.get(event);
43
+ if (!callbacks)
44
+ return;
45
+ const callbackContext = this._callbackContext(context, state.transients);
46
+ for (const callback of callbacks) {
47
+ await callback.fn({ record: state.record, context: callbackContext, strategy: state.strategy });
48
+ }
49
+ }
50
+ /**
51
+ * Runs `body`, then guarantees `afterAll` runs in `finally`. When both the body
52
+ * and cleanup fail, the body's primary error is preserved and the cleanup error
53
+ * is attached as a detail rather than masking it.
54
+ * @param {EvaluationContext} context - Evaluation context.
55
+ * @param {import("../factory-runner.js").CompiledPlan} plan - Compiled plan.
56
+ * @param {() => {record: ?, transients: Record<string, ?>, strategy: string}} state - Late-bound state accessor.
57
+ * @param {() => Promise<?>} body - The strategy body.
58
+ * @returns {Promise<?>} - The body's result.
59
+ */
60
+ async _runWithAfterAll(context, plan, state, body) {
61
+ /** @type {?} */
62
+ let result;
63
+ /** @type {?} */
64
+ let primaryError;
65
+ let hasPrimaryError = false;
66
+ try {
67
+ result = await body();
68
+ }
69
+ catch (error) {
70
+ primaryError = error;
71
+ hasPrimaryError = true;
72
+ }
73
+ /** @type {?} */
74
+ let cleanupError;
75
+ let hasCleanupError = false;
76
+ try {
77
+ await this._runCallbacks(context, plan, "afterAll", state());
78
+ }
79
+ catch (error) {
80
+ cleanupError = error;
81
+ hasCleanupError = true;
82
+ }
83
+ if (hasPrimaryError) {
84
+ if (hasCleanupError)
85
+ this._attachCleanupFailure(primaryError, cleanupError);
86
+ throw primaryError;
87
+ }
88
+ if (hasCleanupError)
89
+ throw cleanupError;
90
+ return result;
91
+ }
92
+ /**
93
+ * Attaches an afterAll cleanup failure to the primary error without masking it.
94
+ * @param {?} primaryError - The original error that will propagate.
95
+ * @param {?} cleanupError - The afterAll cleanup failure.
96
+ * @returns {void}
97
+ */
98
+ _attachCleanupFailure(primaryError, cleanupError) {
99
+ if (!primaryError || typeof primaryError !== "object" || !Object.isExtensible(primaryError))
100
+ return;
101
+ if (!Array.isArray(primaryError.factoryCleanupErrors))
102
+ primaryError.factoryCleanupErrors = [];
103
+ primaryError.factoryCleanupErrors.push(cleanupError);
104
+ }
105
+ /**
106
+ * Constructs a record from evaluated public attributes, honouring a custom
107
+ * `initializeWith` constructor and never assigning constructor-consumed
108
+ * attributes twice.
109
+ * @param {import("../factory-runner.js").CompiledPlan} plan - Compiled plan.
110
+ * @param {Record<string, ?>} publicAttributes - Evaluated public attributes.
111
+ * @param {EvaluationContext} context - Evaluation context.
112
+ * @param {Record<string, ?>} transients - Evaluated transients.
113
+ * @returns {Promise<?>} - The constructed record.
114
+ */
115
+ async _constructRecord(plan, publicAttributes, context, transients) {
116
+ const ModelClass = assertModelClass(plan.modelClass, plan.factoryName);
117
+ if (plan.initializeWith) {
118
+ return await this._constructWithInitializer(plan, ModelClass, publicAttributes, context, transients);
119
+ }
120
+ return new ModelClass(publicAttributes);
121
+ }
122
+ /**
123
+ * Constructs a record via a custom `initializeWith`, tracking which attributes
124
+ * the constructor consumed through its `get(name)` accessor and assigning only
125
+ * the remaining public attributes afterwards.
126
+ * @param {import("../factory-runner.js").CompiledPlan} plan - Compiled plan.
127
+ * @param {new (attributes?: Record<string, ?>) => import("../../../database/record/index.js").default} ModelClass - Validated declared model class.
128
+ * @param {Record<string, ?>} publicAttributes - Evaluated public attributes.
129
+ * @param {EvaluationContext} context - Evaluation context.
130
+ * @param {Record<string, ?>} transients - Evaluated transients.
131
+ * @returns {Promise<?>} - The constructed record.
132
+ */
133
+ async _constructWithInitializer(plan, ModelClass, publicAttributes, context, transients) {
134
+ /** @type {Set<string>} */
135
+ const consumed = new Set();
136
+ const get = (/** @type {string} */ name) => {
137
+ consumed.add(name);
138
+ return publicAttributes[name];
139
+ };
140
+ const initializeWith = /** @type {import("../declarations.js").InitializeWithDeclaration["fn"]} */ (plan.initializeWith);
141
+ const record = await initializeWith({ attributes: { ...publicAttributes }, get, context: this._callbackContext(context, transients) });
142
+ if (!(record instanceof ModelClass)) {
143
+ throw new ModelContractError(`Factory "${plan.factoryName}" initializeWith must return an instance of ${ModelClass.name}, got: ${String(record)}`);
144
+ }
145
+ /** @type {Record<string, ?>} */
146
+ const remaining = {};
147
+ for (const key of Object.keys(publicAttributes)) {
148
+ if (!consumed.has(key))
149
+ remaining[key] = publicAttributes[key];
150
+ }
151
+ if (Object.keys(remaining).length > 0) {
152
+ /** @type {?} */ (record).assign(remaining);
153
+ }
154
+ return record;
155
+ }
156
+ /**
157
+ * Wires evaluated associations onto a record through public relationship
158
+ * reflection and generated setters (never private caches or guessed keys).
159
+ * @param {?} record - The owning record.
160
+ * @param {Array<{name: string, record: ?}>} associations - Evaluated associations.
161
+ * @returns {void}
162
+ */
163
+ _assignAssociations(record, associations) {
164
+ for (const { name, record: associatedRecord } of associations) {
165
+ const instanceRelationship = record.getRelationshipByName(name);
166
+ const relationshipType = instanceRelationship.getType();
167
+ if (relationshipType === "belongsTo") {
168
+ record[`set${inflection.camelize(name)}`](associatedRecord || null);
169
+ }
170
+ else if (relationshipType === "hasOne") {
171
+ instanceRelationship.setLoaded(associatedRecord || undefined);
172
+ }
173
+ else if (relationshipType === "hasMany") {
174
+ instanceRelationship.setLoaded(this._toRecordArray(associatedRecord));
175
+ }
176
+ }
177
+ }
178
+ /**
179
+ * Normalizes a has-many association value into an array of records.
180
+ * @param {?} value - Association value (record, array, or null).
181
+ * @returns {Array<?>} - The normalized record array.
182
+ */
183
+ _toRecordArray(value) {
184
+ if (value == null)
185
+ return [];
186
+ if (Array.isArray(value))
187
+ return value;
188
+ return [value];
189
+ }
190
+ }
191
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFzZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy90ZXN0aW5nL2ZhY3Rvcnkvc3RyYXRlZ2llcy9iYXNlLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLFlBQVk7QUFFWixPQUFPLEtBQUssVUFBVSxNQUFNLFlBQVksQ0FBQTtBQUN4QyxPQUFPLEVBQUMsZ0JBQWdCLEVBQUMsTUFBTSxzQkFBc0IsQ0FBQTtBQUNyRCxPQUFPLEVBQUMsa0JBQWtCLEVBQUMsTUFBTSxjQUFjLENBQUE7QUFDL0MsT0FBTyxpQkFBaUIsTUFBTSwwQkFBMEIsQ0FBQTtBQUV4RDs7Ozs7R0FLRztBQUNILE1BQU0sQ0FBQyxPQUFPLE9BQU8sWUFBWTtJQUMvQjs7Ozs7O09BTUc7SUFDSCxXQUFXLENBQUMsUUFBUSxFQUFFLElBQUksRUFBRSxZQUFZO1FBQ3RDLE9BQU8sSUFBSSxpQkFBaUIsQ0FBQyxFQUFDLFFBQVEsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLFlBQVksRUFBQyxDQUFDLENBQUE7SUFDeEUsQ0FBQztJQUVEOzs7Ozs7T0FNRztJQUNILGdCQUFnQixDQUFDLE9BQU8sRUFBRSxVQUFVO1FBQ2xDLE9BQU8sTUFBTSxDQUFDLE1BQU0sQ0FBQyxFQUFFLEVBQUUsVUFBVSxFQUFFLE9BQU8sQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQTtJQUM5RCxDQUFDO0lBRUQ7Ozs7Ozs7T0FPRztJQUNILEtBQUssQ0FBQyxhQUFhLENBQUMsT0FBTyxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsS0FBSztRQUM3QyxNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQTtRQUUzQyxJQUFJLENBQUMsU0FBUztZQUFFLE9BQU07UUFFdEIsTUFBTSxlQUFlLEdBQUcsSUFBSSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sRUFBRSxLQUFLLENBQUMsVUFBVSxDQUFDLENBQUE7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Q0FBQztJQUVEOzs7Ozs7T0FNRztJQUNILG1CQUFtQixDQUFDLE1BQU0sRUFBRSxZQUFZO1FBQ3RDLEtBQUssTUFBTSxFQUFDLElBQUksRUFBRSxNQUFNLEVBQUUsZ0JBQWdCLEVBQUMsSUFBSSxZQUFZLEVBQUUsQ0FBQztZQUM1RCxNQUFNLG9CQUFvQixHQUFHLE1BQU0sQ0FBQyxxQkFBcUIsQ0FBQyxJQUFJLENBQUMsQ0FBQTtZQUMvRCxNQUFNLGdCQUFnQixHQUFHLG9CQUFvQixDQUFDLE9BQU8sRUFBRSxDQUFBO1lBRXZELElBQUksZ0JBQWdCLEtBQUssV0FBVyxFQUFFLENBQUM7Z0JBQ3JDLE1BQU0sQ0FBQyxNQUFNLFVBQVUsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLGdCQUFnQixJQUFJLElBQUksQ0FBQyxDQUFBO1lBQ3JFLENBQUM7aUJBQU0sSUFBSSxnQkFBZ0IsS0FBSyxRQUFRLEVBQUUsQ0FBQztnQkFDekMsb0JBQW9CLENBQUMsU0FBUyxDQUFDLGdCQUFnQixJQUFJLFNBQVMsQ0FBQyxDQUFBO1lBQy9ELENBQUM7aUJBQU0sSUFBSSxnQkFBZ0IsS0FBSyxTQUFTLEVBQUUsQ0FBQztnQkFDMUMsb0JBQW9CLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxDQUFBO1lBQ3ZFLENBQUM7UUFDSCxDQUFDO0lBQ0gsQ0FBQztJQUVEOzs7O09BSUc7SUFDSCxjQUFjLENBQUMsS0FBSztRQUNsQixJQUFJLEtBQUssSUFBSSxJQUFJO1lBQUUsT0FBTyxFQUFFLENBQUE7UUFDNUIsSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQztZQUFFLE9BQU8sS0FBSyxDQUFBO1FBRXRDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQTtJQUNoQixDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBAdHMtY2hlY2tcblxuaW1wb3J0ICogYXMgaW5mbGVjdGlvbiBmcm9tIFwiaW5mbGVjdGlvblwiXG5pbXBvcnQge2Fzc2VydE1vZGVsQ2xhc3N9IGZyb20gXCIuLi9tb2RlbC1jb250cmFjdC5qc1wiXG5pbXBvcnQge01vZGVsQ29udHJhY3RFcnJvcn0gZnJvbSBcIi4uL2Vycm9ycy5qc1wiXG5pbXBvcnQgRXZhbHVhdGlvbkNvbnRleHQgZnJvbSBcIi4uL2V2YWx1YXRpb24tY29udGV4dC5qc1wiXG5cbi8qKlxuICogU2hhcmVkIGJlaGF2aW91ciBmb3IgdGhlIGJ1aWxkL2NyZWF0ZS9hdHRyaWJ1dGVzRm9yIHN0cmF0ZWdpZXM6IGV2YWx1YXRpb25cbiAqIGNvbnRleHQgY3JlYXRpb24sIGRldGVybWluaXN0aWMgY2FsbGJhY2sgZXhlY3V0aW9uLCBndWFyYW50ZWVkIGBhZnRlckFsbGBcbiAqIGNsZWFudXAsIHJlY29yZCBjb25zdHJ1Y3Rpb24gKGRlZmF1bHQgYW5kIGBpbml0aWFsaXplV2l0aGApLCBhbmQgYXNzb2NpYXRpb25cbiAqIHdpcmluZyB0aHJvdWdoIHB1YmxpYyByZWxhdGlvbnNoaXAgcmVmbGVjdGlvbi5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgQmFzZVN0cmF0ZWd5IHtcbiAgLyoqXG4gICAqIENyZWF0ZXMgYW4gZXZhbHVhdGlvbiBjb250ZXh0IGZvciBhIHBsYW4uXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vZmFjdG9yeS1yZWdpc3RyeS5qc1wiKS5kZWZhdWx0fSByZWdpc3RyeSAtIE93bmluZyByZWdpc3RyeS5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9mYWN0b3J5LXJ1bm5lci5qc1wiKS5Db21waWxlZFBsYW59IHBsYW4gLSBDb21waWxlZCBwbGFuLlxuICAgKiBAcGFyYW0ge1wiYXR0cmlidXRlc0ZvclwiIHwgXCJidWlsZFwiIHwgXCJjcmVhdGVcIn0gc3RyYXRlZ3lOYW1lIC0gU3RyYXRlZ3kgbmFtZS5cbiAgICogQHJldHVybnMge0V2YWx1YXRpb25Db250ZXh0fSAtIFRoZSBjb250ZXh0LlxuICAgKi9cbiAgX25ld0NvbnRleHQocmVnaXN0cnksIHBsYW4sIHN0cmF0ZWd5TmFtZSkge1xuICAgIHJldHVybiBuZXcgRXZhbHVhdGlvbkNvbnRleHQoe3JlZ2lzdHJ5LCBwbGFuLCBzdHJhdGVneTogc3RyYXRlZ3lOYW1lfSlcbiAgfVxuXG4gIC8qKlxuICAgKiBCdWlsZHMgdGhlIGNhbGxiYWNrIGBjb250ZXh0YCBvYmplY3Q6IGV2YWx1YXRlZCB0cmFuc2llbnRzIGV4cG9zZWQgYXMgcGxhaW5cbiAgICogcHJvcGVydGllcyAobm8gUHJveHkpIHBsdXMgdGhlIG5hbWVkIGV2YWx1YXRvciBtZXRob2RzLlxuICAgKiBAcGFyYW0ge0V2YWx1YXRpb25Db250ZXh0fSBjb250ZXh0IC0gRXZhbHVhdGlvbiBjb250ZXh0LlxuICAgKiBAcGFyYW0ge1JlY29yZDxzdHJpbmcsID8+fSB0cmFuc2llbnRzIC0gRXZhbHVhdGVkIHRyYW5zaWVudCB2YWx1ZXMuXG4gICAqIEByZXR1cm5zIHtSZWNvcmQ8c3RyaW5nLCA/Pn0gLSBUaGUgY2FsbGJhY2sgY29udGV4dC5cbiAgICovXG4gIF9jYWxsYmFja0NvbnRleHQoY29udGV4dCwgdHJhbnNpZW50cykge1xuICAgIHJldHVybiBPYmplY3QuYXNzaWduKHt9LCB0cmFuc2llbnRzLCBjb250ZXh0LmNvbnRleHRGb3IoW10pKVxuICB9XG5cbiAgLyoqXG4gICAqIFJ1bnMgZXZlcnkgZGVkdXBlZCBjYWxsYmFjayBmb3IgYW4gZXZlbnQgaW4gZGVjbGFyYXRpb24gb3JkZXIuXG4gICAqIEBwYXJhbSB7RXZhbHVhdGlvbkNvbnRleHR9IGNvbnRleHQgLSBFdmFsdWF0aW9uIGNvbnRleHQuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vZmFjdG9yeS1ydW5uZXIuanNcIikuQ29tcGlsZWRQbGFufSBwbGFuIC0gQ29tcGlsZWQgcGxhbi5cbiAgICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50IC0gRXZlbnQgbmFtZSAoZS5nLiBcImFmdGVyQ3JlYXRlXCIpLlxuICAgKiBAcGFyYW0ge3tyZWNvcmQ6ID8sIHRyYW5zaWVudHM6IFJlY29yZDxzdHJpbmcsID8+LCBzdHJhdGVneTogc3RyaW5nfX0gc3RhdGUgLSBDdXJyZW50IHJlY29yZC90cmFuc2llbnRzL3N0cmF0ZWd5LlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gLSBSZXNvbHZlcyB3aGVuIGFsbCBjYWxsYmFja3MgY29tcGxldGUuXG4gICAqL1xuICBhc3luYyBfcnVuQ2FsbGJhY2tzKGNvbnRleHQsIHBsYW4sIGV2ZW50LCBzdGF0ZSkge1xuICAgIGNvbnN0IGNhbGxiYWNrcyA9IHBsYW4uY2FsbGJhY2tzLmdldChldmVudClcblxuICAgIGlmICghY2FsbGJhY2tzKSByZXR1cm5cblxuICAgIGNvbnN0IGNhbGxiYWNrQ29udGV4dCA9IHRoaXMuX2NhbGxiYWNrQ29udGV4dChjb250ZXh0LCBzdGF0ZS50cmFuc2llbnRzKVxuXG4gICAgZm9yIChjb25zdCBjYWxsYmFjayBvZiBjYWxsYmFja3MpIHtcbiAgICAgIGF3YWl0IGNhbGxiYWNrLmZuKHtyZWNvcmQ6IHN0YXRlLnJlY29yZCwgY29udGV4dDogY2FsbGJhY2tDb250ZXh0LCBzdHJhdGVneTogc3RhdGUuc3RyYXRlZ3l9KVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIGBib2R5YCwgdGhlbiBndWFyYW50ZWVzIGBhZnRlckFsbGAgcnVucyBpbiBgZmluYWxseWAuIFdoZW4gYm90aCB0aGUgYm9keVxuICAgKiBhbmQgY2xlYW51cCBmYWlsLCB0aGUgYm9keSdzIHByaW1hcnkgZXJyb3IgaXMgcHJlc2VydmVkIGFuZCB0aGUgY2xlYW51cCBlcnJvclxuICAgKiBpcyBhdHRhY2hlZCBhcyBhIGRldGFpbCByYXRoZXIgdGhhbiBtYXNraW5nIGl0LlxuICAgKiBAcGFyYW0ge0V2YWx1YXRpb25Db250ZXh0fSBjb250ZXh0IC0gRXZhbHVhdGlvbiBjb250ZXh0LlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL2ZhY3RvcnktcnVubmVyLmpzXCIpLkNvbXBpbGVkUGxhbn0gcGxhbiAtIENvbXBpbGVkIHBsYW4uXG4gICAqIEBwYXJhbSB7KCkgPT4ge3JlY29yZDogPywgdHJhbnNpZW50czogUmVjb3JkPHN0cmluZywgPz4sIHN0cmF0ZWd5OiBzdHJpbmd9fSBzdGF0ZSAtIExhdGUtYm91bmQgc3RhdGUgYWNjZXNzb3IuXG4gICAqIEBwYXJhbSB7KCkgPT4gUHJvbWlzZTw/Pn0gYm9keSAtIFRoZSBzdHJhdGVneSBib2R5LlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTw/Pn0gLSBUaGUgYm9keSdzIHJlc3VsdC5cbiAgICovXG4gIGFzeW5jIF9ydW5XaXRoQWZ0ZXJBbGwoY29udGV4dCwgcGxhbiwgc3RhdGUsIGJvZHkpIHtcbiAgICAvKiogQHR5cGUgez99ICovXG4gICAgbGV0IHJlc3VsdFxuICAgIC8qKiBAdHlwZSB7P30gKi9cbiAgICBsZXQgcHJpbWFyeUVycm9yXG4gICAgbGV0IGhhc1ByaW1hcnlFcnJvciA9IGZhbHNlXG5cbiAgICB0cnkge1xuICAgICAgcmVzdWx0ID0gYXdhaXQgYm9keSgpXG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIHByaW1hcnlFcnJvciA9IGVycm9yXG4gICAgICBoYXNQcmltYXJ5RXJyb3IgPSB0cnVlXG4gICAgfVxuXG4gICAgLyoqIEB0eXBlIHs/fSAqL1xuICAgIGxldCBjbGVhbnVwRXJyb3JcbiAgICBsZXQgaGFzQ2xlYW51cEVycm9yID0gZmFsc2VcblxuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLl9ydW5DYWxsYmFja3MoY29udGV4dCwgcGxhbiwgXCJhZnRlckFsbFwiLCBzdGF0ZSgpKVxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBjbGVhbnVwRXJyb3IgPSBlcnJvclxuICAgICAgaGFzQ2xlYW51cEVycm9yID0gdHJ1ZVxuICAgIH1cblxuICAgIGlmIChoYXNQcmltYXJ5RXJyb3IpIHtcbiAgICAgIGlmIChoYXNDbGVhbnVwRXJyb3IpIHRoaXMuX2F0dGFjaENsZWFudXBGYWlsdXJlKHByaW1hcnlFcnJvciwgY2xlYW51cEVycm9yKVxuXG4gICAgICB0aHJvdyBwcmltYXJ5RXJyb3JcbiAgICB9XG5cbiAgICBpZiAoaGFzQ2xlYW51cEVycm9yKSB0aHJvdyBjbGVhbnVwRXJyb3JcblxuICAgIHJldHVybiByZXN1bHRcbiAgfVxuXG4gIC8qKlxuICAgKiBBdHRhY2hlcyBhbiBhZnRlckFsbCBjbGVhbnVwIGZhaWx1cmUgdG8gdGhlIHByaW1hcnkgZXJyb3Igd2l0aG91dCBtYXNraW5nIGl0LlxuICAgKiBAcGFyYW0gez99IHByaW1hcnlFcnJvciAtIFRoZSBvcmlnaW5hbCBlcnJvciB0aGF0IHdpbGwgcHJvcGFnYXRlLlxuICAgKiBAcGFyYW0gez99IGNsZWFudXBFcnJvciAtIFRoZSBhZnRlckFsbCBjbGVhbnVwIGZhaWx1cmUuXG4gICAqIEByZXR1cm5zIHt2b2lkfVxuICAgKi9cbiAgX2F0dGFjaENsZWFudXBGYWlsdXJlKHByaW1hcnlFcnJvciwgY2xlYW51cEVycm9yKSB7XG4gICAgaWYgKCFwcmltYXJ5RXJyb3IgfHwgdHlwZW9mIHByaW1hcnlFcnJvciAhPT0gXCJvYmplY3RcIiB8fCAhT2JqZWN0LmlzRXh0ZW5zaWJsZShwcmltYXJ5RXJyb3IpKSByZXR1cm5cblxuICAgIGlmICghQXJyYXkuaXNBcnJheShwcmltYXJ5RXJyb3IuZmFjdG9yeUNsZWFudXBFcnJvcnMpKSBwcmltYXJ5RXJyb3IuZmFjdG9yeUNsZWFudXBFcnJvcnMgPSBbXVxuICAgIHByaW1hcnlFcnJvci5mYWN0b3J5Q2xlYW51cEVycm9ycy5wdXNoKGNsZWFudXBFcnJvcilcbiAgfVxuXG4gIC8qKlxuICAgKiBDb25zdHJ1Y3RzIGEgcmVjb3JkIGZyb20gZXZhbHVhdGVkIHB1YmxpYyBhdHRyaWJ1dGVzLCBob25vdXJpbmcgYSBjdXN0b21cbiAgICogYGluaXRpYWxpemVXaXRoYCBjb25zdHJ1Y3RvciBhbmQgbmV2ZXIgYXNzaWduaW5nIGNvbnN0cnVjdG9yLWNvbnN1bWVkXG4gICAqIGF0dHJpYnV0ZXMgdHdpY2UuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vZmFjdG9yeS1ydW5uZXIuanNcIikuQ29tcGlsZWRQbGFufSBwbGFuIC0gQ29tcGlsZWQgcGxhbi5cbiAgICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCA/Pn0gcHVibGljQXR0cmlidXRlcyAtIEV2YWx1YXRlZCBwdWJsaWMgYXR0cmlidXRlcy5cbiAgICogQHBhcmFtIHtFdmFsdWF0aW9uQ29udGV4dH0gY29udGV4dCAtIEV2YWx1YXRpb24gY29udGV4dC5cbiAgICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCA/Pn0gdHJhbnNpZW50cyAtIEV2YWx1YXRlZCB0cmFuc2llbnRzLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTw/Pn0gLSBUaGUgY29uc3RydWN0ZWQgcmVjb3JkLlxuICAgKi9cbiAgYXN5bmMgX2NvbnN0cnVjdFJlY29yZChwbGFuLCBwdWJsaWNBdHRyaWJ1dGVzLCBjb250ZXh0LCB0cmFuc2llbnRzKSB7XG4gICAgY29uc3QgTW9kZWxDbGFzcyA9IGFzc2VydE1vZGVsQ2xhc3MocGxhbi5tb2RlbENsYXNzLCBwbGFuLmZhY3RvcnlOYW1lKVxuXG4gICAgaWYgKHBsYW4uaW5pdGlhbGl6ZVdpdGgpIHtcbiAgICAgIHJldHVybiBhd2FpdCB0aGlzLl9jb25zdHJ1Y3RXaXRoSW5pdGlhbGl6ZXIocGxhbiwgTW9kZWxDbGFzcywgcHVibGljQXR0cmlidXRlcywgY29udGV4dCwgdHJhbnNpZW50cylcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IE1vZGVsQ2xhc3MocHVibGljQXR0cmlidXRlcylcbiAgfVxuXG4gIC8qKlxuICAgKiBDb25zdHJ1Y3RzIGEgcmVjb3JkIHZpYSBhIGN1c3RvbSBgaW5pdGlhbGl6ZVdpdGhgLCB0cmFja2luZyB3aGljaCBhdHRyaWJ1dGVzXG4gICAqIHRoZSBjb25zdHJ1Y3RvciBjb25zdW1lZCB0aHJvdWdoIGl0cyBgZ2V0KG5hbWUpYCBhY2Nlc3NvciBhbmQgYXNzaWduaW5nIG9ubHlcbiAgICogdGhlIHJlbWFpbmluZyBwdWJsaWMgYXR0cmlidXRlcyBhZnRlcndhcmRzLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL2ZhY3RvcnktcnVubmVyLmpzXCIpLkNvbXBpbGVkUGxhbn0gcGxhbiAtIENvbXBpbGVkIHBsYW4uXG4gICAqIEBwYXJhbSB7bmV3IChhdHRyaWJ1dGVzPzogUmVjb3JkPHN0cmluZywgPz4pID0+IGltcG9ydChcIi4uLy4uLy4uL2RhdGFiYXNlL3JlY29yZC9pbmRleC5qc1wiKS5kZWZhdWx0fSBNb2RlbENsYXNzIC0gVmFsaWRhdGVkIGRlY2xhcmVkIG1vZGVsIGNsYXNzLlxuICAgKiBAcGFyYW0ge1JlY29yZDxzdHJpbmcsID8+fSBwdWJsaWNBdHRyaWJ1dGVzIC0gRXZhbHVhdGVkIHB1YmxpYyBhdHRyaWJ1dGVzLlxuICAgKiBAcGFyYW0ge0V2YWx1YXRpb25Db250ZXh0fSBjb250ZXh0IC0gRXZhbHVhdGlvbiBjb250ZXh0LlxuICAgKiBAcGFyYW0ge1JlY29yZDxzdHJpbmcsID8+fSB0cmFuc2llbnRzIC0gRXZhbHVhdGVkIHRyYW5zaWVudHMuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPD8+fSAtIFRoZSBjb25zdHJ1Y3RlZCByZWNvcmQuXG4gICAqL1xuICBhc3luYyBfY29uc3RydWN0V2l0aEluaXRpYWxpemVyKHBsYW4sIE1vZGVsQ2xhc3MsIHB1YmxpY0F0dHJpYnV0ZXMsIGNvbnRleHQsIHRyYW5zaWVudHMpIHtcbiAgICAvKiogQHR5cGUge1NldDxzdHJpbmc+fSAqL1xuICAgIGNvbnN0IGNvbnN1bWVkID0gbmV3IFNldCgpXG4gICAgY29uc3QgZ2V0ID0gKC8qKiBAdHlwZSB7c3RyaW5nfSAqLyBuYW1lKSA9PiB7XG4gICAgICBjb25zdW1lZC5hZGQobmFtZSlcblxuICAgICAgcmV0dXJuIHB1YmxpY0F0dHJpYnV0ZXNbbmFtZV1cbiAgICB9XG4gICAgY29uc3QgaW5pdGlhbGl6ZVdpdGggPSAvKiogQHR5cGUge2ltcG9ydChcIi4uL2RlY2xhcmF0aW9ucy5qc1wiKS5Jbml0aWFsaXplV2l0aERlY2xhcmF0aW9uW1wiZm5cIl19ICovIChwbGFuLmluaXRpYWxpemVXaXRoKVxuICAgIGNvbnN0IHJlY29yZCA9IGF3YWl0IGluaXRpYWxpemVXaXRoKHthdHRyaWJ1dGVzOiB7Li4ucHVibGljQXR0cmlidXRlc30sIGdldCwgY29udGV4dDogdGhpcy5fY2FsbGJhY2tDb250ZXh0KGNvbnRleHQsIHRyYW5zaWVudHMpfSlcblxuICAgIGlmICghKHJlY29yZCBpbnN0YW5jZW9mIE1vZGVsQ2xhc3MpKSB7XG4gICAgICB0aHJvdyBuZXcgTW9kZWxDb250cmFjdEVycm9yKGBGYWN0b3J5IFwiJHtwbGFuLmZhY3RvcnlOYW1lfVwiIGluaXRpYWxpemVXaXRoIG11c3QgcmV0dXJuIGFuIGluc3RhbmNlIG9mICR7TW9kZWxDbGFzcy5uYW1lfSwgZ290OiAke1N0cmluZyhyZWNvcmQpfWApXG4gICAgfVxuXG4gICAgLyoqIEB0eXBlIHtSZWNvcmQ8c3RyaW5nLCA/Pn0gKi9cbiAgICBjb25zdCByZW1haW5pbmcgPSB7fVxuXG4gICAgZm9yIChjb25zdCBrZXkgb2YgT2JqZWN0LmtleXMocHVibGljQXR0cmlidXRlcykpIHtcbiAgICAgIGlmICghY29uc3VtZWQuaGFzKGtleSkpIHJlbWFpbmluZ1trZXldID0gcHVibGljQXR0cmlidXRlc1trZXldXG4gICAgfVxuXG4gICAgaWYgKE9iamVjdC5rZXlzKHJlbWFpbmluZykubGVuZ3RoID4gMCkge1xuICAgICAgLyoqIEB0eXBlIHs/fSAqLyAocmVjb3JkKS5hc3NpZ24ocmVtYWluaW5nKVxuICAgIH1cblxuICAgIHJldHVybiByZWNvcmRcbiAgfVxuXG4gIC8qKlxuICAgKiBXaXJlcyBldmFsdWF0ZWQgYXNzb2NpYXRpb25zIG9udG8gYSByZWNvcmQgdGhyb3VnaCBwdWJsaWMgcmVsYXRpb25zaGlwXG4gICAqIHJlZmxlY3Rpb24gYW5kIGdlbmVyYXRlZCBzZXR0ZXJzIChuZXZlciBwcml2YXRlIGNhY2hlcyBvciBndWVzc2VkIGtleXMpLlxuICAgKiBAcGFyYW0gez99IHJlY29yZCAtIFRoZSBvd25pbmcgcmVjb3JkLlxuICAgKiBAcGFyYW0ge0FycmF5PHtuYW1lOiBzdHJpbmcsIHJlY29yZDogP30+fSBhc3NvY2lhdGlvbnMgLSBFdmFsdWF0ZWQgYXNzb2NpYXRpb25zLlxuICAgKiBAcmV0dXJucyB7dm9pZH1cbiAgICovXG4gIF9hc3NpZ25Bc3NvY2lhdGlvbnMocmVjb3JkLCBhc3NvY2lhdGlvbnMpIHtcbiAgICBmb3IgKGNvbnN0IHtuYW1lLCByZWNvcmQ6IGFzc29jaWF0ZWRSZWNvcmR9IG9mIGFzc29jaWF0aW9ucykge1xuICAgICAgY29uc3QgaW5zdGFuY2VSZWxhdGlvbnNoaXAgPSByZWNvcmQuZ2V0UmVsYXRpb25zaGlwQnlOYW1lKG5hbWUpXG4gICAgICBjb25zdCByZWxhdGlvbnNoaXBUeXBlID0gaW5zdGFuY2VSZWxhdGlvbnNoaXAuZ2V0VHlwZSgpXG5cbiAgICAgIGlmIChyZWxhdGlvbnNoaXBUeXBlID09PSBcImJlbG9uZ3NUb1wiKSB7XG4gICAgICAgIHJlY29yZFtgc2V0JHtpbmZsZWN0aW9uLmNhbWVsaXplKG5hbWUpfWBdKGFzc29jaWF0ZWRSZWNvcmQgfHwgbnVsbClcbiAgICAgIH0gZWxzZSBpZiAocmVsYXRpb25zaGlwVHlwZSA9PT0gXCJoYXNPbmVcIikge1xuICAgICAgICBpbnN0YW5jZVJlbGF0aW9uc2hpcC5zZXRMb2FkZWQoYXNzb2NpYXRlZFJlY29yZCB8fCB1bmRlZmluZWQpXG4gICAgICB9IGVsc2UgaWYgKHJlbGF0aW9uc2hpcFR5cGUgPT09IFwiaGFzTWFueVwiKSB7XG4gICAgICAgIGluc3RhbmNlUmVsYXRpb25zaGlwLnNldExvYWRlZCh0aGlzLl90b1JlY29yZEFycmF5KGFzc29jaWF0ZWRSZWNvcmQpKVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBOb3JtYWxpemVzIGEgaGFzLW1hbnkgYXNzb2NpYXRpb24gdmFsdWUgaW50byBhbiBhcnJheSBvZiByZWNvcmRzLlxuICAgKiBAcGFyYW0gez99IHZhbHVlIC0gQXNzb2NpYXRpb24gdmFsdWUgKHJlY29yZCwgYXJyYXksIG9yIG51bGwpLlxuICAgKiBAcmV0dXJucyB7QXJyYXk8Pz59IC0gVGhlIG5vcm1hbGl6ZWQgcmVjb3JkIGFycmF5LlxuICAgKi9cbiAgX3RvUmVjb3JkQXJyYXkodmFsdWUpIHtcbiAgICBpZiAodmFsdWUgPT0gbnVsbCkgcmV0dXJuIFtdXG4gICAgaWYgKEFycmF5LmlzQXJyYXkodmFsdWUpKSByZXR1cm4gdmFsdWVcblxuICAgIHJldHVybiBbdmFsdWVdXG4gIH1cbn1cbiJdfQ==
@@ -0,0 +1,20 @@
1
+ /**
2
+ * The `build` strategy. It recursively builds associated models (using the parent
3
+ * strategy) and constructs the root record without persisting anything. Runs the
4
+ * beforeAll/beforeBuild/afterBuild callbacks and guarantees afterAll cleanup.
5
+ */
6
+ export default class BuildStrategy extends BaseStrategy {
7
+ /**
8
+ * Runs the strategy.
9
+ * @param {object} args - Options.
10
+ * @param {import("../factory-registry.js").default} args.registry - Owning registry.
11
+ * @param {import("../factory-runner.js").CompiledPlan} args.plan - Compiled plan.
12
+ * @returns {Promise<?>} - The built (unsaved) record.
13
+ */
14
+ run({ registry, plan }: {
15
+ registry: import("../factory-registry.js").default;
16
+ plan: import("../factory-runner.js").CompiledPlan;
17
+ }): Promise<unknown>;
18
+ }
19
+ import BaseStrategy from "./base.js";
20
+ //# sourceMappingURL=build.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../../../../src/testing/factory/strategies/build.js"],"names":[],"mappings":"AAIA;;;;GAIG;AACH;IACE;;;;;;OAMG;IACH,wBAJG;QAAuD,QAAQ,EAAvD,OAAO,wBAAwB,EAAE,OAAO;QACU,IAAI,EAAtD,OAAO,sBAAsB,EAAE,YAAY;KACnD,GAAU,OAAO,CAAC,OAAC,CAAC,CAyBtB;CACF;yBAvCwB,WAAW"}
@@ -0,0 +1,34 @@
1
+ // @ts-check
2
+ import BaseStrategy from "./base.js";
3
+ /**
4
+ * The `build` strategy. It recursively builds associated models (using the parent
5
+ * strategy) and constructs the root record without persisting anything. Runs the
6
+ * beforeAll/beforeBuild/afterBuild callbacks and guarantees afterAll cleanup.
7
+ */
8
+ export default class BuildStrategy extends BaseStrategy {
9
+ /**
10
+ * Runs the strategy.
11
+ * @param {object} args - Options.
12
+ * @param {import("../factory-registry.js").default} args.registry - Owning registry.
13
+ * @param {import("../factory-runner.js").CompiledPlan} args.plan - Compiled plan.
14
+ * @returns {Promise<?>} - The built (unsaved) record.
15
+ */
16
+ async run({ registry, plan }) {
17
+ const context = this._newContext(registry, plan, "build");
18
+ /** @type {{record: ?, transients: Record<string, ?>}} */
19
+ const runState = { record: undefined, transients: {} };
20
+ const state = () => ({ record: runState.record, transients: runState.transients, strategy: "build" });
21
+ return await this._runWithAfterAll(context, plan, state, async () => {
22
+ runState.transients = await context.resolveTransients();
23
+ await this._runCallbacks(context, plan, "beforeAll", state());
24
+ await this._runCallbacks(context, plan, "beforeBuild", state());
25
+ const { publicAttributes, transients, associations } = await context.resolveForConstruction();
26
+ const record = await this._constructRecord(plan, publicAttributes, context, transients);
27
+ this._assignAssociations(record, associations);
28
+ runState.record = record;
29
+ await this._runCallbacks(context, plan, "afterBuild", state());
30
+ return record;
31
+ });
32
+ }
33
+ }
34
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnVpbGQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvdGVzdGluZy9mYWN0b3J5L3N0cmF0ZWdpZXMvYnVpbGQuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsWUFBWTtBQUVaLE9BQU8sWUFBWSxNQUFNLFdBQVcsQ0FBQTtBQUVwQzs7OztHQUlHO0FBQ0gsTUFBTSxDQUFDLE9BQU8sT0FBTyxhQUFjLFNBQVEsWUFBWTtJQUNyRDs7Ozs7O09BTUc7SUFDSCxLQUFLLENBQUMsR0FBRyxDQUFDLEVBQUMsUUFBUSxFQUFFLElBQUksRUFBQztRQUN4QixNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLFFBQVEsRUFBRSxJQUFJLEVBQUUsT0FBTyxDQUFDLENBQUE7UUFDekQseURBQXlEO1FBQ3pELE1BQU0sUUFBUSxHQUFHLEVBQUMsTUFBTSxFQUFFLFNBQVMsRUFBRSxVQUFVLEVBQUUsRUFBRSxFQUFDLENBQUE7UUFDcEQsTUFBTSxLQUFLLEdBQUcsR0FBRyxFQUFFLENBQUMsQ0FBQyxFQUFDLE1BQU0sRUFBRSxRQUFRLENBQUMsTUFBTSxFQUFFLFVBQVUsRUFBRSxRQUFRLENBQUMsVUFBVSxFQUFFLFFBQVEsRUFBRSxPQUFPLEVBQUMsQ0FBQyxDQUFBO1FBRW5HLE9BQU8sTUFBTSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsS0FBSyxJQUFJLEVBQUU7WUFDbEUsUUFBUSxDQUFDLFVBQVUsR0FBRyxNQUFNLE9BQU8sQ0FBQyxpQkFBaUIsRUFBRSxDQUFBO1lBRXZELE1BQU0sSUFBSSxDQUFDLGFBQWEsQ0FBQyxPQUFPLEVBQUUsSUFBSSxFQUFFLFdBQVcsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFBO1lBQzdELE1BQU0sSUFBSSxDQUFDLGFBQWEsQ0FBQyxPQUFPLEVBQUUsSUFBSSxFQUFFLGFBQWEsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFBO1lBRS9ELE1BQU0sRUFBQyxnQkFBZ0IsRUFBRSxVQUFVLEVBQUUsWUFBWSxFQUFDLEdBQUcsTUFBTSxPQUFPLENBQUMsc0JBQXNCLEVBQUUsQ0FBQTtZQUUzRixNQUFNLE1BQU0sR0FBRyxNQUFNLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLEVBQUUsZ0JBQWdCLEVBQUUsT0FBTyxFQUFFLFVBQVUsQ0FBQyxDQUFBO1lBRXZGLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxNQUFNLEVBQUUsWUFBWSxDQUFDLENBQUE7WUFDOUMsUUFBUSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUE7WUFFeEIsTUFBTSxJQUFJLENBQUMsYUFBYSxDQUFDLE9BQU8sRUFBRSxJQUFJLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUE7WUFFOUQsT0FBTyxNQUFNLENBQUE7UUFDZixDQUFDLENBQUMsQ0FBQTtJQUNKLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbIi8vIEB0cy1jaGVja1xuXG5pbXBvcnQgQmFzZVN0cmF0ZWd5IGZyb20gXCIuL2Jhc2UuanNcIlxuXG4vKipcbiAqIFRoZSBgYnVpbGRgIHN0cmF0ZWd5LiBJdCByZWN1cnNpdmVseSBidWlsZHMgYXNzb2NpYXRlZCBtb2RlbHMgKHVzaW5nIHRoZSBwYXJlbnRcbiAqIHN0cmF0ZWd5KSBhbmQgY29uc3RydWN0cyB0aGUgcm9vdCByZWNvcmQgd2l0aG91dCBwZXJzaXN0aW5nIGFueXRoaW5nLiBSdW5zIHRoZVxuICogYmVmb3JlQWxsL2JlZm9yZUJ1aWxkL2FmdGVyQnVpbGQgY2FsbGJhY2tzIGFuZCBndWFyYW50ZWVzIGFmdGVyQWxsIGNsZWFudXAuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEJ1aWxkU3RyYXRlZ3kgZXh0ZW5kcyBCYXNlU3RyYXRlZ3kge1xuICAvKipcbiAgICogUnVucyB0aGUgc3RyYXRlZ3kuXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBhcmdzIC0gT3B0aW9ucy5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9mYWN0b3J5LXJlZ2lzdHJ5LmpzXCIpLmRlZmF1bHR9IGFyZ3MucmVnaXN0cnkgLSBPd25pbmcgcmVnaXN0cnkuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vZmFjdG9yeS1ydW5uZXIuanNcIikuQ29tcGlsZWRQbGFufSBhcmdzLnBsYW4gLSBDb21waWxlZCBwbGFuLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTw/Pn0gLSBUaGUgYnVpbHQgKHVuc2F2ZWQpIHJlY29yZC5cbiAgICovXG4gIGFzeW5jIHJ1bih7cmVnaXN0cnksIHBsYW59KSB7XG4gICAgY29uc3QgY29udGV4dCA9IHRoaXMuX25ld0NvbnRleHQocmVnaXN0cnksIHBsYW4sIFwiYnVpbGRcIilcbiAgICAvKiogQHR5cGUge3tyZWNvcmQ6ID8sIHRyYW5zaWVudHM6IFJlY29yZDxzdHJpbmcsID8+fX0gKi9cbiAgICBjb25zdCBydW5TdGF0ZSA9IHtyZWNvcmQ6IHVuZGVmaW5lZCwgdHJhbnNpZW50czoge319XG4gICAgY29uc3Qgc3RhdGUgPSAoKSA9PiAoe3JlY29yZDogcnVuU3RhdGUucmVjb3JkLCB0cmFuc2llbnRzOiBydW5TdGF0ZS50cmFuc2llbnRzLCBzdHJhdGVneTogXCJidWlsZFwifSlcblxuICAgIHJldHVybiBhd2FpdCB0aGlzLl9ydW5XaXRoQWZ0ZXJBbGwoY29udGV4dCwgcGxhbiwgc3RhdGUsIGFzeW5jICgpID0+IHtcbiAgICAgIHJ1blN0YXRlLnRyYW5zaWVudHMgPSBhd2FpdCBjb250ZXh0LnJlc29sdmVUcmFuc2llbnRzKClcblxuICAgICAgYXdhaXQgdGhpcy5fcnVuQ2FsbGJhY2tzKGNvbnRleHQsIHBsYW4sIFwiYmVmb3JlQWxsXCIsIHN0YXRlKCkpXG4gICAgICBhd2FpdCB0aGlzLl9ydW5DYWxsYmFja3MoY29udGV4dCwgcGxhbiwgXCJiZWZvcmVCdWlsZFwiLCBzdGF0ZSgpKVxuXG4gICAgICBjb25zdCB7cHVibGljQXR0cmlidXRlcywgdHJhbnNpZW50cywgYXNzb2NpYXRpb25zfSA9IGF3YWl0IGNvbnRleHQucmVzb2x2ZUZvckNvbnN0cnVjdGlvbigpXG5cbiAgICAgIGNvbnN0IHJlY29yZCA9IGF3YWl0IHRoaXMuX2NvbnN0cnVjdFJlY29yZChwbGFuLCBwdWJsaWNBdHRyaWJ1dGVzLCBjb250ZXh0LCB0cmFuc2llbnRzKVxuXG4gICAgICB0aGlzLl9hc3NpZ25Bc3NvY2lhdGlvbnMocmVjb3JkLCBhc3NvY2lhdGlvbnMpXG4gICAgICBydW5TdGF0ZS5yZWNvcmQgPSByZWNvcmRcblxuICAgICAgYXdhaXQgdGhpcy5fcnVuQ2FsbGJhY2tzKGNvbnRleHQsIHBsYW4sIFwiYWZ0ZXJCdWlsZFwiLCBzdGF0ZSgpKVxuXG4gICAgICByZXR1cm4gcmVjb3JkXG4gICAgfSlcbiAgfVxufVxuIl19
@@ -0,0 +1,32 @@
1
+ /**
2
+ * The `create` strategy. It builds the object graph (associations use the parent
3
+ * create strategy by default), runs beforeAll/beforeBuild/afterBuild, persists the
4
+ * root record through its native `save()` (letting Velocious own association
5
+ * autosave order and validation) or a custom `toCreate`, then runs
6
+ * beforeCreate/afterCreate and guarantees afterAll cleanup.
7
+ */
8
+ export default class CreateStrategy extends BaseStrategy {
9
+ /**
10
+ * Runs the strategy.
11
+ * @param {object} args - Options.
12
+ * @param {import("../factory-registry.js").default} args.registry - Owning registry.
13
+ * @param {import("../factory-runner.js").CompiledPlan} args.plan - Compiled plan.
14
+ * @returns {Promise<?>} - The persisted record.
15
+ */
16
+ run({ registry, plan }: {
17
+ registry: import("../factory-registry.js").default;
18
+ plan: import("../factory-runner.js").CompiledPlan;
19
+ }): Promise<unknown>;
20
+ /**
21
+ * Persists the record via a custom `toCreate`, native `save()`, or not at all
22
+ * when `skipCreate` is declared.
23
+ * @param {import("../factory-runner.js").CompiledPlan} plan - Compiled plan.
24
+ * @param {?} record - The record to persist.
25
+ * @param {import("../evaluation-context.js").default} context - Evaluation context.
26
+ * @param {Record<string, ?>} transients - Evaluated transients.
27
+ * @returns {Promise<void>} - Resolves when persistence completes.
28
+ */
29
+ _persist(plan: import("../factory-runner.js").CompiledPlan, record: unknown, context: import("../evaluation-context.js").default, transients: Record<string, unknown>): Promise<void>;
30
+ }
31
+ import BaseStrategy from "./base.js";
32
+ //# sourceMappingURL=create.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../../../../src/testing/factory/strategies/create.js"],"names":[],"mappings":"AAIA;;;;;;GAMG;AACH;IACE;;;;;;OAMG;IACH,wBAJG;QAAuD,QAAQ,EAAvD,OAAO,wBAAwB,EAAE,OAAO;QACU,IAAI,EAAtD,OAAO,sBAAsB,EAAE,YAAY;KACnD,GAAU,OAAO,CAAC,OAAC,CAAC,CA4BtB;IAED;;;;;;;;OAQG;IACH,eANW,OAAO,sBAAsB,EAAE,YAAY,UAC3C,OAAC,WACD,OAAO,0BAA0B,EAAE,OAAO,cAC1C,MAAM,CAAC,MAAM,EAAE,OAAC,CAAC,GACf,OAAO,CAAC,IAAI,CAAC,CAYzB;CACF;yBAjEwB,WAAW"}
@@ -0,0 +1,57 @@
1
+ // @ts-check
2
+ import BaseStrategy from "./base.js";
3
+ /**
4
+ * The `create` strategy. It builds the object graph (associations use the parent
5
+ * create strategy by default), runs beforeAll/beforeBuild/afterBuild, persists the
6
+ * root record through its native `save()` (letting Velocious own association
7
+ * autosave order and validation) or a custom `toCreate`, then runs
8
+ * beforeCreate/afterCreate and guarantees afterAll cleanup.
9
+ */
10
+ export default class CreateStrategy extends BaseStrategy {
11
+ /**
12
+ * Runs the strategy.
13
+ * @param {object} args - Options.
14
+ * @param {import("../factory-registry.js").default} args.registry - Owning registry.
15
+ * @param {import("../factory-runner.js").CompiledPlan} args.plan - Compiled plan.
16
+ * @returns {Promise<?>} - The persisted record.
17
+ */
18
+ async run({ registry, plan }) {
19
+ const context = this._newContext(registry, plan, "create");
20
+ /** @type {{record: ?, transients: Record<string, ?>}} */
21
+ const runState = { record: undefined, transients: {} };
22
+ const state = () => ({ record: runState.record, transients: runState.transients, strategy: "create" });
23
+ return await this._runWithAfterAll(context, plan, state, async () => {
24
+ runState.transients = await context.resolveTransients();
25
+ await this._runCallbacks(context, plan, "beforeAll", state());
26
+ await this._runCallbacks(context, plan, "beforeBuild", state());
27
+ const { publicAttributes, transients, associations } = await context.resolveForConstruction();
28
+ const record = await this._constructRecord(plan, publicAttributes, context, transients);
29
+ this._assignAssociations(record, associations);
30
+ runState.record = record;
31
+ await this._runCallbacks(context, plan, "afterBuild", state());
32
+ await this._runCallbacks(context, plan, "beforeCreate", state());
33
+ await this._persist(plan, record, context, transients);
34
+ await this._runCallbacks(context, plan, "afterCreate", state());
35
+ return record;
36
+ });
37
+ }
38
+ /**
39
+ * Persists the record via a custom `toCreate`, native `save()`, or not at all
40
+ * when `skipCreate` is declared.
41
+ * @param {import("../factory-runner.js").CompiledPlan} plan - Compiled plan.
42
+ * @param {?} record - The record to persist.
43
+ * @param {import("../evaluation-context.js").default} context - Evaluation context.
44
+ * @param {Record<string, ?>} transients - Evaluated transients.
45
+ * @returns {Promise<void>} - Resolves when persistence completes.
46
+ */
47
+ async _persist(plan, record, context, transients) {
48
+ if (plan.skipCreate)
49
+ return;
50
+ if (plan.toCreate) {
51
+ await plan.toCreate({ record, context: this._callbackContext(context, transients) });
52
+ return;
53
+ }
54
+ await record.save();
55
+ }
56
+ }
57
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY3JlYXRlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL3Rlc3RpbmcvZmFjdG9yeS9zdHJhdGVnaWVzL2NyZWF0ZS5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxZQUFZO0FBRVosT0FBTyxZQUFZLE1BQU0sV0FBVyxDQUFBO0FBRXBDOzs7Ozs7R0FNRztBQUNILE1BQU0sQ0FBQyxPQUFPLE9BQU8sY0FBZSxTQUFRLFlBQVk7SUFDdEQ7Ozs7OztPQU1HO0lBQ0gsS0FBSyxDQUFDLEdBQUcsQ0FBQyxFQUFDLFFBQVEsRUFBRSxJQUFJLEVBQUM7UUFDeEIsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxRQUFRLEVBQUUsSUFBSSxFQUFFLFFBQVEsQ0FBQyxDQUFBO1FBQzFELHlEQUF5RDtRQUN6RCxNQUFNLFFBQVEsR0FBRyxFQUFDLE1BQU0sRUFBRSxTQUFTLEVBQUUsVUFBVSxFQUFFLEVBQUUsRUFBQyxDQUFBO1FBQ3BELE1BQU0sS0FBSyxHQUFHLEdBQUcsRUFBRSxDQUFDLENBQUMsRUFBQyxNQUFNLEVBQUUsUUFBUSxDQUFDLE1BQU0sRUFBRSxVQUFVLEVBQUUsUUFBUSxDQUFDLFVBQVUsRUFBRSxRQUFRLEVBQUUsUUFBUSxFQUFDLENBQUMsQ0FBQTtRQUVwRyxPQUFPLE1BQU0sSUFBSSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLEtBQUssSUFBSSxFQUFFO1lBQ2xFLFFBQVEsQ0FBQyxVQUFVLEdBQUcsTUFBTSxPQUFPLENBQUMsaUJBQWlCLEVBQUUsQ0FBQTtZQUV2RCxNQUFNLElBQUksQ0FBQyxhQUFhLENBQUMsT0FBTyxFQUFFLElBQUksRUFBRSxXQUFXLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQTtZQUM3RCxNQUFNLElBQUksQ0FBQyxhQUFhLENBQUMsT0FBTyxFQUFFLElBQUksRUFBRSxhQUFhLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQTtZQUUvRCxNQUFNLEVBQUMsZ0JBQWdCLEVBQUUsVUFBVSxFQUFFLFlBQVksRUFBQyxHQUFHLE1BQU0sT0FBTyxDQUFDLHNCQUFzQixFQUFFLENBQUE7WUFFM0YsTUFBTSxNQUFNLEdBQUcsTUFBTSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxFQUFFLGdCQUFnQixFQUFFLE9BQU8sRUFBRSxVQUFVLENBQUMsQ0FBQTtZQUV2RixJQUFJLENBQUMsbUJBQW1CLENBQUMsTUFBTSxFQUFFLFlBQVksQ0FBQyxDQUFBO1lBQzlDLFFBQVEsQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFBO1lBRXhCLE1BQU0sSUFBSSxDQUFDLGFBQWEsQ0FBQyxPQUFPLEVBQUUsSUFBSSxFQUFFLFlBQVksRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFBO1lBQzlELE1BQU0sSUFBSSxDQUFDLGFBQWEsQ0FBQyxPQUFPLEVBQUUsSUFBSSxFQUFFLGNBQWMsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFBO1lBQ2hFLE1BQU0sSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxVQUFVLENBQUMsQ0FBQTtZQUN0RCxNQUFNLElBQUksQ0FBQyxhQUFhLENBQUMsT0FBTyxFQUFFLElBQUksRUFBRSxhQUFhLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQTtZQUUvRCxPQUFPLE1BQU0sQ0FBQTtRQUNmLENBQUMsQ0FBQyxDQUFBO0lBQ0osQ0FBQztJQUVEOzs7Ozs7OztPQVFHO0lBQ0gsS0FBSyxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxVQUFVO1FBQzlDLElBQUksSUFBSSxDQUFDLFVBQVU7WUFBRSxPQUFNO1FBRTNCLElBQUksSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1lBQ2xCLE1BQU0sSUFBSSxDQUFDLFFBQVEsQ0FBQyxFQUFDLE1BQU0sRUFBRSxPQUFPLEVBQUUsSUFBSSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sRUFBRSxVQUFVLENBQUMsRUFBQyxDQUFDLENBQUE7WUFFbEYsT0FBTTtRQUNSLENBQUM7UUFFRCxNQUFNLE1BQU0sQ0FBQyxJQUFJLEVBQUUsQ0FBQTtJQUNyQixDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBAdHMtY2hlY2tcblxuaW1wb3J0IEJhc2VTdHJhdGVneSBmcm9tIFwiLi9iYXNlLmpzXCJcblxuLyoqXG4gKiBUaGUgYGNyZWF0ZWAgc3RyYXRlZ3kuIEl0IGJ1aWxkcyB0aGUgb2JqZWN0IGdyYXBoIChhc3NvY2lhdGlvbnMgdXNlIHRoZSBwYXJlbnRcbiAqIGNyZWF0ZSBzdHJhdGVneSBieSBkZWZhdWx0KSwgcnVucyBiZWZvcmVBbGwvYmVmb3JlQnVpbGQvYWZ0ZXJCdWlsZCwgcGVyc2lzdHMgdGhlXG4gKiByb290IHJlY29yZCB0aHJvdWdoIGl0cyBuYXRpdmUgYHNhdmUoKWAgKGxldHRpbmcgVmVsb2Npb3VzIG93biBhc3NvY2lhdGlvblxuICogYXV0b3NhdmUgb3JkZXIgYW5kIHZhbGlkYXRpb24pIG9yIGEgY3VzdG9tIGB0b0NyZWF0ZWAsIHRoZW4gcnVuc1xuICogYmVmb3JlQ3JlYXRlL2FmdGVyQ3JlYXRlIGFuZCBndWFyYW50ZWVzIGFmdGVyQWxsIGNsZWFudXAuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIENyZWF0ZVN0cmF0ZWd5IGV4dGVuZHMgQmFzZVN0cmF0ZWd5IHtcbiAgLyoqXG4gICAqIFJ1bnMgdGhlIHN0cmF0ZWd5LlxuICAgKiBAcGFyYW0ge29iamVjdH0gYXJncyAtIE9wdGlvbnMuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vZmFjdG9yeS1yZWdpc3RyeS5qc1wiKS5kZWZhdWx0fSBhcmdzLnJlZ2lzdHJ5IC0gT3duaW5nIHJlZ2lzdHJ5LlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL2ZhY3RvcnktcnVubmVyLmpzXCIpLkNvbXBpbGVkUGxhbn0gYXJncy5wbGFuIC0gQ29tcGlsZWQgcGxhbi5cbiAgICogQHJldHVybnMge1Byb21pc2U8Pz59IC0gVGhlIHBlcnNpc3RlZCByZWNvcmQuXG4gICAqL1xuICBhc3luYyBydW4oe3JlZ2lzdHJ5LCBwbGFufSkge1xuICAgIGNvbnN0IGNvbnRleHQgPSB0aGlzLl9uZXdDb250ZXh0KHJlZ2lzdHJ5LCBwbGFuLCBcImNyZWF0ZVwiKVxuICAgIC8qKiBAdHlwZSB7e3JlY29yZDogPywgdHJhbnNpZW50czogUmVjb3JkPHN0cmluZywgPz59fSAqL1xuICAgIGNvbnN0IHJ1blN0YXRlID0ge3JlY29yZDogdW5kZWZpbmVkLCB0cmFuc2llbnRzOiB7fX1cbiAgICBjb25zdCBzdGF0ZSA9ICgpID0+ICh7cmVjb3JkOiBydW5TdGF0ZS5yZWNvcmQsIHRyYW5zaWVudHM6IHJ1blN0YXRlLnRyYW5zaWVudHMsIHN0cmF0ZWd5OiBcImNyZWF0ZVwifSlcblxuICAgIHJldHVybiBhd2FpdCB0aGlzLl9ydW5XaXRoQWZ0ZXJBbGwoY29udGV4dCwgcGxhbiwgc3RhdGUsIGFzeW5jICgpID0+IHtcbiAgICAgIHJ1blN0YXRlLnRyYW5zaWVudHMgPSBhd2FpdCBjb250ZXh0LnJlc29sdmVUcmFuc2llbnRzKClcblxuICAgICAgYXdhaXQgdGhpcy5fcnVuQ2FsbGJhY2tzKGNvbnRleHQsIHBsYW4sIFwiYmVmb3JlQWxsXCIsIHN0YXRlKCkpXG4gICAgICBhd2FpdCB0aGlzLl9ydW5DYWxsYmFja3MoY29udGV4dCwgcGxhbiwgXCJiZWZvcmVCdWlsZFwiLCBzdGF0ZSgpKVxuXG4gICAgICBjb25zdCB7cHVibGljQXR0cmlidXRlcywgdHJhbnNpZW50cywgYXNzb2NpYXRpb25zfSA9IGF3YWl0IGNvbnRleHQucmVzb2x2ZUZvckNvbnN0cnVjdGlvbigpXG5cbiAgICAgIGNvbnN0IHJlY29yZCA9IGF3YWl0IHRoaXMuX2NvbnN0cnVjdFJlY29yZChwbGFuLCBwdWJsaWNBdHRyaWJ1dGVzLCBjb250ZXh0LCB0cmFuc2llbnRzKVxuXG4gICAgICB0aGlzLl9hc3NpZ25Bc3NvY2lhdGlvbnMocmVjb3JkLCBhc3NvY2lhdGlvbnMpXG4gICAgICBydW5TdGF0ZS5yZWNvcmQgPSByZWNvcmRcblxuICAgICAgYXdhaXQgdGhpcy5fcnVuQ2FsbGJhY2tzKGNvbnRleHQsIHBsYW4sIFwiYWZ0ZXJCdWlsZFwiLCBzdGF0ZSgpKVxuICAgICAgYXdhaXQgdGhpcy5fcnVuQ2FsbGJhY2tzKGNvbnRleHQsIHBsYW4sIFwiYmVmb3JlQ3JlYXRlXCIsIHN0YXRlKCkpXG4gICAgICBhd2FpdCB0aGlzLl9wZXJzaXN0KHBsYW4sIHJlY29yZCwgY29udGV4dCwgdHJhbnNpZW50cylcbiAgICAgIGF3YWl0IHRoaXMuX3J1bkNhbGxiYWNrcyhjb250ZXh0LCBwbGFuLCBcImFmdGVyQ3JlYXRlXCIsIHN0YXRlKCkpXG5cbiAgICAgIHJldHVybiByZWNvcmRcbiAgICB9KVxuICB9XG5cbiAgLyoqXG4gICAqIFBlcnNpc3RzIHRoZSByZWNvcmQgdmlhIGEgY3VzdG9tIGB0b0NyZWF0ZWAsIG5hdGl2ZSBgc2F2ZSgpYCwgb3Igbm90IGF0IGFsbFxuICAgKiB3aGVuIGBza2lwQ3JlYXRlYCBpcyBkZWNsYXJlZC5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9mYWN0b3J5LXJ1bm5lci5qc1wiKS5Db21waWxlZFBsYW59IHBsYW4gLSBDb21waWxlZCBwbGFuLlxuICAgKiBAcGFyYW0gez99IHJlY29yZCAtIFRoZSByZWNvcmQgdG8gcGVyc2lzdC5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi9ldmFsdWF0aW9uLWNvbnRleHQuanNcIikuZGVmYXVsdH0gY29udGV4dCAtIEV2YWx1YXRpb24gY29udGV4dC5cbiAgICogQHBhcmFtIHtSZWNvcmQ8c3RyaW5nLCA/Pn0gdHJhbnNpZW50cyAtIEV2YWx1YXRlZCB0cmFuc2llbnRzLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gLSBSZXNvbHZlcyB3aGVuIHBlcnNpc3RlbmNlIGNvbXBsZXRlcy5cbiAgICovXG4gIGFzeW5jIF9wZXJzaXN0KHBsYW4sIHJlY29yZCwgY29udGV4dCwgdHJhbnNpZW50cykge1xuICAgIGlmIChwbGFuLnNraXBDcmVhdGUpIHJldHVyblxuXG4gICAgaWYgKHBsYW4udG9DcmVhdGUpIHtcbiAgICAgIGF3YWl0IHBsYW4udG9DcmVhdGUoe3JlY29yZCwgY29udGV4dDogdGhpcy5fY2FsbGJhY2tDb250ZXh0KGNvbnRleHQsIHRyYW5zaWVudHMpfSlcblxuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgYXdhaXQgcmVjb3JkLnNhdmUoKVxuICB9XG59XG4iXX0=
@@ -0,0 +1,22 @@
1
+ /**
2
+ * An immutable compiled trait. A trait carries an ordered list of declarations
3
+ * (attributes, transients, associations, callbacks, custom construction, and
4
+ * base-trait inclusions) that are mixed into a factory run.
5
+ */
6
+ export default class TraitDefinition {
7
+ /**
8
+ * Builds a trait definition.
9
+ * @param {object} args - Options.
10
+ * @param {string} args.name - Trait name.
11
+ * @param {import("./declarations.js").Declaration[]} args.declarations - Ordered declarations.
12
+ */
13
+ constructor({ name, declarations }: {
14
+ name: string;
15
+ declarations: import("./declarations.js").Declaration[];
16
+ });
17
+ /** @type {string} - Trait name. */
18
+ name: string;
19
+ /** @type {Array<import("./declarations.js").Declaration>} - Ordered declarations. */
20
+ declarations: Array<import("./declarations.js").Declaration>;
21
+ }
22
+ //# sourceMappingURL=trait-definition.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trait-definition.d.ts","sourceRoot":"","sources":["../../../../src/testing/factory/trait-definition.js"],"names":[],"mappings":"AAEA;;;;GAIG;AACH;IACE;;;;;OAKG;IACH,oCAHG;QAAqB,IAAI,EAAjB,MAAM;QAC0C,YAAY,EAA5D,OAAO,mBAAmB,EAAE,WAAW,EAAE;KACnD,EASA;IAPC,mCAAmC;IACnC,MADW,MAAM,CACD;IAEhB,qFAAqF;IACrF,cADW,KAAK,CAAC,OAAO,mBAAmB,EAAE,WAAW,CAAC,CAC2D;CAIvH"}
@@ -0,0 +1,22 @@
1
+ // @ts-check
2
+ /**
3
+ * An immutable compiled trait. A trait carries an ordered list of declarations
4
+ * (attributes, transients, associations, callbacks, custom construction, and
5
+ * base-trait inclusions) that are mixed into a factory run.
6
+ */
7
+ export default class TraitDefinition {
8
+ /**
9
+ * Builds a trait definition.
10
+ * @param {object} args - Options.
11
+ * @param {string} args.name - Trait name.
12
+ * @param {import("./declarations.js").Declaration[]} args.declarations - Ordered declarations.
13
+ */
14
+ constructor({ name, declarations }) {
15
+ /** @type {string} - Trait name. */
16
+ this.name = name;
17
+ /** @type {Array<import("./declarations.js").Declaration>} - Ordered declarations. */
18
+ this.declarations = /** @type {Array<import("./declarations.js").Declaration>} */ (Object.freeze([...declarations]));
19
+ Object.freeze(this);
20
+ }
21
+ }
22
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhaXQtZGVmaW5pdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy90ZXN0aW5nL2ZhY3RvcnkvdHJhaXQtZGVmaW5pdGlvbi5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxZQUFZO0FBRVo7Ozs7R0FJRztBQUNILE1BQU0sQ0FBQyxPQUFPLE9BQU8sZUFBZTtJQUNsQzs7Ozs7T0FLRztJQUNILFlBQVksRUFBQyxJQUFJLEVBQUUsWUFBWSxFQUFDO1FBQzlCLG1DQUFtQztRQUNuQyxJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQTtRQUVoQixxRkFBcUY7UUFDckYsSUFBSSxDQUFDLFlBQVksR0FBRyw2REFBNkQsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxHQUFHLFlBQVksQ0FBQyxDQUFDLENBQUMsQ0FBQTtRQUVwSCxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFBO0lBQ3JCLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbIi8vIEB0cy1jaGVja1xuXG4vKipcbiAqIEFuIGltbXV0YWJsZSBjb21waWxlZCB0cmFpdC4gQSB0cmFpdCBjYXJyaWVzIGFuIG9yZGVyZWQgbGlzdCBvZiBkZWNsYXJhdGlvbnNcbiAqIChhdHRyaWJ1dGVzLCB0cmFuc2llbnRzLCBhc3NvY2lhdGlvbnMsIGNhbGxiYWNrcywgY3VzdG9tIGNvbnN0cnVjdGlvbiwgYW5kXG4gKiBiYXNlLXRyYWl0IGluY2x1c2lvbnMpIHRoYXQgYXJlIG1peGVkIGludG8gYSBmYWN0b3J5IHJ1bi5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgVHJhaXREZWZpbml0aW9uIHtcbiAgLyoqXG4gICAqIEJ1aWxkcyBhIHRyYWl0IGRlZmluaXRpb24uXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBhcmdzIC0gT3B0aW9ucy5cbiAgICogQHBhcmFtIHtzdHJpbmd9IGFyZ3MubmFtZSAtIFRyYWl0IG5hbWUuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9kZWNsYXJhdGlvbnMuanNcIikuRGVjbGFyYXRpb25bXX0gYXJncy5kZWNsYXJhdGlvbnMgLSBPcmRlcmVkIGRlY2xhcmF0aW9ucy5cbiAgICovXG4gIGNvbnN0cnVjdG9yKHtuYW1lLCBkZWNsYXJhdGlvbnN9KSB7XG4gICAgLyoqIEB0eXBlIHtzdHJpbmd9IC0gVHJhaXQgbmFtZS4gKi9cbiAgICB0aGlzLm5hbWUgPSBuYW1lXG5cbiAgICAvKiogQHR5cGUge0FycmF5PGltcG9ydChcIi4vZGVjbGFyYXRpb25zLmpzXCIpLkRlY2xhcmF0aW9uPn0gLSBPcmRlcmVkIGRlY2xhcmF0aW9ucy4gKi9cbiAgICB0aGlzLmRlY2xhcmF0aW9ucyA9IC8qKiBAdHlwZSB7QXJyYXk8aW1wb3J0KFwiLi9kZWNsYXJhdGlvbnMuanNcIikuRGVjbGFyYXRpb24+fSAqLyAoT2JqZWN0LmZyZWV6ZShbLi4uZGVjbGFyYXRpb25zXSkpXG5cbiAgICBPYmplY3QuZnJlZXplKHRoaXMpXG4gIH1cbn1cbiJdfQ==
@@ -0,0 +1,50 @@
1
+ // @ts-check
2
+
3
+ import {InvalidDefinitionError} from "./errors.js"
4
+
5
+ /**
6
+ * A declared association. It records the relationship name, the factory to run
7
+ * (defaulting to the relationship name), any traits/overrides passed to that
8
+ * factory, and an optional explicit strategy. When no strategy is given the
9
+ * association follows the parent strategy at evaluation time.
10
+ */
11
+ export default class AssociationDeclaration {
12
+ /**
13
+ * Builds an association declaration.
14
+ * @param {object} args - Options.
15
+ * @param {string} args.name - Relationship name on the owning model.
16
+ * @param {string} [args.factory] - Factory name to run. Defaults to the relationship name.
17
+ * @param {string[]} [args.traits] - Traits passed to the association factory.
18
+ * @param {Record<string, ?>} [args.overrides] - Overrides passed to the association factory.
19
+ * @param {"build" | "create" | undefined} [args.strategy] - Explicit strategy override.
20
+ */
21
+ constructor({name, factory, traits = [], overrides = {}, strategy}) {
22
+ if (!name || typeof name !== "string") {
23
+ throw new InvalidDefinitionError(`Association name must be a non-empty string, got: ${String(name)}`)
24
+ }
25
+
26
+ if (strategy !== undefined && strategy !== "build" && strategy !== "create") {
27
+ throw new InvalidDefinitionError(`Association strategy must be "build" or "create", got: ${String(strategy)}`)
28
+ }
29
+
30
+ /** @type {"association"} - Discriminant. */
31
+ this.kind = "association"
32
+
33
+ /** @type {string} - Relationship name on the owning model. */
34
+ this.name = name
35
+
36
+ /** @type {string} - Factory name to run for the association. */
37
+ this.factory = factory || name
38
+
39
+ /** @type {string[]} - Traits passed to the association factory. */
40
+ this.traits = traits
41
+
42
+ /** @type {Record<string, ?>} - Overrides passed to the association factory. */
43
+ this.overrides = overrides
44
+
45
+ /** @type {"build" | "create" | undefined} - Explicit strategy override. */
46
+ this.strategy = strategy
47
+
48
+ Object.freeze(this)
49
+ }
50
+ }
@@ -0,0 +1,110 @@
1
+ // @ts-check
2
+
3
+ /**
4
+ * A literal or lazy attribute (or transient) declaration. A function value is the
5
+ * lazy form and receives the evaluator context; any other value is a literal.
6
+ * @typedef {object} AttributeDeclaration
7
+ * @property {"attribute"} kind - Discriminant.
8
+ * @property {string} name - Attribute name.
9
+ * @property {boolean} isTransient - Whether the value is transient (never assigned/returned).
10
+ * @property {?} value - Literal value or lazy `(context) => value` function.
11
+ */
12
+
13
+ /**
14
+ * A lifecycle callback declaration. The same declaration object reached through
15
+ * multiple trait paths runs once per record (dedup is by object identity).
16
+ * @typedef {object} CallbackDeclaration
17
+ * @property {"callback"} kind - Discriminant.
18
+ * @property {string} event - One of the supported callback events.
19
+ * @property {(args: {record: ?, context: ?, strategy: string}) => (void | Promise<void>)} fn - Callback body.
20
+ */
21
+
22
+ /**
23
+ * A base-trait inclusion declaration (a trait applied by default within a factory
24
+ * or composed inside another trait).
25
+ * @typedef {object} TraitIncludeDeclaration
26
+ * @property {"traitInclude"} kind - Discriminant.
27
+ * @property {string} name - Referenced trait name.
28
+ */
29
+
30
+ /**
31
+ * A custom-constructor declaration.
32
+ * @typedef {object} InitializeWithDeclaration
33
+ * @property {"initializeWith"} kind - Discriminant.
34
+ * @property {(args: {attributes: Record<string, ?>, context: ?, get: (name: string) => ?}) => (? | Promise<?>)} fn - Constructor body.
35
+ */
36
+
37
+ /**
38
+ * A custom-persistence declaration.
39
+ * @typedef {object} ToCreateDeclaration
40
+ * @property {"toCreate"} kind - Discriminant.
41
+ * @property {(args: {record: ?, context: ?}) => (void | Promise<void>)} fn - Persistence body.
42
+ */
43
+
44
+ /**
45
+ * A declaration that disables persistence entirely for the create strategy.
46
+ * @typedef {object} SkipCreateDeclaration
47
+ * @property {"skipCreate"} kind - Discriminant.
48
+ */
49
+
50
+ /**
51
+ * Union of every declaration kind stored on a factory/trait definition. Includes
52
+ * association declarations imported from their own module.
53
+ * @typedef {AttributeDeclaration | CallbackDeclaration | TraitIncludeDeclaration | InitializeWithDeclaration | ToCreateDeclaration | SkipCreateDeclaration | import("./association-declaration.js").default} Declaration
54
+ */
55
+
56
+ /**
57
+ * Creates a literal/lazy attribute declaration.
58
+ * @param {string} name - Attribute name.
59
+ * @param {?} value - Literal value or lazy function.
60
+ * @param {boolean} isTransient - Whether the declaration is transient.
61
+ * @returns {AttributeDeclaration} - The frozen declaration.
62
+ */
63
+ export function attributeDeclaration(name, value, isTransient) {
64
+ return Object.freeze({kind: "attribute", name, isTransient, value})
65
+ }
66
+
67
+ /**
68
+ * Creates a lifecycle callback declaration.
69
+ * @param {string} event - Callback event name.
70
+ * @param {CallbackDeclaration["fn"]} fn - Callback body.
71
+ * @returns {CallbackDeclaration} - The frozen declaration.
72
+ */
73
+ export function callbackDeclaration(event, fn) {
74
+ return Object.freeze({kind: "callback", event, fn})
75
+ }
76
+
77
+ /**
78
+ * Creates a base-trait inclusion declaration.
79
+ * @param {string} name - Referenced trait name.
80
+ * @returns {TraitIncludeDeclaration} - The frozen declaration.
81
+ */
82
+ export function traitIncludeDeclaration(name) {
83
+ return Object.freeze({kind: "traitInclude", name})
84
+ }
85
+
86
+ /**
87
+ * Creates a custom-constructor declaration.
88
+ * @param {InitializeWithDeclaration["fn"]} fn - Constructor body.
89
+ * @returns {InitializeWithDeclaration} - The frozen declaration.
90
+ */
91
+ export function initializeWithDeclaration(fn) {
92
+ return Object.freeze({kind: "initializeWith", fn})
93
+ }
94
+
95
+ /**
96
+ * Creates a custom-persistence declaration.
97
+ * @param {ToCreateDeclaration["fn"]} fn - Persistence body.
98
+ * @returns {ToCreateDeclaration} - The frozen declaration.
99
+ */
100
+ export function toCreateDeclaration(fn) {
101
+ return Object.freeze({kind: "toCreate", fn})
102
+ }
103
+
104
+ /**
105
+ * Creates a skip-create declaration.
106
+ * @returns {SkipCreateDeclaration} - The frozen declaration.
107
+ */
108
+ export function skipCreateDeclaration() {
109
+ return Object.freeze({kind: "skipCreate"})
110
+ }