@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.
Files changed (168) hide show
  1. package/README.md +63 -32
  2. package/dist/adapters/aws-lambda.d.ts +5 -3
  3. package/dist/adapters/aws-lambda.js +53 -23
  4. package/dist/adapters/bun.d.ts +7 -4
  5. package/dist/adapters/bun.js +52 -42
  6. package/dist/adapters/cloudflare-workers.d.ts +5 -3
  7. package/dist/adapters/cloudflare-workers.js +23 -28
  8. package/dist/adapters/deno.d.ts +7 -4
  9. package/dist/adapters/deno.js +94 -57
  10. package/dist/adapters/electron.d.ts +13 -5
  11. package/dist/adapters/electron.js +76 -28
  12. package/dist/application/definition.d.ts +31 -0
  13. package/dist/application/definition.js +16 -0
  14. package/dist/application/index.d.ts +4 -63
  15. package/dist/application/index.js +2 -11
  16. package/dist/application/kernel-internal.d.ts +2 -0
  17. package/dist/application/kernel-internal.js +10 -0
  18. package/dist/application/kernel.d.ts +21 -0
  19. package/dist/application/kernel.js +65 -0
  20. package/dist/core/diagnostic.d.ts +9 -0
  21. package/dist/core/diagnostic.js +9 -0
  22. package/dist/core/extension.d.ts +107 -0
  23. package/dist/core/extension.js +73 -0
  24. package/dist/core/generic-layer.d.ts +26 -0
  25. package/dist/core/generic-layer.js +116 -0
  26. package/dist/core/index.d.ts +31 -15
  27. package/dist/core/index.js +15 -15
  28. package/dist/core/injection.d.ts +4 -13
  29. package/dist/core/injection.js +63 -0
  30. package/dist/core/model/context.d.ts +18 -0
  31. package/dist/core/model/context.js +34 -0
  32. package/dist/core/model/lifecycle.d.ts +5 -0
  33. package/dist/core/model/lifecycle.js +44 -0
  34. package/dist/core/model/modules.d.ts +2 -0
  35. package/dist/core/model/modules.js +101 -0
  36. package/dist/core/model/providers.d.ts +4 -0
  37. package/dist/core/model/providers.js +74 -0
  38. package/dist/core/model/snapshot.d.ts +6 -0
  39. package/dist/core/model/snapshot.js +31 -0
  40. package/dist/core/model/types.d.ts +78 -0
  41. package/dist/core/model/validation.d.ts +4 -0
  42. package/dist/core/model/validation.js +40 -0
  43. package/dist/core/model/visibility.d.ts +4 -0
  44. package/dist/core/model/visibility.js +20 -0
  45. package/dist/core/model.d.ts +10 -0
  46. package/dist/core/model.js +346 -0
  47. package/dist/core/module.d.ts +8 -13
  48. package/dist/core/source-location.d.ts +8 -0
  49. package/dist/core/source-location.js +31 -0
  50. package/dist/core/token-internal.d.ts +3 -0
  51. package/dist/core/token-internal.js +4 -0
  52. package/dist/core/type.d.ts +7 -0
  53. package/dist/core/type.js +4 -0
  54. package/dist/generated/version.d.ts +1 -1
  55. package/dist/generated/version.js +1 -1
  56. package/dist/graph/index.d.ts +2 -3
  57. package/dist/graph/index.js +1 -3
  58. package/dist/graph/model.d.ts +34 -0
  59. package/dist/graph/model.js +127 -0
  60. package/dist/http/auth.d.ts +46 -0
  61. package/dist/http/auth.js +96 -0
  62. package/dist/http/client.d.ts +28 -31
  63. package/dist/http/client.js +58 -44
  64. package/dist/http/cors-internal.d.ts +29 -0
  65. package/dist/http/cors-internal.js +160 -0
  66. package/dist/http/cors.d.ts +5 -8
  67. package/dist/http/cors.js +7 -165
  68. package/dist/http/extension.d.ts +348 -0
  69. package/dist/http/extension.js +947 -0
  70. package/dist/http/index.d.ts +9 -7
  71. package/dist/http/index.js +5 -7
  72. package/dist/{application → http}/openapi.d.ts +12 -3
  73. package/dist/{application → http}/openapi.js +164 -102
  74. package/dist/http/path.d.ts +1 -42
  75. package/dist/http/path.js +1 -2
  76. package/dist/http/runtime/request.d.ts +17 -0
  77. package/dist/http/runtime/request.js +109 -0
  78. package/dist/http/runtime/response.d.ts +18 -0
  79. package/dist/http/runtime/response.js +108 -0
  80. package/dist/index.d.ts +4 -0
  81. package/dist/index.js +2 -0
  82. package/dist/message-port/extension.d.ts +66 -0
  83. package/dist/message-port/extension.js +395 -0
  84. package/dist/message-port/index.d.ts +4 -73
  85. package/dist/message-port/index.js +2 -189
  86. package/dist/message-port/transport.d.ts +11 -0
  87. package/dist/message-port/transport.js +45 -0
  88. package/dist/runtime/async-iterator-lifecycle.d.ts +12 -0
  89. package/dist/runtime/async-iterator-lifecycle.js +95 -0
  90. package/dist/runtime/capability.d.ts +11 -11
  91. package/dist/runtime/capability.js +3 -3
  92. package/dist/runtime/di.d.ts +2 -22
  93. package/dist/runtime/di.js +8 -285
  94. package/dist/runtime/execution-tracker.d.ts +8 -0
  95. package/dist/runtime/execution-tracker.js +54 -0
  96. package/dist/runtime/index.d.ts +15 -9
  97. package/dist/runtime/index.js +9 -9
  98. package/dist/runtime/ingress-gate.d.ts +7 -0
  99. package/dist/runtime/ingress-gate.js +33 -0
  100. package/dist/runtime/kernel.d.ts +23 -0
  101. package/dist/runtime/kernel.js +354 -0
  102. package/dist/runtime/logger.d.ts +2 -0
  103. package/dist/runtime/logger.js +2 -0
  104. package/dist/runtime/node-capabilities.d.ts +1 -1
  105. package/dist/runtime/node-capabilities.js +1 -1
  106. package/dist/runtime/server-port.d.ts +2 -0
  107. package/dist/runtime/server-port.js +11 -0
  108. package/dist/tasks/extension.d.ts +144 -0
  109. package/dist/tasks/extension.js +499 -0
  110. package/dist/tasks/index.d.ts +2 -0
  111. package/dist/tasks/index.js +1 -0
  112. package/dist/tasks/runtime/cron.d.ts +6 -0
  113. package/dist/tasks/runtime/cron.js +89 -0
  114. package/dist/websocket/errors.d.ts +9 -0
  115. package/dist/websocket/errors.js +18 -0
  116. package/dist/websocket/extension.d.ts +154 -0
  117. package/dist/websocket/extension.js +524 -0
  118. package/dist/websocket/index.d.ts +3 -0
  119. package/dist/websocket/index.js +2 -0
  120. package/package.json +12 -16
  121. package/dist/application/binding.d.ts +0 -33
  122. package/dist/application/binding.js +0 -295
  123. package/dist/application/host.d.ts +0 -8
  124. package/dist/application/host.js +0 -14
  125. package/dist/application/queue.d.ts +0 -3
  126. package/dist/application/queue.js +0 -4
  127. package/dist/application/scheduler.d.ts +0 -2
  128. package/dist/application/scheduler.js +0 -45
  129. package/dist/core/context-key.d.ts +0 -16
  130. package/dist/core/context-key.js +0 -17
  131. package/dist/core/contract-internal.d.ts +0 -22
  132. package/dist/core/contract-internal.js +0 -61
  133. package/dist/core/contract.d.ts +0 -96
  134. package/dist/core/contract.js +0 -88
  135. package/dist/core/execution.d.ts +0 -78
  136. package/dist/core/execution.js +0 -61
  137. package/dist/core/implementation.d.ts +0 -44
  138. package/dist/core/implementation.js +0 -35
  139. package/dist/core/layer.d.ts +0 -137
  140. package/dist/core/layer.js +0 -81
  141. package/dist/graph/compiler.d.ts +0 -4
  142. package/dist/graph/compiler.js +0 -228
  143. package/dist/graph/graph.d.ts +0 -18
  144. package/dist/graph/graph.js +0 -1118
  145. package/dist/graph/ir.d.ts +0 -175
  146. package/dist/http/application.d.ts +0 -18
  147. package/dist/http/application.js +0 -515
  148. package/dist/http/basic-auth.d.ts +0 -37
  149. package/dist/http/basic-auth.js +0 -67
  150. package/dist/http/definitions.d.ts +0 -363
  151. package/dist/http/definitions.js +0 -310
  152. package/dist/http/hosted-protocol.d.ts +0 -4
  153. package/dist/http/hosted-protocol.js +0 -4
  154. package/dist/http/internal.d.ts +0 -8
  155. package/dist/http/internal.js +0 -1
  156. package/dist/http/params.d.ts +0 -2
  157. package/dist/http/params.js +0 -19
  158. package/dist/http/request-body.d.ts +0 -4
  159. package/dist/http/request-body.js +0 -6
  160. package/dist/http/validate.d.ts +0 -20
  161. package/dist/http/validate.js +0 -6
  162. package/dist/message-port/environment.d.ts +0 -2
  163. package/dist/message-port/environment.js +0 -4
  164. package/dist/runtime/application.d.ts +0 -38
  165. package/dist/runtime/application.js +0 -339
  166. package/dist/runtime/pipeline.d.ts +0 -11
  167. package/dist/runtime/pipeline.js +0 -161
  168. /package/dist/{graph/ir.js → core/model/types.js} +0 -0
@@ -1,4 +1,4 @@
1
- import { asModuleInstance, childPipelineOf, isArgsClass, isEnvClass, layerDefinitionOf, normalizeProvider, runInInjectionContext, tokenName, } from '../core/index.js';
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
- const cached = this.#applicationCache.get(token);
276
- if (this.#applicationCache.has(token))
277
- return cached;
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
- if (this.#probe)
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,8 @@
1
+ import type { ExecutionLease } from '../core/index.js';
2
+ export declare class ExecutionTracker {
3
+ #private;
4
+ get size(): number;
5
+ begin(): ExecutionLease;
6
+ abortAll(reason: unknown): void;
7
+ waitForIdle(timeoutMs?: number): Promise<void>;
8
+ }
@@ -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
+ }
@@ -1,9 +1,15 @@
1
- export * from './application.js';
2
- export * from './capability.js';
3
- export * from './di.js';
4
- export * from './error.js';
5
- export * from './engine.js';
6
- export * from './logger.js';
7
- export * from './pipeline.js';
8
- export * from './node-capabilities.js';
9
- export * from './server-url.js';
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';
@@ -1,9 +1,9 @@
1
- export * from './application.js';
2
- export * from './capability.js';
3
- export * from './di.js';
4
- export * from './error.js';
5
- export * from './engine.js';
6
- export * from './logger.js';
7
- export * from './pipeline.js';
8
- export * from './node-capabilities.js';
9
- export * from './server-url.js';
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,7 @@
1
+ export declare class IngressGate {
2
+ #private;
3
+ get isAccepting(): boolean;
4
+ enter(): (() => void) | undefined;
5
+ stopAccepting(): void;
6
+ waitForIdle(): Promise<void>;
7
+ }
@@ -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
+ }