@afora/core 0.0.8 → 0.0.9

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