@afora/core 0.0.3 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/application/exceptions.d.ts +9 -0
- package/dist/core/application/providers.d.ts +46 -0
- package/dist/core/application/start.d.ts +25 -1
- package/dist/core/application/types/application.interface.d.ts +70 -6
- package/dist/core/command/types/command.interface.d.ts +6 -0
- package/dist/core/entity/event.d.ts +12 -2
- package/dist/core/logger/exceptions.d.ts +4 -0
- package/dist/core/logger/logger.d.ts +106 -0
- package/dist/core/repository/state.d.ts +3 -2
- package/dist/core/use-case/scope.d.ts +3 -0
- package/dist/core/use-case/use-case.d.ts +5 -4
- package/dist/{index-sw2b9ehx.js → index-8m80wjzf.js} +770 -247
- package/dist/index.d.ts +8 -4
- package/dist/index.js +38 -12
- package/dist/testing/index.js +1 -1
- package/package.json +1 -1
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
isRecordClass2,
|
|
11
11
|
recordFieldOf2,
|
|
12
12
|
isBlueprintList2,
|
|
13
|
+
UNEXPECTED_ERROR2,
|
|
13
14
|
Exception2,
|
|
14
15
|
isDeclaredException,
|
|
15
16
|
declaredMessageOf,
|
|
@@ -50,17 +51,38 @@ __export(exports_environment, {
|
|
|
50
51
|
loadEnvironments: () => loadEnvironments
|
|
51
52
|
});
|
|
52
53
|
|
|
53
|
-
// src/core/
|
|
54
|
+
// src/core/application/exceptions.ts
|
|
54
55
|
var exports_exceptions4 = {};
|
|
55
56
|
__export(exports_exceptions4, {
|
|
57
|
+
ApplicationAlreadyStarted: () => ApplicationAlreadyStarted2,
|
|
58
|
+
ApplicationConflict: () => ApplicationConflict2,
|
|
59
|
+
ApplicationNotStarted: () => ApplicationNotStarted2,
|
|
60
|
+
DuplicateApplicationDeclaration: () => DuplicateApplicationDeclaration2,
|
|
61
|
+
InvalidApplicationDeclaration: () => InvalidApplicationDeclaration2,
|
|
62
|
+
InvalidApplicationEnvironment: () => InvalidApplicationEnvironment2,
|
|
63
|
+
ProviderNotBound: () => ProviderNotBound2,
|
|
64
|
+
UnregisteredApplicationReference: () => UnregisteredApplicationReference2,
|
|
65
|
+
UnregisteredRepositoryDependency: () => UnregisteredRepositoryDependency2,
|
|
66
|
+
UnregisteredUseCaseDependency: () => UnregisteredUseCaseDependency2
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
// src/core/logger/exceptions.ts
|
|
70
|
+
var exports_exceptions5 = {};
|
|
71
|
+
__export(exports_exceptions5, {
|
|
72
|
+
InvalidLogDeclaration: () => InvalidLogDeclaration2
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
// src/core/entity/exceptions.ts
|
|
76
|
+
var exports_exceptions6 = {};
|
|
77
|
+
__export(exports_exceptions6, {
|
|
56
78
|
DeletedEntity: () => DeletedEntity2,
|
|
57
79
|
ImmutableEntityKey: () => ImmutableEntityKey2,
|
|
58
80
|
ReservedEntityKey: () => ReservedEntityKey2
|
|
59
81
|
});
|
|
60
82
|
|
|
61
83
|
// src/core/repository/exceptions.ts
|
|
62
|
-
var
|
|
63
|
-
__export(
|
|
84
|
+
var exports_exceptions7 = {};
|
|
85
|
+
__export(exports_exceptions7, {
|
|
64
86
|
InvalidRepositoryData: () => InvalidRepositoryData2,
|
|
65
87
|
InvalidRepositoryDeclaration: () => InvalidRepositoryDeclaration2,
|
|
66
88
|
InvalidRepositoryEntity: () => InvalidRepositoryEntity2,
|
|
@@ -82,14 +104,14 @@ __export(exports_use_case, {
|
|
|
82
104
|
});
|
|
83
105
|
|
|
84
106
|
// src/core/use-case/exceptions.ts
|
|
85
|
-
var
|
|
86
|
-
__export(
|
|
107
|
+
var exports_exceptions8 = {};
|
|
108
|
+
__export(exports_exceptions8, {
|
|
87
109
|
InvalidUseCaseStep: () => InvalidUseCaseStep2
|
|
88
110
|
});
|
|
89
111
|
|
|
90
112
|
// src/core/command/exceptions.ts
|
|
91
|
-
var
|
|
92
|
-
__export(
|
|
113
|
+
var exports_exceptions9 = {};
|
|
114
|
+
__export(exports_exceptions9, {
|
|
93
115
|
CommandEventFailed: () => CommandEventFailed2,
|
|
94
116
|
InvalidCommandContext: () => InvalidCommandContext2,
|
|
95
117
|
InvalidCommandDeclaration: () => InvalidCommandDeclaration2,
|
|
@@ -97,29 +119,15 @@ __export(exports_exceptions7, {
|
|
|
97
119
|
UnknownCommandOperation: () => UnknownCommandOperation2
|
|
98
120
|
});
|
|
99
121
|
|
|
100
|
-
// src/core/application/exceptions.ts
|
|
101
|
-
var exports_exceptions8 = {};
|
|
102
|
-
__export(exports_exceptions8, {
|
|
103
|
-
ApplicationAlreadyStarted: () => ApplicationAlreadyStarted2,
|
|
104
|
-
ApplicationConflict: () => ApplicationConflict2,
|
|
105
|
-
ApplicationNotStarted: () => ApplicationNotStarted2,
|
|
106
|
-
DuplicateApplicationDeclaration: () => DuplicateApplicationDeclaration2,
|
|
107
|
-
InvalidApplicationDeclaration: () => InvalidApplicationDeclaration2,
|
|
108
|
-
InvalidApplicationEnvironment: () => InvalidApplicationEnvironment2,
|
|
109
|
-
UnregisteredApplicationReference: () => UnregisteredApplicationReference2,
|
|
110
|
-
UnregisteredRepositoryDependency: () => UnregisteredRepositoryDependency2,
|
|
111
|
-
UnregisteredUseCaseDependency: () => UnregisteredUseCaseDependency2
|
|
112
|
-
});
|
|
113
|
-
|
|
114
122
|
// src/core/openapi/exceptions.ts
|
|
115
|
-
var
|
|
116
|
-
__export(
|
|
123
|
+
var exports_exceptions10 = {};
|
|
124
|
+
__export(exports_exceptions10, {
|
|
117
125
|
InvalidOpenAPIModel: () => InvalidOpenAPIModel2
|
|
118
126
|
});
|
|
119
127
|
|
|
120
128
|
// src/core/output/exceptions.ts
|
|
121
|
-
var
|
|
122
|
-
__export(
|
|
129
|
+
var exports_exceptions11 = {};
|
|
130
|
+
__export(exports_exceptions11, {
|
|
123
131
|
DuplicateOperation: () => DuplicateOperation2,
|
|
124
132
|
InvalidOutputStage: () => InvalidOutputStage2
|
|
125
133
|
});
|
|
@@ -209,6 +217,288 @@ function guard2(scope, run, resolve) {
|
|
|
209
217
|
}
|
|
210
218
|
}
|
|
211
219
|
|
|
220
|
+
// src/core/application/exceptions.ts
|
|
221
|
+
var InvalidApplicationDeclaration2 = exceptionOf2({
|
|
222
|
+
layer: "application" /* Application */,
|
|
223
|
+
name: "InvalidApplicationDeclaration",
|
|
224
|
+
message: ({ reason }) => reason
|
|
225
|
+
});
|
|
226
|
+
var DuplicateApplicationDeclaration2 = exceptionOf2({
|
|
227
|
+
layer: "application" /* Application */,
|
|
228
|
+
name: "DuplicateApplicationDeclaration",
|
|
229
|
+
message: ({
|
|
230
|
+
first,
|
|
231
|
+
second
|
|
232
|
+
}) => `The same object is registered as ${first} and as ${second}.`
|
|
233
|
+
});
|
|
234
|
+
var ApplicationConflict2 = exceptionOf2({
|
|
235
|
+
layer: "application" /* Application */,
|
|
236
|
+
name: "ApplicationConflict",
|
|
237
|
+
message: ({
|
|
238
|
+
reason
|
|
239
|
+
}) => reason
|
|
240
|
+
});
|
|
241
|
+
var UnregisteredApplicationReference2 = exceptionOf2({
|
|
242
|
+
layer: "application" /* Application */,
|
|
243
|
+
name: "UnregisteredApplicationReference",
|
|
244
|
+
message: ({
|
|
245
|
+
holder,
|
|
246
|
+
reference
|
|
247
|
+
}) => `${holder} holds ${reference}, which is not registered in the application.`
|
|
248
|
+
});
|
|
249
|
+
var UnregisteredRepositoryDependency2 = exceptionOf2({
|
|
250
|
+
layer: "application" /* Application */,
|
|
251
|
+
name: "UnregisteredRepositoryDependency",
|
|
252
|
+
message: ({
|
|
253
|
+
repository,
|
|
254
|
+
dependency
|
|
255
|
+
}) => `Repository ${repository} depends on ${dependency}, which is not registered in the application.`
|
|
256
|
+
});
|
|
257
|
+
var UnregisteredUseCaseDependency2 = exceptionOf2({
|
|
258
|
+
layer: "application" /* Application */,
|
|
259
|
+
name: "UnregisteredUseCaseDependency",
|
|
260
|
+
message: ({
|
|
261
|
+
useCase,
|
|
262
|
+
dependency
|
|
263
|
+
}) => `Use case ${useCase} depends on ${dependency}, which is not registered in the application.`
|
|
264
|
+
});
|
|
265
|
+
var ApplicationNotStarted2 = exceptionOf2({
|
|
266
|
+
layer: "application" /* Application */,
|
|
267
|
+
name: "ApplicationNotStarted",
|
|
268
|
+
message: ({
|
|
269
|
+
application
|
|
270
|
+
}) => application === undefined ? "No application is started: call await app.start() first." : `The application "${application}" is not started: call await app.start() first.`
|
|
271
|
+
});
|
|
272
|
+
var ProviderNotBound2 = exceptionOf2({
|
|
273
|
+
layer: "application" /* Application */,
|
|
274
|
+
name: "ProviderNotBound",
|
|
275
|
+
message: ({
|
|
276
|
+
provider
|
|
277
|
+
}) => `The provider "${provider}" is made by an application: register its storage in applicationOf({ providers }) and call the repository through the application.`
|
|
278
|
+
});
|
|
279
|
+
var ApplicationAlreadyStarted2 = exceptionOf2({
|
|
280
|
+
layer: "application" /* Application */,
|
|
281
|
+
name: "ApplicationAlreadyStarted",
|
|
282
|
+
message: ({
|
|
283
|
+
current,
|
|
284
|
+
attempted
|
|
285
|
+
}) => `The application "${current}" is already started, so "${attempted}" cannot be: stop it, or call start({ replace: true }).`
|
|
286
|
+
});
|
|
287
|
+
var InvalidApplicationEnvironment2 = exceptionOf2({
|
|
288
|
+
layer: "environment" /* Environment */,
|
|
289
|
+
name: "InvalidApplicationEnvironment",
|
|
290
|
+
message: ({
|
|
291
|
+
environments
|
|
292
|
+
}) => `Invalid environment variables: ${Object.entries(environments).map(([name, keys]) => `${name} (${keys.join(", ")})`).join("; ")}.`
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
// src/core/application/registry.ts
|
|
296
|
+
var SLOT = Symbol.for("afora.application");
|
|
297
|
+
function slot() {
|
|
298
|
+
const global = globalThis;
|
|
299
|
+
global[SLOT] ??= { current: undefined };
|
|
300
|
+
return global[SLOT];
|
|
301
|
+
}
|
|
302
|
+
function useApplication2() {
|
|
303
|
+
const { current } = slot();
|
|
304
|
+
if (current === undefined) {
|
|
305
|
+
throw new ApplicationNotStarted2({ source: "useApplication", details: {} });
|
|
306
|
+
}
|
|
307
|
+
return current;
|
|
308
|
+
}
|
|
309
|
+
function resetApplication2() {
|
|
310
|
+
slot().current = undefined;
|
|
311
|
+
}
|
|
312
|
+
function startedApplication() {
|
|
313
|
+
return slot().current;
|
|
314
|
+
}
|
|
315
|
+
function setStartedApplication(application) {
|
|
316
|
+
slot().current = application;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// src/core/logger/exceptions.ts
|
|
320
|
+
var InvalidLogDeclaration2 = exceptionOf2({
|
|
321
|
+
layer: "application" /* Application */,
|
|
322
|
+
name: "InvalidLogDeclaration",
|
|
323
|
+
message: ({ reason }) => reason
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
// src/core/logger/logger.ts
|
|
327
|
+
var LogLevels2 = Object.freeze([
|
|
328
|
+
"debug",
|
|
329
|
+
"info",
|
|
330
|
+
"warn",
|
|
331
|
+
"error"
|
|
332
|
+
]);
|
|
333
|
+
var names = new WeakMap;
|
|
334
|
+
var invalid = (reason) => {
|
|
335
|
+
throw new InvalidLogDeclaration2({ source: "log", details: { reason } });
|
|
336
|
+
};
|
|
337
|
+
function logProviderOf2(settings) {
|
|
338
|
+
if (!settings || typeof settings.write !== "function") {
|
|
339
|
+
invalid("Expected a log provider with a write function.");
|
|
340
|
+
}
|
|
341
|
+
if (settings.flush !== undefined && typeof settings.flush !== "function") {
|
|
342
|
+
invalid("Expected flush to be a function.");
|
|
343
|
+
}
|
|
344
|
+
if (settings.name !== undefined && (typeof settings.name !== "string" || settings.name.trim() === "")) {
|
|
345
|
+
invalid("Expected the name of a log provider to be a non-empty string.");
|
|
346
|
+
}
|
|
347
|
+
const provider = Object.freeze({
|
|
348
|
+
write: settings.write,
|
|
349
|
+
...settings.flush ? { flush: settings.flush } : {}
|
|
350
|
+
});
|
|
351
|
+
if (settings.name)
|
|
352
|
+
names.set(provider, settings.name);
|
|
353
|
+
return provider;
|
|
354
|
+
}
|
|
355
|
+
function logProviderNameOf(provider) {
|
|
356
|
+
return names.get(provider);
|
|
357
|
+
}
|
|
358
|
+
var fieldsText = (fields) => Object.keys(fields).length > 0 ? ` ${JSON.stringify(fields)}` : "";
|
|
359
|
+
function consoleLogProvider2() {
|
|
360
|
+
return logProviderOf2({
|
|
361
|
+
name: "console",
|
|
362
|
+
write: ({ at, level, event, fields, application }) => {
|
|
363
|
+
const line = `${at} ${level.toUpperCase()} [${application}] ${event}${fieldsText(fields)}`;
|
|
364
|
+
(level === "debug" ? console.debug : level === "info" ? console.info : level === "warn" ? console.warn : console.error)(line);
|
|
365
|
+
}
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
function jsonLogProvider2() {
|
|
369
|
+
return logProviderOf2({
|
|
370
|
+
name: "json",
|
|
371
|
+
write: (entry) => {
|
|
372
|
+
console.log(JSON.stringify({
|
|
373
|
+
at: entry.at,
|
|
374
|
+
level: entry.level,
|
|
375
|
+
application: entry.application,
|
|
376
|
+
event: entry.event,
|
|
377
|
+
...entry.fields
|
|
378
|
+
}));
|
|
379
|
+
}
|
|
380
|
+
});
|
|
381
|
+
}
|
|
382
|
+
function memoryLogProvider2() {
|
|
383
|
+
const entries = [];
|
|
384
|
+
const provider = Object.freeze({
|
|
385
|
+
write: (entry) => {
|
|
386
|
+
entries.push(entry);
|
|
387
|
+
},
|
|
388
|
+
entries,
|
|
389
|
+
clear: () => {
|
|
390
|
+
entries.length = 0;
|
|
391
|
+
}
|
|
392
|
+
});
|
|
393
|
+
names.set(provider, "memory");
|
|
394
|
+
return provider;
|
|
395
|
+
}
|
|
396
|
+
function checkLogSettings(settings) {
|
|
397
|
+
if (typeof settings !== "object" || settings === null) {
|
|
398
|
+
return invalid("Expected `log` to be { level?, providers }.");
|
|
399
|
+
}
|
|
400
|
+
const { level = "info", providers } = settings;
|
|
401
|
+
if (!LogLevels2.includes(level)) {
|
|
402
|
+
invalid(`Expected the log level to be one of ${LogLevels2.join(", ")}.`);
|
|
403
|
+
}
|
|
404
|
+
if (!Array.isArray(providers) || providers.some((provider) => typeof provider !== "object" || provider === null || typeof provider.write !== "function")) {
|
|
405
|
+
invalid("Expected `log.providers` to be a list of log providers.");
|
|
406
|
+
}
|
|
407
|
+
return Object.freeze({ level, providers: Object.freeze([...providers]) });
|
|
408
|
+
}
|
|
409
|
+
var silentLogger = Object.freeze({
|
|
410
|
+
debug: () => {},
|
|
411
|
+
info: () => {},
|
|
412
|
+
warn: () => {},
|
|
413
|
+
error: () => {}
|
|
414
|
+
});
|
|
415
|
+
var rank = (level) => LogLevels2.indexOf(level);
|
|
416
|
+
function applicationLogger(application) {
|
|
417
|
+
let current;
|
|
418
|
+
const write = (level) => (event, fields = {}) => {
|
|
419
|
+
if (!current || rank(level) < rank(current.level))
|
|
420
|
+
return;
|
|
421
|
+
const entry = Object.freeze({
|
|
422
|
+
at: new Date().toISOString(),
|
|
423
|
+
level,
|
|
424
|
+
event,
|
|
425
|
+
fields,
|
|
426
|
+
application
|
|
427
|
+
});
|
|
428
|
+
for (const provider of current.providers) {
|
|
429
|
+
try {
|
|
430
|
+
const written = provider.write(entry);
|
|
431
|
+
if (written && typeof written.catch === "function") {
|
|
432
|
+
written.catch(() => {});
|
|
433
|
+
}
|
|
434
|
+
} catch {}
|
|
435
|
+
}
|
|
436
|
+
};
|
|
437
|
+
const logger = Object.freeze({
|
|
438
|
+
debug: write("debug"),
|
|
439
|
+
info: write("info"),
|
|
440
|
+
warn: write("warn"),
|
|
441
|
+
error: write("error")
|
|
442
|
+
});
|
|
443
|
+
return {
|
|
444
|
+
logger,
|
|
445
|
+
get settings() {
|
|
446
|
+
return current;
|
|
447
|
+
},
|
|
448
|
+
set(settings) {
|
|
449
|
+
current = settings;
|
|
450
|
+
},
|
|
451
|
+
async flush() {
|
|
452
|
+
await Promise.all((current?.providers ?? []).map((provider) => Promise.resolve().then(() => provider.flush?.()).catch(() => {})));
|
|
453
|
+
}
|
|
454
|
+
};
|
|
455
|
+
}
|
|
456
|
+
var Logger2 = Object.freeze({
|
|
457
|
+
[Kind2]: "logger"
|
|
458
|
+
});
|
|
459
|
+
function isLoggerDeclaration(value) {
|
|
460
|
+
return value === Logger2;
|
|
461
|
+
}
|
|
462
|
+
function isLogger(value) {
|
|
463
|
+
return typeof value === "object" && value !== null && ["debug", "info", "warn", "error"].every((level) => typeof value[level] === "function");
|
|
464
|
+
}
|
|
465
|
+
var ApplicationLoggerKey = Symbol("afora.application.logger");
|
|
466
|
+
function resolveLogger(scoped, owner) {
|
|
467
|
+
return scoped ?? owner?.[ApplicationLoggerKey] ?? startedApplication()?.[ApplicationLoggerKey];
|
|
468
|
+
}
|
|
469
|
+
function clock() {
|
|
470
|
+
return globalThis.performance?.now() ?? Date.now();
|
|
471
|
+
}
|
|
472
|
+
function elapsed(since) {
|
|
473
|
+
return Math.round(clock() - since);
|
|
474
|
+
}
|
|
475
|
+
var logged = new WeakSet;
|
|
476
|
+
function logFailure(logger, event, fields, error) {
|
|
477
|
+
if (!logger)
|
|
478
|
+
return;
|
|
479
|
+
const exception = error instanceof Exception2 ? error : undefined;
|
|
480
|
+
const key = exception?.origin ?? error;
|
|
481
|
+
if (typeof key === "object" && key !== null) {
|
|
482
|
+
if (logged.has(key))
|
|
483
|
+
return;
|
|
484
|
+
logged.add(key);
|
|
485
|
+
}
|
|
486
|
+
const unexpected = !exception || exception.origin.name === UNEXPECTED_ERROR2;
|
|
487
|
+
try {
|
|
488
|
+
logger[unexpected ? "error" : "warn"](event, {
|
|
489
|
+
...fields,
|
|
490
|
+
exception: exception ? exception.toJSON() : { message: error instanceof Error ? error.message : String(error) }
|
|
491
|
+
});
|
|
492
|
+
} catch {}
|
|
493
|
+
}
|
|
494
|
+
function writeLog(logger, level, event, fields) {
|
|
495
|
+
if (!logger)
|
|
496
|
+
return;
|
|
497
|
+
try {
|
|
498
|
+
logger[level](event, fields);
|
|
499
|
+
} catch {}
|
|
500
|
+
}
|
|
501
|
+
|
|
212
502
|
// src/core/entity/exceptions.ts
|
|
213
503
|
var ReservedEntityKey2 = exceptionOf2({
|
|
214
504
|
layer: "entity" /* Entity */,
|
|
@@ -291,8 +581,10 @@ function eventOf2(name, entityClass, handler) {
|
|
|
291
581
|
return Object.freeze({
|
|
292
582
|
name,
|
|
293
583
|
entity,
|
|
294
|
-
async handle() {
|
|
295
|
-
await handler(entity
|
|
584
|
+
async handle(context) {
|
|
585
|
+
await handler(entity, {
|
|
586
|
+
logger: context?.logger ?? resolveLogger(undefined, undefined) ?? silentLogger
|
|
587
|
+
});
|
|
296
588
|
}
|
|
297
589
|
});
|
|
298
590
|
});
|
|
@@ -473,7 +765,7 @@ function frozenJson(value, subject, fail, seen = new Set) {
|
|
|
473
765
|
// src/core/repository/provider.ts
|
|
474
766
|
var descriptions = new WeakMap;
|
|
475
767
|
var opaque = Object.freeze({ kind: "opaque" });
|
|
476
|
-
function
|
|
768
|
+
function invalid2(reason) {
|
|
477
769
|
throw new InvalidRepositoryDeclaration2({
|
|
478
770
|
source: "providerOf",
|
|
479
771
|
details: { reason }
|
|
@@ -481,13 +773,13 @@ function invalid(reason) {
|
|
|
481
773
|
}
|
|
482
774
|
function providerOf2(settings) {
|
|
483
775
|
if (!settings || typeof settings.name !== "string" || settings.name.trim().length === 0 || typeof settings.create !== "function")
|
|
484
|
-
|
|
485
|
-
const options = frozenJson(settings.options ?? {}, "Provider options",
|
|
776
|
+
invalid2("Expected a provider name and create function.");
|
|
777
|
+
const options = frozenJson(settings.options ?? {}, "Provider options", invalid2);
|
|
486
778
|
if (options === null || typeof options !== "object" || Array.isArray(options))
|
|
487
|
-
|
|
779
|
+
invalid2("Provider options must be an object.");
|
|
488
780
|
const provider = settings.create(options);
|
|
489
781
|
if (!provider || typeof provider !== "object" || ["findOne", "findMany", "insert", "update", "remove", "count"].some((key) => typeof provider[key] !== "function"))
|
|
490
|
-
|
|
782
|
+
invalid2("Expected a repository provider from create.");
|
|
491
783
|
descriptions.set(provider, Object.freeze({
|
|
492
784
|
kind: "provider",
|
|
493
785
|
name: settings.name,
|
|
@@ -576,11 +868,11 @@ function matchesQuery(data, query) {
|
|
|
576
868
|
function codePoints(text) {
|
|
577
869
|
return Array.from(text, (char) => char.codePointAt(0));
|
|
578
870
|
}
|
|
579
|
-
function
|
|
871
|
+
function rank2(value) {
|
|
580
872
|
return value instanceof Date ? 1 : { number: 0, bigint: 0, string: 2, boolean: 3 }[typeof value] ?? 4;
|
|
581
873
|
}
|
|
582
874
|
function compareScalars(a, b) {
|
|
583
|
-
const [left, right] = [
|
|
875
|
+
const [left, right] = [rank2(a), rank2(b)];
|
|
584
876
|
if (left !== right)
|
|
585
877
|
return left - right;
|
|
586
878
|
if (typeof a === "string" && typeof b === "string") {
|
|
@@ -799,31 +1091,31 @@ var origins = new WeakMap;
|
|
|
799
1091
|
function declarationOf(state) {
|
|
800
1092
|
return origins.get(state) ?? state;
|
|
801
1093
|
}
|
|
802
|
-
function bindState(state, provider, bound = new Map) {
|
|
1094
|
+
function bindState(state, provider, instances, bound = new Map) {
|
|
803
1095
|
const done = bound.get(state);
|
|
804
1096
|
if (done)
|
|
805
1097
|
return done;
|
|
806
1098
|
const copy = {
|
|
807
1099
|
...state,
|
|
808
|
-
provider: state.explicitProvider ? state.provider : provider,
|
|
1100
|
+
provider: state.explicitProvider ? instances?.get(state.provider) ?? state.provider : provider ?? state.provider,
|
|
809
1101
|
context: undefined,
|
|
810
1102
|
relations: new Map([...state.relations].map(([target, related]) => [
|
|
811
1103
|
target,
|
|
812
|
-
bindState(related, provider, bound)
|
|
1104
|
+
bindState(related, provider, instances, bound)
|
|
813
1105
|
]))
|
|
814
1106
|
};
|
|
815
1107
|
origins.set(copy, declarationOf(state));
|
|
816
1108
|
bound.set(state, copy);
|
|
817
1109
|
return copy;
|
|
818
1110
|
}
|
|
819
|
-
function bindRepository(repository, provider) {
|
|
1111
|
+
function bindRepository(repository, provider, instances) {
|
|
820
1112
|
const state = stateOf(repository);
|
|
821
1113
|
const Declared = repository.constructor;
|
|
822
1114
|
|
|
823
1115
|
class Bound extends Declared {
|
|
824
1116
|
}
|
|
825
1117
|
Object.defineProperty(Bound, "name", { value: Declared.name });
|
|
826
|
-
states.set(Bound, bindState(state, provider));
|
|
1118
|
+
states.set(Bound, bindState(state, provider, instances));
|
|
827
1119
|
return Object.freeze(new Bound);
|
|
828
1120
|
}
|
|
829
1121
|
|
|
@@ -1138,25 +1430,25 @@ function unknownAction(entity, action, methods) {
|
|
|
1138
1430
|
}
|
|
1139
1431
|
return `"${action}" is not an action of ${entity}.`;
|
|
1140
1432
|
}
|
|
1141
|
-
function
|
|
1433
|
+
function invalid3(source, reason) {
|
|
1142
1434
|
throw new InvalidRepositoryDeclaration2({ source, details: { reason } });
|
|
1143
1435
|
}
|
|
1144
1436
|
function repositoryOf2(settings) {
|
|
1145
1437
|
const { entity, actions, environmentDependencies } = settings ?? {};
|
|
1146
1438
|
if (!isEntityClass2(entity) || !(EntityUniqueKeys2 in entity)) {
|
|
1147
|
-
|
|
1439
|
+
invalid3("repositoryOf", "Expected an entity class made by entityOf.");
|
|
1148
1440
|
}
|
|
1149
1441
|
const name = `${entity.name}Repository`;
|
|
1150
1442
|
const deletion = settings.deletion ?? "hard";
|
|
1151
1443
|
if (deletion !== "hard" && deletion !== "soft") {
|
|
1152
|
-
|
|
1444
|
+
invalid3(name, 'Expected deletion to be "hard" or "soft".');
|
|
1153
1445
|
}
|
|
1154
1446
|
const provider = settings.provider ?? inMemoryProvider2();
|
|
1155
1447
|
if (!Array.isArray(actions) || actions.length === 0) {
|
|
1156
|
-
|
|
1448
|
+
invalid3(name, "Expected a list of actions.");
|
|
1157
1449
|
}
|
|
1158
1450
|
if (environmentDependencies !== undefined && !isEnvironment2(environmentDependencies) && !(Array.isArray(environmentDependencies) && environmentDependencies.every(isEnvironment2))) {
|
|
1159
|
-
|
|
1451
|
+
invalid3(name, "Expected environments made by environmentOf.");
|
|
1160
1452
|
}
|
|
1161
1453
|
const relations = relationsOf(name, entity, settings.relations);
|
|
1162
1454
|
const unique = entity[EntityUniqueKeys2];
|
|
@@ -1182,12 +1474,12 @@ function repositoryOf2(settings) {
|
|
|
1182
1474
|
for (const name_ of new Set(actions)) {
|
|
1183
1475
|
const method = typeof name_ === "string" ? methods.get(name_) : undefined;
|
|
1184
1476
|
if (!method)
|
|
1185
|
-
|
|
1477
|
+
invalid3(name, unknownAction(entity.name, String(name_), methods));
|
|
1186
1478
|
const [kind, implementation] = method;
|
|
1187
1479
|
const needs = deletion === "soft" && kind === "delete" ? ["findOne", "update"] : NEEDS[kind] ?? [];
|
|
1188
1480
|
for (const need of needs) {
|
|
1189
1481
|
if (typeof provider?.[need] !== "function") {
|
|
1190
|
-
|
|
1482
|
+
invalid3(name, `The provider has no "${need}" for "${name_}".`);
|
|
1191
1483
|
}
|
|
1192
1484
|
}
|
|
1193
1485
|
Object.defineProperty(DeclaredRepository.prototype, name_, {
|
|
@@ -1211,7 +1503,7 @@ function repositoryOf2(settings) {
|
|
|
1211
1503
|
}
|
|
1212
1504
|
function RepositoryOf2(repository) {
|
|
1213
1505
|
if (!isRepository2(repository)) {
|
|
1214
|
-
|
|
1506
|
+
invalid3("RepositoryOf", "Expected a repository made by repositoryOf.");
|
|
1215
1507
|
}
|
|
1216
1508
|
return repository.constructor;
|
|
1217
1509
|
}
|
|
@@ -1719,6 +2011,9 @@ var InvalidUseCaseDependencies2 = exceptionOf2({
|
|
|
1719
2011
|
name: "InvalidUseCaseDependencies",
|
|
1720
2012
|
message: "Dependency overrides must contain only declared names: functions for use cases, objects of methods for repositories, and valid variables for environments."
|
|
1721
2013
|
});
|
|
2014
|
+
function loggerOfCall(state) {
|
|
2015
|
+
return resolveLogger(state.scope?.logger, state.owner);
|
|
2016
|
+
}
|
|
1722
2017
|
var states2 = new WeakMap;
|
|
1723
2018
|
function invalidValue(issues, source, phase) {
|
|
1724
2019
|
throw new Exception2({
|
|
@@ -1773,6 +2068,7 @@ function methodNamesOf(repository) {
|
|
|
1773
2068
|
}
|
|
1774
2069
|
function bindRepository2(repository, overrides, state, source) {
|
|
1775
2070
|
const Entity = repository.entity;
|
|
2071
|
+
const repositoryName = Entity.name;
|
|
1776
2072
|
const bound = Object.create(null);
|
|
1777
2073
|
const view = new Proxy(Object.create(repository), {
|
|
1778
2074
|
get: (_target, key, receiver) => {
|
|
@@ -1793,7 +2089,14 @@ function bindRepository2(repository, overrides, state, source) {
|
|
|
1793
2089
|
bound[name] = async (...args) => {
|
|
1794
2090
|
if (!state.active)
|
|
1795
2091
|
throw new InvalidUseCaseDependencies2({ source });
|
|
2092
|
+
const started = clock();
|
|
1796
2093
|
const result = await method.apply(receiver, args);
|
|
2094
|
+
writeLog(loggerOfCall(state), "debug", "repository", {
|
|
2095
|
+
repository: repositoryName,
|
|
2096
|
+
method: name,
|
|
2097
|
+
useCase: source,
|
|
2098
|
+
ms: elapsed(started)
|
|
2099
|
+
});
|
|
1797
2100
|
for (const arg of args)
|
|
1798
2101
|
pullEntities(arg, Entity, state.events);
|
|
1799
2102
|
pullEntities(result, Entity, state.events);
|
|
@@ -1828,6 +2131,8 @@ function narrowedContext(Child, parent) {
|
|
|
1828
2131
|
return picked;
|
|
1829
2132
|
}
|
|
1830
2133
|
function isOverrideOf(dependency, value) {
|
|
2134
|
+
if (isLoggerDeclaration(dependency))
|
|
2135
|
+
return isLogger(value);
|
|
1831
2136
|
if (isRepository2(dependency) || isEnvironment2(dependency)) {
|
|
1832
2137
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1833
2138
|
}
|
|
@@ -1873,7 +2178,8 @@ class AbstractUseCase2 {
|
|
|
1873
2178
|
started: false,
|
|
1874
2179
|
active: false,
|
|
1875
2180
|
events: [],
|
|
1876
|
-
dependencies: Object.create(null)
|
|
2181
|
+
dependencies: Object.create(null),
|
|
2182
|
+
owner: this.constructor
|
|
1877
2183
|
};
|
|
1878
2184
|
states2.set(this, state);
|
|
1879
2185
|
for (const [key, dependency] of Object.entries(declaration.dependencies)) {
|
|
@@ -1881,6 +2187,13 @@ class AbstractUseCase2 {
|
|
|
1881
2187
|
state.dependencies[key] = bindRepository2(dependency, undefined, state, source);
|
|
1882
2188
|
continue;
|
|
1883
2189
|
}
|
|
2190
|
+
if (isLoggerDeclaration(dependency)) {
|
|
2191
|
+
Object.defineProperty(state.dependencies, key, {
|
|
2192
|
+
get: () => loggerOfCall(state) ?? silentLogger,
|
|
2193
|
+
enumerable: true
|
|
2194
|
+
});
|
|
2195
|
+
continue;
|
|
2196
|
+
}
|
|
1884
2197
|
if (isEnvironment2(dependency)) {
|
|
1885
2198
|
Object.defineProperty(state.dependencies, key, {
|
|
1886
2199
|
get: () => state.scope?.environments?.get(dependency) ?? dependency.load(),
|
|
@@ -1925,6 +2238,10 @@ class AbstractUseCase2 {
|
|
|
1925
2238
|
dependencies[key] = bindRepository2(dependency, substitute, state, source);
|
|
1926
2239
|
continue;
|
|
1927
2240
|
}
|
|
2241
|
+
if (isLoggerDeclaration(dependency)) {
|
|
2242
|
+
dependencies[key] = substitute;
|
|
2243
|
+
continue;
|
|
2244
|
+
}
|
|
1928
2245
|
if (isEnvironment2(dependency)) {
|
|
1929
2246
|
const parsed = dependency.blueprint.safeParse(substitute);
|
|
1930
2247
|
if (parsed.issues)
|
|
@@ -1949,13 +2266,22 @@ class AbstractUseCase2 {
|
|
|
1949
2266
|
}
|
|
1950
2267
|
state.resolved = Object.freeze(dependencies);
|
|
1951
2268
|
state.active = true;
|
|
2269
|
+
const started = clock();
|
|
1952
2270
|
try {
|
|
1953
2271
|
const result = await guard2({ layer: "use-case" /* UseCase */, source }, () => implementation.call(this, state.resolved));
|
|
1954
2272
|
const parsed = declaration.response.safeParse(result);
|
|
1955
2273
|
if (parsed.issues)
|
|
1956
2274
|
invalidValue(parsed.issues, source, "response");
|
|
1957
2275
|
collectEvents(declaration.response, parsed.value, state.events);
|
|
2276
|
+
writeLog(loggerOfCall(state), "debug", "use-case", {
|
|
2277
|
+
useCase: source,
|
|
2278
|
+
outcome: "ok",
|
|
2279
|
+
ms: elapsed(started)
|
|
2280
|
+
});
|
|
1958
2281
|
return parsed.value;
|
|
2282
|
+
} catch (error) {
|
|
2283
|
+
logFailure(loggerOfCall(state), "use-case-failed", { useCase: source, ms: elapsed(started) }, error);
|
|
2284
|
+
throw error;
|
|
1959
2285
|
} finally {
|
|
1960
2286
|
state.active = false;
|
|
1961
2287
|
state.resolved = undefined;
|
|
@@ -1981,7 +2307,7 @@ function useCaseOf2(settings) {
|
|
|
1981
2307
|
throw new InvalidUseCaseDeclaration2({
|
|
1982
2308
|
source: typeof name === "string" ? name : "useCaseOf",
|
|
1983
2309
|
details: {
|
|
1984
|
-
reason: "Expected a name, input and response blueprints, and UseCase classes, repositories or
|
|
2310
|
+
reason: "Expected a name, input and response blueprints, and UseCase classes, repositories, environments or Logger as dependencies."
|
|
1985
2311
|
}
|
|
1986
2312
|
});
|
|
1987
2313
|
}
|
|
@@ -2037,7 +2363,7 @@ function useCaseOf2(settings) {
|
|
|
2037
2363
|
return DeclaredUseCase;
|
|
2038
2364
|
}
|
|
2039
2365
|
function isDependency(value) {
|
|
2040
|
-
return isUseCaseClass2(value) || isRepository2(value) || isEnvironment2(value);
|
|
2366
|
+
return isUseCaseClass2(value) || isRepository2(value) || isEnvironment2(value) || isLoggerDeclaration(value);
|
|
2041
2367
|
}
|
|
2042
2368
|
function isUseCaseClass2(value) {
|
|
2043
2369
|
return typeof value === "function" && value.prototype instanceof AbstractUseCase2 && value[Kind2] === "use-case" && typeof value.prototype.execute === "function";
|
|
@@ -2085,7 +2411,7 @@ function commandTransactionProvider(command) {
|
|
|
2085
2411
|
return verifiers.get(command)?.();
|
|
2086
2412
|
}
|
|
2087
2413
|
var IDENTIFIER2 = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
|
|
2088
|
-
function
|
|
2414
|
+
function repositoryProvidersOf(useCases, declared) {
|
|
2089
2415
|
const providers = new Map;
|
|
2090
2416
|
const seen = new Set;
|
|
2091
2417
|
const add = (state) => {
|
|
@@ -2119,7 +2445,7 @@ function providersOf(useCases, declared) {
|
|
|
2119
2445
|
return providers;
|
|
2120
2446
|
}
|
|
2121
2447
|
function transactionProviderOf(name, useCases, declared = false) {
|
|
2122
|
-
const providers =
|
|
2448
|
+
const providers = repositoryProvidersOf(useCases, declared);
|
|
2123
2449
|
const invalid = (reason, repositories) => {
|
|
2124
2450
|
throw new InvalidCommandDeclaration2({
|
|
2125
2451
|
source: name,
|
|
@@ -2283,9 +2609,16 @@ function commandOf2(settings) {
|
|
|
2283
2609
|
given = narrowed(UseCase, callContext);
|
|
2284
2610
|
}
|
|
2285
2611
|
const overrides = options?.env === undefined ? undefined : callEnvironment(where, environments, options.env);
|
|
2286
|
-
const
|
|
2287
|
-
|
|
2288
|
-
environments: overrides.byEnvironment
|
|
2612
|
+
const logger = resolveLogger(undefined, UseCase);
|
|
2613
|
+
const withEnvironments = (scope) => {
|
|
2614
|
+
const environmentsOfCall = overrides === undefined || overrides.byEnvironment.size === 0 ? scope?.environments : overrides.byEnvironment;
|
|
2615
|
+
if (!environmentsOfCall && !logger)
|
|
2616
|
+
return scope;
|
|
2617
|
+
return {
|
|
2618
|
+
providers: scope?.providers ?? new Map,
|
|
2619
|
+
...environmentsOfCall ? { environments: environmentsOfCall } : {},
|
|
2620
|
+
...logger ? { logger } : {}
|
|
2621
|
+
};
|
|
2289
2622
|
};
|
|
2290
2623
|
const run = async (declared) => {
|
|
2291
2624
|
const scope = withEnvironments(declared);
|
|
@@ -2294,11 +2627,20 @@ function commandOf2(settings) {
|
|
|
2294
2627
|
return { value, events: useCase.pullEvents() };
|
|
2295
2628
|
};
|
|
2296
2629
|
const provider = providerOfCall();
|
|
2297
|
-
const
|
|
2630
|
+
const started = clock();
|
|
2631
|
+
const outcome = await guard2({ layer: "command" /* Command */, source: where }, () => provider?.transaction ? provider.transaction((scoped) => run({ providers: new Map([[provider, scoped]]) })) : run(undefined)).catch((error) => {
|
|
2632
|
+
logFailure(logger, "command-failed", { command: where, ms: elapsed(started) }, error);
|
|
2633
|
+
throw error;
|
|
2634
|
+
});
|
|
2635
|
+
writeLog(logger, "debug", "command", {
|
|
2636
|
+
command: where,
|
|
2637
|
+
ms: elapsed(started)
|
|
2638
|
+
});
|
|
2298
2639
|
return {
|
|
2299
2640
|
...outcome,
|
|
2300
2641
|
context: callContext,
|
|
2301
|
-
env: () => overrides?.merged ?? loadEnvironments(environments)
|
|
2642
|
+
env: () => overrides?.merged ?? loadEnvironments(environments),
|
|
2643
|
+
logger: logger ?? silentLogger
|
|
2302
2644
|
};
|
|
2303
2645
|
};
|
|
2304
2646
|
const command = {
|
|
@@ -2325,13 +2667,15 @@ function commandOf2(settings) {
|
|
|
2325
2667
|
value,
|
|
2326
2668
|
events: raised,
|
|
2327
2669
|
context: callContext,
|
|
2328
|
-
env
|
|
2670
|
+
env,
|
|
2671
|
+
logger
|
|
2329
2672
|
} = await perform(op, input, options);
|
|
2330
2673
|
await applyPolicy(command, events, onEventError, {
|
|
2331
2674
|
operation: op,
|
|
2332
2675
|
raised,
|
|
2333
2676
|
context: callContext,
|
|
2334
|
-
env
|
|
2677
|
+
env,
|
|
2678
|
+
logger
|
|
2335
2679
|
});
|
|
2336
2680
|
return value;
|
|
2337
2681
|
}
|
|
@@ -2351,7 +2695,8 @@ async function applyPolicy(command, policy, onEventError, call) {
|
|
|
2351
2695
|
context: call.context,
|
|
2352
2696
|
get env() {
|
|
2353
2697
|
return call.env();
|
|
2354
|
-
}
|
|
2698
|
+
},
|
|
2699
|
+
logger: call.logger
|
|
2355
2700
|
};
|
|
2356
2701
|
if (typeof policy === "function") {
|
|
2357
2702
|
try {
|
|
@@ -2367,7 +2712,7 @@ async function applyPolicy(command, policy, onEventError, call) {
|
|
|
2367
2712
|
}
|
|
2368
2713
|
for (const [index, event] of raised.entries()) {
|
|
2369
2714
|
try {
|
|
2370
|
-
await event.handle();
|
|
2715
|
+
await event.handle({ logger: call.logger });
|
|
2371
2716
|
} catch (cause) {
|
|
2372
2717
|
if (!onEventError) {
|
|
2373
2718
|
throw new CommandEventFailed2({
|
|
@@ -2402,74 +2747,6 @@ function isCommand2(value) {
|
|
|
2402
2747
|
return typeof value === "object" && value !== null && value[Kind2] === "command";
|
|
2403
2748
|
}
|
|
2404
2749
|
|
|
2405
|
-
// src/core/application/exceptions.ts
|
|
2406
|
-
var InvalidApplicationDeclaration2 = exceptionOf2({
|
|
2407
|
-
layer: "application" /* Application */,
|
|
2408
|
-
name: "InvalidApplicationDeclaration",
|
|
2409
|
-
message: ({ reason }) => reason
|
|
2410
|
-
});
|
|
2411
|
-
var DuplicateApplicationDeclaration2 = exceptionOf2({
|
|
2412
|
-
layer: "application" /* Application */,
|
|
2413
|
-
name: "DuplicateApplicationDeclaration",
|
|
2414
|
-
message: ({
|
|
2415
|
-
first,
|
|
2416
|
-
second
|
|
2417
|
-
}) => `The same object is registered as ${first} and as ${second}.`
|
|
2418
|
-
});
|
|
2419
|
-
var ApplicationConflict2 = exceptionOf2({
|
|
2420
|
-
layer: "application" /* Application */,
|
|
2421
|
-
name: "ApplicationConflict",
|
|
2422
|
-
message: ({
|
|
2423
|
-
reason
|
|
2424
|
-
}) => reason
|
|
2425
|
-
});
|
|
2426
|
-
var UnregisteredApplicationReference2 = exceptionOf2({
|
|
2427
|
-
layer: "application" /* Application */,
|
|
2428
|
-
name: "UnregisteredApplicationReference",
|
|
2429
|
-
message: ({
|
|
2430
|
-
holder,
|
|
2431
|
-
reference
|
|
2432
|
-
}) => `${holder} holds ${reference}, which is not registered in the application.`
|
|
2433
|
-
});
|
|
2434
|
-
var UnregisteredRepositoryDependency2 = exceptionOf2({
|
|
2435
|
-
layer: "application" /* Application */,
|
|
2436
|
-
name: "UnregisteredRepositoryDependency",
|
|
2437
|
-
message: ({
|
|
2438
|
-
repository,
|
|
2439
|
-
dependency
|
|
2440
|
-
}) => `Repository ${repository} depends on ${dependency}, which is not registered in the application.`
|
|
2441
|
-
});
|
|
2442
|
-
var UnregisteredUseCaseDependency2 = exceptionOf2({
|
|
2443
|
-
layer: "application" /* Application */,
|
|
2444
|
-
name: "UnregisteredUseCaseDependency",
|
|
2445
|
-
message: ({
|
|
2446
|
-
useCase,
|
|
2447
|
-
dependency
|
|
2448
|
-
}) => `Use case ${useCase} depends on ${dependency}, which is not registered in the application.`
|
|
2449
|
-
});
|
|
2450
|
-
var ApplicationNotStarted2 = exceptionOf2({
|
|
2451
|
-
layer: "application" /* Application */,
|
|
2452
|
-
name: "ApplicationNotStarted",
|
|
2453
|
-
message: ({
|
|
2454
|
-
application
|
|
2455
|
-
}) => application === undefined ? "No application is started: call await app.start() first." : `The application "${application}" is not started: call await app.start() first.`
|
|
2456
|
-
});
|
|
2457
|
-
var ApplicationAlreadyStarted2 = exceptionOf2({
|
|
2458
|
-
layer: "application" /* Application */,
|
|
2459
|
-
name: "ApplicationAlreadyStarted",
|
|
2460
|
-
message: ({
|
|
2461
|
-
current,
|
|
2462
|
-
attempted
|
|
2463
|
-
}) => `The application "${current}" is already started, so "${attempted}" cannot be: stop it, or call start({ replace: true }).`
|
|
2464
|
-
});
|
|
2465
|
-
var InvalidApplicationEnvironment2 = exceptionOf2({
|
|
2466
|
-
layer: "environment" /* Environment */,
|
|
2467
|
-
name: "InvalidApplicationEnvironment",
|
|
2468
|
-
message: ({
|
|
2469
|
-
environments
|
|
2470
|
-
}) => `Invalid environment variables: ${Object.entries(environments).map(([name, keys]) => `${name} (${keys.join(", ")})`).join("; ")}.`
|
|
2471
|
-
});
|
|
2472
|
-
|
|
2473
2750
|
// src/core/openapi/exceptions.ts
|
|
2474
2751
|
var InvalidOpenAPIModel2 = exceptionOf2({
|
|
2475
2752
|
layer: "output" /* Output */,
|
|
@@ -2502,18 +2779,19 @@ function isExportedException(Declared) {
|
|
|
2502
2779
|
if (!collected) {
|
|
2503
2780
|
collected = true;
|
|
2504
2781
|
for (const module of [
|
|
2505
|
-
exports_exceptions8,
|
|
2506
|
-
exports_exceptions2,
|
|
2507
|
-
exports_exceptions7,
|
|
2508
2782
|
exports_exceptions4,
|
|
2509
|
-
|
|
2783
|
+
exports_exceptions2,
|
|
2510
2784
|
exports_exceptions9,
|
|
2785
|
+
exports_exceptions6,
|
|
2786
|
+
exports_environment,
|
|
2787
|
+
exports_exceptions5,
|
|
2511
2788
|
exports_exceptions10,
|
|
2789
|
+
exports_exceptions11,
|
|
2512
2790
|
exports_exceptions3,
|
|
2513
2791
|
exports_exceptions,
|
|
2514
|
-
|
|
2792
|
+
exports_exceptions7,
|
|
2515
2793
|
exports_use_case,
|
|
2516
|
-
|
|
2794
|
+
exports_exceptions8
|
|
2517
2795
|
]) {
|
|
2518
2796
|
markExported(...Object.values(module));
|
|
2519
2797
|
}
|
|
@@ -2635,28 +2913,28 @@ function toOpenAPI2(modelOrModels, { refPrefix = "#/components/schemas/" } = {})
|
|
|
2635
2913
|
var descriptions2 = new WeakMap;
|
|
2636
2914
|
var factories = new WeakMap;
|
|
2637
2915
|
var opaque2 = Object.freeze({ kind: "opaque" });
|
|
2638
|
-
function
|
|
2916
|
+
function invalid4(source, reason) {
|
|
2639
2917
|
throw new InvalidOutputStage2({ source, details: { reason } });
|
|
2640
2918
|
}
|
|
2641
2919
|
function optionsOf(name, given, validate) {
|
|
2642
|
-
const options = frozenJson(given ?? {}, "Stage options", (reason) =>
|
|
2920
|
+
const options = frozenJson(given ?? {}, "Stage options", (reason) => invalid4(name, reason));
|
|
2643
2921
|
if (options === null || typeof options !== "object" || Array.isArray(options)) {
|
|
2644
|
-
|
|
2922
|
+
invalid4(name, "Stage options must be an object.");
|
|
2645
2923
|
}
|
|
2646
2924
|
const reason = validate?.(options);
|
|
2647
2925
|
if (reason !== undefined)
|
|
2648
|
-
|
|
2926
|
+
invalid4(name, reason);
|
|
2649
2927
|
return options;
|
|
2650
2928
|
}
|
|
2651
2929
|
function checkName(source, name) {
|
|
2652
2930
|
if (typeof name !== "string" || !name.trim()) {
|
|
2653
|
-
|
|
2931
|
+
invalid4(source, "Expected the stage name to be a non-empty string.");
|
|
2654
2932
|
}
|
|
2655
2933
|
}
|
|
2656
2934
|
function transformOf2(settings) {
|
|
2657
2935
|
checkName("transformOf", settings?.name);
|
|
2658
2936
|
if (typeof settings.apply !== "function") {
|
|
2659
|
-
|
|
2937
|
+
invalid4(settings.name, "Expected apply to be a function.");
|
|
2660
2938
|
}
|
|
2661
2939
|
const { name, apply, validate } = settings;
|
|
2662
2940
|
const factory = (given) => {
|
|
@@ -2680,7 +2958,7 @@ function transformOf2(settings) {
|
|
|
2680
2958
|
function sinkOf2(settings) {
|
|
2681
2959
|
checkName("sinkOf", settings?.name);
|
|
2682
2960
|
if (typeof settings.build !== "function") {
|
|
2683
|
-
|
|
2961
|
+
invalid4(settings.name, "Expected build to be a function.");
|
|
2684
2962
|
}
|
|
2685
2963
|
const { name, build, validate } = settings;
|
|
2686
2964
|
const factory = (given) => {
|
|
@@ -2718,10 +2996,10 @@ function stageCatalogOf2(...stages) {
|
|
|
2718
2996
|
for (const factory of stages) {
|
|
2719
2997
|
const known = factories.get(factory);
|
|
2720
2998
|
if (!known) {
|
|
2721
|
-
|
|
2999
|
+
invalid4("catalog", "A catalog takes factories made by `transformOf` or `sinkOf`.");
|
|
2722
3000
|
}
|
|
2723
3001
|
if (Object.hasOwn(byName, known.name)) {
|
|
2724
|
-
|
|
3002
|
+
invalid4(known.name, "The catalog has another stage with its name.");
|
|
2725
3003
|
}
|
|
2726
3004
|
byName[known.name] = factory;
|
|
2727
3005
|
}
|
|
@@ -2732,7 +3010,7 @@ function stageCatalogOf2(...stages) {
|
|
|
2732
3010
|
resolve(name, options) {
|
|
2733
3011
|
const factory = Object.hasOwn(byName, name) ? byName[name] : undefined;
|
|
2734
3012
|
if (!factory)
|
|
2735
|
-
|
|
3013
|
+
invalid4("catalog", `Unknown stage "${name}".`);
|
|
2736
3014
|
return factory(options);
|
|
2737
3015
|
}
|
|
2738
3016
|
});
|
|
@@ -2742,38 +3020,38 @@ function stageCatalogOf2(...stages) {
|
|
|
2742
3020
|
function isApplicationLike(value) {
|
|
2743
3021
|
return typeof value === "object" && value !== null && value[Kind2] === "application";
|
|
2744
3022
|
}
|
|
2745
|
-
function
|
|
3023
|
+
function invalid5(source, reason) {
|
|
2746
3024
|
throw new InvalidOutputStage2({ source, details: { reason } });
|
|
2747
3025
|
}
|
|
2748
3026
|
var PATCHABLE = ["meta", "tags", "description", "deprecated", "invoke"];
|
|
2749
3027
|
function operationOf2(operation, patch) {
|
|
2750
3028
|
const source = operation?.id ?? "operationOf";
|
|
2751
3029
|
if (operation?.kind !== "operation" || operation.version !== 1) {
|
|
2752
|
-
|
|
3030
|
+
invalid5(source, "Expected an operation descriptor.");
|
|
2753
3031
|
}
|
|
2754
3032
|
if (typeof patch !== "object" || patch === null || Array.isArray(patch)) {
|
|
2755
|
-
|
|
3033
|
+
invalid5(source, "Expected the patch to be an object.");
|
|
2756
3034
|
}
|
|
2757
3035
|
for (const key of Reflect.ownKeys(patch)) {
|
|
2758
3036
|
if (typeof key !== "string" || !PATCHABLE.includes(key)) {
|
|
2759
|
-
|
|
3037
|
+
invalid5(source, `"${String(key)}" cannot be patched; only ${PATCHABLE.join(", ")} can.`);
|
|
2760
3038
|
}
|
|
2761
3039
|
}
|
|
2762
3040
|
const { meta, tags, description, deprecated, invoke } = patch;
|
|
2763
3041
|
if ("meta" in patch && (typeof meta !== "object" || meta === null || Array.isArray(meta))) {
|
|
2764
|
-
|
|
3042
|
+
invalid5(source, "Expected meta to be an object.");
|
|
2765
3043
|
}
|
|
2766
3044
|
if ("tags" in patch && (!Array.isArray(tags) || tags.some((tag) => typeof tag !== "string"))) {
|
|
2767
|
-
|
|
3045
|
+
invalid5(source, "Expected tags to be a list of strings.");
|
|
2768
3046
|
}
|
|
2769
3047
|
if ("description" in patch && description !== undefined && typeof description !== "string") {
|
|
2770
|
-
|
|
3048
|
+
invalid5(source, "Expected description to be a string.");
|
|
2771
3049
|
}
|
|
2772
3050
|
if ("deprecated" in patch && typeof deprecated !== "boolean") {
|
|
2773
|
-
|
|
3051
|
+
invalid5(source, "Expected deprecated to be a boolean.");
|
|
2774
3052
|
}
|
|
2775
3053
|
if ("invoke" in patch && typeof invoke !== "function") {
|
|
2776
|
-
|
|
3054
|
+
invalid5(source, "Expected invoke to be a function.");
|
|
2777
3055
|
}
|
|
2778
3056
|
return Object.freeze({
|
|
2779
3057
|
...operation,
|
|
@@ -2814,25 +3092,25 @@ function statusesOf(name, statuses) {
|
|
|
2814
3092
|
if (statuses === undefined)
|
|
2815
3093
|
return Object.freeze({});
|
|
2816
3094
|
if (typeof statuses !== "object" || statuses === null || Array.isArray(statuses)) {
|
|
2817
|
-
|
|
3095
|
+
invalid5(name, "Expected statuses to be a map of exception names to statuses.");
|
|
2818
3096
|
}
|
|
2819
3097
|
for (const [exception, status] of Object.entries(statuses)) {
|
|
2820
3098
|
if (!exception || typeof status !== "number" || !Number.isInteger(status) || status < 400 || status > 599) {
|
|
2821
|
-
|
|
3099
|
+
invalid5(name, `Expected the status of "${exception}" to be an integer between 400 and 599.`);
|
|
2822
3100
|
}
|
|
2823
3101
|
}
|
|
2824
3102
|
return Object.freeze({ ...statuses });
|
|
2825
3103
|
}
|
|
2826
3104
|
function checkPipe(name, pipe) {
|
|
2827
3105
|
if (!Array.isArray(pipe))
|
|
2828
|
-
|
|
3106
|
+
invalid5(name, "Expected pipe to be a list of stages.");
|
|
2829
3107
|
const stages = pipe;
|
|
2830
3108
|
stages.forEach((stage, index) => {
|
|
2831
3109
|
if (!isStage(stage)) {
|
|
2832
|
-
|
|
3110
|
+
invalid5(name, `Expected pipe[${index}] to be a transform or sink stage.`);
|
|
2833
3111
|
}
|
|
2834
3112
|
if (stage.kind === "sink" && index !== stages.length - 1) {
|
|
2835
|
-
|
|
3113
|
+
invalid5(name, `The sink at pipe[${index}] must be the last stage.`);
|
|
2836
3114
|
}
|
|
2837
3115
|
});
|
|
2838
3116
|
return Object.freeze([...stages]);
|
|
@@ -2848,7 +3126,7 @@ function transformed(name, operations, transforms, context) {
|
|
|
2848
3126
|
if (result === null)
|
|
2849
3127
|
continue;
|
|
2850
3128
|
if (typeof result !== "object" || result?.kind !== "operation" || result.id !== operation.id) {
|
|
2851
|
-
|
|
3129
|
+
invalid5(name, `A transform must return the operation "${operation.id}" or null.`);
|
|
2852
3130
|
}
|
|
2853
3131
|
next.push(result);
|
|
2854
3132
|
}
|
|
@@ -2873,7 +3151,7 @@ function make(name, commands, operations, stages, statuses) {
|
|
|
2873
3151
|
return built.value;
|
|
2874
3152
|
const sink = stages.at(-1);
|
|
2875
3153
|
if (sink?.kind !== "sink") {
|
|
2876
|
-
|
|
3154
|
+
invalid5(name || "output", "The pipe has no sink to build.");
|
|
2877
3155
|
}
|
|
2878
3156
|
built = { value: sink.build(operations, context) };
|
|
2879
3157
|
return built.value;
|
|
@@ -2882,7 +3160,7 @@ function make(name, commands, operations, stages, statuses) {
|
|
|
2882
3160
|
const next = checkPipe(name || "output", more);
|
|
2883
3161
|
const last = next.at(-1);
|
|
2884
3162
|
if (stages.at(-1)?.kind === "sink") {
|
|
2885
|
-
|
|
3163
|
+
invalid5(name || "output", "Cannot add stages after the sink.");
|
|
2886
3164
|
}
|
|
2887
3165
|
const ops = transformed(name, operations, next, context);
|
|
2888
3166
|
if (last?.kind === "sink") {
|
|
@@ -2896,11 +3174,11 @@ function make(name, commands, operations, stages, statuses) {
|
|
|
2896
3174
|
function outputOf2(settings) {
|
|
2897
3175
|
const { name, commands } = settings ?? {};
|
|
2898
3176
|
if (typeof name !== "string" || !name.trim()) {
|
|
2899
|
-
|
|
3177
|
+
invalid5("outputOf", "Expected name to be a non-empty string.");
|
|
2900
3178
|
}
|
|
2901
3179
|
const sources = Array.isArray(commands) ? commands : [commands];
|
|
2902
3180
|
if (!Array.isArray(commands) && isCommand2(commands) || sources.some((entry) => !isCommand2(entry) && !isApplicationLike(entry))) {
|
|
2903
|
-
|
|
3181
|
+
invalid5(name, "Expected commands to be a list of commands made by commandOf or applications.");
|
|
2904
3182
|
}
|
|
2905
3183
|
const flat = [
|
|
2906
3184
|
...new Set(sources.flatMap((entry) => isCommand2(entry) ? [entry] : Object.values(entry.commands)))
|
|
@@ -2944,32 +3222,16 @@ function describeSteps(steps, names) {
|
|
|
2944
3222
|
});
|
|
2945
3223
|
}
|
|
2946
3224
|
|
|
2947
|
-
// src/core/application/registry.ts
|
|
2948
|
-
var SLOT = Symbol.for("afora.application");
|
|
2949
|
-
function slot() {
|
|
2950
|
-
const global = globalThis;
|
|
2951
|
-
global[SLOT] ??= { current: undefined };
|
|
2952
|
-
return global[SLOT];
|
|
2953
|
-
}
|
|
2954
|
-
function useApplication2() {
|
|
2955
|
-
const { current } = slot();
|
|
2956
|
-
if (current === undefined) {
|
|
2957
|
-
throw new ApplicationNotStarted2({ source: "useApplication", details: {} });
|
|
2958
|
-
}
|
|
2959
|
-
return current;
|
|
2960
|
-
}
|
|
2961
|
-
function resetApplication2() {
|
|
2962
|
-
slot().current = undefined;
|
|
2963
|
-
}
|
|
2964
|
-
function startedApplication() {
|
|
2965
|
-
return slot().current;
|
|
2966
|
-
}
|
|
2967
|
-
function setStartedApplication(application) {
|
|
2968
|
-
slot().current = application;
|
|
2969
|
-
}
|
|
2970
|
-
|
|
2971
3225
|
// src/core/application/start.ts
|
|
2972
3226
|
function providerFrom2(environmentDependencies, create) {
|
|
3227
|
+
if (typeof environmentDependencies === "function" && create === undefined) {
|
|
3228
|
+
return Object.freeze({
|
|
3229
|
+
[Kind2]: "provider-factory",
|
|
3230
|
+
environments: Object.freeze([]),
|
|
3231
|
+
create: environmentDependencies,
|
|
3232
|
+
withContext: true
|
|
3233
|
+
});
|
|
3234
|
+
}
|
|
2973
3235
|
const list = isEnvironment2(environmentDependencies) ? [environmentDependencies] : Array.isArray(environmentDependencies) ? [...environmentDependencies] : [null];
|
|
2974
3236
|
if (!list.every(isEnvironment2) || new Set(list).size !== list.length || typeof create !== "function") {
|
|
2975
3237
|
throw new InvalidApplicationDeclaration2({
|
|
@@ -2982,9 +3244,22 @@ function providerFrom2(environmentDependencies, create) {
|
|
|
2982
3244
|
return Object.freeze({
|
|
2983
3245
|
[Kind2]: "provider-factory",
|
|
2984
3246
|
environments: Object.freeze(list),
|
|
2985
|
-
create
|
|
3247
|
+
create,
|
|
3248
|
+
withContext: false
|
|
2986
3249
|
});
|
|
2987
3250
|
}
|
|
3251
|
+
function logFrom2(create) {
|
|
3252
|
+
if (typeof create !== "function") {
|
|
3253
|
+
throw new InvalidApplicationDeclaration2({
|
|
3254
|
+
source: "logFrom",
|
|
3255
|
+
details: { reason: "Expected logFrom to take a create function." }
|
|
3256
|
+
});
|
|
3257
|
+
}
|
|
3258
|
+
return Object.freeze({ [Kind2]: "log-factory", create });
|
|
3259
|
+
}
|
|
3260
|
+
function isLogFactory2(value) {
|
|
3261
|
+
return typeof value === "object" && value !== null && value[Kind2] === "log-factory";
|
|
3262
|
+
}
|
|
2988
3263
|
function isProviderFactory2(value) {
|
|
2989
3264
|
return typeof value === "object" && value !== null && value[Kind2] === "provider-factory";
|
|
2990
3265
|
}
|
|
@@ -3041,12 +3316,12 @@ function isDeferredProvider(provider) {
|
|
|
3041
3316
|
function deferredEnvironments(provider) {
|
|
3042
3317
|
return (typeof provider === "object" && provider !== null ? deferred.get(provider)?.factory.environments : undefined) ?? [];
|
|
3043
3318
|
}
|
|
3044
|
-
function startDeferred(provider) {
|
|
3319
|
+
function startDeferred(provider, context) {
|
|
3045
3320
|
const state = deferred.get(provider);
|
|
3046
3321
|
if (!state)
|
|
3047
3322
|
return;
|
|
3048
3323
|
state.starting ??= (async () => {
|
|
3049
|
-
const made = await state.factory.create(loadEnvironments(state.factory.environments));
|
|
3324
|
+
const made = await state.factory.create(state.factory.withContext ? context : loadEnvironments(state.factory.environments));
|
|
3050
3325
|
if (typeof made !== "object" || made === null) {
|
|
3051
3326
|
state.starting = undefined;
|
|
3052
3327
|
throw new InvalidApplicationDeclaration2({
|
|
@@ -3085,6 +3360,106 @@ function checkTransactions(source, provider, commands) {
|
|
|
3085
3360
|
}
|
|
3086
3361
|
}
|
|
3087
3362
|
|
|
3363
|
+
// src/core/application/providers.ts
|
|
3364
|
+
var slots = new WeakMap;
|
|
3365
|
+
var storages = new WeakMap;
|
|
3366
|
+
var METHODS2 = [
|
|
3367
|
+
"findOne",
|
|
3368
|
+
"findMany",
|
|
3369
|
+
"insert",
|
|
3370
|
+
"update",
|
|
3371
|
+
"remove",
|
|
3372
|
+
"count"
|
|
3373
|
+
];
|
|
3374
|
+
var KEY = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
|
|
3375
|
+
var RESERVED = new Set(["inMemory", "__proto__", "constructor", "prototype"]);
|
|
3376
|
+
function invalid6(reason) {
|
|
3377
|
+
throw new InvalidApplicationDeclaration2({
|
|
3378
|
+
source: "providersOf",
|
|
3379
|
+
details: { reason }
|
|
3380
|
+
});
|
|
3381
|
+
}
|
|
3382
|
+
function isProviderObject(value) {
|
|
3383
|
+
return typeof value === "object" && value !== null && !isProviderFactory2(value) && METHODS2.some((method) => typeof value[method] === "function");
|
|
3384
|
+
}
|
|
3385
|
+
function slotOf(key, storage, value) {
|
|
3386
|
+
const slot = {
|
|
3387
|
+
[Kind2]: "provider-slot",
|
|
3388
|
+
key
|
|
3389
|
+
};
|
|
3390
|
+
if (isProviderFactory2(value)) {
|
|
3391
|
+
const unbound = () => {
|
|
3392
|
+
throw new ProviderNotBound2({ source: key, details: { provider: key } });
|
|
3393
|
+
};
|
|
3394
|
+
for (const method of METHODS2)
|
|
3395
|
+
slot[method] = unbound;
|
|
3396
|
+
slot.transaction = unbound;
|
|
3397
|
+
Object.defineProperty(slot, "capabilities", {
|
|
3398
|
+
get: () => {
|
|
3399
|
+
return;
|
|
3400
|
+
},
|
|
3401
|
+
enumerable: true
|
|
3402
|
+
});
|
|
3403
|
+
} else {
|
|
3404
|
+
const target = value;
|
|
3405
|
+
for (const method of [...METHODS2, "transaction", "close"]) {
|
|
3406
|
+
if (typeof target[method] === "function") {
|
|
3407
|
+
slot[method] = (...args) => target[method]?.(...args);
|
|
3408
|
+
}
|
|
3409
|
+
}
|
|
3410
|
+
Object.defineProperty(slot, "capabilities", {
|
|
3411
|
+
get: () => value.capabilities,
|
|
3412
|
+
enumerable: true
|
|
3413
|
+
});
|
|
3414
|
+
}
|
|
3415
|
+
Object.freeze(slot);
|
|
3416
|
+
slots.set(slot, { key, storage, value });
|
|
3417
|
+
return slot;
|
|
3418
|
+
}
|
|
3419
|
+
function providersOf2(entries) {
|
|
3420
|
+
if (typeof entries !== "object" || entries === null || Array.isArray(entries) || Object.keys(entries).length === 0) {
|
|
3421
|
+
invalid6("Expected an object of providers by key.");
|
|
3422
|
+
}
|
|
3423
|
+
const storage = Object.create(null);
|
|
3424
|
+
storage[Kind2] = "provider-storage";
|
|
3425
|
+
const seen = new Map;
|
|
3426
|
+
const list = [];
|
|
3427
|
+
for (const [key, value] of Object.entries(entries)) {
|
|
3428
|
+
if (!KEY.test(key) || RESERVED.has(key)) {
|
|
3429
|
+
invalid6(key === "inMemory" ? `"inMemory" is the built-in provider; choose another key.` : `Expected "${key}" to be an identifier that is not reserved.`);
|
|
3430
|
+
}
|
|
3431
|
+
if (isProviderSlot2(value)) {
|
|
3432
|
+
invalid6(`"${key}" holds a provider of another storage; a storage holds providers, not slots.`);
|
|
3433
|
+
}
|
|
3434
|
+
if (!isProviderFactory2(value) && !isProviderObject(value)) {
|
|
3435
|
+
invalid6(`Expected "${key}" to be a repository provider or a factory of providerFrom.`);
|
|
3436
|
+
}
|
|
3437
|
+
const other = seen.get(value);
|
|
3438
|
+
if (other !== undefined) {
|
|
3439
|
+
invalid6(`"${other}" and "${key}" hold the same provider.`);
|
|
3440
|
+
}
|
|
3441
|
+
seen.set(value, key);
|
|
3442
|
+
const slot = slotOf(key, storage, value);
|
|
3443
|
+
storage[key] = slot;
|
|
3444
|
+
list.push(slot);
|
|
3445
|
+
}
|
|
3446
|
+
Object.freeze(storage);
|
|
3447
|
+
storages.set(storage, Object.freeze(list));
|
|
3448
|
+
return storage;
|
|
3449
|
+
}
|
|
3450
|
+
function isProviderSlot2(value) {
|
|
3451
|
+
return typeof value === "object" && value !== null && slots.has(value);
|
|
3452
|
+
}
|
|
3453
|
+
function isProviderStorage2(value) {
|
|
3454
|
+
return typeof value === "object" && value !== null && storages.has(value);
|
|
3455
|
+
}
|
|
3456
|
+
function slotsOf(storage) {
|
|
3457
|
+
return storages.get(storage) ?? [];
|
|
3458
|
+
}
|
|
3459
|
+
function slotEntry(slot) {
|
|
3460
|
+
return slots.get(slot);
|
|
3461
|
+
}
|
|
3462
|
+
|
|
3088
3463
|
// src/core/application/application.ts
|
|
3089
3464
|
var KEYS = [
|
|
3090
3465
|
"properties",
|
|
@@ -3099,6 +3474,12 @@ var KEYS = [
|
|
|
3099
3474
|
"exceptions"
|
|
3100
3475
|
];
|
|
3101
3476
|
var internals = new WeakMap;
|
|
3477
|
+
var logSettings = new WeakMap;
|
|
3478
|
+
var namedProviders = new WeakMap;
|
|
3479
|
+
var defaultSlots = new WeakMap;
|
|
3480
|
+
function referenceOf(slot) {
|
|
3481
|
+
return { kind: "ref", key: slotEntry(slot).key };
|
|
3482
|
+
}
|
|
3102
3483
|
var KIND_OF = {
|
|
3103
3484
|
properties: "property",
|
|
3104
3485
|
blueprints: "blueprint",
|
|
@@ -3114,7 +3495,7 @@ var KIND_OF = {
|
|
|
3114
3495
|
function isApplication2(value) {
|
|
3115
3496
|
return typeof value === "object" && value !== null && value[Kind2] === "application";
|
|
3116
3497
|
}
|
|
3117
|
-
function
|
|
3498
|
+
function invalid7(source, reason) {
|
|
3118
3499
|
throw new InvalidApplicationDeclaration2({ source, details: { reason } });
|
|
3119
3500
|
}
|
|
3120
3501
|
function isOfKind(collection, value) {
|
|
@@ -3199,7 +3580,7 @@ function resolve(settings) {
|
|
|
3199
3580
|
for (const other of settings.extends ?? []) {
|
|
3200
3581
|
const resolved = internals.get(other);
|
|
3201
3582
|
if (!resolved)
|
|
3202
|
-
|
|
3583
|
+
invalid7(source, "Expected `extends` to hold applications.");
|
|
3203
3584
|
for (const key of KEYS) {
|
|
3204
3585
|
for (const entry of resolved[key].values())
|
|
3205
3586
|
add(entry);
|
|
@@ -3210,15 +3591,15 @@ function resolve(settings) {
|
|
|
3210
3591
|
if (declared === undefined)
|
|
3211
3592
|
continue;
|
|
3212
3593
|
if (typeof declared !== "object" || declared === null || Array.isArray(declared)) {
|
|
3213
|
-
|
|
3594
|
+
invalid7(source, `Expected ${collection} to be an object of declarations.`);
|
|
3214
3595
|
}
|
|
3215
3596
|
for (const [name, value] of Object.entries(declared)) {
|
|
3216
3597
|
if (!isOfKind(collection, value)) {
|
|
3217
|
-
|
|
3598
|
+
invalid7(source, `${collection}.${name} is not a ${KIND_OF[collection]} (${collection} takes ${KIND_OF[collection]} declarations).`);
|
|
3218
3599
|
}
|
|
3219
3600
|
const declaredName = collection === "useCases" ? value.useCaseName : collection === "commands" ? value.commandName : collection === "outputs" ? value.outputName : collection === "exceptions" ? value.name : name;
|
|
3220
3601
|
if (declaredName !== name) {
|
|
3221
|
-
|
|
3602
|
+
invalid7(source, `${collection}.${name} must be keyed by its name, "${declaredName}".`);
|
|
3222
3603
|
}
|
|
3223
3604
|
add({
|
|
3224
3605
|
collection,
|
|
@@ -3339,7 +3720,7 @@ function validateOutputs(source, registry) {
|
|
|
3339
3720
|
for (const entry of registry.outputs.values()) {
|
|
3340
3721
|
const output = entry.value;
|
|
3341
3722
|
if (!output.outputName) {
|
|
3342
|
-
|
|
3723
|
+
invalid7(source, `outputs.${entry.name} has no name (an output made by pipe cannot be registered).`);
|
|
3343
3724
|
}
|
|
3344
3725
|
for (const command of output.commands) {
|
|
3345
3726
|
if (commands.has(command))
|
|
@@ -3369,7 +3750,7 @@ function validateUseCases(source, registry) {
|
|
|
3369
3750
|
for (const entry of registry.useCases.values()) {
|
|
3370
3751
|
const UseCase = entry.value;
|
|
3371
3752
|
for (const [key, dependency] of Object.entries(UseCase.dependencies)) {
|
|
3372
|
-
const found = isUseCaseClass2(dependency) ? useCases.has(dependency) : isEnvironment2(dependency) ? environments.has(dependency) : repositories.has(inspectRepository(dependency).state);
|
|
3753
|
+
const found = isLoggerDeclaration(dependency) ? true : isUseCaseClass2(dependency) ? useCases.has(dependency) : isEnvironment2(dependency) ? environments.has(dependency) : repositories.has(inspectRepository(dependency).state);
|
|
3373
3754
|
if (!found) {
|
|
3374
3755
|
throw new UnregisteredUseCaseDependency2({
|
|
3375
3756
|
source,
|
|
@@ -3541,7 +3922,7 @@ function recordDescriptionOf(entry, scope) {
|
|
|
3541
3922
|
plugins
|
|
3542
3923
|
};
|
|
3543
3924
|
}
|
|
3544
|
-
function describeRegistry(name, extended, registry, provider) {
|
|
3925
|
+
function describeRegistry(name, extended, registry, provider, named, log) {
|
|
3545
3926
|
const scope = {
|
|
3546
3927
|
properties: referencesOf(registry, "properties"),
|
|
3547
3928
|
blueprints: referencesOf(registry, "blueprints"),
|
|
@@ -3581,7 +3962,28 @@ function describeRegistry(name, extended, registry, provider) {
|
|
|
3581
3962
|
return {
|
|
3582
3963
|
name,
|
|
3583
3964
|
extends: extended.map((other) => other.name),
|
|
3584
|
-
...provider === undefined ? {} : { provider
|
|
3965
|
+
...provider === undefined ? {} : { provider },
|
|
3966
|
+
...named.size === 0 ? {} : {
|
|
3967
|
+
providers: Object.fromEntries([...named].map(([key, { slot, from }]) => {
|
|
3968
|
+
const { value } = slotEntry(slot);
|
|
3969
|
+
return [
|
|
3970
|
+
key,
|
|
3971
|
+
{
|
|
3972
|
+
from,
|
|
3973
|
+
...isProviderFactory2(value) ? { kind: "opaque" } : providerDescriptionOf2(value)
|
|
3974
|
+
}
|
|
3975
|
+
];
|
|
3976
|
+
}))
|
|
3977
|
+
},
|
|
3978
|
+
...log === undefined ? {} : log === "opaque" ? { log: { kind: "opaque" } } : {
|
|
3979
|
+
log: {
|
|
3980
|
+
level: log.level,
|
|
3981
|
+
providers: log.providers.map((logProvider) => {
|
|
3982
|
+
const providerName = logProviderNameOf(logProvider);
|
|
3983
|
+
return providerName === undefined ? { kind: "opaque" } : { kind: "log-provider", name: providerName };
|
|
3984
|
+
})
|
|
3985
|
+
}
|
|
3986
|
+
},
|
|
3585
3987
|
properties: each("properties", (entry) => ({
|
|
3586
3988
|
from: entry.from,
|
|
3587
3989
|
...propertyDescriptionOf(entry.value, scope)
|
|
@@ -3605,7 +4007,9 @@ function describeRegistry(name, extended, registry, provider) {
|
|
|
3605
4007
|
deletion: info.deletion,
|
|
3606
4008
|
relations: info.relations.map((relation) => repositories.get(relation)),
|
|
3607
4009
|
environments: info.environments.map((environment) => environmentRefs.get(environment)),
|
|
3608
|
-
...info.provider === undefined ? {} : {
|
|
4010
|
+
...info.provider === undefined ? {} : {
|
|
4011
|
+
provider: isProviderSlot2(info.provider) ? referenceOf(info.provider) : providerDescriptionOf2(info.provider)
|
|
4012
|
+
}
|
|
3609
4013
|
};
|
|
3610
4014
|
}),
|
|
3611
4015
|
useCases: each("useCases", (entry) => {
|
|
@@ -3632,7 +4036,10 @@ function describeRegistry(name, extended, registry, provider) {
|
|
|
3632
4036
|
}),
|
|
3633
4037
|
dependencies: Object.fromEntries(Object.entries(UseCase.dependencies).map(([key, dependency]) => [
|
|
3634
4038
|
key,
|
|
3635
|
-
|
|
4039
|
+
isLoggerDeclaration(dependency) ? { kind: "logger", ref: "Logger" } : isUseCaseClass2(dependency) ? {
|
|
4040
|
+
kind: "use-case",
|
|
4041
|
+
ref: useCaseRefs.get(dependency)
|
|
4042
|
+
} : isEnvironment2(dependency) ? {
|
|
3636
4043
|
kind: "environment",
|
|
3637
4044
|
ref: environmentRefs.get(dependency)
|
|
3638
4045
|
} : {
|
|
@@ -3690,49 +4097,123 @@ function describeRegistry(name, extended, registry, provider) {
|
|
|
3690
4097
|
function applicationOf2(settings) {
|
|
3691
4098
|
const { name } = settings ?? {};
|
|
3692
4099
|
if (typeof name !== "string" || name === "") {
|
|
3693
|
-
|
|
4100
|
+
invalid7("applicationOf", "Expected a name.");
|
|
3694
4101
|
}
|
|
3695
4102
|
const extended = settings.extends ?? [];
|
|
3696
4103
|
if (!Array.isArray(extended) || !extended.every(isApplication2)) {
|
|
3697
|
-
|
|
4104
|
+
invalid7(name, "Expected `extends` to be a list of applications.");
|
|
3698
4105
|
}
|
|
3699
4106
|
const registry = resolve(settings);
|
|
3700
4107
|
validate(name, registry);
|
|
3701
4108
|
validateUseCases(name, registry);
|
|
3702
4109
|
validateCommands(name, registry);
|
|
3703
4110
|
validateOutputs(name, registry);
|
|
3704
|
-
|
|
3705
|
-
|
|
3706
|
-
invalid5(name, "Expected `provider` to be a repository provider.");
|
|
4111
|
+
if (settings.providers !== undefined && !isProviderStorage2(settings.providers)) {
|
|
4112
|
+
invalid7(name, "Expected `providers` to be a storage made by providersOf.");
|
|
3707
4113
|
}
|
|
3708
|
-
const
|
|
3709
|
-
{
|
|
3710
|
-
const
|
|
3711
|
-
|
|
3712
|
-
|
|
3713
|
-
|
|
4114
|
+
const named = new Map;
|
|
4115
|
+
const addNamed = (entry) => {
|
|
4116
|
+
const { key } = slotEntry(entry.slot);
|
|
4117
|
+
const current = named.get(key);
|
|
4118
|
+
if (current !== undefined && current.slot !== entry.slot) {
|
|
4119
|
+
throw new ApplicationConflict2({
|
|
4120
|
+
source: name,
|
|
4121
|
+
details: {
|
|
4122
|
+
reason: `The provider "${key}" is declared by different storages, in "${current.from}" and "${entry.from}".`,
|
|
4123
|
+
origins: [current.from, entry.from],
|
|
4124
|
+
declarations: [`provider ${key}`, `provider ${key}`]
|
|
4125
|
+
}
|
|
4126
|
+
});
|
|
4127
|
+
}
|
|
4128
|
+
named.set(key, entry);
|
|
4129
|
+
};
|
|
4130
|
+
for (const other of extended) {
|
|
4131
|
+
for (const entry of namedProviders.get(other)?.values() ?? []) {
|
|
4132
|
+
addNamed(entry);
|
|
4133
|
+
}
|
|
4134
|
+
}
|
|
4135
|
+
for (const slot of settings.providers ? slotsOf(settings.providers) : []) {
|
|
4136
|
+
const inherited = named.get(slotEntry(slot).key);
|
|
4137
|
+
if (inherited?.slot === slot)
|
|
4138
|
+
continue;
|
|
4139
|
+
const { value } = slotEntry(slot);
|
|
4140
|
+
addNamed({
|
|
4141
|
+
slot,
|
|
4142
|
+
from: name,
|
|
4143
|
+
instance: isProviderFactory2(value) ? deferredProvider(value, name) : value
|
|
4144
|
+
});
|
|
4145
|
+
}
|
|
4146
|
+
const instances = new Map([...named.values()].map((entry) => [entry.slot, entry.instance]));
|
|
4147
|
+
const instanceOf = (slot, holder) => {
|
|
4148
|
+
const instance = instances.get(slot);
|
|
4149
|
+
if (instance === undefined) {
|
|
3714
4150
|
throw new UnregisteredApplicationReference2({
|
|
3715
4151
|
source: name,
|
|
3716
4152
|
details: {
|
|
3717
|
-
holder
|
|
3718
|
-
reference:
|
|
4153
|
+
holder,
|
|
4154
|
+
reference: `provider "${slotEntry(slot).key}"`
|
|
3719
4155
|
}
|
|
3720
4156
|
});
|
|
3721
4157
|
}
|
|
4158
|
+
return instance;
|
|
4159
|
+
};
|
|
4160
|
+
for (const entry of registry.repositories.values()) {
|
|
4161
|
+
const declared = inspectRepository(entry.value).provider;
|
|
4162
|
+
if (isProviderSlot2(declared)) {
|
|
4163
|
+
instanceOf(declared, `repository "${entry.name}"`);
|
|
4164
|
+
}
|
|
3722
4165
|
}
|
|
4166
|
+
const inheritedFrom = settings.provider === undefined ? [...extended].reverse().find((other) => other.provider) : undefined;
|
|
4167
|
+
const declaredProvider = settings.provider ?? inheritedFrom?.provider;
|
|
4168
|
+
if (declaredProvider !== undefined && typeof declaredProvider !== "object") {
|
|
4169
|
+
invalid7(name, "Expected `provider` to be a repository provider.");
|
|
4170
|
+
}
|
|
4171
|
+
const defaultSlot = isProviderSlot2(declaredProvider) ? declaredProvider : inheritedFrom === undefined ? undefined : defaultSlots.get(inheritedFrom);
|
|
4172
|
+
const provider = defaultSlot !== undefined ? instanceOf(defaultSlot, "the application") : isProviderFactory2(declaredProvider) ? deferredProvider(declaredProvider, name) : declaredProvider;
|
|
4173
|
+
const allProviders = [
|
|
4174
|
+
...new Set([provider, ...instances.values()].filter((value) => value !== undefined))
|
|
4175
|
+
];
|
|
4176
|
+
{
|
|
4177
|
+
const registered = new Set([...registry.environments.values()].map((entry) => entry.key));
|
|
4178
|
+
const holderOf = (instance) => {
|
|
4179
|
+
const entry = [...named.values()].find((candidate) => candidate.instance === instance);
|
|
4180
|
+
return entry === undefined || instance === provider ? "the provider" : `provider "${slotEntry(entry.slot).key}"`;
|
|
4181
|
+
};
|
|
4182
|
+
for (const instance of allProviders) {
|
|
4183
|
+
for (const environment of deferredEnvironments(instance)) {
|
|
4184
|
+
if (registered.has(environment))
|
|
4185
|
+
continue;
|
|
4186
|
+
throw new UnregisteredApplicationReference2({
|
|
4187
|
+
source: name,
|
|
4188
|
+
details: {
|
|
4189
|
+
holder: holderOf(instance),
|
|
4190
|
+
reference: "an environment"
|
|
4191
|
+
}
|
|
4192
|
+
});
|
|
4193
|
+
}
|
|
4194
|
+
}
|
|
4195
|
+
}
|
|
4196
|
+
const declaredLog = settings.log ?? [...extended].reverse().map((other) => logSettings.get(other)).find((log) => log !== undefined);
|
|
4197
|
+
const log = declaredLog === undefined ? undefined : applicationLogger(name);
|
|
4198
|
+
if (declaredLog !== undefined && !isLogFactory2(declaredLog)) {
|
|
4199
|
+
log?.set(checkLogSettings(declaredLog));
|
|
4200
|
+
}
|
|
4201
|
+
const logger = log?.logger;
|
|
4202
|
+
const bindsProviders = provider !== undefined || instances.size > 0;
|
|
4203
|
+
const rebinds = bindsProviders || logger !== undefined;
|
|
3723
4204
|
const collection = (key) => Object.freeze(Object.fromEntries([...registry[key].values()].map((entry) => [entry.name, entry.value])));
|
|
3724
4205
|
const bound = new Map;
|
|
3725
4206
|
const boundByState = new Map;
|
|
3726
4207
|
const repositories = {};
|
|
3727
4208
|
for (const entry of registry.repositories.values()) {
|
|
3728
|
-
const repository =
|
|
4209
|
+
const repository = bindsProviders ? bindRepository(entry.value, provider, instances) : entry.value;
|
|
3729
4210
|
bound.set(entry.value, repository);
|
|
3730
4211
|
boundByState.set(entry.key, repository);
|
|
3731
4212
|
repositories[entry.name] = repository;
|
|
3732
4213
|
}
|
|
3733
4214
|
const boundUseCases = new Map;
|
|
3734
4215
|
const bindUseCase = (UseCase) => {
|
|
3735
|
-
if (
|
|
4216
|
+
if (!rebinds)
|
|
3736
4217
|
return UseCase;
|
|
3737
4218
|
const done = boundUseCases.get(UseCase);
|
|
3738
4219
|
if (done)
|
|
@@ -3745,11 +4226,13 @@ function applicationOf2(settings) {
|
|
|
3745
4226
|
boundUseCases.set(UseCase, Bound);
|
|
3746
4227
|
const dependencies = Object.fromEntries(Object.entries(UseCase.dependencies).map(([key, dependency]) => [
|
|
3747
4228
|
key,
|
|
3748
|
-
isUseCaseClass2(dependency) ? bindUseCase(dependency) : isEnvironment2(dependency) ? dependency : boundByState.get(inspectRepository(dependency).state) ?? dependency
|
|
4229
|
+
isUseCaseClass2(dependency) ? bindUseCase(dependency) : isEnvironment2(dependency) || isLoggerDeclaration(dependency) ? dependency : boundByState.get(inspectRepository(dependency).state) ?? dependency
|
|
3749
4230
|
]));
|
|
3750
4231
|
Object.defineProperty(Bound, "dependencies", {
|
|
3751
4232
|
value: Object.freeze(dependencies)
|
|
3752
4233
|
});
|
|
4234
|
+
if (logger)
|
|
4235
|
+
Object.defineProperty(Bound, ApplicationLoggerKey, { value: logger });
|
|
3753
4236
|
return Bound;
|
|
3754
4237
|
};
|
|
3755
4238
|
const useCases = {};
|
|
@@ -3763,7 +4246,7 @@ function applicationOf2(settings) {
|
|
|
3763
4246
|
const boundCommandOf = new Map;
|
|
3764
4247
|
for (const entry of registry.commands.values()) {
|
|
3765
4248
|
const declared = entry.value;
|
|
3766
|
-
const rebuilt =
|
|
4249
|
+
const rebuilt = !rebinds ? declared : commandOf2({
|
|
3767
4250
|
name: declared.commandName,
|
|
3768
4251
|
description: declared.description,
|
|
3769
4252
|
tags: declared.tags,
|
|
@@ -3777,7 +4260,7 @@ function applicationOf2(settings) {
|
|
|
3777
4260
|
events: declared.events,
|
|
3778
4261
|
onEventError: declared.onEventError
|
|
3779
4262
|
});
|
|
3780
|
-
if (
|
|
4263
|
+
if (bindsProviders)
|
|
3781
4264
|
verifyCommand(rebuilt);
|
|
3782
4265
|
boundCommandOf.set(entry.value, rebuilt);
|
|
3783
4266
|
commands[entry.name] = rebuilt;
|
|
@@ -3786,7 +4269,7 @@ function applicationOf2(settings) {
|
|
|
3786
4269
|
const boundOutputOf = new Map;
|
|
3787
4270
|
for (const entry of registry.outputs.values()) {
|
|
3788
4271
|
const declared = entry.value;
|
|
3789
|
-
const rebuilt =
|
|
4272
|
+
const rebuilt = !rebinds ? declared : outputOf2({
|
|
3790
4273
|
name: declared.outputName,
|
|
3791
4274
|
commands: declared.commands.map((command) => boundCommandOf.get(command)),
|
|
3792
4275
|
statuses: declared.statuses,
|
|
@@ -3797,6 +4280,19 @@ function applicationOf2(settings) {
|
|
|
3797
4280
|
}
|
|
3798
4281
|
const environmentEntries = [...registry.environments.values()];
|
|
3799
4282
|
const registeredEnvironments = new Set(environmentEntries.map((entry) => entry.value));
|
|
4283
|
+
const context = Object.freeze({
|
|
4284
|
+
name,
|
|
4285
|
+
env(environment) {
|
|
4286
|
+
if (!registeredEnvironments.has(environment)) {
|
|
4287
|
+
throw new UnregisteredApplicationReference2({
|
|
4288
|
+
source: name,
|
|
4289
|
+
details: { holder: "the context", reference: "an environment" }
|
|
4290
|
+
});
|
|
4291
|
+
}
|
|
4292
|
+
return environment.load();
|
|
4293
|
+
},
|
|
4294
|
+
logger: logger ?? silentLogger
|
|
4295
|
+
});
|
|
3800
4296
|
let starting;
|
|
3801
4297
|
let started = false;
|
|
3802
4298
|
const start = async () => {
|
|
@@ -3822,9 +4318,14 @@ function applicationOf2(settings) {
|
|
|
3822
4318
|
cause
|
|
3823
4319
|
});
|
|
3824
4320
|
}
|
|
3825
|
-
if (
|
|
3826
|
-
|
|
3827
|
-
|
|
4321
|
+
if (isLogFactory2(declaredLog)) {
|
|
4322
|
+
log?.set(checkLogSettings(await declaredLog.create(context)));
|
|
4323
|
+
}
|
|
4324
|
+
for (const instance of allProviders) {
|
|
4325
|
+
if (!isDeferredProvider(instance))
|
|
4326
|
+
continue;
|
|
4327
|
+
const made = await startDeferred(instance, context);
|
|
4328
|
+
checkTransactions(name, made, Object.entries(commands).filter(([, command]) => command.transaction && commandTransactionProvider(command) === instance).map(([key]) => key));
|
|
3828
4329
|
}
|
|
3829
4330
|
started = true;
|
|
3830
4331
|
};
|
|
@@ -3833,6 +4334,9 @@ function applicationOf2(settings) {
|
|
|
3833
4334
|
name,
|
|
3834
4335
|
extends: Object.freeze([...extended]),
|
|
3835
4336
|
provider,
|
|
4337
|
+
logger: logger ?? silentLogger,
|
|
4338
|
+
context,
|
|
4339
|
+
...logger ? { [ApplicationLoggerKey]: logger } : {},
|
|
3836
4340
|
properties: collection("properties"),
|
|
3837
4341
|
blueprints: collection("blueprints"),
|
|
3838
4342
|
records: collection("records"),
|
|
@@ -3845,25 +4349,25 @@ function applicationOf2(settings) {
|
|
|
3845
4349
|
exceptions: collection("exceptions"),
|
|
3846
4350
|
useCase(useCase) {
|
|
3847
4351
|
if (!boundUseCaseOf.has(useCase)) {
|
|
3848
|
-
|
|
4352
|
+
invalid7(name, "Expected a use case registered in the application.");
|
|
3849
4353
|
}
|
|
3850
4354
|
return boundUseCaseOf.get(useCase);
|
|
3851
4355
|
},
|
|
3852
4356
|
command(command) {
|
|
3853
4357
|
if (!boundCommandOf.has(command)) {
|
|
3854
|
-
|
|
4358
|
+
invalid7(name, "Expected a command registered in the application.");
|
|
3855
4359
|
}
|
|
3856
4360
|
return boundCommandOf.get(command);
|
|
3857
4361
|
},
|
|
3858
4362
|
output(output) {
|
|
3859
4363
|
if (!boundOutputOf.has(output)) {
|
|
3860
|
-
|
|
4364
|
+
invalid7(name, "Expected an output registered in the application.");
|
|
3861
4365
|
}
|
|
3862
4366
|
return boundOutputOf.get(output);
|
|
3863
4367
|
},
|
|
3864
4368
|
repository(repository) {
|
|
3865
4369
|
if (!bound.has(repository)) {
|
|
3866
|
-
|
|
4370
|
+
invalid7(name, "Expected a repository registered in the application.");
|
|
3867
4371
|
}
|
|
3868
4372
|
return bound.get(repository);
|
|
3869
4373
|
},
|
|
@@ -3871,10 +4375,11 @@ function applicationOf2(settings) {
|
|
|
3871
4375
|
return applicationOf2({
|
|
3872
4376
|
name,
|
|
3873
4377
|
extends: [application, ...others],
|
|
3874
|
-
...provider === undefined ? {} : { provider }
|
|
4378
|
+
...provider === undefined ? {} : { provider: defaultSlot ?? provider },
|
|
4379
|
+
...declaredLog === undefined ? {} : { log: declaredLog }
|
|
3875
4380
|
});
|
|
3876
4381
|
},
|
|
3877
|
-
describe: () => describeRegistry(name, extended, registry, provider),
|
|
4382
|
+
describe: () => describeRegistry(name, extended, registry, defaultSlot !== undefined ? referenceOf(defaultSlot) : provider === undefined ? undefined : providerDescriptionOf2(provider), named, isLogFactory2(declaredLog) ? "opaque" : log?.settings),
|
|
3878
4383
|
get started() {
|
|
3879
4384
|
return started;
|
|
3880
4385
|
},
|
|
@@ -3898,9 +4403,12 @@ function applicationOf2(settings) {
|
|
|
3898
4403
|
setStartedApplication(application);
|
|
3899
4404
|
})().then(() => application, async (error) => {
|
|
3900
4405
|
starting = undefined;
|
|
3901
|
-
|
|
3902
|
-
|
|
4406
|
+
for (const instance of allProviders) {
|
|
4407
|
+
if (isDeferredProvider(instance))
|
|
4408
|
+
await stopProvider(instance);
|
|
3903
4409
|
}
|
|
4410
|
+
if (isLogFactory2(declaredLog))
|
|
4411
|
+
log?.set(undefined);
|
|
3904
4412
|
throw error;
|
|
3905
4413
|
});
|
|
3906
4414
|
return starting;
|
|
@@ -3915,13 +4423,16 @@ function applicationOf2(settings) {
|
|
|
3915
4423
|
});
|
|
3916
4424
|
if (startedApplication() === application)
|
|
3917
4425
|
setStartedApplication(undefined);
|
|
3918
|
-
|
|
3919
|
-
await stopProvider(
|
|
4426
|
+
for (const instance of allProviders)
|
|
4427
|
+
await stopProvider(instance);
|
|
4428
|
+
await log?.flush();
|
|
4429
|
+
if (isLogFactory2(declaredLog))
|
|
4430
|
+
log?.set(undefined);
|
|
3920
4431
|
},
|
|
3921
4432
|
get(declaration) {
|
|
3922
4433
|
if (isEnvironment2(declaration)) {
|
|
3923
4434
|
if (!registeredEnvironments.has(declaration)) {
|
|
3924
|
-
|
|
4435
|
+
invalid7(name, "Expected an environment registered in the application.");
|
|
3925
4436
|
}
|
|
3926
4437
|
return declaration.load();
|
|
3927
4438
|
}
|
|
@@ -3934,10 +4445,22 @@ function applicationOf2(settings) {
|
|
|
3934
4445
|
if (isRepository2(declaration)) {
|
|
3935
4446
|
return application.repository(declaration);
|
|
3936
4447
|
}
|
|
3937
|
-
|
|
4448
|
+
if (isProviderSlot2(declaration)) {
|
|
4449
|
+
const instance = instances.get(declaration);
|
|
4450
|
+
if (instance === undefined) {
|
|
4451
|
+
invalid7(name, "Expected a provider of a storage registered in the application.");
|
|
4452
|
+
}
|
|
4453
|
+
return instance;
|
|
4454
|
+
}
|
|
4455
|
+
return invalid7(name, "Expected a repository, use case, command, output, environment or provider registered in the application.");
|
|
3938
4456
|
}
|
|
3939
4457
|
});
|
|
3940
4458
|
internals.set(application, registry);
|
|
4459
|
+
namedProviders.set(application, named);
|
|
4460
|
+
if (defaultSlot !== undefined)
|
|
4461
|
+
defaultSlots.set(application, defaultSlot);
|
|
4462
|
+
if (declaredLog !== undefined)
|
|
4463
|
+
logSettings.set(application, declaredLog);
|
|
3941
4464
|
return application;
|
|
3942
4465
|
}
|
|
3943
4466
|
// src/core/blueprint/blueprint-plugin.ts
|
|
@@ -4021,7 +4544,7 @@ function outputValueOf2(value) {
|
|
|
4021
4544
|
}
|
|
4022
4545
|
|
|
4023
4546
|
// src/core/output/openapi-sink.ts
|
|
4024
|
-
var
|
|
4547
|
+
var METHODS3 = ["get", "post", "put", "patch", "delete"];
|
|
4025
4548
|
function isObject(value) {
|
|
4026
4549
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4027
4550
|
}
|
|
@@ -4047,8 +4570,8 @@ function routeOptionsIssue2(options, where) {
|
|
|
4047
4570
|
if (!isObject(entry) || onlyKeys(entry, ["method", "path"], "route")) {
|
|
4048
4571
|
return `Expected ${where}.route["${id}"] to be { method?, path? }.`;
|
|
4049
4572
|
}
|
|
4050
|
-
if (entry.method !== undefined && !
|
|
4051
|
-
return `Expected ${where}.route["${id}"].method to be one of ${
|
|
4573
|
+
if (entry.method !== undefined && !METHODS3.includes(entry.method)) {
|
|
4574
|
+
return `Expected ${where}.route["${id}"].method to be one of ${METHODS3.join(", ")}.`;
|
|
4052
4575
|
}
|
|
4053
4576
|
if (entry.path !== undefined && !isPath(entry.path)) {
|
|
4054
4577
|
return `Expected ${where}.route["${id}"].path to start with "/" and have no parameters or query.`;
|
|
@@ -4086,7 +4609,7 @@ function validate2(options) {
|
|
|
4086
4609
|
}
|
|
4087
4610
|
return routeOptionsIssue2({ basePath, route }, "openapi");
|
|
4088
4611
|
}
|
|
4089
|
-
function
|
|
4612
|
+
function invalid8(reason, source = "openapi") {
|
|
4090
4613
|
throw new InvalidOutputStage2({ source, details: { reason } });
|
|
4091
4614
|
}
|
|
4092
4615
|
function kebab(text) {
|
|
@@ -4098,7 +4621,7 @@ function operationRoutes2(operations, options, source = "openapi") {
|
|
|
4098
4621
|
const ids = new Set(operations.map(({ id }) => id));
|
|
4099
4622
|
for (const id of Object.keys(route)) {
|
|
4100
4623
|
if (!ids.has(id)) {
|
|
4101
|
-
|
|
4624
|
+
invalid8(`${source}.route names the unknown operation "${id}".`, source);
|
|
4102
4625
|
}
|
|
4103
4626
|
}
|
|
4104
4627
|
const routes = new Map;
|
|
@@ -4109,7 +4632,7 @@ function operationRoutes2(operations, options, source = "openapi") {
|
|
|
4109
4632
|
const path = base + (chosen.path ?? `/${kebab(operation.command)}/${kebab(operation.name)}`);
|
|
4110
4633
|
const key = `${method} ${path}`;
|
|
4111
4634
|
if (taken.has(key)) {
|
|
4112
|
-
|
|
4635
|
+
invalid8(`Two operations are routed to ${method.toUpperCase()} ${path}.`, source);
|
|
4113
4636
|
}
|
|
4114
4637
|
taken.add(key);
|
|
4115
4638
|
routes.set(operation.id, { method, path });
|
|
@@ -4215,7 +4738,7 @@ function parametersOf(operation, schema) {
|
|
|
4215
4738
|
const field = operation.input.properties[name];
|
|
4216
4739
|
const type = property.type;
|
|
4217
4740
|
if (!isProperty2(field) || type === "object" || type === "array" || Array.isArray(type) && type.some((t) => t === "object" || t === "array")) {
|
|
4218
|
-
|
|
4741
|
+
invalid8(`${operation.id} uses a ${"get/delete"} route, whose input becomes query parameters, but "${name}" is not a scalar; route it with method "post".`);
|
|
4219
4742
|
}
|
|
4220
4743
|
const { description, ...rest } = property;
|
|
4221
4744
|
return {
|
|
@@ -4242,10 +4765,10 @@ var openapi2 = sinkOf2({
|
|
|
4242
4765
|
for (const record of records) {
|
|
4243
4766
|
const name = record.name;
|
|
4244
4767
|
if (!/^[A-Za-z0-9._-]+$/.test(name) || name === "Problem") {
|
|
4245
|
-
|
|
4768
|
+
invalid8(`The record class "${name}" cannot be a component name; give the class a name that is not "Problem".`);
|
|
4246
4769
|
}
|
|
4247
4770
|
if (classes.has(name)) {
|
|
4248
|
-
|
|
4771
|
+
invalid8(`Two record classes are named "${name}"; rename one.`);
|
|
4249
4772
|
}
|
|
4250
4773
|
classes.set(name, record);
|
|
4251
4774
|
models[name] = record;
|
|
@@ -4265,7 +4788,7 @@ var openapi2 = sinkOf2({
|
|
|
4265
4788
|
const { method, path } = routes.get(operation.id);
|
|
4266
4789
|
const operationId = operation.id.replaceAll(".", "_");
|
|
4267
4790
|
if (operationIds.has(operationId)) {
|
|
4268
|
-
|
|
4791
|
+
invalid8(`The operationId "${operationId}" is produced twice.`);
|
|
4269
4792
|
}
|
|
4270
4793
|
operationIds.add(operationId);
|
|
4271
4794
|
const slot = paths[path] ?? {};
|
|
@@ -5016,4 +5539,4 @@ var entityOf2 = entityBuilderOf2({
|
|
|
5016
5539
|
var recordOf2 = recordBuilderOf2(StdRecordPlugins2);
|
|
5017
5540
|
// src/std/stages.ts
|
|
5018
5541
|
var StdStages2 = stageCatalogOf2(select2, openapi2);
|
|
5019
|
-
export { InvalidEnvironment2, environmentOf2, isEnvironment2, guard2, ReservedEntityKey2, ImmutableEntityKey2, DeletedEntity2, entityBuilderOf2, isEntityClass2, isEntity2, eventOf2, ENTITY_IDENTITY_KEYS2, RESERVED_ENTITY_KEYS2, EntityUniqueKeys2, AbstractEntity2, InvalidRepositoryQuery2, InvalidRepositoryDeclaration2, InvalidRepositoryEntity2, InvalidRepositoryData2, RepositoryUniqueViolation2, RepositoryEntityNotFound2, providerOf2, providerDescriptionOf2, inMemoryProvider2, AbstractRepository2, repositoryOf2, RepositoryOf2, isRepository2, InvalidUseCaseStep2, InvalidUseCaseDeclaration2, UseCaseAlreadyExecuted2, InvalidUseCaseDependencies2, AbstractUseCase2, useCaseOf2, isUseCaseClass2, isUseCase2, InvalidCommandDeclaration2, UnknownCommandOperation2, InvalidCommandContext2, InvalidCommandEnvironment2, CommandEventFailed2, commandOf2, isCommand2,
|
|
5542
|
+
export { InvalidEnvironment2, environmentOf2, isEnvironment2, guard2, InvalidApplicationDeclaration2, DuplicateApplicationDeclaration2, ApplicationConflict2, UnregisteredApplicationReference2, UnregisteredRepositoryDependency2, UnregisteredUseCaseDependency2, ApplicationNotStarted2, ProviderNotBound2, ApplicationAlreadyStarted2, InvalidApplicationEnvironment2, useApplication2, resetApplication2, InvalidLogDeclaration2, LogLevels2, logProviderOf2, consoleLogProvider2, jsonLogProvider2, memoryLogProvider2, Logger2, ReservedEntityKey2, ImmutableEntityKey2, DeletedEntity2, entityBuilderOf2, isEntityClass2, isEntity2, eventOf2, ENTITY_IDENTITY_KEYS2, RESERVED_ENTITY_KEYS2, EntityUniqueKeys2, AbstractEntity2, InvalidRepositoryQuery2, InvalidRepositoryDeclaration2, InvalidRepositoryEntity2, InvalidRepositoryData2, RepositoryUniqueViolation2, RepositoryEntityNotFound2, providerOf2, providerDescriptionOf2, inMemoryProvider2, AbstractRepository2, repositoryOf2, RepositoryOf2, isRepository2, InvalidUseCaseStep2, InvalidUseCaseDeclaration2, UseCaseAlreadyExecuted2, InvalidUseCaseDependencies2, AbstractUseCase2, useCaseOf2, isUseCaseClass2, isUseCase2, InvalidCommandDeclaration2, UnknownCommandOperation2, InvalidCommandContext2, InvalidCommandEnvironment2, CommandEventFailed2, commandOf2, isCommand2, InvalidOpenAPIModel2, InvalidOutputStage2, DuplicateOperation2, toOpenAPI2, transformOf2, sinkOf2, stageDescriptionOf2, stageKindOf2, stageCatalogOf2, operationOf2, outputOf2, isOutput2, providerFrom2, logFrom2, isLogFactory2, isProviderFactory2, providersOf2, isProviderSlot2, isProviderStorage2, isApplication2, applicationOf2, blueprintPluginOf2, statusOf2, PROBLEM_MEDIA_TYPE2, problemOf2, outputValueOf2, routeOptionsIssue2, operationRoutes2, openapi2, select2, recordPluginCatalogOf2, Email2, Phone2, Url2, Ip2, enumOf2, SchemaProperty2, PasswordHasherRequired2, SyncVerifyUnsupported2, configure2, resetRuntime2, Id2, Slug2, PASSWORD_MIN_LENGTH2, PASSWORD_MAX_LENGTH2, PASSWORD_SPECIAL_CHARACTERS2, isPasswordHash2, passwordIssues2, Password2, StringProperty2, Text2, NumberProperty2, Integer2, BooleanProperty2, DateTime2, DateProperty2, CreatedAt2, UpdatedAt2, DeletedAt2, Std2, blueprintOf2, Publishable2, Archivable2, Taggable2, Ownable2, Authenticatable2, StdRecordPlugins2, entityOf2, recordOf2, StdStages2 };
|