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.
- package/README.md +2 -0
- package/build/background-jobs/status-reporter.js +15 -2
- package/build/background-jobs/worker.js +5 -1
- package/build/frontend-models/base.js +105 -47
- package/build/frontend-models/transport-deadline.js +66 -0
- package/build/src/background-jobs/status-reporter.d.ts +3 -1
- package/build/src/background-jobs/status-reporter.d.ts.map +1 -1
- package/build/src/background-jobs/status-reporter.js +16 -3
- package/build/src/background-jobs/worker.d.ts.map +1 -1
- package/build/src/background-jobs/worker.js +6 -2
- package/build/src/frontend-models/base.d.ts +10 -1
- package/build/src/frontend-models/base.d.ts.map +1 -1
- package/build/src/frontend-models/base.js +71 -26
- package/build/src/frontend-models/transport-deadline.d.ts +26 -0
- package/build/src/frontend-models/transport-deadline.d.ts.map +1 -0
- package/build/src/frontend-models/transport-deadline.js +61 -0
- package/build/src/testing/factory/association-declaration.d.ts +37 -0
- package/build/src/testing/factory/association-declaration.d.ts.map +1 -0
- package/build/src/testing/factory/association-declaration.js +41 -0
- package/build/src/testing/factory/declarations.d.ts +190 -0
- package/build/src/testing/factory/declarations.d.ts.map +1 -0
- package/build/src/testing/factory/declarations.js +98 -0
- package/build/src/testing/factory/definition-builder.d.ts +132 -0
- package/build/src/testing/factory/definition-builder.d.ts.map +1 -0
- package/build/src/testing/factory/definition-builder.js +417 -0
- package/build/src/testing/factory/errors.d.ts +62 -0
- package/build/src/testing/factory/errors.d.ts.map +1 -0
- package/build/src/testing/factory/errors.js +67 -0
- package/build/src/testing/factory/evaluation-context.d.ts +95 -0
- package/build/src/testing/factory/evaluation-context.d.ts.map +1 -0
- package/build/src/testing/factory/evaluation-context.js +175 -0
- package/build/src/testing/factory/events.d.ts +21 -0
- package/build/src/testing/factory/events.d.ts.map +1 -0
- package/build/src/testing/factory/events.js +26 -0
- package/build/src/testing/factory/factory-definition.d.ts +39 -0
- package/build/src/testing/factory/factory-definition.d.ts.map +1 -0
- package/build/src/testing/factory/factory-definition.js +35 -0
- package/build/src/testing/factory/factory-registry.d.ts +263 -0
- package/build/src/testing/factory/factory-registry.d.ts.map +1 -0
- package/build/src/testing/factory/factory-registry.js +438 -0
- package/build/src/testing/factory/factory-runner.d.ts +179 -0
- package/build/src/testing/factory/factory-runner.d.ts.map +1 -0
- package/build/src/testing/factory/factory-runner.js +266 -0
- package/build/src/testing/factory/index.d.ts +18 -0
- package/build/src/testing/factory/index.d.ts.map +1 -0
- package/build/src/testing/factory/index.js +21 -0
- package/build/src/testing/factory/linter.d.ts +55 -0
- package/build/src/testing/factory/linter.d.ts.map +1 -0
- package/build/src/testing/factory/linter.js +106 -0
- package/build/src/testing/factory/model-contract.d.ts +11 -0
- package/build/src/testing/factory/model-contract.d.ts.map +1 -0
- package/build/src/testing/factory/model-contract.js +26 -0
- package/build/src/testing/factory/node/load-definitions.d.ts +24 -0
- package/build/src/testing/factory/node/load-definitions.d.ts.map +1 -0
- package/build/src/testing/factory/node/load-definitions.js +87 -0
- package/build/src/testing/factory/sequence.d.ts +73 -0
- package/build/src/testing/factory/sequence.d.ts.map +1 -0
- package/build/src/testing/factory/sequence.js +78 -0
- package/build/src/testing/factory/strategies/attributes-for.d.ts +21 -0
- package/build/src/testing/factory/strategies/attributes-for.d.ts.map +1 -0
- package/build/src/testing/factory/strategies/attributes-for.js +22 -0
- package/build/src/testing/factory/strategies/base.d.ts +101 -0
- package/build/src/testing/factory/strategies/base.d.ts.map +1 -0
- package/build/src/testing/factory/strategies/base.js +191 -0
- package/build/src/testing/factory/strategies/build.d.ts +20 -0
- package/build/src/testing/factory/strategies/build.d.ts.map +1 -0
- package/build/src/testing/factory/strategies/build.js +34 -0
- package/build/src/testing/factory/strategies/create.d.ts +32 -0
- package/build/src/testing/factory/strategies/create.d.ts.map +1 -0
- package/build/src/testing/factory/strategies/create.js +57 -0
- package/build/src/testing/factory/trait-definition.d.ts +22 -0
- package/build/src/testing/factory/trait-definition.d.ts.map +1 -0
- package/build/src/testing/factory/trait-definition.js +22 -0
- package/build/testing/factory/association-declaration.js +50 -0
- package/build/testing/factory/declarations.js +110 -0
- package/build/testing/factory/definition-builder.js +476 -0
- package/build/testing/factory/errors.js +79 -0
- package/build/testing/factory/evaluation-context.js +199 -0
- package/build/testing/factory/events.js +30 -0
- package/build/testing/factory/factory-definition.js +41 -0
- package/build/testing/factory/factory-registry.js +501 -0
- package/build/testing/factory/factory-runner.js +296 -0
- package/build/testing/factory/index.js +24 -0
- package/build/testing/factory/linter.js +119 -0
- package/build/testing/factory/model-contract.js +31 -0
- package/build/testing/factory/node/load-definitions.js +103 -0
- package/build/testing/factory/sequence.js +91 -0
- package/build/testing/factory/strategies/attributes-for.js +24 -0
- package/build/testing/factory/strategies/base.js +209 -0
- package/build/testing/factory/strategies/build.js +42 -0
- package/build/testing/factory/strategies/create.js +68 -0
- package/build/testing/factory/trait-definition.js +24 -0
- package/build/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/background-jobs/status-reporter.js +15 -2
- package/src/background-jobs/worker.js +5 -1
- package/src/frontend-models/base.js +105 -47
- package/src/frontend-models/transport-deadline.js +66 -0
- package/src/testing/factory/association-declaration.js +50 -0
- package/src/testing/factory/declarations.js +110 -0
- package/src/testing/factory/definition-builder.js +476 -0
- package/src/testing/factory/errors.js +79 -0
- package/src/testing/factory/evaluation-context.js +199 -0
- package/src/testing/factory/events.js +30 -0
- package/src/testing/factory/factory-definition.js +41 -0
- package/src/testing/factory/factory-registry.js +501 -0
- package/src/testing/factory/factory-runner.js +296 -0
- package/src/testing/factory/index.js +24 -0
- package/src/testing/factory/linter.js +119 -0
- package/src/testing/factory/model-contract.js +31 -0
- package/src/testing/factory/node/load-definitions.js +103 -0
- package/src/testing/factory/sequence.js +91 -0
- package/src/testing/factory/strategies/attributes-for.js +24 -0
- package/src/testing/factory/strategies/base.js +209 -0
- package/src/testing/factory/strategies/build.js +42 -0
- package/src/testing/factory/strategies/create.js +68 -0
- 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
|
+
}
|