@telorun/kernel 0.12.0 → 0.13.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/LICENSE +2 -2
- package/dist/application-env.d.ts +24 -0
- package/dist/application-env.d.ts.map +1 -0
- package/dist/application-env.js +156 -0
- package/dist/application-env.js.map +1 -0
- package/dist/base-definition.d.ts +14 -0
- package/dist/base-definition.d.ts.map +1 -0
- package/dist/base-definition.js +17 -0
- package/dist/base-definition.js.map +1 -0
- package/dist/capabilities/capabilities/component.yaml +4 -0
- package/dist/capabilities/capabilities/executable.yaml +8 -0
- package/dist/capabilities/capabilities/handler.yaml +4 -0
- package/dist/capabilities/capabilities/listener.yaml +4 -0
- package/dist/capabilities/capabilities/provider.yaml +4 -0
- package/dist/capabilities/capabilities/template.yaml +4 -0
- package/dist/capabilities/capabilities/type.yaml +4 -0
- package/dist/capabilities/component.d.ts +3 -0
- package/dist/capabilities/component.d.ts.map +1 -0
- package/dist/capabilities/component.js +4 -0
- package/dist/capabilities/component.js.map +1 -0
- package/dist/capabilities/component.yaml +3 -0
- package/dist/capabilities/executable.d.ts +3 -0
- package/dist/capabilities/executable.d.ts.map +1 -0
- package/dist/capabilities/executable.js +5 -0
- package/dist/capabilities/executable.js.map +1 -0
- package/dist/capabilities/executable.yaml +7 -0
- package/dist/capabilities/handler.d.ts +3 -0
- package/dist/capabilities/handler.d.ts.map +1 -0
- package/dist/capabilities/handler.js +4 -0
- package/dist/capabilities/handler.js.map +1 -0
- package/dist/capabilities/handler.yaml +3 -0
- package/dist/capabilities/invokable.d.ts +3 -0
- package/dist/capabilities/invokable.d.ts.map +1 -0
- package/dist/capabilities/invokable.js +5 -0
- package/dist/capabilities/invokable.js.map +1 -0
- package/dist/capabilities/listener.d.ts +3 -0
- package/dist/capabilities/listener.d.ts.map +1 -0
- package/dist/capabilities/listener.js +5 -0
- package/dist/capabilities/listener.js.map +1 -0
- package/dist/capabilities/listener.yaml +3 -0
- package/dist/capabilities/mount.d.ts +3 -0
- package/dist/capabilities/mount.d.ts.map +1 -0
- package/dist/capabilities/mount.js +5 -0
- package/dist/capabilities/mount.js.map +1 -0
- package/dist/capabilities/provider.d.ts +3 -0
- package/dist/capabilities/provider.d.ts.map +1 -0
- package/dist/capabilities/provider.js +8 -0
- package/dist/capabilities/provider.js.map +1 -0
- package/dist/capabilities/provider.yaml +3 -0
- package/dist/capabilities/runnable.d.ts +3 -0
- package/dist/capabilities/runnable.d.ts.map +1 -0
- package/dist/capabilities/runnable.js +5 -0
- package/dist/capabilities/runnable.js.map +1 -0
- package/dist/capabilities/service.d.ts +3 -0
- package/dist/capabilities/service.d.ts.map +1 -0
- package/dist/capabilities/service.js +5 -0
- package/dist/capabilities/service.js.map +1 -0
- package/dist/capabilities/template.d.ts +3 -0
- package/dist/capabilities/template.d.ts.map +1 -0
- package/dist/capabilities/template.js +5 -0
- package/dist/capabilities/template.js.map +1 -0
- package/dist/capabilities/template.yaml +3 -0
- package/dist/capabilities/type.d.ts +3 -0
- package/dist/capabilities/type.d.ts.map +1 -0
- package/dist/capabilities/type.js +5 -0
- package/dist/capabilities/type.js.map +1 -0
- package/dist/capabilities/type.yaml +3 -0
- package/dist/controller-loaders/npm-loader.d.ts +32 -8
- package/dist/controller-loaders/npm-loader.d.ts.map +1 -1
- package/dist/controller-loaders/npm-loader.js +74 -101
- package/dist/controller-loaders/npm-loader.js.map +1 -1
- package/dist/controllers/capability/capability-controller.d.ts +32 -0
- package/dist/controllers/capability/capability-controller.d.ts.map +1 -0
- package/dist/controllers/capability/capability-controller.js +26 -0
- package/dist/controllers/capability/capability-controller.js.map +1 -0
- package/dist/controllers/module/import-controller.d.ts +3 -2
- package/dist/controllers/module/import-controller.d.ts.map +1 -1
- package/dist/controllers/module/import-controller.js +23 -25
- package/dist/controllers/module/import-controller.js.map +1 -1
- package/dist/controllers/module/module.json +48 -0
- package/dist/controllers/resource-definition/resource-definition-controller.d.ts +1 -0
- package/dist/controllers/resource-definition/resource-definition-controller.d.ts.map +1 -1
- package/dist/controllers/resource-definition/resource-definition-controller.js +3 -0
- package/dist/controllers/resource-definition/resource-definition-controller.js.map +1 -1
- package/dist/controllers/resource-definition/resource-template-controller.d.ts +5 -0
- package/dist/controllers/resource-definition/resource-template-controller.d.ts.map +1 -1
- package/dist/controllers/resource-definition/resource-template-controller.js +67 -6
- package/dist/controllers/resource-definition/resource-template-controller.js.map +1 -1
- package/dist/internal-context.d.ts +25 -0
- package/dist/internal-context.d.ts.map +1 -0
- package/dist/internal-context.js +2 -0
- package/dist/internal-context.js.map +1 -0
- package/dist/kernel.d.ts +21 -1
- package/dist/kernel.d.ts.map +1 -1
- package/dist/kernel.js +109 -5
- package/dist/kernel.js.map +1 -1
- package/dist/loader.d.ts +18 -0
- package/dist/loader.d.ts.map +1 -0
- package/dist/loader.js +127 -0
- package/dist/loader.js.map +1 -0
- package/dist/manifest-adapters/http-adapter.d.ts +8 -0
- package/dist/manifest-adapters/http-adapter.d.ts.map +1 -0
- package/dist/manifest-adapters/http-adapter.js +31 -0
- package/dist/manifest-adapters/http-adapter.js.map +1 -0
- package/dist/manifest-adapters/local-file-adapter.d.ts +15 -0
- package/dist/manifest-adapters/local-file-adapter.d.ts.map +1 -0
- package/dist/manifest-adapters/local-file-adapter.js +95 -0
- package/dist/manifest-adapters/local-file-adapter.js.map +1 -0
- package/dist/manifest-adapters/manifest-adapter.d.ts +35 -0
- package/dist/manifest-adapters/manifest-adapter.d.ts.map +1 -0
- package/dist/manifest-adapters/manifest-adapter.js +2 -0
- package/dist/manifest-adapters/manifest-adapter.js.map +1 -0
- package/dist/manifest-adapters/registry-adapter.d.ts +9 -0
- package/dist/manifest-adapters/registry-adapter.d.ts.map +1 -0
- package/dist/manifest-adapters/registry-adapter.js +48 -0
- package/dist/manifest-adapters/registry-adapter.js.map +1 -0
- package/dist/manifest-schemas.d.ts +7 -23
- package/dist/manifest-schemas.d.ts.map +1 -1
- package/dist/manifest-schemas.js +18 -8
- package/dist/manifest-schemas.js.map +1 -1
- package/dist/manifest-sources/analysis-stamp.d.ts +25 -0
- package/dist/manifest-sources/analysis-stamp.d.ts.map +1 -0
- package/dist/manifest-sources/analysis-stamp.js +151 -0
- package/dist/manifest-sources/analysis-stamp.js.map +1 -0
- package/dist/module-context-registry.d.ts +48 -0
- package/dist/module-context-registry.d.ts.map +1 -0
- package/dist/module-context-registry.js +91 -0
- package/dist/module-context-registry.js.map +1 -0
- package/dist/resource-context.d.ts +2 -0
- package/dist/resource-context.d.ts.map +1 -1
- package/dist/resource-context.js +28 -0
- package/dist/resource-context.js.map +1 -1
- package/dist/schema-valiator.d.ts +15 -0
- package/dist/schema-valiator.d.ts.map +1 -0
- package/dist/schema-valiator.js +127 -0
- package/dist/schema-valiator.js.map +1 -0
- package/dist/schema-validator.d.ts +28 -0
- package/dist/schema-validator.d.ts.map +1 -1
- package/dist/schema-validator.js +161 -1
- package/dist/schema-validator.js.map +1 -1
- package/dist/snapshot-serializer.d.ts +62 -0
- package/dist/snapshot-serializer.d.ts.map +1 -0
- package/dist/snapshot-serializer.js +164 -0
- package/dist/snapshot-serializer.js.map +1 -0
- package/dist/types.d.ts +65 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +8 -0
- package/dist/types.js.map +1 -0
- package/package.json +9 -6
- package/src/application-env.ts +216 -0
- package/src/controller-loaders/npm-loader.ts +78 -103
- package/src/controllers/module/import-controller.ts +33 -36
- package/src/controllers/resource-definition/resource-definition-controller.ts +6 -0
- package/src/controllers/resource-definition/resource-template-controller.ts +95 -7
- package/src/internal-context.ts +25 -0
- package/src/kernel.ts +130 -5
- package/src/manifest-schemas.ts +31 -11
- package/src/manifest-sources/analysis-stamp.ts +169 -0
- package/src/resource-context.ts +34 -0
- package/src/schema-validator.ts +178 -2
- package/dist/generated/runtime-deps.json +0 -6
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snapshot-serializer.js","sourceRoot":"","sources":["../src/snapshot-serializer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,KAAK,IAAI,MAAM,SAAS,CAAC;AAChC,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAa7B;;;;GAIG;AACH,MAAM,OAAO,kBAAkB;IAC7B;;;;;;OAMG;IACH,KAAK,CAAC,YAAY,CAChB,SAAoD,EACpD,iBAA0F,EAC1F,QAAiB;QAEjB,MAAM,QAAQ,GAAiB;YAC7B,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,SAAS,EAAE,EAAE;SACd,CAAC;QAEF,oEAAoE;QACpE,qFAAqF;QACrF,MAAM,gBAAgB,GAAG,IAAI,CAAC,sBAAsB,CAAC,SAAS,CAAC,CAAC;QAEhE,0CAA0C;QAC1C,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;YAC9E,MAAM,gBAAgB,GAAG,gBAAgB,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;YAE3D,KAAK,MAAM,QAAQ,IAAI,gBAAgB,EAAE,CAAC;gBACxC,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC,QAAQ,EAAE,iBAAiB,CAAC,CAAC;gBAChF,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YACzC,CAAC;QACH,CAAC;QAED,iCAAiC;QACjC,IAAI,QAAQ,EAAE,CAAC;YACb,MAAM,IAAI,CAAC,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QACrD,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,iBAAiB,CAC7B,QAAyB,EACzB,iBAA0F;QAQ1F,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAE,GAAG,QAAQ,CAAC;QAC7C,MAAM,EAAE,IAAI,EAAE,GAAG,QAAQ,CAAC;QAE1B,MAAM,aAAa,GAAQ;YACzB,IAAI;YACJ,IAAI;YACJ,QAAQ,EAAE,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC;YAC1C,IAAI,EAAE,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC;SAC/B,CAAC;QAEF,qEAAqE;QACrE,IAAI,iBAAiB,EAAE,CAAC;YACtB,MAAM,GAAG,GAAG,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YAC5C,MAAM,YAAY,GAAG,iBAAiB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAEhD,IAAI,YAAY,IAAI,YAAY,CAAC,QAAQ,EAAE,CAAC;gBAC1C,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,mBAAmB,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;gBAC3E,IAAI,YAAY,EAAE,CAAC;oBACjB,aAAa,CAAC,QAAQ,GAAG,YAAY,CAAC;gBACxC,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,aAAa,CAAC;IACvB,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,mBAAmB,CAC/B,QAA0B;QAE1B,MAAM,WAAW,GAAG,QAAe,CAAC;QAEpC,kCAAkC;QAClC,IAAI,OAAO,WAAW,CAAC,QAAQ,KAAK,UAAU,EAAE,CAAC;YAC/C,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,QAAQ,CAAC,QAAe,CAAC,CAAC,CAAC;gBAC5E,OAAO,MAAM,CAAC;YAChB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,KAAK,CAAC,gDAAgD,EAAE,KAAK,CAAC,CAAC;gBACvE,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;OAEG;IACK,iBAAiB,CAAC,QAA6B;QACrD,MAAM,UAAU,GAAwB,EAAE,CAAC;QAE3C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;YACpD,IAAI,OAAO,KAAK,KAAK,UAAU,EAAE,CAAC;gBAChC,SAAS;YACX,CAAC;YACD,IAAI,CAAC;gBACH,UAAU,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;YACtD,CAAC;YAAC,MAAM,CAAC;gBACP,+BAA+B;YACjC,CAAC;QACH,CAAC;QAED,OAAO,UAAU,CAAC;IACpB,CAAC;IAED;;OAEG;IACK,aAAa,CAAC,IAAyB;QAC7C,MAAM,UAAU,GAAwB,EAAE,CAAC;QAE3C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YAChD,IAAI,OAAO,KAAK,KAAK,UAAU,EAAE,CAAC;gBAChC,SAAS;YACX,CAAC;YACD,IAAI,CAAC;gBACH,UAAU,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;YACtD,CAAC;YAAC,MAAM,CAAC;gBACP,+BAA+B;YACjC,CAAC;QACH,CAAC;QAED,OAAO,UAAU,CAAC;IACpB,CAAC;IAED;;OAEG;IACK,sBAAsB,CAC5B,SAAoD;QAEpD,MAAM,OAAO,GAAG,IAAI,GAAG,EAA6B,CAAC;QAErD,KAAK,MAAM,OAAO,IAAI,SAAS,CAAC,MAAM,EAAE,EAAE,CAAC;YACzC,KAAK,MAAM,QAAQ,IAAI,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;gBACxC,MAAM,KAAK,GAAG,QAAQ,CAAC,QAAQ,CAAC,eAAe,IAAI,CAAC,CAAC;gBAErD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;oBACxB,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;gBACzB,CAAC;gBAED,OAAO,CAAC,GAAG,CAAC,KAAK,CAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACrC,CAAC;QACH,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,mBAAmB,CAAC,QAAsB,EAAE,QAAgB;QACxE,0BAA0B;QAC1B,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACnC,IAAI,GAAG,KAAK,GAAG,IAAI,GAAG,KAAK,EAAE,EAAE,CAAC;YAC9B,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC3C,CAAC;QAED,kBAAkB;QAClB,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE;YAC/B,MAAM,EAAE,CAAC;YACT,SAAS,EAAE,CAAC;SACb,CAAC,CAAC;QAEH,MAAM,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IAC9C,CAAC;IAED;;OAEG;IACK,cAAc,CAAC,IAAY,EAAE,IAAY;QAC/C,OAAO,GAAG,IAAI,IAAI,IAAI,EAAE,CAAC;IAC3B,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,oBAAoB,CAAC,QAAgB;QACzC,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACrD,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAiB,CAAC;IAC5C,CAAC;CACF"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { ControllerContext, ResourceContext, ResourceInstance, ResourceManifest, RuntimeErrorCode, RuntimeResource } from "@telorun/sdk";
|
|
2
|
+
import type { ModuleContext } from "./module-context.js";
|
|
3
|
+
export type { ControllerContext, ResourceContext, ResourceInstance, ResourceManifest } from "@telorun/sdk";
|
|
4
|
+
export interface KernelContext {
|
|
5
|
+
kernel: Kernel;
|
|
6
|
+
}
|
|
7
|
+
export interface ExecContext {
|
|
8
|
+
execute(urn: string, input: any): Promise<any>;
|
|
9
|
+
[key: string]: any;
|
|
10
|
+
}
|
|
11
|
+
export type ResourceCapability = string;
|
|
12
|
+
export interface ResourceDefinition {
|
|
13
|
+
kind: string;
|
|
14
|
+
metadata: {
|
|
15
|
+
name: string;
|
|
16
|
+
module: string;
|
|
17
|
+
};
|
|
18
|
+
schema: Record<string, any>;
|
|
19
|
+
capabilities: ResourceCapability[];
|
|
20
|
+
events?: string[];
|
|
21
|
+
controllers?: Array<{
|
|
22
|
+
runtime: string;
|
|
23
|
+
entry: string;
|
|
24
|
+
}>;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Controller definition for a resource kind.
|
|
28
|
+
* Maps a fully-qualified resource kind to its controller implementation for a specific runtime.
|
|
29
|
+
*/
|
|
30
|
+
export interface ControllerDefinition {
|
|
31
|
+
kind: string;
|
|
32
|
+
runtime: string;
|
|
33
|
+
entry: string;
|
|
34
|
+
controller?: any;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Controller instance - runtime representation of a controller that handles resource instances.
|
|
38
|
+
*/
|
|
39
|
+
export interface ControllerInstance {
|
|
40
|
+
execute?(name: string, inputs: any, ctx: ExecContext): Promise<any>;
|
|
41
|
+
compile?(resource: ResourceManifest, ctx: ResourceContext): RuntimeResource | Promise<RuntimeResource>;
|
|
42
|
+
register?(ctx: ControllerContext): void | Promise<void>;
|
|
43
|
+
create?(resource: ResourceManifest, ctx: ResourceContext): ResourceInstance | null | Promise<ResourceInstance | null>;
|
|
44
|
+
schema: any;
|
|
45
|
+
}
|
|
46
|
+
export interface Kernel {
|
|
47
|
+
loadFromConfig(runtimeYamlPath: string): Promise<void>;
|
|
48
|
+
start(): Promise<void>;
|
|
49
|
+
acquireHold(reason?: string): () => void;
|
|
50
|
+
waitForIdle(): Promise<void>;
|
|
51
|
+
requestExit(code: number): void;
|
|
52
|
+
readonly exitCode: number;
|
|
53
|
+
teardownResource(module: string, kind: string, name: string): Promise<void>;
|
|
54
|
+
registerChildManifest(parentKey: string, resource: ResourceManifest): void;
|
|
55
|
+
getSourceFiles(): string[];
|
|
56
|
+
reloadSource(sourcePath: string): Promise<void>;
|
|
57
|
+
shutdown(): void;
|
|
58
|
+
registerModuleContext(moduleName: string, variables: Record<string, unknown>, secrets: Record<string, unknown>): void;
|
|
59
|
+
getModuleContext(moduleName: string): ModuleContext;
|
|
60
|
+
}
|
|
61
|
+
export declare class RuntimeError extends Error {
|
|
62
|
+
code: RuntimeErrorCode;
|
|
63
|
+
constructor(code: RuntimeErrorCode, message: string);
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AA0FA,MAAM,OAAO,YAAa,SAAQ,KAAK;IACrC,YACS,IAAsB,EAC7B,OAAe;QAEf,KAAK,CAAC,OAAO,CAAC,CAAC;QAHR,SAAI,GAAJ,IAAI,CAAkB;QAI7B,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;IAC7B,CAAC;CACF"}
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@telorun/kernel",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"description": "Telo Runtime - A lightweight, polyglot execution host.",
|
|
5
5
|
"keywords": [
|
|
6
|
-
"
|
|
6
|
+
"telo",
|
|
7
7
|
"runtime",
|
|
8
8
|
"execution",
|
|
9
9
|
"manifest"
|
|
@@ -47,8 +47,8 @@
|
|
|
47
47
|
"dependencies": {
|
|
48
48
|
"@marcbachmann/cel-js": "^7.5.3",
|
|
49
49
|
"@sinclair/typebox": "^0.34.48",
|
|
50
|
-
"@telorun/analyzer": "0.
|
|
51
|
-
"@telorun/
|
|
50
|
+
"@telorun/analyzer": "0.12.0",
|
|
51
|
+
"@telorun/templating": "0.3.0",
|
|
52
52
|
"ajv": "^8.17.1",
|
|
53
53
|
"ajv-formats": "^3.0.1",
|
|
54
54
|
"minimatch": "^10.2.5",
|
|
@@ -60,11 +60,14 @@
|
|
|
60
60
|
"typescript": "^5.0.0",
|
|
61
61
|
"vitest": "^2.1.8"
|
|
62
62
|
},
|
|
63
|
+
"peerDependencies": {
|
|
64
|
+
"@telorun/sdk": "0.12.0"
|
|
65
|
+
},
|
|
63
66
|
"overrides": {
|
|
64
67
|
"@marcbachmann/cel-js": "$@marcbachmann/cel-js",
|
|
65
68
|
"@sinclair/typebox": "$@sinclair/typebox",
|
|
66
69
|
"@telorun/analyzer": "$@telorun/analyzer",
|
|
67
|
-
"@telorun/
|
|
70
|
+
"@telorun/templating": "$@telorun/templating",
|
|
68
71
|
"ajv": "$ajv",
|
|
69
72
|
"ajv-formats": "$ajv-formats",
|
|
70
73
|
"minimatch": "$minimatch",
|
|
@@ -72,7 +75,7 @@
|
|
|
72
75
|
"yaml": "$yaml"
|
|
73
76
|
},
|
|
74
77
|
"scripts": {
|
|
75
|
-
"build": "tsc
|
|
78
|
+
"build": "tsc",
|
|
76
79
|
"dev": "tsc --watch",
|
|
77
80
|
"test": "vitest run",
|
|
78
81
|
"test:watch": "vitest"
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import { residualEntrySchema } from "@telorun/analyzer";
|
|
2
|
+
import { RuntimeError } from "@telorun/sdk";
|
|
3
|
+
import { SchemaValidator } from "./schema-validator.js";
|
|
4
|
+
|
|
5
|
+
type EntryType = "string" | "integer" | "number" | "boolean" | "object" | "array";
|
|
6
|
+
|
|
7
|
+
interface EnvEntry {
|
|
8
|
+
env: string;
|
|
9
|
+
type: EntryType;
|
|
10
|
+
default?: unknown;
|
|
11
|
+
[key: string]: unknown;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface EnvResolutionResult {
|
|
15
|
+
variables: Record<string, unknown>;
|
|
16
|
+
secrets: Record<string, unknown>;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Populate the root Application's `variables` / `secrets` namespaces from
|
|
21
|
+
* host environment variables, per the per-field `env:` mapping declared on
|
|
22
|
+
* each entry.
|
|
23
|
+
*
|
|
24
|
+
* Implements the polyglot env-resolution spec from
|
|
25
|
+
* kernel/nodejs/plans/application-env-variables.md: read the env var, coerce
|
|
26
|
+
* per `entry.type`, validate the coerced value (or the declared default, when
|
|
27
|
+
* the env var is unset) against the entry's residual schema, and aggregate
|
|
28
|
+
* every failure into a single `ERR_MANIFEST_VALIDATION_FAILED` error so all
|
|
29
|
+
* problems surface before any controller initializes.
|
|
30
|
+
*
|
|
31
|
+
* This must run BEFORE any Telo.Import controller initializes — imports may
|
|
32
|
+
* pass `${{ variables.X }}` as their `variables:` inputs, so the root scope
|
|
33
|
+
* has to be populated by the time the import controller evaluates those
|
|
34
|
+
* expressions.
|
|
35
|
+
*/
|
|
36
|
+
export function resolveApplicationEnv(
|
|
37
|
+
manifest: Record<string, any>,
|
|
38
|
+
env: Record<string, string | undefined>,
|
|
39
|
+
validator: SchemaValidator,
|
|
40
|
+
): EnvResolutionResult {
|
|
41
|
+
const errors: string[] = [];
|
|
42
|
+
const variables = resolveBlock(
|
|
43
|
+
manifest.variables ?? {},
|
|
44
|
+
env,
|
|
45
|
+
validator,
|
|
46
|
+
errors,
|
|
47
|
+
false,
|
|
48
|
+
);
|
|
49
|
+
const secrets = resolveBlock(
|
|
50
|
+
manifest.secrets ?? {},
|
|
51
|
+
env,
|
|
52
|
+
validator,
|
|
53
|
+
errors,
|
|
54
|
+
true,
|
|
55
|
+
);
|
|
56
|
+
if (errors.length > 0) {
|
|
57
|
+
throw new RuntimeError(
|
|
58
|
+
"ERR_MANIFEST_VALIDATION_FAILED",
|
|
59
|
+
`Application environment validation failed:\n` +
|
|
60
|
+
errors.map((e) => ` - ${e}`).join("\n"),
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
return { variables, secrets };
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function resolveBlock(
|
|
67
|
+
block: Record<string, EnvEntry> | unknown,
|
|
68
|
+
env: Record<string, string | undefined>,
|
|
69
|
+
validator: SchemaValidator,
|
|
70
|
+
errors: string[],
|
|
71
|
+
isSecret: boolean,
|
|
72
|
+
): Record<string, unknown> {
|
|
73
|
+
const out: Record<string, unknown> = {};
|
|
74
|
+
if (!block || typeof block !== "object" || Array.isArray(block)) {
|
|
75
|
+
return out;
|
|
76
|
+
}
|
|
77
|
+
for (const [name, entry] of Object.entries(block as Record<string, EnvEntry>)) {
|
|
78
|
+
if (!entry || typeof entry !== "object") continue;
|
|
79
|
+
const envKey = entry.env;
|
|
80
|
+
const raw = env[envKey];
|
|
81
|
+
const residual = residualEntrySchema(entry as Record<string, unknown>);
|
|
82
|
+
|
|
83
|
+
if (raw === undefined || raw === null) {
|
|
84
|
+
if (entry.default !== undefined) {
|
|
85
|
+
const validation = validateResidual(entry.default, residual, validator);
|
|
86
|
+
if (validation) {
|
|
87
|
+
errors.push(`${name}: ${validation}`);
|
|
88
|
+
} else {
|
|
89
|
+
out[name] = entry.default;
|
|
90
|
+
}
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
errors.push(`${name}: environment variable ${envKey} is not set (no default)`);
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
let coerced: unknown;
|
|
98
|
+
try {
|
|
99
|
+
coerced = coerce(raw, entry.type, envKey, isSecret);
|
|
100
|
+
} catch (e) {
|
|
101
|
+
errors.push(`${name}: ${(e as Error).message}`);
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const validation = validateResidual(coerced, residual, validator);
|
|
106
|
+
if (validation) {
|
|
107
|
+
errors.push(`${name}: ${validation}`);
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
out[name] = coerced;
|
|
112
|
+
}
|
|
113
|
+
return out;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/** Render a raw env value for inclusion in an error message. Secret values
|
|
117
|
+
* are masked so coercion / schema diagnostics don't leak secret material
|
|
118
|
+
* into logs (the env-var name and the failure reason still surface). */
|
|
119
|
+
function renderRawForError(raw: string, isSecret: boolean): string {
|
|
120
|
+
return isSecret ? "<redacted>" : `"${raw}"`;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function coerce(
|
|
124
|
+
raw: string,
|
|
125
|
+
type: EntryType,
|
|
126
|
+
envKey: string,
|
|
127
|
+
isSecret: boolean,
|
|
128
|
+
): unknown {
|
|
129
|
+
switch (type) {
|
|
130
|
+
case "string":
|
|
131
|
+
return raw;
|
|
132
|
+
case "integer": {
|
|
133
|
+
const trimmed = raw.trim();
|
|
134
|
+
if (!/^-?\d+$/.test(trimmed)) {
|
|
135
|
+
throw new Error(
|
|
136
|
+
`environment variable ${envKey}: value ${renderRawForError(raw, isSecret)} is not a valid integer`,
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
return parseInt(trimmed, 10);
|
|
140
|
+
}
|
|
141
|
+
case "number": {
|
|
142
|
+
const n = parseFloat(raw);
|
|
143
|
+
if (Number.isNaN(n)) {
|
|
144
|
+
throw new Error(
|
|
145
|
+
`environment variable ${envKey}: value ${renderRawForError(raw, isSecret)} is not a valid number`,
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
return n;
|
|
149
|
+
}
|
|
150
|
+
case "boolean":
|
|
151
|
+
if (raw === "true") return true;
|
|
152
|
+
if (raw === "false") return false;
|
|
153
|
+
throw new Error(
|
|
154
|
+
`environment variable ${envKey}: value ${renderRawForError(raw, isSecret)} is not a valid boolean (expected "true" or "false")`,
|
|
155
|
+
);
|
|
156
|
+
case "object": {
|
|
157
|
+
const parsed = parseJson(raw, envKey, isSecret);
|
|
158
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
159
|
+
throw new Error(
|
|
160
|
+
`environment variable ${envKey}: expected JSON object, got ${describeJsonType(parsed)}`,
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
return parsed;
|
|
164
|
+
}
|
|
165
|
+
case "array": {
|
|
166
|
+
const parsed = parseJson(raw, envKey, isSecret);
|
|
167
|
+
if (!Array.isArray(parsed)) {
|
|
168
|
+
throw new Error(
|
|
169
|
+
`environment variable ${envKey}: expected JSON array, got ${describeJsonType(parsed)}`,
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
return parsed;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function parseJson(raw: string, envKey: string, isSecret: boolean): unknown {
|
|
178
|
+
try {
|
|
179
|
+
return JSON.parse(raw);
|
|
180
|
+
} catch (e) {
|
|
181
|
+
// Node's JSON.parse error embeds the offending character / position; for
|
|
182
|
+
// secrets, swallow the parser detail and surface only the env var name.
|
|
183
|
+
const detail = isSecret ? "value is not valid JSON" : (e as Error).message;
|
|
184
|
+
throw new Error(`environment variable ${envKey}: ${isSecret ? detail : `value is not valid JSON: ${detail}`}`);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function describeJsonType(value: unknown): string {
|
|
189
|
+
if (value === null) return "null";
|
|
190
|
+
if (Array.isArray(value)) return "array";
|
|
191
|
+
return typeof value;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
function validateResidual(
|
|
195
|
+
value: unknown,
|
|
196
|
+
residual: Record<string, unknown>,
|
|
197
|
+
validator: SchemaValidator,
|
|
198
|
+
): string | null {
|
|
199
|
+
try {
|
|
200
|
+
validator.compile(residual as any).validate(value);
|
|
201
|
+
return null;
|
|
202
|
+
} catch (e) {
|
|
203
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
204
|
+
// Strip SchemaValidator's "Invalid value passed: <JSON>. Error: " prefix
|
|
205
|
+
// so the JSON-stringified value (which can be secret material for entries
|
|
206
|
+
// under `secrets:`) never reaches the caller. The split is anchored on
|
|
207
|
+
// the literal ". Error: " delimiter — a `[^.]*` regex would have leaked
|
|
208
|
+
// any value containing a dot (URLs, versions, paths).
|
|
209
|
+
const sentinel = ". Error: ";
|
|
210
|
+
const idx = msg.indexOf(sentinel);
|
|
211
|
+
if (msg.startsWith("Invalid value passed:") && idx !== -1) {
|
|
212
|
+
return msg.slice(idx + sentinel.length);
|
|
213
|
+
}
|
|
214
|
+
return msg;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
@@ -81,10 +81,13 @@ export interface NpmControllerLoaderOptions {
|
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
/**
|
|
84
|
-
* The npm-loader maintains a single install root per kernel process
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
84
|
+
* The npm-loader maintains a single install root per kernel process. For a
|
|
85
|
+
* local entry manifest (`file://` URL or bare path) the root lives at
|
|
86
|
+
* `<entry-manifest-dir>/.telo/npm/`; for an HTTP(S) entry URL it lives in a
|
|
87
|
+
* user-level cache keyed by `sha256(entryUrl)` (see `computeInstallRoot`).
|
|
88
|
+
* Every controller — registry tag or `local_path` — is installed via
|
|
89
|
+
* `npm install <spec>` into this root, then imported from
|
|
90
|
+
* `<root>/node_modules/<pkg>`. This collapses two parallel
|
|
88
91
|
* module realms (kernel-side @telorun/sdk vs. controller-side @telorun/sdk)
|
|
89
92
|
* into one: the kernel's own SDK is wired in as a `file:` dep, npm/pnpm
|
|
90
93
|
* symlink it, and Node's ESM resolver follows the symlink to the same
|
|
@@ -190,36 +193,24 @@ export class NpmControllerLoader {
|
|
|
190
193
|
);
|
|
191
194
|
}
|
|
192
195
|
const entryUrlStr = this.entryUrl;
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
//
|
|
196
|
-
//
|
|
197
|
-
//
|
|
198
|
-
//
|
|
199
|
-
//
|
|
200
|
-
|
|
201
|
-
const entryDir = path.dirname(path.resolve(entryPath));
|
|
202
|
-
const installRoot = path.join(entryDir, ".telo", "npm");
|
|
203
|
-
|
|
204
|
-
// Build the install-root package.json: kernel-runtime deps as `file:` refs,
|
|
205
|
-
// `overrides` + `pnpm.overrides` pinning every name to `$<name>`. This is
|
|
206
|
-
// the realm-collapse mechanism — npm's `file:` symlinks the kernel's own
|
|
207
|
-
// package locations, the resolver follows symlinks to the realpath, and
|
|
208
|
-
// every controller transitively resolving these names lands on the
|
|
209
|
-
// identical module instance the kernel itself is using.
|
|
210
|
-
const runtimeDeps = await loadRuntimeDeps();
|
|
196
|
+
const installRoot = computeInstallRoot(entryUrlStr);
|
|
197
|
+
|
|
198
|
+
// Build the install-root package.json: kernel-runtime deps as `file:` refs
|
|
199
|
+
// pointing at the kernel-side realpath. Modules declare these names as
|
|
200
|
+
// `peerDependencies`, so npm/pnpm resolve each controller's `import` to the
|
|
201
|
+
// single copy provided here — the realm-collapse mechanism that gives
|
|
202
|
+
// class-identity-sensitive types (today: `Stream`) one constructor across
|
|
203
|
+
// the kernel/controller boundary.
|
|
211
204
|
const dependencies: Record<string, string> = {};
|
|
212
|
-
const
|
|
213
|
-
for (const name of runtimeDeps) {
|
|
205
|
+
for (const name of REALM_COLLAPSE_NAMES) {
|
|
214
206
|
const resolvedPkgRoot = await resolveKernelPackageRoot(name);
|
|
215
207
|
if (!resolvedPkgRoot) {
|
|
216
208
|
// A kernel runtime dep that can't be resolved at boot is unusual but
|
|
217
|
-
// not fatal — the realm-collapse story degrades to "rely on
|
|
218
|
-
//
|
|
209
|
+
// not fatal — the realm-collapse story degrades to "rely on whatever
|
|
210
|
+
// the package manager picks" for that name. Don't crash the loader.
|
|
219
211
|
continue;
|
|
220
212
|
}
|
|
221
213
|
dependencies[name] = `file:${resolvedPkgRoot}`;
|
|
222
|
-
overrides[name] = `$${name}`;
|
|
223
214
|
}
|
|
224
215
|
|
|
225
216
|
const packageJson = {
|
|
@@ -227,8 +218,6 @@ export class NpmControllerLoader {
|
|
|
227
218
|
private: true,
|
|
228
219
|
version: "0.0.0",
|
|
229
220
|
dependencies,
|
|
230
|
-
overrides,
|
|
231
|
-
pnpm: { overrides },
|
|
232
221
|
};
|
|
233
222
|
const packageJsonPath = path.join(installRoot, "package.json");
|
|
234
223
|
const stateFile = path.join(installRoot, ".telo-state.json");
|
|
@@ -405,54 +394,18 @@ export class NpmControllerLoader {
|
|
|
405
394
|
}
|
|
406
395
|
|
|
407
396
|
/**
|
|
408
|
-
*
|
|
409
|
-
*
|
|
410
|
-
*
|
|
411
|
-
*
|
|
412
|
-
*
|
|
413
|
-
*
|
|
414
|
-
*
|
|
397
|
+
* Names of packages whose realpath must be shared between the kernel and every
|
|
398
|
+
* loaded controller. Each name here becomes a `file:` dep in the install-root
|
|
399
|
+
* `package.json`, pinned at the kernel's own resolution; controllers declare
|
|
400
|
+
* these names as `peerDependencies` so npm/pnpm resolves them to that single
|
|
401
|
+
* copy instead of nesting their own.
|
|
402
|
+
*
|
|
403
|
+
* Add a name here if you ship another shared runtime symbol whose `instanceof`
|
|
404
|
+
* or constructor identity matters across module boundaries. Today the only
|
|
405
|
+
* such name is `@telorun/sdk` (carries the `Stream` class registered with
|
|
406
|
+
* `@marcbachmann/cel-js`).
|
|
415
407
|
*/
|
|
416
|
-
|
|
417
|
-
const here = fileURLToPath(import.meta.url);
|
|
418
|
-
// Walk up from this file's location to the kernel-package root (the dir
|
|
419
|
-
// that contains package.json). In dev: `kernel/nodejs/`. In published:
|
|
420
|
-
// the installed package root inside `node_modules/@telorun/kernel/`.
|
|
421
|
-
// Walk-until-root rather than a fixed depth — the directory tree depth
|
|
422
|
-
// depends on whether we're in a workspace or installed tree.
|
|
423
|
-
const pkgDir = await walkUpToPackageRoot(path.dirname(here));
|
|
424
|
-
if (!pkgDir) return [];
|
|
425
|
-
|
|
426
|
-
const generated = path.join(pkgDir, "dist", "generated", "runtime-deps.json");
|
|
427
|
-
if (!(await pathExists(generated))) return [];
|
|
428
|
-
// The file is generated by `scripts/generate-runtime-deps.mjs`; if it
|
|
429
|
-
// exists but is malformed, that's a kernel-build bug. Don't swallow —
|
|
430
|
-
// surface so the cause is debuggable. Realm collapse is the whole point
|
|
431
|
-
// of this code path; quietly degrading to "no realm collapse" would
|
|
432
|
-
// silently re-introduce the very bug the file fixes.
|
|
433
|
-
const data = JSON.parse(await fs.readFile(generated, "utf8"));
|
|
434
|
-
if (!Array.isArray(data?.names)) {
|
|
435
|
-
throw new Error(
|
|
436
|
-
`[telo] ${generated} is malformed: expected { names: string[] } at top level. ` +
|
|
437
|
-
`Re-run \`node scripts/generate-runtime-deps.mjs <pkg-dir>\` to regenerate.`,
|
|
438
|
-
);
|
|
439
|
-
}
|
|
440
|
-
return data.names as string[];
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
/**
|
|
444
|
-
* Walk up from `from` until the directory contains a `package.json`.
|
|
445
|
-
* Returns null at filesystem root if none found.
|
|
446
|
-
*/
|
|
447
|
-
async function walkUpToPackageRoot(from: string): Promise<string | null> {
|
|
448
|
-
let dir = from;
|
|
449
|
-
while (true) {
|
|
450
|
-
if (await pathExists(path.join(dir, "package.json"))) return dir;
|
|
451
|
-
const parent = path.dirname(dir);
|
|
452
|
-
if (parent === dir) return null;
|
|
453
|
-
dir = parent;
|
|
454
|
-
}
|
|
455
|
-
}
|
|
408
|
+
const REALM_COLLAPSE_NAMES: ReadonlyArray<string> = ["@telorun/sdk"];
|
|
456
409
|
|
|
457
410
|
/**
|
|
458
411
|
* Resolve a kernel-runtime dep name to the realpath of its package directory.
|
|
@@ -675,35 +628,56 @@ async function readDepSpec(installRoot: string, packageName: string): Promise<st
|
|
|
675
628
|
}
|
|
676
629
|
|
|
677
630
|
/**
|
|
678
|
-
*
|
|
679
|
-
*
|
|
680
|
-
*
|
|
681
|
-
*
|
|
682
|
-
*
|
|
683
|
-
* `
|
|
631
|
+
* Decide where the per-kernel install root lives for a given entry URL.
|
|
632
|
+
*
|
|
633
|
+
* - `file://` URL or bare filesystem path: anchored next to the manifest at
|
|
634
|
+
* `<entry-dir>/.telo/npm/`. Same as before — keeps the "install lives with
|
|
635
|
+
* the project" story for local development and Docker builds where the
|
|
636
|
+
* tree is `COPY`-d into the image.
|
|
637
|
+
* - `http(s)://` URL: there is no on-disk anchor next to the manifest, so
|
|
638
|
+
* the install root lives in a user-level cache keyed by the SHA-256 of
|
|
639
|
+
* the entry URL: `<cacheDir>/<hash>/npm/`. Repeat runs of the same URL
|
|
640
|
+
* hit the same cache; distinct URLs get isolated trees so two unrelated
|
|
641
|
+
* remote apps don't share `node_modules` (different controller versions,
|
|
642
|
+
* different realm-collapse pins).
|
|
684
643
|
*
|
|
685
|
-
*
|
|
686
|
-
*
|
|
687
|
-
*
|
|
644
|
+
* Cache location, in priority order:
|
|
645
|
+
* 1. `$TELO_NPM_CACHE_DIR` (explicit override — tests use this to avoid
|
|
646
|
+
* polluting the developer's `~/.cache`).
|
|
647
|
+
* 2. `$XDG_CACHE_HOME/telo/remote` (standard XDG path on Linux).
|
|
648
|
+
* 3. `<os.homedir()>/.cache/telo/remote` (POSIX fallback / macOS).
|
|
649
|
+
*
|
|
650
|
+
* Unrecognised schemes (anything that isn't `file://`, `http://`, or
|
|
651
|
+
* `https://`) still throw `ControllerEnvMissingError` so the dispatcher can
|
|
652
|
+
* advance to a non-npm candidate.
|
|
688
653
|
*/
|
|
689
|
-
function
|
|
690
|
-
if (entryUrl.startsWith("file://"))
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
const schemeMatch = entryUrl.match(/^([a-zA-Z][a-zA-Z0-9+.-]*):\/\//);
|
|
694
|
-
if (schemeMatch) {
|
|
695
|
-
// Env-missing rather than a hard error: the dispatcher should advance
|
|
696
|
-
// to the next candidate when an HTTP-sourced manifest is paired with a
|
|
697
|
-
// `pkg:cargo` (or other non-npm) fallback. Hard-failing would lock the
|
|
698
|
-
// whole resolve chain to this branch.
|
|
699
|
-
throw new ControllerEnvMissingError(
|
|
700
|
-
`[telo] entry URL scheme '${schemeMatch[1]}' is not supported by the npm controller ` +
|
|
701
|
-
`loader. The install root must live next to a local manifest; HTTP-sourced manifests ` +
|
|
702
|
-
`have no such anchor. Resolve the manifest to disk first, or use file:// directly. ` +
|
|
703
|
-
`(entryUrl: ${entryUrl})`,
|
|
704
|
-
);
|
|
654
|
+
function computeInstallRoot(entryUrl: string): string {
|
|
655
|
+
if (entryUrl.startsWith("file://")) {
|
|
656
|
+
const entryPath = fileURLToPath(entryUrl);
|
|
657
|
+
return path.join(path.dirname(path.resolve(entryPath)), ".telo", "npm");
|
|
705
658
|
}
|
|
706
|
-
|
|
659
|
+
const schemeMatch = entryUrl.match(/^([a-zA-Z][a-zA-Z0-9+.-]*):\/\//);
|
|
660
|
+
if (!schemeMatch) {
|
|
661
|
+
// Bare filesystem path: same anchor as `file://`.
|
|
662
|
+
return path.join(path.dirname(path.resolve(entryUrl)), ".telo", "npm");
|
|
663
|
+
}
|
|
664
|
+
const scheme = schemeMatch[1].toLowerCase();
|
|
665
|
+
if (scheme === "http" || scheme === "https") {
|
|
666
|
+
const cacheBase =
|
|
667
|
+
process.env.TELO_NPM_CACHE_DIR ||
|
|
668
|
+
(process.env.XDG_CACHE_HOME
|
|
669
|
+
? path.join(process.env.XDG_CACHE_HOME, "telo", "remote")
|
|
670
|
+
: path.join(os.homedir(), ".cache", "telo", "remote"));
|
|
671
|
+
return path.join(cacheBase, sha256(entryUrl), "npm");
|
|
672
|
+
}
|
|
673
|
+
// Env-missing rather than a hard error: the dispatcher should advance to
|
|
674
|
+
// the next candidate when a non-npm scheme is paired with a `pkg:cargo`
|
|
675
|
+
// (or other) fallback.
|
|
676
|
+
throw new ControllerEnvMissingError(
|
|
677
|
+
`[telo] entry URL scheme '${schemeMatch[1]}' is not supported by the npm controller ` +
|
|
678
|
+
`loader. Supported schemes: file://, http://, https://, or a bare filesystem path. ` +
|
|
679
|
+
`(entryUrl: ${entryUrl})`,
|
|
680
|
+
);
|
|
707
681
|
}
|
|
708
682
|
|
|
709
683
|
/**
|
|
@@ -954,7 +928,8 @@ export const __testing__ = {
|
|
|
954
928
|
resolvePackageExportTarget,
|
|
955
929
|
resolveExportTargetValue,
|
|
956
930
|
tryResolveFile,
|
|
957
|
-
|
|
931
|
+
computeInstallRoot,
|
|
958
932
|
EXPORTS_MAX_DEPTH,
|
|
959
933
|
DEFAULT_RESOLVER_CONDITIONS,
|
|
934
|
+
REALM_COLLAPSE_NAMES,
|
|
960
935
|
};
|