@telorun/kernel 0.36.0 → 0.38.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/src/kernel.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import {
2
2
  AnalysisRegistry,
3
+ defaultSources,
3
4
  flattenForAnalyzer,
4
5
  flattenLoadedModule,
5
6
  isModuleKind,
@@ -150,7 +151,7 @@ export class Kernel implements IKernel {
150
151
  this.env = options.env ?? process.env;
151
152
  this.argv = options.argv ?? [];
152
153
  this.registryUrl = options.registryUrl;
153
- this.loader = new Loader({ registryUrl: this.registryUrl, celHandlers: nodeCelHandlers });
154
+ this.loader = new Loader(defaultSources(this.registryUrl), { celHandlers: nodeCelHandlers });
154
155
  for (const source of options.sources) {
155
156
  this.loader.register(source);
156
157
  }
@@ -239,7 +240,21 @@ export class Kernel implements IKernel {
239
240
  * custom `ManifestSource`s — `isImportValidatedAtLoad` etc. only hit
240
241
  * when both sides agree on the canonical URL. */
241
242
  resolveImportUrl(fromSource: string, importSource: string): string {
242
- return this.loader.resolveImportUrl(fromSource, importSource);
243
+ const resolved = this.loader.resolveImportUrl(fromSource, importSource);
244
+ // Apply version-reconciliation overrides captured during `load()`: when the
245
+ // entry graph hoisted this module identity to a higher version, redirect the
246
+ // import-controller's independent re-resolution onto the winning source so a
247
+ // sub-library importing a lower version loads the same controller/definition
248
+ // the analyzer registered — never a second, colliding copy. Keyed by
249
+ // canonical URL; `canonicalize` maps a registry ref (returned verbatim by
250
+ // the loader) to the URL the graph walk already resolved it to.
251
+ const overrides = this._loadedGraph?.overrides;
252
+ if (overrides && overrides.size > 0) {
253
+ const canonical = this.loader.canonicalize(resolved) ?? resolved;
254
+ const winner = overrides.get(canonical);
255
+ if (winner) return winner;
256
+ }
257
+ return resolved;
243
258
  }
244
259
 
245
260
  /**
@@ -348,6 +363,21 @@ export class Kernel implements IKernel {
348
363
  throw analysisGraph.errors[0].error;
349
364
  }
350
365
  this._loadedGraph = analysisGraph;
366
+ // Version reconciliation: an incompatible major mismatch is fatal (the
367
+ // hoist override would silently run the wrong major); a same-major hoist is
368
+ // advisory — the override already redirects every importer to the winner.
369
+ const versionConflicts = analysisGraph.versionDiagnostics.filter(
370
+ (d) => d.code === "MODULE_VERSION_CONFLICT",
371
+ );
372
+ if (versionConflicts.length > 0) {
373
+ throw new RuntimeError(
374
+ "ERR_MANIFEST_VALIDATION_FAILED",
375
+ versionConflicts.map((d) => d.message).join("\n"),
376
+ );
377
+ }
378
+ for (const d of analysisGraph.versionDiagnostics) {
379
+ if (d.code === "MODULE_VERSION_HOISTED") console.warn(`warning: ${d.message}`);
380
+ }
351
381
  const staticManifests = flattenForAnalyzer(analysisGraph);
352
382
  this.staticManifests = staticManifests;
353
383
 
@@ -865,6 +895,7 @@ export class Kernel implements IKernel {
865
895
  moduleContext: IModuleContext,
866
896
  resource: ResourceManifest,
867
897
  args?: ParsedArgs,
898
+ ownerPrefix = "",
868
899
  ): ResourceContext {
869
900
  return new ResourceContextImpl(
870
901
  this,
@@ -876,6 +907,7 @@ export class Kernel implements IKernel {
876
907
  this.stdout,
877
908
  this.stderr,
878
909
  args,
910
+ ownerPrefix,
879
911
  );
880
912
  }
881
913
 
@@ -1013,7 +1045,12 @@ export class Kernel implements IKernel {
1013
1045
 
1014
1046
  const parsedArgs = this.parseArgsForController(controller);
1015
1047
  const moduleCtx = this.findModuleContext(evalContext);
1016
- const ctx = this.createResourceContext(moduleCtx, processedResource, parsedArgs);
1048
+ const ctx = this.createResourceContext(
1049
+ moduleCtx,
1050
+ processedResource,
1051
+ parsedArgs,
1052
+ evalContext.ownerPrefix,
1053
+ );
1017
1054
  const instance = await controller.create(processedResource, ctx);
1018
1055
  if (!instance) return null;
1019
1056
 
@@ -38,6 +38,10 @@ export class ResourceContextImpl implements ResourceContext {
38
38
  readonly stdout: NodeJS.WritableStream;
39
39
  readonly stderr: NodeJS.WritableStream;
40
40
  readonly args: ParsedArgs;
41
+ /** Id prefix of the context this resource was created in. A controller that
42
+ * spawns sub-resources composes their ids as `ownerPrefix + kind + "." + name`
43
+ * and stamps the owner on the child context it registers them into. */
44
+ readonly ownerPrefix: string;
41
45
 
42
46
  constructor(
43
47
  readonly kernel: Kernel,
@@ -49,12 +53,14 @@ export class ResourceContextImpl implements ResourceContext {
49
53
  stdout?: NodeJS.WritableStream,
50
54
  stderr?: NodeJS.WritableStream,
51
55
  args?: ParsedArgs,
56
+ ownerPrefix = "",
52
57
  ) {
53
58
  this.env = env ?? process.env;
54
59
  this.stdin = stdin ?? process.stdin;
55
60
  this.stdout = stdout ?? process.stdout;
56
61
  this.stderr = stderr ?? process.stderr;
57
62
  this.args = args ?? { _: [] };
63
+ this.ownerPrefix = ownerPrefix;
58
64
  }
59
65
 
60
66
  createSchemaValidator(schema: any) {