@loutrejs/loutre 0.5.0 → 0.7.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 +22 -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 +118 -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 +32 -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/instrumentation.d.ts +36 -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/types.js +1 -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/devtools/capsule.d.ts +51 -0
- package/dist/devtools/capsule.js +245 -0
- package/dist/devtools/index.d.ts +11 -0
- package/dist/devtools/index.js +6 -0
- package/dist/devtools/inspector.d.ts +57 -0
- package/dist/devtools/inspector.js +1 -0
- package/dist/devtools/module.d.ts +18 -0
- package/dist/devtools/module.js +26 -0
- package/dist/devtools/observer.d.ts +77 -0
- package/dist/devtools/observer.js +10 -0
- package/dist/devtools/protocol.d.ts +1 -0
- package/dist/devtools/protocol.js +1 -0
- package/dist/devtools/provider-instrumentation.d.ts +14 -0
- package/dist/devtools/provider-instrumentation.js +117 -0
- package/dist/devtools/runtime.d.ts +20 -0
- package/dist/devtools/runtime.js +519 -0
- package/dist/devtools/values.d.ts +35 -0
- package/dist/devtools/values.js +175 -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 +1061 -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 +411 -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 +5 -21
- package/dist/runtime/di.js +22 -289
- 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 +25 -0
- package/dist/runtime/kernel.js +447 -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 +525 -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 +533 -0
- package/dist/websocket/index.d.ts +3 -0
- package/dist/websocket/index.js +2 -0
- package/package.json +16 -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/instrumentation.js} +0 -0
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { collectInjectedDependencies } from '../injection.js';
|
|
2
|
+
import { diagnostic } from '../diagnostic.js';
|
|
3
|
+
import { asModuleInstance } from '../module.js';
|
|
4
|
+
import { normalizeProvider } from '../provider.js';
|
|
5
|
+
import { tokenName } from '../token.js';
|
|
6
|
+
import { appendLifecycleNodes } from './lifecycle.js';
|
|
7
|
+
import { snapshotProvider } from './snapshot.js';
|
|
8
|
+
import { getSourceLocation } from '../source-location.js';
|
|
9
|
+
export function collectModuleDeclarations(context) {
|
|
10
|
+
const { modules, moduleIds, nodes, edges, diagnostics, providers, providerNodes, } = context;
|
|
11
|
+
const moduleNames = new Set();
|
|
12
|
+
for (const module of modules) {
|
|
13
|
+
const moduleId = moduleIds.get(module);
|
|
14
|
+
if (module.definition.name) {
|
|
15
|
+
if (moduleNames.has(module.definition.name)) {
|
|
16
|
+
diagnostics.push(diagnostic('LUTRE_MODULE_NAME_COLLISION', `Module name ${module.definition.name} is already registered.`, moduleId));
|
|
17
|
+
}
|
|
18
|
+
moduleNames.add(module.definition.name);
|
|
19
|
+
}
|
|
20
|
+
const moduleSource = getSourceLocation(module.template);
|
|
21
|
+
nodes.push({
|
|
22
|
+
kind: 'module',
|
|
23
|
+
id: moduleId,
|
|
24
|
+
...(moduleSource === undefined ? {} : { source: moduleSource }),
|
|
25
|
+
...(module.definition.name === undefined
|
|
26
|
+
? {}
|
|
27
|
+
: { name: module.definition.name }),
|
|
28
|
+
...(module.definition.description === undefined
|
|
29
|
+
? {}
|
|
30
|
+
: { description: module.definition.description }),
|
|
31
|
+
});
|
|
32
|
+
for (const imported of module.definition.imports ?? []) {
|
|
33
|
+
const target = moduleIds.get(asModuleInstance(imported));
|
|
34
|
+
if (target)
|
|
35
|
+
edges.push({ from: moduleId, to: target, kind: 'imports' });
|
|
36
|
+
}
|
|
37
|
+
for (const declaration of module.definition.providers ?? []) {
|
|
38
|
+
const normalized = normalizeProvider(declaration);
|
|
39
|
+
const provider = snapshotProvider(normalized);
|
|
40
|
+
const providerSource = normalized.kind === 'class'
|
|
41
|
+
? getSourceLocation(normalized.useClass)
|
|
42
|
+
: getSourceLocation(declaration);
|
|
43
|
+
const providerId = context.nextProviderId();
|
|
44
|
+
const existingProvider = providerNodes.get(provider.provide);
|
|
45
|
+
if (existingProvider?.provider.kind === 'environment' &&
|
|
46
|
+
provider.kind === 'environment') {
|
|
47
|
+
edges.push({ from: moduleId, to: existingProvider.id, kind: 'owns' });
|
|
48
|
+
if (module.definition.exports?.includes(provider.provide)) {
|
|
49
|
+
edges.push({
|
|
50
|
+
from: moduleId,
|
|
51
|
+
to: existingProvider.id,
|
|
52
|
+
kind: 'exports',
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
if (existingProvider) {
|
|
58
|
+
diagnostics.push(diagnostic('LUTRE_PROVIDER_DUPLICATE', `Provider ${tokenName(provider.provide)} is declared more than once.`, providerId));
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
const node = {
|
|
62
|
+
kind: 'provider',
|
|
63
|
+
id: providerId,
|
|
64
|
+
token: provider.provide,
|
|
65
|
+
provider,
|
|
66
|
+
moduleId,
|
|
67
|
+
dependencies: collectProviderDependencies(provider),
|
|
68
|
+
...(providerSource === undefined ? {} : { source: providerSource }),
|
|
69
|
+
};
|
|
70
|
+
providers.push(provider);
|
|
71
|
+
providerNodes.set(provider.provide, node);
|
|
72
|
+
nodes.push(node);
|
|
73
|
+
edges.push({ from: moduleId, to: providerId, kind: 'owns' });
|
|
74
|
+
if (module.definition.exports?.includes(provider.provide)) {
|
|
75
|
+
edges.push({ from: moduleId, to: providerId, kind: 'exports' });
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
appendLifecycleNodes(module, moduleId, nodes, edges);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
function collectProviderDependencies(provider) {
|
|
82
|
+
switch (provider.kind) {
|
|
83
|
+
case 'class':
|
|
84
|
+
return Object.freeze(collectInjectedDependencies(provider.provide, () => Reflect.construct(provider.useClass, [])));
|
|
85
|
+
case 'factory':
|
|
86
|
+
return Object.freeze([...provider.inject]);
|
|
87
|
+
case 'conditional': {
|
|
88
|
+
const dependencies = new Set();
|
|
89
|
+
for (const implementation of Object.values(provider.mapping)) {
|
|
90
|
+
for (const dependency of collectInjectedDependencies(provider.provide, () => Reflect.construct(implementation, []))) {
|
|
91
|
+
dependencies.add(dependency);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return Object.freeze([...dependencies]);
|
|
95
|
+
}
|
|
96
|
+
case 'value':
|
|
97
|
+
case 'environment':
|
|
98
|
+
case 'arguments':
|
|
99
|
+
return Object.freeze([]);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ModelBuildContext } from './context.js';
|
|
2
|
+
export declare function resolveModuleExports(context: ModelBuildContext): void;
|
|
3
|
+
export declare function compileArgumentsProvider(context: ModelBuildContext): void;
|
|
4
|
+
export declare function resolveProviderDependencies(context: ModelBuildContext): void;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { diagnostic } from '../diagnostic.js';
|
|
2
|
+
import { argumentsProvider } from '../provider.js';
|
|
3
|
+
import { isFrameworkProvidedToken } from '../token-internal.js';
|
|
4
|
+
import { tokenName } from '../token.js';
|
|
5
|
+
import { snapshotProvider } from './snapshot.js';
|
|
6
|
+
import { isTokenVisible, moduleDeclaresToken } from './visibility.js';
|
|
7
|
+
export function resolveModuleExports(context) {
|
|
8
|
+
const { modules, moduleIds, providerNodes, edges, diagnostics } = context;
|
|
9
|
+
for (const module of modules) {
|
|
10
|
+
const moduleId = moduleIds.get(module);
|
|
11
|
+
for (const exported of module.definition.exports ?? []) {
|
|
12
|
+
if (moduleDeclaresToken(module, exported))
|
|
13
|
+
continue;
|
|
14
|
+
const provider = providerNodes.get(exported);
|
|
15
|
+
const providerModule = provider
|
|
16
|
+
? modules.find((candidate) => moduleIds.get(candidate) === provider.moduleId)
|
|
17
|
+
: undefined;
|
|
18
|
+
if (provider &&
|
|
19
|
+
providerModule &&
|
|
20
|
+
isTokenVisible(module, providerModule, exported)) {
|
|
21
|
+
edges.push({ from: moduleId, to: provider.id, kind: 'exports' });
|
|
22
|
+
continue;
|
|
23
|
+
}
|
|
24
|
+
diagnostics.push(diagnostic('LUTRE_MODULE_EXPORT_UNRESOLVED', `Module export ${tokenName(exported)} is neither declared by the Module nor re-exported from an imported Module.`, `${moduleId}.exports.${tokenName(exported)}`));
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
export function compileArgumentsProvider(context) {
|
|
29
|
+
const { options, providerNodes, diagnostics, providers, nodes } = context;
|
|
30
|
+
if (!options.arguments)
|
|
31
|
+
return;
|
|
32
|
+
const existingProvider = providerNodes.get(options.arguments);
|
|
33
|
+
if (existingProvider) {
|
|
34
|
+
diagnostics.push(diagnostic('LUTRE_ARGS_001', `Arguments ${tokenName(options.arguments)} is runtime-managed and cannot also be declared as a normal provider.`, existingProvider.id));
|
|
35
|
+
}
|
|
36
|
+
const provider = snapshotProvider(argumentsProvider(options.arguments));
|
|
37
|
+
const node = {
|
|
38
|
+
kind: 'provider',
|
|
39
|
+
id: context.nextProviderId(),
|
|
40
|
+
token: options.arguments,
|
|
41
|
+
provider,
|
|
42
|
+
moduleId: 'application',
|
|
43
|
+
dependencies: Object.freeze([]),
|
|
44
|
+
};
|
|
45
|
+
providers.push(provider);
|
|
46
|
+
providerNodes.set(options.arguments, node);
|
|
47
|
+
nodes.push(node);
|
|
48
|
+
}
|
|
49
|
+
export function resolveProviderDependencies(context) {
|
|
50
|
+
const { providerNodes, modules, moduleIds, edges, diagnostics } = context;
|
|
51
|
+
for (const provider of providerNodes.values()) {
|
|
52
|
+
if (provider.moduleId === 'application')
|
|
53
|
+
continue;
|
|
54
|
+
const sourceModule = modules.find((candidate) => moduleIds.get(candidate) === provider.moduleId);
|
|
55
|
+
if (!sourceModule)
|
|
56
|
+
continue;
|
|
57
|
+
for (const dependency of provider.dependencies) {
|
|
58
|
+
const target = providerNodes.get(dependency);
|
|
59
|
+
if (target) {
|
|
60
|
+
edges.push({ from: provider.id, to: target.id, kind: 'injects' });
|
|
61
|
+
const targetModule = modules.find((candidate) => moduleIds.get(candidate) === target.moduleId);
|
|
62
|
+
if (targetModule &&
|
|
63
|
+
target.moduleId !== provider.moduleId &&
|
|
64
|
+
!moduleDeclaresToken(sourceModule, dependency) &&
|
|
65
|
+
!isTokenVisible(sourceModule, targetModule, dependency)) {
|
|
66
|
+
diagnostics.push(diagnostic('LUTRE_MODULE_VISIBILITY', `Provider ${tokenName(provider.token)} depends on private ${tokenName(dependency)} from another Module.`, provider.id));
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
else if (!isFrameworkProvidedToken(dependency)) {
|
|
70
|
+
diagnostics.push(diagnostic('LUTRE_PROVIDER_DEPENDENCY_MISSING', `Provider ${tokenName(provider.token)} requires ${tokenName(dependency)}, but no provider is declared.`, provider.id));
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { ExecutionExtension } from '../extension.js';
|
|
2
|
+
import type { LifecycleHook } from '../lifecycle.js';
|
|
3
|
+
import type { ProviderDescriptor } from '../provider.js';
|
|
4
|
+
export declare function snapshotProvider(provider: ProviderDescriptor): ProviderDescriptor;
|
|
5
|
+
export declare function snapshotLifecycleHook(hook: LifecycleHook<any>): LifecycleHook<any>;
|
|
6
|
+
export declare function snapshotExecutionExtension(extension: ExecutionExtension): ExecutionExtension;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export function snapshotProvider(provider) {
|
|
2
|
+
if (provider.kind === 'conditional') {
|
|
3
|
+
return Object.freeze({
|
|
4
|
+
...provider,
|
|
5
|
+
select: Object.freeze({ ...provider.select }),
|
|
6
|
+
mapping: Object.freeze({ ...provider.mapping }),
|
|
7
|
+
});
|
|
8
|
+
}
|
|
9
|
+
if (provider.kind === 'factory') {
|
|
10
|
+
return Object.freeze({
|
|
11
|
+
...provider,
|
|
12
|
+
inject: Object.freeze([...provider.inject]),
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
return Object.freeze({ ...provider });
|
|
16
|
+
}
|
|
17
|
+
export function snapshotLifecycleHook(hook) {
|
|
18
|
+
return Object.freeze({
|
|
19
|
+
kind: 'lifecycle-hook',
|
|
20
|
+
inject: Object.freeze([...hook.inject]),
|
|
21
|
+
run: hook.run,
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
export function snapshotExecutionExtension(extension) {
|
|
25
|
+
return Object.freeze({
|
|
26
|
+
...extension,
|
|
27
|
+
...(extension.host === undefined
|
|
28
|
+
? {}
|
|
29
|
+
: { host: Object.freeze({ ...extension.host }) }),
|
|
30
|
+
});
|
|
31
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import type { ArgsClass } from '../args.js';
|
|
2
|
+
import type { AnyExecutionExtension, ExecutionExtension, RuntimeCapability } from '../extension.js';
|
|
3
|
+
import type { LifecycleHook } from '../lifecycle.js';
|
|
4
|
+
import type { ModuleInstance, ModuleTemplate } from '../module.js';
|
|
5
|
+
import type { ProviderDescriptor } from '../provider.js';
|
|
6
|
+
import type { Diagnostic } from '../diagnostic.js';
|
|
7
|
+
import type { TokenLike } from '../token.js';
|
|
8
|
+
import type { SourceLocation } from '../source-location.js';
|
|
9
|
+
export interface ModuleModelNode {
|
|
10
|
+
readonly kind: 'module';
|
|
11
|
+
readonly id: string;
|
|
12
|
+
readonly name?: string;
|
|
13
|
+
readonly description?: string;
|
|
14
|
+
readonly source?: SourceLocation;
|
|
15
|
+
}
|
|
16
|
+
export interface ProviderModelNode {
|
|
17
|
+
readonly kind: 'provider';
|
|
18
|
+
readonly id: string;
|
|
19
|
+
readonly token: TokenLike;
|
|
20
|
+
readonly provider: ProviderDescriptor;
|
|
21
|
+
readonly moduleId: string;
|
|
22
|
+
readonly dependencies: readonly TokenLike[];
|
|
23
|
+
readonly source?: SourceLocation;
|
|
24
|
+
}
|
|
25
|
+
export interface ExecutionModelNode<TCompiled = unknown> {
|
|
26
|
+
readonly kind: 'execution';
|
|
27
|
+
readonly id: string;
|
|
28
|
+
readonly executionKind: string;
|
|
29
|
+
readonly moduleId: string;
|
|
30
|
+
readonly dependencies: readonly TokenLike[];
|
|
31
|
+
readonly capabilities: readonly RuntimeCapability[];
|
|
32
|
+
readonly compiled: TCompiled;
|
|
33
|
+
readonly source?: SourceLocation;
|
|
34
|
+
}
|
|
35
|
+
export interface LifecycleModelNode {
|
|
36
|
+
readonly kind: 'lifecycle';
|
|
37
|
+
readonly id: string;
|
|
38
|
+
readonly moduleId: string;
|
|
39
|
+
readonly phase: string;
|
|
40
|
+
readonly hook: LifecycleHook<any>;
|
|
41
|
+
readonly source?: SourceLocation;
|
|
42
|
+
}
|
|
43
|
+
export interface FrameworkModelNode {
|
|
44
|
+
readonly kind: 'framework';
|
|
45
|
+
readonly id: string;
|
|
46
|
+
readonly frameworkKind: 'runtime-capability' | 'execution-extension';
|
|
47
|
+
readonly name: string;
|
|
48
|
+
readonly source?: SourceLocation;
|
|
49
|
+
}
|
|
50
|
+
export type ApplicationModelNode = ModuleModelNode | ProviderModelNode | ExecutionModelNode | LifecycleModelNode | FrameworkModelNode;
|
|
51
|
+
export interface ApplicationModelEdge {
|
|
52
|
+
readonly from: string;
|
|
53
|
+
readonly to: string;
|
|
54
|
+
readonly kind: 'owns' | 'imports' | 'exports' | 'injects' | 'references' | 'requires' | 'starts' | 'wraps';
|
|
55
|
+
}
|
|
56
|
+
export type CompiledOf<TExtension extends AnyExecutionExtension> = TExtension extends ExecutionExtension<any, infer TCompiled, any, any, any> ? TCompiled : never;
|
|
57
|
+
export interface ApplicationModelExtension<TExtension extends AnyExecutionExtension = AnyExecutionExtension> {
|
|
58
|
+
readonly extension: TExtension;
|
|
59
|
+
readonly executions: readonly ExecutionModelNode<CompiledOf<TExtension>>[];
|
|
60
|
+
}
|
|
61
|
+
export interface ApplicationModelExtensions extends Iterable<ApplicationModelExtension> {
|
|
62
|
+
get<TExtension extends AnyExecutionExtension>(extension: TExtension): ApplicationModelExtension<TExtension> | undefined;
|
|
63
|
+
values(): readonly ApplicationModelExtension[];
|
|
64
|
+
}
|
|
65
|
+
export interface ApplicationModel {
|
|
66
|
+
readonly kind: 'application-model';
|
|
67
|
+
readonly arguments?: ArgsClass;
|
|
68
|
+
readonly providers: readonly ProviderDescriptor[];
|
|
69
|
+
readonly nodes: readonly ApplicationModelNode[];
|
|
70
|
+
readonly edges: readonly ApplicationModelEdge[];
|
|
71
|
+
readonly executions: readonly ExecutionModelNode[];
|
|
72
|
+
readonly extensions: ApplicationModelExtensions;
|
|
73
|
+
readonly diagnostics: readonly Diagnostic[];
|
|
74
|
+
}
|
|
75
|
+
export interface ApplicationModelBuildOptions {
|
|
76
|
+
readonly modules: readonly (ModuleInstance | ModuleTemplate<void>)[];
|
|
77
|
+
readonly arguments?: ArgsClass;
|
|
78
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { type Diagnostic } from '../diagnostic.js';
|
|
2
|
+
import type { ApplicationModelExtension, ApplicationModelNode } from './types.js';
|
|
3
|
+
export declare function validateHostNamespaces(extensions: readonly ApplicationModelExtension[], diagnostics: Diagnostic[]): void;
|
|
4
|
+
export declare function validateNodeIds(nodes: readonly ApplicationModelNode[], diagnostics: Diagnostic[]): void;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { diagnostic } from '../diagnostic.js';
|
|
2
|
+
export function validateHostNamespaces(extensions, diagnostics) {
|
|
3
|
+
const reserved = new Set([
|
|
4
|
+
'graph',
|
|
5
|
+
'init',
|
|
6
|
+
'get',
|
|
7
|
+
'close',
|
|
8
|
+
'serve',
|
|
9
|
+
'then',
|
|
10
|
+
'__proto__',
|
|
11
|
+
'prototype',
|
|
12
|
+
'constructor',
|
|
13
|
+
]);
|
|
14
|
+
const owners = new Map();
|
|
15
|
+
for (const { extension } of extensions) {
|
|
16
|
+
const namespace = extension.host?.namespace;
|
|
17
|
+
if (!namespace)
|
|
18
|
+
continue;
|
|
19
|
+
if (reserved.has(namespace)) {
|
|
20
|
+
diagnostics.push(diagnostic('LUTRE_HOST_NAMESPACE_RESERVED', `Host namespace ${namespace} is reserved by the Application or runtime adapter API.`, `host.${namespace}`));
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
const owner = owners.get(namespace);
|
|
24
|
+
if (owner && owner.identity !== extension.identity) {
|
|
25
|
+
diagnostics.push(diagnostic('LUTRE_HOST_NAMESPACE_COLLISION', `Host namespace ${namespace} is contributed by both ${owner.name} and ${extension.name}.`, `host.${namespace}`));
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
owners.set(namespace, extension);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
export function validateNodeIds(nodes, diagnostics) {
|
|
32
|
+
const seen = new Set();
|
|
33
|
+
for (const node of nodes) {
|
|
34
|
+
if (!seen.has(node.id)) {
|
|
35
|
+
seen.add(node.id);
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
diagnostics.push(diagnostic('LUTRE_APPLICATION_NODE_ID_COLLISION', `Application Model node id ${node.id} is not globally unique.`, node.id));
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { type ModuleInstance } from '../module.js';
|
|
2
|
+
import type { TokenLike } from '../token.js';
|
|
3
|
+
export declare function moduleDeclaresToken(module: ModuleInstance, token: TokenLike): boolean;
|
|
4
|
+
export declare function isTokenVisible(source: ModuleInstance, target: ModuleInstance, token: TokenLike, visited?: Set<ModuleInstance<import("../module.js").ModuleDefinition>>): boolean;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { asModuleInstance } from '../module.js';
|
|
2
|
+
import { normalizeProvider } from '../provider.js';
|
|
3
|
+
export function moduleDeclaresToken(module, token) {
|
|
4
|
+
return (module.definition.providers ?? []).some((declaration) => normalizeProvider(declaration).provide === token);
|
|
5
|
+
}
|
|
6
|
+
export function isTokenVisible(source, target, token, visited = new Set()) {
|
|
7
|
+
if (visited.has(source))
|
|
8
|
+
return false;
|
|
9
|
+
visited.add(source);
|
|
10
|
+
for (const importedValue of source.definition.imports ?? []) {
|
|
11
|
+
const imported = asModuleInstance(importedValue);
|
|
12
|
+
if (!imported.definition.exports?.includes(token))
|
|
13
|
+
continue;
|
|
14
|
+
if (imported === target)
|
|
15
|
+
return true;
|
|
16
|
+
if (isTokenVisible(imported, target, token, new Set(visited)))
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type Diagnostic } from './diagnostic.js';
|
|
2
|
+
import type { ApplicationModel, ApplicationModelBuildOptions } from './model/types.js';
|
|
3
|
+
export type { ApplicationModel, ApplicationModelBuildOptions, ApplicationModelEdge, ApplicationModelExtension, ApplicationModelExtensions, ApplicationModelNode, CompiledOf, ExecutionModelNode, FrameworkModelNode, LifecycleModelNode, ModuleModelNode, ProviderModelNode, } from './model/types.js';
|
|
4
|
+
export declare class ApplicationModelError extends Error {
|
|
5
|
+
readonly diagnostics: readonly Diagnostic[];
|
|
6
|
+
readonly code = "LUTRE_APPLICATION_MODEL_INVALID";
|
|
7
|
+
constructor(diagnostics: readonly Diagnostic[]);
|
|
8
|
+
}
|
|
9
|
+
export declare function assertValidApplicationModel(model: ApplicationModel): ApplicationModel;
|
|
10
|
+
export declare function buildApplicationModel(options: ApplicationModelBuildOptions): ApplicationModel;
|