@afora/core 0.0.3 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/application/start.d.ts +25 -1
- package/dist/core/application/types/application.interface.d.ts +45 -2
- 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/use-case/scope.d.ts +3 -0
- package/dist/core/use-case/use-case.d.ts +5 -4
- package/dist/{index-sw2b9ehx.js → index-ewm6r4nw.js} +533 -217
- package/dist/index.d.ts +6 -3
- package/dist/index.js +30 -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,37 @@ __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
|
+
UnregisteredApplicationReference: () => UnregisteredApplicationReference2,
|
|
64
|
+
UnregisteredRepositoryDependency: () => UnregisteredRepositoryDependency2,
|
|
65
|
+
UnregisteredUseCaseDependency: () => UnregisteredUseCaseDependency2
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
// src/core/logger/exceptions.ts
|
|
69
|
+
var exports_exceptions5 = {};
|
|
70
|
+
__export(exports_exceptions5, {
|
|
71
|
+
InvalidLogDeclaration: () => InvalidLogDeclaration2
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
// src/core/entity/exceptions.ts
|
|
75
|
+
var exports_exceptions6 = {};
|
|
76
|
+
__export(exports_exceptions6, {
|
|
56
77
|
DeletedEntity: () => DeletedEntity2,
|
|
57
78
|
ImmutableEntityKey: () => ImmutableEntityKey2,
|
|
58
79
|
ReservedEntityKey: () => ReservedEntityKey2
|
|
59
80
|
});
|
|
60
81
|
|
|
61
82
|
// src/core/repository/exceptions.ts
|
|
62
|
-
var
|
|
63
|
-
__export(
|
|
83
|
+
var exports_exceptions7 = {};
|
|
84
|
+
__export(exports_exceptions7, {
|
|
64
85
|
InvalidRepositoryData: () => InvalidRepositoryData2,
|
|
65
86
|
InvalidRepositoryDeclaration: () => InvalidRepositoryDeclaration2,
|
|
66
87
|
InvalidRepositoryEntity: () => InvalidRepositoryEntity2,
|
|
@@ -82,14 +103,14 @@ __export(exports_use_case, {
|
|
|
82
103
|
});
|
|
83
104
|
|
|
84
105
|
// src/core/use-case/exceptions.ts
|
|
85
|
-
var
|
|
86
|
-
__export(
|
|
106
|
+
var exports_exceptions8 = {};
|
|
107
|
+
__export(exports_exceptions8, {
|
|
87
108
|
InvalidUseCaseStep: () => InvalidUseCaseStep2
|
|
88
109
|
});
|
|
89
110
|
|
|
90
111
|
// src/core/command/exceptions.ts
|
|
91
|
-
var
|
|
92
|
-
__export(
|
|
112
|
+
var exports_exceptions9 = {};
|
|
113
|
+
__export(exports_exceptions9, {
|
|
93
114
|
CommandEventFailed: () => CommandEventFailed2,
|
|
94
115
|
InvalidCommandContext: () => InvalidCommandContext2,
|
|
95
116
|
InvalidCommandDeclaration: () => InvalidCommandDeclaration2,
|
|
@@ -97,29 +118,15 @@ __export(exports_exceptions7, {
|
|
|
97
118
|
UnknownCommandOperation: () => UnknownCommandOperation2
|
|
98
119
|
});
|
|
99
120
|
|
|
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
121
|
// src/core/openapi/exceptions.ts
|
|
115
|
-
var
|
|
116
|
-
__export(
|
|
122
|
+
var exports_exceptions10 = {};
|
|
123
|
+
__export(exports_exceptions10, {
|
|
117
124
|
InvalidOpenAPIModel: () => InvalidOpenAPIModel2
|
|
118
125
|
});
|
|
119
126
|
|
|
120
127
|
// src/core/output/exceptions.ts
|
|
121
|
-
var
|
|
122
|
-
__export(
|
|
128
|
+
var exports_exceptions11 = {};
|
|
129
|
+
__export(exports_exceptions11, {
|
|
123
130
|
DuplicateOperation: () => DuplicateOperation2,
|
|
124
131
|
InvalidOutputStage: () => InvalidOutputStage2
|
|
125
132
|
});
|
|
@@ -209,6 +216,281 @@ function guard2(scope, run, resolve) {
|
|
|
209
216
|
}
|
|
210
217
|
}
|
|
211
218
|
|
|
219
|
+
// src/core/application/exceptions.ts
|
|
220
|
+
var InvalidApplicationDeclaration2 = exceptionOf2({
|
|
221
|
+
layer: "application" /* Application */,
|
|
222
|
+
name: "InvalidApplicationDeclaration",
|
|
223
|
+
message: ({ reason }) => reason
|
|
224
|
+
});
|
|
225
|
+
var DuplicateApplicationDeclaration2 = exceptionOf2({
|
|
226
|
+
layer: "application" /* Application */,
|
|
227
|
+
name: "DuplicateApplicationDeclaration",
|
|
228
|
+
message: ({
|
|
229
|
+
first,
|
|
230
|
+
second
|
|
231
|
+
}) => `The same object is registered as ${first} and as ${second}.`
|
|
232
|
+
});
|
|
233
|
+
var ApplicationConflict2 = exceptionOf2({
|
|
234
|
+
layer: "application" /* Application */,
|
|
235
|
+
name: "ApplicationConflict",
|
|
236
|
+
message: ({
|
|
237
|
+
reason
|
|
238
|
+
}) => reason
|
|
239
|
+
});
|
|
240
|
+
var UnregisteredApplicationReference2 = exceptionOf2({
|
|
241
|
+
layer: "application" /* Application */,
|
|
242
|
+
name: "UnregisteredApplicationReference",
|
|
243
|
+
message: ({
|
|
244
|
+
holder,
|
|
245
|
+
reference
|
|
246
|
+
}) => `${holder} holds ${reference}, which is not registered in the application.`
|
|
247
|
+
});
|
|
248
|
+
var UnregisteredRepositoryDependency2 = exceptionOf2({
|
|
249
|
+
layer: "application" /* Application */,
|
|
250
|
+
name: "UnregisteredRepositoryDependency",
|
|
251
|
+
message: ({
|
|
252
|
+
repository,
|
|
253
|
+
dependency
|
|
254
|
+
}) => `Repository ${repository} depends on ${dependency}, which is not registered in the application.`
|
|
255
|
+
});
|
|
256
|
+
var UnregisteredUseCaseDependency2 = exceptionOf2({
|
|
257
|
+
layer: "application" /* Application */,
|
|
258
|
+
name: "UnregisteredUseCaseDependency",
|
|
259
|
+
message: ({
|
|
260
|
+
useCase,
|
|
261
|
+
dependency
|
|
262
|
+
}) => `Use case ${useCase} depends on ${dependency}, which is not registered in the application.`
|
|
263
|
+
});
|
|
264
|
+
var ApplicationNotStarted2 = exceptionOf2({
|
|
265
|
+
layer: "application" /* Application */,
|
|
266
|
+
name: "ApplicationNotStarted",
|
|
267
|
+
message: ({
|
|
268
|
+
application
|
|
269
|
+
}) => application === undefined ? "No application is started: call await app.start() first." : `The application "${application}" is not started: call await app.start() first.`
|
|
270
|
+
});
|
|
271
|
+
var ApplicationAlreadyStarted2 = exceptionOf2({
|
|
272
|
+
layer: "application" /* Application */,
|
|
273
|
+
name: "ApplicationAlreadyStarted",
|
|
274
|
+
message: ({
|
|
275
|
+
current,
|
|
276
|
+
attempted
|
|
277
|
+
}) => `The application "${current}" is already started, so "${attempted}" cannot be: stop it, or call start({ replace: true }).`
|
|
278
|
+
});
|
|
279
|
+
var InvalidApplicationEnvironment2 = exceptionOf2({
|
|
280
|
+
layer: "environment" /* Environment */,
|
|
281
|
+
name: "InvalidApplicationEnvironment",
|
|
282
|
+
message: ({
|
|
283
|
+
environments
|
|
284
|
+
}) => `Invalid environment variables: ${Object.entries(environments).map(([name, keys]) => `${name} (${keys.join(", ")})`).join("; ")}.`
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
// src/core/application/registry.ts
|
|
288
|
+
var SLOT = Symbol.for("afora.application");
|
|
289
|
+
function slot() {
|
|
290
|
+
const global = globalThis;
|
|
291
|
+
global[SLOT] ??= { current: undefined };
|
|
292
|
+
return global[SLOT];
|
|
293
|
+
}
|
|
294
|
+
function useApplication2() {
|
|
295
|
+
const { current } = slot();
|
|
296
|
+
if (current === undefined) {
|
|
297
|
+
throw new ApplicationNotStarted2({ source: "useApplication", details: {} });
|
|
298
|
+
}
|
|
299
|
+
return current;
|
|
300
|
+
}
|
|
301
|
+
function resetApplication2() {
|
|
302
|
+
slot().current = undefined;
|
|
303
|
+
}
|
|
304
|
+
function startedApplication() {
|
|
305
|
+
return slot().current;
|
|
306
|
+
}
|
|
307
|
+
function setStartedApplication(application) {
|
|
308
|
+
slot().current = application;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// src/core/logger/exceptions.ts
|
|
312
|
+
var InvalidLogDeclaration2 = exceptionOf2({
|
|
313
|
+
layer: "application" /* Application */,
|
|
314
|
+
name: "InvalidLogDeclaration",
|
|
315
|
+
message: ({ reason }) => reason
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
// src/core/logger/logger.ts
|
|
319
|
+
var LogLevels2 = Object.freeze([
|
|
320
|
+
"debug",
|
|
321
|
+
"info",
|
|
322
|
+
"warn",
|
|
323
|
+
"error"
|
|
324
|
+
]);
|
|
325
|
+
var names = new WeakMap;
|
|
326
|
+
var invalid = (reason) => {
|
|
327
|
+
throw new InvalidLogDeclaration2({ source: "log", details: { reason } });
|
|
328
|
+
};
|
|
329
|
+
function logProviderOf2(settings) {
|
|
330
|
+
if (!settings || typeof settings.write !== "function") {
|
|
331
|
+
invalid("Expected a log provider with a write function.");
|
|
332
|
+
}
|
|
333
|
+
if (settings.flush !== undefined && typeof settings.flush !== "function") {
|
|
334
|
+
invalid("Expected flush to be a function.");
|
|
335
|
+
}
|
|
336
|
+
if (settings.name !== undefined && (typeof settings.name !== "string" || settings.name.trim() === "")) {
|
|
337
|
+
invalid("Expected the name of a log provider to be a non-empty string.");
|
|
338
|
+
}
|
|
339
|
+
const provider = Object.freeze({
|
|
340
|
+
write: settings.write,
|
|
341
|
+
...settings.flush ? { flush: settings.flush } : {}
|
|
342
|
+
});
|
|
343
|
+
if (settings.name)
|
|
344
|
+
names.set(provider, settings.name);
|
|
345
|
+
return provider;
|
|
346
|
+
}
|
|
347
|
+
function logProviderNameOf(provider) {
|
|
348
|
+
return names.get(provider);
|
|
349
|
+
}
|
|
350
|
+
var fieldsText = (fields) => Object.keys(fields).length > 0 ? ` ${JSON.stringify(fields)}` : "";
|
|
351
|
+
function consoleLogProvider2() {
|
|
352
|
+
return logProviderOf2({
|
|
353
|
+
name: "console",
|
|
354
|
+
write: ({ at, level, event, fields, application }) => {
|
|
355
|
+
const line = `${at} ${level.toUpperCase()} [${application}] ${event}${fieldsText(fields)}`;
|
|
356
|
+
(level === "debug" ? console.debug : level === "info" ? console.info : level === "warn" ? console.warn : console.error)(line);
|
|
357
|
+
}
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
function jsonLogProvider2() {
|
|
361
|
+
return logProviderOf2({
|
|
362
|
+
name: "json",
|
|
363
|
+
write: (entry) => {
|
|
364
|
+
console.log(JSON.stringify({
|
|
365
|
+
at: entry.at,
|
|
366
|
+
level: entry.level,
|
|
367
|
+
application: entry.application,
|
|
368
|
+
event: entry.event,
|
|
369
|
+
...entry.fields
|
|
370
|
+
}));
|
|
371
|
+
}
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
function memoryLogProvider2() {
|
|
375
|
+
const entries = [];
|
|
376
|
+
const provider = Object.freeze({
|
|
377
|
+
write: (entry) => {
|
|
378
|
+
entries.push(entry);
|
|
379
|
+
},
|
|
380
|
+
entries,
|
|
381
|
+
clear: () => {
|
|
382
|
+
entries.length = 0;
|
|
383
|
+
}
|
|
384
|
+
});
|
|
385
|
+
names.set(provider, "memory");
|
|
386
|
+
return provider;
|
|
387
|
+
}
|
|
388
|
+
function checkLogSettings(settings) {
|
|
389
|
+
if (typeof settings !== "object" || settings === null) {
|
|
390
|
+
return invalid("Expected `log` to be { level?, providers }.");
|
|
391
|
+
}
|
|
392
|
+
const { level = "info", providers } = settings;
|
|
393
|
+
if (!LogLevels2.includes(level)) {
|
|
394
|
+
invalid(`Expected the log level to be one of ${LogLevels2.join(", ")}.`);
|
|
395
|
+
}
|
|
396
|
+
if (!Array.isArray(providers) || providers.some((provider) => typeof provider !== "object" || provider === null || typeof provider.write !== "function")) {
|
|
397
|
+
invalid("Expected `log.providers` to be a list of log providers.");
|
|
398
|
+
}
|
|
399
|
+
return Object.freeze({ level, providers: Object.freeze([...providers]) });
|
|
400
|
+
}
|
|
401
|
+
var silentLogger = Object.freeze({
|
|
402
|
+
debug: () => {},
|
|
403
|
+
info: () => {},
|
|
404
|
+
warn: () => {},
|
|
405
|
+
error: () => {}
|
|
406
|
+
});
|
|
407
|
+
var rank = (level) => LogLevels2.indexOf(level);
|
|
408
|
+
function applicationLogger(application) {
|
|
409
|
+
let current;
|
|
410
|
+
const write = (level) => (event, fields = {}) => {
|
|
411
|
+
if (!current || rank(level) < rank(current.level))
|
|
412
|
+
return;
|
|
413
|
+
const entry = Object.freeze({
|
|
414
|
+
at: new Date().toISOString(),
|
|
415
|
+
level,
|
|
416
|
+
event,
|
|
417
|
+
fields,
|
|
418
|
+
application
|
|
419
|
+
});
|
|
420
|
+
for (const provider of current.providers) {
|
|
421
|
+
try {
|
|
422
|
+
const written = provider.write(entry);
|
|
423
|
+
if (written && typeof written.catch === "function") {
|
|
424
|
+
written.catch(() => {});
|
|
425
|
+
}
|
|
426
|
+
} catch {}
|
|
427
|
+
}
|
|
428
|
+
};
|
|
429
|
+
const logger = Object.freeze({
|
|
430
|
+
debug: write("debug"),
|
|
431
|
+
info: write("info"),
|
|
432
|
+
warn: write("warn"),
|
|
433
|
+
error: write("error")
|
|
434
|
+
});
|
|
435
|
+
return {
|
|
436
|
+
logger,
|
|
437
|
+
get settings() {
|
|
438
|
+
return current;
|
|
439
|
+
},
|
|
440
|
+
set(settings) {
|
|
441
|
+
current = settings;
|
|
442
|
+
},
|
|
443
|
+
async flush() {
|
|
444
|
+
await Promise.all((current?.providers ?? []).map((provider) => Promise.resolve().then(() => provider.flush?.()).catch(() => {})));
|
|
445
|
+
}
|
|
446
|
+
};
|
|
447
|
+
}
|
|
448
|
+
var Logger2 = Object.freeze({
|
|
449
|
+
[Kind2]: "logger"
|
|
450
|
+
});
|
|
451
|
+
function isLoggerDeclaration(value) {
|
|
452
|
+
return value === Logger2;
|
|
453
|
+
}
|
|
454
|
+
function isLogger(value) {
|
|
455
|
+
return typeof value === "object" && value !== null && ["debug", "info", "warn", "error"].every((level) => typeof value[level] === "function");
|
|
456
|
+
}
|
|
457
|
+
var ApplicationLoggerKey = Symbol("afora.application.logger");
|
|
458
|
+
function resolveLogger(scoped, owner) {
|
|
459
|
+
return scoped ?? owner?.[ApplicationLoggerKey] ?? startedApplication()?.[ApplicationLoggerKey];
|
|
460
|
+
}
|
|
461
|
+
function clock() {
|
|
462
|
+
return globalThis.performance?.now() ?? Date.now();
|
|
463
|
+
}
|
|
464
|
+
function elapsed(since) {
|
|
465
|
+
return Math.round(clock() - since);
|
|
466
|
+
}
|
|
467
|
+
var logged = new WeakSet;
|
|
468
|
+
function logFailure(logger, event, fields, error) {
|
|
469
|
+
if (!logger)
|
|
470
|
+
return;
|
|
471
|
+
const exception = error instanceof Exception2 ? error : undefined;
|
|
472
|
+
const key = exception?.origin ?? error;
|
|
473
|
+
if (typeof key === "object" && key !== null) {
|
|
474
|
+
if (logged.has(key))
|
|
475
|
+
return;
|
|
476
|
+
logged.add(key);
|
|
477
|
+
}
|
|
478
|
+
const unexpected = !exception || exception.origin.name === UNEXPECTED_ERROR2;
|
|
479
|
+
try {
|
|
480
|
+
logger[unexpected ? "error" : "warn"](event, {
|
|
481
|
+
...fields,
|
|
482
|
+
exception: exception ? exception.toJSON() : { message: error instanceof Error ? error.message : String(error) }
|
|
483
|
+
});
|
|
484
|
+
} catch {}
|
|
485
|
+
}
|
|
486
|
+
function writeLog(logger, level, event, fields) {
|
|
487
|
+
if (!logger)
|
|
488
|
+
return;
|
|
489
|
+
try {
|
|
490
|
+
logger[level](event, fields);
|
|
491
|
+
} catch {}
|
|
492
|
+
}
|
|
493
|
+
|
|
212
494
|
// src/core/entity/exceptions.ts
|
|
213
495
|
var ReservedEntityKey2 = exceptionOf2({
|
|
214
496
|
layer: "entity" /* Entity */,
|
|
@@ -291,8 +573,10 @@ function eventOf2(name, entityClass, handler) {
|
|
|
291
573
|
return Object.freeze({
|
|
292
574
|
name,
|
|
293
575
|
entity,
|
|
294
|
-
async handle() {
|
|
295
|
-
await handler(entity
|
|
576
|
+
async handle(context) {
|
|
577
|
+
await handler(entity, {
|
|
578
|
+
logger: context?.logger ?? resolveLogger(undefined, undefined) ?? silentLogger
|
|
579
|
+
});
|
|
296
580
|
}
|
|
297
581
|
});
|
|
298
582
|
});
|
|
@@ -473,7 +757,7 @@ function frozenJson(value, subject, fail, seen = new Set) {
|
|
|
473
757
|
// src/core/repository/provider.ts
|
|
474
758
|
var descriptions = new WeakMap;
|
|
475
759
|
var opaque = Object.freeze({ kind: "opaque" });
|
|
476
|
-
function
|
|
760
|
+
function invalid2(reason) {
|
|
477
761
|
throw new InvalidRepositoryDeclaration2({
|
|
478
762
|
source: "providerOf",
|
|
479
763
|
details: { reason }
|
|
@@ -481,13 +765,13 @@ function invalid(reason) {
|
|
|
481
765
|
}
|
|
482
766
|
function providerOf2(settings) {
|
|
483
767
|
if (!settings || typeof settings.name !== "string" || settings.name.trim().length === 0 || typeof settings.create !== "function")
|
|
484
|
-
|
|
485
|
-
const options = frozenJson(settings.options ?? {}, "Provider options",
|
|
768
|
+
invalid2("Expected a provider name and create function.");
|
|
769
|
+
const options = frozenJson(settings.options ?? {}, "Provider options", invalid2);
|
|
486
770
|
if (options === null || typeof options !== "object" || Array.isArray(options))
|
|
487
|
-
|
|
771
|
+
invalid2("Provider options must be an object.");
|
|
488
772
|
const provider = settings.create(options);
|
|
489
773
|
if (!provider || typeof provider !== "object" || ["findOne", "findMany", "insert", "update", "remove", "count"].some((key) => typeof provider[key] !== "function"))
|
|
490
|
-
|
|
774
|
+
invalid2("Expected a repository provider from create.");
|
|
491
775
|
descriptions.set(provider, Object.freeze({
|
|
492
776
|
kind: "provider",
|
|
493
777
|
name: settings.name,
|
|
@@ -576,11 +860,11 @@ function matchesQuery(data, query) {
|
|
|
576
860
|
function codePoints(text) {
|
|
577
861
|
return Array.from(text, (char) => char.codePointAt(0));
|
|
578
862
|
}
|
|
579
|
-
function
|
|
863
|
+
function rank2(value) {
|
|
580
864
|
return value instanceof Date ? 1 : { number: 0, bigint: 0, string: 2, boolean: 3 }[typeof value] ?? 4;
|
|
581
865
|
}
|
|
582
866
|
function compareScalars(a, b) {
|
|
583
|
-
const [left, right] = [
|
|
867
|
+
const [left, right] = [rank2(a), rank2(b)];
|
|
584
868
|
if (left !== right)
|
|
585
869
|
return left - right;
|
|
586
870
|
if (typeof a === "string" && typeof b === "string") {
|
|
@@ -1138,25 +1422,25 @@ function unknownAction(entity, action, methods) {
|
|
|
1138
1422
|
}
|
|
1139
1423
|
return `"${action}" is not an action of ${entity}.`;
|
|
1140
1424
|
}
|
|
1141
|
-
function
|
|
1425
|
+
function invalid3(source, reason) {
|
|
1142
1426
|
throw new InvalidRepositoryDeclaration2({ source, details: { reason } });
|
|
1143
1427
|
}
|
|
1144
1428
|
function repositoryOf2(settings) {
|
|
1145
1429
|
const { entity, actions, environmentDependencies } = settings ?? {};
|
|
1146
1430
|
if (!isEntityClass2(entity) || !(EntityUniqueKeys2 in entity)) {
|
|
1147
|
-
|
|
1431
|
+
invalid3("repositoryOf", "Expected an entity class made by entityOf.");
|
|
1148
1432
|
}
|
|
1149
1433
|
const name = `${entity.name}Repository`;
|
|
1150
1434
|
const deletion = settings.deletion ?? "hard";
|
|
1151
1435
|
if (deletion !== "hard" && deletion !== "soft") {
|
|
1152
|
-
|
|
1436
|
+
invalid3(name, 'Expected deletion to be "hard" or "soft".');
|
|
1153
1437
|
}
|
|
1154
1438
|
const provider = settings.provider ?? inMemoryProvider2();
|
|
1155
1439
|
if (!Array.isArray(actions) || actions.length === 0) {
|
|
1156
|
-
|
|
1440
|
+
invalid3(name, "Expected a list of actions.");
|
|
1157
1441
|
}
|
|
1158
1442
|
if (environmentDependencies !== undefined && !isEnvironment2(environmentDependencies) && !(Array.isArray(environmentDependencies) && environmentDependencies.every(isEnvironment2))) {
|
|
1159
|
-
|
|
1443
|
+
invalid3(name, "Expected environments made by environmentOf.");
|
|
1160
1444
|
}
|
|
1161
1445
|
const relations = relationsOf(name, entity, settings.relations);
|
|
1162
1446
|
const unique = entity[EntityUniqueKeys2];
|
|
@@ -1182,12 +1466,12 @@ function repositoryOf2(settings) {
|
|
|
1182
1466
|
for (const name_ of new Set(actions)) {
|
|
1183
1467
|
const method = typeof name_ === "string" ? methods.get(name_) : undefined;
|
|
1184
1468
|
if (!method)
|
|
1185
|
-
|
|
1469
|
+
invalid3(name, unknownAction(entity.name, String(name_), methods));
|
|
1186
1470
|
const [kind, implementation] = method;
|
|
1187
1471
|
const needs = deletion === "soft" && kind === "delete" ? ["findOne", "update"] : NEEDS[kind] ?? [];
|
|
1188
1472
|
for (const need of needs) {
|
|
1189
1473
|
if (typeof provider?.[need] !== "function") {
|
|
1190
|
-
|
|
1474
|
+
invalid3(name, `The provider has no "${need}" for "${name_}".`);
|
|
1191
1475
|
}
|
|
1192
1476
|
}
|
|
1193
1477
|
Object.defineProperty(DeclaredRepository.prototype, name_, {
|
|
@@ -1211,7 +1495,7 @@ function repositoryOf2(settings) {
|
|
|
1211
1495
|
}
|
|
1212
1496
|
function RepositoryOf2(repository) {
|
|
1213
1497
|
if (!isRepository2(repository)) {
|
|
1214
|
-
|
|
1498
|
+
invalid3("RepositoryOf", "Expected a repository made by repositoryOf.");
|
|
1215
1499
|
}
|
|
1216
1500
|
return repository.constructor;
|
|
1217
1501
|
}
|
|
@@ -1719,6 +2003,9 @@ var InvalidUseCaseDependencies2 = exceptionOf2({
|
|
|
1719
2003
|
name: "InvalidUseCaseDependencies",
|
|
1720
2004
|
message: "Dependency overrides must contain only declared names: functions for use cases, objects of methods for repositories, and valid variables for environments."
|
|
1721
2005
|
});
|
|
2006
|
+
function loggerOfCall(state) {
|
|
2007
|
+
return resolveLogger(state.scope?.logger, state.owner);
|
|
2008
|
+
}
|
|
1722
2009
|
var states2 = new WeakMap;
|
|
1723
2010
|
function invalidValue(issues, source, phase) {
|
|
1724
2011
|
throw new Exception2({
|
|
@@ -1773,6 +2060,7 @@ function methodNamesOf(repository) {
|
|
|
1773
2060
|
}
|
|
1774
2061
|
function bindRepository2(repository, overrides, state, source) {
|
|
1775
2062
|
const Entity = repository.entity;
|
|
2063
|
+
const repositoryName = Entity.name;
|
|
1776
2064
|
const bound = Object.create(null);
|
|
1777
2065
|
const view = new Proxy(Object.create(repository), {
|
|
1778
2066
|
get: (_target, key, receiver) => {
|
|
@@ -1793,7 +2081,14 @@ function bindRepository2(repository, overrides, state, source) {
|
|
|
1793
2081
|
bound[name] = async (...args) => {
|
|
1794
2082
|
if (!state.active)
|
|
1795
2083
|
throw new InvalidUseCaseDependencies2({ source });
|
|
2084
|
+
const started = clock();
|
|
1796
2085
|
const result = await method.apply(receiver, args);
|
|
2086
|
+
writeLog(loggerOfCall(state), "debug", "repository", {
|
|
2087
|
+
repository: repositoryName,
|
|
2088
|
+
method: name,
|
|
2089
|
+
useCase: source,
|
|
2090
|
+
ms: elapsed(started)
|
|
2091
|
+
});
|
|
1797
2092
|
for (const arg of args)
|
|
1798
2093
|
pullEntities(arg, Entity, state.events);
|
|
1799
2094
|
pullEntities(result, Entity, state.events);
|
|
@@ -1828,6 +2123,8 @@ function narrowedContext(Child, parent) {
|
|
|
1828
2123
|
return picked;
|
|
1829
2124
|
}
|
|
1830
2125
|
function isOverrideOf(dependency, value) {
|
|
2126
|
+
if (isLoggerDeclaration(dependency))
|
|
2127
|
+
return isLogger(value);
|
|
1831
2128
|
if (isRepository2(dependency) || isEnvironment2(dependency)) {
|
|
1832
2129
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1833
2130
|
}
|
|
@@ -1873,7 +2170,8 @@ class AbstractUseCase2 {
|
|
|
1873
2170
|
started: false,
|
|
1874
2171
|
active: false,
|
|
1875
2172
|
events: [],
|
|
1876
|
-
dependencies: Object.create(null)
|
|
2173
|
+
dependencies: Object.create(null),
|
|
2174
|
+
owner: this.constructor
|
|
1877
2175
|
};
|
|
1878
2176
|
states2.set(this, state);
|
|
1879
2177
|
for (const [key, dependency] of Object.entries(declaration.dependencies)) {
|
|
@@ -1881,6 +2179,13 @@ class AbstractUseCase2 {
|
|
|
1881
2179
|
state.dependencies[key] = bindRepository2(dependency, undefined, state, source);
|
|
1882
2180
|
continue;
|
|
1883
2181
|
}
|
|
2182
|
+
if (isLoggerDeclaration(dependency)) {
|
|
2183
|
+
Object.defineProperty(state.dependencies, key, {
|
|
2184
|
+
get: () => loggerOfCall(state) ?? silentLogger,
|
|
2185
|
+
enumerable: true
|
|
2186
|
+
});
|
|
2187
|
+
continue;
|
|
2188
|
+
}
|
|
1884
2189
|
if (isEnvironment2(dependency)) {
|
|
1885
2190
|
Object.defineProperty(state.dependencies, key, {
|
|
1886
2191
|
get: () => state.scope?.environments?.get(dependency) ?? dependency.load(),
|
|
@@ -1925,6 +2230,10 @@ class AbstractUseCase2 {
|
|
|
1925
2230
|
dependencies[key] = bindRepository2(dependency, substitute, state, source);
|
|
1926
2231
|
continue;
|
|
1927
2232
|
}
|
|
2233
|
+
if (isLoggerDeclaration(dependency)) {
|
|
2234
|
+
dependencies[key] = substitute;
|
|
2235
|
+
continue;
|
|
2236
|
+
}
|
|
1928
2237
|
if (isEnvironment2(dependency)) {
|
|
1929
2238
|
const parsed = dependency.blueprint.safeParse(substitute);
|
|
1930
2239
|
if (parsed.issues)
|
|
@@ -1949,13 +2258,22 @@ class AbstractUseCase2 {
|
|
|
1949
2258
|
}
|
|
1950
2259
|
state.resolved = Object.freeze(dependencies);
|
|
1951
2260
|
state.active = true;
|
|
2261
|
+
const started = clock();
|
|
1952
2262
|
try {
|
|
1953
2263
|
const result = await guard2({ layer: "use-case" /* UseCase */, source }, () => implementation.call(this, state.resolved));
|
|
1954
2264
|
const parsed = declaration.response.safeParse(result);
|
|
1955
2265
|
if (parsed.issues)
|
|
1956
2266
|
invalidValue(parsed.issues, source, "response");
|
|
1957
2267
|
collectEvents(declaration.response, parsed.value, state.events);
|
|
2268
|
+
writeLog(loggerOfCall(state), "debug", "use-case", {
|
|
2269
|
+
useCase: source,
|
|
2270
|
+
outcome: "ok",
|
|
2271
|
+
ms: elapsed(started)
|
|
2272
|
+
});
|
|
1958
2273
|
return parsed.value;
|
|
2274
|
+
} catch (error) {
|
|
2275
|
+
logFailure(loggerOfCall(state), "use-case-failed", { useCase: source, ms: elapsed(started) }, error);
|
|
2276
|
+
throw error;
|
|
1959
2277
|
} finally {
|
|
1960
2278
|
state.active = false;
|
|
1961
2279
|
state.resolved = undefined;
|
|
@@ -1981,7 +2299,7 @@ function useCaseOf2(settings) {
|
|
|
1981
2299
|
throw new InvalidUseCaseDeclaration2({
|
|
1982
2300
|
source: typeof name === "string" ? name : "useCaseOf",
|
|
1983
2301
|
details: {
|
|
1984
|
-
reason: "Expected a name, input and response blueprints, and UseCase classes, repositories or
|
|
2302
|
+
reason: "Expected a name, input and response blueprints, and UseCase classes, repositories, environments or Logger as dependencies."
|
|
1985
2303
|
}
|
|
1986
2304
|
});
|
|
1987
2305
|
}
|
|
@@ -2037,7 +2355,7 @@ function useCaseOf2(settings) {
|
|
|
2037
2355
|
return DeclaredUseCase;
|
|
2038
2356
|
}
|
|
2039
2357
|
function isDependency(value) {
|
|
2040
|
-
return isUseCaseClass2(value) || isRepository2(value) || isEnvironment2(value);
|
|
2358
|
+
return isUseCaseClass2(value) || isRepository2(value) || isEnvironment2(value) || isLoggerDeclaration(value);
|
|
2041
2359
|
}
|
|
2042
2360
|
function isUseCaseClass2(value) {
|
|
2043
2361
|
return typeof value === "function" && value.prototype instanceof AbstractUseCase2 && value[Kind2] === "use-case" && typeof value.prototype.execute === "function";
|
|
@@ -2283,9 +2601,16 @@ function commandOf2(settings) {
|
|
|
2283
2601
|
given = narrowed(UseCase, callContext);
|
|
2284
2602
|
}
|
|
2285
2603
|
const overrides = options?.env === undefined ? undefined : callEnvironment(where, environments, options.env);
|
|
2286
|
-
const
|
|
2287
|
-
|
|
2288
|
-
environments: overrides.byEnvironment
|
|
2604
|
+
const logger = resolveLogger(undefined, UseCase);
|
|
2605
|
+
const withEnvironments = (scope) => {
|
|
2606
|
+
const environmentsOfCall = overrides === undefined || overrides.byEnvironment.size === 0 ? scope?.environments : overrides.byEnvironment;
|
|
2607
|
+
if (!environmentsOfCall && !logger)
|
|
2608
|
+
return scope;
|
|
2609
|
+
return {
|
|
2610
|
+
providers: scope?.providers ?? new Map,
|
|
2611
|
+
...environmentsOfCall ? { environments: environmentsOfCall } : {},
|
|
2612
|
+
...logger ? { logger } : {}
|
|
2613
|
+
};
|
|
2289
2614
|
};
|
|
2290
2615
|
const run = async (declared) => {
|
|
2291
2616
|
const scope = withEnvironments(declared);
|
|
@@ -2294,11 +2619,20 @@ function commandOf2(settings) {
|
|
|
2294
2619
|
return { value, events: useCase.pullEvents() };
|
|
2295
2620
|
};
|
|
2296
2621
|
const provider = providerOfCall();
|
|
2297
|
-
const
|
|
2622
|
+
const started = clock();
|
|
2623
|
+
const outcome = await guard2({ layer: "command" /* Command */, source: where }, () => provider?.transaction ? provider.transaction((scoped) => run({ providers: new Map([[provider, scoped]]) })) : run(undefined)).catch((error) => {
|
|
2624
|
+
logFailure(logger, "command-failed", { command: where, ms: elapsed(started) }, error);
|
|
2625
|
+
throw error;
|
|
2626
|
+
});
|
|
2627
|
+
writeLog(logger, "debug", "command", {
|
|
2628
|
+
command: where,
|
|
2629
|
+
ms: elapsed(started)
|
|
2630
|
+
});
|
|
2298
2631
|
return {
|
|
2299
2632
|
...outcome,
|
|
2300
2633
|
context: callContext,
|
|
2301
|
-
env: () => overrides?.merged ?? loadEnvironments(environments)
|
|
2634
|
+
env: () => overrides?.merged ?? loadEnvironments(environments),
|
|
2635
|
+
logger: logger ?? silentLogger
|
|
2302
2636
|
};
|
|
2303
2637
|
};
|
|
2304
2638
|
const command = {
|
|
@@ -2325,13 +2659,15 @@ function commandOf2(settings) {
|
|
|
2325
2659
|
value,
|
|
2326
2660
|
events: raised,
|
|
2327
2661
|
context: callContext,
|
|
2328
|
-
env
|
|
2662
|
+
env,
|
|
2663
|
+
logger
|
|
2329
2664
|
} = await perform(op, input, options);
|
|
2330
2665
|
await applyPolicy(command, events, onEventError, {
|
|
2331
2666
|
operation: op,
|
|
2332
2667
|
raised,
|
|
2333
2668
|
context: callContext,
|
|
2334
|
-
env
|
|
2669
|
+
env,
|
|
2670
|
+
logger
|
|
2335
2671
|
});
|
|
2336
2672
|
return value;
|
|
2337
2673
|
}
|
|
@@ -2351,7 +2687,8 @@ async function applyPolicy(command, policy, onEventError, call) {
|
|
|
2351
2687
|
context: call.context,
|
|
2352
2688
|
get env() {
|
|
2353
2689
|
return call.env();
|
|
2354
|
-
}
|
|
2690
|
+
},
|
|
2691
|
+
logger: call.logger
|
|
2355
2692
|
};
|
|
2356
2693
|
if (typeof policy === "function") {
|
|
2357
2694
|
try {
|
|
@@ -2367,7 +2704,7 @@ async function applyPolicy(command, policy, onEventError, call) {
|
|
|
2367
2704
|
}
|
|
2368
2705
|
for (const [index, event] of raised.entries()) {
|
|
2369
2706
|
try {
|
|
2370
|
-
await event.handle();
|
|
2707
|
+
await event.handle({ logger: call.logger });
|
|
2371
2708
|
} catch (cause) {
|
|
2372
2709
|
if (!onEventError) {
|
|
2373
2710
|
throw new CommandEventFailed2({
|
|
@@ -2402,74 +2739,6 @@ function isCommand2(value) {
|
|
|
2402
2739
|
return typeof value === "object" && value !== null && value[Kind2] === "command";
|
|
2403
2740
|
}
|
|
2404
2741
|
|
|
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
2742
|
// src/core/openapi/exceptions.ts
|
|
2474
2743
|
var InvalidOpenAPIModel2 = exceptionOf2({
|
|
2475
2744
|
layer: "output" /* Output */,
|
|
@@ -2502,18 +2771,19 @@ function isExportedException(Declared) {
|
|
|
2502
2771
|
if (!collected) {
|
|
2503
2772
|
collected = true;
|
|
2504
2773
|
for (const module of [
|
|
2505
|
-
exports_exceptions8,
|
|
2506
|
-
exports_exceptions2,
|
|
2507
|
-
exports_exceptions7,
|
|
2508
2774
|
exports_exceptions4,
|
|
2509
|
-
|
|
2775
|
+
exports_exceptions2,
|
|
2510
2776
|
exports_exceptions9,
|
|
2777
|
+
exports_exceptions6,
|
|
2778
|
+
exports_environment,
|
|
2779
|
+
exports_exceptions5,
|
|
2511
2780
|
exports_exceptions10,
|
|
2781
|
+
exports_exceptions11,
|
|
2512
2782
|
exports_exceptions3,
|
|
2513
2783
|
exports_exceptions,
|
|
2514
|
-
|
|
2784
|
+
exports_exceptions7,
|
|
2515
2785
|
exports_use_case,
|
|
2516
|
-
|
|
2786
|
+
exports_exceptions8
|
|
2517
2787
|
]) {
|
|
2518
2788
|
markExported(...Object.values(module));
|
|
2519
2789
|
}
|
|
@@ -2635,28 +2905,28 @@ function toOpenAPI2(modelOrModels, { refPrefix = "#/components/schemas/" } = {})
|
|
|
2635
2905
|
var descriptions2 = new WeakMap;
|
|
2636
2906
|
var factories = new WeakMap;
|
|
2637
2907
|
var opaque2 = Object.freeze({ kind: "opaque" });
|
|
2638
|
-
function
|
|
2908
|
+
function invalid4(source, reason) {
|
|
2639
2909
|
throw new InvalidOutputStage2({ source, details: { reason } });
|
|
2640
2910
|
}
|
|
2641
2911
|
function optionsOf(name, given, validate) {
|
|
2642
|
-
const options = frozenJson(given ?? {}, "Stage options", (reason) =>
|
|
2912
|
+
const options = frozenJson(given ?? {}, "Stage options", (reason) => invalid4(name, reason));
|
|
2643
2913
|
if (options === null || typeof options !== "object" || Array.isArray(options)) {
|
|
2644
|
-
|
|
2914
|
+
invalid4(name, "Stage options must be an object.");
|
|
2645
2915
|
}
|
|
2646
2916
|
const reason = validate?.(options);
|
|
2647
2917
|
if (reason !== undefined)
|
|
2648
|
-
|
|
2918
|
+
invalid4(name, reason);
|
|
2649
2919
|
return options;
|
|
2650
2920
|
}
|
|
2651
2921
|
function checkName(source, name) {
|
|
2652
2922
|
if (typeof name !== "string" || !name.trim()) {
|
|
2653
|
-
|
|
2923
|
+
invalid4(source, "Expected the stage name to be a non-empty string.");
|
|
2654
2924
|
}
|
|
2655
2925
|
}
|
|
2656
2926
|
function transformOf2(settings) {
|
|
2657
2927
|
checkName("transformOf", settings?.name);
|
|
2658
2928
|
if (typeof settings.apply !== "function") {
|
|
2659
|
-
|
|
2929
|
+
invalid4(settings.name, "Expected apply to be a function.");
|
|
2660
2930
|
}
|
|
2661
2931
|
const { name, apply, validate } = settings;
|
|
2662
2932
|
const factory = (given) => {
|
|
@@ -2680,7 +2950,7 @@ function transformOf2(settings) {
|
|
|
2680
2950
|
function sinkOf2(settings) {
|
|
2681
2951
|
checkName("sinkOf", settings?.name);
|
|
2682
2952
|
if (typeof settings.build !== "function") {
|
|
2683
|
-
|
|
2953
|
+
invalid4(settings.name, "Expected build to be a function.");
|
|
2684
2954
|
}
|
|
2685
2955
|
const { name, build, validate } = settings;
|
|
2686
2956
|
const factory = (given) => {
|
|
@@ -2718,10 +2988,10 @@ function stageCatalogOf2(...stages) {
|
|
|
2718
2988
|
for (const factory of stages) {
|
|
2719
2989
|
const known = factories.get(factory);
|
|
2720
2990
|
if (!known) {
|
|
2721
|
-
|
|
2991
|
+
invalid4("catalog", "A catalog takes factories made by `transformOf` or `sinkOf`.");
|
|
2722
2992
|
}
|
|
2723
2993
|
if (Object.hasOwn(byName, known.name)) {
|
|
2724
|
-
|
|
2994
|
+
invalid4(known.name, "The catalog has another stage with its name.");
|
|
2725
2995
|
}
|
|
2726
2996
|
byName[known.name] = factory;
|
|
2727
2997
|
}
|
|
@@ -2732,7 +3002,7 @@ function stageCatalogOf2(...stages) {
|
|
|
2732
3002
|
resolve(name, options) {
|
|
2733
3003
|
const factory = Object.hasOwn(byName, name) ? byName[name] : undefined;
|
|
2734
3004
|
if (!factory)
|
|
2735
|
-
|
|
3005
|
+
invalid4("catalog", `Unknown stage "${name}".`);
|
|
2736
3006
|
return factory(options);
|
|
2737
3007
|
}
|
|
2738
3008
|
});
|
|
@@ -2742,38 +3012,38 @@ function stageCatalogOf2(...stages) {
|
|
|
2742
3012
|
function isApplicationLike(value) {
|
|
2743
3013
|
return typeof value === "object" && value !== null && value[Kind2] === "application";
|
|
2744
3014
|
}
|
|
2745
|
-
function
|
|
3015
|
+
function invalid5(source, reason) {
|
|
2746
3016
|
throw new InvalidOutputStage2({ source, details: { reason } });
|
|
2747
3017
|
}
|
|
2748
3018
|
var PATCHABLE = ["meta", "tags", "description", "deprecated", "invoke"];
|
|
2749
3019
|
function operationOf2(operation, patch) {
|
|
2750
3020
|
const source = operation?.id ?? "operationOf";
|
|
2751
3021
|
if (operation?.kind !== "operation" || operation.version !== 1) {
|
|
2752
|
-
|
|
3022
|
+
invalid5(source, "Expected an operation descriptor.");
|
|
2753
3023
|
}
|
|
2754
3024
|
if (typeof patch !== "object" || patch === null || Array.isArray(patch)) {
|
|
2755
|
-
|
|
3025
|
+
invalid5(source, "Expected the patch to be an object.");
|
|
2756
3026
|
}
|
|
2757
3027
|
for (const key of Reflect.ownKeys(patch)) {
|
|
2758
3028
|
if (typeof key !== "string" || !PATCHABLE.includes(key)) {
|
|
2759
|
-
|
|
3029
|
+
invalid5(source, `"${String(key)}" cannot be patched; only ${PATCHABLE.join(", ")} can.`);
|
|
2760
3030
|
}
|
|
2761
3031
|
}
|
|
2762
3032
|
const { meta, tags, description, deprecated, invoke } = patch;
|
|
2763
3033
|
if ("meta" in patch && (typeof meta !== "object" || meta === null || Array.isArray(meta))) {
|
|
2764
|
-
|
|
3034
|
+
invalid5(source, "Expected meta to be an object.");
|
|
2765
3035
|
}
|
|
2766
3036
|
if ("tags" in patch && (!Array.isArray(tags) || tags.some((tag) => typeof tag !== "string"))) {
|
|
2767
|
-
|
|
3037
|
+
invalid5(source, "Expected tags to be a list of strings.");
|
|
2768
3038
|
}
|
|
2769
3039
|
if ("description" in patch && description !== undefined && typeof description !== "string") {
|
|
2770
|
-
|
|
3040
|
+
invalid5(source, "Expected description to be a string.");
|
|
2771
3041
|
}
|
|
2772
3042
|
if ("deprecated" in patch && typeof deprecated !== "boolean") {
|
|
2773
|
-
|
|
3043
|
+
invalid5(source, "Expected deprecated to be a boolean.");
|
|
2774
3044
|
}
|
|
2775
3045
|
if ("invoke" in patch && typeof invoke !== "function") {
|
|
2776
|
-
|
|
3046
|
+
invalid5(source, "Expected invoke to be a function.");
|
|
2777
3047
|
}
|
|
2778
3048
|
return Object.freeze({
|
|
2779
3049
|
...operation,
|
|
@@ -2814,25 +3084,25 @@ function statusesOf(name, statuses) {
|
|
|
2814
3084
|
if (statuses === undefined)
|
|
2815
3085
|
return Object.freeze({});
|
|
2816
3086
|
if (typeof statuses !== "object" || statuses === null || Array.isArray(statuses)) {
|
|
2817
|
-
|
|
3087
|
+
invalid5(name, "Expected statuses to be a map of exception names to statuses.");
|
|
2818
3088
|
}
|
|
2819
3089
|
for (const [exception, status] of Object.entries(statuses)) {
|
|
2820
3090
|
if (!exception || typeof status !== "number" || !Number.isInteger(status) || status < 400 || status > 599) {
|
|
2821
|
-
|
|
3091
|
+
invalid5(name, `Expected the status of "${exception}" to be an integer between 400 and 599.`);
|
|
2822
3092
|
}
|
|
2823
3093
|
}
|
|
2824
3094
|
return Object.freeze({ ...statuses });
|
|
2825
3095
|
}
|
|
2826
3096
|
function checkPipe(name, pipe) {
|
|
2827
3097
|
if (!Array.isArray(pipe))
|
|
2828
|
-
|
|
3098
|
+
invalid5(name, "Expected pipe to be a list of stages.");
|
|
2829
3099
|
const stages = pipe;
|
|
2830
3100
|
stages.forEach((stage, index) => {
|
|
2831
3101
|
if (!isStage(stage)) {
|
|
2832
|
-
|
|
3102
|
+
invalid5(name, `Expected pipe[${index}] to be a transform or sink stage.`);
|
|
2833
3103
|
}
|
|
2834
3104
|
if (stage.kind === "sink" && index !== stages.length - 1) {
|
|
2835
|
-
|
|
3105
|
+
invalid5(name, `The sink at pipe[${index}] must be the last stage.`);
|
|
2836
3106
|
}
|
|
2837
3107
|
});
|
|
2838
3108
|
return Object.freeze([...stages]);
|
|
@@ -2848,7 +3118,7 @@ function transformed(name, operations, transforms, context) {
|
|
|
2848
3118
|
if (result === null)
|
|
2849
3119
|
continue;
|
|
2850
3120
|
if (typeof result !== "object" || result?.kind !== "operation" || result.id !== operation.id) {
|
|
2851
|
-
|
|
3121
|
+
invalid5(name, `A transform must return the operation "${operation.id}" or null.`);
|
|
2852
3122
|
}
|
|
2853
3123
|
next.push(result);
|
|
2854
3124
|
}
|
|
@@ -2873,7 +3143,7 @@ function make(name, commands, operations, stages, statuses) {
|
|
|
2873
3143
|
return built.value;
|
|
2874
3144
|
const sink = stages.at(-1);
|
|
2875
3145
|
if (sink?.kind !== "sink") {
|
|
2876
|
-
|
|
3146
|
+
invalid5(name || "output", "The pipe has no sink to build.");
|
|
2877
3147
|
}
|
|
2878
3148
|
built = { value: sink.build(operations, context) };
|
|
2879
3149
|
return built.value;
|
|
@@ -2882,7 +3152,7 @@ function make(name, commands, operations, stages, statuses) {
|
|
|
2882
3152
|
const next = checkPipe(name || "output", more);
|
|
2883
3153
|
const last = next.at(-1);
|
|
2884
3154
|
if (stages.at(-1)?.kind === "sink") {
|
|
2885
|
-
|
|
3155
|
+
invalid5(name || "output", "Cannot add stages after the sink.");
|
|
2886
3156
|
}
|
|
2887
3157
|
const ops = transformed(name, operations, next, context);
|
|
2888
3158
|
if (last?.kind === "sink") {
|
|
@@ -2896,11 +3166,11 @@ function make(name, commands, operations, stages, statuses) {
|
|
|
2896
3166
|
function outputOf2(settings) {
|
|
2897
3167
|
const { name, commands } = settings ?? {};
|
|
2898
3168
|
if (typeof name !== "string" || !name.trim()) {
|
|
2899
|
-
|
|
3169
|
+
invalid5("outputOf", "Expected name to be a non-empty string.");
|
|
2900
3170
|
}
|
|
2901
3171
|
const sources = Array.isArray(commands) ? commands : [commands];
|
|
2902
3172
|
if (!Array.isArray(commands) && isCommand2(commands) || sources.some((entry) => !isCommand2(entry) && !isApplicationLike(entry))) {
|
|
2903
|
-
|
|
3173
|
+
invalid5(name, "Expected commands to be a list of commands made by commandOf or applications.");
|
|
2904
3174
|
}
|
|
2905
3175
|
const flat = [
|
|
2906
3176
|
...new Set(sources.flatMap((entry) => isCommand2(entry) ? [entry] : Object.values(entry.commands)))
|
|
@@ -2944,32 +3214,16 @@ function describeSteps(steps, names) {
|
|
|
2944
3214
|
});
|
|
2945
3215
|
}
|
|
2946
3216
|
|
|
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
3217
|
// src/core/application/start.ts
|
|
2972
3218
|
function providerFrom2(environmentDependencies, create) {
|
|
3219
|
+
if (typeof environmentDependencies === "function" && create === undefined) {
|
|
3220
|
+
return Object.freeze({
|
|
3221
|
+
[Kind2]: "provider-factory",
|
|
3222
|
+
environments: Object.freeze([]),
|
|
3223
|
+
create: environmentDependencies,
|
|
3224
|
+
withContext: true
|
|
3225
|
+
});
|
|
3226
|
+
}
|
|
2973
3227
|
const list = isEnvironment2(environmentDependencies) ? [environmentDependencies] : Array.isArray(environmentDependencies) ? [...environmentDependencies] : [null];
|
|
2974
3228
|
if (!list.every(isEnvironment2) || new Set(list).size !== list.length || typeof create !== "function") {
|
|
2975
3229
|
throw new InvalidApplicationDeclaration2({
|
|
@@ -2982,9 +3236,22 @@ function providerFrom2(environmentDependencies, create) {
|
|
|
2982
3236
|
return Object.freeze({
|
|
2983
3237
|
[Kind2]: "provider-factory",
|
|
2984
3238
|
environments: Object.freeze(list),
|
|
2985
|
-
create
|
|
3239
|
+
create,
|
|
3240
|
+
withContext: false
|
|
2986
3241
|
});
|
|
2987
3242
|
}
|
|
3243
|
+
function logFrom2(create) {
|
|
3244
|
+
if (typeof create !== "function") {
|
|
3245
|
+
throw new InvalidApplicationDeclaration2({
|
|
3246
|
+
source: "logFrom",
|
|
3247
|
+
details: { reason: "Expected logFrom to take a create function." }
|
|
3248
|
+
});
|
|
3249
|
+
}
|
|
3250
|
+
return Object.freeze({ [Kind2]: "log-factory", create });
|
|
3251
|
+
}
|
|
3252
|
+
function isLogFactory2(value) {
|
|
3253
|
+
return typeof value === "object" && value !== null && value[Kind2] === "log-factory";
|
|
3254
|
+
}
|
|
2988
3255
|
function isProviderFactory2(value) {
|
|
2989
3256
|
return typeof value === "object" && value !== null && value[Kind2] === "provider-factory";
|
|
2990
3257
|
}
|
|
@@ -3041,12 +3308,12 @@ function isDeferredProvider(provider) {
|
|
|
3041
3308
|
function deferredEnvironments(provider) {
|
|
3042
3309
|
return (typeof provider === "object" && provider !== null ? deferred.get(provider)?.factory.environments : undefined) ?? [];
|
|
3043
3310
|
}
|
|
3044
|
-
function startDeferred(provider) {
|
|
3311
|
+
function startDeferred(provider, context) {
|
|
3045
3312
|
const state = deferred.get(provider);
|
|
3046
3313
|
if (!state)
|
|
3047
3314
|
return;
|
|
3048
3315
|
state.starting ??= (async () => {
|
|
3049
|
-
const made = await state.factory.create(loadEnvironments(state.factory.environments));
|
|
3316
|
+
const made = await state.factory.create(state.factory.withContext ? context : loadEnvironments(state.factory.environments));
|
|
3050
3317
|
if (typeof made !== "object" || made === null) {
|
|
3051
3318
|
state.starting = undefined;
|
|
3052
3319
|
throw new InvalidApplicationDeclaration2({
|
|
@@ -3099,6 +3366,7 @@ var KEYS = [
|
|
|
3099
3366
|
"exceptions"
|
|
3100
3367
|
];
|
|
3101
3368
|
var internals = new WeakMap;
|
|
3369
|
+
var logSettings = new WeakMap;
|
|
3102
3370
|
var KIND_OF = {
|
|
3103
3371
|
properties: "property",
|
|
3104
3372
|
blueprints: "blueprint",
|
|
@@ -3114,7 +3382,7 @@ var KIND_OF = {
|
|
|
3114
3382
|
function isApplication2(value) {
|
|
3115
3383
|
return typeof value === "object" && value !== null && value[Kind2] === "application";
|
|
3116
3384
|
}
|
|
3117
|
-
function
|
|
3385
|
+
function invalid6(source, reason) {
|
|
3118
3386
|
throw new InvalidApplicationDeclaration2({ source, details: { reason } });
|
|
3119
3387
|
}
|
|
3120
3388
|
function isOfKind(collection, value) {
|
|
@@ -3199,7 +3467,7 @@ function resolve(settings) {
|
|
|
3199
3467
|
for (const other of settings.extends ?? []) {
|
|
3200
3468
|
const resolved = internals.get(other);
|
|
3201
3469
|
if (!resolved)
|
|
3202
|
-
|
|
3470
|
+
invalid6(source, "Expected `extends` to hold applications.");
|
|
3203
3471
|
for (const key of KEYS) {
|
|
3204
3472
|
for (const entry of resolved[key].values())
|
|
3205
3473
|
add(entry);
|
|
@@ -3210,15 +3478,15 @@ function resolve(settings) {
|
|
|
3210
3478
|
if (declared === undefined)
|
|
3211
3479
|
continue;
|
|
3212
3480
|
if (typeof declared !== "object" || declared === null || Array.isArray(declared)) {
|
|
3213
|
-
|
|
3481
|
+
invalid6(source, `Expected ${collection} to be an object of declarations.`);
|
|
3214
3482
|
}
|
|
3215
3483
|
for (const [name, value] of Object.entries(declared)) {
|
|
3216
3484
|
if (!isOfKind(collection, value)) {
|
|
3217
|
-
|
|
3485
|
+
invalid6(source, `${collection}.${name} is not a ${KIND_OF[collection]} (${collection} takes ${KIND_OF[collection]} declarations).`);
|
|
3218
3486
|
}
|
|
3219
3487
|
const declaredName = collection === "useCases" ? value.useCaseName : collection === "commands" ? value.commandName : collection === "outputs" ? value.outputName : collection === "exceptions" ? value.name : name;
|
|
3220
3488
|
if (declaredName !== name) {
|
|
3221
|
-
|
|
3489
|
+
invalid6(source, `${collection}.${name} must be keyed by its name, "${declaredName}".`);
|
|
3222
3490
|
}
|
|
3223
3491
|
add({
|
|
3224
3492
|
collection,
|
|
@@ -3339,7 +3607,7 @@ function validateOutputs(source, registry) {
|
|
|
3339
3607
|
for (const entry of registry.outputs.values()) {
|
|
3340
3608
|
const output = entry.value;
|
|
3341
3609
|
if (!output.outputName) {
|
|
3342
|
-
|
|
3610
|
+
invalid6(source, `outputs.${entry.name} has no name (an output made by pipe cannot be registered).`);
|
|
3343
3611
|
}
|
|
3344
3612
|
for (const command of output.commands) {
|
|
3345
3613
|
if (commands.has(command))
|
|
@@ -3369,7 +3637,7 @@ function validateUseCases(source, registry) {
|
|
|
3369
3637
|
for (const entry of registry.useCases.values()) {
|
|
3370
3638
|
const UseCase = entry.value;
|
|
3371
3639
|
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);
|
|
3640
|
+
const found = isLoggerDeclaration(dependency) ? true : isUseCaseClass2(dependency) ? useCases.has(dependency) : isEnvironment2(dependency) ? environments.has(dependency) : repositories.has(inspectRepository(dependency).state);
|
|
3373
3641
|
if (!found) {
|
|
3374
3642
|
throw new UnregisteredUseCaseDependency2({
|
|
3375
3643
|
source,
|
|
@@ -3541,7 +3809,7 @@ function recordDescriptionOf(entry, scope) {
|
|
|
3541
3809
|
plugins
|
|
3542
3810
|
};
|
|
3543
3811
|
}
|
|
3544
|
-
function describeRegistry(name, extended, registry, provider) {
|
|
3812
|
+
function describeRegistry(name, extended, registry, provider, log) {
|
|
3545
3813
|
const scope = {
|
|
3546
3814
|
properties: referencesOf(registry, "properties"),
|
|
3547
3815
|
blueprints: referencesOf(registry, "blueprints"),
|
|
@@ -3582,6 +3850,15 @@ function describeRegistry(name, extended, registry, provider) {
|
|
|
3582
3850
|
name,
|
|
3583
3851
|
extends: extended.map((other) => other.name),
|
|
3584
3852
|
...provider === undefined ? {} : { provider: providerDescriptionOf2(provider) },
|
|
3853
|
+
...log === undefined ? {} : log === "opaque" ? { log: { kind: "opaque" } } : {
|
|
3854
|
+
log: {
|
|
3855
|
+
level: log.level,
|
|
3856
|
+
providers: log.providers.map((logProvider) => {
|
|
3857
|
+
const providerName = logProviderNameOf(logProvider);
|
|
3858
|
+
return providerName === undefined ? { kind: "opaque" } : { kind: "log-provider", name: providerName };
|
|
3859
|
+
})
|
|
3860
|
+
}
|
|
3861
|
+
},
|
|
3585
3862
|
properties: each("properties", (entry) => ({
|
|
3586
3863
|
from: entry.from,
|
|
3587
3864
|
...propertyDescriptionOf(entry.value, scope)
|
|
@@ -3632,7 +3909,10 @@ function describeRegistry(name, extended, registry, provider) {
|
|
|
3632
3909
|
}),
|
|
3633
3910
|
dependencies: Object.fromEntries(Object.entries(UseCase.dependencies).map(([key, dependency]) => [
|
|
3634
3911
|
key,
|
|
3635
|
-
|
|
3912
|
+
isLoggerDeclaration(dependency) ? { kind: "logger", ref: "Logger" } : isUseCaseClass2(dependency) ? {
|
|
3913
|
+
kind: "use-case",
|
|
3914
|
+
ref: useCaseRefs.get(dependency)
|
|
3915
|
+
} : isEnvironment2(dependency) ? {
|
|
3636
3916
|
kind: "environment",
|
|
3637
3917
|
ref: environmentRefs.get(dependency)
|
|
3638
3918
|
} : {
|
|
@@ -3690,11 +3970,11 @@ function describeRegistry(name, extended, registry, provider) {
|
|
|
3690
3970
|
function applicationOf2(settings) {
|
|
3691
3971
|
const { name } = settings ?? {};
|
|
3692
3972
|
if (typeof name !== "string" || name === "") {
|
|
3693
|
-
|
|
3973
|
+
invalid6("applicationOf", "Expected a name.");
|
|
3694
3974
|
}
|
|
3695
3975
|
const extended = settings.extends ?? [];
|
|
3696
3976
|
if (!Array.isArray(extended) || !extended.every(isApplication2)) {
|
|
3697
|
-
|
|
3977
|
+
invalid6(name, "Expected `extends` to be a list of applications.");
|
|
3698
3978
|
}
|
|
3699
3979
|
const registry = resolve(settings);
|
|
3700
3980
|
validate(name, registry);
|
|
@@ -3703,7 +3983,7 @@ function applicationOf2(settings) {
|
|
|
3703
3983
|
validateOutputs(name, registry);
|
|
3704
3984
|
const declaredProvider = settings.provider ?? [...extended].reverse().find((other) => other.provider)?.provider;
|
|
3705
3985
|
if (declaredProvider !== undefined && typeof declaredProvider !== "object") {
|
|
3706
|
-
|
|
3986
|
+
invalid6(name, "Expected `provider` to be a repository provider.");
|
|
3707
3987
|
}
|
|
3708
3988
|
const provider = isProviderFactory2(declaredProvider) ? deferredProvider(declaredProvider, name) : declaredProvider;
|
|
3709
3989
|
{
|
|
@@ -3720,6 +4000,13 @@ function applicationOf2(settings) {
|
|
|
3720
4000
|
});
|
|
3721
4001
|
}
|
|
3722
4002
|
}
|
|
4003
|
+
const declaredLog = settings.log ?? [...extended].reverse().map((other) => logSettings.get(other)).find((log) => log !== undefined);
|
|
4004
|
+
const log = declaredLog === undefined ? undefined : applicationLogger(name);
|
|
4005
|
+
if (declaredLog !== undefined && !isLogFactory2(declaredLog)) {
|
|
4006
|
+
log?.set(checkLogSettings(declaredLog));
|
|
4007
|
+
}
|
|
4008
|
+
const logger = log?.logger;
|
|
4009
|
+
const rebinds = provider !== undefined || logger !== undefined;
|
|
3723
4010
|
const collection = (key) => Object.freeze(Object.fromEntries([...registry[key].values()].map((entry) => [entry.name, entry.value])));
|
|
3724
4011
|
const bound = new Map;
|
|
3725
4012
|
const boundByState = new Map;
|
|
@@ -3732,7 +4019,7 @@ function applicationOf2(settings) {
|
|
|
3732
4019
|
}
|
|
3733
4020
|
const boundUseCases = new Map;
|
|
3734
4021
|
const bindUseCase = (UseCase) => {
|
|
3735
|
-
if (
|
|
4022
|
+
if (!rebinds)
|
|
3736
4023
|
return UseCase;
|
|
3737
4024
|
const done = boundUseCases.get(UseCase);
|
|
3738
4025
|
if (done)
|
|
@@ -3745,11 +4032,13 @@ function applicationOf2(settings) {
|
|
|
3745
4032
|
boundUseCases.set(UseCase, Bound);
|
|
3746
4033
|
const dependencies = Object.fromEntries(Object.entries(UseCase.dependencies).map(([key, dependency]) => [
|
|
3747
4034
|
key,
|
|
3748
|
-
isUseCaseClass2(dependency) ? bindUseCase(dependency) : isEnvironment2(dependency) ? dependency : boundByState.get(inspectRepository(dependency).state) ?? dependency
|
|
4035
|
+
isUseCaseClass2(dependency) ? bindUseCase(dependency) : isEnvironment2(dependency) || isLoggerDeclaration(dependency) ? dependency : boundByState.get(inspectRepository(dependency).state) ?? dependency
|
|
3749
4036
|
]));
|
|
3750
4037
|
Object.defineProperty(Bound, "dependencies", {
|
|
3751
4038
|
value: Object.freeze(dependencies)
|
|
3752
4039
|
});
|
|
4040
|
+
if (logger)
|
|
4041
|
+
Object.defineProperty(Bound, ApplicationLoggerKey, { value: logger });
|
|
3753
4042
|
return Bound;
|
|
3754
4043
|
};
|
|
3755
4044
|
const useCases = {};
|
|
@@ -3763,7 +4052,7 @@ function applicationOf2(settings) {
|
|
|
3763
4052
|
const boundCommandOf = new Map;
|
|
3764
4053
|
for (const entry of registry.commands.values()) {
|
|
3765
4054
|
const declared = entry.value;
|
|
3766
|
-
const rebuilt =
|
|
4055
|
+
const rebuilt = !rebinds ? declared : commandOf2({
|
|
3767
4056
|
name: declared.commandName,
|
|
3768
4057
|
description: declared.description,
|
|
3769
4058
|
tags: declared.tags,
|
|
@@ -3786,7 +4075,7 @@ function applicationOf2(settings) {
|
|
|
3786
4075
|
const boundOutputOf = new Map;
|
|
3787
4076
|
for (const entry of registry.outputs.values()) {
|
|
3788
4077
|
const declared = entry.value;
|
|
3789
|
-
const rebuilt =
|
|
4078
|
+
const rebuilt = !rebinds ? declared : outputOf2({
|
|
3790
4079
|
name: declared.outputName,
|
|
3791
4080
|
commands: declared.commands.map((command) => boundCommandOf.get(command)),
|
|
3792
4081
|
statuses: declared.statuses,
|
|
@@ -3797,6 +4086,19 @@ function applicationOf2(settings) {
|
|
|
3797
4086
|
}
|
|
3798
4087
|
const environmentEntries = [...registry.environments.values()];
|
|
3799
4088
|
const registeredEnvironments = new Set(environmentEntries.map((entry) => entry.value));
|
|
4089
|
+
const context = Object.freeze({
|
|
4090
|
+
name,
|
|
4091
|
+
env(environment) {
|
|
4092
|
+
if (!registeredEnvironments.has(environment)) {
|
|
4093
|
+
throw new UnregisteredApplicationReference2({
|
|
4094
|
+
source: name,
|
|
4095
|
+
details: { holder: "the context", reference: "an environment" }
|
|
4096
|
+
});
|
|
4097
|
+
}
|
|
4098
|
+
return environment.load();
|
|
4099
|
+
},
|
|
4100
|
+
logger: logger ?? silentLogger
|
|
4101
|
+
});
|
|
3800
4102
|
let starting;
|
|
3801
4103
|
let started = false;
|
|
3802
4104
|
const start = async () => {
|
|
@@ -3822,8 +4124,11 @@ function applicationOf2(settings) {
|
|
|
3822
4124
|
cause
|
|
3823
4125
|
});
|
|
3824
4126
|
}
|
|
4127
|
+
if (isLogFactory2(declaredLog)) {
|
|
4128
|
+
log?.set(checkLogSettings(await declaredLog.create(context)));
|
|
4129
|
+
}
|
|
3825
4130
|
if (provider !== undefined && isDeferredProvider(provider)) {
|
|
3826
|
-
const made = await startDeferred(provider);
|
|
4131
|
+
const made = await startDeferred(provider, context);
|
|
3827
4132
|
checkTransactions(name, made, Object.entries(commands).filter(([, command]) => command.transaction && commandTransactionProvider(command) === provider).map(([key]) => key));
|
|
3828
4133
|
}
|
|
3829
4134
|
started = true;
|
|
@@ -3833,6 +4138,9 @@ function applicationOf2(settings) {
|
|
|
3833
4138
|
name,
|
|
3834
4139
|
extends: Object.freeze([...extended]),
|
|
3835
4140
|
provider,
|
|
4141
|
+
logger: logger ?? silentLogger,
|
|
4142
|
+
context,
|
|
4143
|
+
...logger ? { [ApplicationLoggerKey]: logger } : {},
|
|
3836
4144
|
properties: collection("properties"),
|
|
3837
4145
|
blueprints: collection("blueprints"),
|
|
3838
4146
|
records: collection("records"),
|
|
@@ -3845,25 +4153,25 @@ function applicationOf2(settings) {
|
|
|
3845
4153
|
exceptions: collection("exceptions"),
|
|
3846
4154
|
useCase(useCase) {
|
|
3847
4155
|
if (!boundUseCaseOf.has(useCase)) {
|
|
3848
|
-
|
|
4156
|
+
invalid6(name, "Expected a use case registered in the application.");
|
|
3849
4157
|
}
|
|
3850
4158
|
return boundUseCaseOf.get(useCase);
|
|
3851
4159
|
},
|
|
3852
4160
|
command(command) {
|
|
3853
4161
|
if (!boundCommandOf.has(command)) {
|
|
3854
|
-
|
|
4162
|
+
invalid6(name, "Expected a command registered in the application.");
|
|
3855
4163
|
}
|
|
3856
4164
|
return boundCommandOf.get(command);
|
|
3857
4165
|
},
|
|
3858
4166
|
output(output) {
|
|
3859
4167
|
if (!boundOutputOf.has(output)) {
|
|
3860
|
-
|
|
4168
|
+
invalid6(name, "Expected an output registered in the application.");
|
|
3861
4169
|
}
|
|
3862
4170
|
return boundOutputOf.get(output);
|
|
3863
4171
|
},
|
|
3864
4172
|
repository(repository) {
|
|
3865
4173
|
if (!bound.has(repository)) {
|
|
3866
|
-
|
|
4174
|
+
invalid6(name, "Expected a repository registered in the application.");
|
|
3867
4175
|
}
|
|
3868
4176
|
return bound.get(repository);
|
|
3869
4177
|
},
|
|
@@ -3871,10 +4179,11 @@ function applicationOf2(settings) {
|
|
|
3871
4179
|
return applicationOf2({
|
|
3872
4180
|
name,
|
|
3873
4181
|
extends: [application, ...others],
|
|
3874
|
-
...provider === undefined ? {} : { provider }
|
|
4182
|
+
...provider === undefined ? {} : { provider },
|
|
4183
|
+
...declaredLog === undefined ? {} : { log: declaredLog }
|
|
3875
4184
|
});
|
|
3876
4185
|
},
|
|
3877
|
-
describe: () => describeRegistry(name, extended, registry, provider),
|
|
4186
|
+
describe: () => describeRegistry(name, extended, registry, provider, isLogFactory2(declaredLog) ? "opaque" : log?.settings),
|
|
3878
4187
|
get started() {
|
|
3879
4188
|
return started;
|
|
3880
4189
|
},
|
|
@@ -3901,6 +4210,8 @@ function applicationOf2(settings) {
|
|
|
3901
4210
|
if (provider !== undefined && isDeferredProvider(provider)) {
|
|
3902
4211
|
await stopProvider(provider);
|
|
3903
4212
|
}
|
|
4213
|
+
if (isLogFactory2(declaredLog))
|
|
4214
|
+
log?.set(undefined);
|
|
3904
4215
|
throw error;
|
|
3905
4216
|
});
|
|
3906
4217
|
return starting;
|
|
@@ -3917,11 +4228,14 @@ function applicationOf2(settings) {
|
|
|
3917
4228
|
setStartedApplication(undefined);
|
|
3918
4229
|
if (provider !== undefined)
|
|
3919
4230
|
await stopProvider(provider);
|
|
4231
|
+
await log?.flush();
|
|
4232
|
+
if (isLogFactory2(declaredLog))
|
|
4233
|
+
log?.set(undefined);
|
|
3920
4234
|
},
|
|
3921
4235
|
get(declaration) {
|
|
3922
4236
|
if (isEnvironment2(declaration)) {
|
|
3923
4237
|
if (!registeredEnvironments.has(declaration)) {
|
|
3924
|
-
|
|
4238
|
+
invalid6(name, "Expected an environment registered in the application.");
|
|
3925
4239
|
}
|
|
3926
4240
|
return declaration.load();
|
|
3927
4241
|
}
|
|
@@ -3934,10 +4248,12 @@ function applicationOf2(settings) {
|
|
|
3934
4248
|
if (isRepository2(declaration)) {
|
|
3935
4249
|
return application.repository(declaration);
|
|
3936
4250
|
}
|
|
3937
|
-
return
|
|
4251
|
+
return invalid6(name, "Expected a repository, use case, command, output or environment registered in the application.");
|
|
3938
4252
|
}
|
|
3939
4253
|
});
|
|
3940
4254
|
internals.set(application, registry);
|
|
4255
|
+
if (declaredLog !== undefined)
|
|
4256
|
+
logSettings.set(application, declaredLog);
|
|
3941
4257
|
return application;
|
|
3942
4258
|
}
|
|
3943
4259
|
// src/core/blueprint/blueprint-plugin.ts
|
|
@@ -4086,7 +4402,7 @@ function validate2(options) {
|
|
|
4086
4402
|
}
|
|
4087
4403
|
return routeOptionsIssue2({ basePath, route }, "openapi");
|
|
4088
4404
|
}
|
|
4089
|
-
function
|
|
4405
|
+
function invalid7(reason, source = "openapi") {
|
|
4090
4406
|
throw new InvalidOutputStage2({ source, details: { reason } });
|
|
4091
4407
|
}
|
|
4092
4408
|
function kebab(text) {
|
|
@@ -4098,7 +4414,7 @@ function operationRoutes2(operations, options, source = "openapi") {
|
|
|
4098
4414
|
const ids = new Set(operations.map(({ id }) => id));
|
|
4099
4415
|
for (const id of Object.keys(route)) {
|
|
4100
4416
|
if (!ids.has(id)) {
|
|
4101
|
-
|
|
4417
|
+
invalid7(`${source}.route names the unknown operation "${id}".`, source);
|
|
4102
4418
|
}
|
|
4103
4419
|
}
|
|
4104
4420
|
const routes = new Map;
|
|
@@ -4109,7 +4425,7 @@ function operationRoutes2(operations, options, source = "openapi") {
|
|
|
4109
4425
|
const path = base + (chosen.path ?? `/${kebab(operation.command)}/${kebab(operation.name)}`);
|
|
4110
4426
|
const key = `${method} ${path}`;
|
|
4111
4427
|
if (taken.has(key)) {
|
|
4112
|
-
|
|
4428
|
+
invalid7(`Two operations are routed to ${method.toUpperCase()} ${path}.`, source);
|
|
4113
4429
|
}
|
|
4114
4430
|
taken.add(key);
|
|
4115
4431
|
routes.set(operation.id, { method, path });
|
|
@@ -4215,7 +4531,7 @@ function parametersOf(operation, schema) {
|
|
|
4215
4531
|
const field = operation.input.properties[name];
|
|
4216
4532
|
const type = property.type;
|
|
4217
4533
|
if (!isProperty2(field) || type === "object" || type === "array" || Array.isArray(type) && type.some((t) => t === "object" || t === "array")) {
|
|
4218
|
-
|
|
4534
|
+
invalid7(`${operation.id} uses a ${"get/delete"} route, whose input becomes query parameters, but "${name}" is not a scalar; route it with method "post".`);
|
|
4219
4535
|
}
|
|
4220
4536
|
const { description, ...rest } = property;
|
|
4221
4537
|
return {
|
|
@@ -4242,10 +4558,10 @@ var openapi2 = sinkOf2({
|
|
|
4242
4558
|
for (const record of records) {
|
|
4243
4559
|
const name = record.name;
|
|
4244
4560
|
if (!/^[A-Za-z0-9._-]+$/.test(name) || name === "Problem") {
|
|
4245
|
-
|
|
4561
|
+
invalid7(`The record class "${name}" cannot be a component name; give the class a name that is not "Problem".`);
|
|
4246
4562
|
}
|
|
4247
4563
|
if (classes.has(name)) {
|
|
4248
|
-
|
|
4564
|
+
invalid7(`Two record classes are named "${name}"; rename one.`);
|
|
4249
4565
|
}
|
|
4250
4566
|
classes.set(name, record);
|
|
4251
4567
|
models[name] = record;
|
|
@@ -4265,7 +4581,7 @@ var openapi2 = sinkOf2({
|
|
|
4265
4581
|
const { method, path } = routes.get(operation.id);
|
|
4266
4582
|
const operationId = operation.id.replaceAll(".", "_");
|
|
4267
4583
|
if (operationIds.has(operationId)) {
|
|
4268
|
-
|
|
4584
|
+
invalid7(`The operationId "${operationId}" is produced twice.`);
|
|
4269
4585
|
}
|
|
4270
4586
|
operationIds.add(operationId);
|
|
4271
4587
|
const slot = paths[path] ?? {};
|
|
@@ -5016,4 +5332,4 @@ var entityOf2 = entityBuilderOf2({
|
|
|
5016
5332
|
var recordOf2 = recordBuilderOf2(StdRecordPlugins2);
|
|
5017
5333
|
// src/std/stages.ts
|
|
5018
5334
|
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,
|
|
5335
|
+
export { InvalidEnvironment2, environmentOf2, isEnvironment2, guard2, InvalidApplicationDeclaration2, DuplicateApplicationDeclaration2, ApplicationConflict2, UnregisteredApplicationReference2, UnregisteredRepositoryDependency2, UnregisteredUseCaseDependency2, ApplicationNotStarted2, 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, 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 };
|