@afora/core 0.0.2 → 0.0.4

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 (82) hide show
  1. package/README.md +220 -733
  2. package/dist/core/application/application.d.ts +9 -1
  3. package/dist/core/application/exceptions.d.ts +28 -0
  4. package/dist/core/application/registry.d.ts +33 -0
  5. package/dist/core/application/start.d.ts +75 -0
  6. package/dist/core/application/types/application.interface.d.ts +229 -7
  7. package/dist/core/blueprint/types/blueprint.interface.d.ts +66 -11
  8. package/dist/core/blueprint/types/slice.interface.d.ts +7 -2
  9. package/dist/core/command/command.d.ts +25 -0
  10. package/dist/core/command/exceptions.d.ts +33 -0
  11. package/dist/core/command/types/command.interface.d.ts +108 -0
  12. package/dist/core/entity/event.d.ts +12 -2
  13. package/dist/core/environment/environment.d.ts +4 -1
  14. package/dist/core/exception/exception.d.ts +4 -0
  15. package/dist/core/exception/exported.d.ts +4 -0
  16. package/dist/core/json.d.ts +10 -0
  17. package/dist/core/logger/exceptions.d.ts +4 -0
  18. package/dist/core/logger/logger.d.ts +106 -0
  19. package/dist/core/output/exceptions.d.ts +8 -0
  20. package/dist/core/output/openapi-sink.d.ts +83 -0
  21. package/dist/core/output/output.d.ts +19 -0
  22. package/dist/core/output/problem.d.ts +15 -0
  23. package/dist/core/output/select.d.ts +14 -0
  24. package/dist/core/output/stage.d.ts +24 -0
  25. package/dist/core/output/status.d.ts +17 -0
  26. package/dist/core/output/types/output.interface.d.ts +171 -0
  27. package/dist/core/property/abstract-property.d.ts +8 -7
  28. package/dist/core/property/define-property.d.ts +8 -7
  29. package/dist/core/property/property.d.ts +26 -15
  30. package/dist/core/property/types/abstract-property-constructor.type.d.ts +8 -7
  31. package/dist/core/property/types/define-property.interface.d.ts +5 -4
  32. package/dist/core/property/types/optional-property.type.d.ts +5 -5
  33. package/dist/core/property/types/property-collection.type.d.ts +2 -2
  34. package/dist/core/property/types/property-constructor.type.d.ts +5 -1
  35. package/dist/core/property/types/property-options.interface.d.ts +17 -8
  36. package/dist/core/property/types/property-type.interface.d.ts +7 -3
  37. package/dist/core/property/types/property.interface.d.ts +5 -4
  38. package/dist/core/record/abstract-record.d.ts +12 -4
  39. package/dist/core/record/types/plugin.interface.d.ts +13 -3
  40. package/dist/core/record/types/record.interface.d.ts +20 -8
  41. package/dist/core/repository/exceptions.d.ts +4 -0
  42. package/dist/core/repository/in-memory.d.ts +3 -0
  43. package/dist/core/repository/provider.d.ts +6 -0
  44. package/dist/core/repository/query.d.ts +9 -0
  45. package/dist/core/repository/references.d.ts +4 -2
  46. package/dist/core/repository/repository.d.ts +4 -2
  47. package/dist/core/repository/state.d.ts +4 -0
  48. package/dist/core/repository/types/query.interface.d.ts +67 -0
  49. package/dist/core/repository/types/repository.interface.d.ts +13 -13
  50. package/dist/core/schema/types/schema.interface.d.ts +11 -4
  51. package/dist/core/symbols/meta.d.ts +2 -0
  52. package/dist/core/use-case/exceptions.d.ts +10 -0
  53. package/dist/core/use-case/scope.d.ts +24 -0
  54. package/dist/core/use-case/steps/describe.d.ts +13 -0
  55. package/dist/core/use-case/steps/references.d.ts +27 -0
  56. package/dist/core/use-case/steps/run.d.ts +20 -0
  57. package/dist/core/use-case/steps/types/steps.interface.d.ts +153 -0
  58. package/dist/core/use-case/steps/validate.d.ts +17 -0
  59. package/dist/core/use-case/use-case.d.ts +79 -13
  60. package/dist/experimental.d.ts +6 -0
  61. package/dist/experimental.js +123 -0
  62. package/dist/index-ewm6r4nw.js +5335 -0
  63. package/dist/index-hn82hm31.js +1651 -0
  64. package/dist/index.d.ts +34 -12
  65. package/dist/index.js +343 -4142
  66. package/dist/std/blueprint-plugin.d.ts +10 -10
  67. package/dist/std/blueprint.d.ts +10 -10
  68. package/dist/std/entity.d.ts +2 -2
  69. package/dist/std/properties/contact.d.ts +4 -4
  70. package/dist/std/properties/enum.d.ts +1 -1
  71. package/dist/std/properties/headless.d.ts +1 -1
  72. package/dist/std/properties/identity.d.ts +2 -2
  73. package/dist/std/properties/password.d.ts +1 -1
  74. package/dist/std/properties/primitives.d.ts +5 -5
  75. package/dist/std/properties/time.d.ts +2 -2
  76. package/dist/std/record-plugins.d.ts +12 -12
  77. package/dist/std/record.d.ts +1 -1
  78. package/dist/std/stages.d.ts +2 -0
  79. package/dist/testing/index.d.ts +2 -0
  80. package/dist/testing/index.js +502 -0
  81. package/dist/testing/provider-contract.d.ts +22 -0
  82. package/package.json +28 -8
package/dist/index.js CHANGED
@@ -1,4145 +1,346 @@
1
- // src/core/property/is-property.ts
2
- function isProperty(value) {
3
- return typeof value === "function" && typeof value.type === "object";
4
- }
5
-
6
- // src/core/schema/schema.ts
7
- import Compile from "typebox/compile";
8
- var KEPT_KEYWORDS = new Set([
9
- "type",
10
- "required",
11
- "$ref",
12
- "$id",
13
- "$anchor",
14
- "$dynamicRef",
15
- "$dynamicAnchor"
16
- ]);
17
- var SCHEMA_KEYWORDS = new Set([
18
- "additionalProperties",
19
- "items",
20
- "additionalItems",
21
- "prefixItems",
22
- "anyOf",
23
- "oneOf",
24
- "allOf",
25
- "contains",
26
- "propertyNames"
27
- ]);
28
- var SCHEMA_MAP_KEYWORDS = new Set([
29
- "properties",
30
- "patternProperties",
31
- "dependentSchemas",
32
- "$defs",
33
- "definitions"
34
- ]);
35
- var JSON_TYPES = new Set([
36
- "null",
37
- "array",
38
- "string",
39
- "number",
40
- "boolean",
41
- "object"
42
- ]);
43
- function typeOfValue(value) {
44
- const type = value === null ? "null" : Array.isArray(value) ? "array" : typeof value;
45
- return JSON_TYPES.has(type) ? type : undefined;
46
- }
47
- function shapeOf(schema) {
48
- if (Array.isArray(schema))
49
- return schema.map(shapeOf);
50
- if (typeof schema !== "object" || schema === null)
51
- return schema;
52
- const shape = {};
53
- for (const [key, value] of Object.entries(schema)) {
54
- if (KEPT_KEYWORDS.has(key))
55
- shape[key] = value;
56
- else if (SCHEMA_KEYWORDS.has(key))
57
- shape[key] = shapeOf(value);
58
- else if (SCHEMA_MAP_KEYWORDS.has(key)) {
59
- shape[key] = Object.fromEntries(Object.entries(value).map(([name, item]) => [
60
- name,
61
- shapeOf(item)
62
- ]));
63
- }
64
- }
65
- if (!("type" in shape)) {
66
- const values = "const" in schema ? [schema.const] : schema.enum;
67
- if (Array.isArray(values)) {
68
- const types = values.map(typeOfValue);
69
- if (types.every((type) => type !== undefined)) {
70
- shape.type = [...new Set(types)];
71
- }
72
- }
73
- }
74
- return shape;
75
- }
76
- function describeError(error) {
77
- return `${error.instancePath || "/"}: ${error.message}`;
78
- }
79
-
80
- class AbstractSchema {
81
- _type;
82
- validator;
83
- shapeValidator;
84
- constructor(_type) {
85
- this._type = _type;
86
- }
87
- match(value) {
88
- return this.type.Check(value);
89
- }
90
- matchShape(value) {
91
- this.shapeValidator ??= Compile(shapeOf(this._type));
92
- return this.shapeValidator.Check(value);
93
- }
94
- errors(value) {
95
- return this.type.Errors(value).map(describeError);
96
- }
97
- toString() {
98
- return JSON.stringify(this._type);
99
- }
100
- get type() {
101
- this.validator ??= Compile(this._type);
102
- return this.validator;
103
- }
104
- }
105
- function schemaOf(name, schema) {
106
-
107
- class Schema extends AbstractSchema {
108
- constructor(type = schema) {
109
- super(type);
110
- }
111
- static fromString(value) {
112
- return new Schema(JSON.parse(value));
113
- }
114
- }
115
- Object.defineProperty(Schema, "name", { value: name });
116
- Object.defineProperty(Schema, Symbol.for("nodejs.util.inspect.custom"), {
117
- value: () => `@afora::schema:${name}`
118
- });
119
- return Schema;
120
- }
121
-
122
- // src/core/symbols/demo.ts
123
- var Demo = Symbol("demo");
124
-
125
- // src/core/property/lineage.ts
126
- var lineages = new WeakMap;
127
- function recordPropertyLineage(Property, lineage) {
128
- if (!lineages.has(Property))
129
- lineages.set(Property, lineage);
130
- }
131
- function propertyLineageOf(Property) {
132
- return typeof Property === "function" ? lineages.get(Property) : undefined;
133
- }
134
-
135
- // src/core/property/refine.ts
136
- var METADATA_KEYS = [
137
- "title",
138
- "description",
139
- "examples",
140
- "deprecated",
141
- "readOnly",
142
- "writeOnly"
143
- ];
144
- var LOWER_BOUNDS = {
145
- min: ["minimum", "minLength"],
146
- exclusiveMin: ["exclusiveMinimum"]
147
- };
148
- var UPPER_BOUNDS = {
149
- max: ["maximum", "maxLength"],
150
- exclusiveMax: ["exclusiveMaximum"]
151
- };
152
- function derivePropertyOf(Property, type) {
153
- const Base = Property;
154
-
155
- class Derived extends Base {
156
- static type = type;
157
- createDefinition() {
158
- const definition = super.createDefinition();
159
- Object.defineProperty(definition, "type", {
160
- value: type,
161
- configurable: true
162
- });
163
- return definition;
164
- }
165
- }
166
- Object.defineProperty(Derived, "name", { value: Property.name });
167
- return Derived;
168
- }
169
- function copyOf(schema) {
170
- return Object.defineProperties({}, Object.getOwnPropertyDescriptors(schema));
171
- }
172
- function addAllOf(schema, constraint) {
173
- schema.allOf = [...schema.allOf ?? [], constraint];
174
- }
175
- function refinedSchemaOf(base, options) {
176
- const schema = copyOf(base);
177
- const keyword = (keys) => keys.length === 1 || schema.type !== "string" ? keys[0] : keys[1];
178
- for (const key of METADATA_KEYS) {
179
- if (options[key] !== undefined)
180
- schema[key] = options[key];
181
- }
182
- for (const [option, keys] of Object.entries(LOWER_BOUNDS)) {
183
- const value = options[option];
184
- if (value === undefined)
185
- continue;
186
- const name = keyword(keys);
187
- const current = schema[name];
188
- schema[name] = current === undefined ? value : Math.max(current, value);
189
- }
190
- for (const [option, keys] of Object.entries(UPPER_BOUNDS)) {
191
- const value = options[option];
192
- if (value === undefined)
193
- continue;
194
- const name = keyword(keys);
195
- const current = schema[name];
196
- schema[name] = current === undefined ? value : Math.min(current, value);
197
- }
198
- if (options.multipleOf !== undefined) {
199
- if (schema.multipleOf === undefined)
200
- schema.multipleOf = options.multipleOf;
201
- else
202
- addAllOf(schema, { multipleOf: options.multipleOf });
203
- }
204
- if (options.pattern !== undefined) {
205
- const pattern = options.pattern instanceof RegExp ? options.pattern.source : options.pattern;
206
- if (schema.pattern === undefined)
207
- schema.pattern = pattern;
208
- else
209
- addAllOf(schema, { pattern });
210
- }
211
- return schema;
212
- }
213
- function refinePropertyOf(Property, options) {
214
- const base = Property.type;
215
- const settings = options;
216
- const schema = refinedSchemaOf(base.schema.type.Type(), settings);
217
- const SchemaConstructor = schemaOf(base.name, schema);
218
- const examples = settings.examples;
219
- const type = {
220
- ...base,
221
- [Demo]: settings.default ?? examples?.[0] ?? base[Demo],
222
- schema: new SchemaConstructor
223
- };
224
- const Refined = derivePropertyOf(Property, type);
225
- recordPropertyLineage(Refined, {
226
- kind: "refined",
227
- base: Property,
228
- options: Object.freeze({ ...settings })
229
- });
230
- return Refined;
231
- }
232
-
233
- // src/core/blueprint/callable.ts
234
- var targets = new WeakMap;
235
- function callableOf(Property) {
236
- const callable = new Proxy(Property, {
237
- apply: (target, _this, [options]) => refinePropertyOf(target, options ?? {})
238
- });
239
- targets.set(callable, Property);
240
- return callable;
241
- }
242
- function fieldOf(field) {
243
- return (isProperty(field) ? targets.get(field) : undefined) ?? field;
244
- }
245
-
246
- // src/core/symbols/kind.ts
247
- var Kind = Symbol("kind");
248
-
249
- // src/core/blueprint/is-blueprint.ts
250
- function isBlueprint(value) {
251
- return typeof value === "object" && value !== null && value[Kind] === "blueprint";
252
- }
253
-
254
- // src/core/blueprint/record-field.ts
255
- function isRecordClass(value) {
256
- return typeof value === "function" && value[Kind] === "record";
257
- }
258
- function isOptionalRecord(value) {
259
- return typeof value === "object" && value !== null && value[Kind] === "record";
260
- }
261
- function recordFieldOf(field) {
262
- if (isRecordClass(field))
263
- return { record: field, optional: false };
264
- if (isOptionalRecord(field))
265
- return field;
266
- return;
267
- }
268
-
269
- // src/core/parse/issue.ts
270
- function withLazyCause(issue, build) {
271
- let cause;
272
- return Object.defineProperty(issue, "cause", {
273
- get: () => {
274
- cause ??= build();
275
- return cause;
276
- },
277
- enumerable: false,
278
- configurable: true
279
- });
280
- }
281
- function movedIssue(issue, path) {
282
- const moved = { ...issue, path };
283
- const cause = Object.getOwnPropertyDescriptor(issue, "cause");
284
- if (cause && !cause.enumerable)
285
- Object.defineProperty(moved, "cause", cause);
286
- return moved;
287
- }
288
-
289
- // src/core/parse/parse.ts
290
- var NO_KEY = Symbol("no key");
291
- function pathAt(parent, key) {
292
- return key === NO_KEY ? parent : [...parent, key];
293
- }
294
- function rejection(code, message, path, source) {
295
- return { issues: [{ code, message, path, source }] };
296
- }
297
- function underPath(result, path) {
298
- if (!result.issues)
299
- return result;
300
- return {
301
- issues: result.issues.map((issue) => movedIssue(issue, [...path, ...issue.path]))
302
- };
303
- }
304
- function ownIssuesUnderPath(result, path) {
305
- if (!result.issues)
306
- return result;
307
- if (result.issues.some((issue) => Object.isFrozen(issue))) {
308
- return underPath(result, path);
309
- }
310
- for (const issue of result.issues) {
311
- issue.path = [...path, ...issue.path];
312
- }
313
- return result;
314
- }
315
- var entriesOf = new WeakMap;
316
- function fieldsOf(properties) {
317
- let entries = entriesOf.get(properties);
318
- if (!entries) {
319
- entries = Object.entries(properties);
320
- entriesOf.set(properties, entries);
321
- }
322
- return entries;
323
- }
324
- function isPlainObject(value) {
325
- if (typeof value !== "object" || value === null)
326
- return false;
327
- const prototype = Object.getPrototypeOf(value);
328
- return prototype === Object.prototype || prototype === null;
329
- }
330
- function parseCollection(properties, value, path, source) {
331
- return collectionAt(properties, value, path, NO_KEY, source);
332
- }
333
- function collectionAt(properties, value, parent, key, source) {
334
- if (typeof value !== "object" || value === null || Array.isArray(value)) {
335
- return rejection("invalid_type", "must be an object", pathAt(parent, key), source);
336
- }
337
- let issues;
338
- const path = pathAt(parent, key);
339
- for (const name of Object.keys(value)) {
340
- if (Object.hasOwn(properties, name))
341
- continue;
342
- issues ??= [];
343
- issues.push({
344
- code: "undeclared_key",
345
- message: "is not declared",
346
- path: [...path, name],
347
- source
348
- });
349
- }
350
- const handled = {};
351
- for (const [name, field] of fieldsOf(properties)) {
352
- const result = fieldAt(field, value[name], path, name, source);
353
- if (result.issues) {
354
- issues ??= [];
355
- issues.push(...result.issues);
356
- } else if (result.value !== undefined)
357
- handled[name] = result.value;
358
- }
359
- return issues ? { issues } : { value: Object.freeze(handled) };
360
- }
361
- function parseField(field, value, path, source) {
362
- return fieldAt(field, value, path, NO_KEY, source);
363
- }
364
- function fieldAt(field, value, parent, key, source) {
365
- const required = () => rejection("required", "is required", pathAt(parent, key), source);
366
- if (isBlueprintList(field)) {
367
- if (value === undefined)
368
- return field.optional ? { value } : required();
369
- if (!Array.isArray(value)) {
370
- return rejection("invalid_type", "must be an array", pathAt(parent, key), source);
371
- }
372
- const { minItems, maxItems } = field;
373
- const path = pathAt(parent, key);
374
- let issues;
375
- if (minItems !== undefined && value.length < minItems) {
376
- issues ??= [];
377
- issues.push({
378
- code: "too_few_items",
379
- message: `must have at least ${minItems} items`,
380
- path,
381
- source
382
- });
383
- }
384
- if (maxItems !== undefined && value.length > maxItems) {
385
- issues ??= [];
386
- issues.push({
387
- code: "too_many_items",
388
- message: `must have at most ${maxItems} items`,
389
- path,
390
- source
391
- });
392
- }
393
- const items = [];
394
- for (const [index, item] of value.entries()) {
395
- const result = fieldAt(field.item, item, path, index, source);
396
- if (result.issues) {
397
- issues ??= [];
398
- issues.push(...result.issues);
399
- } else
400
- items.push(result.value);
401
- }
402
- return issues ? { issues } : { value: Object.freeze(items) };
403
- }
404
- if (isBlueprint(field)) {
405
- if (value === undefined)
406
- return field.optional ? { value } : required();
407
- return collectionAt(field.properties, value, parent, key, source);
408
- }
409
- const record = recordFieldOf(field);
410
- if (record) {
411
- if (value === undefined)
412
- return record.optional ? { value } : required();
413
- if (value instanceof record.record)
414
- return { value };
415
- if (!isPlainObject(value)) {
416
- return rejection("not_record", `must be an instance of record "${record.record.name}"`, pathAt(parent, key), source);
417
- }
418
- const result = record.record.safeParse(value);
419
- return result.issues ? underPath(result, pathAt(parent, key)) : result;
420
- }
421
- if (isProperty(field)) {
422
- const result = field.safeParse(value);
423
- return result.issues ? ownIssuesUnderPath(result, pathAt(parent, key)) : result;
424
- }
425
- return rejection("undeclared_key", "is not declared", pathAt(parent, key), source);
426
- }
427
-
428
- // src/core/standard/standard-schema.ts
429
- var STANDARD_VENDOR = "afora";
430
-
431
- // src/core/standard/standard.ts
432
- function standardOf(parse) {
433
- return Object.freeze({
434
- version: 1,
435
- vendor: STANDARD_VENDOR,
436
- validate: (value) => parse(value)
437
- });
438
- }
439
- function withStandard(target, parse) {
440
- return Object.defineProperty(target, "~standard", {
441
- value: standardOf(parse),
442
- enumerable: false
443
- });
444
- }
445
- var cache = new WeakMap;
446
- function standardOfClass(Class) {
447
- let standard = cache.get(Class);
448
- if (!standard) {
449
- standard = standardOf((value) => Class.safeParse(value));
450
- cache.set(Class, standard);
451
- }
452
- return standard;
453
- }
454
-
455
- // src/core/blueprint/list.ts
456
- function listOf(item, { minItems, maxItems } = {}) {
457
- return standardListOf({
458
- [Kind]: "list",
459
- item: fieldOf(item),
460
- optional: false,
461
- minItems,
462
- maxItems
463
- });
464
- }
465
- function standardListOf(list) {
466
- return Object.freeze(withStandard(list, (value) => parseField(list, value, [], "list")));
467
- }
468
- function isBlueprintList(value) {
469
- return typeof value === "object" && value !== null && value[Kind] === "list";
470
- }
471
-
472
- // src/core/exception/enums/exception-layers.ts
473
- var ExceptionLayers;
474
- ((ExceptionLayers) => {
475
- ExceptionLayers["Schema"] = "schema";
476
- ExceptionLayers["Property"] = "property";
477
- ExceptionLayers["Blueprint"] = "blueprint";
478
- ExceptionLayers["Record"] = "record";
479
- ExceptionLayers["Entity"] = "entity";
480
- ExceptionLayers["UseCase"] = "use-case";
481
- ExceptionLayers["Repository"] = "repository";
482
- ExceptionLayers["Environment"] = "environment";
483
- ExceptionLayers["Event"] = "event";
484
- ExceptionLayers["Command"] = "command";
485
- ExceptionLayers["Application"] = "application";
486
- ExceptionLayers["Output"] = "output";
487
- })(ExceptionLayers ||= {});
488
-
489
- // src/core/exception/exception.ts
490
- var UNEXPECTED_ERROR = "UnexpectedError";
491
-
492
- class Exception extends Error {
493
- name;
494
- layer;
495
- source;
496
- details;
497
- cause;
498
- constructor({
499
- layer,
500
- name,
501
- source,
502
- message,
503
- details,
504
- cause
505
- }) {
506
- super(message, cause === undefined ? undefined : { cause });
507
- this.name = name;
508
- this.layer = layer;
509
- this.source = source;
510
- this.details = details;
511
- this.cause = cause;
512
- }
513
- static from(error, scope) {
514
- if (error instanceof Exception)
515
- return error;
516
- return new Exception({
517
- ...scope,
518
- name: UNEXPECTED_ERROR,
519
- message: error instanceof Error ? error.message : String(error),
520
- cause: error
521
- });
522
- }
523
- get frame() {
524
- const { layer, name, source, message, details } = this;
525
- return { layer, name, source, message, details };
526
- }
527
- get trace() {
528
- return this.chain().map((exception) => exception.frame).reverse();
529
- }
530
- get origin() {
531
- return this.chain().at(-1);
532
- }
533
- find(target) {
534
- return this.chain().find((exception) => typeof target === "string" ? exception.name === target : exception instanceof target);
535
- }
536
- is(target) {
537
- return this.find(target) !== undefined;
538
- }
539
- passedThrough(layer) {
540
- return this.chain().some((exception) => exception.layer === layer);
541
- }
542
- propagate({
543
- layer,
544
- source,
545
- name = this.name,
546
- message = this.message,
547
- details
548
- }) {
549
- return new Exception({
550
- layer,
551
- source,
552
- name,
553
- message,
554
- details,
555
- cause: this
556
- });
557
- }
558
- toJSON() {
559
- return { ...this.frame, trace: this.trace };
560
- }
561
- toString() {
562
- return this.chain().map((exception, index) => `${index === 0 ? "" : " <- "}${exception.name} [${exception.layer} @ ${exception.source}]: ${exception.message}`).join(`
563
- `);
564
- }
565
- chain() {
566
- const chain = [];
567
- for (let current = this;current instanceof Exception; current = current.cause) {
568
- chain.push(current);
569
- }
570
- return chain;
571
- }
572
- }
573
- function exceptionOf({
574
- layer,
575
- name,
576
- message
577
- }) {
578
-
579
- class DeclaredException extends Exception {
580
- static layer = layer;
581
- constructor({
582
- source,
583
- details,
584
- cause,
585
- message: custom
586
- }) {
587
- super({
588
- layer,
589
- name,
590
- source,
591
- details,
592
- cause,
593
- message: custom ?? (typeof message === "function" ? message(details, source) : message)
594
- });
595
- }
596
- }
597
- Object.defineProperty(DeclaredException, "name", { value: name });
598
- return DeclaredException;
599
- }
600
-
601
- // src/core/record/exceptions.ts
602
- var InvalidRecordValue = exceptionOf({
603
- layer: "record" /* Record */,
604
- name: "InvalidRecordValue",
605
- message: ({
606
- key,
607
- errors
608
- }, source) => `Invalid value for ${key ? `"${key}" of ` : ""}record "${source}": ${errors.join("; ")}`
609
- });
610
- var UndeclaredRecordProperty = exceptionOf({
611
- layer: "record" /* Record */,
612
- name: "UndeclaredRecordProperty",
613
- message: ({ key }, source) => `Property "${key}" is not declared in record "${source}".`
614
- });
615
- var ReservedRecordKey = exceptionOf({
616
- layer: "record" /* Record */,
617
- name: "ReservedRecordKey",
618
- message: ({ key }, source) => `"${key}" is a member of record "${source}" and cannot be a key of its blueprint.`
619
- });
620
- var InvalidRecordPlugin = exceptionOf({
621
- layer: "record" /* Record */,
622
- name: "InvalidRecordPlugin",
623
- message: ({ reason }, source) => `Invalid record plugin "${source}": ${reason}.`
624
- });
625
- var RecordPluginConflict = exceptionOf({
626
- layer: "record" /* Record */,
627
- name: "RecordPluginConflict",
628
- message: ({
629
- plugin,
630
- key,
631
- owner
632
- }, source) => `Plugin "${plugin}" of record "${source}" adds "${key}", which ${owner} already has.`
633
- });
634
- var UnknownRecordPlugin = exceptionOf({
635
- layer: "record" /* Record */,
636
- name: "UnknownRecordPlugin",
637
- message: ({ name }) => `No record plugin named "${name}" in the catalog.`
638
- });
639
- var IncompatibleRecordPlugin = exceptionOf({
640
- layer: "record" /* Record */,
641
- name: "IncompatibleRecordPlugin",
642
- message: ({ reason }, source) => `Record plugin "${source}" does not satisfy the reference: ${reason}.`
643
- });
644
-
645
- // src/core/record/marks.ts
646
- function isMarked(field, mark, { lists = false } = {}) {
647
- if (lists && isBlueprintList(field))
648
- return isMarked(field.item, mark, { lists });
649
- return isProperty(field) && field.type[mark] === true;
650
- }
651
-
652
- // src/core/record/mask.ts
653
- var MASK = "********";
654
- function maskAll(value) {
655
- if (value === undefined || value === null)
656
- return value;
657
- if (Array.isArray(value))
658
- return Object.freeze(value.map(maskAll));
659
- if (typeof value === "object" && isRecordClass(value.constructor)) {
660
- return maskAll(value.toJSON());
661
- }
662
- if (typeof value === "object") {
663
- return Object.freeze(Object.fromEntries(Object.entries(value).map(([key, item]) => [key, maskAll(item)])));
664
- }
665
- return MASK;
666
- }
667
- function maskField(field, value, sensitive) {
668
- if (value === undefined)
669
- return value;
670
- if (recordFieldOf(field)) {
671
- const json = value.toJSON();
672
- return sensitive ? maskAll(json) : json;
673
- }
674
- if (sensitive || isMarked(field, "sensitive"))
675
- return maskAll(value);
676
- if (isBlueprintList(field) && Array.isArray(value)) {
677
- return Object.freeze(value.map((item) => maskField(field.item, item, false)));
678
- }
679
- if (isBlueprint(field) && typeof value === "object" && value !== null) {
680
- return maskCollection(field.properties, value);
681
- }
682
- return value;
683
- }
684
- function maskCollection(properties, value, sensitive = []) {
685
- return Object.freeze(Object.fromEntries(Object.entries(value).map(([key, item]) => [
686
- key,
687
- maskField(properties[key], item, sensitive.includes(key))
688
- ])));
689
- }
690
-
691
- // src/core/record/abstract-record.ts
692
- var values = new WeakMap;
693
- var RESERVED_RECORD_KEYS = Object.freeze([
694
- "blueprint",
695
- "options",
696
- "onSet",
697
- "onSetAll",
698
- "set",
699
- "toJSON",
700
- ...Object.getOwnPropertyNames(Object.prototype)
701
- ]);
702
- function exposeRecordKeys(prototype, keys) {
703
- for (const key of keys) {
704
- Object.defineProperty(prototype, key, {
705
- get() {
706
- return values.get(this)?.[key];
707
- },
708
- enumerable: true,
709
- configurable: true
710
- });
711
- }
712
- }
713
- var checked = new WeakSet;
714
- function checkMembers(record, keys) {
715
- const Class = record.constructor;
716
- if (checked.has(Class))
717
- return;
718
- for (let prototype = Object.getPrototypeOf(record);prototype !== null && !Object.hasOwn(prototype.constructor, "blueprint"); prototype = Object.getPrototypeOf(prototype)) {
719
- const key = Object.getOwnPropertyNames(prototype).find((name) => keys.includes(name));
720
- if (key !== undefined) {
721
- throw new ReservedRecordKey({ source: Class.name, details: { key } });
722
- }
723
- }
724
- checked.add(Class);
725
- }
726
- function withIssues(details, issues) {
727
- return Object.defineProperty(details, "issues", {
728
- value: Object.freeze([...issues]),
729
- enumerable: false
730
- });
731
- }
732
- function exceptionOfIssues(issues, source) {
733
- const [first] = issues;
734
- const key = first.path.join(".");
735
- if (first.cause) {
736
- return first.cause.propagate({
737
- layer: "record" /* Record */,
738
- source,
739
- details: withIssues({ key }, issues)
740
- });
741
- }
742
- if (first.code === "undeclared_key") {
743
- return new UndeclaredRecordProperty({
744
- source,
745
- details: withIssues({ key }, issues)
746
- });
747
- }
748
- return new InvalidRecordValue({
749
- source,
750
- details: withIssues({ key, errors: [first.message] }, issues)
751
- });
752
- }
753
- function issuesOfError(error, source) {
754
- const issues = error?.details?.issues;
755
- if (error instanceof Exception && issues)
756
- return issues;
757
- const cause = Exception.from(error, {
758
- layer: "record" /* Record */,
759
- source
760
- });
761
- return [
762
- {
763
- code: "invalid_value",
764
- message: cause.message,
765
- path: [],
766
- source,
767
- cause
768
- }
769
- ];
770
- }
771
- function parseRecord(Class, value) {
772
- if (value instanceof Class)
773
- return { value };
774
- try {
775
- return { value: new Class(value) };
776
- } catch (error) {
777
- return { issues: issuesOfError(error, Class.name) };
778
- }
779
- }
780
- function recordValue(record) {
781
- return values.get(record);
782
- }
783
- function recordDataOf(record, options) {
784
- const { properties } = record.blueprint;
785
- return dataOfCollection(properties, values.get(record), options);
786
- }
787
- function dataOfCollection(properties, value, options) {
788
- return Object.freeze(Object.fromEntries(Object.entries(value).map(([key, item]) => [
789
- key,
790
- recordFieldDataOf(properties[key], item, options)
791
- ])));
792
- }
793
- function recordFieldDataOf(field, value, options) {
794
- if (value === undefined || value === null)
795
- return value;
796
- if (value instanceof AbstractRecord) {
797
- return options?.reference?.(value) ?? recordDataOf(value, options);
798
- }
799
- if (isBlueprintList(field) && Array.isArray(value)) {
800
- return Object.freeze(value.map((item) => recordFieldDataOf(field.item, item, options)));
801
- }
802
- if (isBlueprint(field) && typeof value === "object") {
803
- return dataOfCollection(field.properties, value, options);
804
- }
805
- return value;
806
- }
807
- function storeRecordValue(record, key, value) {
808
- const source = record.constructor.name;
809
- const { properties } = record.blueprint;
810
- if (!Object.hasOwn(properties, key)) {
811
- throw exceptionOfIssues([
812
- {
813
- code: "undeclared_key",
814
- message: "is not declared",
815
- path: [key],
816
- source
817
- }
818
- ], source);
819
- }
820
- const current = values.get(record);
821
- const previous = current[key];
822
- const result = parseField(properties[key], value, [key], source);
823
- if (result.issues)
824
- throw exceptionOfIssues(result.issues, source);
825
- const next = result.value;
826
- const { [key]: _, ...rest } = current;
827
- values.set(record, Object.freeze(next === undefined ? rest : { ...rest, [key]: next }));
828
- return { next, previous };
829
- }
830
- var RecordPluginHooks = Symbol("recordPluginHooks");
831
- function runRecordEffects(record, key, next, previous) {
832
- const pluginHooks = record.constructor[RecordPluginHooks];
833
- if (pluginHooks !== undefined && pluginHooks.length > 0) {
834
- const name = String(key);
835
- for (const hook of pluginHooks) {
836
- if (!hook.keys.includes(name))
837
- continue;
838
- hook.onSetAll?.call(record, { key, value: next, previous });
839
- hook.onSet?.call(record)[name]?.call(record, next, previous);
840
- }
841
- }
842
- const hooks = record;
843
- hooks.onSetAll({ key, value: next, previous });
844
- hooks.onSet()[key]?.(next, previous);
845
- return record;
846
- }
847
-
848
- class AbstractRecord {
849
- blueprint;
850
- options;
851
- constructor(value) {
852
- ({ blueprint: this.blueprint, options: this.options } = this.constructor);
853
- checkMembers(this, Object.keys(this.blueprint.properties));
854
- const source = this.constructor.name;
855
- const result = parseCollection(this.blueprint.properties, value, [], source);
856
- if (result.issues)
857
- throw exceptionOfIssues(result.issues, source);
858
- values.set(this, result.value);
859
- }
860
- static safeParse(value) {
861
- return parseRecord(this, value);
862
- }
863
- static get "~standard"() {
864
- return standardOfClass(this);
865
- }
866
- toJSON() {
867
- return maskCollection(this.blueprint.properties, recordValue(this), this.options.sensitive);
868
- }
869
- set(key, value) {
870
- const { next, previous } = storeRecordValue(this, String(key), value);
871
- return runRecordEffects(this, key, next, previous);
872
- }
873
- onSetAll(_change) {}
874
- onSet() {
875
- return {};
876
- }
877
- }
878
-
879
- // src/core/record/plugin.ts
880
- var RecordPlugins = Symbol("recordPlugins");
881
- var IdentifiedRecord = Symbol("identifiedRecord");
882
- var SEMVER = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;
883
- function isVersion(version) {
884
- return typeof version === "string" && SEMVER.test(version);
885
- }
886
- function versionParts(version) {
887
- const [, major, minor, patch] = SEMVER.exec(version);
888
- return [Number(major), Number(minor), Number(patch)];
889
- }
890
- var HOOKS = ["onSet", "onSetAll"];
891
- var internals = new WeakMap;
892
- function pluginsOf(value) {
893
- const Class = typeof value === "function" ? value : typeof value === "object" && value !== null ? value.constructor : undefined;
894
- return Class?.[RecordPlugins] ?? [];
895
- }
896
- function isRecordPlugin(value) {
897
- return typeof value === "object" && value !== null && value[Kind] === "record-plugin";
898
- }
899
- function hasPlugin(value, plugin) {
900
- const plugins = pluginsOf(value);
901
- if (typeof plugin === "string") {
902
- return plugins.some((applied) => applied.name === plugin);
903
- }
904
- if (plugins.includes(plugin))
905
- return true;
906
- return typeof value === "function" ? value === plugin.record || value.prototype instanceof plugin.record : value instanceof plugin.record;
907
- }
908
- function membersOf(Record, name) {
909
- const descriptors = {};
910
- const hooks = {};
911
- for (let prototype = Record.prototype;prototype !== null && !Object.hasOwn(prototype.constructor, "blueprint"); prototype = Object.getPrototypeOf(prototype)) {
912
- for (const member of Object.getOwnPropertyNames(prototype)) {
913
- if (member === "constructor")
914
- continue;
915
- const descriptor = Object.getOwnPropertyDescriptor(prototype, member);
916
- if (HOOKS.includes(member)) {
917
- hooks[member] ??= descriptor.value;
918
- continue;
919
- }
920
- if (RESERVED_RECORD_KEYS.includes(member)) {
921
- throw new InvalidRecordPlugin({
922
- source: name,
923
- details: {
924
- reason: `"${member}" is a member of every record and cannot be replaced`
925
- }
926
- });
927
- }
928
- descriptors[member] ??= descriptor;
929
- }
930
- }
931
- return { descriptors: Object.freeze(descriptors), hooks };
932
- }
933
- function recordPluginOf(name, Record, { version = "1.0.0", description } = {}) {
934
- if (typeof name !== "string" || name.length === 0) {
935
- throw new InvalidRecordPlugin({
936
- source: String(name),
937
- details: { reason: "its name must be a non-empty string" }
938
- });
939
- }
940
- if (!isRecordClass(Record)) {
941
- throw new InvalidRecordPlugin({
942
- source: name,
943
- details: { reason: "it must be made from a class of `recordOf`" }
944
- });
945
- }
946
- if (Record[IdentifiedRecord]) {
947
- throw new InvalidRecordPlugin({
948
- source: name,
949
- details: {
950
- reason: "it must be made from a record, not an entity: plugins have no identity"
951
- }
952
- });
953
- }
954
- if (!isVersion(version)) {
955
- throw new InvalidRecordPlugin({
956
- source: name,
957
- details: { reason: `"${version}" is not a semantic version` }
958
- });
959
- }
960
- const requires = pluginsOf(Record);
961
- const inherited = new Set(requires.flatMap((required) => required.keys));
962
- const declaration = Record;
963
- const keys = Object.freeze(Object.keys(declaration.blueprint.properties).filter((key) => !inherited.has(key)));
964
- const own = membersOf(Record, name);
965
- const plugin = Object.freeze({
966
- [Kind]: "record-plugin",
967
- name,
968
- version,
969
- ...description === undefined ? {} : { description },
970
- record: Record,
971
- keys,
972
- members: Object.freeze(Object.keys(own.descriptors)),
973
- options: declaration.options,
974
- requires,
975
- is: (value) => hasPlugin(value, plugin),
976
- toJSON: () => descriptorOf(plugin)
977
- });
978
- internals.set(plugin, own);
979
- return plugin;
980
- }
981
- function descriptorOf(plugin) {
982
- return Object.freeze({
983
- kind: "record-plugin",
984
- name: plugin.name,
985
- version: plugin.version,
986
- ...plugin.description === undefined ? {} : { description: plugin.description },
987
- keys: plugin.keys,
988
- sensitive: plugin.options.sensitive,
989
- unique: plugin.options.unique,
990
- change: plugin.options.change,
991
- members: plugin.members,
992
- requires: Object.freeze(plugin.requires.map(({ name, version }) => Object.freeze({ name, version })))
993
- });
994
- }
995
- function applyPlugins(blueprint, plugins, name, reserved) {
996
- const flat = [];
997
- for (const plugin of plugins) {
998
- if (!isRecordPlugin(plugin)) {
999
- throw new InvalidRecordPlugin({
1000
- source: name,
1001
- details: {
1002
- reason: "`options.plugins` takes plugins made by `recordPluginOf`"
1003
- }
1004
- });
1005
- }
1006
- for (const applied of [...plugin.requires, plugin]) {
1007
- if (flat.includes(applied))
1008
- continue;
1009
- if (flat.some((other) => other.name === applied.name)) {
1010
- throw new RecordPluginConflict({
1011
- source: name,
1012
- details: {
1013
- plugin: applied.name,
1014
- key: applied.name,
1015
- owner: "another plugin"
1016
- }
1017
- });
1018
- }
1019
- flat.push(applied);
1020
- }
1021
- }
1022
- const owners = new Map(Object.keys(blueprint.properties).map((key) => [key, `record "${name}"`]));
1023
- for (const member of reserved)
1024
- owners.set(member, `record "${name}"`);
1025
- const claim = (plugin, key) => {
1026
- const owner = owners.get(key);
1027
- if (owner !== undefined) {
1028
- throw new RecordPluginConflict({
1029
- source: name,
1030
- details: { plugin: plugin.name, key, owner }
1031
- });
1032
- }
1033
- owners.set(key, `plugin "${plugin.name}"`);
1034
- };
1035
- const descriptors = {};
1036
- const hooks = [];
1037
- for (const plugin of flat) {
1038
- for (const key of plugin.keys)
1039
- claim(plugin, key);
1040
- const own = internals.get(plugin);
1041
- for (const member of plugin.members) {
1042
- claim(plugin, member);
1043
- descriptors[member] = own.descriptors[member];
1044
- }
1045
- if (own.hooks.onSet || own.hooks.onSetAll) {
1046
- hooks.push(Object.freeze({
1047
- plugin,
1048
- keys: Object.freeze(Object.keys(plugin.record.blueprint.properties)),
1049
- ...own.hooks
1050
- }));
1051
- }
1052
- }
1053
- return {
1054
- blueprint: flat.length === 0 ? blueprint : blueprint.join(...flat.map((plugin) => plugin.record.blueprint)),
1055
- plugins: Object.freeze(flat),
1056
- sensitive: flat.flatMap((plugin) => plugin.options.sensitive),
1057
- unique: flat.flatMap((plugin) => plugin.options.unique),
1058
- change: flat.flatMap((plugin) => plugin.options.change),
1059
- descriptors,
1060
- hooks: Object.freeze(hooks)
1061
- };
1062
- }
1063
-
1064
- // src/core/record/record.ts
1065
- function recordBuilderOf(...catalogs) {
1066
- const context = pluginContextOf(catalogs);
1067
- return (blueprint, options = {}) => declareRecord(AbstractRecord, blueprint, options, "record", [], context);
1068
- }
1069
- function pluginContextOf(catalogs) {
1070
- return Object.freeze(Object.assign({}, ...catalogs.map((catalog) => catalog.plugins)));
1071
- }
1072
- var recordOf = recordBuilderOf();
1073
- function declareRecord(Base, declared, { plugins = [], ...declaredOptions }, name, reserved = [], context = {}) {
1074
- const applied = applyPlugins(declared, typeof plugins === "function" ? plugins(context) : plugins, name, reserved);
1075
- const blueprint = applied.blueprint;
1076
- const sensitive = [
1077
- ...declaredOptions.sensitive ?? [],
1078
- ...applied.sensitive
1079
- ];
1080
- const unique = [...declaredOptions.unique ?? [], ...applied.unique];
1081
- const declaredChange = declaredOptions.change ?? [];
1082
- const keys = Object.keys(blueprint.properties);
1083
- const change = keys.filter((key) => declaredChange.includes(key) || applied.change.includes(key));
1084
- for (const key of [...sensitive, ...unique, ...declaredChange]) {
1085
- if (!keys.includes(key)) {
1086
- throw new UndeclaredRecordProperty({
1087
- source: name,
1088
- details: { key }
1089
- });
1090
- }
1091
- }
1092
- const methods = change.length > 0 ? [CHANGE_MEMBER] : [];
1093
- for (const member of Object.keys(applied.descriptors)) {
1094
- if (methods.includes(member)) {
1095
- const plugin = applied.plugins.find((plugin) => plugin.members.includes(member));
1096
- throw new RecordPluginConflict({
1097
- source: name,
1098
- details: {
1099
- plugin: plugin.name,
1100
- key: member,
1101
- owner: `record "${name}" (the \`change\` namespace)`
1102
- }
1103
- });
1104
- }
1105
- }
1106
- for (const key of keys) {
1107
- if (RESERVED_RECORD_KEYS.includes(key) || reserved.includes(key) || methods.includes(key)) {
1108
- throw new ReservedRecordKey({ source: name, details: { key } });
1109
- }
1110
- }
1111
- const options = Object.freeze({
1112
- sensitive: Object.freeze(keys.filter((key) => sensitive.includes(key) || isMarked(blueprint.properties[key], "sensitive", { lists: true }))),
1113
- unique: Object.freeze(keys.filter((key) => unique.includes(key) || isMarked(blueprint.properties[key], "unique"))),
1114
- change: Object.freeze([...change])
1115
- });
1116
-
1117
- class DeclaredRecord extends Base {
1118
- static [Kind] = "record";
1119
- static blueprint = blueprint;
1120
- static options = options;
1121
- static plugins = applied.plugins;
1122
- static [RecordPlugins] = applied.plugins;
1123
- static [RecordPluginHooks] = applied.hooks;
1124
- }
1125
- exposeRecordKeys(DeclaredRecord.prototype, keys);
1126
- for (const [member, descriptor] of Object.entries(applied.descriptors)) {
1127
- Object.defineProperty(DeclaredRecord.prototype, member, descriptor);
1128
- }
1129
- if (change.length > 0) {
1130
- Object.defineProperty(DeclaredRecord.prototype, CHANGE_MEMBER, {
1131
- get() {
1132
- let namespace = changeNamespaces.get(this);
1133
- if (namespace === undefined) {
1134
- namespace = Object.freeze(Object.fromEntries(change.map((key) => [
1135
- key,
1136
- (value) => this.set(key, value)
1137
- ])));
1138
- changeNamespaces.set(this, namespace);
1139
- }
1140
- return namespace;
1141
- },
1142
- configurable: true
1143
- });
1144
- }
1145
- Object.defineProperty(DeclaredRecord, "name", { value: name });
1146
- return DeclaredRecord;
1147
- }
1148
- var CHANGE_MEMBER = "change";
1149
- var changeNamespaces = new WeakMap;
1150
-
1151
- // src/core/entity/exceptions.ts
1152
- var ReservedEntityKey = exceptionOf({
1153
- layer: "entity" /* Entity */,
1154
- name: "ReservedEntityKey",
1155
- message: ({ key }, source) => `"${key}" is a key or a member of every entity and cannot be a key of the blueprint of "${source}".`
1156
- });
1157
- var ImmutableEntityKey = exceptionOf({
1158
- layer: "entity" /* Entity */,
1159
- name: "ImmutableEntityKey",
1160
- message: ({ key }, source) => `"${key}" of entity "${source}" cannot be changed.`
1161
- });
1162
- var DeletedEntity = exceptionOf({
1163
- layer: "entity" /* Entity */,
1164
- name: "DeletedEntity",
1165
- message: ({ id }, source) => `Entity "${source}" of id "${id}" was destroyed and cannot change.`
1166
- });
1167
-
1168
- // src/core/entity/entity.ts
1169
- function entityBuilderOf({
1170
- identity,
1171
- generateId,
1172
- now,
1173
- plugins: catalogs
1174
- }) {
1175
- const clock = Object.freeze({ generateId, now });
1176
- const context = pluginContextOf(catalogs ?? []);
1177
- return (blueprint, options = {}) => {
1178
- for (const key of Object.keys(blueprint.properties)) {
1179
- if (RESERVED_ENTITY_KEYS.includes(key)) {
1180
- throw new ReservedEntityKey({ source: "entity", details: { key } });
1181
- }
1182
- }
1183
- for (const key of options.change ?? []) {
1184
- if (ENTITY_IDENTITY_KEYS.includes(key)) {
1185
- throw new ImmutableEntityKey({ source: "entity", details: { key } });
1186
- }
1187
- }
1188
- const DeclaredEntity = declareRecord(AbstractEntity, identity.join(blueprint), { ...options, unique: ["id", ...options.unique ?? []] }, "entity", ENTITY_MEMBERS, context);
1189
- Object.defineProperty(DeclaredEntity, IdentifiedRecord, { value: true });
1190
- Object.defineProperty(DeclaredEntity, EntityClock, { value: clock });
1191
- Object.defineProperty(DeclaredEntity, EntityClassBrand, { value: true });
1192
- Object.defineProperty(DeclaredEntity, EntityUniqueKeys, {
1193
- value: DeclaredEntity.options.unique
1194
- });
1195
- Object.defineProperty(DeclaredEntity, EntityEventSettings, {
1196
- value: Object.freeze({
1197
- onCreate: options.onCreate,
1198
- onUpdate: options.onUpdate,
1199
- onDelete: options.onDelete
1200
- })
1201
- });
1202
- return DeclaredEntity;
1203
- };
1204
- }
1205
- function isEntityClass(value) {
1206
- return isRecordClass(value) && value.prototype instanceof AbstractEntity;
1207
- }
1208
- function isEntity(value) {
1209
- return value instanceof AbstractEntity;
1210
- }
1211
-
1212
- // src/core/entity/event.ts
1213
- var EntityClassBrand = Symbol("entityClass");
1214
- var EventBrand = Symbol("event");
1215
- var EntityEventSettings = Symbol("entityEvents");
1216
- var definitions = new WeakMap;
1217
- var queues = new WeakMap;
1218
- function eventOf(name, entityClass, handler) {
1219
- if (!isEntityClass(entityClass)) {
1220
- throw new TypeError("An event requires an entity class");
1221
- }
1222
- const event = Object.freeze({
1223
- name,
1224
- [EventBrand]: true
1225
- });
1226
- definitions.set(event, (entity) => {
1227
- if (!(entity instanceof entityClass)) {
1228
- throw new TypeError(`Incompatible entity for event ${name}`);
1229
- }
1230
- return Object.freeze({
1231
- name,
1232
- entity,
1233
- async handle() {
1234
- await handler(entity);
1235
- }
1236
- });
1237
- });
1238
- return event;
1239
- }
1240
- function enqueueEvent(entity, event) {
1241
- const bind = definitions.get(event);
1242
- if (!bind)
1243
- throw new TypeError("Expected an eventOf definition");
1244
- const occurrence = bind(entity);
1245
- const queue = queues.get(entity) ?? [];
1246
- queue.push(occurrence);
1247
- queues.set(entity, queue);
1248
- }
1249
- function pullEntityEvents(entity) {
1250
- const queue = queues.get(entity) ?? [];
1251
- queues.delete(entity);
1252
- return queue;
1253
- }
1254
- function enqueueLifecycle(entity, cycle) {
1255
- const settings = entity.constructor[EntityEventSettings];
1256
- const reference = settings?.[cycle];
1257
- if (reference === undefined)
1258
- return;
1259
- const events = typeof reference === "function" ? reference() : reference;
1260
- for (const event of Array.isArray(events) ? events : [events]) {
1261
- enqueueEvent(entity, event);
1262
- }
1263
- }
1264
-
1265
- // src/core/entity/abstract-entity.ts
1266
- var ENTITY_IDENTITY_KEYS = Object.freeze(["id", "createdAt", "updatedAt", "deletedAt"]);
1267
- var ENTITY_MEMBERS = Object.freeze([
1268
- "destroy",
1269
- "isDeleted",
1270
- "equals",
1271
- "onDestroy",
1272
- "emit",
1273
- "pullEvents"
1274
- ]);
1275
- var RESERVED_ENTITY_KEYS = Object.freeze([
1276
- ...ENTITY_IDENTITY_KEYS,
1277
- ...ENTITY_MEMBERS
1278
- ]);
1279
- var EntityClock = Symbol("entityClock");
1280
- var EntityUniqueKeys = Symbol("entityUniqueKeys");
1281
- function identityOf(entity) {
1282
- return entity;
1283
- }
1284
- function clockOf(entity) {
1285
- return entity.constructor[EntityClock];
1286
- }
1287
- function assertAlive(entity) {
1288
- if (entity.isDeleted) {
1289
- throw new DeletedEntity({
1290
- source: entity.constructor.name,
1291
- details: { id: identityOf(entity).id }
1292
- });
1293
- }
1294
- }
1295
- function withIdentity(value, clock) {
1296
- if (typeof value !== "object" || value === null || Array.isArray(value)) {
1297
- return value;
1298
- }
1299
- const { id, createdAt } = value;
1300
- if (id !== undefined && createdAt !== undefined)
1301
- return value;
1302
- return {
1303
- ...value,
1304
- id: id === undefined ? clock.generateId() : id,
1305
- createdAt: createdAt === undefined ? clock.now() : createdAt
1306
- };
1307
- }
1308
-
1309
- class AbstractEntity extends AbstractRecord {
1310
- constructor(value) {
1311
- super(withIdentity(value, new.target[EntityClock]));
1312
- const input = value;
1313
- if (input.id === undefined && input.createdAt === undefined) {
1314
- enqueueLifecycle(this, "onCreate");
1315
- }
1316
- }
1317
- emit(event) {
1318
- enqueueEvent(this, event);
1319
- }
1320
- pullEvents() {
1321
- return pullEntityEvents(this);
1322
- }
1323
- get isDeleted() {
1324
- return identityOf(this).deletedAt !== undefined;
1325
- }
1326
- equals(other) {
1327
- return other instanceof AbstractEntity && other.blueprint === this.blueprint && identityOf(other).id === identityOf(this).id;
1328
- }
1329
- destroy() {
1330
- assertAlive(this);
1331
- storeRecordValue(this, "deletedAt", clockOf(this).now());
1332
- enqueueLifecycle(this, "onDelete");
1333
- this.onDestroy();
1334
- return this;
1335
- }
1336
- set(key, value) {
1337
- const name = String(key);
1338
- if (ENTITY_IDENTITY_KEYS.includes(name)) {
1339
- throw new ImmutableEntityKey({
1340
- source: this.constructor.name,
1341
- details: { key: name }
1342
- });
1343
- }
1344
- assertAlive(this);
1345
- const { next, previous } = storeRecordValue(this, name, value);
1346
- storeRecordValue(this, "updatedAt", clockOf(this).now());
1347
- enqueueLifecycle(this, "onUpdate");
1348
- return runRecordEffects(this, key, next, previous);
1349
- }
1350
- onDestroy() {}
1351
- }
1352
-
1353
- // src/core/environment/environment.ts
1354
- var InvalidEnvironment = exceptionOf({
1355
- layer: "environment" /* Environment */,
1356
- name: "InvalidEnvironment",
1357
- message: ({ keys }) => `Invalid environment variables: ${keys.join(", ")}.`
1358
- });
1359
- var processEnv = () => globalThis.process?.env ?? {};
1360
- function environmentOf(blueprint, { source = processEnv } = {}) {
1361
- if (!isBlueprint(blueprint) || blueprint.optional) {
1362
- throw new TypeError("An environment requires a blueprint");
1363
- }
1364
- let value;
1365
- return Object.freeze({
1366
- [Kind]: "environment",
1367
- blueprint,
1368
- load() {
1369
- if (value !== undefined)
1370
- return value;
1371
- value = parseEnvironment(blueprint, source());
1372
- return value;
1373
- }
1374
- });
1375
- }
1376
- function parseEnvironment(blueprint, variables) {
1377
- const declared = {};
1378
- for (const [key, field] of Object.entries(blueprint.properties)) {
1379
- const variable = variables[key];
1380
- if (variable !== undefined)
1381
- declared[key] = convert(field, variable);
1382
- }
1383
- const parsed = blueprint.safeParse(declared);
1384
- if (!parsed.issues)
1385
- return Object.freeze(parsed.value);
1386
- const issues = parsed.issues;
1387
- throw new InvalidEnvironment({
1388
- source: "environment",
1389
- details: {
1390
- keys: [...new Set(issues.map((issue) => String(issue.path[0] ?? "")))]
1391
- },
1392
- cause: issues.find((issue) => issue.cause)?.cause
1393
- });
1394
- }
1395
- function convert(field, variable) {
1396
- if (!isProperty(field))
1397
- return variable;
1398
- const { schema } = field.type;
1399
- if (schema.matchShape(variable))
1400
- return variable;
1401
- const text = variable.trim();
1402
- if (text === "true" || text === "false") {
1403
- if (schema.matchShape(text === "true"))
1404
- return text === "true";
1405
- }
1406
- const number = text === "" ? Number.NaN : Number(text);
1407
- if (Number.isFinite(number) && schema.matchShape(number))
1408
- return number;
1409
- return variable;
1410
- }
1411
- function loadEnvironments(dependencies) {
1412
- if (dependencies === undefined)
1413
- return Object.freeze({});
1414
- const list = isEnvironment(dependencies) ? [dependencies] : dependencies;
1415
- return Object.freeze(Object.assign({}, ...list.map((environment) => environment.load())));
1416
- }
1417
- function isEnvironment(value) {
1418
- return typeof value === "object" && value !== null && value[Kind] === "environment";
1419
- }
1420
-
1421
- // src/core/openapi/exceptions.ts
1422
- var InvalidOpenAPIModel = exceptionOf({
1423
- layer: "output" /* Output */,
1424
- name: "InvalidOpenAPIModel",
1425
- message: ({ name }) => `"${name}" is not a property, blueprint, list, record or entity.`
1426
- });
1427
-
1428
- // src/core/openapi/openapi.ts
1429
- var NO_MARKS = { writeOnly: [], readOnly: [] };
1430
- function isField(value) {
1431
- return isProperty(value) || isBlueprint(value) || isBlueprintList(value) || recordFieldOf(value) !== undefined;
1432
- }
1433
- function isOptional(field) {
1434
- if (isProperty(field))
1435
- return field.type.optional === true;
1436
- if (isBlueprint(field) || isBlueprintList(field))
1437
- return field.optional;
1438
- return recordFieldOf(field)?.optional ?? false;
1439
- }
1440
- function plainOf(value, nested = false) {
1441
- if (Array.isArray(value))
1442
- return value.map((item) => plainOf(item, true));
1443
- if (typeof value !== "object" || value === null)
1444
- return value;
1445
- const id = value.$id;
1446
- if (nested && typeof id === "string")
1447
- return { $ref: id };
1448
- const plain = {};
1449
- for (const [key, item] of Object.entries(value)) {
1450
- if (!key.startsWith("~"))
1451
- plain[key] = plainOf(item, true);
1452
- }
1453
- return plain;
1454
- }
1455
- function objectOf(properties, scope, marks) {
1456
- const shape = {};
1457
- const required = [];
1458
- for (const [key, field] of Object.entries(properties)) {
1459
- const schema = schemaOf2(field, scope);
1460
- if (marks.readOnly.includes(key))
1461
- schema.readOnly = true;
1462
- if (marks.writeOnly.includes(key))
1463
- schema.writeOnly = true;
1464
- shape[key] = schema;
1465
- if (!isOptional(field))
1466
- required.push(key);
1467
- }
1468
- return {
1469
- type: "object",
1470
- properties: shape,
1471
- ...required.length > 0 ? { required } : {},
1472
- additionalProperties: false
1473
- };
1474
- }
1475
- function recordSchemaOf(record, scope) {
1476
- const { sensitive = [] } = record.options ?? {};
1477
- return objectOf(record.blueprint.properties, scope, {
1478
- writeOnly: sensitive,
1479
- readOnly: isEntityClass(record) ? ENTITY_IDENTITY_KEYS : []
1480
- });
1481
- }
1482
- function schemaOf2(field, scope) {
1483
- if (isBlueprintList(field)) {
1484
- const { item, minItems, maxItems } = field;
1485
- return {
1486
- type: "array",
1487
- items: schemaOf2(item, scope),
1488
- ...minItems === undefined ? {} : { minItems },
1489
- ...maxItems === undefined ? {} : { maxItems }
1490
- };
1491
- }
1492
- if (isBlueprint(field))
1493
- return objectOf(field.properties, scope, NO_MARKS);
1494
- const record = recordFieldOf(field);
1495
- if (record) {
1496
- const name = scope.names.get(record.record);
1497
- return name === undefined ? recordSchemaOf(record.record, scope) : { $ref: `${scope.prefix}${name}` };
1498
- }
1499
- if (!isProperty(field)) {
1500
- throw new InvalidOpenAPIModel({
1501
- source: "openapi",
1502
- details: { name: String(field) }
1503
- });
1504
- }
1505
- const schema = plainOf(field.type.schema.type.Type());
1506
- if (field.type.sensitive)
1507
- schema.writeOnly = true;
1508
- return schema;
1509
- }
1510
- function toOpenAPI(modelOrModels, { refPrefix = "#/components/schemas/" } = {}) {
1511
- if (isField(modelOrModels)) {
1512
- return schemaOf2(modelOrModels, { names: new Map, prefix: refPrefix });
1513
- }
1514
- if (typeof modelOrModels !== "object" || modelOrModels === null) {
1515
- throw new InvalidOpenAPIModel({
1516
- source: "openapi",
1517
- details: { name: String(modelOrModels) }
1518
- });
1519
- }
1520
- const names = new Map;
1521
- for (const [name, model] of Object.entries(modelOrModels)) {
1522
- if (!isField(model)) {
1523
- throw new InvalidOpenAPIModel({ source: "openapi", details: { name } });
1524
- }
1525
- const record = recordFieldOf(model);
1526
- if (record && !names.has(record.record))
1527
- names.set(record.record, name);
1528
- }
1529
- const scope = { names, prefix: refPrefix };
1530
- const schemas = {};
1531
- for (const [name, model] of Object.entries(modelOrModels)) {
1532
- const record = recordFieldOf(model);
1533
- schemas[name] = record && names.get(record.record) === name ? recordSchemaOf(record.record, scope) : schemaOf2(model, scope);
1534
- }
1535
- return { schemas };
1536
- }
1537
-
1538
- // src/core/repository/state.ts
1539
- var states = new WeakMap;
1540
- function findState(repository) {
1541
- if (typeof repository !== "object" || repository === null)
1542
- return;
1543
- for (let Class = repository.constructor;typeof Class === "function"; Class = Object.getPrototypeOf(Class)) {
1544
- const state = states.get(Class);
1545
- if (state)
1546
- return state;
1547
- }
1548
- return;
1549
- }
1550
- function stateOf(repository) {
1551
- const state = findState(repository);
1552
- if (!state)
1553
- throw new TypeError("Expected a repository made by repositoryOf");
1554
- return state;
1555
- }
1556
- function contextOf(state) {
1557
- state.context ??= Object.freeze({
1558
- entity: state.entity,
1559
- name: state.name,
1560
- unique: state.entity[EntityUniqueKeys],
1561
- env: loadEnvironments(state.environment)
1562
- });
1563
- return state.context;
1564
- }
1565
- function inspectRepository(repository) {
1566
- const state = findState(repository);
1567
- if (!state)
1568
- return;
1569
- const { environment } = state;
1570
- return {
1571
- entity: state.entity,
1572
- actions: state.actions,
1573
- explicitProvider: state.explicitProvider,
1574
- environments: environment === undefined ? [] : Array.isArray(environment) ? environment : [environment],
1575
- relations: [...state.relations.values()].map(declarationOf),
1576
- state: declarationOf(state)
1577
- };
1578
- }
1579
- var origins = new WeakMap;
1580
- function declarationOf(state) {
1581
- return origins.get(state) ?? state;
1582
- }
1583
- function bindState(state, provider, bound = new Map) {
1584
- const done = bound.get(state);
1585
- if (done)
1586
- return done;
1587
- const copy = {
1588
- ...state,
1589
- provider: state.explicitProvider ? state.provider : provider,
1590
- context: undefined,
1591
- relations: new Map([...state.relations].map(([target, related]) => [
1592
- target,
1593
- bindState(related, provider, bound)
1594
- ]))
1595
- };
1596
- origins.set(copy, declarationOf(state));
1597
- bound.set(state, copy);
1598
- return copy;
1599
- }
1600
- function bindRepository(repository, provider) {
1601
- const state = stateOf(repository);
1602
- const Declared = repository.constructor;
1603
-
1604
- class Bound extends Declared {
1605
- }
1606
- Object.defineProperty(Bound, "name", { value: Declared.name });
1607
- states.set(Bound, bindState(state, provider));
1608
- return Object.freeze(new Bound);
1609
- }
1610
-
1611
- // src/core/application/exceptions.ts
1612
- var InvalidApplicationDeclaration = exceptionOf({
1613
- layer: "application" /* Application */,
1614
- name: "InvalidApplicationDeclaration",
1615
- message: ({ reason }) => reason
1616
- });
1617
- var DuplicateApplicationDeclaration = exceptionOf({
1618
- layer: "application" /* Application */,
1619
- name: "DuplicateApplicationDeclaration",
1620
- message: ({
1621
- first,
1622
- second
1623
- }) => `The same object is registered as ${first} and as ${second}.`
1624
- });
1625
- var ApplicationConflict = exceptionOf({
1626
- layer: "application" /* Application */,
1627
- name: "ApplicationConflict",
1628
- message: ({
1629
- reason
1630
- }) => reason
1631
- });
1632
- var UnregisteredApplicationReference = exceptionOf({
1633
- layer: "application" /* Application */,
1634
- name: "UnregisteredApplicationReference",
1635
- message: ({
1636
- holder,
1637
- reference
1638
- }) => `${holder} holds ${reference}, which is not registered in the application.`
1639
- });
1640
- var UnregisteredRepositoryDependency = exceptionOf({
1641
- layer: "application" /* Application */,
1642
- name: "UnregisteredRepositoryDependency",
1643
- message: ({
1644
- repository,
1645
- dependency
1646
- }) => `Repository ${repository} depends on ${dependency}, which is not registered in the application.`
1647
- });
1648
-
1649
- // src/core/application/application.ts
1650
- var KEYS = [
1651
- "properties",
1652
- "blueprints",
1653
- "records",
1654
- "entities",
1655
- "environments",
1656
- "repositories"
1657
- ];
1658
- var internals2 = new WeakMap;
1659
- var KIND_OF = {
1660
- properties: "property",
1661
- blueprints: "blueprint",
1662
- records: "record",
1663
- entities: "entity",
1664
- environments: "environment",
1665
- repositories: "repository"
1666
- };
1667
- function isApplication(value) {
1668
- return typeof value === "object" && value !== null && value[Kind] === "application";
1669
- }
1670
- function invalid(source, reason) {
1671
- throw new InvalidApplicationDeclaration({ source, details: { reason } });
1672
- }
1673
- function isOfKind(collection, value) {
1674
- switch (collection) {
1675
- case "properties":
1676
- return isProperty(value);
1677
- case "blueprints":
1678
- return isBlueprint(value);
1679
- case "records":
1680
- return isRecordClass(value) && !isEntityClass(value);
1681
- case "entities":
1682
- return isEntityClass(value);
1683
- case "environments":
1684
- return isEnvironment(value);
1685
- case "repositories":
1686
- return inspectRepository(value) !== undefined;
1687
- }
1688
- }
1689
- function keyOf(collection, value) {
1690
- switch (collection) {
1691
- case "properties":
1692
- return fieldOf(value);
1693
- case "blueprints":
1694
- return value.properties;
1695
- case "repositories":
1696
- return inspectRepository(value).state;
1697
- default:
1698
- return value;
1699
- }
1700
- }
1701
- function emptyRegistry() {
1702
- return Object.fromEntries(KEYS.map((key) => [key, new Map]));
1703
- }
1704
- function resolve(settings) {
1705
- const registry = emptyRegistry();
1706
- const byKey = new Map;
1707
- const source = settings.name;
1708
- const add = (entry) => {
1709
- const same = registry[entry.collection].get(entry.name);
1710
- if (same) {
1711
- if (same.key === entry.key)
1712
- return;
1713
- conflict(`${KIND_OF[entry.collection]} "${entry.name}" is declared as different objects by "${same.from}" and by "${entry.from}".`, same, entry);
1714
- }
1715
- const other = byKey.get(entry.key);
1716
- if (other) {
1717
- if (other.from === entry.from) {
1718
- throw new DuplicateApplicationDeclaration({
1719
- source,
1720
- details: {
1721
- first: `${KIND_OF[other.collection]} "${other.name}"`,
1722
- second: `${KIND_OF[entry.collection]} "${entry.name}"`
1723
- }
1724
- });
1725
- }
1726
- conflict(`The same ${KIND_OF[entry.collection]} is ${KIND_OF[other.collection]} "${other.name}" in "${other.from}" and ${KIND_OF[entry.collection]} "${entry.name}" in "${entry.from}".`, other, entry);
1727
- }
1728
- registry[entry.collection].set(entry.name, entry);
1729
- byKey.set(entry.key, entry);
1730
- };
1731
- const conflict = (reason, first, second) => {
1732
- throw new ApplicationConflict({
1733
- source,
1734
- details: {
1735
- reason,
1736
- origins: [first.from, second.from],
1737
- declarations: [
1738
- `${KIND_OF[first.collection]} ${first.name}`,
1739
- `${KIND_OF[second.collection]} ${second.name}`
1740
- ]
1741
- }
1742
- });
1743
- };
1744
- for (const other of settings.extends ?? []) {
1745
- const resolved = internals2.get(other);
1746
- if (!resolved)
1747
- invalid(source, "Expected `extends` to hold applications.");
1748
- for (const key of KEYS) {
1749
- for (const entry of resolved[key].values())
1750
- add(entry);
1751
- }
1752
- }
1753
- for (const collection of KEYS) {
1754
- const declared = settings[collection];
1755
- if (declared === undefined)
1756
- continue;
1757
- if (typeof declared !== "object" || declared === null || Array.isArray(declared)) {
1758
- invalid(source, `Expected ${collection} to be an object of declarations.`);
1759
- }
1760
- for (const [name, value] of Object.entries(declared)) {
1761
- if (!isOfKind(collection, value)) {
1762
- invalid(source, `${collection}.${name} is not a ${KIND_OF[collection]} (${collection} takes ${KIND_OF[collection]} declarations).`);
1763
- }
1764
- add({
1765
- collection,
1766
- name,
1767
- value,
1768
- key: keyOf(collection, value),
1769
- from: source
1770
- });
1771
- }
1772
- }
1773
- return registry;
1774
- }
1775
- function recordsIn(properties) {
1776
- const found = new Set;
1777
- const visit = (field) => {
1778
- if (isBlueprintList(field))
1779
- visit(field.item);
1780
- else if (isBlueprint(field))
1781
- walk(field.properties);
1782
- else {
1783
- const record = recordFieldOf(field)?.record;
1784
- if (record)
1785
- found.add(record);
1786
- }
1787
- };
1788
- const walk = (collection) => {
1789
- for (const field of Object.values(collection))
1790
- visit(field);
1791
- };
1792
- walk(properties);
1793
- return found;
1794
- }
1795
- function validate(source, registry) {
1796
- const registered = new Set([
1797
- ...[...registry.records.values()].map((entry) => entry.key),
1798
- ...[...registry.entities.values()].map((entry) => entry.key)
1799
- ]);
1800
- const holders = [
1801
- ["blueprints", "properties"],
1802
- ["records", "blueprint.properties"],
1803
- ["entities", "blueprint.properties"]
1804
- ];
1805
- for (const [collection] of holders) {
1806
- for (const entry of registry[collection].values()) {
1807
- const properties = collection === "blueprints" ? entry.value.properties : entry.value.blueprint.properties;
1808
- for (const record of recordsIn(properties)) {
1809
- if (registered.has(record))
1810
- continue;
1811
- throw new UnregisteredApplicationReference({
1812
- source,
1813
- details: {
1814
- holder: `${KIND_OF[collection]} "${entry.name}"`,
1815
- reference: `${isEntityClass(record) ? "entity" : "record"} "${record.name}"`
1816
- }
1817
- });
1818
- }
1819
- }
1820
- }
1821
- const repositories = new Set([...registry.repositories.values()].map((entry) => entry.key));
1822
- const environments = new Set([...registry.environments.values()].map((entry) => entry.key));
1823
- const unregistered = (repository, dependency) => {
1824
- throw new UnregisteredRepositoryDependency({
1825
- source,
1826
- details: { repository, dependency }
1827
- });
1828
- };
1829
- for (const entry of registry.repositories.values()) {
1830
- const info = inspectRepository(entry.value);
1831
- if (!registered.has(info.entity)) {
1832
- unregistered(entry.name, `entity "${info.entity.name}"`);
1833
- }
1834
- for (const relation of info.relations) {
1835
- if (!repositories.has(relation)) {
1836
- unregistered(entry.name, `the repository of "${relation.entity.name}"`);
1837
- }
1838
- }
1839
- for (const environment of info.environments) {
1840
- if (!environments.has(environment)) {
1841
- unregistered(entry.name, "an environment");
1842
- }
1843
- }
1844
- }
1845
- }
1846
- function jsonOf(value) {
1847
- return JSON.parse(JSON.stringify(value, (_key, item) => item instanceof RegExp ? item.source : item));
1848
- }
1849
- function referencesOf(registry, collection) {
1850
- return new Map([...registry[collection].values()].map((entry) => [entry.key, entry.name]));
1851
- }
1852
- function propertyReferenceOf(Property, scope) {
1853
- const ref = scope.properties.get(fieldOf(Property));
1854
- return ref === undefined ? propertyDescriptionOf(Property, scope) : { ref };
1855
- }
1856
- function lineageDescriptionOf(lineage, scope) {
1857
- switch (lineage.kind) {
1858
- case "refined":
1859
- return {
1860
- kind: "refined",
1861
- base: propertyReferenceOf(lineage.base, scope),
1862
- options: jsonOf(lineage.options)
1863
- };
1864
- case "optional":
1865
- return {
1866
- kind: "optional",
1867
- base: propertyReferenceOf(lineage.base, scope)
1868
- };
1869
- case "factory":
1870
- return {
1871
- kind: "factory",
1872
- factory: lineage.factory,
1873
- args: jsonOf(lineage.args)
1874
- };
1875
- }
1876
- }
1877
- function propertyDescriptionOf(Property, scope) {
1878
- const { type } = Property;
1879
- const lineage = propertyLineageOf(Property);
1880
- return {
1881
- name: type.name,
1882
- optional: type.optional === true,
1883
- sensitive: type.sensitive === true,
1884
- unique: type.unique === true,
1885
- schema: plainOf(type.schema.type.Type()),
1886
- ...lineage ? { lineage: lineageDescriptionOf(lineage, scope) } : {}
1887
- };
1888
- }
1889
- function fieldDescriptionOf(field, scope) {
1890
- if (isProperty(field)) {
1891
- const real = fieldOf(field);
1892
- const ref = scope.properties.get(real);
1893
- return ref === undefined ? { kind: "property", ...propertyDescriptionOf(real, scope) } : { kind: "property", ref, optional: real.type.optional === true };
1894
- }
1895
- if (isBlueprintList(field)) {
1896
- return {
1897
- kind: "list",
1898
- item: fieldDescriptionOf(field.item, scope),
1899
- optional: field.optional,
1900
- ...field.minItems === undefined ? {} : { minItems: field.minItems },
1901
- ...field.maxItems === undefined ? {} : { maxItems: field.maxItems }
1902
- };
1903
- }
1904
- if (isBlueprint(field)) {
1905
- const ref = scope.blueprints.get(field.properties);
1906
- return ref === undefined ? {
1907
- kind: "blueprint",
1908
- optional: field.optional,
1909
- fields: fieldsDescriptionOf(field.properties, scope)
1910
- } : { kind: "blueprint", ref, optional: field.optional };
1911
- }
1912
- const record = recordFieldOf(field);
1913
- if (record) {
1914
- const entity = scope.entities.get(record.record);
1915
- const ref = entity ?? scope.records.get(record.record);
1916
- return {
1917
- kind: entity === undefined ? "record" : "entity",
1918
- ref: ref ?? record.record.name,
1919
- optional: record.optional
1920
- };
1921
- }
1922
- return {
1923
- kind: "property",
1924
- name: "unknown",
1925
- optional: false,
1926
- sensitive: false,
1927
- unique: false,
1928
- schema: {}
1929
- };
1930
- }
1931
- function fieldsDescriptionOf(properties, scope, skip = new Set) {
1932
- return Object.fromEntries(Object.entries(properties).filter(([key]) => !skip.has(key)).map(([key, field]) => [key, fieldDescriptionOf(field, scope)]));
1933
- }
1934
- function recordDescriptionOf(entry, scope) {
1935
- const Record = entry.value;
1936
- const plugins = pluginsOf(Record).map((plugin) => plugin.toJSON());
1937
- const skip = new Set(plugins.flatMap((plugin) => plugin.keys));
1938
- if (entry.collection === "entities") {
1939
- for (const key of ENTITY_IDENTITY_KEYS)
1940
- skip.add(key);
1941
- }
1942
- const own = (keys, flag) => keys.filter((key) => {
1943
- if (skip.has(key))
1944
- return false;
1945
- const field = Record.blueprint.properties[key];
1946
- return !(flag && isProperty(field) && field.type[flag] === true);
1947
- });
1948
- return {
1949
- from: entry.from,
1950
- fields: fieldsDescriptionOf(Record.blueprint.properties, scope, skip),
1951
- options: {
1952
- sensitive: own(Record.options.sensitive, "sensitive"),
1953
- unique: own(Record.options.unique, "unique"),
1954
- change: own(Record.options.change)
1955
- },
1956
- plugins
1957
- };
1958
- }
1959
- function describeRegistry(name, extended, registry) {
1960
- const scope = {
1961
- properties: referencesOf(registry, "properties"),
1962
- blueprints: referencesOf(registry, "blueprints"),
1963
- records: referencesOf(registry, "records"),
1964
- entities: referencesOf(registry, "entities")
1965
- };
1966
- const repositories = referencesOf(registry, "repositories");
1967
- const each = (collection, describe) => Object.fromEntries([...registry[collection].values()].map((entry) => [
1968
- entry.name,
1969
- describe(entry)
1970
- ]));
1971
- return {
1972
- name,
1973
- extends: extended.map((other) => other.name),
1974
- properties: each("properties", (entry) => ({
1975
- from: entry.from,
1976
- ...propertyDescriptionOf(entry.value, scope)
1977
- })),
1978
- blueprints: each("blueprints", (entry) => ({
1979
- from: entry.from,
1980
- fields: fieldsDescriptionOf(entry.value.properties, scope)
1981
- })),
1982
- records: each("records", (entry) => recordDescriptionOf(entry, scope)),
1983
- entities: each("entities", (entry) => recordDescriptionOf(entry, scope)),
1984
- environments: each("environments", (entry) => ({
1985
- from: entry.from,
1986
- fields: fieldsDescriptionOf(entry.value.blueprint.properties, scope)
1987
- })),
1988
- repositories: each("repositories", (entry) => {
1989
- const info = inspectRepository(entry.value);
1990
- return {
1991
- from: entry.from,
1992
- entity: scope.entities.get(info.entity),
1993
- actions: info.actions,
1994
- relations: info.relations.map((relation) => repositories.get(relation)),
1995
- environments: info.environments.map((environment) => referencesOf(registry, "environments").get(environment)),
1996
- provider: info.explicitProvider
1997
- };
1998
- })
1999
- };
2000
- }
2001
- function applicationOf(settings) {
2002
- const { name } = settings ?? {};
2003
- if (typeof name !== "string" || name === "") {
2004
- invalid("applicationOf", "Expected a name.");
2005
- }
2006
- const extended = settings.extends ?? [];
2007
- if (!Array.isArray(extended) || !extended.every(isApplication)) {
2008
- invalid(name, "Expected `extends` to be a list of applications.");
2009
- }
2010
- const registry = resolve(settings);
2011
- validate(name, registry);
2012
- const provider = settings.provider ?? [...extended].reverse().find((other) => other.provider)?.provider;
2013
- if (provider !== undefined && typeof provider !== "object") {
2014
- invalid(name, "Expected `provider` to be a repository provider.");
2015
- }
2016
- const collection = (key) => Object.freeze(Object.fromEntries([...registry[key].values()].map((entry) => [entry.name, entry.value])));
2017
- const bound = new Map;
2018
- const repositories = {};
2019
- for (const entry of registry.repositories.values()) {
2020
- const repository = provider === undefined ? entry.value : bindRepository(entry.value, provider);
2021
- bound.set(entry.value, repository);
2022
- repositories[entry.name] = repository;
2023
- }
2024
- const application = Object.freeze({
2025
- [Kind]: "application",
2026
- name,
2027
- extends: Object.freeze([...extended]),
2028
- provider,
2029
- properties: collection("properties"),
2030
- blueprints: collection("blueprints"),
2031
- records: collection("records"),
2032
- entities: collection("entities"),
2033
- environments: collection("environments"),
2034
- repositories: Object.freeze(repositories),
2035
- repository(repository) {
2036
- if (!bound.has(repository)) {
2037
- invalid(name, "Expected a repository registered in the application.");
2038
- }
2039
- return bound.get(repository);
2040
- },
2041
- extend(...others) {
2042
- return applicationOf({
2043
- name,
2044
- extends: [application, ...others],
2045
- ...provider === undefined ? {} : { provider }
2046
- });
2047
- },
2048
- describe: () => describeRegistry(name, extended, registry)
2049
- });
2050
- internals2.set(application, registry);
2051
- return application;
2052
- }
2053
- // src/core/blueprint/blueprint.ts
2054
- import { Type as Type3 } from "typebox";
2055
-
2056
- // src/core/property/property.ts
2057
- import { Type } from "typebox";
2058
-
2059
- // src/core/symbols/state.ts
2060
- var State = Symbol("state");
2061
-
2062
- // src/core/property/abstract-property.ts
2063
- var parsingDefinitions = new WeakMap;
2064
- function parsingDefinitionOf(Class) {
2065
- let definition = parsingDefinitions.get(Class);
2066
- if (!definition) {
2067
- definition = Object.create(Class.prototype).createDefinition();
2068
- parsingDefinitions.set(Class, definition);
2069
- }
2070
- return definition;
2071
- }
2072
-
2073
- class AbstractProperty {
2074
- get [State]() {
2075
- return this.definition[State];
2076
- }
2077
- definition;
2078
- value;
2079
- constructor(value) {
2080
- this.definition = this.createDefinition();
2081
- this.value = this.definition.make(value === Demo ? this.definition.type[Demo] : value);
2082
- }
2083
- static demo() {
2084
- return new this(Demo);
2085
- }
2086
- static safeParse(value) {
2087
- return parsingDefinitionOf(this).parse(value);
2088
- }
2089
- static with(options) {
2090
- return refinePropertyOf(this, options);
2091
- }
2092
- static get "~standard"() {
2093
- return standardOfClass(this);
2094
- }
2095
- }
2096
-
2097
- // src/core/property/enums/property-states.ts
2098
- var PropertyStates;
2099
- ((PropertyStates) => {
2100
- PropertyStates[PropertyStates["Declared"] = 0] = "Declared";
2101
- PropertyStates[PropertyStates["PreHandling"] = 1] = "PreHandling";
2102
- PropertyStates[PropertyStates["Handling"] = 2] = "Handling";
2103
- PropertyStates[PropertyStates["AfterHandling"] = 3] = "AfterHandling";
2104
- PropertyStates[PropertyStates["Done"] = 4] = "Done";
2105
- })(PropertyStates ||= {});
2106
-
2107
- // src/core/property/exceptions.ts
2108
- var PropertyRequired = exceptionOf({
2109
- layer: "property" /* Property */,
2110
- name: "PropertyRequired",
2111
- message: (_, source) => `Property "${source}" is required.`
2112
- });
2113
- var InvalidPropertyValue = exceptionOf({
2114
- layer: "property" /* Property */,
2115
- name: "InvalidPropertyValue",
2116
- message: ({ errors }, source) => `Invalid value for property "${source}": ${errors.join("; ")}`
2117
- });
2118
-
2119
- // src/core/property/define-property.ts
2120
- var MISMATCH = Symbol("mismatch");
2121
- function once(build) {
2122
- let result;
2123
- return () => {
2124
- result ??= build();
2125
- return result;
2126
- };
2127
- }
2128
- function segmentsOf(pointer) {
2129
- if (pointer === "")
2130
- return [];
2131
- return pointer.slice(1).split("/").map((segment) => {
2132
- const key = segment.replaceAll("~1", "/").replaceAll("~0", "~");
2133
- return /^(0|[1-9]\d*)$/.test(key) ? Number(key) : key;
2134
- });
2135
- }
2136
-
2137
- class AbstractDefineProperty {
2138
- [State] = 0 /* Declared */;
2139
- make(value) {
2140
- const attempt = this.attempt(value);
2141
- if ("failure" in attempt)
2142
- throw attempt.failure.exception();
2143
- return attempt.value;
2144
- }
2145
- parse(value) {
2146
- const attempt = this.attemptWithoutThrowing(value);
2147
- if (!("failure" in attempt))
2148
- return { value: attempt.value };
2149
- const { exception, raised, issues } = attempt.failure;
2150
- return {
2151
- issues: issues.map((issue) => raised ? { ...issue, cause: exception() } : withLazyCause(issue, exception))
2152
- };
2153
- }
2154
- preHandle(value) {
2155
- return value;
2156
- }
2157
- afterHandle(value) {
2158
- return value;
2159
- }
2160
- handle(value) {
2161
- return this.type.schema.match(value) ? value : MISMATCH;
2162
- }
2163
- attemptWithoutThrowing(value) {
2164
- try {
2165
- return this.attempt(value);
2166
- } catch (error) {
2167
- return {
2168
- failure: this.raise(error instanceof Exception ? error : this.invalidValue(error))
2169
- };
2170
- }
2171
- }
2172
- attempt(value) {
2173
- const { name, optional } = this.type;
2174
- this[State] = 0 /* Declared */;
2175
- if (value === undefined) {
2176
- if (!optional) {
2177
- return {
2178
- failure: {
2179
- exception: () => new PropertyRequired({ source: name }),
2180
- raised: false,
2181
- issues: [
2182
- {
2183
- message: "is required",
2184
- path: [],
2185
- code: "required",
2186
- source: name
2187
- }
2188
- ]
2189
- }
2190
- };
2191
- }
2192
- this[State] = 4 /* Done */;
2193
- return { value };
2194
- }
2195
- if (!this.type.schema.matchShape(value)) {
2196
- return { failure: this.mismatch(value) };
2197
- }
2198
- try {
2199
- this[State] = 1 /* PreHandling */;
2200
- value = this.runHandler(() => this.preHandle(value));
2201
- this[State] = 2 /* Handling */;
2202
- const handled = this.handle(value);
2203
- if (handled === MISMATCH) {
2204
- return { failure: this.mismatch(value) };
2205
- }
2206
- value = handled;
2207
- this[State] = 3 /* AfterHandling */;
2208
- value = this.runHandler(() => this.afterHandle(value));
2209
- } catch (error) {
2210
- if (error instanceof Exception)
2211
- return { failure: this.raise(error) };
2212
- throw error;
2213
- }
2214
- this[State] = 4 /* Done */;
2215
- return { value };
2216
- }
2217
- runHandler(handler) {
2218
- try {
2219
- return handler();
2220
- } catch (error) {
2221
- if (error instanceof Exception)
2222
- throw error;
2223
- throw this.invalidValue(error);
2224
- }
2225
- }
2226
- invalidValue(error) {
2227
- return new InvalidPropertyValue({
2228
- source: this.type.name,
2229
- details: {
2230
- errors: [error instanceof Error ? error.message : String(error)]
2231
- },
2232
- cause: error
2233
- });
2234
- }
2235
- raise(exception) {
2236
- return {
2237
- exception: () => exception,
2238
- raised: true,
2239
- issues: [
2240
- {
2241
- message: exception.message,
2242
- path: [],
2243
- code: "invalid_value",
2244
- source: this.type.name
2245
- }
2246
- ]
2247
- };
2248
- }
2249
- mismatch(value) {
2250
- const { name, schema } = this.type;
2251
- const errors = schema.type.Errors(value);
2252
- const issues = errors.map((error) => ({
2253
- message: error.message,
2254
- path: segmentsOf(error.instancePath),
2255
- code: "invalid_value",
2256
- source: name
2257
- }));
2258
- return {
2259
- exception: once(() => new InvalidPropertyValue({
2260
- source: name,
2261
- details: { errors: errors.map(describeError) }
2262
- })),
2263
- raised: false,
2264
- issues: issues.length > 0 ? issues : [
2265
- {
2266
- message: "is invalid",
2267
- path: [],
2268
- code: "invalid_value",
2269
- source: name
2270
- }
2271
- ]
2272
- };
2273
- }
2274
- }
2275
-
2276
- // src/core/property/property.ts
2277
- function propertyOf({
2278
- name,
2279
- schema,
2280
- optional,
2281
- sensitive = false,
2282
- unique = false,
2283
- default: _default,
2284
- preHandle: onPreHandle,
2285
- afterHandle: onAfterHandle
2286
- }) {
2287
- const valueSchema = optional ? Type.Optional(schema) : schema;
2288
- const SchemaConstructor = schemaOf(name, valueSchema);
2289
- const type = {
2290
- [Demo]: _default,
2291
- name,
2292
- schema: new SchemaConstructor,
2293
- optional: optional ?? false,
2294
- sensitive,
2295
- unique
2296
- };
2297
-
2298
- class DefineProperty extends AbstractDefineProperty {
2299
- get type() {
2300
- return type;
2301
- }
2302
- preHandle(value) {
2303
- return onPreHandle ? onPreHandle(value) : value;
2304
- }
2305
- afterHandle(value) {
2306
- return onAfterHandle ? onAfterHandle(value) : value;
2307
- }
2308
- }
2309
-
2310
- class Property extends AbstractProperty {
2311
- static type = type;
2312
- createDefinition() {
2313
- return new DefineProperty;
2314
- }
2315
- }
2316
- return Property;
2317
- }
2318
-
2319
- // src/core/blueprint/exceptions.ts
2320
- var ReservedBlueprintKey = exceptionOf({
2321
- layer: "blueprint" /* Blueprint */,
2322
- name: "ReservedBlueprintKey",
2323
- message: ({ key }) => `"${key}" is reserved and cannot be a plugin property.`
2324
- });
2325
- var UndeclaredBlueprintProperty = exceptionOf({
2326
- layer: "blueprint" /* Blueprint */,
2327
- name: "UndeclaredBlueprintProperty",
2328
- message: ({ key }) => `Property "${key}" of the blueprint is not declared.`
2329
- });
2330
-
2331
- // src/core/blueprint/optional.ts
2332
- import { Type as Type2 } from "typebox";
2333
- var cache2 = new WeakMap;
2334
- function optionalOf(given) {
2335
- const field = fieldOf(given);
2336
- const cached = cache2.get(field);
2337
- if (cached)
2338
- return cached;
2339
- if (isOptionalRecord(field))
2340
- return field;
2341
- if (isRecordClass(field)) {
2342
- const optional = Object.freeze(withStandard({
2343
- [Kind]: "record",
2344
- record: field,
2345
- optional: true
2346
- }, (value) => value === undefined ? { value } : field.safeParse(value)));
2347
- cache2.set(field, optional);
2348
- return optional;
2349
- }
2350
- if (isBlueprint(field)) {
2351
- if (field.optional)
2352
- return field;
2353
- const optional = {
2354
- ...field,
2355
- optional: true,
2356
- safeParse: (value) => value === undefined ? { value } : field.safeParse(value)
2357
- };
2358
- Object.freeze(withStandard(optional, (value) => optional.safeParse(value)));
2359
- cache2.set(field, optional);
2360
- return optional;
2361
- }
2362
- if (isBlueprintList(field)) {
2363
- if (field.optional)
2364
- return field;
2365
- const optional = standardListOf({ ...field, optional: true });
2366
- cache2.set(field, optional);
2367
- return optional;
2368
- }
2369
- const Property = field;
2370
- if (Property.type.optional)
2371
- return Property;
2372
- const base = Property.type;
2373
- const SchemaConstructor = schemaOf(base.name, Type2.Optional(base.schema.type.Type()));
2374
- const type = {
2375
- ...base,
2376
- schema: new SchemaConstructor,
2377
- optional: true
2378
- };
2379
- const Optional = derivePropertyOf(Property, type);
2380
- recordPropertyLineage(Optional, { kind: "optional", base: Property });
2381
- cache2.set(Property, Optional);
2382
- return Optional;
2383
- }
2384
-
2385
- // src/core/blueprint/blueprint.ts
2386
- function blueprintBuilderOf(...base) {
2387
- return (sourcesOrDefine, maybeDefine) => {
2388
- const [sources, define] = typeof sourcesOrDefine === "function" ? [[], sourcesOrDefine] : [
2389
- sourcesOrDefine,
2390
- maybeDefine
2391
- ];
2392
- const all = [...base, ...sources];
2393
- return create(all.flatMap((source) => isBlueprint(source) ? source.plugins : [source]), { ...define(contextOf2(all)) });
2394
- };
2395
- }
2396
- function blueprintFromProperties(plugins, properties) {
2397
- return create(plugins, { ...properties });
2398
- }
2399
- function create(plugins, properties) {
2400
- const shape = {};
2401
- for (const [key, field] of Object.entries(properties)) {
2402
- properties[key] = fieldOf(field);
2403
- shape[key] = schemaOfField(key, properties[key]);
2404
- }
2405
- const SchemaConstructor = schemaOf("blueprint", Type3.Object(shape));
2406
- const blueprint = {
2407
- [Kind]: "blueprint",
2408
- plugins: Object.freeze([...new Set(plugins)]),
2409
- properties: Object.freeze(properties),
2410
- schema: new SchemaConstructor,
2411
- optional: false,
2412
- safeParse: (value) => parseCollection(properties, value, [], "blueprint"),
2413
- join: (...others) => create([blueprint, ...others].flatMap((source) => source.plugins), Object.assign({}, ...[blueprint, ...others].map((source) => source.properties)))
2414
- };
2415
- return Object.freeze(withStandard(blueprint, (value) => blueprint.safeParse(value)));
2416
- }
2417
- var HELPERS = { listOf, optionalOf, propertyOf };
2418
- var RESERVED_KEYS = ["optional", "list", ...Object.keys(HELPERS)];
2419
- function contextOf2(sources) {
2420
- for (const key of RESERVED_KEYS) {
2421
- const reserving = sources.find((source) => Object.hasOwn(source.properties, key));
2422
- if (reserving) {
2423
- throw new ReservedBlueprintKey({
2424
- source: isBlueprint(reserving) ? "blueprint" : reserving.name,
2425
- details: { key }
2426
- });
2427
- }
2428
- }
2429
- const factories = Object.assign({}, ...sources.map((source) => isBlueprint(source) ? {} : source.factories ?? {}));
2430
- for (const key of RESERVED_KEYS) {
2431
- if (Object.hasOwn(factories, key)) {
2432
- const reserving = sources.find((source) => !isBlueprint(source) && Object.hasOwn(source.factories ?? {}, key));
2433
- throw new ReservedBlueprintKey({
2434
- source: reserving.name,
2435
- details: { key }
2436
- });
2437
- }
2438
- }
2439
- const available = Object.assign({}, ...sources.map((source) => source.properties));
2440
- for (const key of Object.keys(factories))
2441
- delete available[key];
2442
- const mirror = (fields, map) => Object.fromEntries(Object.entries(fields).map(([key, field]) => [key, map(field)]));
2443
- const list = mirror(available, (field) => listOf(field));
2444
- const callable = (field) => isProperty(field) ? callableOf(field) : field;
2445
- return Object.freeze({
2446
- ...mirror(available, callable),
2447
- ...factories,
2448
- ...HELPERS,
2449
- optional: Object.freeze(mirror(available, (field) => callable(optionalOf(field)))),
2450
- list: Object.freeze({
2451
- ...list,
2452
- optional: Object.freeze(mirror(list, optionalOf))
2453
- })
2454
- });
2455
- }
2456
- function schemaOfField(key, field) {
2457
- if (isBlueprintList(field)) {
2458
- const { item, minItems, maxItems } = field;
2459
- const schema = Type3.Array(schemaOfField(key, item), {
2460
- ...minItems === undefined ? {} : { minItems },
2461
- ...maxItems === undefined ? {} : { maxItems }
2462
- });
2463
- return field.optional ? Type3.Optional(schema) : schema;
2464
- }
2465
- if (isBlueprint(field)) {
2466
- const schema = field.schema.type.Type();
2467
- return field.optional ? Type3.Optional(schema) : schema;
2468
- }
2469
- const record = recordFieldOf(field);
2470
- if (record) {
2471
- const schema = record.record.blueprint.schema.type.Type();
2472
- return record.optional ? Type3.Optional(schema) : schema;
2473
- }
2474
- if (isProperty(field)) {
2475
- return field.type.schema.type.Type();
2476
- }
2477
- throw new UndeclaredBlueprintProperty({
2478
- source: "blueprint",
2479
- details: { key }
2480
- });
2481
- }
2482
- // src/core/blueprint/blueprint-plugin.ts
2483
- function blueprintPluginOf(name, properties, factories = {}) {
2484
- return Object.freeze({
2485
- name,
2486
- properties: Object.freeze({ ...properties }),
2487
- factories: Object.freeze({ ...factories })
2488
- });
2489
- }
2490
- // src/core/blueprint/slice.ts
2491
- function propertiesOfField(field) {
2492
- if (field === undefined)
2493
- return;
2494
- if (isBlueprintList(field))
2495
- return propertiesOfField(field.item);
2496
- const record = recordFieldOf(field);
2497
- if (record)
2498
- return record.record.blueprint.properties;
2499
- return isBlueprint(field) ? field.properties : undefined;
2500
- }
2501
- function maskOf(selector, against) {
2502
- if (isRecordClass(selector))
2503
- return maskOf(selector.blueprint, against);
2504
- if (isBlueprint(selector)) {
2505
- return Object.fromEntries(Object.entries(selector.properties).map(([key, field]) => [key, fieldMaskOf(field, against?.[key])]));
2506
- }
2507
- return selector;
2508
- }
2509
- function fieldMaskOf(field, other) {
2510
- if (isBlueprintList(field)) {
2511
- return fieldMaskOf(field.item, isBlueprintList(other) ? other.item : other);
2512
- }
2513
- const record = recordFieldOf(field);
2514
- if (record) {
2515
- if (record.record === recordFieldOf(other)?.record)
2516
- return true;
2517
- return maskOf(record.record, propertiesOfField(other));
2518
- }
2519
- if (isBlueprint(field)) {
2520
- return field === other ? true : maskOf(field, propertiesOfField(other));
2521
- }
2522
- return true;
2523
- }
2524
- function sliceCollection(properties, mask, path) {
2525
- const sliced = {};
2526
- for (const [key, selected] of Object.entries(mask)) {
2527
- if (!selected)
2528
- continue;
2529
- if (!Object.hasOwn(properties, key)) {
2530
- throw new UndeclaredBlueprintProperty({
2531
- source: "blueprint",
2532
- details: { key: path + key }
2533
- });
2534
- }
2535
- sliced[key] = sliceField(properties[key], selected, path + key);
2536
- }
2537
- return sliced;
2538
- }
2539
- function slicedRecordOf(Original, mask, path) {
2540
- const source = Original.blueprint;
2541
- const blueprint = blueprintFromProperties(source.plugins, sliceCollection(source.properties, mask, `${path}.`));
2542
- const kept = (keys) => keys.filter((key) => Object.hasOwn(blueprint.properties, key));
2543
- const { sensitive, unique, change } = Original.options;
2544
- const Sliced = declareRecord(AbstractRecord, blueprint, {
2545
- sensitive: kept(sensitive),
2546
- unique: kept(unique),
2547
- change: kept(change)
2548
- }, Original.name);
2549
- Object.defineProperty(Sliced, Symbol.hasInstance, {
2550
- value(value) {
2551
- return Function.prototype[Symbol.hasInstance].call(this, value) || value instanceof Original;
2552
- }
2553
- });
2554
- return Sliced;
2555
- }
2556
- function sliceField(field, selected, path) {
2557
- if (selected === true)
2558
- return field;
2559
- if (isBlueprintList(field)) {
2560
- const list = listOf(sliceField(field.item, selected, path), {
2561
- minItems: field.minItems,
2562
- maxItems: field.maxItems
2563
- });
2564
- return field.optional ? optionalOf(list) : list;
2565
- }
2566
- const record = recordFieldOf(field);
2567
- if (record) {
2568
- const sliced = slicedRecordOf(record.record, selected, path);
2569
- return record.optional ? optionalOf(sliced) : sliced;
2570
- }
2571
- if (isBlueprint(field)) {
2572
- const sliced = blueprintFromProperties(field.plugins, sliceCollection(field.properties, selected, `${path}.`));
2573
- return field.optional ? optionalOf(sliced) : sliced;
2574
- }
2575
- throw new UndeclaredBlueprintProperty({
2576
- source: "blueprint",
2577
- details: { key: `${path}.${Object.keys(selected)[0] ?? ""}` }
2578
- });
2579
- }
2580
- var sliceOf = (blueprint, selector) => blueprintFromProperties(blueprint.plugins, sliceCollection(blueprint.properties, maskOf(selector, blueprint.properties), ""));
2581
- var sliceValue = (value, selector) => pick(value, maskOf(selector));
2582
- function pick(value, mask) {
2583
- if (Array.isArray(value))
2584
- return value.map((item) => pick(item, mask));
2585
- if (typeof value !== "object" || value === null)
2586
- return value;
2587
- const source = isRecordClass(value.constructor) ? value.toJSON() : value;
2588
- const picked = {};
2589
- for (const [key, selected] of Object.entries(mask)) {
2590
- if (!selected || !Object.hasOwn(source, key))
2591
- continue;
2592
- picked[key] = selected === true ? source[key] : pick(source[key], selected);
2593
- }
2594
- return picked;
2595
- }
2596
- // src/core/exception/guard.ts
2597
- function guard(scope, run, resolve) {
2598
- const handle = (error) => {
2599
- const exception = Exception.from(error, scope);
2600
- const pass = () => {
2601
- throw exception === error ? exception.propagate(scope) : exception;
2602
- };
2603
- return resolve ? resolve(exception, pass) : pass();
2604
- };
2605
- try {
2606
- const result = run();
2607
- return result instanceof Promise ? result.catch(handle) : result;
2608
- } catch (error) {
2609
- return handle(error);
2610
- }
2611
- }
2612
- // src/core/record/plugin-catalog.ts
2613
- function satisfies(available, requested) {
2614
- const [major, minor, patch] = versionParts(available);
2615
- const [wantedMajor, wantedMinor, wantedPatch] = versionParts(requested);
2616
- if (major !== wantedMajor)
2617
- return false;
2618
- if (major === 0 && minor !== wantedMinor)
2619
- return false;
2620
- if (minor !== wantedMinor)
2621
- return minor > wantedMinor;
2622
- return patch >= wantedPatch;
2623
- }
2624
- var LISTS = ["keys", "sensitive", "unique", "change", "members"];
2625
- function isDescriptor(value) {
2626
- if (typeof value !== "object" || value === null)
2627
- return false;
2628
- const descriptor = value;
2629
- const isList = (list) => Array.isArray(list) && list.every((item) => typeof item === "string");
2630
- return descriptor.kind === "record-plugin" && typeof descriptor.name === "string" && isVersion(descriptor.version) && LISTS.every((list) => isList(descriptor[list])) && Array.isArray(descriptor.requires) && descriptor.requires.every((required) => typeof required === "object" && required !== null && typeof required.name === "string" && isVersion(required.version));
2631
- }
2632
- function mismatchOf(plugin, descriptor) {
2633
- if (!satisfies(plugin.version, descriptor.version)) {
2634
- return `version ${plugin.version} does not satisfy ${descriptor.version}`;
2635
- }
2636
- const current = {
2637
- keys: plugin.keys,
2638
- sensitive: plugin.options.sensitive,
2639
- unique: plugin.options.unique,
2640
- change: plugin.options.change,
2641
- members: plugin.members
2642
- };
2643
- for (const list of LISTS) {
2644
- const missing = descriptor[list].find((item) => !current[list].includes(item));
2645
- if (missing !== undefined)
2646
- return `"${missing}" is not in its ${list}`;
2647
- }
2648
- for (const required of descriptor.requires) {
2649
- const found = plugin.requires.find(({ name }) => name === required.name);
2650
- if (!found)
2651
- return `it does not require "${required.name}"`;
2652
- if (!satisfies(found.version, required.version)) {
2653
- return `its "${required.name}" ${found.version} does not satisfy ${required.version}`;
2654
- }
2655
- }
2656
- return;
2657
- }
2658
- function recordPluginCatalogOf(...plugins) {
2659
- const byName = {};
2660
- for (const plugin of plugins) {
2661
- if (!isRecordPlugin(plugin)) {
2662
- throw new InvalidRecordPlugin({
2663
- source: "catalog",
2664
- details: {
2665
- reason: "a catalog takes plugins made by `recordPluginOf`"
2666
- }
2667
- });
2668
- }
2669
- if (Object.hasOwn(byName, plugin.name)) {
2670
- throw new InvalidRecordPlugin({
2671
- source: plugin.name,
2672
- details: { reason: "the catalog has another plugin with its name" }
2673
- });
2674
- }
2675
- byName[plugin.name] = plugin;
2676
- }
2677
- const find = (name) => {
2678
- const plugin = Object.hasOwn(byName, name) ? byName[name] : undefined;
2679
- if (!plugin) {
2680
- throw new UnknownRecordPlugin({ source: "catalog", details: { name } });
2681
- }
2682
- return plugin;
2683
- };
2684
- const resolve = (reference) => {
2685
- if (typeof reference === "string") {
2686
- const at = reference.lastIndexOf("@");
2687
- if (at <= 0)
2688
- return find(reference);
2689
- const plugin = find(reference.slice(0, at));
2690
- const version = reference.slice(at + 1);
2691
- if (!isVersion(version)) {
2692
- throw new IncompatibleRecordPlugin({
2693
- source: plugin.name,
2694
- details: { reason: `"${version}" is not a semantic version` }
2695
- });
2696
- }
2697
- if (!satisfies(plugin.version, version)) {
2698
- throw new IncompatibleRecordPlugin({
2699
- source: plugin.name,
2700
- details: {
2701
- reason: `version ${plugin.version} does not satisfy ${version}`
2702
- }
2703
- });
2704
- }
2705
- return plugin;
2706
- }
2707
- if (!isDescriptor(reference)) {
2708
- const name = reference?.name;
2709
- throw new IncompatibleRecordPlugin({
2710
- source: typeof name === "string" ? name : "unknown",
2711
- details: { reason: "it is not a record plugin descriptor" }
2712
- });
2713
- }
2714
- const plugin = find(reference.name);
2715
- const reason = mismatchOf(plugin, reference);
2716
- if (reason !== undefined) {
2717
- throw new IncompatibleRecordPlugin({
2718
- source: plugin.name,
2719
- details: { reason }
2720
- });
2721
- }
2722
- return plugin;
2723
- };
2724
- return Object.freeze({
2725
- [Kind]: "record-plugin-catalog",
2726
- plugins: Object.freeze(byName),
2727
- list: Object.freeze([...plugins]),
2728
- resolve,
2729
- resolveAll: (references) => Object.freeze(references.map(resolve))
2730
- });
2731
- }
2732
- // src/core/repository/exceptions.ts
2733
- var InvalidRepositoryDeclaration = exceptionOf({
2734
- layer: "repository" /* Repository */,
2735
- name: "InvalidRepositoryDeclaration",
2736
- message: ({ reason }) => reason
2737
- });
2738
- var InvalidRepositoryEntity = exceptionOf({
2739
- layer: "repository" /* Repository */,
2740
- name: "InvalidRepositoryEntity",
2741
- message: (_details, source) => `"${source}" expected an entity of its own class.`
2742
- });
2743
- var InvalidRepositoryData = exceptionOf({
2744
- layer: "repository" /* Repository */,
2745
- name: "InvalidRepositoryData",
2746
- message: (_details, source) => `"${source}" read a value that its entity rejects.`
2747
- });
2748
- var RepositoryUniqueViolation = exceptionOf({
2749
- layer: "repository" /* Repository */,
2750
- name: "RepositoryUniqueViolation",
2751
- message: ({ key }, source) => `"${source}" already holds an entity with this "${key}".`
2752
- });
2753
- var RepositoryEntityNotFound = exceptionOf({
2754
- layer: "repository" /* Repository */,
2755
- name: "RepositoryEntityNotFound",
2756
- message: ({ id }, source) => `"${source}" holds no entity of id "${id}".`
2757
- });
2758
- // src/core/repository/in-memory.ts
2759
- function same(a, b) {
2760
- if (a === b)
2761
- return true;
2762
- return typeof a === "object" && typeof b === "object" && a !== null && b !== null && JSON.stringify(a) === JSON.stringify(b);
2763
- }
2764
- function idOf(data) {
2765
- return data.id;
2766
- }
2767
- function inMemoryProvider() {
2768
- const tables = new WeakMap;
2769
- const tableOf = (context) => {
2770
- let table = tables.get(context.entity);
2771
- if (!table) {
2772
- table = new Map;
2773
- tables.set(context.entity, table);
2774
- }
2775
- return table;
2776
- };
2777
- const assertUnique = (context, data) => {
2778
- for (const stored of tableOf(context).values()) {
2779
- if (idOf(stored) === idOf(data))
2780
- continue;
2781
- const key = context.unique.find((key) => data[key] !== undefined && same(stored[key], data[key]));
2782
- if (key !== undefined) {
2783
- throw new RepositoryUniqueViolation({
2784
- source: context.name,
2785
- details: { key }
2786
- });
2787
- }
2788
- }
2789
- };
2790
- return Object.freeze({
2791
- async findOne(context, key, value) {
2792
- for (const data of tableOf(context).values()) {
2793
- if (same(data[key], value))
2794
- return data;
2795
- }
2796
- return;
2797
- },
2798
- async findMany(context, key, value) {
2799
- return [...tableOf(context).values()].filter((data) => same(data[key], value));
2800
- },
2801
- async findIn(context, key, values) {
2802
- return [...tableOf(context).values()].filter((data) => values.some((value) => same(data[key], value)));
2803
- },
2804
- async insert(context, data) {
2805
- const table = tableOf(context);
2806
- if (table.has(idOf(data))) {
2807
- throw new RepositoryUniqueViolation({
2808
- source: context.name,
2809
- details: { key: "id" }
2810
- });
2811
- }
2812
- assertUnique(context, data);
2813
- table.set(idOf(data), data);
2814
- },
2815
- async update(context, data) {
2816
- const table = tableOf(context);
2817
- if (!table.has(idOf(data))) {
2818
- throw new RepositoryEntityNotFound({
2819
- source: context.name,
2820
- details: { id: idOf(data) }
2821
- });
2822
- }
2823
- assertUnique(context, data);
2824
- table.set(idOf(data), data);
2825
- },
2826
- async remove(context, id) {
2827
- if (!tableOf(context).delete(id)) {
2828
- throw new RepositoryEntityNotFound({
2829
- source: context.name,
2830
- details: { id }
2831
- });
2832
- }
2833
- },
2834
- async count(context) {
2835
- return tableOf(context).size;
2836
- }
2837
- });
2838
- }
2839
- // src/core/repository/references.ts
2840
- function isPlain(value) {
2841
- return typeof value === "object" && value !== null && !Array.isArray(value);
2842
- }
2843
- function recordClassOf(field) {
2844
- return recordFieldOf(field)?.record;
2845
- }
2846
- function entityClassesOf(properties) {
2847
- const found = new Set;
2848
- function visit(field) {
2849
- if (isBlueprintList(field)) {
2850
- visit(field.item);
2851
- } else if (isBlueprint(field)) {
2852
- walk(field.properties);
2853
- } else {
2854
- const record = recordClassOf(field);
2855
- if (!record)
2856
- return;
2857
- if (isEntityClass(record))
2858
- found.add(record);
2859
- else
2860
- walk(record.blueprint.properties);
2861
- }
2862
- }
2863
- function walk(properties) {
2864
- for (const field of Object.values(properties))
2865
- visit(field);
2866
- }
2867
- walk(properties);
2868
- return found;
2869
- }
2870
- function mapReferences(properties, data, visit) {
2871
- function mapField(field, value) {
2872
- if (value === undefined || value === null)
2873
- return value;
2874
- if (isBlueprintList(field)) {
2875
- return Array.isArray(value) ? Object.freeze(value.map((item) => mapField(field.item, item))) : value;
2876
- }
2877
- if (isBlueprint(field)) {
2878
- return isPlain(value) ? mapCollection(field.properties, value) : value;
2879
- }
2880
- const record = recordClassOf(field);
2881
- if (!record)
2882
- return value;
2883
- if (isEntityClass(record))
2884
- return visit(record, value);
2885
- return isPlain(value) ? mapCollection(record.blueprint.properties, value) : value;
2886
- }
2887
- function mapCollection(properties, value) {
2888
- return Object.freeze(Object.fromEntries(Object.entries(value).map(([key, item]) => [
2889
- key,
2890
- mapField(properties[key], item)
2891
- ])));
2892
- }
2893
- return mapCollection(properties, data);
2894
- }
2895
- function relationsOf(name, entity, relations) {
2896
- const invalid = (reason) => {
2897
- throw new InvalidRepositoryDeclaration({
2898
- source: name,
2899
- details: { reason }
2900
- });
2901
- };
2902
- if (relations === undefined)
2903
- relations = [];
2904
- if (!Array.isArray(relations)) {
2905
- return invalid("Expected relations to be a list of repositories.");
2906
- }
2907
- const related = [];
2908
- for (const relation of relations) {
2909
- const state = findState(relation);
2910
- if (!state)
2911
- return invalid("Expected relations made by repositoryOf.");
2912
- if (related.some((other) => other.entity === state.entity)) {
2913
- return invalid(`Relation "${state.entity.name}" is duplicated.`);
2914
- }
2915
- const { provider } = state;
2916
- if (typeof provider.findIn !== "function" && typeof provider.findOne !== "function") {
2917
- return invalid(`The provider of "${state.name}" has no "findIn" or "findOne" to load it.`);
2918
- }
2919
- related.push(state);
2920
- }
2921
- const used = new Set;
2922
- const map = new Map;
2923
- for (const target of entityClassesOf(entity.blueprint.properties)) {
2924
- const matches = related.filter((state) => state.entity === target || state.entity.prototype instanceof target);
2925
- const exact = matches.find((state) => state.entity === target);
2926
- if (!exact && matches.length === 0) {
2927
- return invalid(`Missing relation: no repository of "${target.name}".`);
2928
- }
2929
- if (!exact && matches.length > 1) {
2930
- return invalid(`Relation "${target.name}" matches more than one repository.`);
2931
- }
2932
- const state = exact ?? matches[0];
2933
- map.set(target, state);
2934
- used.add(state);
2935
- }
2936
- for (const state of related) {
2937
- if (!used.has(state)) {
2938
- return invalid(`Relation "${state.entity.name}" is not held by ${entity.name}.`);
2939
- }
2940
- }
2941
- return map;
2942
- }
2943
- function parseEntity(state, data) {
2944
- const parsed = state.entity.safeParse(data);
2945
- if (parsed.issues) {
2946
- throw new InvalidRepositoryData({
2947
- source: state.name,
2948
- cause: parsed.issues.find((issue) => issue.cause)?.cause
2949
- });
2950
- }
2951
- return parsed.value;
2952
- }
2953
- async function loadByIds(state, ids) {
2954
- const context = contextOf(state);
2955
- const { provider } = state;
2956
- if (typeof provider.findIn === "function") {
2957
- return provider.findIn(context, "id", ids);
2958
- }
2959
- const found = await Promise.all(ids.map((id) => provider.findOne(context, "id", id)));
2960
- return found.filter((data) => data !== undefined);
2961
- }
2962
- async function resolveReferences(state, datas, session) {
2963
- if (state.relations.size === 0)
2964
- return datas;
2965
- const { properties } = state.entity.blueprint;
2966
- const wanted = new Map;
2967
- for (const data of datas) {
2968
- mapReferences(properties, data, (target, value) => {
2969
- const relation = state.relations.get(target);
2970
- if (relation && typeof value === "string") {
2971
- const ids = wanted.get(relation) ?? new Set;
2972
- wanted.set(relation, ids.add(value));
2973
- }
2974
- return value;
2975
- });
2976
- }
2977
- for (const [relation, ids] of wanted) {
2978
- const loaded = session.get(relation) ?? new Map;
2979
- session.set(relation, loaded);
2980
- const missing = [...ids].filter((id) => !loaded.has(id));
2981
- if (missing.length === 0)
2982
- continue;
2983
- const found = await loadByIds(relation, missing);
2984
- const resolved = await resolveReferences(relation, found, session);
2985
- for (const data of resolved) {
2986
- const id = data.id;
2987
- if (!loaded.has(id))
2988
- loaded.set(id, parseEntity(relation, data));
2989
- }
2990
- for (const id of missing) {
2991
- if (loaded.has(id))
2992
- continue;
2993
- throw new InvalidRepositoryData({
2994
- source: state.name,
2995
- cause: new RepositoryEntityNotFound({
2996
- source: relation.name,
2997
- details: { id }
2998
- })
2999
- });
3000
- }
3001
- }
3002
- return datas.map((data) => mapReferences(properties, data, (target, value) => {
3003
- const relation = state.relations.get(target);
3004
- return relation && typeof value === "string" ? session.get(relation)?.get(value) ?? value : value;
3005
- }));
3006
- }
3007
-
3008
- // src/core/repository/repository.ts
3009
- var REFERENCES = {
3010
- reference: (record) => isEntity(record) ? record.id : undefined
3011
- };
3012
-
3013
- class AbstractRepository {
3014
- get [Kind]() {
3015
- return "repository";
3016
- }
3017
- get entity() {
3018
- return stateOf(this).entity;
3019
- }
3020
- get actions() {
3021
- return stateOf(this).actions;
3022
- }
3023
- get provider() {
3024
- return stateOf(this).provider;
3025
- }
3026
- get context() {
3027
- return contextOf(stateOf(this));
3028
- }
3029
- get env() {
3030
- return this.context.env;
3031
- }
3032
- async hydrate(data) {
3033
- return (await this.hydrateMany([data]))[0];
3034
- }
3035
- async hydrateMany(list) {
3036
- const state = stateOf(this);
3037
- const resolved = await resolveReferences(state, list, new Map);
3038
- return resolved.map((data) => parseEntity(state, data));
3039
- }
3040
- dataOf(entity) {
3041
- if (!(entity instanceof stateOf(this).entity)) {
3042
- throw new InvalidRepositoryEntity({ source: stateOf(this).name });
3043
- }
3044
- return recordDataOf(entity, REFERENCES);
3045
- }
3046
- }
3047
- function action(method) {
3048
- return function(...args) {
3049
- return guard({ layer: "repository" /* Repository */, source: stateOf(this).name }, () => method(this, ...args));
3050
- };
3051
- }
3052
- function queryOf(context, key, value) {
3053
- const properties = context.entity.blueprint.properties;
3054
- return recordFieldDataOf(properties[key], value, REFERENCES);
3055
- }
3056
- var findBy = (key) => action(async (self, value) => {
3057
- const data = await self.provider.findOne(self.context, key, queryOf(self.context, key, value));
3058
- return data === undefined ? undefined : await self.hydrate(data);
3059
- });
3060
- var findManyBy = (key) => action(async (self, value) => {
3061
- const list = await self.provider.findMany(self.context, key, queryOf(self.context, key, value));
3062
- return self.hydrateMany(list);
3063
- });
3064
- var create2 = action(async (self, input) => {
3065
- const { entity: Entity } = self.context;
3066
- const entity = input instanceof Entity ? input : new Entity(input);
3067
- await self.provider.insert(self.context, self.dataOf(entity));
3068
- return entity;
3069
- });
3070
- var update = action(async (self, entity) => {
3071
- await self.provider.update(self.context, self.dataOf(entity));
3072
- return entity;
3073
- });
3074
- var remove = action(async (self, target) => {
3075
- const { context } = self;
3076
- let entity = target;
3077
- if (typeof target === "string") {
3078
- const data = await self.provider.findOne(context, "id", target);
3079
- if (data === undefined) {
3080
- throw new RepositoryEntityNotFound({
3081
- source: context.name,
3082
- details: { id: target }
3083
- });
3084
- }
3085
- entity = await self.hydrate(data);
3086
- }
3087
- const data = self.dataOf(entity);
3088
- const destroyable = entity;
3089
- if (!destroyable.isDeleted)
3090
- destroyable.destroy();
3091
- await self.provider.remove(context, data.id);
3092
- return entity;
3093
- });
3094
- var count = action(async (self) => self.provider.count(self.context));
3095
- var NEEDS = {
3096
- findBy: ["findOne"],
3097
- findManyBy: ["findMany"],
3098
- create: ["insert"],
3099
- update: ["update"],
3100
- delete: ["findOne", "remove"],
3101
- count: ["count"]
3102
- };
3103
- function capitalize(key) {
3104
- return `${key.charAt(0).toUpperCase()}${key.slice(1)}`;
3105
- }
3106
- function unknownAction(entity, action, methods) {
3107
- const many = /^findManyBy(.+)$/.exec(action)?.[1];
3108
- const one = many === undefined ? /^findBy(.+)$/.exec(action)?.[1] : undefined;
3109
- const suffix = many ?? one;
3110
- const key = suffix === undefined ? undefined : `${suffix.charAt(0).toLowerCase()}${suffix.slice(1)}`;
3111
- if (one !== undefined && methods.has(`findManyBy${one}`)) {
3112
- return `"${action}" requires "${key}" to be a unique key of ${entity}.`;
3113
- }
3114
- if (many !== undefined && methods.has(`findBy${many}`)) {
3115
- return `"${action}" is not available for the unique key "${key}" of ${entity}; use "findBy${many}".`;
3116
- }
3117
- return `"${action}" is not an action of ${entity}.`;
3118
- }
3119
- function invalid2(source, reason) {
3120
- throw new InvalidRepositoryDeclaration({ source, details: { reason } });
3121
- }
3122
- function repositoryOf(settings) {
3123
- const { entity, actions, environmentDependencies } = settings ?? {};
3124
- if (!isEntityClass(entity) || !(EntityUniqueKeys in entity)) {
3125
- invalid2("repositoryOf", "Expected an entity class made by entityOf.");
3126
- }
3127
- const name = `${entity.name}Repository`;
3128
- const provider = settings.provider ?? inMemoryProvider();
3129
- if (!Array.isArray(actions) || actions.length === 0) {
3130
- invalid2(name, "Expected a list of actions.");
3131
- }
3132
- if (environmentDependencies !== undefined && !isEnvironment(environmentDependencies) && !(Array.isArray(environmentDependencies) && environmentDependencies.every(isEnvironment))) {
3133
- invalid2(name, "Expected environments made by environmentOf.");
3134
- }
3135
- const relations = relationsOf(name, entity, settings.relations);
3136
- const unique = entity[EntityUniqueKeys];
3137
- const methods = new Map;
3138
- for (const key of Object.keys(entity.blueprint.properties)) {
3139
- const suffix = capitalize(key);
3140
- if (unique.includes(key)) {
3141
- methods.set(`findBy${suffix}`, ["findBy", findBy(key)]);
3142
- } else {
3143
- methods.set(`findManyBy${suffix}`, ["findManyBy", findManyBy(key)]);
3144
- }
3145
- }
3146
- methods.set("create", ["create", create2]);
3147
- methods.set("update", ["update", update]);
3148
- methods.set("delete", ["delete", remove]);
3149
- methods.set("count", ["count", count]);
3150
-
3151
- class DeclaredRepository extends AbstractRepository {
3152
- }
3153
- for (const name_ of new Set(actions)) {
3154
- const method = typeof name_ === "string" ? methods.get(name_) : undefined;
3155
- if (!method)
3156
- invalid2(name, unknownAction(entity.name, String(name_), methods));
3157
- const [kind, implementation] = method;
3158
- for (const need of NEEDS[kind] ?? []) {
3159
- if (typeof provider?.[need] !== "function") {
3160
- invalid2(name, `The provider has no "${need}" for "${name_}".`);
3161
- }
3162
- }
3163
- Object.defineProperty(DeclaredRepository.prototype, name_, {
3164
- value: implementation,
3165
- writable: true,
3166
- configurable: true
3167
- });
3168
- }
3169
- Object.defineProperty(DeclaredRepository, "name", { value: name });
3170
- states.set(DeclaredRepository, {
3171
- name,
3172
- entity,
3173
- actions: Object.freeze([...new Set(actions)]),
3174
- provider,
3175
- explicitProvider: settings.provider !== undefined,
3176
- environment: environmentDependencies,
3177
- relations
3178
- });
3179
- return Object.freeze(new DeclaredRepository);
3180
- }
3181
- function RepositoryOf(repository) {
3182
- if (!isRepository(repository)) {
3183
- invalid2("RepositoryOf", "Expected a repository made by repositoryOf.");
3184
- }
3185
- return repository.constructor;
3186
- }
3187
- function isRepository(value) {
3188
- return value instanceof AbstractRepository;
3189
- }
3190
- // src/core/use-case/use-case.ts
3191
- var InvalidUseCaseDeclaration = exceptionOf({
3192
- layer: "use-case" /* UseCase */,
3193
- name: "InvalidUseCaseDeclaration",
3194
- message: ({ reason }) => reason
3195
- });
3196
- var UseCaseAlreadyExecuted = exceptionOf({
3197
- layer: "use-case" /* UseCase */,
3198
- name: "UseCaseAlreadyExecuted",
3199
- message: "A UseCase instance can execute only once."
3200
- });
3201
- var InvalidUseCaseDependencies = exceptionOf({
3202
- layer: "use-case" /* UseCase */,
3203
- name: "InvalidUseCaseDependencies",
3204
- message: "Dependency overrides must contain only declared names: functions for use cases, objects of methods for repositories, and valid variables for environments."
3205
- });
3206
- var states2 = new WeakMap;
3207
- function invalidValue(issues, source, phase) {
3208
- throw new Exception({
3209
- layer: "use-case" /* UseCase */,
3210
- name: phase === "input" ? "InvalidUseCaseInput" : "InvalidUseCaseResponse",
3211
- source,
3212
- message: `Invalid UseCase ${phase}.`,
3213
- details: { issues },
3214
- cause: issues.find((issue) => issue.cause)?.cause
3215
- });
3216
- }
3217
- function collectEvents(blueprint, value, events) {
3218
- const visited = new WeakSet;
3219
- const visit = (field, current) => {
3220
- if (typeof current !== "object" || current === null || visited.has(current))
3221
- return;
3222
- visited.add(current);
3223
- if (isEntity(current))
3224
- events.push(...current.pullEvents());
3225
- if (isBlueprintList(field)) {
3226
- for (const item of current)
3227
- visit(field.item, item);
3228
- return;
3229
- }
3230
- const shape = isBlueprint(field) ? field : recordFieldOf(field)?.record.blueprint;
3231
- if (!shape)
3232
- return;
3233
- for (const [key, child] of Object.entries(shape.properties)) {
3234
- visit(child, current[key]);
3235
- }
3236
- };
3237
- visit(blueprint, value);
3238
- }
3239
- function pullEntities(value, Entity, events) {
3240
- for (const item of Array.isArray(value) ? value : [value]) {
3241
- if (isEntity(item) && item instanceof Entity) {
3242
- events.push(...item.pullEvents());
3243
- }
3244
- }
3245
- }
3246
- function methodNamesOf(repository) {
3247
- const names = new Set;
3248
- for (let current = repository;current !== null && current !== AbstractRepository.prototype && current !== Object.prototype; current = Object.getPrototypeOf(current)) {
3249
- for (const name of Object.getOwnPropertyNames(current)) {
3250
- const descriptor = Object.getOwnPropertyDescriptor(current, name);
3251
- if (name !== "constructor" && typeof descriptor?.value === "function") {
3252
- names.add(name);
3253
- }
3254
- }
3255
- }
3256
- return [...names];
3257
- }
3258
- function bindRepository2(repository, overrides, state, source) {
3259
- const Entity = repository.entity;
3260
- const bound = Object.create(null);
3261
- const view = new Proxy(Object.create(repository), {
3262
- get: (_target, key, receiver) => typeof key === "string" && Object.hasOwn(bound, key) ? bound[key] : Reflect.get(repository, key, receiver),
3263
- set: (_target, key, value) => Reflect.set(repository, key, value),
3264
- defineProperty: (_target, key, descriptor) => Reflect.defineProperty(repository, key, descriptor),
3265
- deleteProperty: (_target, key) => Reflect.deleteProperty(repository, key)
3266
- });
3267
- const bind = (target, name, receiver) => {
3268
- const method = target[name];
3269
- bound[name] = async (...args) => {
3270
- if (!state.active)
3271
- throw new InvalidUseCaseDependencies({ source });
3272
- const result = await method.apply(receiver, args);
3273
- for (const arg of args)
3274
- pullEntities(arg, Entity, state.events);
3275
- pullEntities(result, Entity, state.events);
3276
- return result;
3277
- };
3278
- };
3279
- for (const name of methodNamesOf(repository))
3280
- bind(repository, name, view);
3281
- if (overrides) {
3282
- for (const name of new Set([
3283
- ...methodNamesOf(repository),
3284
- ...methodNamesOf(overrides)
3285
- ])) {
3286
- if (typeof overrides[name] === "function") {
3287
- bind(overrides, name, overrides);
3288
- }
3289
- }
3290
- }
3291
- bound.entity = Entity;
3292
- bound.actions = repository.actions;
3293
- return Object.freeze(bound);
3294
- }
3295
- function isOverrideOf(dependency, value) {
3296
- if (isRepository(dependency) || isEnvironment(dependency)) {
3297
- return typeof value === "object" && value !== null && !Array.isArray(value);
3298
- }
3299
- return typeof value === "function";
3300
- }
3301
-
3302
- class AbstractUseCase {
3303
- input;
3304
- constructor(input) {
3305
- const declaration = this.constructor;
3306
- const source = declaration.useCaseName;
3307
- const parsed = declaration.blueprint.safeParse(input);
3308
- if (parsed.issues)
3309
- invalidValue(parsed.issues, source, "input");
3310
- this.input = parsed.value;
3311
- Object.defineProperty(this, "input", {
3312
- writable: false,
3313
- configurable: false
3314
- });
3315
- const implementation = this.execute;
3316
- if (typeof implementation !== "function") {
3317
- throw new InvalidUseCaseDeclaration({
3318
- source,
3319
- details: { reason: "Implement execute as a prototype method." }
3320
- });
3321
- }
3322
- const state = {
3323
- started: false,
3324
- active: false,
3325
- events: [],
3326
- dependencies: Object.create(null)
3327
- };
3328
- states2.set(this, state);
3329
- for (const [key, dependency] of Object.entries(declaration.dependencies)) {
3330
- if (isRepository(dependency)) {
3331
- state.dependencies[key] = bindRepository2(dependency, undefined, state, source);
3332
- continue;
3333
- }
3334
- if (isEnvironment(dependency)) {
3335
- Object.defineProperty(state.dependencies, key, {
3336
- get: () => dependency.load(),
3337
- enumerable: true
3338
- });
3339
- continue;
3340
- }
3341
- const Child = dependency;
3342
- state.dependencies[key] = async (value) => {
3343
- if (!state.active)
3344
- throw new InvalidUseCaseDependencies({ source });
3345
- const child = new Child(value);
3346
- try {
3347
- return await child.execute();
3348
- } finally {
3349
- state.events.push(...child.pullEvents());
3350
- }
3351
- };
3352
- }
3353
- Object.freeze(state.dependencies);
3354
- Object.defineProperty(this, "execute", {
3355
- value: async (overrides = {}) => {
3356
- if (state.started)
3357
- throw new UseCaseAlreadyExecuted({ source });
3358
- state.started = true;
3359
- if (typeof overrides !== "object" || overrides === null || Array.isArray(overrides) || Reflect.ownKeys(overrides).some((key) => typeof key !== "string" || !Object.hasOwn(declaration.dependencies, key) || !isOverrideOf(declaration.dependencies[key], overrides[key]))) {
3360
- throw new InvalidUseCaseDependencies({ source });
3361
- }
3362
- const replaced = overrides;
3363
- const dependencies = {};
3364
- for (const key of Object.keys(declaration.dependencies)) {
3365
- if (!Object.hasOwn(replaced, key)) {
3366
- dependencies[key] = state.dependencies[key];
3367
- }
3368
- }
3369
- for (const [key, substitute] of Object.entries(replaced)) {
3370
- const dependency = declaration.dependencies[key];
3371
- if (isRepository(dependency)) {
3372
- dependencies[key] = bindRepository2(dependency, substitute, state, source);
3373
- continue;
3374
- }
3375
- if (isEnvironment(dependency)) {
3376
- const parsed = dependency.blueprint.safeParse(substitute);
3377
- if (parsed.issues)
3378
- throw new InvalidUseCaseDependencies({ source });
3379
- dependencies[key] = Object.freeze(parsed.value);
3380
- continue;
3381
- }
3382
- const Child = dependency;
3383
- dependencies[key] = async (value) => {
3384
- if (!state.active)
3385
- throw new InvalidUseCaseDependencies({ source });
3386
- const childSource = Child.useCaseName;
3387
- const input = Child.blueprint.safeParse(value);
3388
- if (input.issues)
3389
- invalidValue(input.issues, childSource, "input");
3390
- const output = Child.response.safeParse(await guard({ layer: "use-case" /* UseCase */, source: childSource }, () => substitute(input.value)));
3391
- if (output.issues)
3392
- invalidValue(output.issues, childSource, "response");
3393
- collectEvents(Child.response, output.value, state.events);
3394
- return output.value;
3395
- };
3396
- }
3397
- state.resolved = Object.freeze(dependencies);
3398
- state.active = true;
3399
- try {
3400
- const result = await guard({ layer: "use-case" /* UseCase */, source }, () => implementation.call(this, state.resolved));
3401
- const parsed = declaration.response.safeParse(result);
3402
- if (parsed.issues)
3403
- invalidValue(parsed.issues, source, "response");
3404
- collectEvents(declaration.response, parsed.value, state.events);
3405
- return parsed.value;
3406
- } finally {
3407
- state.active = false;
3408
- state.resolved = undefined;
3409
- }
3410
- }
3411
- });
3412
- }
3413
- get dependencies() {
3414
- const state = states2.get(this);
3415
- return state?.resolved ?? state?.dependencies;
3416
- }
3417
- pullEvents() {
3418
- return states2.get(this)?.events.splice(0) ?? [];
3419
- }
3420
- }
3421
- function useCaseOf(settings) {
3422
- const { name, blueprint, response } = settings;
3423
- const dependencies = settings.dependencies === undefined ? {} : settings.dependencies;
3424
- if (typeof name !== "string" || !name.trim() || !isBlueprint(blueprint) || blueprint.optional || !isBlueprint(response) || response.optional || typeof dependencies !== "object" || dependencies === null || Array.isArray(dependencies) || Reflect.ownKeys(dependencies).some((key) => typeof key !== "string" || !isDependency(dependencies[key]))) {
3425
- throw new InvalidUseCaseDeclaration({
3426
- source: typeof name === "string" ? name : "useCaseOf",
3427
- details: {
3428
- reason: "Expected a name, input and response blueprints, and UseCase classes, repositories or environments as dependencies."
3429
- }
3430
- });
3431
- }
3432
-
3433
- class DeclaredUseCase extends AbstractUseCase {
3434
- static [Kind] = "use-case";
3435
- static useCaseName = name;
3436
- static blueprint = blueprint;
3437
- static response = response;
3438
- static dependencies = Object.freeze({
3439
- ...dependencies
3440
- });
3441
- }
3442
- Object.defineProperty(DeclaredUseCase, "name", { value: name });
3443
- return DeclaredUseCase;
3444
- }
3445
- function isDependency(value) {
3446
- return isUseCaseClass(value) || isRepository(value) || isEnvironment(value);
3447
- }
3448
- function isUseCaseClass(value) {
3449
- return typeof value === "function" && value.prototype instanceof AbstractUseCase && value[Kind] === "use-case" && typeof value.prototype.execute === "function";
3450
- }
3451
- function isUseCase(value) {
3452
- return value instanceof AbstractUseCase;
3453
- }
3454
- // src/std/properties/contact.ts
3455
- import { Type as Type4 } from "typebox";
3456
- var Email = propertyOf({
3457
- name: "email",
3458
- schema: Type4.String({ format: "email", maxLength: 254 }),
3459
- default: "demo@example.com",
3460
- preHandle: (value) => value.trim().toLowerCase()
3461
- });
3462
- var Phone = propertyOf({
3463
- name: "phone",
3464
- schema: Type4.String({ pattern: "^\\+[1-9]\\d{1,14}$" }),
3465
- default: "+5511999999999",
3466
- preHandle: (value) => value.replace(/[\s().-]/g, "")
3467
- });
3468
- var Url = propertyOf({
3469
- name: "url",
3470
- schema: Type4.String({ format: "url", maxLength: 2048 }),
3471
- default: "https://example.com",
3472
- preHandle: (value) => value.trim()
3473
- });
3474
- var Ip = propertyOf({
3475
- name: "ip",
3476
- schema: Type4.Union([
3477
- Type4.String({ format: "ipv4" }),
3478
- Type4.String({ format: "ipv6" })
3479
- ]),
3480
- default: "127.0.0.1",
3481
- preHandle: (value) => value.trim()
3482
- });
3483
-
3484
- // src/std/properties/enum.ts
3485
- import { Type as Type5 } from "typebox";
3486
- function enumOf(values, {
3487
- name = "enum",
3488
- optional,
3489
- default: _default = values[0]
3490
- } = {}) {
3491
- const Enum = propertyOf({
3492
- name,
3493
- schema: Type5.Enum(values),
3494
- optional,
3495
- default: _default
3496
- });
3497
- recordPropertyLineage(Enum, {
3498
- kind: "factory",
3499
- factory: "enumOf",
3500
- args: Object.freeze({
3501
- values: Object.freeze([...values]),
3502
- ...name === "enum" ? {} : { name },
3503
- ...optional ? { optional: true } : {},
3504
- ..._default === values[0] ? {} : { default: _default }
3505
- })
3506
- });
3507
- return Enum;
3508
- }
3509
-
3510
- // src/std/properties/headless.ts
3511
- import { Type as Type6 } from "typebox";
3512
- import { Meta } from "typebox/schema";
3513
- var JSON_SCHEMA = Type6.Unsafe({
3514
- type: "object",
3515
- allOf: [Meta["https://json-schema.org/draft/2020-12/schema"]]
3516
- });
3517
-
3518
- class SchemaProperty extends propertyOf({
3519
- name: "schema",
3520
- schema: JSON_SCHEMA,
3521
- default: Type6.String()
3522
- }) {
3523
- compiled;
3524
- static deserialize(json) {
3525
- let value;
3526
- try {
3527
- value = JSON.parse(json);
3528
- } catch (error) {
3529
- throw new InvalidPropertyValue({
3530
- source: "schema",
3531
- details: { errors: [error.message] }
3532
- });
3533
- }
3534
- return new SchemaProperty(value);
3535
- }
3536
- serialize() {
3537
- return JSON.stringify(this.value);
3538
- }
3539
- match(data) {
3540
- return this.toSchema().match(data);
3541
- }
3542
- errors(data) {
3543
- return this.toSchema().errors(data);
3544
- }
3545
- toSchema() {
3546
- if (!this.compiled) {
3547
- const Schema = schemaOf("schema", this.value);
3548
- this.compiled = new Schema;
3549
- }
3550
- return this.compiled;
3551
- }
3552
- }
3553
-
3554
- // src/std/properties/identity.ts
3555
- import slugify from "slugify";
3556
- import { Type as Type7 } from "typebox";
3557
-
3558
- // src/std/runtime.ts
3559
- var PasswordHasherRequired = exceptionOf({
3560
- layer: "property" /* Property */,
3561
- name: "PasswordHasherRequired",
3562
- message: "No password hasher is available: this runtime has neither Bun.password nor native argon2 (node:crypto, Node >= 24.7). Call configure({ hasher }) with your own PasswordHasher."
3563
- });
3564
- var SyncVerifyUnsupported = exceptionOf({
3565
- layer: "property" /* Property */,
3566
- name: "SyncVerifyUnsupported",
3567
- message: "The configured password hasher has no verifySync. Use verify, or configure a hasher that provides verifySync."
3568
- });
3569
- var UnsupportedPasswordHash = exceptionOf({
3570
- layer: "property" /* Property */,
3571
- name: "UnsupportedPasswordHash",
3572
- message: ({ version }) => `The password hash uses argon2 version ${version}, but native argon2 (node:crypto) only derives version ${ARGON2_VERSION}. Verify it with Bun.password or configure({ hasher }).`
3573
- });
3574
- var ARGON2_VERSION = 19;
3575
- var ARGON2_PARAMS = {
3576
- memory: 65536,
3577
- passes: 2,
3578
- parallelism: 1,
3579
- tagLength: 32,
3580
- saltLength: 32,
3581
- version: ARGON2_VERSION
3582
- };
3583
- var toBase64 = (bytes) => btoa(Array.from(bytes, (byte) => String.fromCharCode(byte)).join("")).replace(/=+$/, "");
3584
- var fromBase64 = (text) => Uint8Array.from(atob(text), (char) => char.charCodeAt(0));
3585
- function encodePhc(salt, tag) {
3586
- const { memory, passes, parallelism, version } = ARGON2_PARAMS;
3587
- return `$argon2id$v=${version}$m=${memory},t=${passes},p=${parallelism}$${toBase64(salt)}$${toBase64(tag)}`;
3588
- }
3589
- var PHC = /^\$argon2id\$v=(\d+)\$m=(\d+),t=(\d+),p=(\d+)\$([A-Za-z0-9+/]+)\$([A-Za-z0-9+/]+)$/;
3590
- function decodePhc(phc) {
3591
- const match = PHC.exec(phc);
3592
- if (!match)
3593
- return;
3594
- return {
3595
- version: Number(match[1]),
3596
- memory: Number(match[2]),
3597
- passes: Number(match[3]),
3598
- parallelism: Number(match[4]),
3599
- salt: fromBase64(match[5]),
3600
- tag: fromBase64(match[6])
3601
- };
3602
- }
3603
- function nodeHasherOf(crypto) {
3604
- const { argon2, argon2Sync, randomBytes, timingSafeEqual } = crypto;
3605
- if (!argon2 || !argon2Sync || !randomBytes || !timingSafeEqual) {
3606
- return;
3607
- }
3608
- const derive = (parameters) => new Promise((resolve, reject) => {
3609
- argon2("argon2id", parameters, (error, key) => error ? reject(error) : resolve(key));
3610
- });
3611
- const parametersOf = (plain, parsed) => ({
3612
- message: plain,
3613
- nonce: parsed.salt,
3614
- parallelism: parsed.parallelism,
3615
- tagLength: parsed.tag.length,
3616
- memory: parsed.memory,
3617
- passes: parsed.passes
3618
- });
3619
- const decode = (hash) => {
3620
- const parsed = decodePhc(hash);
3621
- if (parsed && parsed.version !== ARGON2_VERSION) {
3622
- throw new UnsupportedPasswordHash({
3623
- source: "password",
3624
- details: { version: parsed.version }
3625
- });
3626
- }
3627
- return parsed;
3628
- };
3629
- const matches = (tag, expected) => tag.length === expected.length && timingSafeEqual(tag, expected);
3630
- return {
3631
- async hash(plain) {
3632
- const salt = randomBytes(ARGON2_PARAMS.saltLength);
3633
- const tag = await derive({
3634
- message: plain,
3635
- nonce: salt,
3636
- parallelism: ARGON2_PARAMS.parallelism,
3637
- tagLength: ARGON2_PARAMS.tagLength,
3638
- memory: ARGON2_PARAMS.memory,
3639
- passes: ARGON2_PARAMS.passes
3640
- });
3641
- return encodePhc(salt, tag);
3642
- },
3643
- async verify(plain, hash) {
3644
- const parsed = decode(hash);
3645
- if (!parsed)
3646
- return false;
3647
- return matches(await derive(parametersOf(plain, parsed)), parsed.tag);
3648
- },
3649
- verifySync(plain, hash) {
3650
- const parsed = decode(hash);
3651
- if (!parsed)
3652
- return false;
3653
- const tag = argon2Sync("argon2id", parametersOf(plain, parsed));
3654
- return matches(tag, parsed.tag);
3655
- }
3656
- };
3657
- }
3658
- function bunHasherOf(password) {
3659
- return {
3660
- hash: (plain) => password.hash(plain, { algorithm: "argon2id" }),
3661
- verify: (plain, hash) => password.verify(plain, hash),
3662
- verifySync: (plain, hash) => password.verifySync(plain, hash)
3663
- };
3664
- }
3665
- function missingHasher() {
3666
- return {
3667
- hash: () => Promise.reject(new PasswordHasherRequired({ source: "password" })),
3668
- verify: () => Promise.reject(new PasswordHasherRequired({ source: "password" })),
3669
- verifySync: () => {
3670
- throw new PasswordHasherRequired({ source: "password" });
3671
- }
3672
- };
3673
- }
3674
- function defaultHasherOf(environment) {
3675
- if (environment.bun?.password) {
3676
- return bunHasherOf(environment.bun.password);
3677
- }
3678
- const node = environment.crypto && nodeHasherOf(environment.crypto);
3679
- return node ?? missingHasher();
3680
- }
3681
- var lastTimestamp = 0;
3682
- var sequence = 0;
3683
- function uuidv7(now = Date.now()) {
3684
- const random = globalThis.crypto.getRandomValues(new Uint8Array(10));
3685
- const start = random[8] << 8 | random[9];
3686
- if (now > lastTimestamp) {
3687
- lastTimestamp = now;
3688
- sequence = start & 2047;
3689
- } else if (sequence < 4095) {
3690
- sequence++;
3691
- } else {
3692
- lastTimestamp++;
3693
- sequence = start & 2047;
3694
- }
3695
- const bytes = new Uint8Array(16);
3696
- const view = new DataView(bytes.buffer);
3697
- view.setUint16(0, Math.floor(lastTimestamp / 2 ** 32));
3698
- view.setUint32(2, lastTimestamp % 2 ** 32);
3699
- view.setUint16(6, 28672 | sequence);
3700
- bytes.set(random.subarray(0, 8), 8);
3701
- bytes[8] = bytes[8] & 63 | 128;
3702
- const hex = Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0"));
3703
- return [
3704
- hex.slice(0, 4),
3705
- hex.slice(4, 6),
3706
- hex.slice(6, 8),
3707
- hex.slice(8, 10),
3708
- hex.slice(10)
3709
- ].map((part) => part.join("")).join("-");
3710
- }
3711
- var hasher;
3712
- var idGenerator = () => uuidv7();
3713
- function configure(services) {
3714
- if (services.hasher)
3715
- hasher = services.hasher;
3716
- if (services.idGenerator)
3717
- idGenerator = services.idGenerator;
3718
- }
3719
- function resetRuntime() {
3720
- hasher = undefined;
3721
- idGenerator = () => uuidv7();
3722
- lastTimestamp = 0;
3723
- sequence = 0;
3724
- }
3725
- function nodeCryptoOf() {
3726
- const process = globalThis.process;
3727
- return process?.getBuiltinModule?.("node:crypto");
3728
- }
3729
- function currentHasher() {
3730
- hasher ??= defaultHasherOf({
3731
- bun: globalThis.Bun,
3732
- crypto: nodeCryptoOf()
3733
- });
3734
- return hasher;
3735
- }
3736
- function generateId() {
3737
- return idGenerator();
3738
- }
3739
- function verifySyncWithCurrent(plain, hash) {
3740
- const current = currentHasher();
3741
- if (!current.verifySync)
3742
- throw new SyncVerifyUnsupported({ source: "password" });
3743
- return current.verifySync(plain, hash);
3744
- }
3745
-
3746
- // src/std/properties/identity.ts
3747
- var UUID_V7 = "^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$";
3748
-
3749
- class Id extends propertyOf({
3750
- name: "id",
3751
- schema: Type7.String({ pattern: UUID_V7 }),
3752
- default: "01a173d2-051c-77bb-8166-a371e999573e",
3753
- preHandle: (value) => value.toLowerCase()
3754
- }) {
3755
- static generate() {
3756
- return new Id(generateId());
3757
- }
3758
- }
3759
-
3760
- class Slug extends propertyOf({
3761
- name: "slug",
3762
- schema: Type7.String({
3763
- pattern: "^[a-z0-9]+(?:-[a-z0-9]+)*$",
3764
- maxLength: 255
3765
- }),
3766
- default: "demo-slug",
3767
- unique: true,
3768
- preHandle: (value) => slugify(value, { lower: true, strict: true, trim: true })
3769
- }) {
3770
- }
3771
-
3772
- // src/std/properties/password.ts
3773
- import { Type as Type8 } from "typebox";
3774
- var PASSWORD_MIN_LENGTH = 7;
3775
- var PASSWORD_MAX_LENGTH = 128;
3776
- var PASSWORD_SPECIAL_CHARACTERS = "!@#$%^&*()-_=+[]{}|\\;:'\",.<>/?`~";
3777
- var ARGON2_HASH = "^\\$argon2(id|i|d)\\$v=\\d+\\$m=\\d+,t=\\d+,p=\\d+\\$[A-Za-z0-9+/]+\\$[A-Za-z0-9+/]+$";
3778
- var DEMO_HASH = "$argon2id$v=19$m=65536,t=2,p=1$YO5NNmxyK9+adO95GxWsAaUX4TULmT3IGhTYfpshXl0$/C89OCh7bhDY2cR2UkgvOV3dPlkghNLhv/DJsdopwMo";
3779
- function isPasswordHash(value) {
3780
- return new RegExp(ARGON2_HASH).test(value);
3781
- }
3782
- function passwordIssues(value) {
3783
- const issues = [];
3784
- if (value.length < PASSWORD_MIN_LENGTH) {
3785
- issues.push(`must have at least ${PASSWORD_MIN_LENGTH} characters`);
3786
- }
3787
- if (value.length > PASSWORD_MAX_LENGTH) {
3788
- issues.push(`must have at most ${PASSWORD_MAX_LENGTH} characters`);
3789
- }
3790
- if (!/[a-z]/.test(value))
3791
- issues.push("must contain a lowercase letter");
3792
- if (!/[A-Z]/.test(value))
3793
- issues.push("must contain an uppercase letter");
3794
- if (!/\d/.test(value))
3795
- issues.push("must contain a number");
3796
- if (![...value].some((char) => PASSWORD_SPECIAL_CHARACTERS.includes(char))) {
3797
- issues.push(`must contain a special character (${PASSWORD_SPECIAL_CHARACTERS})`);
3798
- }
3799
- return issues;
3800
- }
3801
-
3802
- class Password extends propertyOf({
3803
- name: "password",
3804
- schema: Type8.String({ pattern: ARGON2_HASH }),
3805
- default: DEMO_HASH,
3806
- sensitive: true
3807
- }) {
3808
- static async hash(plain) {
3809
- const issues = passwordIssues(plain);
3810
- if (issues.length > 0) {
3811
- throw new InvalidPropertyValue({
3812
- source: "password",
3813
- details: { errors: issues }
3814
- });
3815
- }
3816
- return new Password(await currentHasher().hash(plain));
3817
- }
3818
- verify(input) {
3819
- const hash = this.value;
3820
- if (hash === undefined)
3821
- return Promise.resolve(false);
3822
- return currentHasher().verify(input, hash);
3823
- }
3824
- verifySync(input) {
3825
- const hash = this.value;
3826
- if (hash === undefined)
3827
- return false;
3828
- return verifySyncWithCurrent(input, hash);
3829
- }
3830
- }
3831
-
3832
- // src/std/properties/primitives.ts
3833
- import { Type as Type9 } from "typebox";
3834
- var StringProperty = propertyOf({
3835
- name: "string",
3836
- schema: Type9.String(),
3837
- default: "demo"
3838
- });
3839
- var Text = propertyOf({
3840
- name: "text",
3841
- schema: Type9.String({ minLength: 1 }),
3842
- default: "Demo",
3843
- preHandle: (value) => value.trim()
3844
- });
3845
- var NumberProperty = propertyOf({
3846
- name: "number",
3847
- schema: Type9.Number(),
3848
- default: 0
3849
- });
3850
- var Integer = propertyOf({
3851
- name: "integer",
3852
- schema: Type9.Integer(),
3853
- default: 0
3854
- });
3855
- var BooleanProperty = propertyOf({
3856
- name: "boolean",
3857
- schema: Type9.Boolean(),
3858
- default: false
3859
- });
3860
-
3861
- // src/std/properties/time.ts
3862
- import { Type as Type10 } from "typebox";
3863
- var DEMO_DATE_TIME = "2026-01-01T00:00:00.000Z";
3864
- function dateTimeOf({
3865
- name,
3866
- optional,
3867
- default: _default
3868
- }) {
3869
- return class extends propertyOf({
3870
- name,
3871
- schema: Type10.String({ format: "date-time" }),
3872
- optional,
3873
- default: _default
3874
- }) {
3875
- static now() {
3876
- return new this(new Date().toISOString());
3877
- }
3878
- };
3879
- }
3880
-
3881
- class DateTime extends dateTimeOf({
3882
- name: "dateTime",
3883
- default: DEMO_DATE_TIME
3884
- }) {
3885
- }
3886
- var DateProperty = propertyOf({
3887
- name: "date",
3888
- schema: Type10.String({ format: "date" }),
3889
- default: "2026-01-01"
3890
- });
3891
-
3892
- class CreatedAt extends dateTimeOf({
3893
- name: "createdAt",
3894
- default: DEMO_DATE_TIME
3895
- }) {
3896
- }
3897
-
3898
- class UpdatedAt extends dateTimeOf({
3899
- name: "updatedAt",
3900
- optional: true,
3901
- default: DEMO_DATE_TIME
3902
- }) {
3903
- }
3904
-
3905
- class DeletedAt extends dateTimeOf({
3906
- name: "deletedAt",
3907
- optional: true
3908
- }) {
3909
- }
3910
-
3911
- // src/std/blueprint-plugin.ts
3912
- var Std = blueprintPluginOf("std", {
3913
- id: Id,
3914
- slug: Slug,
3915
- email: Email,
3916
- phone: Phone,
3917
- url: Url,
3918
- ip: Ip,
3919
- password: Password,
3920
- string: StringProperty,
3921
- text: Text,
3922
- number: NumberProperty,
3923
- integer: Integer,
3924
- boolean: BooleanProperty,
3925
- date: DateProperty,
3926
- dateTime: DateTime,
3927
- createdAt: CreatedAt,
3928
- updatedAt: UpdatedAt,
3929
- deletedAt: DeletedAt,
3930
- schema: SchemaProperty
3931
- }, { enumOf });
3932
-
3933
- // src/std/blueprint.ts
3934
- var blueprintOf = blueprintBuilderOf(Std);
3935
- // src/std/record-plugins.ts
3936
- var now = () => new Date().toISOString();
3937
-
3938
- class PublishableRecord extends recordOf(blueprintOf((ctx) => ({ publishedAt: ctx.optional.dateTime }))) {
3939
- get isPublished() {
3940
- return this.publishedAt !== undefined;
3941
- }
3942
- publish(at = now()) {
3943
- return this.set("publishedAt", at);
3944
- }
3945
- unpublish() {
3946
- return this.set("publishedAt", undefined);
3947
- }
3948
- }
3949
- var Publishable = recordPluginOf("publishable", PublishableRecord, {
3950
- description: "A publication date, with publish, unpublish and isPublished."
3951
- });
3952
-
3953
- class ArchivableRecord extends recordOf(blueprintOf((ctx) => ({ archivedAt: ctx.optional.dateTime }))) {
3954
- get isArchived() {
3955
- return this.archivedAt !== undefined;
3956
- }
3957
- archive(at = now()) {
3958
- return this.set("archivedAt", at);
3959
- }
3960
- restore() {
3961
- return this.set("archivedAt", undefined);
3962
- }
3963
- }
3964
- var Archivable = recordPluginOf("archivable", ArchivableRecord, {
3965
- description: "An archive date, with archive, restore and isArchived."
3966
- });
3967
-
3968
- class TaggableRecord extends recordOf(blueprintOf((ctx) => ({ tags: ctx.list.optional.string }))) {
3969
- hasTag(tag) {
3970
- return this.tags?.includes(tag) ?? false;
3971
- }
3972
- tag(...tags) {
3973
- return this.set("tags", [...new Set([...this.tags ?? [], ...tags])]);
3974
- }
3975
- untag(...tags) {
3976
- return this.set("tags", (this.tags ?? []).filter((tag) => !tags.includes(tag)));
3977
- }
3978
- }
3979
- var Taggable = recordPluginOf("taggable", TaggableRecord, {
3980
- description: "A list of tags, with tag, untag and hasTag."
3981
- });
3982
-
3983
- class OwnableRecord extends recordOf(blueprintOf((ctx) => ({ ownerId: ctx.id }))) {
3984
- isOwnedBy(id) {
3985
- return this.ownerId === id.toLowerCase();
3986
- }
3987
- transferTo(id) {
3988
- return this.set("ownerId", id);
3989
- }
3990
- }
3991
- var Ownable = recordPluginOf("ownable", OwnableRecord, {
3992
- description: "The id of the owner, with isOwnedBy and transferTo."
3993
- });
3994
-
3995
- class AuthenticatableRecord extends recordOf(blueprintOf((ctx) => ({ email: ctx.email, password: ctx.password })), { unique: ["email"], change: ["password"] }) {
3996
- verifyPassword(plain) {
3997
- return new Password(this.password).verify(plain);
3998
- }
3999
- }
4000
- var Authenticatable = recordPluginOf("authenticatable", AuthenticatableRecord, {
4001
- description: "A unique email and a sensitive password hash, with change.password and verifyPassword."
4002
- });
4003
- var StdRecordPlugins = recordPluginCatalogOf(Publishable, Archivable, Taggable, Ownable, Authenticatable);
4004
-
4005
- // src/std/entity.ts
4006
- var Identity = blueprintBuilderOf()(() => ({
4007
- id: Id,
4008
- createdAt: CreatedAt,
4009
- updatedAt: UpdatedAt,
4010
- deletedAt: DeletedAt
4011
- }));
4012
- var entityOf = entityBuilderOf({
4013
- identity: Identity,
4014
- generateId,
4015
- now: () => new Date().toISOString(),
4016
- plugins: [StdRecordPlugins]
4017
- });
4018
- // src/std/record.ts
4019
- var recordOf2 = recordBuilderOf(StdRecordPlugins);
1
+ import {
2
+ InvalidEnvironment2,
3
+ environmentOf2,
4
+ isEnvironment2,
5
+ guard2,
6
+ InvalidApplicationDeclaration2,
7
+ DuplicateApplicationDeclaration2,
8
+ ApplicationConflict2,
9
+ UnregisteredApplicationReference2,
10
+ UnregisteredRepositoryDependency2,
11
+ UnregisteredUseCaseDependency2,
12
+ ApplicationNotStarted2,
13
+ ApplicationAlreadyStarted2,
14
+ InvalidApplicationEnvironment2,
15
+ useApplication2,
16
+ resetApplication2,
17
+ InvalidLogDeclaration2,
18
+ LogLevels2,
19
+ logProviderOf2,
20
+ consoleLogProvider2,
21
+ jsonLogProvider2,
22
+ memoryLogProvider2,
23
+ Logger2,
24
+ ReservedEntityKey2,
25
+ ImmutableEntityKey2,
26
+ DeletedEntity2,
27
+ entityBuilderOf2,
28
+ isEntityClass2,
29
+ isEntity2,
30
+ eventOf2,
31
+ ENTITY_IDENTITY_KEYS2,
32
+ RESERVED_ENTITY_KEYS2,
33
+ EntityUniqueKeys2,
34
+ AbstractEntity2,
35
+ InvalidRepositoryQuery2,
36
+ InvalidRepositoryDeclaration2,
37
+ InvalidRepositoryEntity2,
38
+ InvalidRepositoryData2,
39
+ RepositoryUniqueViolation2,
40
+ RepositoryEntityNotFound2,
41
+ providerOf2,
42
+ providerDescriptionOf2,
43
+ inMemoryProvider2,
44
+ AbstractRepository2,
45
+ repositoryOf2,
46
+ RepositoryOf2,
47
+ isRepository2,
48
+ InvalidUseCaseStep2,
49
+ InvalidUseCaseDeclaration2,
50
+ UseCaseAlreadyExecuted2,
51
+ InvalidUseCaseDependencies2,
52
+ AbstractUseCase2,
53
+ useCaseOf2,
54
+ isUseCaseClass2,
55
+ isUseCase2,
56
+ InvalidCommandDeclaration2,
57
+ UnknownCommandOperation2,
58
+ InvalidCommandContext2,
59
+ InvalidCommandEnvironment2,
60
+ CommandEventFailed2,
61
+ commandOf2,
62
+ isCommand2,
63
+ InvalidOpenAPIModel2,
64
+ InvalidOutputStage2,
65
+ DuplicateOperation2,
66
+ toOpenAPI2,
67
+ transformOf2,
68
+ sinkOf2,
69
+ stageDescriptionOf2,
70
+ stageKindOf2,
71
+ stageCatalogOf2,
72
+ operationOf2,
73
+ outputOf2,
74
+ isOutput2,
75
+ providerFrom2,
76
+ logFrom2,
77
+ isLogFactory2,
78
+ isProviderFactory2,
79
+ isApplication2,
80
+ applicationOf2,
81
+ blueprintPluginOf2,
82
+ statusOf2,
83
+ PROBLEM_MEDIA_TYPE2,
84
+ problemOf2,
85
+ outputValueOf2,
86
+ routeOptionsIssue2,
87
+ operationRoutes2,
88
+ openapi2,
89
+ select2,
90
+ recordPluginCatalogOf2,
91
+ Email2,
92
+ Phone2,
93
+ Url2,
94
+ Ip2,
95
+ enumOf2,
96
+ SchemaProperty2,
97
+ PasswordHasherRequired2,
98
+ SyncVerifyUnsupported2,
99
+ configure2,
100
+ resetRuntime2,
101
+ Id2,
102
+ Slug2,
103
+ PASSWORD_MIN_LENGTH2,
104
+ PASSWORD_MAX_LENGTH2,
105
+ PASSWORD_SPECIAL_CHARACTERS2,
106
+ isPasswordHash2,
107
+ passwordIssues2,
108
+ Password2,
109
+ StringProperty2,
110
+ Text2,
111
+ NumberProperty2,
112
+ Integer2,
113
+ BooleanProperty2,
114
+ DateTime2,
115
+ DateProperty2,
116
+ CreatedAt2,
117
+ UpdatedAt2,
118
+ DeletedAt2,
119
+ Std2,
120
+ blueprintOf2,
121
+ Publishable2,
122
+ Archivable2,
123
+ Taggable2,
124
+ Ownable2,
125
+ Authenticatable2,
126
+ StdRecordPlugins2,
127
+ entityOf2,
128
+ recordOf2,
129
+ StdStages2
130
+ } from "./index-ewm6r4nw.js";
131
+ import {
132
+ isProperty2,
133
+ schemaOf2,
134
+ Demo2,
135
+ propertyLineageOf2,
136
+ Kind2,
137
+ isBlueprint2,
138
+ isRecordClass2,
139
+ isOptionalRecord2,
140
+ recordFieldOf2,
141
+ listOf2,
142
+ isBlueprintList2,
143
+ ExceptionLayers2,
144
+ UNEXPECTED_ERROR2,
145
+ Exception2,
146
+ exceptionOf2,
147
+ Meta2,
148
+ InvalidRecordValue2,
149
+ UndeclaredRecordProperty2,
150
+ ReservedRecordKey2,
151
+ InvalidRecordPlugin2,
152
+ RecordPluginConflict2,
153
+ UnknownRecordPlugin2,
154
+ IncompatibleRecordPlugin2,
155
+ MASK2,
156
+ RESERVED_RECORD_KEYS2,
157
+ AbstractRecord2,
158
+ pluginsOf2,
159
+ isRecordPlugin2,
160
+ hasPlugin2,
161
+ recordPluginOf2,
162
+ recordBuilderOf2,
163
+ ReservedBlueprintKey2,
164
+ UndeclaredBlueprintProperty2,
165
+ PropertyRequired2,
166
+ InvalidPropertyValue2,
167
+ State2,
168
+ AbstractProperty2,
169
+ PropertyStates2,
170
+ AbstractDefineProperty2,
171
+ propertyOf2,
172
+ optionalOf2,
173
+ blueprintBuilderOf2
174
+ } from "./index-hn82hm31.js";
4020
175
  export {
4021
- AbstractDefineProperty,
4022
- AbstractEntity,
4023
- AbstractProperty,
4024
- AbstractRecord,
4025
- AbstractRepository,
4026
- AbstractUseCase,
4027
- ApplicationConflict,
4028
- Archivable,
4029
- Authenticatable,
4030
- BooleanProperty,
4031
- CreatedAt,
4032
- DateProperty,
4033
- DateTime,
4034
- DeletedAt,
4035
- DeletedEntity,
4036
- Demo,
4037
- DuplicateApplicationDeclaration,
4038
- ENTITY_IDENTITY_KEYS,
4039
- Email,
4040
- EntityUniqueKeys,
4041
- Exception,
4042
- ExceptionLayers,
4043
- Id,
4044
- ImmutableEntityKey,
4045
- IncompatibleRecordPlugin,
4046
- Integer,
4047
- InvalidApplicationDeclaration,
4048
- InvalidEnvironment,
4049
- InvalidOpenAPIModel,
4050
- InvalidPropertyValue,
4051
- InvalidRecordPlugin,
4052
- InvalidRecordValue,
4053
- InvalidRepositoryData,
4054
- InvalidRepositoryDeclaration,
4055
- InvalidRepositoryEntity,
4056
- InvalidUseCaseDeclaration,
4057
- InvalidUseCaseDependencies,
4058
- Ip,
4059
- Kind,
4060
- MASK,
4061
- NumberProperty,
4062
- Ownable,
4063
- PASSWORD_MAX_LENGTH,
4064
- PASSWORD_MIN_LENGTH,
4065
- PASSWORD_SPECIAL_CHARACTERS,
4066
- Password,
4067
- PasswordHasherRequired,
4068
- Phone,
4069
- PropertyRequired,
4070
- PropertyStates,
4071
- Publishable,
4072
- RESERVED_ENTITY_KEYS,
4073
- RESERVED_RECORD_KEYS,
4074
- RecordPluginConflict,
4075
- RepositoryEntityNotFound,
4076
- RepositoryOf,
4077
- RepositoryUniqueViolation,
4078
- ReservedBlueprintKey,
4079
- ReservedEntityKey,
4080
- ReservedRecordKey,
4081
- SchemaProperty,
4082
- Slug,
4083
- State,
4084
- Std,
4085
- StdRecordPlugins,
4086
- StringProperty,
4087
- SyncVerifyUnsupported,
4088
- Taggable,
4089
- Text,
4090
- UNEXPECTED_ERROR,
4091
- UndeclaredBlueprintProperty,
4092
- UndeclaredRecordProperty,
4093
- UnknownRecordPlugin,
4094
- UnregisteredApplicationReference,
4095
- UnregisteredRepositoryDependency,
4096
- UpdatedAt,
4097
- Url,
4098
- UseCaseAlreadyExecuted,
4099
- applicationOf,
4100
- blueprintBuilderOf,
4101
- blueprintOf,
4102
- blueprintPluginOf,
4103
- configure,
4104
- entityBuilderOf,
4105
- entityOf,
4106
- enumOf,
4107
- environmentOf,
4108
- eventOf,
4109
- exceptionOf,
4110
- guard,
4111
- hasPlugin,
4112
- inMemoryProvider,
4113
- isApplication,
4114
- isBlueprint,
4115
- isBlueprintList,
4116
- isEntity,
4117
- isEntityClass,
4118
- isEnvironment,
4119
- isOptionalRecord,
4120
- isPasswordHash,
4121
- isProperty,
4122
- isRecordClass,
4123
- isRecordPlugin,
4124
- isRepository,
4125
- isUseCase,
4126
- isUseCaseClass,
4127
- listOf,
4128
- optionalOf,
4129
- passwordIssues,
4130
- pluginsOf,
4131
- propertyLineageOf,
4132
- propertyOf,
4133
- recordBuilderOf,
4134
- recordFieldOf,
176
+ AbstractDefineProperty2 as AbstractDefineProperty,
177
+ AbstractEntity2 as AbstractEntity,
178
+ AbstractProperty2 as AbstractProperty,
179
+ AbstractRecord2 as AbstractRecord,
180
+ AbstractRepository2 as AbstractRepository,
181
+ AbstractUseCase2 as AbstractUseCase,
182
+ ApplicationAlreadyStarted2 as ApplicationAlreadyStarted,
183
+ ApplicationConflict2 as ApplicationConflict,
184
+ ApplicationNotStarted2 as ApplicationNotStarted,
185
+ Archivable2 as Archivable,
186
+ Authenticatable2 as Authenticatable,
187
+ BooleanProperty2 as BooleanProperty,
188
+ CommandEventFailed2 as CommandEventFailed,
189
+ CreatedAt2 as CreatedAt,
190
+ DateProperty2 as DateProperty,
191
+ DateTime2 as DateTime,
192
+ DeletedAt2 as DeletedAt,
193
+ DeletedEntity2 as DeletedEntity,
194
+ Demo2 as Demo,
195
+ DuplicateApplicationDeclaration2 as DuplicateApplicationDeclaration,
196
+ DuplicateOperation2 as DuplicateOperation,
197
+ ENTITY_IDENTITY_KEYS2 as ENTITY_IDENTITY_KEYS,
198
+ Email2 as Email,
199
+ EntityUniqueKeys2 as EntityUniqueKeys,
200
+ Exception2 as Exception,
201
+ ExceptionLayers2 as ExceptionLayers,
202
+ Id2 as Id,
203
+ ImmutableEntityKey2 as ImmutableEntityKey,
204
+ IncompatibleRecordPlugin2 as IncompatibleRecordPlugin,
205
+ Integer2 as Integer,
206
+ InvalidApplicationDeclaration2 as InvalidApplicationDeclaration,
207
+ InvalidApplicationEnvironment2 as InvalidApplicationEnvironment,
208
+ InvalidCommandContext2 as InvalidCommandContext,
209
+ InvalidCommandDeclaration2 as InvalidCommandDeclaration,
210
+ InvalidCommandEnvironment2 as InvalidCommandEnvironment,
211
+ InvalidEnvironment2 as InvalidEnvironment,
212
+ InvalidLogDeclaration2 as InvalidLogDeclaration,
213
+ InvalidOpenAPIModel2 as InvalidOpenAPIModel,
214
+ InvalidOutputStage2 as InvalidOutputStage,
215
+ InvalidPropertyValue2 as InvalidPropertyValue,
216
+ InvalidRecordPlugin2 as InvalidRecordPlugin,
217
+ InvalidRecordValue2 as InvalidRecordValue,
218
+ InvalidRepositoryData2 as InvalidRepositoryData,
219
+ InvalidRepositoryDeclaration2 as InvalidRepositoryDeclaration,
220
+ InvalidRepositoryEntity2 as InvalidRepositoryEntity,
221
+ InvalidRepositoryQuery2 as InvalidRepositoryQuery,
222
+ InvalidUseCaseDeclaration2 as InvalidUseCaseDeclaration,
223
+ InvalidUseCaseDependencies2 as InvalidUseCaseDependencies,
224
+ InvalidUseCaseStep2 as InvalidUseCaseStep,
225
+ Ip2 as Ip,
226
+ Kind2 as Kind,
227
+ LogLevels2 as LogLevels,
228
+ Logger2 as Logger,
229
+ MASK2 as MASK,
230
+ Meta2 as Meta,
231
+ NumberProperty2 as NumberProperty,
232
+ Ownable2 as Ownable,
233
+ PASSWORD_MAX_LENGTH2 as PASSWORD_MAX_LENGTH,
234
+ PASSWORD_MIN_LENGTH2 as PASSWORD_MIN_LENGTH,
235
+ PASSWORD_SPECIAL_CHARACTERS2 as PASSWORD_SPECIAL_CHARACTERS,
236
+ PROBLEM_MEDIA_TYPE2 as PROBLEM_MEDIA_TYPE,
237
+ Password2 as Password,
238
+ PasswordHasherRequired2 as PasswordHasherRequired,
239
+ Phone2 as Phone,
240
+ PropertyRequired2 as PropertyRequired,
241
+ PropertyStates2 as PropertyStates,
242
+ Publishable2 as Publishable,
243
+ RESERVED_ENTITY_KEYS2 as RESERVED_ENTITY_KEYS,
244
+ RESERVED_RECORD_KEYS2 as RESERVED_RECORD_KEYS,
245
+ RecordPluginConflict2 as RecordPluginConflict,
246
+ RepositoryEntityNotFound2 as RepositoryEntityNotFound,
247
+ RepositoryOf2 as RepositoryOf,
248
+ RepositoryUniqueViolation2 as RepositoryUniqueViolation,
249
+ ReservedBlueprintKey2 as ReservedBlueprintKey,
250
+ ReservedEntityKey2 as ReservedEntityKey,
251
+ ReservedRecordKey2 as ReservedRecordKey,
252
+ SchemaProperty2 as SchemaProperty,
253
+ Slug2 as Slug,
254
+ State2 as State,
255
+ Std2 as Std,
256
+ StdRecordPlugins2 as StdRecordPlugins,
257
+ StdStages2 as StdStages,
258
+ StringProperty2 as StringProperty,
259
+ SyncVerifyUnsupported2 as SyncVerifyUnsupported,
260
+ Taggable2 as Taggable,
261
+ Text2 as Text,
262
+ UNEXPECTED_ERROR2 as UNEXPECTED_ERROR,
263
+ UndeclaredBlueprintProperty2 as UndeclaredBlueprintProperty,
264
+ UndeclaredRecordProperty2 as UndeclaredRecordProperty,
265
+ UnknownCommandOperation2 as UnknownCommandOperation,
266
+ UnknownRecordPlugin2 as UnknownRecordPlugin,
267
+ UnregisteredApplicationReference2 as UnregisteredApplicationReference,
268
+ UnregisteredRepositoryDependency2 as UnregisteredRepositoryDependency,
269
+ UnregisteredUseCaseDependency2 as UnregisteredUseCaseDependency,
270
+ UpdatedAt2 as UpdatedAt,
271
+ Url2 as Url,
272
+ UseCaseAlreadyExecuted2 as UseCaseAlreadyExecuted,
273
+ applicationOf2 as applicationOf,
274
+ blueprintBuilderOf2 as blueprintBuilderOf,
275
+ blueprintOf2 as blueprintOf,
276
+ blueprintPluginOf2 as blueprintPluginOf,
277
+ commandOf2 as commandOf,
278
+ configure2 as configure,
279
+ consoleLogProvider2 as consoleLogProvider,
280
+ entityBuilderOf2 as entityBuilderOf,
281
+ entityOf2 as entityOf,
282
+ enumOf2 as enumOf,
283
+ environmentOf2 as environmentOf,
284
+ eventOf2 as eventOf,
285
+ exceptionOf2 as exceptionOf,
286
+ guard2 as guard,
287
+ hasPlugin2 as hasPlugin,
288
+ inMemoryProvider2 as inMemoryProvider,
289
+ isApplication2 as isApplication,
290
+ isBlueprint2 as isBlueprint,
291
+ isBlueprintList2 as isBlueprintList,
292
+ isCommand2 as isCommand,
293
+ isEntity2 as isEntity,
294
+ isEntityClass2 as isEntityClass,
295
+ isEnvironment2 as isEnvironment,
296
+ isLogFactory2 as isLogFactory,
297
+ isOptionalRecord2 as isOptionalRecord,
298
+ isOutput2 as isOutput,
299
+ isPasswordHash2 as isPasswordHash,
300
+ isProperty2 as isProperty,
301
+ isProviderFactory2 as isProviderFactory,
302
+ isRecordClass2 as isRecordClass,
303
+ isRecordPlugin2 as isRecordPlugin,
304
+ isRepository2 as isRepository,
305
+ isUseCase2 as isUseCase,
306
+ isUseCaseClass2 as isUseCaseClass,
307
+ jsonLogProvider2 as jsonLogProvider,
308
+ listOf2 as listOf,
309
+ logFrom2 as logFrom,
310
+ logProviderOf2 as logProviderOf,
311
+ memoryLogProvider2 as memoryLogProvider,
312
+ openapi2 as openapi,
313
+ operationOf2 as operationOf,
314
+ operationRoutes2 as operationRoutes,
315
+ optionalOf2 as optionalOf,
316
+ outputOf2 as outputOf,
317
+ outputValueOf2 as outputValueOf,
318
+ passwordIssues2 as passwordIssues,
319
+ pluginsOf2 as pluginsOf,
320
+ problemOf2 as problemOf,
321
+ propertyLineageOf2 as propertyLineageOf,
322
+ propertyOf2 as propertyOf,
323
+ providerDescriptionOf2 as providerDescriptionOf,
324
+ providerFrom2 as providerFrom,
325
+ providerOf2 as providerOf,
326
+ recordBuilderOf2 as recordBuilderOf,
327
+ recordFieldOf2 as recordFieldOf,
4135
328
  recordOf2 as recordOf,
4136
- recordPluginCatalogOf,
4137
- recordPluginOf,
4138
- repositoryOf,
4139
- resetRuntime,
4140
- schemaOf,
4141
- sliceOf,
4142
- sliceValue,
4143
- toOpenAPI,
4144
- useCaseOf
329
+ recordPluginCatalogOf2 as recordPluginCatalogOf,
330
+ recordPluginOf2 as recordPluginOf,
331
+ repositoryOf2 as repositoryOf,
332
+ resetApplication2 as resetApplication,
333
+ resetRuntime2 as resetRuntime,
334
+ routeOptionsIssue2 as routeOptionsIssue,
335
+ schemaOf2 as schemaOf,
336
+ select2 as select,
337
+ sinkOf2 as sinkOf,
338
+ stageCatalogOf2 as stageCatalogOf,
339
+ stageDescriptionOf2 as stageDescriptionOf,
340
+ stageKindOf2 as stageKindOf,
341
+ statusOf2 as statusOf,
342
+ toOpenAPI2 as toOpenAPI,
343
+ transformOf2 as transformOf,
344
+ useApplication2 as useApplication,
345
+ useCaseOf2 as useCaseOf
4145
346
  };