@telorun/kernel 0.4.1 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/controller-loader.d.ts +19 -20
- package/dist/controller-loader.d.ts.map +1 -1
- package/dist/controller-loader.js +67 -247
- package/dist/controller-loader.js.map +1 -1
- package/dist/controller-loaders/napi-loader.d.ts +27 -0
- package/dist/controller-loaders/napi-loader.d.ts.map +1 -0
- package/dist/controller-loaders/napi-loader.js +158 -0
- package/dist/controller-loaders/napi-loader.js.map +1 -0
- package/dist/controller-loaders/npm-loader.d.ts +20 -0
- package/dist/controller-loaders/npm-loader.d.ts.map +1 -0
- package/dist/controller-loaders/npm-loader.js +256 -0
- package/dist/controller-loaders/npm-loader.js.map +1 -0
- package/dist/controller-registry.d.ts +30 -20
- package/dist/controller-registry.d.ts.map +1 -1
- package/dist/controller-registry.js +50 -99
- package/dist/controller-registry.js.map +1 -1
- package/dist/controllers/module/import-controller.d.ts +11 -0
- package/dist/controllers/module/import-controller.d.ts.map +1 -1
- package/dist/controllers/module/import-controller.js +30 -3
- package/dist/controllers/module/import-controller.js.map +1 -1
- package/dist/controllers/resource-definition/abstract-controller.d.ts +35 -0
- package/dist/controllers/resource-definition/abstract-controller.d.ts.map +1 -0
- package/dist/controllers/resource-definition/abstract-controller.js +34 -0
- package/dist/controllers/resource-definition/abstract-controller.js.map +1 -0
- package/dist/controllers/resource-definition/resource-definition-controller.d.ts.map +1 -1
- package/dist/controllers/resource-definition/resource-definition-controller.js +1 -1
- package/dist/controllers/resource-definition/resource-definition-controller.js.map +1 -1
- package/dist/evaluation-context.js +1 -1
- package/dist/evaluation-context.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/kernel.d.ts +14 -16
- package/dist/kernel.d.ts.map +1 -1
- package/dist/kernel.js +58 -49
- package/dist/kernel.js.map +1 -1
- package/dist/manifest-schemas.d.ts +50 -0
- package/dist/manifest-schemas.d.ts.map +1 -1
- package/dist/manifest-schemas.js +31 -0
- package/dist/manifest-schemas.js.map +1 -1
- package/dist/{manifest-adapters/local-file-adapter.d.ts → manifest-sources/local-file-source.d.ts} +3 -3
- package/dist/manifest-sources/local-file-source.d.ts.map +1 -0
- package/dist/{manifest-adapters/local-file-adapter.js → manifest-sources/local-file-source.js} +2 -2
- package/dist/manifest-sources/local-file-source.js.map +1 -0
- package/dist/manifest-sources/memory-source.d.ts +23 -0
- package/dist/manifest-sources/memory-source.d.ts.map +1 -0
- package/dist/manifest-sources/memory-source.js +83 -0
- package/dist/manifest-sources/memory-source.js.map +1 -0
- package/dist/module-context.d.ts +17 -3
- package/dist/module-context.d.ts.map +1 -1
- package/dist/module-context.js +19 -1
- package/dist/module-context.js.map +1 -1
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +0 -1
- package/dist/registry.js.map +1 -1
- package/dist/resource-context.d.ts +2 -7
- package/dist/resource-context.d.ts.map +1 -1
- package/dist/resource-context.js +8 -28
- package/dist/resource-context.js.map +1 -1
- package/dist/runtime-registry.d.ts +50 -0
- package/dist/runtime-registry.d.ts.map +1 -0
- package/dist/runtime-registry.js +140 -0
- package/dist/runtime-registry.js.map +1 -0
- package/package.json +16 -5
- package/src/controller-loader.ts +77 -273
- package/src/controller-loaders/napi-loader.ts +191 -0
- package/src/controller-loaders/npm-loader.ts +285 -0
- package/src/controller-registry.ts +66 -129
- package/src/controllers/module/import-controller.ts +32 -3
- package/src/controllers/resource-definition/abstract-controller.ts +56 -0
- package/src/controllers/resource-definition/resource-definition-controller.ts +1 -0
- package/src/evaluation-context.ts +1 -1
- package/src/index.ts +2 -1
- package/src/kernel.ts +86 -67
- package/src/manifest-schemas.ts +33 -0
- package/src/{manifest-adapters/local-file-adapter.ts → manifest-sources/local-file-source.ts} +2 -2
- package/src/manifest-sources/memory-source.ts +104 -0
- package/src/module-context.ts +36 -3
- package/src/registry.ts +0 -1
- package/src/resource-context.ts +11 -36
- package/src/runtime-registry.ts +170 -0
- package/dist/manifest-adapters/local-file-adapter.d.ts.map +0 -1
- package/dist/manifest-adapters/local-file-adapter.js.map +0 -1
- package/dist/manifest-adapters/manifest-adapter.d.ts +0 -35
- package/dist/manifest-adapters/manifest-adapter.d.ts.map +0 -1
- package/dist/manifest-adapters/manifest-adapter.js +0 -2
- package/dist/manifest-adapters/manifest-adapter.js.map +0 -1
- package/src/manifest-adapters/manifest-adapter.ts +0 -35
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
import { execFile } from "child_process";
|
|
2
|
+
import { createHash } from "crypto";
|
|
3
|
+
import * as fs from "fs/promises";
|
|
4
|
+
import * as os from "os";
|
|
5
|
+
import { PackageURL } from "packageurl-js";
|
|
6
|
+
import * as path from "path";
|
|
7
|
+
import { promisify } from "util";
|
|
8
|
+
const homedir = os.homedir();
|
|
9
|
+
const cacheRoot = process.env.TELO_CACHE_DIR
|
|
10
|
+
? path.resolve(process.env.TELO_CACHE_DIR)
|
|
11
|
+
: path.join(homedir, ".cache", "telo");
|
|
12
|
+
const npmCacheRoot = path.join(cacheRoot, "npm");
|
|
13
|
+
const isBun = typeof globalThis.Bun !== "undefined";
|
|
14
|
+
export class NpmControllerLoader {
|
|
15
|
+
/**
|
|
16
|
+
* Resolve a `pkg:npm/...` PURL to a controller module instance. Tries, in order:
|
|
17
|
+
* a relative `local_path` qualifier, the workspace's `node_modules`, and finally
|
|
18
|
+
* an isolated install under `~/.cache/telo/npm/<hash>`.
|
|
19
|
+
*/
|
|
20
|
+
async load(purl, baseUri) {
|
|
21
|
+
const [, namespace, name, versionSpec, qualifiers, entry] = PackageURL.parseString(purl);
|
|
22
|
+
const localPath = qualifiers?.get("local_path");
|
|
23
|
+
const cacheKey = createHash("sha256").update(purl).digest("hex").slice(0, 12);
|
|
24
|
+
const installDir = path.join(npmCacheRoot, cacheKey);
|
|
25
|
+
let packageRoot;
|
|
26
|
+
const isLocalManifest = baseUri && !baseUri.startsWith("http://") && !baseUri.startsWith("https://");
|
|
27
|
+
if (localPath && isLocalManifest) {
|
|
28
|
+
const baseUriPath = baseUri.startsWith("file://") ? baseUri.slice("file://".length) : baseUri;
|
|
29
|
+
const manifestDir = path.dirname(baseUriPath);
|
|
30
|
+
const resolvedLocalPath = path.resolve(manifestDir, localPath);
|
|
31
|
+
if (await this.pathExists(resolvedLocalPath)) {
|
|
32
|
+
packageRoot = resolvedLocalPath;
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
const nodeModulesPath = await this.findInNodeModules(`${namespace}/${name}`);
|
|
36
|
+
if (nodeModulesPath) {
|
|
37
|
+
packageRoot = nodeModulesPath;
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
await this.ensureNpmPackageInstalled(installDir, `${namespace}/${name}@${versionSpec}`);
|
|
41
|
+
packageRoot = this.getInstalledPackageRoot(installDir, `${namespace}/${name}`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
const nodeModulesPath = await this.findInNodeModules(`${namespace}/${name}`);
|
|
47
|
+
if (nodeModulesPath) {
|
|
48
|
+
packageRoot = nodeModulesPath;
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
await this.ensureNpmPackageInstalled(installDir, `${namespace}/${name}@${versionSpec}`);
|
|
52
|
+
packageRoot = this.getInstalledPackageRoot(installDir, `${namespace}/${name}`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
const entryFile = await this.resolvePackageEntry(packageRoot, entry ? `./${entry}` : ".");
|
|
56
|
+
const instance = await import(entryFile);
|
|
57
|
+
if (!instance || (!instance.create && !instance.register)) {
|
|
58
|
+
throw new Error(`Invalid controller loaded from "${purl}": missing create or register function`);
|
|
59
|
+
}
|
|
60
|
+
return instance;
|
|
61
|
+
}
|
|
62
|
+
async ensureNpmPackageInstalled(installDir, packageSpec) {
|
|
63
|
+
const packageName = this.getPackageName(packageSpec.startsWith(".") || path.isAbsolute(packageSpec)
|
|
64
|
+
? await this.getLocalPackageName(packageSpec)
|
|
65
|
+
: packageSpec);
|
|
66
|
+
const packageRoot = this.getInstalledPackageRoot(installDir, packageName);
|
|
67
|
+
const packageJsonPath = path.join(packageRoot, "package.json");
|
|
68
|
+
if (await this.pathExists(packageJsonPath)) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
await fs.mkdir(installDir, { recursive: true });
|
|
72
|
+
const rootPackageJson = path.join(installDir, "package.json");
|
|
73
|
+
if (!(await this.pathExists(rootPackageJson))) {
|
|
74
|
+
await fs.writeFile(rootPackageJson, JSON.stringify({ name: "telo-cache", private: true }, null, 2));
|
|
75
|
+
}
|
|
76
|
+
const execFileAsync = promisify(execFile);
|
|
77
|
+
const args = [
|
|
78
|
+
"install",
|
|
79
|
+
"--no-audit",
|
|
80
|
+
"--no-fund",
|
|
81
|
+
"--silent",
|
|
82
|
+
"--prefix",
|
|
83
|
+
installDir,
|
|
84
|
+
packageSpec,
|
|
85
|
+
];
|
|
86
|
+
await execFileAsync("npm", args);
|
|
87
|
+
}
|
|
88
|
+
getPackageName(packageSpec) {
|
|
89
|
+
if (packageSpec.startsWith("@")) {
|
|
90
|
+
const lastAt = packageSpec.lastIndexOf("@");
|
|
91
|
+
return lastAt > 0 ? packageSpec.slice(0, lastAt) : packageSpec;
|
|
92
|
+
}
|
|
93
|
+
const [name] = packageSpec.split("@");
|
|
94
|
+
return name;
|
|
95
|
+
}
|
|
96
|
+
getInstalledPackageRoot(installDir, packageName) {
|
|
97
|
+
const nameParts = packageName.split("/");
|
|
98
|
+
return path.join(installDir, "node_modules", ...nameParts);
|
|
99
|
+
}
|
|
100
|
+
async getLocalPackageName(packagePath) {
|
|
101
|
+
const packageJsonPath = path.join(packagePath, "package.json");
|
|
102
|
+
if (!(await this.pathExists(packageJsonPath))) {
|
|
103
|
+
throw new Error(`Local package missing package.json: ${packagePath}`);
|
|
104
|
+
}
|
|
105
|
+
const content = await fs.readFile(packageJsonPath, "utf8");
|
|
106
|
+
const parsed = JSON.parse(content);
|
|
107
|
+
if (!parsed?.name) {
|
|
108
|
+
throw new Error(`Local package missing name in package.json: ${packagePath}`);
|
|
109
|
+
}
|
|
110
|
+
return parsed.name;
|
|
111
|
+
}
|
|
112
|
+
async resolvePackageEntry(packageRoot, entry, packageName) {
|
|
113
|
+
const packageJsonPath = path.join(packageRoot, "package.json");
|
|
114
|
+
let resolvedPackageName = packageName;
|
|
115
|
+
let packageJson = null;
|
|
116
|
+
if (!resolvedPackageName && (await this.pathExists(packageJsonPath))) {
|
|
117
|
+
const content = await fs.readFile(packageJsonPath, "utf8");
|
|
118
|
+
try {
|
|
119
|
+
packageJson = JSON.parse(content);
|
|
120
|
+
resolvedPackageName = packageJson?.name;
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
resolvedPackageName = packageName;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
else if (await this.pathExists(packageJsonPath)) {
|
|
127
|
+
try {
|
|
128
|
+
packageJson = JSON.parse(await fs.readFile(packageJsonPath, "utf8"));
|
|
129
|
+
}
|
|
130
|
+
catch {
|
|
131
|
+
packageJson = null;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
const entryValue = entry.trim();
|
|
135
|
+
const exportTarget = this.resolvePackageExportTarget(packageJson?.exports, entryValue);
|
|
136
|
+
if (exportTarget) {
|
|
137
|
+
const resolved = path.resolve(packageRoot, exportTarget);
|
|
138
|
+
if (await this.pathExists(resolved)) {
|
|
139
|
+
return this.resolveForRuntime(resolved, packageRoot);
|
|
140
|
+
}
|
|
141
|
+
if (!path.extname(resolved)) {
|
|
142
|
+
const withJs = `${resolved}.js`;
|
|
143
|
+
if (await this.pathExists(withJs)) {
|
|
144
|
+
return withJs;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
if ((entryValue === "." || entryValue === "./") && packageJson) {
|
|
149
|
+
const mainFields = ["module", "main"];
|
|
150
|
+
for (const field of mainFields) {
|
|
151
|
+
const target = packageJson[field];
|
|
152
|
+
if (typeof target === "string") {
|
|
153
|
+
const resolved = path.resolve(packageRoot, target);
|
|
154
|
+
if (await this.pathExists(resolved)) {
|
|
155
|
+
return this.resolveForRuntime(resolved, packageRoot);
|
|
156
|
+
}
|
|
157
|
+
if (!path.extname(resolved)) {
|
|
158
|
+
const withJs = `${resolved}.js`;
|
|
159
|
+
if (await this.pathExists(withJs)) {
|
|
160
|
+
return withJs;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
const directPath = path.resolve(packageRoot, entryValue);
|
|
167
|
+
if (await this.pathExists(directPath)) {
|
|
168
|
+
return this.resolveForRuntime(directPath, packageRoot);
|
|
169
|
+
}
|
|
170
|
+
if (!path.extname(directPath)) {
|
|
171
|
+
const withJs = `${directPath}.js`;
|
|
172
|
+
if (await this.pathExists(withJs)) {
|
|
173
|
+
return withJs;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
throw new Error(`Controller entry "${entryValue}" could not be resolved in ${packageRoot}`);
|
|
177
|
+
}
|
|
178
|
+
resolvePackageExportTarget(exportsField, entry) {
|
|
179
|
+
if (!exportsField) {
|
|
180
|
+
return null;
|
|
181
|
+
}
|
|
182
|
+
const key = entry === "." || entry === "./" ? "." : entry;
|
|
183
|
+
const target = exportsField[key];
|
|
184
|
+
return this.resolveExportTargetValue(target);
|
|
185
|
+
}
|
|
186
|
+
resolveExportTargetValue(target) {
|
|
187
|
+
if (!target) {
|
|
188
|
+
return null;
|
|
189
|
+
}
|
|
190
|
+
if (typeof target === "string") {
|
|
191
|
+
return target;
|
|
192
|
+
}
|
|
193
|
+
if (Array.isArray(target)) {
|
|
194
|
+
for (const item of target) {
|
|
195
|
+
const resolved = this.resolveExportTargetValue(item);
|
|
196
|
+
if (resolved) {
|
|
197
|
+
return resolved;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return null;
|
|
201
|
+
}
|
|
202
|
+
if (typeof target === "object") {
|
|
203
|
+
const preferredKeys = isBun
|
|
204
|
+
? ["bun", "import", "default", "require"]
|
|
205
|
+
: ["import", "default", "require"];
|
|
206
|
+
for (const key of preferredKeys) {
|
|
207
|
+
if (target[key]) {
|
|
208
|
+
const resolved = this.resolveExportTargetValue(target[key]);
|
|
209
|
+
if (resolved) {
|
|
210
|
+
return resolved;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
return null;
|
|
216
|
+
}
|
|
217
|
+
async resolveForRuntime(resolvedPath, packageRoot) {
|
|
218
|
+
if (isBun || !resolvedPath.endsWith(".ts")) {
|
|
219
|
+
return resolvedPath;
|
|
220
|
+
}
|
|
221
|
+
const relative = path.relative(packageRoot, resolvedPath);
|
|
222
|
+
const distEquivalent = path.resolve(packageRoot, relative.replace(/^src\//, "dist/").replace(/\.ts$/, ".js"));
|
|
223
|
+
if (await this.pathExists(distEquivalent)) {
|
|
224
|
+
return distEquivalent;
|
|
225
|
+
}
|
|
226
|
+
const jsPath = resolvedPath.replace(/\.ts$/, ".js");
|
|
227
|
+
if (await this.pathExists(jsPath)) {
|
|
228
|
+
return jsPath;
|
|
229
|
+
}
|
|
230
|
+
return resolvedPath;
|
|
231
|
+
}
|
|
232
|
+
async findInNodeModules(packageName) {
|
|
233
|
+
const nameParts = packageName.split("/");
|
|
234
|
+
const candidates = [
|
|
235
|
+
path.join(process.cwd(), "node_modules", ...nameParts),
|
|
236
|
+
path.join(process.cwd(), "node_modules", ".pnpm", "node_modules", ...nameParts),
|
|
237
|
+
];
|
|
238
|
+
for (const candidate of candidates) {
|
|
239
|
+
const packageJsonPath = path.join(candidate, "package.json");
|
|
240
|
+
if (await this.pathExists(packageJsonPath)) {
|
|
241
|
+
return candidate;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
return null;
|
|
245
|
+
}
|
|
246
|
+
async pathExists(filePath) {
|
|
247
|
+
try {
|
|
248
|
+
await fs.access(filePath);
|
|
249
|
+
return true;
|
|
250
|
+
}
|
|
251
|
+
catch {
|
|
252
|
+
return false;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
//# sourceMappingURL=npm-loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"npm-loader.js","sourceRoot":"","sources":["../../src/controller-loaders/npm-loader.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,28 +1,41 @@
|
|
|
1
|
-
import { ControllerInstance, ResourceDefinition
|
|
1
|
+
import { ControllerInstance, ResourceDefinition } from "@telorun/sdk";
|
|
2
2
|
/**
|
|
3
3
|
* ControllerRegistry: Manages controller loading and dispatch
|
|
4
|
-
* Maps fully-qualified resource kinds to their controller implementations
|
|
4
|
+
* Maps fully-qualified resource kinds to their controller implementations.
|
|
5
|
+
*
|
|
6
|
+
* Controllers are keyed by `(kind, runtimeFingerprint)` so that two
|
|
7
|
+
* `Telo.Import`s of the same library with different `runtime:` selections
|
|
8
|
+
* each get their own cached controller instance — the first winner does not
|
|
9
|
+
* lock out the second. Definitions remain kind-only; only the loaded
|
|
10
|
+
* controller instance is policy-scoped.
|
|
5
11
|
*/
|
|
6
12
|
export declare class ControllerRegistry {
|
|
7
13
|
private controllersByKind;
|
|
8
14
|
private definitionsByKind;
|
|
9
|
-
private controllerLoaders;
|
|
10
15
|
/**
|
|
11
16
|
* Register a controller definition
|
|
12
17
|
*/
|
|
13
18
|
registerDefinition(definition: ResourceDefinition): void;
|
|
14
19
|
/**
|
|
15
|
-
* Get a controller instance for a kind
|
|
16
|
-
*
|
|
17
|
-
*
|
|
20
|
+
* Get a controller instance for a (kind, fingerprint) pair. Lookup order:
|
|
21
|
+
* 1. Exact match for the requested fingerprint (the common path).
|
|
22
|
+
* 2. The "default" fingerprint — kernel built-ins register here once and
|
|
23
|
+
* should be reachable from any module's fingerprinted lookup.
|
|
24
|
+
* 3. The first registered entry for this kind, regardless of fingerprint
|
|
25
|
+
* — handles the case of a root-context resource referencing a kind
|
|
26
|
+
* that an import loaded under its own runtime selection.
|
|
27
|
+
*
|
|
28
|
+
* Throws `ERR_CONTROLLER_NOT_LOADED` on full miss.
|
|
18
29
|
*/
|
|
19
|
-
getController(kind: string): ControllerInstance;
|
|
30
|
+
getController(kind: string, fingerprint?: string): ControllerInstance;
|
|
20
31
|
/**
|
|
21
|
-
* Safe get - returns undefined if controller not found
|
|
32
|
+
* Safe get - returns undefined if controller not found. Same fallback
|
|
33
|
+
* order as `getController`.
|
|
22
34
|
*/
|
|
23
|
-
getControllerOrUndefined(kind: string): ControllerInstance | undefined;
|
|
35
|
+
getControllerOrUndefined(kind: string, fingerprint?: string): ControllerInstance | undefined;
|
|
36
|
+
private lookup;
|
|
24
37
|
/**
|
|
25
|
-
* Check if
|
|
38
|
+
* Check if any controller exists for this kind (any fingerprint, or just a definition).
|
|
26
39
|
*/
|
|
27
40
|
hasController(kind: string): boolean;
|
|
28
41
|
/**
|
|
@@ -33,19 +46,16 @@ export declare class ControllerRegistry {
|
|
|
33
46
|
* Get all registered kinds
|
|
34
47
|
*/
|
|
35
48
|
getKinds(): string[];
|
|
36
|
-
getControllerKinds(): string[];
|
|
37
|
-
/**
|
|
38
|
-
* Create a resource instance using its controller
|
|
39
|
-
*/
|
|
40
|
-
create(kind: string, resource: RuntimeResource, ctx: any): Promise<any | null>;
|
|
41
49
|
/**
|
|
42
|
-
*
|
|
50
|
+
* Distinct kinds with at least one registered controller. Used by the boot
|
|
51
|
+
* register-hook loop, which fires once per kind regardless of fingerprint.
|
|
43
52
|
*/
|
|
44
|
-
|
|
53
|
+
getControllerKinds(): string[];
|
|
45
54
|
/**
|
|
46
|
-
*
|
|
55
|
+
* Register a controller for a (kind, fingerprint). Multiple registrations
|
|
56
|
+
* for the same kind with different fingerprints coexist; same fingerprint
|
|
57
|
+
* overwrites the prior entry.
|
|
47
58
|
*/
|
|
48
|
-
|
|
49
|
-
private isModuleClass;
|
|
59
|
+
registerController(kind: string, controller: ControllerInstance, fingerprint?: string): void;
|
|
50
60
|
}
|
|
51
61
|
//# sourceMappingURL=controller-registry.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"controller-registry.d.ts","sourceRoot":"","sources":["../src/controller-registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,
|
|
1
|
+
{"version":3,"file":"controller-registry.d.ts","sourceRoot":"","sources":["../src/controller-registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAgB,MAAM,cAAc,CAAC;AAIpF;;;;;;;;;GASG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,iBAAiB,CAA2D;IACpF,OAAO,CAAC,iBAAiB,CAA8C;IAEvE;;OAEG;IACH,kBAAkB,CAAC,UAAU,EAAE,kBAAkB,GAAG,IAAI;IAOxD;;;;;;;;;;OAUG;IACH,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,GAAE,MAA4B,GAAG,kBAAkB;IAW1F;;;OAGG;IACH,wBAAwB,CACtB,IAAI,EAAE,MAAM,EACZ,WAAW,GAAE,MAA4B,GACxC,kBAAkB,GAAG,SAAS;IAIjC,OAAO,CAAC,MAAM;IAUd;;OAEG;IACH,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAIpC;;OAEG;IACH,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS;IAI3D;;OAEG;IACH,QAAQ,IAAI,MAAM,EAAE;IAIpB;;;OAGG;IACH,kBAAkB,IAAI,MAAM,EAAE;IAI9B;;;;OAIG;IACH,kBAAkB,CAChB,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,kBAAkB,EAC9B,WAAW,GAAE,MAA4B,GACxC,IAAI;CAkBR"}
|
|
@@ -1,64 +1,64 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { RuntimeError } from "@telorun/sdk";
|
|
2
|
+
const DEFAULT_FINGERPRINT = "default";
|
|
2
3
|
/**
|
|
3
4
|
* ControllerRegistry: Manages controller loading and dispatch
|
|
4
|
-
* Maps fully-qualified resource kinds to their controller implementations
|
|
5
|
+
* Maps fully-qualified resource kinds to their controller implementations.
|
|
6
|
+
*
|
|
7
|
+
* Controllers are keyed by `(kind, runtimeFingerprint)` so that two
|
|
8
|
+
* `Telo.Import`s of the same library with different `runtime:` selections
|
|
9
|
+
* each get their own cached controller instance — the first winner does not
|
|
10
|
+
* lock out the second. Definitions remain kind-only; only the loaded
|
|
11
|
+
* controller instance is policy-scoped.
|
|
5
12
|
*/
|
|
6
13
|
export class ControllerRegistry {
|
|
7
14
|
constructor() {
|
|
8
15
|
this.controllersByKind = new Map();
|
|
9
16
|
this.definitionsByKind = new Map();
|
|
10
|
-
this.controllerLoaders = new Map();
|
|
11
17
|
}
|
|
12
18
|
/**
|
|
13
19
|
* Register a controller definition
|
|
14
20
|
*/
|
|
15
21
|
registerDefinition(definition) {
|
|
16
|
-
// Construct fully qualified kind: Namespace.Name
|
|
17
|
-
// Only add namespace if name is not already qualified (doesn't contain a dot)
|
|
18
22
|
const namespace = definition.metadata.module;
|
|
19
|
-
const baseDir = null;
|
|
20
23
|
const name = definition.metadata.name;
|
|
21
24
|
const kind = namespace && !name.includes(".") ? `${namespace}.${name}` : name;
|
|
22
25
|
this.definitionsByKind.set(kind, definition);
|
|
23
|
-
// If definition has controllers, register loader for them
|
|
24
|
-
if (definition.controllers && definition.controllers.length > 0 && baseDir) {
|
|
25
|
-
this.registerControllerLoader(kind, definition, baseDir);
|
|
26
|
-
}
|
|
27
26
|
}
|
|
28
27
|
/**
|
|
29
|
-
* Get a controller instance for a kind
|
|
30
|
-
*
|
|
31
|
-
*
|
|
28
|
+
* Get a controller instance for a (kind, fingerprint) pair. Lookup order:
|
|
29
|
+
* 1. Exact match for the requested fingerprint (the common path).
|
|
30
|
+
* 2. The "default" fingerprint — kernel built-ins register here once and
|
|
31
|
+
* should be reachable from any module's fingerprinted lookup.
|
|
32
|
+
* 3. The first registered entry for this kind, regardless of fingerprint
|
|
33
|
+
* — handles the case of a root-context resource referencing a kind
|
|
34
|
+
* that an import loaded under its own runtime selection.
|
|
35
|
+
*
|
|
36
|
+
* Throws `ERR_CONTROLLER_NOT_LOADED` on full miss.
|
|
32
37
|
*/
|
|
33
|
-
getController(kind) {
|
|
34
|
-
|
|
35
|
-
if (
|
|
36
|
-
return
|
|
38
|
+
getController(kind, fingerprint = DEFAULT_FINGERPRINT) {
|
|
39
|
+
const cached = this.lookup(kind, fingerprint);
|
|
40
|
+
if (cached) {
|
|
41
|
+
return cached;
|
|
37
42
|
}
|
|
38
|
-
|
|
39
|
-
// const loader = this.controllerLoaders.get(kind);
|
|
40
|
-
// if (loader) {
|
|
41
|
-
// const controller = await loader();
|
|
42
|
-
// this.controllersByKind.set(kind, controller);
|
|
43
|
-
// return controller;
|
|
44
|
-
// }
|
|
45
|
-
return {
|
|
46
|
-
schema: { type: "object", additionalProperties: false },
|
|
47
|
-
};
|
|
48
|
-
// throw new Error(`No controller registered for kind: ${kind}`);
|
|
43
|
+
throw new RuntimeError("ERR_CONTROLLER_NOT_LOADED", `No controller loaded for kind "${kind}" (runtime fingerprint "${fingerprint}"). The kind's Telo.Definition must init before its controller is consulted.`);
|
|
49
44
|
}
|
|
50
45
|
/**
|
|
51
|
-
* Safe get - returns undefined if controller not found
|
|
46
|
+
* Safe get - returns undefined if controller not found. Same fallback
|
|
47
|
+
* order as `getController`.
|
|
52
48
|
*/
|
|
53
|
-
getControllerOrUndefined(kind) {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
49
|
+
getControllerOrUndefined(kind, fingerprint = DEFAULT_FINGERPRINT) {
|
|
50
|
+
return this.lookup(kind, fingerprint);
|
|
51
|
+
}
|
|
52
|
+
lookup(kind, fingerprint) {
|
|
53
|
+
const byFp = this.controllersByKind.get(kind);
|
|
54
|
+
if (!byFp)
|
|
55
|
+
return undefined;
|
|
56
|
+
return (byFp.get(fingerprint) ??
|
|
57
|
+
byFp.get(DEFAULT_FINGERPRINT) ??
|
|
58
|
+
byFp.values().next().value);
|
|
59
59
|
}
|
|
60
60
|
/**
|
|
61
|
-
* Check if
|
|
61
|
+
* Check if any controller exists for this kind (any fingerprint, or just a definition).
|
|
62
62
|
*/
|
|
63
63
|
hasController(kind) {
|
|
64
64
|
return this.controllersByKind.has(kind) || this.definitionsByKind.has(kind);
|
|
@@ -75,27 +75,22 @@ export class ControllerRegistry {
|
|
|
75
75
|
getKinds() {
|
|
76
76
|
return Array.from(this.definitionsByKind.keys());
|
|
77
77
|
}
|
|
78
|
-
getControllerKinds() {
|
|
79
|
-
return Array.from(this.controllersByKind.keys());
|
|
80
|
-
}
|
|
81
78
|
/**
|
|
82
|
-
*
|
|
79
|
+
* Distinct kinds with at least one registered controller. Used by the boot
|
|
80
|
+
* register-hook loop, which fires once per kind regardless of fingerprint.
|
|
83
81
|
*/
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
if (!controller || !controller.create) {
|
|
87
|
-
return null;
|
|
88
|
-
}
|
|
89
|
-
return controller.create(resource, ctx);
|
|
82
|
+
getControllerKinds() {
|
|
83
|
+
return Array.from(this.controllersByKind.keys());
|
|
90
84
|
}
|
|
91
85
|
/**
|
|
92
|
-
* Register a controller for a kind
|
|
86
|
+
* Register a controller for a (kind, fingerprint). Multiple registrations
|
|
87
|
+
* for the same kind with different fingerprints coexist; same fingerprint
|
|
88
|
+
* overwrites the prior entry.
|
|
93
89
|
*/
|
|
94
|
-
registerController(kind, controller) {
|
|
90
|
+
registerController(kind, controller, fingerprint = DEFAULT_FINGERPRINT) {
|
|
95
91
|
if (!this.definitionsByKind.has(kind)) {
|
|
96
92
|
throw new Error(`Cannot register controller for kind ${kind} without definition`);
|
|
97
93
|
}
|
|
98
|
-
// Ensure controller has schema from definition
|
|
99
94
|
const definition = this.definitionsByKind.get(kind);
|
|
100
95
|
const wrappedController = {
|
|
101
96
|
...controller,
|
|
@@ -103,56 +98,12 @@ export class ControllerRegistry {
|
|
|
103
98
|
inputType: controller.inputType,
|
|
104
99
|
outputType: controller.outputType,
|
|
105
100
|
};
|
|
106
|
-
this.controllersByKind.
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
const controllerDef = definition.controllers?.[0]; // Use first matching controller for now
|
|
113
|
-
if (!controllerDef)
|
|
114
|
-
return;
|
|
115
|
-
this.controllerLoaders.set(kind, async () => {
|
|
116
|
-
const modulePath = path.resolve(moduleDir, controllerDef.entry);
|
|
117
|
-
const moduleRuntime = await import(modulePath);
|
|
118
|
-
const exported = moduleRuntime.default || moduleRuntime.Module || moduleRuntime;
|
|
119
|
-
const registerFn = typeof moduleRuntime.register === "function"
|
|
120
|
-
? moduleRuntime.register
|
|
121
|
-
: typeof exported === "function" && !this.isModuleClass(exported)
|
|
122
|
-
? exported
|
|
123
|
-
: null;
|
|
124
|
-
const createFn = typeof moduleRuntime.create === "function"
|
|
125
|
-
? moduleRuntime.create
|
|
126
|
-
: typeof exported?.create === "function"
|
|
127
|
-
? exported.create
|
|
128
|
-
: null;
|
|
129
|
-
const executeFn = typeof moduleRuntime.execute === "function"
|
|
130
|
-
? moduleRuntime.execute
|
|
131
|
-
: typeof exported?.execute === "function"
|
|
132
|
-
? exported.execute
|
|
133
|
-
: null;
|
|
134
|
-
const compileFn = typeof moduleRuntime.compile === "function"
|
|
135
|
-
? moduleRuntime.compile
|
|
136
|
-
: typeof exported?.compile === "function"
|
|
137
|
-
? exported.compile
|
|
138
|
-
: null;
|
|
139
|
-
if (!registerFn && !executeFn && !createFn && !compileFn) {
|
|
140
|
-
throw new Error(`Controller for "${kind}" exports no usable handlers`);
|
|
141
|
-
}
|
|
142
|
-
if (!definition.schema) {
|
|
143
|
-
throw new Error(`Definition for "${kind}" does not have schema`);
|
|
144
|
-
}
|
|
145
|
-
return {
|
|
146
|
-
register: registerFn ?? undefined,
|
|
147
|
-
create: createFn ?? undefined,
|
|
148
|
-
execute: executeFn ?? undefined,
|
|
149
|
-
compile: compileFn ?? undefined,
|
|
150
|
-
schema: definition.schema,
|
|
151
|
-
};
|
|
152
|
-
});
|
|
153
|
-
}
|
|
154
|
-
isModuleClass(obj) {
|
|
155
|
-
return (typeof obj === "function" && (obj.name === "Controller" || obj.toString().includes("class")));
|
|
101
|
+
let byFp = this.controllersByKind.get(kind);
|
|
102
|
+
if (!byFp) {
|
|
103
|
+
byFp = new Map();
|
|
104
|
+
this.controllersByKind.set(kind, byFp);
|
|
105
|
+
}
|
|
106
|
+
byFp.set(fingerprint, wrappedController);
|
|
156
107
|
}
|
|
157
108
|
}
|
|
158
109
|
//# sourceMappingURL=controller-registry.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"controller-registry.js","sourceRoot":"","sources":["../src/controller-registry.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"controller-registry.js","sourceRoot":"","sources":["../src/controller-registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -28,6 +28,17 @@ export declare const schema: {
|
|
|
28
28
|
secrets: {
|
|
29
29
|
type: string;
|
|
30
30
|
};
|
|
31
|
+
runtime: {
|
|
32
|
+
oneOf: ({
|
|
33
|
+
type: string;
|
|
34
|
+
items?: undefined;
|
|
35
|
+
} | {
|
|
36
|
+
type: string;
|
|
37
|
+
items: {
|
|
38
|
+
type: string;
|
|
39
|
+
};
|
|
40
|
+
})[];
|
|
41
|
+
};
|
|
31
42
|
};
|
|
32
43
|
required: string[];
|
|
33
44
|
additionalProperties: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"import-controller.d.ts","sourceRoot":"","sources":["../../../src/controllers/module/import-controller.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"import-controller.d.ts","sourceRoot":"","sources":["../../../src/controllers/module/import-controller.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAqBtE,wBAAsB,MAAM,CAAC,QAAQ,EAAE,GAAG,EAAE,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA6H3F;AAeD,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyBlB,CAAC"}
|