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,106 @@
1
+ // @ts-check
2
+ import { FactoryError } from "./errors.js";
3
+ /** Internal sentinel thrown to force a per-case transaction rollback. */
4
+ class LintRollbackSignal extends Error {
5
+ }
6
+ /**
7
+ * Aggregated lint failure raised when one or more linted factories/traits error.
8
+ */
9
+ class FactoryLintError extends FactoryError {
10
+ }
11
+ /**
12
+ * Executes registered factories (and optionally their traits) to prove they build
13
+ * and persist, aggregating every failure by case. For the create strategy each
14
+ * case runs inside the model's ambient transaction and is rolled back, so no rows
15
+ * remain in the supported single-connection case. External callback side effects
16
+ * are not reversible and cross-database writes are not globally atomic.
17
+ */
18
+ export default class FactoryLinter {
19
+ /**
20
+ * Builds a linter.
21
+ * @param {import("./factory-registry.js").default} registry - Registry to lint.
22
+ */
23
+ constructor(registry) {
24
+ /** @type {import("./factory-registry.js").default} - Registry to lint. */
25
+ this.registry = registry;
26
+ }
27
+ /**
28
+ * Lints selected factories and reports every failure together.
29
+ * @param {object} [options] - Options.
30
+ * @param {string[]} [options.factories] - Factory names to lint. Defaults to all.
31
+ * @param {boolean} [options.traits] - Whether to also lint each factory's local traits.
32
+ * @param {"attributesFor" | "build" | "create"} [options.strategy] - Strategy to lint with. Defaults to create.
33
+ * @returns {Promise<void>} - Resolves when every case passed; rejects with an aggregate otherwise.
34
+ */
35
+ async lint({ factories, traits = false, strategy = "create" } = {}) {
36
+ const definitions = this._selectDefinitions(factories);
37
+ /** @type {Array<{label: string, error: ?}>} */
38
+ const failures = [];
39
+ for (const definition of definitions) {
40
+ await this._lintCase(definition, [], strategy, failures);
41
+ if (traits) {
42
+ for (const traitName of definition.localTraits.keys()) {
43
+ await this._lintCase(definition, [traitName], strategy, failures);
44
+ }
45
+ }
46
+ }
47
+ if (failures.length > 0) {
48
+ const details = failures.map((failure) => ` ${failure.label}: ${failure.error && failure.error.message}`).join("\n");
49
+ throw new FactoryLintError(`Factory lint found ${failures.length} error(s):\n${details}`);
50
+ }
51
+ }
52
+ /**
53
+ * Resolves the unique set of factory definitions to lint.
54
+ * @param {string[] | undefined} factories - Explicit names, or undefined for all.
55
+ * @returns {import("./factory-definition.js").default[]} - Unique definitions.
56
+ */
57
+ _selectDefinitions(factories) {
58
+ if (factories) {
59
+ return factories.map((name) => this.registry._runner._resolveFactory(name));
60
+ }
61
+ return [...new Set(this.registry._factories.values())];
62
+ }
63
+ /**
64
+ * Lints one factory/trait case, rolling back create-strategy persistence.
65
+ * @param {import("./factory-definition.js").default} definition - Factory definition.
66
+ * @param {string[]} traits - Traits to apply for this case.
67
+ * @param {"attributesFor" | "build" | "create"} strategy - Strategy to run.
68
+ * @param {Array<{label: string, error: ?}>} failures - Failure sink.
69
+ * @returns {Promise<void>} - Resolves when the case has been evaluated.
70
+ */
71
+ async _lintCase(definition, traits, strategy, failures) {
72
+ const label = traits.length > 0 ? `${definition.name} + ${traits.join(", ")}` : definition.name;
73
+ try {
74
+ if (strategy === "create") {
75
+ await this._lintCreateCase(definition, traits);
76
+ }
77
+ else {
78
+ await this.registry[strategy](definition.name, ...traits);
79
+ }
80
+ }
81
+ catch (error) {
82
+ if (error instanceof LintRollbackSignal)
83
+ return;
84
+ failures.push({ label, error });
85
+ }
86
+ }
87
+ /**
88
+ * Runs a create-strategy case inside a transaction and forces a rollback.
89
+ * @param {import("./factory-definition.js").default} definition - Factory definition.
90
+ * @param {string[]} traits - Traits to apply.
91
+ * @returns {Promise<void>} - Resolves (or rejects) once the rollback completes.
92
+ */
93
+ async _lintCreateCase(definition, traits) {
94
+ const chain = this.registry._runner._resolveChain(definition.name);
95
+ const modelClass = this.registry._runner._resolveModelClass(chain);
96
+ if (!modelClass) {
97
+ await this.registry.create(definition.name, ...traits);
98
+ return;
99
+ }
100
+ await /** @type {typeof import("../../database/record/index.js").default} */ (modelClass).transaction(async () => {
101
+ await this.registry.create(definition.name, ...traits);
102
+ throw new LintRollbackSignal();
103
+ });
104
+ }
105
+ }
106
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGludGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL3Rlc3RpbmcvZmFjdG9yeS9saW50ZXIuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsWUFBWTtBQUVaLE9BQU8sRUFBQyxZQUFZLEVBQUMsTUFBTSxhQUFhLENBQUE7QUFFeEMseUVBQXlFO0FBQ3pFLE1BQU0sa0JBQW1CLFNBQVEsS0FBSztDQUFHO0FBRXpDOztHQUVHO0FBQ0gsTUFBTSxnQkFBaUIsU0FBUSxZQUFZO0NBQUc7QUFFOUM7Ozs7OztHQU1HO0FBQ0gsTUFBTSxDQUFDLE9BQU8sT0FBTyxhQUFhO0lBQ2hDOzs7T0FHRztJQUNILFlBQVksUUFBUTtRQUNsQiwwRUFBMEU7UUFDMUUsSUFBSSxDQUFDLFFBQVEsR0FBRyxRQUFRLENBQUE7SUFDMUIsQ0FBQztJQUVEOzs7Ozs7O09BT0c7SUFDSCxLQUFLLENBQUMsSUFBSSxDQUFDLEVBQUMsU0FBUyxFQUFFLE1BQU0sR0FBRyxLQUFLLEVBQUUsUUFBUSxHQUFHLFFBQVEsRUFBQyxHQUFHLEVBQUU7UUFDOUQsTUFBTSxXQUFXLEdBQUcsSUFBSSxDQUFDLGtCQUFrQixDQUFDLFNBQVMsQ0FBQyxDQUFBO1FBQ3RELCtDQUErQztRQUMvQyxNQUFNLFFBQVEsR0FBRyxFQUFFLENBQUE7UUFFbkIsS0FBSyxNQUFNLFVBQVUsSUFBSSxXQUFXLEVBQUUsQ0FBQztZQUNyQyxNQUFNLElBQUksQ0FBQyxTQUFTLENBQUMsVUFBVSxFQUFFLEVBQUUsRUFBRSxRQUFRLEVBQUUsUUFBUSxDQUFDLENBQUE7WUFFeEQsSUFBSSxNQUFNLEVBQUUsQ0FBQztnQkFDWCxLQUFLLE1BQU0sU0FBUyxJQUFJLFVBQVUsQ0FBQyxXQUFXLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQztvQkFDdEQsTUFBTSxJQUFJLENBQUMsU0FBUyxDQUFDLFVBQVUsRUFBRSxDQUFDLFNBQVMsQ0FBQyxFQUFFLFFBQVEsRUFBRSxRQUFRLENBQUMsQ0FBQTtnQkFDbkUsQ0FBQztZQUNILENBQUM7UUFDSCxDQUFDO1FBRUQsSUFBSSxRQUFRLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQ3hCLE1BQU0sT0FBTyxHQUFHLFFBQVEsQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDLEtBQUssT0FBTyxDQUFDLEtBQUssS0FBSyxPQUFPLENBQUMsS0FBSyxJQUFJLE9BQU8sQ0FBQyxLQUFLLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUE7WUFFckgsTUFBTSxJQUFJLGdCQUFnQixDQUFDLHNCQUFzQixRQUFRLENBQUMsTUFBTSxlQUFlLE9BQU8sRUFBRSxDQUFDLENBQUE7UUFDM0YsQ0FBQztJQUNILENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsa0JBQWtCLENBQUMsU0FBUztRQUMxQixJQUFJLFNBQVMsRUFBRSxDQUFDO1lBQ2QsT0FBTyxTQUFTLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQTtRQUM3RSxDQUFDO1FBRUQsT0FBTyxDQUFDLEdBQUcsSUFBSSxHQUFHLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQyxDQUFBO0lBQ3hELENBQUM7SUFFRDs7Ozs7OztPQU9HO0lBQ0gsS0FBSyxDQUFDLFNBQVMsQ0FBQyxVQUFVLEVBQUUsTUFBTSxFQUFFLFFBQVEsRUFBRSxRQUFRO1FBQ3BELE1BQU0sS0FBSyxHQUFHLE1BQU0sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLFVBQVUsQ0FBQyxJQUFJLE1BQU0sTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFBO1FBRS9GLElBQUksQ0FBQztZQUNILElBQUksUUFBUSxLQUFLLFFBQVEsRUFBRSxDQUFDO2dCQUMxQixNQUFNLElBQUksQ0FBQyxlQUFlLENBQUMsVUFBVSxFQUFFLE1BQU0sQ0FBQyxDQUFBO1lBQ2hELENBQUM7aUJBQU0sQ0FBQztnQkFDTixNQUFNLElBQUksQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLENBQUMsVUFBVSxDQUFDLElBQUksRUFBRSxHQUFHLE1BQU0sQ0FBQyxDQUFBO1lBQzNELENBQUM7UUFDSCxDQUFDO1FBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztZQUNmLElBQUksS0FBSyxZQUFZLGtCQUFrQjtnQkFBRSxPQUFNO1lBRS9DLFFBQVEsQ0FBQyxJQUFJLENBQUMsRUFBQyxLQUFLLEVBQUUsS0FBSyxFQUFDLENBQUMsQ0FBQTtRQUMvQixDQUFDO0lBQ0gsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsS0FBSyxDQUFDLGVBQWUsQ0FBQyxVQUFVLEVBQUUsTUFBTTtRQUN0QyxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFBO1FBQ2xFLE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLGtCQUFrQixDQUFDLEtBQUssQ0FBQyxDQUFBO1FBRWxFLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztZQUNoQixNQUFNLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxJQUFJLEVBQUUsR0FBRyxNQUFNLENBQUMsQ0FBQTtZQUV0RCxPQUFNO1FBQ1IsQ0FBQztRQUVELE1BQU0sc0VBQXNFLENBQUMsQ0FBQyxVQUFVLENBQUMsQ0FBQyxXQUFXLENBQUMsS0FBSyxJQUFJLEVBQUU7WUFDL0csTUFBTSxJQUFJLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsSUFBSSxFQUFFLEdBQUcsTUFBTSxDQUFDLENBQUE7WUFFdEQsTUFBTSxJQUFJLGtCQUFrQixFQUFFLENBQUE7UUFDaEMsQ0FBQyxDQUFDLENBQUE7SUFDSixDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBAdHMtY2hlY2tcblxuaW1wb3J0IHtGYWN0b3J5RXJyb3J9IGZyb20gXCIuL2Vycm9ycy5qc1wiXG5cbi8qKiBJbnRlcm5hbCBzZW50aW5lbCB0aHJvd24gdG8gZm9yY2UgYSBwZXItY2FzZSB0cmFuc2FjdGlvbiByb2xsYmFjay4gKi9cbmNsYXNzIExpbnRSb2xsYmFja1NpZ25hbCBleHRlbmRzIEVycm9yIHt9XG5cbi8qKlxuICogQWdncmVnYXRlZCBsaW50IGZhaWx1cmUgcmFpc2VkIHdoZW4gb25lIG9yIG1vcmUgbGludGVkIGZhY3Rvcmllcy90cmFpdHMgZXJyb3IuXG4gKi9cbmNsYXNzIEZhY3RvcnlMaW50RXJyb3IgZXh0ZW5kcyBGYWN0b3J5RXJyb3Ige31cblxuLyoqXG4gKiBFeGVjdXRlcyByZWdpc3RlcmVkIGZhY3RvcmllcyAoYW5kIG9wdGlvbmFsbHkgdGhlaXIgdHJhaXRzKSB0byBwcm92ZSB0aGV5IGJ1aWxkXG4gKiBhbmQgcGVyc2lzdCwgYWdncmVnYXRpbmcgZXZlcnkgZmFpbHVyZSBieSBjYXNlLiBGb3IgdGhlIGNyZWF0ZSBzdHJhdGVneSBlYWNoXG4gKiBjYXNlIHJ1bnMgaW5zaWRlIHRoZSBtb2RlbCdzIGFtYmllbnQgdHJhbnNhY3Rpb24gYW5kIGlzIHJvbGxlZCBiYWNrLCBzbyBubyByb3dzXG4gKiByZW1haW4gaW4gdGhlIHN1cHBvcnRlZCBzaW5nbGUtY29ubmVjdGlvbiBjYXNlLiBFeHRlcm5hbCBjYWxsYmFjayBzaWRlIGVmZmVjdHNcbiAqIGFyZSBub3QgcmV2ZXJzaWJsZSBhbmQgY3Jvc3MtZGF0YWJhc2Ugd3JpdGVzIGFyZSBub3QgZ2xvYmFsbHkgYXRvbWljLlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBGYWN0b3J5TGludGVyIHtcbiAgLyoqXG4gICAqIEJ1aWxkcyBhIGxpbnRlci5cbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuL2ZhY3RvcnktcmVnaXN0cnkuanNcIikuZGVmYXVsdH0gcmVnaXN0cnkgLSBSZWdpc3RyeSB0byBsaW50LlxuICAgKi9cbiAgY29uc3RydWN0b3IocmVnaXN0cnkpIHtcbiAgICAvKiogQHR5cGUge2ltcG9ydChcIi4vZmFjdG9yeS1yZWdpc3RyeS5qc1wiKS5kZWZhdWx0fSAtIFJlZ2lzdHJ5IHRvIGxpbnQuICovXG4gICAgdGhpcy5yZWdpc3RyeSA9IHJlZ2lzdHJ5XG4gIH1cblxuICAvKipcbiAgICogTGludHMgc2VsZWN0ZWQgZmFjdG9yaWVzIGFuZCByZXBvcnRzIGV2ZXJ5IGZhaWx1cmUgdG9nZXRoZXIuXG4gICAqIEBwYXJhbSB7b2JqZWN0fSBbb3B0aW9uc10gLSBPcHRpb25zLlxuICAgKiBAcGFyYW0ge3N0cmluZ1tdfSBbb3B0aW9ucy5mYWN0b3JpZXNdIC0gRmFjdG9yeSBuYW1lcyB0byBsaW50LiBEZWZhdWx0cyB0byBhbGwuXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gW29wdGlvbnMudHJhaXRzXSAtIFdoZXRoZXIgdG8gYWxzbyBsaW50IGVhY2ggZmFjdG9yeSdzIGxvY2FsIHRyYWl0cy5cbiAgICogQHBhcmFtIHtcImF0dHJpYnV0ZXNGb3JcIiB8IFwiYnVpbGRcIiB8IFwiY3JlYXRlXCJ9IFtvcHRpb25zLnN0cmF0ZWd5XSAtIFN0cmF0ZWd5IHRvIGxpbnQgd2l0aC4gRGVmYXVsdHMgdG8gY3JlYXRlLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gLSBSZXNvbHZlcyB3aGVuIGV2ZXJ5IGNhc2UgcGFzc2VkOyByZWplY3RzIHdpdGggYW4gYWdncmVnYXRlIG90aGVyd2lzZS5cbiAgICovXG4gIGFzeW5jIGxpbnQoe2ZhY3RvcmllcywgdHJhaXRzID0gZmFsc2UsIHN0cmF0ZWd5ID0gXCJjcmVhdGVcIn0gPSB7fSkge1xuICAgIGNvbnN0IGRlZmluaXRpb25zID0gdGhpcy5fc2VsZWN0RGVmaW5pdGlvbnMoZmFjdG9yaWVzKVxuICAgIC8qKiBAdHlwZSB7QXJyYXk8e2xhYmVsOiBzdHJpbmcsIGVycm9yOiA/fT59ICovXG4gICAgY29uc3QgZmFpbHVyZXMgPSBbXVxuXG4gICAgZm9yIChjb25zdCBkZWZpbml0aW9uIG9mIGRlZmluaXRpb25zKSB7XG4gICAgICBhd2FpdCB0aGlzLl9saW50Q2FzZShkZWZpbml0aW9uLCBbXSwgc3RyYXRlZ3ksIGZhaWx1cmVzKVxuXG4gICAgICBpZiAodHJhaXRzKSB7XG4gICAgICAgIGZvciAoY29uc3QgdHJhaXROYW1lIG9mIGRlZmluaXRpb24ubG9jYWxUcmFpdHMua2V5cygpKSB7XG4gICAgICAgICAgYXdhaXQgdGhpcy5fbGludENhc2UoZGVmaW5pdGlvbiwgW3RyYWl0TmFtZV0sIHN0cmF0ZWd5LCBmYWlsdXJlcylcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChmYWlsdXJlcy5sZW5ndGggPiAwKSB7XG4gICAgICBjb25zdCBkZXRhaWxzID0gZmFpbHVyZXMubWFwKChmYWlsdXJlKSA9PiBgICAke2ZhaWx1cmUubGFiZWx9OiAke2ZhaWx1cmUuZXJyb3IgJiYgZmFpbHVyZS5lcnJvci5tZXNzYWdlfWApLmpvaW4oXCJcXG5cIilcblxuICAgICAgdGhyb3cgbmV3IEZhY3RvcnlMaW50RXJyb3IoYEZhY3RvcnkgbGludCBmb3VuZCAke2ZhaWx1cmVzLmxlbmd0aH0gZXJyb3Iocyk6XFxuJHtkZXRhaWxzfWApXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlc29sdmVzIHRoZSB1bmlxdWUgc2V0IG9mIGZhY3RvcnkgZGVmaW5pdGlvbnMgdG8gbGludC5cbiAgICogQHBhcmFtIHtzdHJpbmdbXSB8IHVuZGVmaW5lZH0gZmFjdG9yaWVzIC0gRXhwbGljaXQgbmFtZXMsIG9yIHVuZGVmaW5lZCBmb3IgYWxsLlxuICAgKiBAcmV0dXJucyB7aW1wb3J0KFwiLi9mYWN0b3J5LWRlZmluaXRpb24uanNcIikuZGVmYXVsdFtdfSAtIFVuaXF1ZSBkZWZpbml0aW9ucy5cbiAgICovXG4gIF9zZWxlY3REZWZpbml0aW9ucyhmYWN0b3JpZXMpIHtcbiAgICBpZiAoZmFjdG9yaWVzKSB7XG4gICAgICByZXR1cm4gZmFjdG9yaWVzLm1hcCgobmFtZSkgPT4gdGhpcy5yZWdpc3RyeS5fcnVubmVyLl9yZXNvbHZlRmFjdG9yeShuYW1lKSlcbiAgICB9XG5cbiAgICByZXR1cm4gWy4uLm5ldyBTZXQodGhpcy5yZWdpc3RyeS5fZmFjdG9yaWVzLnZhbHVlcygpKV1cbiAgfVxuXG4gIC8qKlxuICAgKiBMaW50cyBvbmUgZmFjdG9yeS90cmFpdCBjYXNlLCByb2xsaW5nIGJhY2sgY3JlYXRlLXN0cmF0ZWd5IHBlcnNpc3RlbmNlLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vZmFjdG9yeS1kZWZpbml0aW9uLmpzXCIpLmRlZmF1bHR9IGRlZmluaXRpb24gLSBGYWN0b3J5IGRlZmluaXRpb24uXG4gICAqIEBwYXJhbSB7c3RyaW5nW119IHRyYWl0cyAtIFRyYWl0cyB0byBhcHBseSBmb3IgdGhpcyBjYXNlLlxuICAgKiBAcGFyYW0ge1wiYXR0cmlidXRlc0ZvclwiIHwgXCJidWlsZFwiIHwgXCJjcmVhdGVcIn0gc3RyYXRlZ3kgLSBTdHJhdGVneSB0byBydW4uXG4gICAqIEBwYXJhbSB7QXJyYXk8e2xhYmVsOiBzdHJpbmcsIGVycm9yOiA/fT59IGZhaWx1cmVzIC0gRmFpbHVyZSBzaW5rLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gLSBSZXNvbHZlcyB3aGVuIHRoZSBjYXNlIGhhcyBiZWVuIGV2YWx1YXRlZC5cbiAgICovXG4gIGFzeW5jIF9saW50Q2FzZShkZWZpbml0aW9uLCB0cmFpdHMsIHN0cmF0ZWd5LCBmYWlsdXJlcykge1xuICAgIGNvbnN0IGxhYmVsID0gdHJhaXRzLmxlbmd0aCA+IDAgPyBgJHtkZWZpbml0aW9uLm5hbWV9ICsgJHt0cmFpdHMuam9pbihcIiwgXCIpfWAgOiBkZWZpbml0aW9uLm5hbWVcblxuICAgIHRyeSB7XG4gICAgICBpZiAoc3RyYXRlZ3kgPT09IFwiY3JlYXRlXCIpIHtcbiAgICAgICAgYXdhaXQgdGhpcy5fbGludENyZWF0ZUNhc2UoZGVmaW5pdGlvbiwgdHJhaXRzKVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYXdhaXQgdGhpcy5yZWdpc3RyeVtzdHJhdGVneV0oZGVmaW5pdGlvbi5uYW1lLCAuLi50cmFpdHMpXG4gICAgICB9XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGlmIChlcnJvciBpbnN0YW5jZW9mIExpbnRSb2xsYmFja1NpZ25hbCkgcmV0dXJuXG5cbiAgICAgIGZhaWx1cmVzLnB1c2goe2xhYmVsLCBlcnJvcn0pXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJ1bnMgYSBjcmVhdGUtc3RyYXRlZ3kgY2FzZSBpbnNpZGUgYSB0cmFuc2FjdGlvbiBhbmQgZm9yY2VzIGEgcm9sbGJhY2suXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9mYWN0b3J5LWRlZmluaXRpb24uanNcIikuZGVmYXVsdH0gZGVmaW5pdGlvbiAtIEZhY3RvcnkgZGVmaW5pdGlvbi5cbiAgICogQHBhcmFtIHtzdHJpbmdbXX0gdHJhaXRzIC0gVHJhaXRzIHRvIGFwcGx5LlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gLSBSZXNvbHZlcyAob3IgcmVqZWN0cykgb25jZSB0aGUgcm9sbGJhY2sgY29tcGxldGVzLlxuICAgKi9cbiAgYXN5bmMgX2xpbnRDcmVhdGVDYXNlKGRlZmluaXRpb24sIHRyYWl0cykge1xuICAgIGNvbnN0IGNoYWluID0gdGhpcy5yZWdpc3RyeS5fcnVubmVyLl9yZXNvbHZlQ2hhaW4oZGVmaW5pdGlvbi5uYW1lKVxuICAgIGNvbnN0IG1vZGVsQ2xhc3MgPSB0aGlzLnJlZ2lzdHJ5Ll9ydW5uZXIuX3Jlc29sdmVNb2RlbENsYXNzKGNoYWluKVxuXG4gICAgaWYgKCFtb2RlbENsYXNzKSB7XG4gICAgICBhd2FpdCB0aGlzLnJlZ2lzdHJ5LmNyZWF0ZShkZWZpbml0aW9uLm5hbWUsIC4uLnRyYWl0cylcblxuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgYXdhaXQgLyoqIEB0eXBlIHt0eXBlb2YgaW1wb3J0KFwiLi4vLi4vZGF0YWJhc2UvcmVjb3JkL2luZGV4LmpzXCIpLmRlZmF1bHR9ICovIChtb2RlbENsYXNzKS50cmFuc2FjdGlvbihhc3luYyAoKSA9PiB7XG4gICAgICBhd2FpdCB0aGlzLnJlZ2lzdHJ5LmNyZWF0ZShkZWZpbml0aW9uLm5hbWUsIC4uLnRyYWl0cylcblxuICAgICAgdGhyb3cgbmV3IExpbnRSb2xsYmFja1NpZ25hbCgpXG4gICAgfSlcbiAgfVxufVxuIl19
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Asserts a class satisfies the V1 factory model contract: it must be an
3
+ * initialized backend Velocious `DatabaseRecord` subclass. Uninitialized backend
4
+ * classes and non-backend classes (e.g. generated frontend models) are rejected
5
+ * with a named, actionable error rather than failing deep inside construction.
6
+ * @param {?} modelClass - The candidate model class.
7
+ * @param {string} factoryName - Factory name, for the error message.
8
+ * @returns {new (attributes?: Record<string, ?>) => import("../../database/record/index.js").default} - The validated model class.
9
+ */
10
+ export function assertModelClass(modelClass: unknown, factoryName: string): new (attributes?: Record<string, unknown>) => import("../../database/record/index.js").default;
11
+ //# sourceMappingURL=model-contract.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-contract.d.ts","sourceRoot":"","sources":["../../../../src/testing/factory/model-contract.js"],"names":[],"mappings":"AAKA;;;;;;;;GAQG;AACH,6CAJW,OAAC,eACD,MAAM,GACJ,KAAK,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAC,CAAC,KAAK,OAAO,gCAAgC,EAAE,OAAO,CAkBpG"}
@@ -0,0 +1,26 @@
1
+ // @ts-check
2
+ import DatabaseRecord from "../../database/record/index.js";
3
+ import { ModelContractError } from "./errors.js";
4
+ /**
5
+ * Asserts a class satisfies the V1 factory model contract: it must be an
6
+ * initialized backend Velocious `DatabaseRecord` subclass. Uninitialized backend
7
+ * classes and non-backend classes (e.g. generated frontend models) are rejected
8
+ * with a named, actionable error rather than failing deep inside construction.
9
+ * @param {?} modelClass - The candidate model class.
10
+ * @param {string} factoryName - Factory name, for the error message.
11
+ * @returns {new (attributes?: Record<string, ?>) => import("../../database/record/index.js").default} - The validated model class.
12
+ */
13
+ export function assertModelClass(modelClass, factoryName) {
14
+ if (typeof modelClass !== "function") {
15
+ throw new ModelContractError(`Factory "${factoryName}" has no model class to construct. Declare one with factory("${factoryName}", ModelClass, ...).`);
16
+ }
17
+ if (!(modelClass.prototype instanceof DatabaseRecord)) {
18
+ throw new ModelContractError(`Factory "${factoryName}" model ${modelClass.name || "class"} is not a supported Velocious backend record. build/create require an initialized DatabaseRecord subclass; generated frontend models are not supported in V1.`);
19
+ }
20
+ const backendModelClass = /** @type {typeof import("../../database/record/index.js").default} */ (modelClass);
21
+ if (!backendModelClass.isInitialized()) {
22
+ throw new ModelContractError(`Factory "${factoryName}" model ${backendModelClass.name} has not been initialized. Ensure the model class is initialized (e.g. via configuration.initialize()/ensureInitialized) before build/create.`);
23
+ }
24
+ return /** @type {new (attributes?: Record<string, ?>) => import("../../database/record/index.js").default} */ (modelClass);
25
+ }
26
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9kZWwtY29udHJhY3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvdGVzdGluZy9mYWN0b3J5L21vZGVsLWNvbnRyYWN0LmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLFlBQVk7QUFFWixPQUFPLGNBQWMsTUFBTSxnQ0FBZ0MsQ0FBQTtBQUMzRCxPQUFPLEVBQUMsa0JBQWtCLEVBQUMsTUFBTSxhQUFhLENBQUE7QUFFOUM7Ozs7Ozs7O0dBUUc7QUFDSCxNQUFNLFVBQVUsZ0JBQWdCLENBQUMsVUFBVSxFQUFFLFdBQVc7SUFDdEQsSUFBSSxPQUFPLFVBQVUsS0FBSyxVQUFVLEVBQUUsQ0FBQztRQUNyQyxNQUFNLElBQUksa0JBQWtCLENBQUMsWUFBWSxXQUFXLGdFQUFnRSxXQUFXLHNCQUFzQixDQUFDLENBQUE7SUFDeEosQ0FBQztJQUVELElBQUksQ0FBQyxDQUFDLFVBQVUsQ0FBQyxTQUFTLFlBQVksY0FBYyxDQUFDLEVBQUUsQ0FBQztRQUN0RCxNQUFNLElBQUksa0JBQWtCLENBQUMsWUFBWSxXQUFXLFdBQVcsVUFBVSxDQUFDLElBQUksSUFBSSxPQUFPLCtKQUErSixDQUFDLENBQUE7SUFDM1AsQ0FBQztJQUVELE1BQU0saUJBQWlCLEdBQUcsc0VBQXNFLENBQUMsQ0FBQyxVQUFVLENBQUMsQ0FBQTtJQUU3RyxJQUFJLENBQUMsaUJBQWlCLENBQUMsYUFBYSxFQUFFLEVBQUUsQ0FBQztRQUN2QyxNQUFNLElBQUksa0JBQWtCLENBQUMsWUFBWSxXQUFXLFdBQVcsaUJBQWlCLENBQUMsSUFBSSwrSUFBK0ksQ0FBQyxDQUFBO0lBQ3ZPLENBQUM7SUFFRCxPQUFPLHVHQUF1RyxDQUFDLENBQUMsVUFBVSxDQUFDLENBQUE7QUFDN0gsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIEB0cy1jaGVja1xuXG5pbXBvcnQgRGF0YWJhc2VSZWNvcmQgZnJvbSBcIi4uLy4uL2RhdGFiYXNlL3JlY29yZC9pbmRleC5qc1wiXG5pbXBvcnQge01vZGVsQ29udHJhY3RFcnJvcn0gZnJvbSBcIi4vZXJyb3JzLmpzXCJcblxuLyoqXG4gKiBBc3NlcnRzIGEgY2xhc3Mgc2F0aXNmaWVzIHRoZSBWMSBmYWN0b3J5IG1vZGVsIGNvbnRyYWN0OiBpdCBtdXN0IGJlIGFuXG4gKiBpbml0aWFsaXplZCBiYWNrZW5kIFZlbG9jaW91cyBgRGF0YWJhc2VSZWNvcmRgIHN1YmNsYXNzLiBVbmluaXRpYWxpemVkIGJhY2tlbmRcbiAqIGNsYXNzZXMgYW5kIG5vbi1iYWNrZW5kIGNsYXNzZXMgKGUuZy4gZ2VuZXJhdGVkIGZyb250ZW5kIG1vZGVscykgYXJlIHJlamVjdGVkXG4gKiB3aXRoIGEgbmFtZWQsIGFjdGlvbmFibGUgZXJyb3IgcmF0aGVyIHRoYW4gZmFpbGluZyBkZWVwIGluc2lkZSBjb25zdHJ1Y3Rpb24uXG4gKiBAcGFyYW0gez99IG1vZGVsQ2xhc3MgLSBUaGUgY2FuZGlkYXRlIG1vZGVsIGNsYXNzLlxuICogQHBhcmFtIHtzdHJpbmd9IGZhY3RvcnlOYW1lIC0gRmFjdG9yeSBuYW1lLCBmb3IgdGhlIGVycm9yIG1lc3NhZ2UuXG4gKiBAcmV0dXJucyB7bmV3IChhdHRyaWJ1dGVzPzogUmVjb3JkPHN0cmluZywgPz4pID0+IGltcG9ydChcIi4uLy4uL2RhdGFiYXNlL3JlY29yZC9pbmRleC5qc1wiKS5kZWZhdWx0fSAtIFRoZSB2YWxpZGF0ZWQgbW9kZWwgY2xhc3MuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhc3NlcnRNb2RlbENsYXNzKG1vZGVsQ2xhc3MsIGZhY3RvcnlOYW1lKSB7XG4gIGlmICh0eXBlb2YgbW9kZWxDbGFzcyAhPT0gXCJmdW5jdGlvblwiKSB7XG4gICAgdGhyb3cgbmV3IE1vZGVsQ29udHJhY3RFcnJvcihgRmFjdG9yeSBcIiR7ZmFjdG9yeU5hbWV9XCIgaGFzIG5vIG1vZGVsIGNsYXNzIHRvIGNvbnN0cnVjdC4gRGVjbGFyZSBvbmUgd2l0aCBmYWN0b3J5KFwiJHtmYWN0b3J5TmFtZX1cIiwgTW9kZWxDbGFzcywgLi4uKS5gKVxuICB9XG5cbiAgaWYgKCEobW9kZWxDbGFzcy5wcm90b3R5cGUgaW5zdGFuY2VvZiBEYXRhYmFzZVJlY29yZCkpIHtcbiAgICB0aHJvdyBuZXcgTW9kZWxDb250cmFjdEVycm9yKGBGYWN0b3J5IFwiJHtmYWN0b3J5TmFtZX1cIiBtb2RlbCAke21vZGVsQ2xhc3MubmFtZSB8fCBcImNsYXNzXCJ9IGlzIG5vdCBhIHN1cHBvcnRlZCBWZWxvY2lvdXMgYmFja2VuZCByZWNvcmQuIGJ1aWxkL2NyZWF0ZSByZXF1aXJlIGFuIGluaXRpYWxpemVkIERhdGFiYXNlUmVjb3JkIHN1YmNsYXNzOyBnZW5lcmF0ZWQgZnJvbnRlbmQgbW9kZWxzIGFyZSBub3Qgc3VwcG9ydGVkIGluIFYxLmApXG4gIH1cblxuICBjb25zdCBiYWNrZW5kTW9kZWxDbGFzcyA9IC8qKiBAdHlwZSB7dHlwZW9mIGltcG9ydChcIi4uLy4uL2RhdGFiYXNlL3JlY29yZC9pbmRleC5qc1wiKS5kZWZhdWx0fSAqLyAobW9kZWxDbGFzcylcblxuICBpZiAoIWJhY2tlbmRNb2RlbENsYXNzLmlzSW5pdGlhbGl6ZWQoKSkge1xuICAgIHRocm93IG5ldyBNb2RlbENvbnRyYWN0RXJyb3IoYEZhY3RvcnkgXCIke2ZhY3RvcnlOYW1lfVwiIG1vZGVsICR7YmFja2VuZE1vZGVsQ2xhc3MubmFtZX0gaGFzIG5vdCBiZWVuIGluaXRpYWxpemVkLiBFbnN1cmUgdGhlIG1vZGVsIGNsYXNzIGlzIGluaXRpYWxpemVkIChlLmcuIHZpYSBjb25maWd1cmF0aW9uLmluaXRpYWxpemUoKS9lbnN1cmVJbml0aWFsaXplZCkgYmVmb3JlIGJ1aWxkL2NyZWF0ZS5gKVxuICB9XG5cbiAgcmV0dXJuIC8qKiBAdHlwZSB7bmV3IChhdHRyaWJ1dGVzPzogUmVjb3JkPHN0cmluZywgPz4pID0+IGltcG9ydChcIi4uLy4uL2RhdGFiYXNlL3JlY29yZC9pbmRleC5qc1wiKS5kZWZhdWx0fSAqLyAobW9kZWxDbGFzcylcbn1cbiJdfQ==
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Loads Velocious factory definition files (Node only). Each file must
3
+ * default-export a `(registry) => void` function that defines into the registry.
4
+ * Files load in deterministic path order. This module is intentionally Node-only
5
+ * (filesystem + dynamic import) and must never be imported from browser/Metro
6
+ * bundles; import the browser-safe core from `../index.js` there instead.
7
+ * @param {import("../factory-registry.js").default} registry - Registry to define into.
8
+ * @param {string | string[]} target - File path, directory, or list of paths.
9
+ * @param {{reload?: boolean}} [options] - Options.
10
+ * @returns {Promise<string[]>} - The loaded file paths, in load order.
11
+ */
12
+ export function loadDefinitions(registry: import("../factory-registry.js").default, target: string | string[], { reload }?: {
13
+ reload?: boolean;
14
+ }): Promise<string[]>;
15
+ /**
16
+ * Fully reloads definitions: resets the registry (dropping every factory, trait,
17
+ * sequence, callback and default) and re-imports the target files with cache
18
+ * busting so edited definitions take effect.
19
+ * @param {import("../factory-registry.js").default} registry - Registry to reload.
20
+ * @param {string | string[]} target - File path, directory, or list of paths.
21
+ * @returns {Promise<string[]>} - The reloaded file paths, in load order.
22
+ */
23
+ export function reloadDefinitions(registry: import("../factory-registry.js").default, target: string | string[]): Promise<string[]>;
24
+ //# sourceMappingURL=load-definitions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load-definitions.d.ts","sourceRoot":"","sources":["../../../../../src/testing/factory/node/load-definitions.js"],"names":[],"mappings":"AAwDA;;;;;;;;;;GAUG;AACH,0CALW,OAAO,wBAAwB,EAAE,OAAO,UACxC,MAAM,GAAG,MAAM,EAAE,eACjB;IAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAC,GAChB,OAAO,CAAC,MAAM,EAAE,CAAC,CAuB7B;AAED;;;;;;;GAOG;AACH,4CAJW,OAAO,wBAAwB,EAAE,OAAO,UACxC,MAAM,GAAG,MAAM,EAAE,GACf,OAAO,CAAC,MAAM,EAAE,CAAC,CAM7B"}
@@ -0,0 +1,87 @@
1
+ // @ts-check
2
+ import { pathToFileURL } from "node:url";
3
+ import { readdir, stat } from "node:fs/promises";
4
+ import path from "node:path";
5
+ /**
6
+ * Monotonic cache-busting counter shared by reloads. Kept module-local so a reload
7
+ * imports a fresh module instance rather than the cached one.
8
+ * @type {number}
9
+ */
10
+ let reloadCounter = 0;
11
+ /**
12
+ * Recursively collects `.js` files under a directory in a deterministic
13
+ * (lexicographically sorted) order.
14
+ * @param {string} directory - Directory to scan.
15
+ * @returns {Promise<string[]>} - Sorted absolute file paths.
16
+ */
17
+ async function collectDirectoryFiles(directory) {
18
+ const entries = await readdir(directory, { withFileTypes: true });
19
+ /** @type {string[]} */
20
+ const files = [];
21
+ for (const entry of [...entries].sort((left, right) => (left.name < right.name ? -1 : 1))) {
22
+ const fullPath = path.join(directory, entry.name);
23
+ if (entry.isDirectory()) {
24
+ files.push(...await collectDirectoryFiles(fullPath));
25
+ }
26
+ else if (entry.name.endsWith(".js")) {
27
+ files.push(fullPath);
28
+ }
29
+ }
30
+ return files;
31
+ }
32
+ /**
33
+ * Resolves a load target (a single file, a directory, or an explicit list) into a
34
+ * deterministic, de-duplicated list of absolute definition file paths.
35
+ * @param {string | string[]} target - File path, directory, or list of paths.
36
+ * @returns {Promise<string[]>} - Sorted, de-duplicated absolute file paths.
37
+ */
38
+ async function resolveFiles(target) {
39
+ if (Array.isArray(target)) {
40
+ return [...new Set(target.map((entry) => path.resolve(entry)))].sort();
41
+ }
42
+ const resolved = path.resolve(target);
43
+ const stats = await stat(resolved);
44
+ if (stats.isDirectory())
45
+ return await collectDirectoryFiles(resolved);
46
+ return [resolved];
47
+ }
48
+ /**
49
+ * Loads Velocious factory definition files (Node only). Each file must
50
+ * default-export a `(registry) => void` function that defines into the registry.
51
+ * Files load in deterministic path order. This module is intentionally Node-only
52
+ * (filesystem + dynamic import) and must never be imported from browser/Metro
53
+ * bundles; import the browser-safe core from `../index.js` there instead.
54
+ * @param {import("../factory-registry.js").default} registry - Registry to define into.
55
+ * @param {string | string[]} target - File path, directory, or list of paths.
56
+ * @param {{reload?: boolean}} [options] - Options.
57
+ * @returns {Promise<string[]>} - The loaded file paths, in load order.
58
+ */
59
+ export async function loadDefinitions(registry, target, { reload = false } = {}) {
60
+ const files = await resolveFiles(target);
61
+ for (const file of files) {
62
+ let href = pathToFileURL(file).href;
63
+ if (reload) {
64
+ reloadCounter += 1;
65
+ href += `?factoryReload=${reloadCounter}`;
66
+ }
67
+ const module = await import(href);
68
+ if (typeof module.default !== "function") {
69
+ throw new Error(`Factory definition file ${file} must default-export a (registry) => void function`);
70
+ }
71
+ module.default(registry);
72
+ }
73
+ return files;
74
+ }
75
+ /**
76
+ * Fully reloads definitions: resets the registry (dropping every factory, trait,
77
+ * sequence, callback and default) and re-imports the target files with cache
78
+ * busting so edited definitions take effect.
79
+ * @param {import("../factory-registry.js").default} registry - Registry to reload.
80
+ * @param {string | string[]} target - File path, directory, or list of paths.
81
+ * @returns {Promise<string[]>} - The reloaded file paths, in load order.
82
+ */
83
+ export async function reloadDefinitions(registry, target) {
84
+ registry.reset();
85
+ return await loadDefinitions(registry, target, { reload: true });
86
+ }
87
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9hZC1kZWZpbml0aW9ucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy90ZXN0aW5nL2ZhY3Rvcnkvbm9kZS9sb2FkLWRlZmluaXRpb25zLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLFlBQVk7QUFFWixPQUFPLEVBQUMsYUFBYSxFQUFDLE1BQU0sVUFBVSxDQUFBO0FBQ3RDLE9BQU8sRUFBQyxPQUFPLEVBQUUsSUFBSSxFQUFDLE1BQU0sa0JBQWtCLENBQUE7QUFDOUMsT0FBTyxJQUFJLE1BQU0sV0FBVyxDQUFBO0FBRTVCOzs7O0dBSUc7QUFDSCxJQUFJLGFBQWEsR0FBRyxDQUFDLENBQUE7QUFFckI7Ozs7O0dBS0c7QUFDSCxLQUFLLFVBQVUscUJBQXFCLENBQUMsU0FBUztJQUM1QyxNQUFNLE9BQU8sR0FBRyxNQUFNLE9BQU8sQ0FBQyxTQUFTLEVBQUUsRUFBQyxhQUFhLEVBQUUsSUFBSSxFQUFDLENBQUMsQ0FBQTtJQUMvRCx1QkFBdUI7SUFDdkIsTUFBTSxLQUFLLEdBQUcsRUFBRSxDQUFBO0lBRWhCLEtBQUssTUFBTSxLQUFLLElBQUksQ0FBQyxHQUFHLE9BQU8sQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLElBQUksRUFBRSxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksR0FBRyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1FBQzFGLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQTtRQUVqRCxJQUFJLEtBQUssQ0FBQyxXQUFXLEVBQUUsRUFBRSxDQUFDO1lBQ3hCLEtBQUssQ0FBQyxJQUFJLENBQUMsR0FBRyxNQUFNLHFCQUFxQixDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUE7UUFDdEQsQ0FBQzthQUFNLElBQUksS0FBSyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQztZQUN0QyxLQUFLLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFBO1FBQ3RCLENBQUM7SUFDSCxDQUFDO0lBRUQsT0FBTyxLQUFLLENBQUE7QUFDZCxDQUFDO0FBRUQ7Ozs7O0dBS0c7QUFDSCxLQUFLLFVBQVUsWUFBWSxDQUFDLE1BQU07SUFDaEMsSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUM7UUFDMUIsT0FBTyxDQUFDLEdBQUcsSUFBSSxHQUFHLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQTtJQUN4RSxDQUFDO0lBRUQsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQTtJQUNyQyxNQUFNLEtBQUssR0FBRyxNQUFNLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQTtJQUVsQyxJQUFJLEtBQUssQ0FBQyxXQUFXLEVBQUU7UUFBRSxPQUFPLE1BQU0scUJBQXFCLENBQUMsUUFBUSxDQUFDLENBQUE7SUFFckUsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFBO0FBQ25CLENBQUM7QUFFRDs7Ozs7Ozs7OztHQVVHO0FBQ0gsTUFBTSxDQUFDLEtBQUssVUFBVSxlQUFlLENBQUMsUUFBUSxFQUFFLE1BQU0sRUFBRSxFQUFDLE1BQU0sR0FBRyxLQUFLLEVBQUMsR0FBRyxFQUFFO0lBQzNFLE1BQU0sS0FBSyxHQUFHLE1BQU0sWUFBWSxDQUFDLE1BQU0sQ0FBQyxDQUFBO0lBRXhDLEtBQUssTUFBTSxJQUFJLElBQUksS0FBSyxFQUFFLENBQUM7UUFDekIsSUFBSSxJQUFJLEdBQUcsYUFBYSxDQUFDLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQTtRQUVuQyxJQUFJLE1BQU0sRUFBRSxDQUFDO1lBQ1gsYUFBYSxJQUFJLENBQUMsQ0FBQTtZQUNsQixJQUFJLElBQUksa0JBQWtCLGFBQWEsRUFBRSxDQUFBO1FBQzNDLENBQUM7UUFFRCxNQUFNLE1BQU0sR0FBRyxNQUFNLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQTtRQUVqQyxJQUFJLE9BQU8sTUFBTSxDQUFDLE9BQU8sS0FBSyxVQUFVLEVBQUUsQ0FBQztZQUN6QyxNQUFNLElBQUksS0FBSyxDQUFDLDJCQUEyQixJQUFJLG9EQUFvRCxDQUFDLENBQUE7UUFDdEcsQ0FBQztRQUVELE1BQU0sQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUE7SUFDMUIsQ0FBQztJQUVELE9BQU8sS0FBSyxDQUFBO0FBQ2QsQ0FBQztBQUVEOzs7Ozs7O0dBT0c7QUFDSCxNQUFNLENBQUMsS0FBSyxVQUFVLGlCQUFpQixDQUFDLFFBQVEsRUFBRSxNQUFNO0lBQ3RELFFBQVEsQ0FBQyxLQUFLLEVBQUUsQ0FBQTtJQUVoQixPQUFPLE1BQU0sZUFBZSxDQUFDLFFBQVEsRUFBRSxNQUFNLEVBQUUsRUFBQyxNQUFNLEVBQUUsSUFBSSxFQUFDLENBQUMsQ0FBQTtBQUNoRSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQHRzLWNoZWNrXG5cbmltcG9ydCB7cGF0aFRvRmlsZVVSTH0gZnJvbSBcIm5vZGU6dXJsXCJcbmltcG9ydCB7cmVhZGRpciwgc3RhdH0gZnJvbSBcIm5vZGU6ZnMvcHJvbWlzZXNcIlxuaW1wb3J0IHBhdGggZnJvbSBcIm5vZGU6cGF0aFwiXG5cbi8qKlxuICogTW9ub3RvbmljIGNhY2hlLWJ1c3RpbmcgY291bnRlciBzaGFyZWQgYnkgcmVsb2Fkcy4gS2VwdCBtb2R1bGUtbG9jYWwgc28gYSByZWxvYWRcbiAqIGltcG9ydHMgYSBmcmVzaCBtb2R1bGUgaW5zdGFuY2UgcmF0aGVyIHRoYW4gdGhlIGNhY2hlZCBvbmUuXG4gKiBAdHlwZSB7bnVtYmVyfVxuICovXG5sZXQgcmVsb2FkQ291bnRlciA9IDBcblxuLyoqXG4gKiBSZWN1cnNpdmVseSBjb2xsZWN0cyBgLmpzYCBmaWxlcyB1bmRlciBhIGRpcmVjdG9yeSBpbiBhIGRldGVybWluaXN0aWNcbiAqIChsZXhpY29ncmFwaGljYWxseSBzb3J0ZWQpIG9yZGVyLlxuICogQHBhcmFtIHtzdHJpbmd9IGRpcmVjdG9yeSAtIERpcmVjdG9yeSB0byBzY2FuLlxuICogQHJldHVybnMge1Byb21pc2U8c3RyaW5nW10+fSAtIFNvcnRlZCBhYnNvbHV0ZSBmaWxlIHBhdGhzLlxuICovXG5hc3luYyBmdW5jdGlvbiBjb2xsZWN0RGlyZWN0b3J5RmlsZXMoZGlyZWN0b3J5KSB7XG4gIGNvbnN0IGVudHJpZXMgPSBhd2FpdCByZWFkZGlyKGRpcmVjdG9yeSwge3dpdGhGaWxlVHlwZXM6IHRydWV9KVxuICAvKiogQHR5cGUge3N0cmluZ1tdfSAqL1xuICBjb25zdCBmaWxlcyA9IFtdXG5cbiAgZm9yIChjb25zdCBlbnRyeSBvZiBbLi4uZW50cmllc10uc29ydCgobGVmdCwgcmlnaHQpID0+IChsZWZ0Lm5hbWUgPCByaWdodC5uYW1lID8gLTEgOiAxKSkpIHtcbiAgICBjb25zdCBmdWxsUGF0aCA9IHBhdGguam9pbihkaXJlY3RvcnksIGVudHJ5Lm5hbWUpXG5cbiAgICBpZiAoZW50cnkuaXNEaXJlY3RvcnkoKSkge1xuICAgICAgZmlsZXMucHVzaCguLi5hd2FpdCBjb2xsZWN0RGlyZWN0b3J5RmlsZXMoZnVsbFBhdGgpKVxuICAgIH0gZWxzZSBpZiAoZW50cnkubmFtZS5lbmRzV2l0aChcIi5qc1wiKSkge1xuICAgICAgZmlsZXMucHVzaChmdWxsUGF0aClcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZmlsZXNcbn1cblxuLyoqXG4gKiBSZXNvbHZlcyBhIGxvYWQgdGFyZ2V0IChhIHNpbmdsZSBmaWxlLCBhIGRpcmVjdG9yeSwgb3IgYW4gZXhwbGljaXQgbGlzdCkgaW50byBhXG4gKiBkZXRlcm1pbmlzdGljLCBkZS1kdXBsaWNhdGVkIGxpc3Qgb2YgYWJzb2x1dGUgZGVmaW5pdGlvbiBmaWxlIHBhdGhzLlxuICogQHBhcmFtIHtzdHJpbmcgfCBzdHJpbmdbXX0gdGFyZ2V0IC0gRmlsZSBwYXRoLCBkaXJlY3RvcnksIG9yIGxpc3Qgb2YgcGF0aHMuXG4gKiBAcmV0dXJucyB7UHJvbWlzZTxzdHJpbmdbXT59IC0gU29ydGVkLCBkZS1kdXBsaWNhdGVkIGFic29sdXRlIGZpbGUgcGF0aHMuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIHJlc29sdmVGaWxlcyh0YXJnZXQpIHtcbiAgaWYgKEFycmF5LmlzQXJyYXkodGFyZ2V0KSkge1xuICAgIHJldHVybiBbLi4ubmV3IFNldCh0YXJnZXQubWFwKChlbnRyeSkgPT4gcGF0aC5yZXNvbHZlKGVudHJ5KSkpXS5zb3J0KClcbiAgfVxuXG4gIGNvbnN0IHJlc29sdmVkID0gcGF0aC5yZXNvbHZlKHRhcmdldClcbiAgY29uc3Qgc3RhdHMgPSBhd2FpdCBzdGF0KHJlc29sdmVkKVxuXG4gIGlmIChzdGF0cy5pc0RpcmVjdG9yeSgpKSByZXR1cm4gYXdhaXQgY29sbGVjdERpcmVjdG9yeUZpbGVzKHJlc29sdmVkKVxuXG4gIHJldHVybiBbcmVzb2x2ZWRdXG59XG5cbi8qKlxuICogTG9hZHMgVmVsb2Npb3VzIGZhY3RvcnkgZGVmaW5pdGlvbiBmaWxlcyAoTm9kZSBvbmx5KS4gRWFjaCBmaWxlIG11c3RcbiAqIGRlZmF1bHQtZXhwb3J0IGEgYChyZWdpc3RyeSkgPT4gdm9pZGAgZnVuY3Rpb24gdGhhdCBkZWZpbmVzIGludG8gdGhlIHJlZ2lzdHJ5LlxuICogRmlsZXMgbG9hZCBpbiBkZXRlcm1pbmlzdGljIHBhdGggb3JkZXIuIFRoaXMgbW9kdWxlIGlzIGludGVudGlvbmFsbHkgTm9kZS1vbmx5XG4gKiAoZmlsZXN5c3RlbSArIGR5bmFtaWMgaW1wb3J0KSBhbmQgbXVzdCBuZXZlciBiZSBpbXBvcnRlZCBmcm9tIGJyb3dzZXIvTWV0cm9cbiAqIGJ1bmRsZXM7IGltcG9ydCB0aGUgYnJvd3Nlci1zYWZlIGNvcmUgZnJvbSBgLi4vaW5kZXguanNgIHRoZXJlIGluc3RlYWQuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL2ZhY3RvcnktcmVnaXN0cnkuanNcIikuZGVmYXVsdH0gcmVnaXN0cnkgLSBSZWdpc3RyeSB0byBkZWZpbmUgaW50by5cbiAqIEBwYXJhbSB7c3RyaW5nIHwgc3RyaW5nW119IHRhcmdldCAtIEZpbGUgcGF0aCwgZGlyZWN0b3J5LCBvciBsaXN0IG9mIHBhdGhzLlxuICogQHBhcmFtIHt7cmVsb2FkPzogYm9vbGVhbn19IFtvcHRpb25zXSAtIE9wdGlvbnMuXG4gKiBAcmV0dXJucyB7UHJvbWlzZTxzdHJpbmdbXT59IC0gVGhlIGxvYWRlZCBmaWxlIHBhdGhzLCBpbiBsb2FkIG9yZGVyLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gbG9hZERlZmluaXRpb25zKHJlZ2lzdHJ5LCB0YXJnZXQsIHtyZWxvYWQgPSBmYWxzZX0gPSB7fSkge1xuICBjb25zdCBmaWxlcyA9IGF3YWl0IHJlc29sdmVGaWxlcyh0YXJnZXQpXG5cbiAgZm9yIChjb25zdCBmaWxlIG9mIGZpbGVzKSB7XG4gICAgbGV0IGhyZWYgPSBwYXRoVG9GaWxlVVJMKGZpbGUpLmhyZWZcblxuICAgIGlmIChyZWxvYWQpIHtcbiAgICAgIHJlbG9hZENvdW50ZXIgKz0gMVxuICAgICAgaHJlZiArPSBgP2ZhY3RvcnlSZWxvYWQ9JHtyZWxvYWRDb3VudGVyfWBcbiAgICB9XG5cbiAgICBjb25zdCBtb2R1bGUgPSBhd2FpdCBpbXBvcnQoaHJlZilcblxuICAgIGlmICh0eXBlb2YgbW9kdWxlLmRlZmF1bHQgIT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBGYWN0b3J5IGRlZmluaXRpb24gZmlsZSAke2ZpbGV9IG11c3QgZGVmYXVsdC1leHBvcnQgYSAocmVnaXN0cnkpID0+IHZvaWQgZnVuY3Rpb25gKVxuICAgIH1cblxuICAgIG1vZHVsZS5kZWZhdWx0KHJlZ2lzdHJ5KVxuICB9XG5cbiAgcmV0dXJuIGZpbGVzXG59XG5cbi8qKlxuICogRnVsbHkgcmVsb2FkcyBkZWZpbml0aW9uczogcmVzZXRzIHRoZSByZWdpc3RyeSAoZHJvcHBpbmcgZXZlcnkgZmFjdG9yeSwgdHJhaXQsXG4gKiBzZXF1ZW5jZSwgY2FsbGJhY2sgYW5kIGRlZmF1bHQpIGFuZCByZS1pbXBvcnRzIHRoZSB0YXJnZXQgZmlsZXMgd2l0aCBjYWNoZVxuICogYnVzdGluZyBzbyBlZGl0ZWQgZGVmaW5pdGlvbnMgdGFrZSBlZmZlY3QuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4uL2ZhY3RvcnktcmVnaXN0cnkuanNcIikuZGVmYXVsdH0gcmVnaXN0cnkgLSBSZWdpc3RyeSB0byByZWxvYWQuXG4gKiBAcGFyYW0ge3N0cmluZyB8IHN0cmluZ1tdfSB0YXJnZXQgLSBGaWxlIHBhdGgsIGRpcmVjdG9yeSwgb3IgbGlzdCBvZiBwYXRocy5cbiAqIEByZXR1cm5zIHtQcm9taXNlPHN0cmluZ1tdPn0gLSBUaGUgcmVsb2FkZWQgZmlsZSBwYXRocywgaW4gbG9hZCBvcmRlci5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlbG9hZERlZmluaXRpb25zKHJlZ2lzdHJ5LCB0YXJnZXQpIHtcbiAgcmVnaXN0cnkucmVzZXQoKVxuXG4gIHJldHVybiBhd2FpdCBsb2FkRGVmaW5pdGlvbnMocmVnaXN0cnksIHRhcmdldCwge3JlbG9hZDogdHJ1ZX0pXG59XG4iXX0=
@@ -0,0 +1,73 @@
1
+ /**
2
+ * SequenceFormatter type. Receives the synchronously-allocated numeric value and
3
+ * returns the formatted value (optionally asynchronously).
4
+ * @typedef {(args: {value: number}) => (? | Promise<?>)} SequenceFormatter
5
+ */
6
+ /**
7
+ * A numeric counter sequence. Values are allocated and consumed synchronously
8
+ * before the (possibly async) formatter runs, so a rejected formatter still
9
+ * advances the counter and concurrent `Promise.all` allocation never collides —
10
+ * matching FactoryBot's failed-value-consumption behaviour.
11
+ */
12
+ export default class Sequence {
13
+ /**
14
+ * Builds a sequence.
15
+ * @param {object} args - Options.
16
+ * @param {string} args.name - Primary sequence name.
17
+ * @param {number} [args.initial] - First value the sequence yields. Defaults to 1.
18
+ * @param {SequenceFormatter} [args.formatter] - Optional formatter for the value.
19
+ * @param {string[]} [args.aliases] - Additional names that share this sequence's state.
20
+ */
21
+ constructor({ name, initial, formatter, aliases }: {
22
+ name: string;
23
+ initial?: number | undefined;
24
+ formatter?: SequenceFormatter | undefined;
25
+ aliases?: string[] | undefined;
26
+ });
27
+ /** @type {string} - Primary sequence name. */
28
+ name: string;
29
+ /** @type {number} - First value the sequence yields. */
30
+ initial: number;
31
+ /** @type {SequenceFormatter | undefined} - Optional value formatter. */
32
+ formatter: SequenceFormatter | undefined;
33
+ /** @type {string[]} - Names that share this sequence's counter. */
34
+ aliases: string[];
35
+ /** @type {number} - Next value to allocate. */
36
+ _next: number;
37
+ /**
38
+ * Allocates and consumes the next numeric value synchronously.
39
+ * @returns {number} - The allocated raw value.
40
+ */
41
+ _allocate(): number;
42
+ /**
43
+ * Advances the sequence and returns the formatted value. The numeric value is
44
+ * consumed synchronously before awaiting the formatter, so a rejected formatter
45
+ * still advances the counter.
46
+ * @returns {Promise<?>} - The formatted value.
47
+ */
48
+ next(): Promise<unknown>;
49
+ /**
50
+ * Returns the value the next `next()` call will allocate without consuming it.
51
+ * @returns {number} - The upcoming raw value.
52
+ */
53
+ peek(): number;
54
+ /**
55
+ * Sets the next value the sequence will allocate.
56
+ * @param {number} value - Next raw value.
57
+ * @returns {void}
58
+ */
59
+ set(value: number): void;
60
+ /**
61
+ * Resets the counter back to its initial value.
62
+ * @returns {void}
63
+ */
64
+ rewind(): void;
65
+ }
66
+ /**
67
+ * SequenceFormatter type. Receives the synchronously-allocated numeric value and
68
+ * returns the formatted value (optionally asynchronously).
69
+ */
70
+ export type SequenceFormatter = (args: {
71
+ value: number;
72
+ }) => (unknown | Promise<unknown>);
73
+ //# sourceMappingURL=sequence.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sequence.d.ts","sourceRoot":"","sources":["../../../../src/testing/factory/sequence.js"],"names":[],"mappings":"AAEA;;;;GAIG;AAEH;;;;;GAKG;AACH;IACE;;;;;;;OAOG;IACH,mDALG;QAAqB,IAAI,EAAjB,MAAM;QACQ,OAAO;QACI,SAAS;QAClB,OAAO;KACjC,EAgBA;IAdC,8CAA8C;IAC9C,MADW,MAAM,CACD;IAEhB,wDAAwD;IACxD,SADW,MAAM,CACK;IAEtB,wEAAwE;IACxE,WADW,iBAAiB,GAAG,SAAS,CACd;IAE1B,mEAAmE;IACnE,SADW,MAAM,EAAE,CACG;IAEtB,+CAA+C;IAC/C,OADW,MAAM,CACG;IAGtB;;;OAGG;IACH,aAFa,MAAM,CAQlB;IAED;;;;;OAKG;IACH,QAFa,OAAO,CAAC,OAAC,CAAC,CAQtB;IAED;;;OAGG;IACH,QAFa,MAAM,CAIlB;IAED;;;;OAIG;IACH,WAHW,MAAM,GACJ,IAAI,CAIhB;IAED;;;OAGG;IACH,UAFa,IAAI,CAIhB;CACF;;;;;gCArFY,CAAC,IAAI,EAAE;IAAC,KAAK,EAAE,MAAM,CAAA;CAAC,KAAK,CAAC,OAAC,GAAG,OAAO,CAAC,OAAC,CAAC,CAAC"}
@@ -0,0 +1,78 @@
1
+ // @ts-check
2
+ /**
3
+ * SequenceFormatter type. Receives the synchronously-allocated numeric value and
4
+ * returns the formatted value (optionally asynchronously).
5
+ * @typedef {(args: {value: number}) => (? | Promise<?>)} SequenceFormatter
6
+ */
7
+ /**
8
+ * A numeric counter sequence. Values are allocated and consumed synchronously
9
+ * before the (possibly async) formatter runs, so a rejected formatter still
10
+ * advances the counter and concurrent `Promise.all` allocation never collides —
11
+ * matching FactoryBot's failed-value-consumption behaviour.
12
+ */
13
+ export default class Sequence {
14
+ /**
15
+ * Builds a sequence.
16
+ * @param {object} args - Options.
17
+ * @param {string} args.name - Primary sequence name.
18
+ * @param {number} [args.initial] - First value the sequence yields. Defaults to 1.
19
+ * @param {SequenceFormatter} [args.formatter] - Optional formatter for the value.
20
+ * @param {string[]} [args.aliases] - Additional names that share this sequence's state.
21
+ */
22
+ constructor({ name, initial = 1, formatter, aliases = [] }) {
23
+ /** @type {string} - Primary sequence name. */
24
+ this.name = name;
25
+ /** @type {number} - First value the sequence yields. */
26
+ this.initial = initial;
27
+ /** @type {SequenceFormatter | undefined} - Optional value formatter. */
28
+ this.formatter = formatter;
29
+ /** @type {string[]} - Names that share this sequence's counter. */
30
+ this.aliases = aliases;
31
+ /** @type {number} - Next value to allocate. */
32
+ this._next = initial;
33
+ }
34
+ /**
35
+ * Allocates and consumes the next numeric value synchronously.
36
+ * @returns {number} - The allocated raw value.
37
+ */
38
+ _allocate() {
39
+ const value = this._next;
40
+ this._next += 1;
41
+ return value;
42
+ }
43
+ /**
44
+ * Advances the sequence and returns the formatted value. The numeric value is
45
+ * consumed synchronously before awaiting the formatter, so a rejected formatter
46
+ * still advances the counter.
47
+ * @returns {Promise<?>} - The formatted value.
48
+ */
49
+ async next() {
50
+ const value = this._allocate();
51
+ if (!this.formatter)
52
+ return value;
53
+ return await this.formatter({ value });
54
+ }
55
+ /**
56
+ * Returns the value the next `next()` call will allocate without consuming it.
57
+ * @returns {number} - The upcoming raw value.
58
+ */
59
+ peek() {
60
+ return this._next;
61
+ }
62
+ /**
63
+ * Sets the next value the sequence will allocate.
64
+ * @param {number} value - Next raw value.
65
+ * @returns {void}
66
+ */
67
+ set(value) {
68
+ this._next = value;
69
+ }
70
+ /**
71
+ * Resets the counter back to its initial value.
72
+ * @returns {void}
73
+ */
74
+ rewind() {
75
+ this._next = this.initial;
76
+ }
77
+ }
78
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VxdWVuY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvdGVzdGluZy9mYWN0b3J5L3NlcXVlbmNlLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLFlBQVk7QUFFWjs7OztHQUlHO0FBRUg7Ozs7O0dBS0c7QUFDSCxNQUFNLENBQUMsT0FBTyxPQUFPLFFBQVE7SUFDM0I7Ozs7Ozs7T0FPRztJQUNILFlBQVksRUFBQyxJQUFJLEVBQUUsT0FBTyxHQUFHLENBQUMsRUFBRSxTQUFTLEVBQUUsT0FBTyxHQUFHLEVBQUUsRUFBQztRQUN0RCw4Q0FBOEM7UUFDOUMsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUE7UUFFaEIsd0RBQXdEO1FBQ3hELElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFBO1FBRXRCLHdFQUF3RTtRQUN4RSxJQUFJLENBQUMsU0FBUyxHQUFHLFNBQVMsQ0FBQTtRQUUxQixtRUFBbUU7UUFDbkUsSUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUE7UUFFdEIsK0NBQStDO1FBQy9DLElBQUksQ0FBQyxLQUFLLEdBQUcsT0FBTyxDQUFBO0lBQ3RCLENBQUM7SUFFRDs7O09BR0c7SUFDSCxTQUFTO1FBQ1AsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQTtRQUV4QixJQUFJLENBQUMsS0FBSyxJQUFJLENBQUMsQ0FBQTtRQUVmLE9BQU8sS0FBSyxDQUFBO0lBQ2QsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsS0FBSyxDQUFDLElBQUk7UUFDUixNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUE7UUFFOUIsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTO1lBQUUsT0FBTyxLQUFLLENBQUE7UUFFakMsT0FBTyxNQUFNLElBQUksQ0FBQyxTQUFTLENBQUMsRUFBQyxLQUFLLEVBQUMsQ0FBQyxDQUFBO0lBQ3RDLENBQUM7SUFFRDs7O09BR0c7SUFDSCxJQUFJO1FBQ0YsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFBO0lBQ25CLENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsR0FBRyxDQUFDLEtBQUs7UUFDUCxJQUFJLENBQUMsS0FBSyxHQUFHLEtBQUssQ0FBQTtJQUNwQixDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsTUFBTTtRQUNKLElBQUksQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQTtJQUMzQixDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBAdHMtY2hlY2tcblxuLyoqXG4gKiBTZXF1ZW5jZUZvcm1hdHRlciB0eXBlLiBSZWNlaXZlcyB0aGUgc3luY2hyb25vdXNseS1hbGxvY2F0ZWQgbnVtZXJpYyB2YWx1ZSBhbmRcbiAqIHJldHVybnMgdGhlIGZvcm1hdHRlZCB2YWx1ZSAob3B0aW9uYWxseSBhc3luY2hyb25vdXNseSkuXG4gKiBAdHlwZWRlZiB7KGFyZ3M6IHt2YWx1ZTogbnVtYmVyfSkgPT4gKD8gfCBQcm9taXNlPD8+KX0gU2VxdWVuY2VGb3JtYXR0ZXJcbiAqL1xuXG4vKipcbiAqIEEgbnVtZXJpYyBjb3VudGVyIHNlcXVlbmNlLiBWYWx1ZXMgYXJlIGFsbG9jYXRlZCBhbmQgY29uc3VtZWQgc3luY2hyb25vdXNseVxuICogYmVmb3JlIHRoZSAocG9zc2libHkgYXN5bmMpIGZvcm1hdHRlciBydW5zLCBzbyBhIHJlamVjdGVkIGZvcm1hdHRlciBzdGlsbFxuICogYWR2YW5jZXMgdGhlIGNvdW50ZXIgYW5kIGNvbmN1cnJlbnQgYFByb21pc2UuYWxsYCBhbGxvY2F0aW9uIG5ldmVyIGNvbGxpZGVzIOKAlFxuICogbWF0Y2hpbmcgRmFjdG9yeUJvdCdzIGZhaWxlZC12YWx1ZS1jb25zdW1wdGlvbiBiZWhhdmlvdXIuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFNlcXVlbmNlIHtcbiAgLyoqXG4gICAqIEJ1aWxkcyBhIHNlcXVlbmNlLlxuICAgKiBAcGFyYW0ge29iamVjdH0gYXJncyAtIE9wdGlvbnMuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBhcmdzLm5hbWUgLSBQcmltYXJ5IHNlcXVlbmNlIG5hbWUuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbYXJncy5pbml0aWFsXSAtIEZpcnN0IHZhbHVlIHRoZSBzZXF1ZW5jZSB5aWVsZHMuIERlZmF1bHRzIHRvIDEuXG4gICAqIEBwYXJhbSB7U2VxdWVuY2VGb3JtYXR0ZXJ9IFthcmdzLmZvcm1hdHRlcl0gLSBPcHRpb25hbCBmb3JtYXR0ZXIgZm9yIHRoZSB2YWx1ZS5cbiAgICogQHBhcmFtIHtzdHJpbmdbXX0gW2FyZ3MuYWxpYXNlc10gLSBBZGRpdGlvbmFsIG5hbWVzIHRoYXQgc2hhcmUgdGhpcyBzZXF1ZW5jZSdzIHN0YXRlLlxuICAgKi9cbiAgY29uc3RydWN0b3Ioe25hbWUsIGluaXRpYWwgPSAxLCBmb3JtYXR0ZXIsIGFsaWFzZXMgPSBbXX0pIHtcbiAgICAvKiogQHR5cGUge3N0cmluZ30gLSBQcmltYXJ5IHNlcXVlbmNlIG5hbWUuICovXG4gICAgdGhpcy5uYW1lID0gbmFtZVxuXG4gICAgLyoqIEB0eXBlIHtudW1iZXJ9IC0gRmlyc3QgdmFsdWUgdGhlIHNlcXVlbmNlIHlpZWxkcy4gKi9cbiAgICB0aGlzLmluaXRpYWwgPSBpbml0aWFsXG5cbiAgICAvKiogQHR5cGUge1NlcXVlbmNlRm9ybWF0dGVyIHwgdW5kZWZpbmVkfSAtIE9wdGlvbmFsIHZhbHVlIGZvcm1hdHRlci4gKi9cbiAgICB0aGlzLmZvcm1hdHRlciA9IGZvcm1hdHRlclxuXG4gICAgLyoqIEB0eXBlIHtzdHJpbmdbXX0gLSBOYW1lcyB0aGF0IHNoYXJlIHRoaXMgc2VxdWVuY2UncyBjb3VudGVyLiAqL1xuICAgIHRoaXMuYWxpYXNlcyA9IGFsaWFzZXNcblxuICAgIC8qKiBAdHlwZSB7bnVtYmVyfSAtIE5leHQgdmFsdWUgdG8gYWxsb2NhdGUuICovXG4gICAgdGhpcy5fbmV4dCA9IGluaXRpYWxcbiAgfVxuXG4gIC8qKlxuICAgKiBBbGxvY2F0ZXMgYW5kIGNvbnN1bWVzIHRoZSBuZXh0IG51bWVyaWMgdmFsdWUgc3luY2hyb25vdXNseS5cbiAgICogQHJldHVybnMge251bWJlcn0gLSBUaGUgYWxsb2NhdGVkIHJhdyB2YWx1ZS5cbiAgICovXG4gIF9hbGxvY2F0ZSgpIHtcbiAgICBjb25zdCB2YWx1ZSA9IHRoaXMuX25leHRcblxuICAgIHRoaXMuX25leHQgKz0gMVxuXG4gICAgcmV0dXJuIHZhbHVlXG4gIH1cblxuICAvKipcbiAgICogQWR2YW5jZXMgdGhlIHNlcXVlbmNlIGFuZCByZXR1cm5zIHRoZSBmb3JtYXR0ZWQgdmFsdWUuIFRoZSBudW1lcmljIHZhbHVlIGlzXG4gICAqIGNvbnN1bWVkIHN5bmNocm9ub3VzbHkgYmVmb3JlIGF3YWl0aW5nIHRoZSBmb3JtYXR0ZXIsIHNvIGEgcmVqZWN0ZWQgZm9ybWF0dGVyXG4gICAqIHN0aWxsIGFkdmFuY2VzIHRoZSBjb3VudGVyLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTw/Pn0gLSBUaGUgZm9ybWF0dGVkIHZhbHVlLlxuICAgKi9cbiAgYXN5bmMgbmV4dCgpIHtcbiAgICBjb25zdCB2YWx1ZSA9IHRoaXMuX2FsbG9jYXRlKClcblxuICAgIGlmICghdGhpcy5mb3JtYXR0ZXIpIHJldHVybiB2YWx1ZVxuXG4gICAgcmV0dXJuIGF3YWl0IHRoaXMuZm9ybWF0dGVyKHt2YWx1ZX0pXG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgdmFsdWUgdGhlIG5leHQgYG5leHQoKWAgY2FsbCB3aWxsIGFsbG9jYXRlIHdpdGhvdXQgY29uc3VtaW5nIGl0LlxuICAgKiBAcmV0dXJucyB7bnVtYmVyfSAtIFRoZSB1cGNvbWluZyByYXcgdmFsdWUuXG4gICAqL1xuICBwZWVrKCkge1xuICAgIHJldHVybiB0aGlzLl9uZXh0XG4gIH1cblxuICAvKipcbiAgICogU2V0cyB0aGUgbmV4dCB2YWx1ZSB0aGUgc2VxdWVuY2Ugd2lsbCBhbGxvY2F0ZS5cbiAgICogQHBhcmFtIHtudW1iZXJ9IHZhbHVlIC0gTmV4dCByYXcgdmFsdWUuXG4gICAqIEByZXR1cm5zIHt2b2lkfVxuICAgKi9cbiAgc2V0KHZhbHVlKSB7XG4gICAgdGhpcy5fbmV4dCA9IHZhbHVlXG4gIH1cblxuICAvKipcbiAgICogUmVzZXRzIHRoZSBjb3VudGVyIGJhY2sgdG8gaXRzIGluaXRpYWwgdmFsdWUuXG4gICAqIEByZXR1cm5zIHt2b2lkfVxuICAgKi9cbiAgcmV3aW5kKCkge1xuICAgIHRoaXMuX25leHQgPSB0aGlzLmluaXRpYWxcbiAgfVxufVxuIl19
@@ -0,0 +1,21 @@
1
+ /**
2
+ * The `attributesFor` strategy. It resolves scalar/lazy attributes (and any
3
+ * transients they depend on) but never initializes the model, runs lifecycle
4
+ * callbacks, or evaluates/builds declared associations. Transients and
5
+ * associations are omitted from the returned plain object.
6
+ */
7
+ export default class AttributesForStrategy extends BaseStrategy {
8
+ /**
9
+ * Runs the strategy.
10
+ * @param {object} args - Options.
11
+ * @param {import("../factory-registry.js").default} args.registry - Owning registry.
12
+ * @param {import("../factory-runner.js").CompiledPlan} args.plan - Compiled plan.
13
+ * @returns {Promise<Record<string, ?>>} - The resolved attributes.
14
+ */
15
+ run({ registry, plan }: {
16
+ registry: import("../factory-registry.js").default;
17
+ plan: import("../factory-runner.js").CompiledPlan;
18
+ }): Promise<Record<string, unknown>>;
19
+ }
20
+ import BaseStrategy from "./base.js";
21
+ //# sourceMappingURL=attributes-for.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attributes-for.d.ts","sourceRoot":"","sources":["../../../../../src/testing/factory/strategies/attributes-for.js"],"names":[],"mappings":"AAIA;;;;;GAKG;AACH;IACE;;;;;;OAMG;IACH,wBAJG;QAAuD,QAAQ,EAAvD,OAAO,wBAAwB,EAAE,OAAO;QACU,IAAI,EAAtD,OAAO,sBAAsB,EAAE,YAAY;KACnD,GAAU,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAC,CAAC,CAAC,CAMtC;CACF;yBArBwB,WAAW"}
@@ -0,0 +1,22 @@
1
+ // @ts-check
2
+ import BaseStrategy from "./base.js";
3
+ /**
4
+ * The `attributesFor` strategy. It resolves scalar/lazy attributes (and any
5
+ * transients they depend on) but never initializes the model, runs lifecycle
6
+ * callbacks, or evaluates/builds declared associations. Transients and
7
+ * associations are omitted from the returned plain object.
8
+ */
9
+ export default class AttributesForStrategy extends BaseStrategy {
10
+ /**
11
+ * Runs the strategy.
12
+ * @param {object} args - Options.
13
+ * @param {import("../factory-registry.js").default} args.registry - Owning registry.
14
+ * @param {import("../factory-runner.js").CompiledPlan} args.plan - Compiled plan.
15
+ * @returns {Promise<Record<string, ?>>} - The resolved attributes.
16
+ */
17
+ async run({ registry, plan }) {
18
+ const context = this._newContext(registry, plan, "attributesFor");
19
+ return await context.resolveAttributes();
20
+ }
21
+ }
22
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXR0cmlidXRlcy1mb3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvdGVzdGluZy9mYWN0b3J5L3N0cmF0ZWdpZXMvYXR0cmlidXRlcy1mb3IuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsWUFBWTtBQUVaLE9BQU8sWUFBWSxNQUFNLFdBQVcsQ0FBQTtBQUVwQzs7Ozs7R0FLRztBQUNILE1BQU0sQ0FBQyxPQUFPLE9BQU8scUJBQXNCLFNBQVEsWUFBWTtJQUM3RDs7Ozs7O09BTUc7SUFDSCxLQUFLLENBQUMsR0FBRyxDQUFDLEVBQUMsUUFBUSxFQUFFLElBQUksRUFBQztRQUN4QixNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLFFBQVEsRUFBRSxJQUFJLEVBQUUsZUFBZSxDQUFDLENBQUE7UUFFakUsT0FBTyxNQUFNLE9BQU8sQ0FBQyxpQkFBaUIsRUFBRSxDQUFBO0lBQzFDLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbIi8vIEB0cy1jaGVja1xuXG5pbXBvcnQgQmFzZVN0cmF0ZWd5IGZyb20gXCIuL2Jhc2UuanNcIlxuXG4vKipcbiAqIFRoZSBgYXR0cmlidXRlc0ZvcmAgc3RyYXRlZ3kuIEl0IHJlc29sdmVzIHNjYWxhci9sYXp5IGF0dHJpYnV0ZXMgKGFuZCBhbnlcbiAqIHRyYW5zaWVudHMgdGhleSBkZXBlbmQgb24pIGJ1dCBuZXZlciBpbml0aWFsaXplcyB0aGUgbW9kZWwsIHJ1bnMgbGlmZWN5Y2xlXG4gKiBjYWxsYmFja3MsIG9yIGV2YWx1YXRlcy9idWlsZHMgZGVjbGFyZWQgYXNzb2NpYXRpb25zLiBUcmFuc2llbnRzIGFuZFxuICogYXNzb2NpYXRpb25zIGFyZSBvbWl0dGVkIGZyb20gdGhlIHJldHVybmVkIHBsYWluIG9iamVjdC5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgQXR0cmlidXRlc0ZvclN0cmF0ZWd5IGV4dGVuZHMgQmFzZVN0cmF0ZWd5IHtcbiAgLyoqXG4gICAqIFJ1bnMgdGhlIHN0cmF0ZWd5LlxuICAgKiBAcGFyYW0ge29iamVjdH0gYXJncyAtIE9wdGlvbnMuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vZmFjdG9yeS1yZWdpc3RyeS5qc1wiKS5kZWZhdWx0fSBhcmdzLnJlZ2lzdHJ5IC0gT3duaW5nIHJlZ2lzdHJ5LlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL2ZhY3RvcnktcnVubmVyLmpzXCIpLkNvbXBpbGVkUGxhbn0gYXJncy5wbGFuIC0gQ29tcGlsZWQgcGxhbi5cbiAgICogQHJldHVybnMge1Byb21pc2U8UmVjb3JkPHN0cmluZywgPz4+fSAtIFRoZSByZXNvbHZlZCBhdHRyaWJ1dGVzLlxuICAgKi9cbiAgYXN5bmMgcnVuKHtyZWdpc3RyeSwgcGxhbn0pIHtcbiAgICBjb25zdCBjb250ZXh0ID0gdGhpcy5fbmV3Q29udGV4dChyZWdpc3RyeSwgcGxhbiwgXCJhdHRyaWJ1dGVzRm9yXCIpXG5cbiAgICByZXR1cm4gYXdhaXQgY29udGV4dC5yZXNvbHZlQXR0cmlidXRlcygpXG4gIH1cbn1cbiJdfQ==
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Shared behaviour for the build/create/attributesFor strategies: evaluation
3
+ * context creation, deterministic callback execution, guaranteed `afterAll`
4
+ * cleanup, record construction (default and `initializeWith`), and association
5
+ * wiring through public relationship reflection.
6
+ */
7
+ export default class BaseStrategy {
8
+ /**
9
+ * Creates an evaluation context for a plan.
10
+ * @param {import("../factory-registry.js").default} registry - Owning registry.
11
+ * @param {import("../factory-runner.js").CompiledPlan} plan - Compiled plan.
12
+ * @param {"attributesFor" | "build" | "create"} strategyName - Strategy name.
13
+ * @returns {EvaluationContext} - The context.
14
+ */
15
+ _newContext(registry: import("../factory-registry.js").default, plan: import("../factory-runner.js").CompiledPlan, strategyName: "attributesFor" | "build" | "create"): EvaluationContext;
16
+ /**
17
+ * Builds the callback `context` object: evaluated transients exposed as plain
18
+ * properties (no Proxy) plus the named evaluator methods.
19
+ * @param {EvaluationContext} context - Evaluation context.
20
+ * @param {Record<string, ?>} transients - Evaluated transient values.
21
+ * @returns {Record<string, ?>} - The callback context.
22
+ */
23
+ _callbackContext(context: EvaluationContext, transients: Record<string, unknown>): Record<string, unknown>;
24
+ /**
25
+ * Runs every deduped callback for an event in declaration order.
26
+ * @param {EvaluationContext} context - Evaluation context.
27
+ * @param {import("../factory-runner.js").CompiledPlan} plan - Compiled plan.
28
+ * @param {string} event - Event name (e.g. "afterCreate").
29
+ * @param {{record: ?, transients: Record<string, ?>, strategy: string}} state - Current record/transients/strategy.
30
+ * @returns {Promise<void>} - Resolves when all callbacks complete.
31
+ */
32
+ _runCallbacks(context: EvaluationContext, plan: import("../factory-runner.js").CompiledPlan, event: string, state: {
33
+ record: unknown;
34
+ transients: Record<string, unknown>;
35
+ strategy: string;
36
+ }): Promise<void>;
37
+ /**
38
+ * Runs `body`, then guarantees `afterAll` runs in `finally`. When both the body
39
+ * and cleanup fail, the body's primary error is preserved and the cleanup error
40
+ * is attached as a detail rather than masking it.
41
+ * @param {EvaluationContext} context - Evaluation context.
42
+ * @param {import("../factory-runner.js").CompiledPlan} plan - Compiled plan.
43
+ * @param {() => {record: ?, transients: Record<string, ?>, strategy: string}} state - Late-bound state accessor.
44
+ * @param {() => Promise<?>} body - The strategy body.
45
+ * @returns {Promise<?>} - The body's result.
46
+ */
47
+ _runWithAfterAll(context: EvaluationContext, plan: import("../factory-runner.js").CompiledPlan, state: () => {
48
+ record: unknown;
49
+ transients: Record<string, unknown>;
50
+ strategy: string;
51
+ }, body: () => Promise<unknown>): Promise<unknown>;
52
+ /**
53
+ * Attaches an afterAll cleanup failure to the primary error without masking it.
54
+ * @param {?} primaryError - The original error that will propagate.
55
+ * @param {?} cleanupError - The afterAll cleanup failure.
56
+ * @returns {void}
57
+ */
58
+ _attachCleanupFailure(primaryError: unknown, cleanupError: unknown): void;
59
+ /**
60
+ * Constructs a record from evaluated public attributes, honouring a custom
61
+ * `initializeWith` constructor and never assigning constructor-consumed
62
+ * attributes twice.
63
+ * @param {import("../factory-runner.js").CompiledPlan} plan - Compiled plan.
64
+ * @param {Record<string, ?>} publicAttributes - Evaluated public attributes.
65
+ * @param {EvaluationContext} context - Evaluation context.
66
+ * @param {Record<string, ?>} transients - Evaluated transients.
67
+ * @returns {Promise<?>} - The constructed record.
68
+ */
69
+ _constructRecord(plan: import("../factory-runner.js").CompiledPlan, publicAttributes: Record<string, unknown>, context: EvaluationContext, transients: Record<string, unknown>): Promise<unknown>;
70
+ /**
71
+ * Constructs a record via a custom `initializeWith`, tracking which attributes
72
+ * the constructor consumed through its `get(name)` accessor and assigning only
73
+ * the remaining public attributes afterwards.
74
+ * @param {import("../factory-runner.js").CompiledPlan} plan - Compiled plan.
75
+ * @param {new (attributes?: Record<string, ?>) => import("../../../database/record/index.js").default} ModelClass - Validated declared model class.
76
+ * @param {Record<string, ?>} publicAttributes - Evaluated public attributes.
77
+ * @param {EvaluationContext} context - Evaluation context.
78
+ * @param {Record<string, ?>} transients - Evaluated transients.
79
+ * @returns {Promise<?>} - The constructed record.
80
+ */
81
+ _constructWithInitializer(plan: import("../factory-runner.js").CompiledPlan, ModelClass: new (attributes?: Record<string, unknown>) => import("../../../database/record/index.js").default, publicAttributes: Record<string, unknown>, context: EvaluationContext, transients: Record<string, unknown>): Promise<unknown>;
82
+ /**
83
+ * Wires evaluated associations onto a record through public relationship
84
+ * reflection and generated setters (never private caches or guessed keys).
85
+ * @param {?} record - The owning record.
86
+ * @param {Array<{name: string, record: ?}>} associations - Evaluated associations.
87
+ * @returns {void}
88
+ */
89
+ _assignAssociations(record: unknown, associations: Array<{
90
+ name: string;
91
+ record: unknown;
92
+ }>): void;
93
+ /**
94
+ * Normalizes a has-many association value into an array of records.
95
+ * @param {?} value - Association value (record, array, or null).
96
+ * @returns {Array<?>} - The normalized record array.
97
+ */
98
+ _toRecordArray(value: unknown): Array<unknown>;
99
+ }
100
+ import EvaluationContext from "../evaluation-context.js";
101
+ //# sourceMappingURL=base.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../../../src/testing/factory/strategies/base.js"],"names":[],"mappings":"AAOA;;;;;GAKG;AACH;IACE;;;;;;OAMG;IACH,sBALW,OAAO,wBAAwB,EAAE,OAAO,QACxC,OAAO,sBAAsB,EAAE,YAAY,gBAC3C,eAAe,GAAG,OAAO,GAAG,QAAQ,GAClC,iBAAiB,CAI7B;IAED;;;;;;OAMG;IACH,0BAJW,iBAAiB,cACjB,MAAM,CAAC,MAAM,EAAE,OAAC,CAAC,GACf,MAAM,CAAC,MAAM,EAAE,OAAC,CAAC,CAI7B;IAED;;;;;;;OAOG;IACH,uBANW,iBAAiB,QACjB,OAAO,sBAAsB,EAAE,YAAY,SAC3C,MAAM,SACN;QAAC,MAAM,EAAE,OAAC,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAC,CAAC,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAC,GAC1D,OAAO,CAAC,IAAI,CAAC,CAYzB;IAED;;;;;;;;;OASG;IACH,0BANW,iBAAiB,QACjB,OAAO,sBAAsB,EAAE,YAAY,SAC3C,MAAM;QAAC,MAAM,EAAE,OAAC,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAC,CAAC,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAC,QAClE,MAAM,OAAO,CAAC,OAAC,CAAC,GACd,OAAO,CAAC,OAAC,CAAC,CAoCtB;IAED;;;;;OAKG;IACH,oCAJW,OAAC,gBACD,OAAC,GACC,IAAI,CAOhB;IAED;;;;;;;;;OASG;IACH,uBANW,OAAO,sBAAsB,EAAE,YAAY,oBAC3C,MAAM,CAAC,MAAM,EAAE,OAAC,CAAC,WACjB,iBAAiB,cACjB,MAAM,CAAC,MAAM,EAAE,OAAC,CAAC,GACf,OAAO,CAAC,OAAC,CAAC,CAUtB;IAED;;;;;;;;;;OAUG;IACH,gCAPW,OAAO,sBAAsB,EAAE,YAAY,cAC3C,KAAK,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAC,CAAC,KAAK,OAAO,mCAAmC,EAAE,OAAO,oBAC3F,MAAM,CAAC,MAAM,EAAE,OAAC,CAAC,WACjB,iBAAiB,cACjB,MAAM,CAAC,MAAM,EAAE,OAAC,CAAC,GACf,OAAO,CAAC,OAAC,CAAC,CA6BtB;IAED;;;;;;OAMG;IACH,4BAJW,OAAC,gBACD,KAAK,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,OAAC,CAAA;KAAC,CAAC,GAC9B,IAAI,CAehB;IAED;;;;OAIG;IACH,sBAHW,OAAC,GACC,KAAK,CAAC,OAAC,CAAC,CAOpB;CACF;8BA3M6B,0BAA0B"}