@telorun/kernel 0.25.0 → 0.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/dist/controller-loader.d.ts +4 -0
  2. package/dist/controller-loader.d.ts.map +1 -1
  3. package/dist/controller-loader.js +4 -1
  4. package/dist/controller-loader.js.map +1 -1
  5. package/dist/controller-loaders/npm-loader.d.ts +10 -0
  6. package/dist/controller-loaders/npm-loader.d.ts.map +1 -1
  7. package/dist/controller-loaders/npm-loader.js +2 -1
  8. package/dist/controller-loaders/npm-loader.js.map +1 -1
  9. package/dist/controllers/resource-definition/resource-definition-controller.d.ts.map +1 -1
  10. package/dist/controllers/resource-definition/resource-definition-controller.js +1 -0
  11. package/dist/controllers/resource-definition/resource-definition-controller.js.map +1 -1
  12. package/dist/index.d.ts +1 -1
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +1 -1
  15. package/dist/index.js.map +1 -1
  16. package/dist/kernel.d.ts +8 -0
  17. package/dist/kernel.d.ts.map +1 -1
  18. package/dist/kernel.js +29 -14
  19. package/dist/kernel.js.map +1 -1
  20. package/dist/manifest-sources/analysis-stamp.d.ts +2 -2
  21. package/dist/manifest-sources/analysis-stamp.d.ts.map +1 -1
  22. package/dist/manifest-sources/analysis-stamp.js +9 -4
  23. package/dist/manifest-sources/analysis-stamp.js.map +1 -1
  24. package/dist/manifest-sources/local-manifest-cache-source.d.ts +13 -3
  25. package/dist/manifest-sources/local-manifest-cache-source.d.ts.map +1 -1
  26. package/dist/manifest-sources/local-manifest-cache-source.js +25 -6
  27. package/dist/manifest-sources/local-manifest-cache-source.js.map +1 -1
  28. package/dist/resource-context.d.ts +1 -0
  29. package/dist/resource-context.d.ts.map +1 -1
  30. package/dist/resource-context.js +3 -0
  31. package/dist/resource-context.js.map +1 -1
  32. package/dist/schema-validator.d.ts +8 -1
  33. package/dist/schema-validator.d.ts.map +1 -1
  34. package/dist/schema-validator.js +8 -2
  35. package/dist/schema-validator.js.map +1 -1
  36. package/package.json +2 -2
  37. package/src/controller-loader.ts +8 -1
  38. package/src/controller-loaders/npm-loader.ts +12 -1
  39. package/src/controllers/resource-definition/resource-definition-controller.ts +1 -0
  40. package/src/index.ts +1 -0
  41. package/src/kernel.ts +41 -15
  42. package/src/manifest-sources/analysis-stamp.ts +9 -2
  43. package/src/manifest-sources/local-manifest-cache-source.ts +29 -4
  44. package/src/resource-context.ts +4 -0
  45. package/src/schema-validator.ts +8 -2
@@ -136,9 +136,13 @@ export function computeAnalysisSignature(graph: LoadedGraph): string {
136
136
  * reading a newer stamp (or vice versa) discard rather than misparse. */
137
137
  export async function readAnalysisStamp(
138
138
  entryDir: string,
139
+ manifestsDir?: string,
139
140
  ): Promise<AnalysisStamp | undefined> {
141
+ const stampPath = manifestsDir
142
+ ? path.join(manifestsDir, ".validated.json")
143
+ : path.join(entryDir, ANALYSIS_STAMP_FILE);
140
144
  try {
141
- const text = await fs.readFile(path.join(entryDir, ANALYSIS_STAMP_FILE), "utf-8");
145
+ const text = await fs.readFile(stampPath, "utf-8");
142
146
  const parsed = JSON.parse(text) as Partial<AnalysisStamp>;
143
147
  if (
144
148
  parsed?.version === ANALYSIS_STAMP_FORMAT_VERSION &&
@@ -158,12 +162,15 @@ export async function readAnalysisStamp(
158
162
  export async function writeAnalysisStamp(
159
163
  entryDir: string,
160
164
  signature: string,
165
+ manifestsDir?: string,
161
166
  ): Promise<void> {
162
167
  const stamp: AnalysisStamp = {
163
168
  version: ANALYSIS_STAMP_FORMAT_VERSION,
164
169
  signature,
165
170
  };
166
- const target = path.join(entryDir, ANALYSIS_STAMP_FILE);
171
+ const target = manifestsDir
172
+ ? path.join(manifestsDir, ".validated.json")
173
+ : path.join(entryDir, ANALYSIS_STAMP_FILE);
167
174
  await fs.mkdir(path.dirname(target), { recursive: true });
168
175
  await fs.writeFile(target, JSON.stringify(stamp), "utf-8");
169
176
  }
@@ -133,8 +133,15 @@ export class LocalManifestCacheSource implements ManifestSource {
133
133
  private readonly cacheRoot: string;
134
134
  private readonly registryUrl: string;
135
135
 
136
- constructor(entryDir: string, registryUrl: string = DEFAULT_REGISTRY_URL) {
137
- this.cacheRoot = path.join(entryDir, CACHE_SUBDIR);
136
+ constructor(
137
+ entryDir: string,
138
+ registryUrl: string = DEFAULT_REGISTRY_URL,
139
+ manifestsDir?: string,
140
+ ) {
141
+ // `manifestsDir` is the resolved manifest-cache directory threaded from a
142
+ // single `resolveCacheRoot` (honours `TELO_CACHE_DIR`); when absent we fall
143
+ // back to the entry-anchored default so library/test callers are unchanged.
144
+ this.cacheRoot = manifestsDir ?? path.join(entryDir, CACHE_SUBDIR);
138
145
  this.registryUrl = registryUrl;
139
146
  }
140
147
 
@@ -189,8 +196,9 @@ export function cachePathForCanonical(
189
196
  canonicalSource: string,
190
197
  entryDir: string,
191
198
  registryUrl: string,
199
+ manifestsDir?: string,
192
200
  ): string | null {
193
- const cacheRoot = path.join(entryDir, CACHE_SUBDIR);
201
+ const cacheRoot = manifestsDir ?? path.join(entryDir, CACHE_SUBDIR);
194
202
  return cachePathForUrl(canonicalSource, cacheRoot, registryUrl);
195
203
  }
196
204
 
@@ -210,6 +218,7 @@ export async function writeManifestCache(
210
218
  graph: LoadedGraph,
211
219
  entryDir: string,
212
220
  registryUrl: string = DEFAULT_REGISTRY_URL,
221
+ manifestsDir?: string,
213
222
  ): Promise<string[]> {
214
223
  const written: string[] = [];
215
224
  const seen = new Set<string>();
@@ -220,7 +229,7 @@ export async function writeManifestCache(
220
229
  if (seen.has(file.source)) continue;
221
230
  seen.add(file.source);
222
231
 
223
- const target = cachePathForCanonical(file.source, entryDir, registryUrl);
232
+ const target = cachePathForCanonical(file.source, entryDir, registryUrl, manifestsDir);
224
233
  if (!target) continue;
225
234
 
226
235
  await fs.mkdir(path.dirname(target), { recursive: true });
@@ -254,3 +263,19 @@ export function resolveEntryDir(entryPath: string): string | null {
254
263
  return path.dirname(absolute);
255
264
  }
256
265
  }
266
+
267
+ /** The single `.telo` cache root for an entry, resolved once and threaded to
268
+ * every consumer (manifest cache, compiled validators, analysis stamp, npm
269
+ * install root) so none of them re-derive it or read the env independently.
270
+ *
271
+ * `TELO_CACHE_DIR` (the relocated root a prebuilt image bakes its deps into)
272
+ * wins; otherwise the root sits beside the entry at `<entry-dir>/.telo`.
273
+ * Returns `null` for http(s) entries with no local anchor (disk cache skipped).
274
+ * Consumers append the conventional subdirs: `manifests/`, `manifests/__validators/`,
275
+ * `npm/`. */
276
+ export function resolveCacheRoot(entryPath: string): string | null {
277
+ const override = process.env.TELO_CACHE_DIR;
278
+ if (override && override.trim()) return path.resolve(override.trim());
279
+ const entryDir = resolveEntryDir(entryPath);
280
+ return entryDir ? path.join(entryDir, ".telo") : null;
281
+ }
@@ -344,6 +344,10 @@ export class ResourceContextImpl implements ResourceContext {
344
344
  return this.kernel.getEntryUrl();
345
345
  }
346
346
 
347
+ getInstallRoot(): string | undefined {
348
+ return this.kernel.getInstallRoot();
349
+ }
350
+
347
351
  on(event: string, handler: (payload?: any) => void | Promise<void>): void {
348
352
  this.kernel.on(event, handler);
349
353
  }
@@ -117,6 +117,11 @@ export class SchemaValidator {
117
117
  private rawSchemas = new Map<string, object>();
118
118
  private compiledValidators = new WeakMap<object, DataValidator>();
119
119
  private cacheDir: string | undefined;
120
+ /** When false, the disk cache is read-only: compiled validators are still
121
+ * loaded from `cacheDir` but never written back. `telo run --no-cache-write`
122
+ * sets this so an ephemeral, read-only session rootfs validates in-memory
123
+ * without touching (or failing to write) the baked cache. */
124
+ private cacheWritable = true;
120
125
  /** Tracks (schema-hash → in-memory compiled validator) so two distinct
121
126
  * but content-equal schema objects share one compile across the kernel
122
127
  * process — `compiledValidators` is keyed by object identity and would
@@ -183,8 +188,9 @@ export class SchemaValidator {
183
188
  * kernel anchors this under `<entry-dir>/.telo/manifests/__validators/`
184
189
  * so it lives next to the manifest cache and rides along in
185
190
  * `COPY --from=build /srv /srv` Docker images. */
186
- setCacheDir(dir: string | undefined): void {
191
+ setCacheDir(dir: string | undefined, opts?: { write?: boolean }): void {
187
192
  this.cacheDir = dir;
193
+ this.cacheWritable = opts?.write ?? true;
188
194
  }
189
195
 
190
196
  compile(schema: any): DataValidator {
@@ -315,7 +321,7 @@ export class SchemaValidator {
315
321
  }
316
322
 
317
323
  const validate = this.ajv.compile(schema) as ValidateFunction;
318
- if (cacheDir) {
324
+ if (cacheDir && this.cacheWritable) {
319
325
  try {
320
326
  const body = standaloneCode(this.ajv, validate);
321
327
  const integrity = createHash("sha256").update(body).digest("hex");