@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.
Files changed (188) 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 +22 -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 +118 -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 +32 -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/instrumentation.d.ts +36 -0
  31. package/dist/core/model/context.d.ts +18 -0
  32. package/dist/core/model/context.js +34 -0
  33. package/dist/core/model/lifecycle.d.ts +5 -0
  34. package/dist/core/model/lifecycle.js +44 -0
  35. package/dist/core/model/modules.d.ts +2 -0
  36. package/dist/core/model/modules.js +101 -0
  37. package/dist/core/model/providers.d.ts +4 -0
  38. package/dist/core/model/providers.js +74 -0
  39. package/dist/core/model/snapshot.d.ts +6 -0
  40. package/dist/core/model/snapshot.js +31 -0
  41. package/dist/core/model/types.d.ts +78 -0
  42. package/dist/core/model/types.js +1 -0
  43. package/dist/core/model/validation.d.ts +4 -0
  44. package/dist/core/model/validation.js +40 -0
  45. package/dist/core/model/visibility.d.ts +4 -0
  46. package/dist/core/model/visibility.js +20 -0
  47. package/dist/core/model.d.ts +10 -0
  48. package/dist/core/model.js +346 -0
  49. package/dist/core/module.d.ts +8 -13
  50. package/dist/core/source-location.d.ts +8 -0
  51. package/dist/core/source-location.js +31 -0
  52. package/dist/core/token-internal.d.ts +3 -0
  53. package/dist/core/token-internal.js +4 -0
  54. package/dist/core/type.d.ts +7 -0
  55. package/dist/core/type.js +4 -0
  56. package/dist/devtools/capsule.d.ts +51 -0
  57. package/dist/devtools/capsule.js +245 -0
  58. package/dist/devtools/index.d.ts +11 -0
  59. package/dist/devtools/index.js +6 -0
  60. package/dist/devtools/inspector.d.ts +57 -0
  61. package/dist/devtools/inspector.js +1 -0
  62. package/dist/devtools/module.d.ts +18 -0
  63. package/dist/devtools/module.js +26 -0
  64. package/dist/devtools/observer.d.ts +77 -0
  65. package/dist/devtools/observer.js +10 -0
  66. package/dist/devtools/protocol.d.ts +1 -0
  67. package/dist/devtools/protocol.js +1 -0
  68. package/dist/devtools/provider-instrumentation.d.ts +14 -0
  69. package/dist/devtools/provider-instrumentation.js +117 -0
  70. package/dist/devtools/runtime.d.ts +20 -0
  71. package/dist/devtools/runtime.js +519 -0
  72. package/dist/devtools/values.d.ts +35 -0
  73. package/dist/devtools/values.js +175 -0
  74. package/dist/generated/version.d.ts +1 -1
  75. package/dist/generated/version.js +1 -1
  76. package/dist/graph/index.d.ts +2 -3
  77. package/dist/graph/index.js +1 -3
  78. package/dist/graph/model.d.ts +34 -0
  79. package/dist/graph/model.js +127 -0
  80. package/dist/http/auth.d.ts +46 -0
  81. package/dist/http/auth.js +96 -0
  82. package/dist/http/client.d.ts +28 -31
  83. package/dist/http/client.js +58 -44
  84. package/dist/http/cors-internal.d.ts +29 -0
  85. package/dist/http/cors-internal.js +160 -0
  86. package/dist/http/cors.d.ts +5 -8
  87. package/dist/http/cors.js +7 -165
  88. package/dist/http/extension.d.ts +348 -0
  89. package/dist/http/extension.js +1061 -0
  90. package/dist/http/index.d.ts +9 -7
  91. package/dist/http/index.js +5 -7
  92. package/dist/{application → http}/openapi.d.ts +12 -3
  93. package/dist/{application → http}/openapi.js +164 -102
  94. package/dist/http/path.d.ts +1 -42
  95. package/dist/http/path.js +1 -2
  96. package/dist/http/runtime/request.d.ts +17 -0
  97. package/dist/http/runtime/request.js +109 -0
  98. package/dist/http/runtime/response.d.ts +18 -0
  99. package/dist/http/runtime/response.js +108 -0
  100. package/dist/index.d.ts +4 -0
  101. package/dist/index.js +2 -0
  102. package/dist/message-port/extension.d.ts +66 -0
  103. package/dist/message-port/extension.js +411 -0
  104. package/dist/message-port/index.d.ts +4 -73
  105. package/dist/message-port/index.js +2 -189
  106. package/dist/message-port/transport.d.ts +11 -0
  107. package/dist/message-port/transport.js +45 -0
  108. package/dist/runtime/async-iterator-lifecycle.d.ts +12 -0
  109. package/dist/runtime/async-iterator-lifecycle.js +95 -0
  110. package/dist/runtime/capability.d.ts +11 -11
  111. package/dist/runtime/capability.js +3 -3
  112. package/dist/runtime/di.d.ts +5 -21
  113. package/dist/runtime/di.js +22 -289
  114. package/dist/runtime/execution-tracker.d.ts +8 -0
  115. package/dist/runtime/execution-tracker.js +54 -0
  116. package/dist/runtime/index.d.ts +15 -9
  117. package/dist/runtime/index.js +9 -9
  118. package/dist/runtime/ingress-gate.d.ts +7 -0
  119. package/dist/runtime/ingress-gate.js +33 -0
  120. package/dist/runtime/kernel.d.ts +25 -0
  121. package/dist/runtime/kernel.js +447 -0
  122. package/dist/runtime/logger.d.ts +2 -0
  123. package/dist/runtime/logger.js +2 -0
  124. package/dist/runtime/node-capabilities.d.ts +1 -1
  125. package/dist/runtime/node-capabilities.js +1 -1
  126. package/dist/runtime/server-port.d.ts +2 -0
  127. package/dist/runtime/server-port.js +11 -0
  128. package/dist/tasks/extension.d.ts +144 -0
  129. package/dist/tasks/extension.js +525 -0
  130. package/dist/tasks/index.d.ts +2 -0
  131. package/dist/tasks/index.js +1 -0
  132. package/dist/tasks/runtime/cron.d.ts +6 -0
  133. package/dist/tasks/runtime/cron.js +89 -0
  134. package/dist/websocket/errors.d.ts +9 -0
  135. package/dist/websocket/errors.js +18 -0
  136. package/dist/websocket/extension.d.ts +154 -0
  137. package/dist/websocket/extension.js +533 -0
  138. package/dist/websocket/index.d.ts +3 -0
  139. package/dist/websocket/index.js +2 -0
  140. package/package.json +16 -16
  141. package/dist/application/binding.d.ts +0 -33
  142. package/dist/application/binding.js +0 -295
  143. package/dist/application/host.d.ts +0 -8
  144. package/dist/application/host.js +0 -14
  145. package/dist/application/queue.d.ts +0 -3
  146. package/dist/application/queue.js +0 -4
  147. package/dist/application/scheduler.d.ts +0 -2
  148. package/dist/application/scheduler.js +0 -45
  149. package/dist/core/context-key.d.ts +0 -16
  150. package/dist/core/context-key.js +0 -17
  151. package/dist/core/contract-internal.d.ts +0 -22
  152. package/dist/core/contract-internal.js +0 -61
  153. package/dist/core/contract.d.ts +0 -96
  154. package/dist/core/contract.js +0 -88
  155. package/dist/core/execution.d.ts +0 -78
  156. package/dist/core/execution.js +0 -61
  157. package/dist/core/implementation.d.ts +0 -44
  158. package/dist/core/implementation.js +0 -35
  159. package/dist/core/layer.d.ts +0 -137
  160. package/dist/core/layer.js +0 -81
  161. package/dist/graph/compiler.d.ts +0 -4
  162. package/dist/graph/compiler.js +0 -228
  163. package/dist/graph/graph.d.ts +0 -18
  164. package/dist/graph/graph.js +0 -1118
  165. package/dist/graph/ir.d.ts +0 -175
  166. package/dist/http/application.d.ts +0 -18
  167. package/dist/http/application.js +0 -515
  168. package/dist/http/basic-auth.d.ts +0 -37
  169. package/dist/http/basic-auth.js +0 -67
  170. package/dist/http/definitions.d.ts +0 -363
  171. package/dist/http/definitions.js +0 -310
  172. package/dist/http/hosted-protocol.d.ts +0 -4
  173. package/dist/http/hosted-protocol.js +0 -4
  174. package/dist/http/internal.d.ts +0 -8
  175. package/dist/http/internal.js +0 -1
  176. package/dist/http/params.d.ts +0 -2
  177. package/dist/http/params.js +0 -19
  178. package/dist/http/request-body.d.ts +0 -4
  179. package/dist/http/request-body.js +0 -6
  180. package/dist/http/validate.d.ts +0 -20
  181. package/dist/http/validate.js +0 -6
  182. package/dist/message-port/environment.d.ts +0 -2
  183. package/dist/message-port/environment.js +0 -4
  184. package/dist/runtime/application.d.ts +0 -38
  185. package/dist/runtime/application.js +0 -339
  186. package/dist/runtime/pipeline.d.ts +0 -11
  187. package/dist/runtime/pipeline.js +0 -161
  188. /package/dist/{graph/ir.js → core/instrumentation.js} +0 -0
@@ -0,0 +1,346 @@
1
+ import { diagnostic, isErrorDiagnostic } from './diagnostic.js';
2
+ import { isExecutionDefinition, } from './extension.js';
3
+ import { isFrameworkProvidedToken } from './token-internal.js';
4
+ import { tokenName } from './token.js';
5
+ import { createModelBuildContext } from './model/context.js';
6
+ import { resolveLifecycleDependencies } from './model/lifecycle.js';
7
+ import { collectModuleDeclarations } from './model/modules.js';
8
+ import { compileArgumentsProvider, resolveModuleExports, resolveProviderDependencies, } from './model/providers.js';
9
+ import { snapshotExecutionExtension } from './model/snapshot.js';
10
+ import { validateHostNamespaces, validateNodeIds } from './model/validation.js';
11
+ import { getSourceLocation } from './source-location.js';
12
+ import { isTokenVisible, moduleDeclaresToken } from './model/visibility.js';
13
+ class ApplicationModelExtensionRegistry {
14
+ #ordered;
15
+ #groups;
16
+ constructor(groups) {
17
+ this.#ordered = Object.freeze([...groups]);
18
+ this.#groups = new Map(groups.map((group) => [group.extension.identity, group]));
19
+ }
20
+ get(extension) {
21
+ return this.#groups.get(extension.identity);
22
+ }
23
+ values() {
24
+ return this.#ordered;
25
+ }
26
+ [Symbol.iterator]() {
27
+ return this.#ordered[Symbol.iterator]();
28
+ }
29
+ }
30
+ export class ApplicationModelError extends Error {
31
+ diagnostics;
32
+ code = 'LUTRE_APPLICATION_MODEL_INVALID';
33
+ constructor(diagnostics) {
34
+ super(`Application Model is invalid:\n${diagnostics
35
+ .map((item) => `${item.code} at ${item.path}: ${item.message}`)
36
+ .join('\n')}`);
37
+ this.diagnostics = diagnostics;
38
+ this.name = 'ApplicationModelError';
39
+ }
40
+ }
41
+ export function assertValidApplicationModel(model) {
42
+ const errors = model.diagnostics.filter(isErrorDiagnostic);
43
+ if (errors.length > 0)
44
+ throw new ApplicationModelError(errors);
45
+ return model;
46
+ }
47
+ export function buildApplicationModel(options) {
48
+ const context = createModelBuildContext(options);
49
+ collectModuleDeclarations(context);
50
+ resolveModuleExports(context);
51
+ compileArgumentsProvider(context);
52
+ resolveProviderDependencies(context);
53
+ resolveLifecycleDependencies(context);
54
+ const { modules, moduleIds, nodes, edges, diagnostics, providers, executions, providerNodes, } = context;
55
+ const extensionExecutions = new Map();
56
+ const extensionNames = new Map();
57
+ const extensionIdentities = new Map();
58
+ const executionIds = new Set();
59
+ const capabilityNodeIds = new Set();
60
+ const visitedDefinitions = new Set();
61
+ const compiledDefinitions = new Map();
62
+ const executionReferences = [];
63
+ const executionReferenceResults = new Map();
64
+ const getExecutionReferences = (definition) => {
65
+ const cached = executionReferenceResults.get(definition);
66
+ if (cached)
67
+ return cached;
68
+ const references = definition.extension.references;
69
+ if (!references) {
70
+ const result = { references: Object.freeze([]) };
71
+ executionReferenceResults.set(definition, result);
72
+ return result;
73
+ }
74
+ try {
75
+ const result = {
76
+ references: references(definition),
77
+ };
78
+ executionReferenceResults.set(definition, result);
79
+ return result;
80
+ }
81
+ catch (error) {
82
+ const result = { error };
83
+ executionReferenceResults.set(definition, result);
84
+ return result;
85
+ }
86
+ };
87
+ const rootDefinitionOwners = new Map();
88
+ for (const module of modules) {
89
+ for (const value of module.definition.executions ?? []) {
90
+ if (!isExecutionDefinition(value))
91
+ continue;
92
+ const owners = rootDefinitionOwners.get(value) ?? new Set();
93
+ owners.add(module);
94
+ rootDefinitionOwners.set(value, owners);
95
+ }
96
+ }
97
+ const reachableDefinitionModules = new Map();
98
+ for (const module of modules) {
99
+ const queue = (module.definition.executions ?? []).filter(isExecutionDefinition);
100
+ const seen = new Set();
101
+ let queueIndex = 0;
102
+ while (queueIndex < queue.length) {
103
+ const value = queue[queueIndex++];
104
+ if (seen.has(value))
105
+ continue;
106
+ seen.add(value);
107
+ const explicitOwners = rootDefinitionOwners.get(value);
108
+ if (explicitOwners && !explicitOwners.has(module))
109
+ continue;
110
+ const reachableModules = reachableDefinitionModules.get(value) ?? new Set();
111
+ reachableModules.add(module);
112
+ reachableDefinitionModules.set(value, reachableModules);
113
+ const referenceResult = getExecutionReferences(value);
114
+ if ('error' in referenceResult)
115
+ continue;
116
+ for (const reference of referenceResult.references) {
117
+ if (!isExecutionDefinition(reference))
118
+ continue;
119
+ if (reference.extension.identity !== value.extension.identity)
120
+ continue;
121
+ queue.push(reference);
122
+ }
123
+ }
124
+ }
125
+ const definitionOwners = new Map();
126
+ const ambiguousDefinitions = new Set();
127
+ for (const [definition, explicitOwners] of rootDefinitionOwners) {
128
+ if (explicitOwners.size === 1) {
129
+ definitionOwners.set(definition, [...explicitOwners][0]);
130
+ }
131
+ else {
132
+ ambiguousDefinitions.add(definition);
133
+ }
134
+ }
135
+ for (const [definition, reachableModules] of reachableDefinitionModules) {
136
+ if (rootDefinitionOwners.has(definition))
137
+ continue;
138
+ if (reachableModules.size === 1) {
139
+ definitionOwners.set(definition, [...reachableModules][0]);
140
+ }
141
+ else {
142
+ ambiguousDefinitions.add(definition);
143
+ }
144
+ }
145
+ if (ambiguousDefinitions.size > 0) {
146
+ diagnostics.push(diagnostic('LUTRE_EXECUTION_OWNER_AMBIGUOUS', 'Execution Definition ownership is ambiguous across multiple Modules. Register each shared Definition in exactly one Module.executions; other Modules may reference it.', 'application.executions'));
147
+ }
148
+ for (const module of modules) {
149
+ const moduleId = moduleIds.get(module);
150
+ const rootDefinitions = module.definition.executions ?? [];
151
+ const rootDefinitionIndexes = new Map();
152
+ for (const [definitionIndex, value] of rootDefinitions.entries()) {
153
+ if (isExecutionDefinition(value) && !rootDefinitionIndexes.has(value)) {
154
+ rootDefinitionIndexes.set(value, definitionIndex);
155
+ }
156
+ }
157
+ const discoveredDefinitionIndexes = new Map();
158
+ const queue = rootDefinitions.map((value, definitionIndex) => ({
159
+ value,
160
+ definitionIndex,
161
+ path: `${moduleId}.executions.${definitionIndex}`,
162
+ }));
163
+ let nextDiscoveredDefinitionIndex = rootDefinitions.length;
164
+ let queueIndex = 0;
165
+ while (queueIndex < queue.length) {
166
+ const { value, definitionIndex, path } = queue[queueIndex++];
167
+ if (!isExecutionDefinition(value)) {
168
+ diagnostics.push(diagnostic('LUTRE_EXECUTION_DEFINITION_INVALID', 'Module executions and referenced executions accept only branded Execution Definitions.', path));
169
+ continue;
170
+ }
171
+ if (ambiguousDefinitions.has(value))
172
+ continue;
173
+ if (definitionOwners.get(value) !== module)
174
+ continue;
175
+ if (visitedDefinitions.has(value))
176
+ continue;
177
+ visitedDefinitions.add(value);
178
+ const extension = value.extension;
179
+ const namedIdentity = extensionNames.get(extension.name);
180
+ if (namedIdentity && namedIdentity.identity !== extension.identity) {
181
+ diagnostics.push(diagnostic('LUTRE_EXTENSION_ABI_MISMATCH', `Extension ${extension.name} mixes incompatible ABI versions ${namedIdentity.abiVersion} and ${extension.abiVersion}.`, path));
182
+ continue;
183
+ }
184
+ const identityOwner = extensionIdentities.get(extension.identity);
185
+ if (identityOwner && identityOwner.name !== extension.name) {
186
+ diagnostics.push(diagnostic('LUTRE_EXTENSION_IDENTITY_COLLISION', `Extension identity is shared by ${identityOwner.name} and ${extension.name}.`, path));
187
+ continue;
188
+ }
189
+ const canonicalExtension = identityOwner?.extension ?? snapshotExecutionExtension(extension);
190
+ extensionNames.set(extension.name, {
191
+ identity: extension.identity,
192
+ abiVersion: extension.abiVersion,
193
+ });
194
+ extensionIdentities.set(extension.identity, {
195
+ name: extension.name,
196
+ extension: canonicalExtension,
197
+ });
198
+ let contribution;
199
+ try {
200
+ contribution = extension.compile(value, {
201
+ moduleId,
202
+ definitionIndex,
203
+ });
204
+ }
205
+ catch (error) {
206
+ diagnostics.push(diagnostic('LUTRE_EXTENSION_COMPILE', describeError(error), path));
207
+ continue;
208
+ }
209
+ if (executionIds.has(contribution.id)) {
210
+ diagnostics.push(diagnostic('LUTRE_EXECUTION_ID_COLLISION', `Execution id ${contribution.id} is already registered.`, path));
211
+ continue;
212
+ }
213
+ executionIds.add(contribution.id);
214
+ const executionSource = getSourceLocation(value);
215
+ const execution = Object.freeze({
216
+ ...contribution,
217
+ dependencies: Object.freeze([...contribution.dependencies]),
218
+ capabilities: Object.freeze([...contribution.capabilities]),
219
+ moduleId,
220
+ ...(executionSource === undefined ? {} : { source: executionSource }),
221
+ });
222
+ compiledDefinitions.set(value, execution);
223
+ executions.push(execution);
224
+ nodes.push(execution);
225
+ edges.push({ from: moduleId, to: execution.id, kind: 'owns' });
226
+ const grouped = extensionExecutions.get(extension.identity) ?? {
227
+ extension: canonicalExtension,
228
+ executions: [],
229
+ };
230
+ grouped.executions.push(execution);
231
+ extensionExecutions.set(extension.identity, grouped);
232
+ for (const dependency of execution.dependencies) {
233
+ const provider = providerNodes.get(dependency);
234
+ if (provider) {
235
+ edges.push({ from: execution.id, to: provider.id, kind: 'injects' });
236
+ const providerModule = modules.find((candidate) => moduleIds.get(candidate) === provider.moduleId);
237
+ if (providerModule &&
238
+ provider.moduleId !== moduleId &&
239
+ !moduleDeclaresToken(module, dependency) &&
240
+ !isTokenVisible(module, providerModule, dependency)) {
241
+ diagnostics.push(diagnostic('LUTRE_MODULE_VISIBILITY', `Execution ${execution.id} depends on private ${tokenName(dependency)} from another Module.`, execution.id));
242
+ }
243
+ }
244
+ else if (!isFrameworkProvidedToken(dependency)) {
245
+ diagnostics.push(diagnostic('LUTRE_EXECUTION_DEPENDENCY_MISSING', `Execution ${execution.id} requires ${tokenName(dependency)}, but no provider is declared.`, execution.id));
246
+ }
247
+ }
248
+ for (const capability of execution.capabilities) {
249
+ const capabilityId = `capability:${capability.id}`;
250
+ if (!capabilityNodeIds.has(capabilityId)) {
251
+ capabilityNodeIds.add(capabilityId);
252
+ nodes.push({
253
+ kind: 'framework',
254
+ id: capabilityId,
255
+ frameworkKind: 'runtime-capability',
256
+ name: capability.id,
257
+ });
258
+ }
259
+ edges.push({
260
+ from: execution.id,
261
+ to: capabilityId,
262
+ kind: 'requires',
263
+ });
264
+ }
265
+ const referenceResult = getExecutionReferences(value);
266
+ if ('error' in referenceResult) {
267
+ diagnostics.push(diagnostic('LUTRE_EXTENSION_REFERENCES', describeError(referenceResult.error), path));
268
+ continue;
269
+ }
270
+ for (const [referenceIndex, reference,] of referenceResult.references.entries()) {
271
+ const referencePath = `${path}.references.${referenceIndex}`;
272
+ if (!isExecutionDefinition(reference)) {
273
+ diagnostics.push(diagnostic('LUTRE_EXECUTION_REFERENCE_INVALID', 'Execution references accept only branded Execution Definitions.', referencePath));
274
+ continue;
275
+ }
276
+ if (reference.extension.identity !== extension.identity) {
277
+ diagnostics.push(diagnostic('LUTRE_EXECUTION_REFERENCE_EXTENSION', `Execution ${execution.id} cannot reference an execution owned by ${reference.extension.name}.`, referencePath));
278
+ continue;
279
+ }
280
+ executionReferences.push({ from: value, to: reference });
281
+ let referencedDefinitionIndex = rootDefinitionIndexes.get(reference);
282
+ if (referencedDefinitionIndex === undefined) {
283
+ referencedDefinitionIndex = discoveredDefinitionIndexes.get(reference);
284
+ if (referencedDefinitionIndex === undefined) {
285
+ referencedDefinitionIndex = nextDiscoveredDefinitionIndex++;
286
+ discoveredDefinitionIndexes.set(reference, referencedDefinitionIndex);
287
+ }
288
+ }
289
+ queue.push({
290
+ value: reference,
291
+ definitionIndex: referencedDefinitionIndex,
292
+ path: referencePath,
293
+ });
294
+ }
295
+ }
296
+ }
297
+ for (const reference of executionReferences) {
298
+ const from = compiledDefinitions.get(reference.from);
299
+ const to = compiledDefinitions.get(reference.to);
300
+ if (!from || !to)
301
+ continue;
302
+ edges.push({ from: from.id, to: to.id, kind: 'references' });
303
+ }
304
+ const extensionGroups = [...extensionExecutions.values()].map(({ extension, executions: ownedExecutions }) => {
305
+ const extensionId = `extension:${extension.name}`;
306
+ nodes.push({
307
+ kind: 'framework',
308
+ id: extensionId,
309
+ frameworkKind: 'execution-extension',
310
+ name: extension.name,
311
+ });
312
+ for (const execution of ownedExecutions) {
313
+ edges.push({ from: extensionId, to: execution.id, kind: 'starts' });
314
+ }
315
+ if (extension.validate) {
316
+ try {
317
+ diagnostics.push(...extension.validate({ executions: ownedExecutions }));
318
+ }
319
+ catch (error) {
320
+ diagnostics.push(diagnostic('LUTRE_EXTENSION_VALIDATE', describeError(error), extensionId));
321
+ }
322
+ }
323
+ return Object.freeze({
324
+ extension,
325
+ executions: Object.freeze([...ownedExecutions]),
326
+ });
327
+ });
328
+ const extensions = new ApplicationModelExtensionRegistry(extensionGroups);
329
+ validateHostNamespaces(extensionGroups, diagnostics);
330
+ validateNodeIds(nodes, diagnostics);
331
+ return Object.freeze({
332
+ kind: 'application-model',
333
+ ...(options.arguments === undefined
334
+ ? {}
335
+ : { arguments: options.arguments }),
336
+ providers: Object.freeze(providers),
337
+ nodes: Object.freeze(nodes.map((node) => Object.freeze(node))),
338
+ edges: Object.freeze(edges.map((edge) => Object.freeze(edge))),
339
+ executions: Object.freeze(executions),
340
+ extensions,
341
+ diagnostics: Object.freeze(diagnostics.map((item) => Object.freeze({ ...item }))),
342
+ });
343
+ }
344
+ function describeError(error) {
345
+ return error instanceof Error ? error.message : String(error);
346
+ }
@@ -1,5 +1,5 @@
1
1
  import type { EnvClass } from './env.js';
2
- import type { ImplementationDescriptor } from './implementation.js';
2
+ import type { ExecutionDefinition, ExtensionOfDefinition, HostApiOfExtension } from './extension.js';
3
3
  import type { ModuleLifecycle } from './lifecycle.js';
4
4
  import { type ProviderDeclaration } from './provider.js';
5
5
  export interface ModuleDefinition {
@@ -8,24 +8,19 @@ export interface ModuleDefinition {
8
8
  readonly imports?: readonly ModuleInstance[];
9
9
  readonly environment?: readonly EnvClass[];
10
10
  readonly providers?: readonly ProviderDeclaration[];
11
- readonly implementations?: readonly ImplementationDescriptor[];
11
+ readonly executions?: readonly ExecutionDefinition[];
12
12
  readonly exports?: readonly unknown[];
13
13
  readonly lifecycle?: ModuleLifecycle;
14
- readonly requires?: readonly string[];
15
14
  }
16
15
  export declare const moduleTypeInfo: unique symbol;
17
16
  export interface ModuleTypeInfo<TDefinition extends ModuleDefinition = ModuleDefinition> {
18
- readonly protocols: ProtocolsOfModuleDefinition<TDefinition>;
19
- readonly capabilities: CapabilitiesOfModuleDefinition<TDefinition>;
17
+ readonly extensions: ExtensionsOfModuleDefinition<TDefinition>;
20
18
  }
21
- type DirectProtocols<TDefinition extends ModuleDefinition> = TDefinition['implementations'] extends readonly ImplementationDescriptor[] ? TDefinition['implementations'][number]['protocol'] : never;
22
- type ImportedProtocols<TDefinition extends ModuleDefinition> = TDefinition['imports'] extends readonly ModuleInstance[] ? ModuleProtocols<TDefinition['imports'][number]> : never;
23
- export type ProtocolsOfModuleDefinition<TDefinition extends ModuleDefinition> = DirectProtocols<TDefinition> | ImportedProtocols<TDefinition>;
24
- type DirectCapabilities<TDefinition extends ModuleDefinition> = TDefinition['implementations'] extends readonly ImplementationDescriptor[] ? TDefinition['implementations'][number]['capabilities'][number] : never;
25
- type ImportedCapabilities<TDefinition extends ModuleDefinition> = TDefinition['imports'] extends readonly ModuleInstance[] ? ModuleCapabilities<TDefinition['imports'][number]> : never;
26
- export type CapabilitiesOfModuleDefinition<TDefinition extends ModuleDefinition> = DirectCapabilities<TDefinition> | ImportedCapabilities<TDefinition>;
27
- export type ModuleProtocols<TModule> = TModule extends ModuleInstance<infer TDefinition> ? ProtocolsOfModuleDefinition<TDefinition> : never;
28
- export type ModuleCapabilities<TModule> = TModule extends ModuleInstance<infer TDefinition> ? CapabilitiesOfModuleDefinition<TDefinition> : never;
19
+ type DirectExtensions<TDefinition extends ModuleDefinition> = TDefinition['executions'] extends readonly ExecutionDefinition[] ? ExtensionOfDefinition<TDefinition['executions'][number]> : never;
20
+ type ImportedExtensions<TDefinition extends ModuleDefinition> = TDefinition['imports'] extends readonly ModuleInstance[] ? ModuleExtensions<TDefinition['imports'][number]> : never;
21
+ export type ExtensionsOfModuleDefinition<TDefinition extends ModuleDefinition> = DirectExtensions<TDefinition> | ImportedExtensions<TDefinition>;
22
+ export type ModuleExtensions<TModule> = TModule extends ModuleInstance<infer TDefinition> ? ExtensionsOfModuleDefinition<TDefinition> : never;
23
+ export type ModuleHostApis<TModule> = HostApiOfExtension<ModuleExtensions<TModule>>;
29
24
  export interface ModuleInstance<TDefinition extends ModuleDefinition = ModuleDefinition> {
30
25
  readonly kind: 'module-instance';
31
26
  readonly template: AnyModuleTemplate;
@@ -0,0 +1,8 @@
1
+ export interface SourceLocation {
2
+ readonly file: string;
3
+ readonly line?: number;
4
+ readonly column?: number;
5
+ }
6
+ export declare function registerSourceLocation<T>(value: T, source: SourceLocation): T;
7
+ export declare function getSourceLocation(value: unknown): SourceLocation | undefined;
8
+ export declare function inheritSourceLocation<T>(target: T, source: unknown): T;
@@ -0,0 +1,31 @@
1
+ const sourceMetadata = new WeakMap();
2
+ function asObject(value) {
3
+ return (typeof value === 'object' && value !== null) ||
4
+ typeof value === 'function'
5
+ ? value
6
+ : undefined;
7
+ }
8
+ function snapshotSourceLocation(source) {
9
+ return Object.freeze({
10
+ file: source.file,
11
+ ...(source.line === undefined ? {} : { line: source.line }),
12
+ ...(source.column === undefined ? {} : { column: source.column }),
13
+ });
14
+ }
15
+ export function registerSourceLocation(value, source) {
16
+ const target = asObject(value);
17
+ if (!target || sourceMetadata.has(target))
18
+ return value;
19
+ sourceMetadata.set(target, snapshotSourceLocation(source));
20
+ return value;
21
+ }
22
+ export function getSourceLocation(value) {
23
+ const target = asObject(value);
24
+ return target ? sourceMetadata.get(target) : undefined;
25
+ }
26
+ export function inheritSourceLocation(target, source) {
27
+ const location = getSourceLocation(source);
28
+ return location === undefined
29
+ ? target
30
+ : registerSourceLocation(target, location);
31
+ }
@@ -0,0 +1,3 @@
1
+ import type { TokenLike } from './token.js';
2
+ export declare const frameworkProvidedTokenBrand: unique symbol;
3
+ export declare function isFrameworkProvidedToken(token: TokenLike): boolean;
@@ -0,0 +1,4 @@
1
+ export const frameworkProvidedTokenBrand = Symbol.for('loutre.framework-provided-token');
2
+ export function isFrameworkProvidedToken(token) {
3
+ return (token[frameworkProvidedTokenBrand] === true);
4
+ }
@@ -0,0 +1,7 @@
1
+ declare const typeValue: unique symbol;
2
+ export interface Type<T> {
3
+ readonly [typeValue]: T;
4
+ }
5
+ export type TypeOf<TType> = TType extends Type<infer TValue> ? TValue : never;
6
+ export declare function type<T>(): Type<T>;
7
+ export {};
@@ -0,0 +1,4 @@
1
+ const typeCarrier = Object.freeze({});
2
+ export function type() {
3
+ return typeCarrier;
4
+ }
@@ -0,0 +1,51 @@
1
+ import type { RuntimeExecutionMetadata } from '../core/instrumentation.js';
2
+ import type { DevtoolsModuleOptions } from './module.js';
3
+ import type { ReplayCapsuleRequest, ReplayExecutionContext, RuntimeInvocationResult } from './inspector.js';
4
+ import { type DevtoolsValuePreview } from './values.js';
5
+ export interface ReplayRegistration {
6
+ readonly input: unknown;
7
+ replay(input: unknown, context: ReplayExecutionContext): unknown | Promise<unknown>;
8
+ }
9
+ export type CapturedValue = {
10
+ readonly mode: 'snapshot';
11
+ readonly value: unknown;
12
+ } | {
13
+ readonly mode: 'reference';
14
+ readonly handleId: string;
15
+ } | {
16
+ readonly mode: 'unavailable';
17
+ readonly reason: string;
18
+ };
19
+ export interface ExecutionReplayCapsulePreview {
20
+ readonly id: string;
21
+ readonly kind: 'execution';
22
+ readonly runId: string;
23
+ readonly traceId: string;
24
+ readonly spanId: string;
25
+ readonly createdAt: number;
26
+ readonly expiresAt: number;
27
+ readonly execution: {
28
+ readonly executionId: string;
29
+ readonly executionKind: string;
30
+ readonly graphNodeId?: string;
31
+ readonly name: string;
32
+ };
33
+ readonly input: DevtoolsValuePreview;
34
+ readonly fidelity: 'snapshot' | 'reference' | 'unavailable';
35
+ readonly replayModes: readonly ['direct'];
36
+ }
37
+ export interface ReplayCapsuleStoreOptions {
38
+ readonly ttlMs?: number;
39
+ readonly maxCapsules?: number;
40
+ readonly capture?: DevtoolsModuleOptions['capture'];
41
+ readonly redact?: readonly string[];
42
+ }
43
+ export declare class ReplayCapsuleStore {
44
+ #private;
45
+ constructor(runId: string, options?: ReplayCapsuleStoreOptions);
46
+ createExecution(traceId: string, spanId: string, observation: RuntimeExecutionMetadata, registration: ReplayRegistration): ExecutionReplayCapsulePreview;
47
+ preview(capsuleId: string): ExecutionReplayCapsulePreview | undefined;
48
+ replay(request: ReplayCapsuleRequest): Promise<RuntimeInvocationResult>;
49
+ discard(capsuleId: string): void;
50
+ clear(): void;
51
+ }