@loutrejs/loutre 0.5.0 → 0.6.0
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/README.md +63 -32
- package/dist/adapters/aws-lambda.d.ts +5 -3
- package/dist/adapters/aws-lambda.js +53 -23
- package/dist/adapters/bun.d.ts +7 -4
- package/dist/adapters/bun.js +52 -42
- package/dist/adapters/cloudflare-workers.d.ts +5 -3
- package/dist/adapters/cloudflare-workers.js +23 -28
- package/dist/adapters/deno.d.ts +7 -4
- package/dist/adapters/deno.js +94 -57
- package/dist/adapters/electron.d.ts +13 -5
- package/dist/adapters/electron.js +76 -28
- package/dist/application/definition.d.ts +31 -0
- package/dist/application/definition.js +16 -0
- package/dist/application/index.d.ts +4 -63
- package/dist/application/index.js +2 -11
- package/dist/application/kernel-internal.d.ts +2 -0
- package/dist/application/kernel-internal.js +10 -0
- package/dist/application/kernel.d.ts +21 -0
- package/dist/application/kernel.js +65 -0
- package/dist/core/diagnostic.d.ts +9 -0
- package/dist/core/diagnostic.js +9 -0
- package/dist/core/extension.d.ts +107 -0
- package/dist/core/extension.js +73 -0
- package/dist/core/generic-layer.d.ts +26 -0
- package/dist/core/generic-layer.js +116 -0
- package/dist/core/index.d.ts +31 -15
- package/dist/core/index.js +15 -15
- package/dist/core/injection.d.ts +4 -13
- package/dist/core/injection.js +63 -0
- package/dist/core/model/context.d.ts +18 -0
- package/dist/core/model/context.js +34 -0
- package/dist/core/model/lifecycle.d.ts +5 -0
- package/dist/core/model/lifecycle.js +44 -0
- package/dist/core/model/modules.d.ts +2 -0
- package/dist/core/model/modules.js +101 -0
- package/dist/core/model/providers.d.ts +4 -0
- package/dist/core/model/providers.js +74 -0
- package/dist/core/model/snapshot.d.ts +6 -0
- package/dist/core/model/snapshot.js +31 -0
- package/dist/core/model/types.d.ts +78 -0
- package/dist/core/model/validation.d.ts +4 -0
- package/dist/core/model/validation.js +40 -0
- package/dist/core/model/visibility.d.ts +4 -0
- package/dist/core/model/visibility.js +20 -0
- package/dist/core/model.d.ts +10 -0
- package/dist/core/model.js +346 -0
- package/dist/core/module.d.ts +8 -13
- package/dist/core/source-location.d.ts +8 -0
- package/dist/core/source-location.js +31 -0
- package/dist/core/token-internal.d.ts +3 -0
- package/dist/core/token-internal.js +4 -0
- package/dist/core/type.d.ts +7 -0
- package/dist/core/type.js +4 -0
- package/dist/generated/version.d.ts +1 -1
- package/dist/generated/version.js +1 -1
- package/dist/graph/index.d.ts +2 -3
- package/dist/graph/index.js +1 -3
- package/dist/graph/model.d.ts +34 -0
- package/dist/graph/model.js +127 -0
- package/dist/http/auth.d.ts +46 -0
- package/dist/http/auth.js +96 -0
- package/dist/http/client.d.ts +28 -31
- package/dist/http/client.js +58 -44
- package/dist/http/cors-internal.d.ts +29 -0
- package/dist/http/cors-internal.js +160 -0
- package/dist/http/cors.d.ts +5 -8
- package/dist/http/cors.js +7 -165
- package/dist/http/extension.d.ts +348 -0
- package/dist/http/extension.js +947 -0
- package/dist/http/index.d.ts +9 -7
- package/dist/http/index.js +5 -7
- package/dist/{application → http}/openapi.d.ts +12 -3
- package/dist/{application → http}/openapi.js +164 -102
- package/dist/http/path.d.ts +1 -42
- package/dist/http/path.js +1 -2
- package/dist/http/runtime/request.d.ts +17 -0
- package/dist/http/runtime/request.js +109 -0
- package/dist/http/runtime/response.d.ts +18 -0
- package/dist/http/runtime/response.js +108 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +2 -0
- package/dist/message-port/extension.d.ts +66 -0
- package/dist/message-port/extension.js +395 -0
- package/dist/message-port/index.d.ts +4 -73
- package/dist/message-port/index.js +2 -189
- package/dist/message-port/transport.d.ts +11 -0
- package/dist/message-port/transport.js +45 -0
- package/dist/runtime/async-iterator-lifecycle.d.ts +12 -0
- package/dist/runtime/async-iterator-lifecycle.js +95 -0
- package/dist/runtime/capability.d.ts +11 -11
- package/dist/runtime/capability.js +3 -3
- package/dist/runtime/di.d.ts +2 -22
- package/dist/runtime/di.js +8 -285
- package/dist/runtime/execution-tracker.d.ts +8 -0
- package/dist/runtime/execution-tracker.js +54 -0
- package/dist/runtime/index.d.ts +15 -9
- package/dist/runtime/index.js +9 -9
- package/dist/runtime/ingress-gate.d.ts +7 -0
- package/dist/runtime/ingress-gate.js +33 -0
- package/dist/runtime/kernel.d.ts +23 -0
- package/dist/runtime/kernel.js +354 -0
- package/dist/runtime/logger.d.ts +2 -0
- package/dist/runtime/logger.js +2 -0
- package/dist/runtime/node-capabilities.d.ts +1 -1
- package/dist/runtime/node-capabilities.js +1 -1
- package/dist/runtime/server-port.d.ts +2 -0
- package/dist/runtime/server-port.js +11 -0
- package/dist/tasks/extension.d.ts +144 -0
- package/dist/tasks/extension.js +499 -0
- package/dist/tasks/index.d.ts +2 -0
- package/dist/tasks/index.js +1 -0
- package/dist/tasks/runtime/cron.d.ts +6 -0
- package/dist/tasks/runtime/cron.js +89 -0
- package/dist/websocket/errors.d.ts +9 -0
- package/dist/websocket/errors.js +18 -0
- package/dist/websocket/extension.d.ts +154 -0
- package/dist/websocket/extension.js +524 -0
- package/dist/websocket/index.d.ts +3 -0
- package/dist/websocket/index.js +2 -0
- package/package.json +12 -16
- package/dist/application/binding.d.ts +0 -33
- package/dist/application/binding.js +0 -295
- package/dist/application/host.d.ts +0 -8
- package/dist/application/host.js +0 -14
- package/dist/application/queue.d.ts +0 -3
- package/dist/application/queue.js +0 -4
- package/dist/application/scheduler.d.ts +0 -2
- package/dist/application/scheduler.js +0 -45
- package/dist/core/context-key.d.ts +0 -16
- package/dist/core/context-key.js +0 -17
- package/dist/core/contract-internal.d.ts +0 -22
- package/dist/core/contract-internal.js +0 -61
- package/dist/core/contract.d.ts +0 -96
- package/dist/core/contract.js +0 -88
- package/dist/core/execution.d.ts +0 -78
- package/dist/core/execution.js +0 -61
- package/dist/core/implementation.d.ts +0 -44
- package/dist/core/implementation.js +0 -35
- package/dist/core/layer.d.ts +0 -137
- package/dist/core/layer.js +0 -81
- package/dist/graph/compiler.d.ts +0 -4
- package/dist/graph/compiler.js +0 -228
- package/dist/graph/graph.d.ts +0 -18
- package/dist/graph/graph.js +0 -1118
- package/dist/graph/ir.d.ts +0 -175
- package/dist/http/application.d.ts +0 -18
- package/dist/http/application.js +0 -515
- package/dist/http/basic-auth.d.ts +0 -37
- package/dist/http/basic-auth.js +0 -67
- package/dist/http/definitions.d.ts +0 -363
- package/dist/http/definitions.js +0 -310
- package/dist/http/hosted-protocol.d.ts +0 -4
- package/dist/http/hosted-protocol.js +0 -4
- package/dist/http/internal.d.ts +0 -8
- package/dist/http/internal.js +0 -1
- package/dist/http/params.d.ts +0 -2
- package/dist/http/params.js +0 -19
- package/dist/http/request-body.d.ts +0 -4
- package/dist/http/request-body.js +0 -6
- package/dist/http/validate.d.ts +0 -20
- package/dist/http/validate.js +0 -6
- package/dist/message-port/environment.d.ts +0 -2
- package/dist/message-port/environment.js +0 -4
- package/dist/runtime/application.d.ts +0 -38
- package/dist/runtime/application.js +0 -339
- package/dist/runtime/pipeline.d.ts +0 -11
- package/dist/runtime/pipeline.js +0 -161
- /package/dist/{graph/ir.js → core/model/types.js} +0 -0
package/dist/runtime/di.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isArgsClass, isEnvClass, runInInjectionContext, tokenName, } from '../core/index.js';
|
|
2
2
|
import { Logger } from './logger.js';
|
|
3
3
|
export class DependencyResolutionError extends Error {
|
|
4
4
|
constructor(message) {
|
|
@@ -6,59 +6,15 @@ export class DependencyResolutionError extends Error {
|
|
|
6
6
|
this.name = 'DependencyResolutionError';
|
|
7
7
|
}
|
|
8
8
|
}
|
|
9
|
-
class GraphProbeBoundary extends Error {
|
|
10
|
-
source;
|
|
11
|
-
constructor(source) {
|
|
12
|
-
super(`Graph Probe reached runtime-dependent value: ${source}`);
|
|
13
|
-
this.source = source;
|
|
14
|
-
this.name = 'GraphProbeBoundary';
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
export function collectRuntimeModuleGraph(roots) {
|
|
18
|
-
const modules = [];
|
|
19
|
-
const providers = [];
|
|
20
|
-
const environmentProviders = new Set();
|
|
21
|
-
const visited = new Set();
|
|
22
|
-
const visit = (moduleLike) => {
|
|
23
|
-
const module = asModuleInstance(moduleLike);
|
|
24
|
-
if (visited.has(module))
|
|
25
|
-
return;
|
|
26
|
-
visited.add(module);
|
|
27
|
-
for (const imported of module.definition.imports ?? [])
|
|
28
|
-
visit(imported);
|
|
29
|
-
modules.push(module);
|
|
30
|
-
for (const declaration of module.definition.providers ?? []) {
|
|
31
|
-
const provider = normalizeProvider(declaration);
|
|
32
|
-
if (provider.kind === 'environment') {
|
|
33
|
-
if (environmentProviders.has(provider.provide))
|
|
34
|
-
continue;
|
|
35
|
-
environmentProviders.add(provider.provide);
|
|
36
|
-
}
|
|
37
|
-
providers.push(provider);
|
|
38
|
-
}
|
|
39
|
-
};
|
|
40
|
-
for (const root of roots)
|
|
41
|
-
visit(root);
|
|
42
|
-
return { modules, providers };
|
|
43
|
-
}
|
|
44
9
|
export class Container {
|
|
45
10
|
#providers = new Map();
|
|
46
11
|
#applicationCache = new Map();
|
|
47
|
-
#implementationCache = new Map();
|
|
48
|
-
#implementationConsumers = new Map();
|
|
49
|
-
#taskCache = new Map();
|
|
50
|
-
#taskConsumers = new Map();
|
|
51
|
-
#layerCache = new Map();
|
|
52
12
|
#logger;
|
|
53
|
-
#recorder;
|
|
54
13
|
#environment = new Map();
|
|
55
14
|
#arguments = new Map();
|
|
56
|
-
#probe;
|
|
57
15
|
constructor(providers, options = {}) {
|
|
58
16
|
this.#logger =
|
|
59
17
|
options instanceof Logger ? options : (options.logger ?? new Logger());
|
|
60
|
-
this.#recorder = options instanceof Logger ? undefined : options.recorder;
|
|
61
|
-
this.#probe = options instanceof Logger ? false : (options.probe ?? false);
|
|
62
18
|
if (!(options instanceof Logger)) {
|
|
63
19
|
for (const [environment, value] of options.environment ?? []) {
|
|
64
20
|
this.#environment.set(environment, value);
|
|
@@ -107,8 +63,8 @@ export class Container {
|
|
|
107
63
|
}
|
|
108
64
|
this.#arguments.set(argumentsContract, value);
|
|
109
65
|
}
|
|
110
|
-
resolve(token) {
|
|
111
|
-
return this.#resolve(token);
|
|
66
|
+
resolve(token, source) {
|
|
67
|
+
return this.#resolve(token, source);
|
|
112
68
|
}
|
|
113
69
|
get(token) {
|
|
114
70
|
const provider = this.#providers.get(token);
|
|
@@ -141,112 +97,6 @@ export class Container {
|
|
|
141
97
|
}
|
|
142
98
|
throw new DependencyResolutionError(`LUTRE_DI_NOT_INITIALIZED: ${tokenName(token)} has not been constructed by Application initialization.`);
|
|
143
99
|
}
|
|
144
|
-
probeClass(target) {
|
|
145
|
-
try {
|
|
146
|
-
return this.#instantiate(target, [target]);
|
|
147
|
-
}
|
|
148
|
-
catch (error) {
|
|
149
|
-
if (isGraphProbeBoundary(error)) {
|
|
150
|
-
return createOpaqueProbeValue(target.name);
|
|
151
|
-
}
|
|
152
|
-
throw error;
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
prepareImplementation(implementation) {
|
|
156
|
-
if (this.#implementationCache.has(implementation))
|
|
157
|
-
return;
|
|
158
|
-
let consumer = this.#implementationConsumers.get(implementation);
|
|
159
|
-
if (!consumer) {
|
|
160
|
-
consumer = {
|
|
161
|
-
kind: 'implementation-consumer',
|
|
162
|
-
id: `runtime-implementation:${this.#implementationConsumers.size + 1}`,
|
|
163
|
-
name: implementation.name,
|
|
164
|
-
};
|
|
165
|
-
this.#implementationConsumers.set(implementation, consumer);
|
|
166
|
-
}
|
|
167
|
-
this.#constructImplementation(implementation, consumer, true);
|
|
168
|
-
}
|
|
169
|
-
implementationRuntime(implementation) {
|
|
170
|
-
const cached = this.#implementationCache.get(implementation);
|
|
171
|
-
if (!cached) {
|
|
172
|
-
throw new DependencyResolutionError(`LUTRE_IMPL_NOT_PREPARED: Implementation ${implementation.name} is not prepared during application construction.`);
|
|
173
|
-
}
|
|
174
|
-
return cached;
|
|
175
|
-
}
|
|
176
|
-
prepareTask(task) {
|
|
177
|
-
if (this.#taskCache.has(task))
|
|
178
|
-
return;
|
|
179
|
-
let consumer = this.#taskConsumers.get(task);
|
|
180
|
-
if (!consumer) {
|
|
181
|
-
consumer = {
|
|
182
|
-
kind: 'task-consumer',
|
|
183
|
-
id: `runtime-task:${this.#taskConsumers.size + 1}`,
|
|
184
|
-
name: task.name,
|
|
185
|
-
};
|
|
186
|
-
this.#taskConsumers.set(task, consumer);
|
|
187
|
-
}
|
|
188
|
-
this.#constructTask(task, consumer, true);
|
|
189
|
-
}
|
|
190
|
-
taskRuntime(task) {
|
|
191
|
-
const cached = this.#taskCache.get(task);
|
|
192
|
-
if (!cached) {
|
|
193
|
-
throw new DependencyResolutionError(`LUTRE_TASK_NOT_PREPARED: Task ${task.name} is not prepared during application construction.`);
|
|
194
|
-
}
|
|
195
|
-
return cached;
|
|
196
|
-
}
|
|
197
|
-
probeTask(task, consumer) {
|
|
198
|
-
try {
|
|
199
|
-
this.#constructTask(task, consumer, false);
|
|
200
|
-
}
|
|
201
|
-
catch (error) {
|
|
202
|
-
if (isGraphProbeBoundary(error))
|
|
203
|
-
return;
|
|
204
|
-
throw error;
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
probeImplementation(implementation, consumer) {
|
|
208
|
-
try {
|
|
209
|
-
return this.#constructImplementation(implementation, consumer, false);
|
|
210
|
-
}
|
|
211
|
-
catch (error) {
|
|
212
|
-
if (isGraphProbeBoundary(error)) {
|
|
213
|
-
return createOpaqueProbeValue(implementation.name);
|
|
214
|
-
}
|
|
215
|
-
throw error;
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
preparePipeline(pipeline) {
|
|
219
|
-
for (const item of pipeline) {
|
|
220
|
-
if (item.kind !== 'layer')
|
|
221
|
-
continue;
|
|
222
|
-
const definition = layerDefinitionOf(item);
|
|
223
|
-
this.#constructLayer(definition, {
|
|
224
|
-
kind: 'layer-consumer',
|
|
225
|
-
id: `runtime-layer:${definition.name}`,
|
|
226
|
-
name: definition.name,
|
|
227
|
-
}, true);
|
|
228
|
-
const child = childPipelineOf(item);
|
|
229
|
-
if (child)
|
|
230
|
-
this.preparePipeline(child);
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
layerRuntime(layer) {
|
|
234
|
-
const cached = this.#layerCache.get(layer);
|
|
235
|
-
if (!cached) {
|
|
236
|
-
throw new DependencyResolutionError(`LUTRE_LAYER_NOT_PREPARED: Layer ${layer.name} is not prepared during application construction.`);
|
|
237
|
-
}
|
|
238
|
-
return cached;
|
|
239
|
-
}
|
|
240
|
-
probeLayer(layer, consumer) {
|
|
241
|
-
try {
|
|
242
|
-
this.#constructLayer(layer, consumer, false);
|
|
243
|
-
}
|
|
244
|
-
catch (error) {
|
|
245
|
-
if (isGraphProbeBoundary(error))
|
|
246
|
-
return;
|
|
247
|
-
throw error;
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
100
|
#resolve(token, source, lineage = []) {
|
|
251
101
|
const cycleStart = lineage.indexOf(token);
|
|
252
102
|
if (cycleStart >= 0) {
|
|
@@ -272,9 +122,9 @@ export class Container {
|
|
|
272
122
|
if (provider.scope !== 'application') {
|
|
273
123
|
return this.#create(provider, nextLineage);
|
|
274
124
|
}
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
125
|
+
if (this.#applicationCache.has(token)) {
|
|
126
|
+
return this.#applicationCache.get(token);
|
|
127
|
+
}
|
|
278
128
|
const instance = this.#create(provider, nextLineage);
|
|
279
129
|
this.#applicationCache.set(token, instance);
|
|
280
130
|
return instance;
|
|
@@ -288,17 +138,13 @@ export class Container {
|
|
|
288
138
|
if (this.#environment.has(provider.provide)) {
|
|
289
139
|
return this.#environment.get(provider.provide);
|
|
290
140
|
}
|
|
291
|
-
if (this.#probe)
|
|
292
|
-
return createOpaqueProbeValue(provider.provide.name);
|
|
293
141
|
throw new DependencyResolutionError(`LUTRE_ENV_005: Environment ${provider.provide.name} requires a runtime Environment source before Application initialization.`);
|
|
294
142
|
}
|
|
295
143
|
case 'arguments': {
|
|
296
144
|
if (this.#arguments.has(provider.provide)) {
|
|
297
145
|
return this.#arguments.get(provider.provide);
|
|
298
146
|
}
|
|
299
|
-
|
|
300
|
-
return createOpaqueProbeValue(provider.provide.name);
|
|
301
|
-
throw new DependencyResolutionError(`LUTRE_ARGS_005: Arguments ${provider.provide.name} requires a runtime Arguments source before Application initialization.`);
|
|
147
|
+
throw new DependencyResolutionError(`LUTRE_ARGS_005: Arguments ${provider.provide.name} requires runtime Arguments before Application initialization.`);
|
|
302
148
|
}
|
|
303
149
|
case 'class':
|
|
304
150
|
return this.#instantiate(provider.useClass, lineage);
|
|
@@ -311,8 +157,6 @@ export class Container {
|
|
|
311
157
|
return value;
|
|
312
158
|
}
|
|
313
159
|
case 'conditional': {
|
|
314
|
-
if (this.#probe)
|
|
315
|
-
return Object.create(null);
|
|
316
160
|
const input = this.#resolve(provider.select.contract, tokenName(provider.provide), lineage);
|
|
317
161
|
const selected = input[provider.select.key];
|
|
318
162
|
const implementation = provider.mapping[selected];
|
|
@@ -327,9 +171,6 @@ export class Container {
|
|
|
327
171
|
if (provider.scope === 'application') {
|
|
328
172
|
this.#applicationCache.delete(provider.provide);
|
|
329
173
|
}
|
|
330
|
-
if (this.#probe && isGraphProbeBoundary(error)) {
|
|
331
|
-
return createOpaqueProbeValue(tokenName(provider.provide));
|
|
332
|
-
}
|
|
333
174
|
throw error;
|
|
334
175
|
}
|
|
335
176
|
}
|
|
@@ -340,133 +181,15 @@ export class Container {
|
|
|
340
181
|
return runInInjectionContext({
|
|
341
182
|
consumer: target,
|
|
342
183
|
resolve: (token) => this.#resolve(token, target.name, lineage),
|
|
343
|
-
...(this.#recorder === undefined
|
|
344
|
-
? {}
|
|
345
|
-
: {
|
|
346
|
-
record: (consumer, dependency) => this.#recorder.record(consumer, dependency),
|
|
347
|
-
}),
|
|
348
184
|
}, () => new target());
|
|
349
185
|
}
|
|
350
|
-
#constructLayer(layer, consumer, cache) {
|
|
351
|
-
const cached = this.#layerCache.get(layer);
|
|
352
|
-
if (cache && cached)
|
|
353
|
-
return cached;
|
|
354
|
-
const runtime = runInInjectionContext({
|
|
355
|
-
consumer,
|
|
356
|
-
resolve: (token) => this.#resolve(token, layer.name),
|
|
357
|
-
...(this.#recorder === undefined
|
|
358
|
-
? {}
|
|
359
|
-
: {
|
|
360
|
-
record: (recordedConsumer, dependency) => this.#recorder.record(recordedConsumer, dependency),
|
|
361
|
-
}),
|
|
362
|
-
}, () => layer.factory());
|
|
363
|
-
if (isThenable(runtime)) {
|
|
364
|
-
throw new DependencyResolutionError(`LUTRE_LAYER_ASYNC_FACTORY: Layer ${layer.name} factory must be synchronous.`);
|
|
365
|
-
}
|
|
366
|
-
if (typeof runtime !== 'function') {
|
|
367
|
-
throw new DependencyResolutionError(`LUTRE_LAYER_FACTORY_RESULT: Layer ${layer.name} factory must return a runtime function.`);
|
|
368
|
-
}
|
|
369
|
-
const normalized = runtime;
|
|
370
|
-
if (cache)
|
|
371
|
-
this.#layerCache.set(layer, normalized);
|
|
372
|
-
return normalized;
|
|
373
|
-
}
|
|
374
|
-
#constructImplementation(implementation, consumer, cache) {
|
|
375
|
-
const cached = this.#implementationCache.get(implementation);
|
|
376
|
-
if (cache && cached)
|
|
377
|
-
return cached;
|
|
378
|
-
const runtime = runInInjectionContext({
|
|
379
|
-
consumer,
|
|
380
|
-
resolve: (token) => this.#resolve(token, implementation.name),
|
|
381
|
-
...(this.#recorder === undefined
|
|
382
|
-
? {}
|
|
383
|
-
: {
|
|
384
|
-
record: (recordedConsumer, dependency) => this.#recorder.record(recordedConsumer, dependency),
|
|
385
|
-
}),
|
|
386
|
-
}, () => implementation.factory());
|
|
387
|
-
if (isThenable(runtime)) {
|
|
388
|
-
throw new DependencyResolutionError(`LUTRE_IMPL_ASYNC_FACTORY: Implementation ${implementation.name} factory must be synchronous.`);
|
|
389
|
-
}
|
|
390
|
-
if (typeof runtime !== 'object' ||
|
|
391
|
-
runtime === null ||
|
|
392
|
-
Array.isArray(runtime)) {
|
|
393
|
-
throw new DependencyResolutionError(`LUTRE_IMPL_FACTORY_RESULT: Implementation ${implementation.name} factory must return a non-null object.`);
|
|
394
|
-
}
|
|
395
|
-
const normalized = runtime;
|
|
396
|
-
for (const procedure of implementation.procedures) {
|
|
397
|
-
if (typeof normalized[procedure] !== 'function') {
|
|
398
|
-
throw new DependencyResolutionError(`LUTRE_IMPL_004: Implementation ${implementation.name} does not implement callable procedure ${procedure}.`);
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
if (cache)
|
|
402
|
-
this.#implementationCache.set(implementation, normalized);
|
|
403
|
-
return normalized;
|
|
404
|
-
}
|
|
405
|
-
#constructTask(task, consumer, cache) {
|
|
406
|
-
const cached = this.#taskCache.get(task);
|
|
407
|
-
if (cache && cached)
|
|
408
|
-
return cached;
|
|
409
|
-
const runtime = runInInjectionContext({
|
|
410
|
-
consumer,
|
|
411
|
-
resolve: (token) => this.#resolve(token, task.name),
|
|
412
|
-
...(this.#recorder === undefined
|
|
413
|
-
? {}
|
|
414
|
-
: {
|
|
415
|
-
record: (recordedConsumer, dependency) => this.#recorder.record(recordedConsumer, dependency),
|
|
416
|
-
}),
|
|
417
|
-
}, () => task.factory());
|
|
418
|
-
if (isThenable(runtime)) {
|
|
419
|
-
throw new DependencyResolutionError(`LUTRE_TASK_ASYNC_FACTORY: Task ${task.name} factory must be synchronous.`);
|
|
420
|
-
}
|
|
421
|
-
if (typeof runtime !== 'function') {
|
|
422
|
-
throw new DependencyResolutionError(`LUTRE_TASK_FACTORY_RESULT: Task ${task.name} factory must return a runtime function.`);
|
|
423
|
-
}
|
|
424
|
-
const normalized = runtime;
|
|
425
|
-
if (cache)
|
|
426
|
-
this.#taskCache.set(task, normalized);
|
|
427
|
-
return normalized;
|
|
428
|
-
}
|
|
429
186
|
}
|
|
430
187
|
function isRuntimeInputProvider(provider) {
|
|
431
188
|
return provider.kind === 'environment' || provider.kind === 'arguments';
|
|
432
189
|
}
|
|
433
|
-
function isGraphProbeBoundary(error) {
|
|
434
|
-
return error instanceof GraphProbeBoundary;
|
|
435
|
-
}
|
|
436
|
-
function createOpaqueProbeValue(source) {
|
|
437
|
-
const boundary = (operation) => new GraphProbeBoundary(`${source}.${String(operation)}`);
|
|
438
|
-
return new Proxy(Object.create(null), {
|
|
439
|
-
get(_target, key) {
|
|
440
|
-
throw boundary(key);
|
|
441
|
-
},
|
|
442
|
-
set(_target, key) {
|
|
443
|
-
throw boundary(key);
|
|
444
|
-
},
|
|
445
|
-
has(_target, key) {
|
|
446
|
-
throw boundary(key);
|
|
447
|
-
},
|
|
448
|
-
ownKeys() {
|
|
449
|
-
throw boundary('*');
|
|
450
|
-
},
|
|
451
|
-
getOwnPropertyDescriptor(_target, key) {
|
|
452
|
-
throw boundary(key);
|
|
453
|
-
},
|
|
454
|
-
defineProperty(_target, key) {
|
|
455
|
-
throw boundary(key);
|
|
456
|
-
},
|
|
457
|
-
deleteProperty(_target, key) {
|
|
458
|
-
throw boundary(key);
|
|
459
|
-
},
|
|
460
|
-
getPrototypeOf() {
|
|
461
|
-
throw boundary('[[Prototype]]');
|
|
462
|
-
},
|
|
463
|
-
setPrototypeOf() {
|
|
464
|
-
throw boundary('[[Prototype]]');
|
|
465
|
-
},
|
|
466
|
-
});
|
|
467
|
-
}
|
|
468
190
|
function isThenable(value) {
|
|
469
191
|
return (((typeof value === 'object' && value !== null) ||
|
|
470
192
|
typeof value === 'function') &&
|
|
193
|
+
'then' in value &&
|
|
471
194
|
typeof value.then === 'function');
|
|
472
195
|
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
export class ExecutionTracker {
|
|
2
|
+
#active = new Set();
|
|
3
|
+
#idleWaiters = new Set();
|
|
4
|
+
get size() {
|
|
5
|
+
return this.#active.size;
|
|
6
|
+
}
|
|
7
|
+
begin() {
|
|
8
|
+
const controller = new AbortController();
|
|
9
|
+
const lease = {
|
|
10
|
+
controller,
|
|
11
|
+
signal: controller.signal,
|
|
12
|
+
completed: false,
|
|
13
|
+
abort: (reason) => controller.abort(reason),
|
|
14
|
+
complete: () => {
|
|
15
|
+
if (lease.completed)
|
|
16
|
+
return;
|
|
17
|
+
lease.completed = true;
|
|
18
|
+
if (!controller.signal.aborted)
|
|
19
|
+
controller.abort();
|
|
20
|
+
this.#active.delete(lease);
|
|
21
|
+
if (this.#active.size !== 0)
|
|
22
|
+
return;
|
|
23
|
+
for (const resolve of this.#idleWaiters)
|
|
24
|
+
resolve();
|
|
25
|
+
this.#idleWaiters.clear();
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
this.#active.add(lease);
|
|
29
|
+
return lease;
|
|
30
|
+
}
|
|
31
|
+
abortAll(reason) {
|
|
32
|
+
for (const execution of this.#active)
|
|
33
|
+
execution.abort(reason);
|
|
34
|
+
}
|
|
35
|
+
waitForIdle(timeoutMs) {
|
|
36
|
+
if (this.#active.size === 0)
|
|
37
|
+
return Promise.resolve();
|
|
38
|
+
return new Promise((resolve, reject) => {
|
|
39
|
+
let timer;
|
|
40
|
+
const resolveWhenIdle = () => {
|
|
41
|
+
if (timer !== undefined)
|
|
42
|
+
clearTimeout(timer);
|
|
43
|
+
resolve();
|
|
44
|
+
};
|
|
45
|
+
this.#idleWaiters.add(resolveWhenIdle);
|
|
46
|
+
if (timeoutMs === undefined)
|
|
47
|
+
return;
|
|
48
|
+
timer = setTimeout(() => {
|
|
49
|
+
this.#idleWaiters.delete(resolveWhenIdle);
|
|
50
|
+
reject(new Error(`LUTRE_APPLICATION_FORCE_SHUTDOWN_TIMEOUT: ${this.#active.size} active execution(s) did not complete within ${timeoutMs}ms.`));
|
|
51
|
+
}, timeoutMs);
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
}
|
package/dist/runtime/index.d.ts
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
|
-
export
|
|
2
|
-
export
|
|
3
|
-
export
|
|
4
|
-
export
|
|
5
|
-
export
|
|
6
|
-
export
|
|
7
|
-
export
|
|
8
|
-
export
|
|
9
|
-
export
|
|
1
|
+
export { checkRuntimeSupport, MissingRuntimeSupportError, } from './capability.js';
|
|
2
|
+
export type { RuntimeCapabilityId, RuntimeSupportCheck, RuntimeSupportProfile, } from './capability.js';
|
|
3
|
+
export { Container, DependencyResolutionError } from './di.js';
|
|
4
|
+
export type { ContainerOptions } from './di.js';
|
|
5
|
+
export { normalizeUnknownError } from './error.js';
|
|
6
|
+
export type { NormalizedApplicationError } from './error.js';
|
|
7
|
+
export { assertRuntimeEngine, detectRuntimeEngine } from './engine.js';
|
|
8
|
+
export type { RuntimeEngine } from './engine.js';
|
|
9
|
+
export { ConsoleLoggerBackend, JsonConsoleLoggerBackend, Logger, SilentLogger, } from './logger.js';
|
|
10
|
+
export type { ConsoleLoggerBackendOptions, LoggerBackend, LogLevel, LogRecord, } from './logger.js';
|
|
11
|
+
export { ApplicationKernelRuntime } from './kernel.js';
|
|
12
|
+
export type { ApplicationKernelRuntimeOptions } from './kernel.js';
|
|
13
|
+
export { nodeRuntimeSupport } from './node-capabilities.js';
|
|
14
|
+
export { canRetryOnNextPort, initialServerPort } from './server-port.js';
|
|
15
|
+
export { serverUrl } from './server-url.js';
|
package/dist/runtime/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
export
|
|
2
|
-
export
|
|
3
|
-
export
|
|
4
|
-
export
|
|
5
|
-
export
|
|
6
|
-
export
|
|
7
|
-
export
|
|
8
|
-
export
|
|
9
|
-
export
|
|
1
|
+
export { checkRuntimeSupport, MissingRuntimeSupportError, } from './capability.js';
|
|
2
|
+
export { Container, DependencyResolutionError } from './di.js';
|
|
3
|
+
export { normalizeUnknownError } from './error.js';
|
|
4
|
+
export { assertRuntimeEngine, detectRuntimeEngine } from './engine.js';
|
|
5
|
+
export { ConsoleLoggerBackend, JsonConsoleLoggerBackend, Logger, SilentLogger, } from './logger.js';
|
|
6
|
+
export { ApplicationKernelRuntime } from './kernel.js';
|
|
7
|
+
export { nodeRuntimeSupport } from './node-capabilities.js';
|
|
8
|
+
export { canRetryOnNextPort, initialServerPort } from './server-port.js';
|
|
9
|
+
export { serverUrl } from './server-url.js';
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export class IngressGate {
|
|
2
|
+
#accepting = true;
|
|
3
|
+
#pending = 0;
|
|
4
|
+
#idleWaiters = new Set();
|
|
5
|
+
get isAccepting() {
|
|
6
|
+
return this.#accepting;
|
|
7
|
+
}
|
|
8
|
+
enter() {
|
|
9
|
+
if (!this.#accepting)
|
|
10
|
+
return undefined;
|
|
11
|
+
this.#pending += 1;
|
|
12
|
+
let completed = false;
|
|
13
|
+
return () => {
|
|
14
|
+
if (completed)
|
|
15
|
+
return;
|
|
16
|
+
completed = true;
|
|
17
|
+
this.#pending -= 1;
|
|
18
|
+
if (this.#pending !== 0)
|
|
19
|
+
return;
|
|
20
|
+
for (const resolve of this.#idleWaiters)
|
|
21
|
+
resolve();
|
|
22
|
+
this.#idleWaiters.clear();
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
stopAccepting() {
|
|
26
|
+
this.#accepting = false;
|
|
27
|
+
}
|
|
28
|
+
waitForIdle() {
|
|
29
|
+
return this.#pending === 0
|
|
30
|
+
? Promise.resolve()
|
|
31
|
+
: new Promise((resolve) => this.#idleWaiters.add(resolve));
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { RuntimeCapabilityRegistry, type ApplicationModel, type ExecutionExtension, type ExecutionExtensionRuntime, type ExecutionKernelRuntime, type ExecutionLease, type RuntimeCapabilityBinding, type TokenLike } from '../core/index.js';
|
|
2
|
+
import { Container } from './di.js';
|
|
3
|
+
import { Logger } from './logger.js';
|
|
4
|
+
export interface ApplicationKernelRuntimeOptions {
|
|
5
|
+
readonly capabilities?: readonly RuntimeCapabilityBinding[];
|
|
6
|
+
readonly logger?: Logger;
|
|
7
|
+
readonly environmentSource?: unknown;
|
|
8
|
+
readonly argumentsSource?: unknown;
|
|
9
|
+
readonly forceShutdownTimeoutMs?: number;
|
|
10
|
+
}
|
|
11
|
+
export declare class ApplicationKernelRuntime implements ExecutionKernelRuntime {
|
|
12
|
+
#private;
|
|
13
|
+
readonly model: ApplicationModel;
|
|
14
|
+
readonly container: Container;
|
|
15
|
+
readonly capabilities: RuntimeCapabilityRegistry;
|
|
16
|
+
constructor(model: ApplicationModel, options?: ApplicationKernelRuntimeOptions);
|
|
17
|
+
initialize(): Promise<void>;
|
|
18
|
+
resolve<TValue>(token: TokenLike<TValue>, source?: string): TValue;
|
|
19
|
+
get<TValue>(token: TokenLike<TValue>): TValue;
|
|
20
|
+
extensionRuntime<TRuntime extends ExecutionExtensionRuntime>(extension: ExecutionExtension<any, any, any, any, TRuntime>): TRuntime;
|
|
21
|
+
beginExecution(): ExecutionLease;
|
|
22
|
+
shutdown(signal?: string): Promise<void>;
|
|
23
|
+
}
|