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,209 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
import * as inflection from "inflection"
|
|
4
|
+
import {assertModelClass} from "../model-contract.js"
|
|
5
|
+
import {ModelContractError} from "../errors.js"
|
|
6
|
+
import EvaluationContext from "../evaluation-context.js"
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Shared behaviour for the build/create/attributesFor strategies: evaluation
|
|
10
|
+
* context creation, deterministic callback execution, guaranteed `afterAll`
|
|
11
|
+
* cleanup, record construction (default and `initializeWith`), and association
|
|
12
|
+
* wiring through public relationship reflection.
|
|
13
|
+
*/
|
|
14
|
+
export default class BaseStrategy {
|
|
15
|
+
/**
|
|
16
|
+
* Creates an evaluation context for a plan.
|
|
17
|
+
* @param {import("../factory-registry.js").default} registry - Owning registry.
|
|
18
|
+
* @param {import("../factory-runner.js").CompiledPlan} plan - Compiled plan.
|
|
19
|
+
* @param {"attributesFor" | "build" | "create"} strategyName - Strategy name.
|
|
20
|
+
* @returns {EvaluationContext} - The context.
|
|
21
|
+
*/
|
|
22
|
+
_newContext(registry, plan, strategyName) {
|
|
23
|
+
return new EvaluationContext({registry, plan, strategy: strategyName})
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Builds the callback `context` object: evaluated transients exposed as plain
|
|
28
|
+
* properties (no Proxy) plus the named evaluator methods.
|
|
29
|
+
* @param {EvaluationContext} context - Evaluation context.
|
|
30
|
+
* @param {Record<string, ?>} transients - Evaluated transient values.
|
|
31
|
+
* @returns {Record<string, ?>} - The callback context.
|
|
32
|
+
*/
|
|
33
|
+
_callbackContext(context, transients) {
|
|
34
|
+
return Object.assign({}, transients, context.contextFor([]))
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Runs every deduped callback for an event in declaration order.
|
|
39
|
+
* @param {EvaluationContext} context - Evaluation context.
|
|
40
|
+
* @param {import("../factory-runner.js").CompiledPlan} plan - Compiled plan.
|
|
41
|
+
* @param {string} event - Event name (e.g. "afterCreate").
|
|
42
|
+
* @param {{record: ?, transients: Record<string, ?>, strategy: string}} state - Current record/transients/strategy.
|
|
43
|
+
* @returns {Promise<void>} - Resolves when all callbacks complete.
|
|
44
|
+
*/
|
|
45
|
+
async _runCallbacks(context, plan, event, state) {
|
|
46
|
+
const callbacks = plan.callbacks.get(event)
|
|
47
|
+
|
|
48
|
+
if (!callbacks) return
|
|
49
|
+
|
|
50
|
+
const callbackContext = this._callbackContext(context, state.transients)
|
|
51
|
+
|
|
52
|
+
for (const callback of callbacks) {
|
|
53
|
+
await callback.fn({record: state.record, context: callbackContext, strategy: state.strategy})
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Runs `body`, then guarantees `afterAll` runs in `finally`. When both the body
|
|
59
|
+
* and cleanup fail, the body's primary error is preserved and the cleanup error
|
|
60
|
+
* is attached as a detail rather than masking it.
|
|
61
|
+
* @param {EvaluationContext} context - Evaluation context.
|
|
62
|
+
* @param {import("../factory-runner.js").CompiledPlan} plan - Compiled plan.
|
|
63
|
+
* @param {() => {record: ?, transients: Record<string, ?>, strategy: string}} state - Late-bound state accessor.
|
|
64
|
+
* @param {() => Promise<?>} body - The strategy body.
|
|
65
|
+
* @returns {Promise<?>} - The body's result.
|
|
66
|
+
*/
|
|
67
|
+
async _runWithAfterAll(context, plan, state, body) {
|
|
68
|
+
/** @type {?} */
|
|
69
|
+
let result
|
|
70
|
+
/** @type {?} */
|
|
71
|
+
let primaryError
|
|
72
|
+
let hasPrimaryError = false
|
|
73
|
+
|
|
74
|
+
try {
|
|
75
|
+
result = await body()
|
|
76
|
+
} catch (error) {
|
|
77
|
+
primaryError = error
|
|
78
|
+
hasPrimaryError = true
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/** @type {?} */
|
|
82
|
+
let cleanupError
|
|
83
|
+
let hasCleanupError = false
|
|
84
|
+
|
|
85
|
+
try {
|
|
86
|
+
await this._runCallbacks(context, plan, "afterAll", state())
|
|
87
|
+
} catch (error) {
|
|
88
|
+
cleanupError = error
|
|
89
|
+
hasCleanupError = true
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (hasPrimaryError) {
|
|
93
|
+
if (hasCleanupError) this._attachCleanupFailure(primaryError, cleanupError)
|
|
94
|
+
|
|
95
|
+
throw primaryError
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (hasCleanupError) throw cleanupError
|
|
99
|
+
|
|
100
|
+
return result
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Attaches an afterAll cleanup failure to the primary error without masking it.
|
|
105
|
+
* @param {?} primaryError - The original error that will propagate.
|
|
106
|
+
* @param {?} cleanupError - The afterAll cleanup failure.
|
|
107
|
+
* @returns {void}
|
|
108
|
+
*/
|
|
109
|
+
_attachCleanupFailure(primaryError, cleanupError) {
|
|
110
|
+
if (!primaryError || typeof primaryError !== "object" || !Object.isExtensible(primaryError)) return
|
|
111
|
+
|
|
112
|
+
if (!Array.isArray(primaryError.factoryCleanupErrors)) primaryError.factoryCleanupErrors = []
|
|
113
|
+
primaryError.factoryCleanupErrors.push(cleanupError)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Constructs a record from evaluated public attributes, honouring a custom
|
|
118
|
+
* `initializeWith` constructor and never assigning constructor-consumed
|
|
119
|
+
* attributes twice.
|
|
120
|
+
* @param {import("../factory-runner.js").CompiledPlan} plan - Compiled plan.
|
|
121
|
+
* @param {Record<string, ?>} publicAttributes - Evaluated public attributes.
|
|
122
|
+
* @param {EvaluationContext} context - Evaluation context.
|
|
123
|
+
* @param {Record<string, ?>} transients - Evaluated transients.
|
|
124
|
+
* @returns {Promise<?>} - The constructed record.
|
|
125
|
+
*/
|
|
126
|
+
async _constructRecord(plan, publicAttributes, context, transients) {
|
|
127
|
+
const ModelClass = assertModelClass(plan.modelClass, plan.factoryName)
|
|
128
|
+
|
|
129
|
+
if (plan.initializeWith) {
|
|
130
|
+
return await this._constructWithInitializer(plan, ModelClass, publicAttributes, context, transients)
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return new ModelClass(publicAttributes)
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Constructs a record via a custom `initializeWith`, tracking which attributes
|
|
138
|
+
* the constructor consumed through its `get(name)` accessor and assigning only
|
|
139
|
+
* the remaining public attributes afterwards.
|
|
140
|
+
* @param {import("../factory-runner.js").CompiledPlan} plan - Compiled plan.
|
|
141
|
+
* @param {new (attributes?: Record<string, ?>) => import("../../../database/record/index.js").default} ModelClass - Validated declared model class.
|
|
142
|
+
* @param {Record<string, ?>} publicAttributes - Evaluated public attributes.
|
|
143
|
+
* @param {EvaluationContext} context - Evaluation context.
|
|
144
|
+
* @param {Record<string, ?>} transients - Evaluated transients.
|
|
145
|
+
* @returns {Promise<?>} - The constructed record.
|
|
146
|
+
*/
|
|
147
|
+
async _constructWithInitializer(plan, ModelClass, publicAttributes, context, transients) {
|
|
148
|
+
/** @type {Set<string>} */
|
|
149
|
+
const consumed = new Set()
|
|
150
|
+
const get = (/** @type {string} */ name) => {
|
|
151
|
+
consumed.add(name)
|
|
152
|
+
|
|
153
|
+
return publicAttributes[name]
|
|
154
|
+
}
|
|
155
|
+
const initializeWith = /** @type {import("../declarations.js").InitializeWithDeclaration["fn"]} */ (plan.initializeWith)
|
|
156
|
+
const record = await initializeWith({attributes: {...publicAttributes}, get, context: this._callbackContext(context, transients)})
|
|
157
|
+
|
|
158
|
+
if (!(record instanceof ModelClass)) {
|
|
159
|
+
throw new ModelContractError(`Factory "${plan.factoryName}" initializeWith must return an instance of ${ModelClass.name}, got: ${String(record)}`)
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/** @type {Record<string, ?>} */
|
|
163
|
+
const remaining = {}
|
|
164
|
+
|
|
165
|
+
for (const key of Object.keys(publicAttributes)) {
|
|
166
|
+
if (!consumed.has(key)) remaining[key] = publicAttributes[key]
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if (Object.keys(remaining).length > 0) {
|
|
170
|
+
/** @type {?} */ (record).assign(remaining)
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
return record
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Wires evaluated associations onto a record through public relationship
|
|
178
|
+
* reflection and generated setters (never private caches or guessed keys).
|
|
179
|
+
* @param {?} record - The owning record.
|
|
180
|
+
* @param {Array<{name: string, record: ?}>} associations - Evaluated associations.
|
|
181
|
+
* @returns {void}
|
|
182
|
+
*/
|
|
183
|
+
_assignAssociations(record, associations) {
|
|
184
|
+
for (const {name, record: associatedRecord} of associations) {
|
|
185
|
+
const instanceRelationship = record.getRelationshipByName(name)
|
|
186
|
+
const relationshipType = instanceRelationship.getType()
|
|
187
|
+
|
|
188
|
+
if (relationshipType === "belongsTo") {
|
|
189
|
+
record[`set${inflection.camelize(name)}`](associatedRecord || null)
|
|
190
|
+
} else if (relationshipType === "hasOne") {
|
|
191
|
+
instanceRelationship.setLoaded(associatedRecord || undefined)
|
|
192
|
+
} else if (relationshipType === "hasMany") {
|
|
193
|
+
instanceRelationship.setLoaded(this._toRecordArray(associatedRecord))
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Normalizes a has-many association value into an array of records.
|
|
200
|
+
* @param {?} value - Association value (record, array, or null).
|
|
201
|
+
* @returns {Array<?>} - The normalized record array.
|
|
202
|
+
*/
|
|
203
|
+
_toRecordArray(value) {
|
|
204
|
+
if (value == null) return []
|
|
205
|
+
if (Array.isArray(value)) return value
|
|
206
|
+
|
|
207
|
+
return [value]
|
|
208
|
+
}
|
|
209
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
import BaseStrategy from "./base.js"
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The `build` strategy. It recursively builds associated models (using the parent
|
|
7
|
+
* strategy) and constructs the root record without persisting anything. Runs the
|
|
8
|
+
* beforeAll/beforeBuild/afterBuild callbacks and guarantees afterAll cleanup.
|
|
9
|
+
*/
|
|
10
|
+
export default class BuildStrategy 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 built (unsaved) record.
|
|
17
|
+
*/
|
|
18
|
+
async run({registry, plan}) {
|
|
19
|
+
const context = this._newContext(registry, plan, "build")
|
|
20
|
+
/** @type {{record: ?, transients: Record<string, ?>}} */
|
|
21
|
+
const runState = {record: undefined, transients: {}}
|
|
22
|
+
const state = () => ({record: runState.record, transients: runState.transients, strategy: "build"})
|
|
23
|
+
|
|
24
|
+
return await this._runWithAfterAll(context, plan, state, async () => {
|
|
25
|
+
runState.transients = await context.resolveTransients()
|
|
26
|
+
|
|
27
|
+
await this._runCallbacks(context, plan, "beforeAll", state())
|
|
28
|
+
await this._runCallbacks(context, plan, "beforeBuild", state())
|
|
29
|
+
|
|
30
|
+
const {publicAttributes, transients, associations} = await context.resolveForConstruction()
|
|
31
|
+
|
|
32
|
+
const record = await this._constructRecord(plan, publicAttributes, context, transients)
|
|
33
|
+
|
|
34
|
+
this._assignAssociations(record, associations)
|
|
35
|
+
runState.record = record
|
|
36
|
+
|
|
37
|
+
await this._runCallbacks(context, plan, "afterBuild", state())
|
|
38
|
+
|
|
39
|
+
return record
|
|
40
|
+
})
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
import BaseStrategy from "./base.js"
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The `create` strategy. It builds the object graph (associations use the parent
|
|
7
|
+
* create strategy by default), runs beforeAll/beforeBuild/afterBuild, persists the
|
|
8
|
+
* root record through its native `save()` (letting Velocious own association
|
|
9
|
+
* autosave order and validation) or a custom `toCreate`, then runs
|
|
10
|
+
* beforeCreate/afterCreate and guarantees afterAll cleanup.
|
|
11
|
+
*/
|
|
12
|
+
export default class CreateStrategy extends BaseStrategy {
|
|
13
|
+
/**
|
|
14
|
+
* Runs the strategy.
|
|
15
|
+
* @param {object} args - Options.
|
|
16
|
+
* @param {import("../factory-registry.js").default} args.registry - Owning registry.
|
|
17
|
+
* @param {import("../factory-runner.js").CompiledPlan} args.plan - Compiled plan.
|
|
18
|
+
* @returns {Promise<?>} - The persisted record.
|
|
19
|
+
*/
|
|
20
|
+
async run({registry, plan}) {
|
|
21
|
+
const context = this._newContext(registry, plan, "create")
|
|
22
|
+
/** @type {{record: ?, transients: Record<string, ?>}} */
|
|
23
|
+
const runState = {record: undefined, transients: {}}
|
|
24
|
+
const state = () => ({record: runState.record, transients: runState.transients, strategy: "create"})
|
|
25
|
+
|
|
26
|
+
return await this._runWithAfterAll(context, plan, state, async () => {
|
|
27
|
+
runState.transients = await context.resolveTransients()
|
|
28
|
+
|
|
29
|
+
await this._runCallbacks(context, plan, "beforeAll", state())
|
|
30
|
+
await this._runCallbacks(context, plan, "beforeBuild", state())
|
|
31
|
+
|
|
32
|
+
const {publicAttributes, transients, associations} = await context.resolveForConstruction()
|
|
33
|
+
|
|
34
|
+
const record = await this._constructRecord(plan, publicAttributes, context, transients)
|
|
35
|
+
|
|
36
|
+
this._assignAssociations(record, associations)
|
|
37
|
+
runState.record = record
|
|
38
|
+
|
|
39
|
+
await this._runCallbacks(context, plan, "afterBuild", state())
|
|
40
|
+
await this._runCallbacks(context, plan, "beforeCreate", state())
|
|
41
|
+
await this._persist(plan, record, context, transients)
|
|
42
|
+
await this._runCallbacks(context, plan, "afterCreate", state())
|
|
43
|
+
|
|
44
|
+
return record
|
|
45
|
+
})
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Persists the record via a custom `toCreate`, native `save()`, or not at all
|
|
50
|
+
* when `skipCreate` is declared.
|
|
51
|
+
* @param {import("../factory-runner.js").CompiledPlan} plan - Compiled plan.
|
|
52
|
+
* @param {?} record - The record to persist.
|
|
53
|
+
* @param {import("../evaluation-context.js").default} context - Evaluation context.
|
|
54
|
+
* @param {Record<string, ?>} transients - Evaluated transients.
|
|
55
|
+
* @returns {Promise<void>} - Resolves when persistence completes.
|
|
56
|
+
*/
|
|
57
|
+
async _persist(plan, record, context, transients) {
|
|
58
|
+
if (plan.skipCreate) return
|
|
59
|
+
|
|
60
|
+
if (plan.toCreate) {
|
|
61
|
+
await plan.toCreate({record, context: this._callbackContext(context, transients)})
|
|
62
|
+
|
|
63
|
+
return
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
await record.save()
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* An immutable compiled trait. A trait carries an ordered list of declarations
|
|
5
|
+
* (attributes, transients, associations, callbacks, custom construction, and
|
|
6
|
+
* base-trait inclusions) that are mixed into a factory run.
|
|
7
|
+
*/
|
|
8
|
+
export default class TraitDefinition {
|
|
9
|
+
/**
|
|
10
|
+
* Builds a trait definition.
|
|
11
|
+
* @param {object} args - Options.
|
|
12
|
+
* @param {string} args.name - Trait name.
|
|
13
|
+
* @param {import("./declarations.js").Declaration[]} args.declarations - Ordered declarations.
|
|
14
|
+
*/
|
|
15
|
+
constructor({name, declarations}) {
|
|
16
|
+
/** @type {string} - Trait name. */
|
|
17
|
+
this.name = name
|
|
18
|
+
|
|
19
|
+
/** @type {Array<import("./declarations.js").Declaration>} - Ordered declarations. */
|
|
20
|
+
this.declarations = /** @type {Array<import("./declarations.js").Declaration>} */ (Object.freeze([...declarations]))
|
|
21
|
+
|
|
22
|
+
Object.freeze(this)
|
|
23
|
+
}
|
|
24
|
+
}
|