@telorun/kernel 0.62.0 → 0.63.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 +4 -0
- package/dist/controller-loader.d.ts.map +1 -1
- package/dist/controller-loader.js +1 -1
- package/dist/controller-loader.js.map +1 -1
- package/dist/controller-loaders/bundle-loader.d.ts +21 -0
- package/dist/controller-loaders/bundle-loader.d.ts.map +1 -1
- package/dist/controller-loaders/bundle-loader.js +97 -17
- package/dist/controller-loaders/bundle-loader.js.map +1 -1
- package/dist/controller-loaders/source-bundle-builder.d.ts +30 -0
- package/dist/controller-loaders/source-bundle-builder.d.ts.map +1 -0
- package/dist/controller-loaders/source-bundle-builder.js +302 -0
- package/dist/controller-loaders/source-bundle-builder.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 +9 -2
- package/dist/controllers/resource-definition/resource-definition-controller.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/kernel.d.ts +9 -0
- package/dist/kernel.d.ts.map +1 -1
- package/dist/kernel.js +7 -0
- package/dist/kernel.js.map +1 -1
- package/dist/logging/file-sink.js +1 -1
- package/dist/logging/file-sink.js.map +1 -1
- package/dist/logging/index.d.ts +1 -1
- package/dist/logging/index.d.ts.map +1 -1
- package/dist/logging/index.js +1 -1
- package/dist/logging/index.js.map +1 -1
- package/dist/logging/log-sink.d.ts +1 -1
- package/dist/logging/log-sink.d.ts.map +1 -1
- package/dist/logging/log-sink.js +1 -1
- package/dist/logging/log-sink.js.map +1 -1
- package/dist/resource-context.d.ts +11 -1
- package/dist/resource-context.d.ts.map +1 -1
- package/dist/resource-context.js +22 -2
- package/dist/resource-context.js.map +1 -1
- package/dist/runtime-seam.d.ts +19 -0
- package/dist/runtime-seam.d.ts.map +1 -0
- package/dist/runtime-seam.js +211 -0
- package/dist/runtime-seam.js.map +1 -0
- package/package.json +4 -4
- package/src/controller-loader.ts +5 -1
- package/src/controller-loaders/bundle-loader.ts +108 -23
- package/src/controller-loaders/source-bundle-builder.ts +337 -0
- package/src/controllers/resource-definition/resource-definition-controller.ts +23 -17
- package/src/index.ts +1 -0
- package/src/kernel.ts +13 -0
- package/src/logging/file-sink.ts +1 -1
- package/src/logging/index.ts +1 -1
- package/src/logging/log-sink.ts +1 -0
- package/src/resource-context.ts +23 -0
- package/src/runtime-seam.ts +230 -0
- package/dist/logging/record-buffer.d.ts +0 -24
- package/dist/logging/record-buffer.d.ts.map +0 -1
- package/dist/logging/record-buffer.js +0 -78
- package/dist/logging/record-buffer.js.map +0 -1
- package/src/logging/record-buffer.ts +0 -72
|
@@ -79,6 +79,10 @@ export interface ControllerLoaderOptions {
|
|
|
79
79
|
* single `resolveCacheRoot`. Overrides the entry-anchored default so a
|
|
80
80
|
* relocated `TELO_CACHE_DIR` is honoured. */
|
|
81
81
|
installRoot?: string;
|
|
82
|
+
/** The `.telo` cache root for this load. The bundle loader caches a dev build
|
|
83
|
+
* of a local module's controller source under it; absent simply disables that
|
|
84
|
+
* path, leaving a prebuilt `path=` to load. */
|
|
85
|
+
cacheRoot?: string;
|
|
82
86
|
/** Where the sub-loaders' diagnostics go — install-lock waits, bundle skips.
|
|
83
87
|
* Threaded from `ctx.log` so §13.1 holds (no direct `process.stderr`), and so
|
|
84
88
|
* the bundle-skip diagnostics that replaced `TELO_BUNDLE_DEBUG` actually reach
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"controller-loader.d.ts","sourceRoot":"","sources":["../src/controller-loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAgB,KAAK,MAAM,EAAE,MAAM,cAAc,CAAC;AAE7E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAGlE,OAAO,EAAE,gBAAgB,EAAmC,MAAM,uBAAuB,CAAC;AAE1F,YAAY,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAE9D;;;;;;;;GAQG;AACH,MAAM,MAAM,uBAAuB,GAC/B,OAAO,GACP,cAAc,GACd,OAAO,GACP,aAAa,GACb,aAAa,GACb,QAAQ,CAAC;AAEb;;;;;;GAMG;AACH,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,uBAAuB,CAAC;IAChC,cAAc,EAAE,MAAM,OAAO,CAAC,kBAAkB,CAAC,CAAC;CACnD;AAED,MAAM,MAAM,qBAAqB,GAC7B;IAAE,IAAI,EAAE,mBAAmB,CAAC;IAAC,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,GACxD;IACE,IAAI,EAAE,kBAAkB,CAAC;IACzB,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,uBAAuB,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;CAChF,GACD;IAAE,IAAI,EAAE,sBAAsB,CAAC;IAAC,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE;AAC5E;;;;;;GAMG;GACD;IAAE,IAAI,EAAE,uBAAuB,CAAC;IAAC,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAAC;AAEjF;;;;;;GAMG;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,KAAK,EAAE,qBAAqB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAE1F,MAAM,WAAW,uBAAuB;IACtC,IAAI,CAAC,EAAE,oBAAoB,CAAC;IAC5B;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;kDAE8C;IAC9C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;2DAGuD;IACvD,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAmC;IACxD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAsB;IAChD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAuB;IAClD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAyB;gBAE1C,OAAO,GAAE,uBAA4B;IAW3C,IAAI,CACR,cAAc,EAAE,MAAM,EAAE,EACxB,OAAO,EAAE,MAAM,EACf,MAAM,CAAC,EAAE,gBAAgB,EACzB,QAAQ,CAAC,EAAE,cAAc,GACxB,OAAO,CAAC,kBAAkB,CAAC;IAqD9B;;;;;;;;;;;;OAYG;IACG,OAAO,CACX,cAAc,EAAE,MAAM,EAAE,EACxB,OAAO,EAAE,MAAM,EACf,MAAM,CAAC,EAAE,gBAAgB,EACzB,QAAQ,CAAC,EAAE,cAAc,GACxB,OAAO,CAAC,kBAAkB,CAAC;YA+BhB,WAAW;YASX,kBAAkB;CAgBjC"}
|
|
1
|
+
{"version":3,"file":"controller-loader.d.ts","sourceRoot":"","sources":["../src/controller-loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAgB,KAAK,MAAM,EAAE,MAAM,cAAc,CAAC;AAE7E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAGlE,OAAO,EAAE,gBAAgB,EAAmC,MAAM,uBAAuB,CAAC;AAE1F,YAAY,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAE9D;;;;;;;;GAQG;AACH,MAAM,MAAM,uBAAuB,GAC/B,OAAO,GACP,cAAc,GACd,OAAO,GACP,aAAa,GACb,aAAa,GACb,QAAQ,CAAC;AAEb;;;;;;GAMG;AACH,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,uBAAuB,CAAC;IAChC,cAAc,EAAE,MAAM,OAAO,CAAC,kBAAkB,CAAC,CAAC;CACnD;AAED,MAAM,MAAM,qBAAqB,GAC7B;IAAE,IAAI,EAAE,mBAAmB,CAAC;IAAC,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,GACxD;IACE,IAAI,EAAE,kBAAkB,CAAC;IACzB,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,uBAAuB,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;CAChF,GACD;IAAE,IAAI,EAAE,sBAAsB,CAAC;IAAC,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE;AAC5E;;;;;;GAMG;GACD;IAAE,IAAI,EAAE,uBAAuB,CAAC;IAAC,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAAC;AAEjF;;;;;;GAMG;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,KAAK,EAAE,qBAAqB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAE1F,MAAM,WAAW,uBAAuB;IACtC,IAAI,CAAC,EAAE,oBAAoB,CAAC;IAC5B;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;kDAE8C;IAC9C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;oDAEgD;IAChD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;2DAGuD;IACvD,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAmC;IACxD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAsB;IAChD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAuB;IAClD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAyB;gBAE1C,OAAO,GAAE,uBAA4B;IAW3C,IAAI,CACR,cAAc,EAAE,MAAM,EAAE,EACxB,OAAO,EAAE,MAAM,EACf,MAAM,CAAC,EAAE,gBAAgB,EACzB,QAAQ,CAAC,EAAE,cAAc,GACxB,OAAO,CAAC,kBAAkB,CAAC;IAqD9B;;;;;;;;;;;;OAYG;IACG,OAAO,CACX,cAAc,EAAE,MAAM,EAAE,EACxB,OAAO,EAAE,MAAM,EACf,MAAM,CAAC,EAAE,gBAAgB,EACzB,QAAQ,CAAC,EAAE,cAAc,GACxB,OAAO,CAAC,kBAAkB,CAAC;YA+BhB,WAAW;YASX,kBAAkB;CAgBjC"}
|
|
@@ -30,7 +30,7 @@ export class ControllerLoader {
|
|
|
30
30
|
if (options.log)
|
|
31
31
|
this.npmLoader.setLogger(options.log);
|
|
32
32
|
this.napiLoader = new NapiControllerLoader();
|
|
33
|
-
this.bundleLoader = new BundleControllerLoader();
|
|
33
|
+
this.bundleLoader = new BundleControllerLoader(options.cacheRoot);
|
|
34
34
|
}
|
|
35
35
|
async load(purlCandidates, baseUri, policy, artifact) {
|
|
36
36
|
if (!purlCandidates || purlCandidates.length === 0) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"controller-loader.js","sourceRoot":"","sources":["../src/controller-loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,YAAY,EAAe,MAAM,cAAc,CAAC;AAC7E,OAAO,EAAE,sBAAsB,EAAE,MAAM,uCAAuC,CAAC;AAE/E,OAAO,EAAE,yBAAyB,EAAE,oBAAoB,EAAE,MAAM,qCAAqC,CAAC;AACtG,OAAO,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AACzE,OAAO,EAAoB,cAAc,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"controller-loader.js","sourceRoot":"","sources":["../src/controller-loader.ts"],"names":[],"mappings":"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"}
|
|
@@ -22,7 +22,16 @@ import type { ControllerResolveSource } from "../controller-loader.js";
|
|
|
22
22
|
* (or `[pkg:telo …, pkg:npm …]`) falls through to a candidate this — or
|
|
23
23
|
* another runtime's — kernel can load.
|
|
24
24
|
* - `path` — the file in the bundle; `#export` — the named export.
|
|
25
|
+
* - `local_path` — the TypeScript source `path=` was built from. Present only
|
|
26
|
+
* while the module is a working copy; a published artifact ships no `src/`.
|
|
27
|
+
* When the module arrives with **no artifact handle** and the source resolves
|
|
28
|
+
* on disk, the loader builds it (see `source-bundle-builder.ts`) rather than
|
|
29
|
+
* importing `path=`, so editing a controller and re-running picks the edit up
|
|
30
|
+
* with no build step. The guard is the absence of an artifact, not the shape
|
|
31
|
+
* of the base URI: a published module served from the on-disk manifest cache
|
|
32
|
+
* has a local base too, and its payload is the layer regardless.
|
|
25
33
|
*
|
|
34
|
+
|
|
26
35
|
* Two separate concerns for `js` bundles importing `@telorun/sdk`:
|
|
27
36
|
* - *Resolution* — the bare specifier must point at a real file. The bundle has
|
|
28
37
|
* no node_modules, so `ensureRealmSymlinks()` symlinks the realm-collapse
|
|
@@ -38,6 +47,11 @@ import type { ControllerResolveSource } from "../controller-loader.js";
|
|
|
38
47
|
* through); a bundle that loads but is malformed is a hard `ERR_CONTROLLER_INVALID`.
|
|
39
48
|
*/
|
|
40
49
|
export declare class BundleControllerLoader {
|
|
50
|
+
private readonly cacheRoot?;
|
|
51
|
+
/** Where a dev build from `local_path` is cached (`<cache-root>/controller-src`).
|
|
52
|
+
* Absent for callers that resolved no cache root, which simply disables the
|
|
53
|
+
* source path — a prebuilt `path=` still loads. */
|
|
54
|
+
constructor(cacheRoot?: string | undefined);
|
|
41
55
|
load(purl: string, baseUri: string, artifact?: ModuleArtifact): Promise<{
|
|
42
56
|
instance: ControllerInstance;
|
|
43
57
|
source: ControllerResolveSource;
|
|
@@ -53,5 +67,12 @@ export declare class BundleControllerLoader {
|
|
|
53
67
|
source: ControllerResolveSource;
|
|
54
68
|
importInstance: () => Promise<ControllerInstance>;
|
|
55
69
|
}>;
|
|
70
|
+
/** The `local_path` source this candidate names, resolved against the declaring
|
|
71
|
+
* module's directory — or `undefined` when the candidate declares none, or the
|
|
72
|
+
* module is not on disk to resolve it against. */
|
|
73
|
+
private localSourceFile;
|
|
74
|
+
/** Directory of the declaring module's manifest. Only meaningful for a local
|
|
75
|
+
* base; callers gate on {@link isLocalBase} first. */
|
|
76
|
+
private moduleDir;
|
|
56
77
|
}
|
|
57
78
|
//# sourceMappingURL=bundle-loader.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bundle-loader.d.ts","sourceRoot":"","sources":["../../src/controller-loaders/bundle-loader.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAgB,MAAM,cAAc,CAAC;AAOhE,OAAO,EAAsB,KAAK,cAAc,EAAE,MAAM,8BAA8B,CAAC;AACvF,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"bundle-loader.d.ts","sourceRoot":"","sources":["../../src/controller-loaders/bundle-loader.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAgB,MAAM,cAAc,CAAC;AAOhE,OAAO,EAAsB,KAAK,cAAc,EAAE,MAAM,8BAA8B,CAAC;AACvF,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAuGvE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,qBAAa,sBAAsB;IAIrB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC;IAHvC;;wDAEoD;gBACvB,SAAS,CAAC,EAAE,MAAM,YAAA;IAEzC,IAAI,CACR,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,QAAQ,CAAC,EAAE,cAAc,GACxB,OAAO,CAAC;QAAE,QAAQ,EAAE,kBAAkB,CAAC;QAAC,MAAM,EAAE,uBAAuB,CAAA;KAAE,CAAC;IAK7E;;;;;;OAMG;IACG,OAAO,CACX,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,QAAQ,CAAC,EAAE,cAAc,GACxB,OAAO,CAAC;QAAE,MAAM,EAAE,uBAAuB,CAAC;QAAC,cAAc,EAAE,MAAM,OAAO,CAAC,kBAAkB,CAAC,CAAA;KAAE,CAAC;IAsJlG;;uDAEmD;IACnD,OAAO,CAAC,eAAe;IAMvB;2DACuD;IACvD,OAAO,CAAC,SAAS;CAGlB"}
|
|
@@ -9,6 +9,7 @@ import { fileURLToPath, pathToFileURL } from "url";
|
|
|
9
9
|
import { hostPlatformTarget } from "../bundle/module-artifact.js";
|
|
10
10
|
import { ControllerEnvMissingError } from "./napi-loader.js";
|
|
11
11
|
import { REALM_COLLAPSE_NAMES } from "./realm.js";
|
|
12
|
+
import { buildControllerFromSource, canBuildFromSource } from "./source-bundle-builder.js";
|
|
12
13
|
/** A base URI whose files are already on disk: a `file://` URL or a bare
|
|
13
14
|
* absolute path. Everything else (`oci://`, `http(s)://`, `memory://`) names a
|
|
14
15
|
* module whose payload only exists inside an artifact. */
|
|
@@ -136,7 +137,16 @@ function findPackageRoot(entryFile, name) {
|
|
|
136
137
|
* (or `[pkg:telo …, pkg:npm …]`) falls through to a candidate this — or
|
|
137
138
|
* another runtime's — kernel can load.
|
|
138
139
|
* - `path` — the file in the bundle; `#export` — the named export.
|
|
140
|
+
* - `local_path` — the TypeScript source `path=` was built from. Present only
|
|
141
|
+
* while the module is a working copy; a published artifact ships no `src/`.
|
|
142
|
+
* When the module arrives with **no artifact handle** and the source resolves
|
|
143
|
+
* on disk, the loader builds it (see `source-bundle-builder.ts`) rather than
|
|
144
|
+
* importing `path=`, so editing a controller and re-running picks the edit up
|
|
145
|
+
* with no build step. The guard is the absence of an artifact, not the shape
|
|
146
|
+
* of the base URI: a published module served from the on-disk manifest cache
|
|
147
|
+
* has a local base too, and its payload is the layer regardless.
|
|
139
148
|
*
|
|
149
|
+
|
|
140
150
|
* Two separate concerns for `js` bundles importing `@telorun/sdk`:
|
|
141
151
|
* - *Resolution* — the bare specifier must point at a real file. The bundle has
|
|
142
152
|
* no node_modules, so `ensureRealmSymlinks()` symlinks the realm-collapse
|
|
@@ -152,6 +162,12 @@ function findPackageRoot(entryFile, name) {
|
|
|
152
162
|
* through); a bundle that loads but is malformed is a hard `ERR_CONTROLLER_INVALID`.
|
|
153
163
|
*/
|
|
154
164
|
export class BundleControllerLoader {
|
|
165
|
+
/** Where a dev build from `local_path` is cached (`<cache-root>/controller-src`).
|
|
166
|
+
* Absent for callers that resolved no cache root, which simply disables the
|
|
167
|
+
* source path — a prebuilt `path=` still loads. */
|
|
168
|
+
constructor(cacheRoot) {
|
|
169
|
+
this.cacheRoot = cacheRoot;
|
|
170
|
+
}
|
|
155
171
|
async load(purl, baseUri, artifact) {
|
|
156
172
|
const { source, importInstance } = await this.resolve(purl, baseUri, artifact);
|
|
157
173
|
return { instance: await importInstance(), source };
|
|
@@ -198,6 +214,55 @@ export class BundleControllerLoader {
|
|
|
198
214
|
`match this host (${host.os ?? "unknown os"}/${host.arch ?? "unknown arch"}` +
|
|
199
215
|
`${host.libc ? `/${host.libc}` : ""})`);
|
|
200
216
|
}
|
|
217
|
+
const fragment = parsed.subpath;
|
|
218
|
+
// Dev path: a module that is a working copy — no artifact behind it — with a
|
|
219
|
+
// `local_path` source on disk is built from that source, because the source
|
|
220
|
+
// is what is authoritative there. An artifact means the payload IS the layer,
|
|
221
|
+
// so this never fires for a published module, including one served from the
|
|
222
|
+
// on-disk manifest cache (whose base is local but whose payload is a layer).
|
|
223
|
+
//
|
|
224
|
+
// esbuild is probed HERE rather than inside the build. It is an optional
|
|
225
|
+
// dependency so that an install skipping optionals still runs published
|
|
226
|
+
// artifacts — and a working copy that has run its build script has the same
|
|
227
|
+
// prebuilt file on disk. Deciding it lazily would turn "no bundler" into a
|
|
228
|
+
// hard failure standing next to a perfectly good bundle, and the candidate
|
|
229
|
+
// list could not rescue it: the fallback belongs to this same PURL, not to a
|
|
230
|
+
// sibling candidate.
|
|
231
|
+
const cacheRoot = this.cacheRoot;
|
|
232
|
+
const sourceFile = artifact ? undefined : this.localSourceFile(parsed, baseUri);
|
|
233
|
+
const buildFromSource = sourceFile !== undefined &&
|
|
234
|
+
cacheRoot !== undefined &&
|
|
235
|
+
(await pathExists(sourceFile)) &&
|
|
236
|
+
(await canBuildFromSource());
|
|
237
|
+
if (buildFromSource) {
|
|
238
|
+
// The same file the prebuilt branch would import, kept as the fallback for
|
|
239
|
+
// an environment that stops being able to build between resolve and first
|
|
240
|
+
// instantiation.
|
|
241
|
+
const prebuilt = path.resolve(this.moduleDir(baseUri), relPath);
|
|
242
|
+
return {
|
|
243
|
+
source: "local",
|
|
244
|
+
// Deferred like every other branch: the build is paid on the kind's
|
|
245
|
+
// first instantiation, so a manifest pays only for the kinds it uses.
|
|
246
|
+
// A build FAILURE is user code and propagates unchanged; only a missing
|
|
247
|
+
// *environment* falls back, and only to a file that is actually there.
|
|
248
|
+
importInstance: async () => {
|
|
249
|
+
let built;
|
|
250
|
+
try {
|
|
251
|
+
built = await buildControllerFromSource(sourceFile, cacheRoot);
|
|
252
|
+
}
|
|
253
|
+
catch (err) {
|
|
254
|
+
if (!(err instanceof ControllerEnvMissingError))
|
|
255
|
+
throw err;
|
|
256
|
+
if (!(await pathExists(prebuilt)))
|
|
257
|
+
throw err;
|
|
258
|
+
await ensureRealmSymlinks(path.dirname(prebuilt));
|
|
259
|
+
return importControllerModule(prebuilt, purl, fragment);
|
|
260
|
+
}
|
|
261
|
+
await ensureRealmSymlinks(path.dirname(built));
|
|
262
|
+
return importControllerModule(built, purl, fragment);
|
|
263
|
+
},
|
|
264
|
+
};
|
|
265
|
+
}
|
|
201
266
|
// A published module's payload lives in its artifact, so materialize the one
|
|
202
267
|
// layer carrying this candidate and resolve `path=` inside it. Nothing is
|
|
203
268
|
// fetched here: the artifact handle owns the pinned ref and the verified
|
|
@@ -236,26 +301,41 @@ export class BundleControllerLoader {
|
|
|
236
301
|
// Make bare `@telorun/sdk` (etc.) resolve to the kernel's copy before
|
|
237
302
|
// importing the bundle, so authors write normal imports.
|
|
238
303
|
await ensureRealmSymlinks(path.dirname(absFile));
|
|
239
|
-
const fragment = parsed.subpath;
|
|
240
304
|
return {
|
|
241
305
|
source,
|
|
242
|
-
importInstance:
|
|
243
|
-
// A broken bundle (syntax / failed import) is a real user-code failure —
|
|
244
|
-
// let it propagate rather than masking it as env-missing.
|
|
245
|
-
const mod = (await import(pathToFileURL(absFile).href));
|
|
246
|
-
// Distinguish "no such export" from "export isn't a controller" so the
|
|
247
|
-
// error points at the actual problem (mirrors the napi loader's project()).
|
|
248
|
-
if (fragment && !(fragment in mod)) {
|
|
249
|
-
throw new RuntimeError("ERR_CONTROLLER_INVALID", `Bundled controller "${purl}": module "${absFile}" has no export named "${fragment}"`);
|
|
250
|
-
}
|
|
251
|
-
const instance = fragment ? mod[fragment] : mod;
|
|
252
|
-
if (!instance || (!instance.create && !instance.register)) {
|
|
253
|
-
throw new RuntimeError("ERR_CONTROLLER_INVALID", `Bundled controller "${purl}" exports neither create() nor register()` +
|
|
254
|
-
(fragment ? ` at fragment "#${fragment}"` : ""));
|
|
255
|
-
}
|
|
256
|
-
return instance;
|
|
257
|
-
},
|
|
306
|
+
importInstance: () => importControllerModule(absFile, purl, fragment),
|
|
258
307
|
};
|
|
259
308
|
}
|
|
309
|
+
/** The `local_path` source this candidate names, resolved against the declaring
|
|
310
|
+
* module's directory — or `undefined` when the candidate declares none, or the
|
|
311
|
+
* module is not on disk to resolve it against. */
|
|
312
|
+
localSourceFile(parsed, baseUri) {
|
|
313
|
+
const localPath = parsed.qualifiers?.local_path;
|
|
314
|
+
if (!localPath || !isLocalBase(baseUri))
|
|
315
|
+
return undefined;
|
|
316
|
+
return path.resolve(this.moduleDir(baseUri), localPath);
|
|
317
|
+
}
|
|
318
|
+
/** Directory of the declaring module's manifest. Only meaningful for a local
|
|
319
|
+
* base; callers gate on {@link isLocalBase} first. */
|
|
320
|
+
moduleDir(baseUri) {
|
|
321
|
+
return path.dirname(baseUri.startsWith("file://") ? fileURLToPath(baseUri) : baseUri);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
/** Import a built bundle and project out the controller the fragment names. A
|
|
325
|
+
* broken bundle (syntax error, failed import) is a real user-code failure and
|
|
326
|
+
* propagates; it is never masked as env-missing. */
|
|
327
|
+
async function importControllerModule(absFile, purl, fragment) {
|
|
328
|
+
const mod = (await import(pathToFileURL(absFile).href));
|
|
329
|
+
// Distinguish "no such export" from "export isn't a controller" so the error
|
|
330
|
+
// points at the actual problem (mirrors the napi loader's project()).
|
|
331
|
+
if (fragment && !(fragment in mod)) {
|
|
332
|
+
throw new RuntimeError("ERR_CONTROLLER_INVALID", `Bundled controller "${purl}": module "${absFile}" has no export named "${fragment}"`);
|
|
333
|
+
}
|
|
334
|
+
const instance = fragment ? mod[fragment] : mod;
|
|
335
|
+
if (!instance || (!instance.create && !instance.register)) {
|
|
336
|
+
throw new RuntimeError("ERR_CONTROLLER_INVALID", `Bundled controller "${purl}" exports neither create() nor register()` +
|
|
337
|
+
(fragment ? ` at fragment "#${fragment}"` : ""));
|
|
338
|
+
}
|
|
339
|
+
return instance;
|
|
260
340
|
}
|
|
261
341
|
//# sourceMappingURL=bundle-loader.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bundle-loader.js","sourceRoot":"","sources":["../../src/controller-loaders/bundle-loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAC9F,OAAO,EAAsB,YAAY,EAAE,MAAM,cAAc,CAAC;AAChE,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAC9C,OAAO,KAAK,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AACvC,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAuB,MAAM,8BAA8B,CAAC;AAEvF,OAAO,EAAE,yBAAyB,EAAE,MAAM,kBAAkB,CAAC;AAC7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"bundle-loader.js","sourceRoot":"","sources":["../../src/controller-loaders/bundle-loader.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether this host can build a controller from source at all.
|
|
3
|
+
*
|
|
4
|
+
* Asked at *resolve* time, not at build time, so the absence of esbuild selects
|
|
5
|
+
* the prebuilt `path=` file instead of failing the load. esbuild is an
|
|
6
|
+
* **optional** dependency precisely so an install that skips optionals still runs
|
|
7
|
+
* published artifacts — and a working copy that has run its build script has the
|
|
8
|
+
* same prebuilt file sitting there. Deciding this lazily inside the build would
|
|
9
|
+
* turn "no bundler" into a hard failure with a perfectly good bundle on disk.
|
|
10
|
+
*/
|
|
11
|
+
export declare function canBuildFromSource(): Promise<boolean>;
|
|
12
|
+
/**
|
|
13
|
+
* Every file the last build of `entryFile` actually read, from esbuild's own
|
|
14
|
+
* metafile — the module's sources, the shared TS libraries it inlines, and its
|
|
15
|
+
* dependency tree.
|
|
16
|
+
*
|
|
17
|
+
* Exported for watch mode, which needs exactly this set and cannot derive it:
|
|
18
|
+
* the bundle's inputs are a graph, so watching the entry point's directory both
|
|
19
|
+
* misses a shared library one directory over and sweeps in build output. Empty
|
|
20
|
+
* before the first build, when there is nothing to be stale about yet.
|
|
21
|
+
*/
|
|
22
|
+
export declare function lastBuildInputs(entryFile: string, cacheRoot: string): Promise<string[]>;
|
|
23
|
+
/**
|
|
24
|
+
* Return the path of a current bundle for `entryFile`, building it if the cache
|
|
25
|
+
* has none. Throws `ERR_CONTROLLER_BUILD_FAILED` when the source does not build —
|
|
26
|
+
* that is broken user code and must surface, never fall through to another
|
|
27
|
+
* candidate.
|
|
28
|
+
*/
|
|
29
|
+
export declare function buildControllerFromSource(entryFile: string, cacheRoot: string): Promise<string>;
|
|
30
|
+
//# sourceMappingURL=source-bundle-builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"source-bundle-builder.d.ts","sourceRoot":"","sources":["../../src/controller-loaders/source-bundle-builder.ts"],"names":[],"mappings":"AAuIA;;;;;;;;;GASG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,OAAO,CAAC,CAE3D;AAkDD;;;;;;;;;GASG;AACH,wBAAsB,eAAe,CACnC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,MAAM,EAAE,CAAC,CAGnB;AAgBD;;;;;GAKG;AACH,wBAAsB,yBAAyB,CAC7C,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,MAAM,CAAC,CAgBjB"}
|
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
import { RuntimeError } from "@telorun/sdk";
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
3
|
+
import * as fs from "node:fs/promises";
|
|
4
|
+
import * as path from "node:path";
|
|
5
|
+
import { ControllerEnvMissingError } from "./napi-loader.js";
|
|
6
|
+
import { REALM_COLLAPSE_NAMES } from "./realm.js";
|
|
7
|
+
/**
|
|
8
|
+
* Build a **local** module's bundled controller from its TypeScript source, so a
|
|
9
|
+
* fresh clone runs `telo run ./manifest.yaml` with no build step.
|
|
10
|
+
*
|
|
11
|
+
* This is the dev half of `pkg:telo/local/js?path=…&local_path=…`: `path=` names
|
|
12
|
+
* the prebuilt `.mjs` that ships in a published artifact, `local_path=` names the
|
|
13
|
+
* source it was built from. When the declaring module is on disk with no artifact
|
|
14
|
+
* behind it, the source is what is authoritative — a stale checked-in bundle
|
|
15
|
+
* would otherwise shadow the edit the author just made.
|
|
16
|
+
*
|
|
17
|
+
* Same shape the kernel already runs twice: `NapiControllerLoader` builds a crate
|
|
18
|
+
* from `local_path`, and `bundle-builder.ts` runs esbuild at load time over an npm
|
|
19
|
+
* controller's dependency tree.
|
|
20
|
+
*
|
|
21
|
+
* ## How the cache is keyed
|
|
22
|
+
*
|
|
23
|
+
* A bundle's inputs are a graph — the module's own `src/**`, the shared TS
|
|
24
|
+
* libraries it inlines, its dependency tree — so a staleness check anchored on
|
|
25
|
+
* the entry point is wrong for the most common edit there is: a sibling file, or
|
|
26
|
+
* a shared library one directory over. The output path is therefore keyed on a
|
|
27
|
+
* signature over **every input esbuild reported**, which turns a changed input
|
|
28
|
+
* into a different key: nothing to invalidate, and nothing to get wrong.
|
|
29
|
+
*
|
|
30
|
+
* It is **stat-addressed, not content-addressed**: the signature is each input's
|
|
31
|
+
* path, size and mtime, because the set spans a whole dependency tree and a few
|
|
32
|
+
* thousand `stat`s cost less than the build they avoid, while hashing every byte
|
|
33
|
+
* would cost more. The trade is worth naming, because it is not free:
|
|
34
|
+
*
|
|
35
|
+
* - a checkout that restores byte-identical files mints a fresh key, so a branch
|
|
36
|
+
* switch rebuilds rather than hitting the cache;
|
|
37
|
+
* - two different contents with the same size, written inside the same
|
|
38
|
+
* millisecond, collide — vanishingly unlikely for hand edits, and bounded by
|
|
39
|
+
* the fact that this path only ever runs against a working copy.
|
|
40
|
+
*
|
|
41
|
+
* Neither costs correctness of what ships: a published artifact never takes this
|
|
42
|
+
* path at all.
|
|
43
|
+
*
|
|
44
|
+
* Keying the output path (rather than overwriting one file) also makes
|
|
45
|
+
* concurrency benign. The test suite spawns one kernel *process* per manifest, so
|
|
46
|
+
* the contention is between processes, where an in-process single-flight gate
|
|
47
|
+
* sees nothing. Two processes that race build identical bytes for identical keys,
|
|
48
|
+
* and each writes through a private temp file before an atomic rename — so a
|
|
49
|
+
* reader sees a whole bundle or no bundle, never a torn one.
|
|
50
|
+
*
|
|
51
|
+
* Superseded bundles are pruned on the build that replaces them, so a long-lived
|
|
52
|
+
* checkout does not accumulate one `.mjs` per save.
|
|
53
|
+
*/
|
|
54
|
+
/** Cache layout under the kernel's cache root: the built bundles, plus one index
|
|
55
|
+
* entry per entry point recording the inputs its last build read. */
|
|
56
|
+
const CACHE_DIR = "controller-src";
|
|
57
|
+
/**
|
|
58
|
+
* The esbuild options a controller bundle is built with. They must match the
|
|
59
|
+
* flags each module's `build` script passes, because a bundle a contributor runs
|
|
60
|
+
* has to be the bundle that ships.
|
|
61
|
+
*
|
|
62
|
+
* The realm names stay external because the bundle loader symlinks them to the
|
|
63
|
+
* kernel's own copy at load time. Inlining them would duplicate the runtime and
|
|
64
|
+
* break the constructor identity `Stream` / `InvokeError` depend on.
|
|
65
|
+
*
|
|
66
|
+
* The banner defines `require` in module scope so esbuild's `__require` shim —
|
|
67
|
+
* emitted for `require(...)` calls inside a bundled CJS dependency — falls
|
|
68
|
+
* through to the real require instead of throwing "Dynamic require of X is not
|
|
69
|
+
* supported", which it would in a `.mjs` where `require` is otherwise undefined.
|
|
70
|
+
*/
|
|
71
|
+
const CONTROLLER_BUNDLE_OPTIONS = {
|
|
72
|
+
bundle: true,
|
|
73
|
+
format: "esm",
|
|
74
|
+
platform: "node",
|
|
75
|
+
target: "node20",
|
|
76
|
+
// Inline a workspace TS library from its SOURCE, not from its `dist/`.
|
|
77
|
+
//
|
|
78
|
+
// Two reasons, and the first is load-bearing: `dist/` is a build output, so
|
|
79
|
+
// resolving through it would make building a controller depend on having built
|
|
80
|
+
// every library it inlines — which is exactly the build step this path exists
|
|
81
|
+
// to remove, and it fails on a fresh clone with "Could not resolve". The second
|
|
82
|
+
// is that the shipping build passes the same condition, so both inline the same
|
|
83
|
+
// bytes; resolving to `dist` in one and `src` in the other would mean two
|
|
84
|
+
// transpilers producing the bundle a contributor runs versus the one that ships.
|
|
85
|
+
//
|
|
86
|
+
// `source` is the conventional name for this and every inlined package declares
|
|
87
|
+
// it ahead of `import`. A package that does not simply resolves as before.
|
|
88
|
+
conditions: ["source"],
|
|
89
|
+
banner: {
|
|
90
|
+
js: 'import { createRequire as __teloCreateRequire } from "node:module";' +
|
|
91
|
+
"const require = __teloCreateRequire(import.meta.url);",
|
|
92
|
+
},
|
|
93
|
+
external: [...REALM_COLLAPSE_NAMES],
|
|
94
|
+
};
|
|
95
|
+
/**
|
|
96
|
+
* Fingerprint of the options above, folded into every cache key.
|
|
97
|
+
*
|
|
98
|
+
* The output is a function of the inputs *and* how they were built, so a change
|
|
99
|
+
* to the option set has to invalidate the cache the same way an edited source
|
|
100
|
+
* does — otherwise a kernel upgrade that changes the banner or the externals
|
|
101
|
+
* keeps serving bundles built the old way, which is the exact silent-stale-copy
|
|
102
|
+
* failure the content-addressing exists to prevent.
|
|
103
|
+
*/
|
|
104
|
+
const OPTIONS_FINGERPRINT = createHash("sha256")
|
|
105
|
+
.update(JSON.stringify(CONTROLLER_BUNDLE_OPTIONS))
|
|
106
|
+
.digest("hex")
|
|
107
|
+
.slice(0, 8);
|
|
108
|
+
/** Memoized esbuild handle: `undefined` until first tried, `null` when absent. A
|
|
109
|
+
* failed dynamic import is not reliably cached by Node, so without this every
|
|
110
|
+
* controller load re-attempts (and re-fails) the import. */
|
|
111
|
+
let esbuildModule;
|
|
112
|
+
async function loadEsbuild() {
|
|
113
|
+
if (esbuildModule !== undefined)
|
|
114
|
+
return esbuildModule;
|
|
115
|
+
try {
|
|
116
|
+
esbuildModule = await import("esbuild");
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
esbuildModule = null;
|
|
120
|
+
}
|
|
121
|
+
return esbuildModule;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Whether this host can build a controller from source at all.
|
|
125
|
+
*
|
|
126
|
+
* Asked at *resolve* time, not at build time, so the absence of esbuild selects
|
|
127
|
+
* the prebuilt `path=` file instead of failing the load. esbuild is an
|
|
128
|
+
* **optional** dependency precisely so an install that skips optionals still runs
|
|
129
|
+
* published artifacts — and a working copy that has run its build script has the
|
|
130
|
+
* same prebuilt file sitting there. Deciding this lazily inside the build would
|
|
131
|
+
* turn "no bundler" into a hard failure with a perfectly good bundle on disk.
|
|
132
|
+
*/
|
|
133
|
+
export async function canBuildFromSource() {
|
|
134
|
+
return (await loadEsbuild()) !== null;
|
|
135
|
+
}
|
|
136
|
+
async function pathExists(p) {
|
|
137
|
+
try {
|
|
138
|
+
await fs.access(p);
|
|
139
|
+
return true;
|
|
140
|
+
}
|
|
141
|
+
catch {
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Signature of an input set: each file's path, size and mtime, hashed together.
|
|
147
|
+
* Stat rather than content because the set spans a whole dependency tree — a few
|
|
148
|
+
* thousand stats cost less than the build they are avoiding, while reading every
|
|
149
|
+
* byte would cost more.
|
|
150
|
+
*
|
|
151
|
+
* Returns `null` when any recorded input has disappeared, which is itself a
|
|
152
|
+
* change: the caller rebuilds rather than trusting a signature computed over a
|
|
153
|
+
* file set that no longer exists.
|
|
154
|
+
*/
|
|
155
|
+
async function signInputs(inputs) {
|
|
156
|
+
const stats = await Promise.all(inputs.map(async (file) => {
|
|
157
|
+
try {
|
|
158
|
+
const stat = await fs.stat(file);
|
|
159
|
+
return `${file}\0${stat.size}\0${stat.mtimeMs}`;
|
|
160
|
+
}
|
|
161
|
+
catch {
|
|
162
|
+
return null;
|
|
163
|
+
}
|
|
164
|
+
}));
|
|
165
|
+
if (stats.some((entry) => entry === null))
|
|
166
|
+
return null;
|
|
167
|
+
return createHash("sha256")
|
|
168
|
+
.update(OPTIONS_FINGERPRINT)
|
|
169
|
+
.update("\n")
|
|
170
|
+
.update(stats.join("\n"))
|
|
171
|
+
.digest("hex")
|
|
172
|
+
.slice(0, 32);
|
|
173
|
+
}
|
|
174
|
+
function indexPath(cacheDir, entryFile) {
|
|
175
|
+
const id = createHash("sha256").update(entryFile).digest("hex").slice(0, 32);
|
|
176
|
+
return path.join(cacheDir, `${id}.index.json`);
|
|
177
|
+
}
|
|
178
|
+
function bundlePath(cacheDir, key) {
|
|
179
|
+
return path.join(cacheDir, `${key}.mjs`);
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Every file the last build of `entryFile` actually read, from esbuild's own
|
|
183
|
+
* metafile — the module's sources, the shared TS libraries it inlines, and its
|
|
184
|
+
* dependency tree.
|
|
185
|
+
*
|
|
186
|
+
* Exported for watch mode, which needs exactly this set and cannot derive it:
|
|
187
|
+
* the bundle's inputs are a graph, so watching the entry point's directory both
|
|
188
|
+
* misses a shared library one directory over and sweeps in build output. Empty
|
|
189
|
+
* before the first build, when there is nothing to be stale about yet.
|
|
190
|
+
*/
|
|
191
|
+
export async function lastBuildInputs(entryFile, cacheRoot) {
|
|
192
|
+
const index = await readIndex(indexPath(path.join(cacheRoot, CACHE_DIR), entryFile));
|
|
193
|
+
return index?.inputs ?? [];
|
|
194
|
+
}
|
|
195
|
+
async function readIndex(file) {
|
|
196
|
+
try {
|
|
197
|
+
const parsed = JSON.parse(await fs.readFile(file, "utf8"));
|
|
198
|
+
return Array.isArray(parsed.inputs) && typeof parsed.key === "string" ? parsed : null;
|
|
199
|
+
}
|
|
200
|
+
catch {
|
|
201
|
+
return null;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
/** In-process single-flight per entry point — the cheap common case, on top of
|
|
205
|
+
* the cross-process safety the content-addressed path already provides. */
|
|
206
|
+
const buildsInFlight = new Map();
|
|
207
|
+
let tmpCounter = 0;
|
|
208
|
+
/**
|
|
209
|
+
* Return the path of a current bundle for `entryFile`, building it if the cache
|
|
210
|
+
* has none. Throws `ERR_CONTROLLER_BUILD_FAILED` when the source does not build —
|
|
211
|
+
* that is broken user code and must surface, never fall through to another
|
|
212
|
+
* candidate.
|
|
213
|
+
*/
|
|
214
|
+
export async function buildControllerFromSource(entryFile, cacheRoot) {
|
|
215
|
+
const cacheDir = path.join(cacheRoot, CACHE_DIR);
|
|
216
|
+
const index = await readIndex(indexPath(cacheDir, entryFile));
|
|
217
|
+
if (index) {
|
|
218
|
+
const key = await signInputs(index.inputs);
|
|
219
|
+
if (key === index.key) {
|
|
220
|
+
const cached = bundlePath(cacheDir, key);
|
|
221
|
+
if (await pathExists(cached))
|
|
222
|
+
return cached;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
const inFlight = buildsInFlight.get(entryFile);
|
|
226
|
+
if (inFlight)
|
|
227
|
+
return inFlight;
|
|
228
|
+
const work = build(entryFile, cacheDir).finally(() => buildsInFlight.delete(entryFile));
|
|
229
|
+
buildsInFlight.set(entryFile, work);
|
|
230
|
+
return work;
|
|
231
|
+
}
|
|
232
|
+
async function build(entryFile, cacheDir) {
|
|
233
|
+
const esbuild = await loadEsbuild();
|
|
234
|
+
if (!esbuild) {
|
|
235
|
+
// Explicit rather than a silent fallthrough: esbuild is an *optional*
|
|
236
|
+
// dependency precisely so a production install that skips optionals still
|
|
237
|
+
// loads published artifacts, which ship prebuilt bundles. Only building a
|
|
238
|
+
// local module from source needs it, and that case has to say so.
|
|
239
|
+
throw new ControllerEnvMissingError(`Cannot build controller from source "${entryFile}": esbuild is not installed. ` +
|
|
240
|
+
`Building a local module's controller needs it; a published module ships a ` +
|
|
241
|
+
`prebuilt bundle and does not.`);
|
|
242
|
+
}
|
|
243
|
+
let built;
|
|
244
|
+
try {
|
|
245
|
+
built = await esbuild.build({
|
|
246
|
+
...CONTROLLER_BUNDLE_OPTIONS,
|
|
247
|
+
// esbuild's options are mutable arrays; the shared constant is `as const`
|
|
248
|
+
// so it cannot be edited in place by one caller and read by another.
|
|
249
|
+
external: [...CONTROLLER_BUNDLE_OPTIONS.external],
|
|
250
|
+
conditions: [...CONTROLLER_BUNDLE_OPTIONS.conditions],
|
|
251
|
+
entryPoints: [entryFile],
|
|
252
|
+
write: false,
|
|
253
|
+
metafile: true,
|
|
254
|
+
logLevel: "silent",
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
catch (err) {
|
|
258
|
+
throw new RuntimeError("ERR_CONTROLLER_BUILD_FAILED", `Failed to build controller from source "${entryFile}":\n` +
|
|
259
|
+
(err instanceof Error ? err.message : String(err)));
|
|
260
|
+
}
|
|
261
|
+
const output = built.outputFiles?.[0];
|
|
262
|
+
if (!output) {
|
|
263
|
+
throw new RuntimeError("ERR_CONTROLLER_BUILD_FAILED", `esbuild produced no output for controller source "${entryFile}"`);
|
|
264
|
+
}
|
|
265
|
+
// Absolute, so the signature is independent of the working directory the next
|
|
266
|
+
// kernel happens to run from.
|
|
267
|
+
const inputs = Object.keys(built.metafile.inputs).map((rel) => path.resolve(rel));
|
|
268
|
+
const key = (await signInputs(inputs)) ?? createHash("sha256")
|
|
269
|
+
.update(output.text)
|
|
270
|
+
.digest("hex")
|
|
271
|
+
.slice(0, 32);
|
|
272
|
+
const target = bundlePath(cacheDir, key);
|
|
273
|
+
await fs.mkdir(cacheDir, { recursive: true });
|
|
274
|
+
const index = indexPath(cacheDir, entryFile);
|
|
275
|
+
const superseded = (await readIndex(index))?.key;
|
|
276
|
+
const tmp = `${target}.${process.pid}.${tmpCounter++}.tmp`;
|
|
277
|
+
await fs.writeFile(tmp, output.text);
|
|
278
|
+
await fs.rename(tmp, target);
|
|
279
|
+
// Index last: a reader that finds it trusts the bundle it names to be on disk.
|
|
280
|
+
// A torn index self-heals — an unparseable one reads as a miss and rebuilds.
|
|
281
|
+
const tmpIndex = `${index}.${process.pid}.${tmpCounter++}.tmp`;
|
|
282
|
+
await fs.writeFile(tmpIndex, JSON.stringify({ inputs, key }));
|
|
283
|
+
await fs.rename(tmpIndex, index);
|
|
284
|
+
await prune(cacheDir, superseded, key);
|
|
285
|
+
return target;
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Drop the bundle this build replaced.
|
|
289
|
+
*
|
|
290
|
+
* Every save mints a new key, so without this a day of editing leaves one `.mjs`
|
|
291
|
+
* per save and the cache grows for the life of the checkout. Pruned *after* the
|
|
292
|
+
* new index is in place, so a concurrent reader is already being pointed at the
|
|
293
|
+
* replacement; on Linux a process that opened the old file keeps reading it
|
|
294
|
+
* through the open handle, and on Windows a failed unlink is swallowed — a stale
|
|
295
|
+
* file costs disk, never correctness.
|
|
296
|
+
*/
|
|
297
|
+
async function prune(cacheDir, superseded, current) {
|
|
298
|
+
if (!superseded || superseded === current)
|
|
299
|
+
return;
|
|
300
|
+
await fs.rm(bundlePath(cacheDir, superseded), { force: true }).catch(() => { });
|
|
301
|
+
}
|
|
302
|
+
//# sourceMappingURL=source-bundle-builder.js.map
|