@telorun/kernel 0.37.0 → 0.39.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/controllers/resource-definition/resource-template-controller.d.ts.map +1 -1
- package/dist/controllers/resource-definition/resource-template-controller.js +12 -1
- package/dist/controllers/resource-definition/resource-template-controller.js.map +1 -1
- package/dist/evaluation-context.d.ts +21 -1
- package/dist/evaluation-context.d.ts.map +1 -1
- package/dist/evaluation-context.js +152 -14
- package/dist/evaluation-context.js.map +1 -1
- package/dist/kernel.d.ts.map +1 -1
- package/dist/kernel.js +4 -5
- package/dist/kernel.js.map +1 -1
- package/dist/manifest-sources/local-file-source.d.ts.map +1 -1
- package/dist/manifest-sources/local-file-source.js +8 -9
- package/dist/manifest-sources/local-file-source.js.map +1 -1
- package/dist/resource-context.d.ts +5 -1
- package/dist/resource-context.d.ts.map +1 -1
- package/dist/resource-context.js +2 -1
- package/dist/resource-context.js.map +1 -1
- package/package.json +5 -5
- package/src/controllers/resource-definition/resource-template-controller.ts +12 -1
- package/src/evaluation-context.ts +164 -15
- package/src/kernel.ts +9 -2
- package/src/manifest-sources/local-file-source.ts +10 -9
- package/src/resource-context.ts +6 -0
- package/dist/eval-paths.d.ts +0 -10
- package/dist/eval-paths.d.ts.map +0 -1
- package/dist/eval-paths.js +0 -35
- package/dist/eval-paths.js.map +0 -1
- package/src/eval-paths.ts +0 -44
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
2
2
|
import {
|
|
3
|
+
getRefIdentity,
|
|
3
4
|
isCompiledValue,
|
|
4
5
|
isInvokeError,
|
|
5
6
|
isCancellationError,
|
|
@@ -16,12 +17,14 @@ import {
|
|
|
16
17
|
type ResourceDefinition,
|
|
17
18
|
type ResourceInstance,
|
|
18
19
|
type ResourceManifest,
|
|
20
|
+
type ResourceOwner,
|
|
19
21
|
type RuntimeDiagnostic,
|
|
20
22
|
type ScopeContext,
|
|
21
23
|
type ScopeHandle,
|
|
22
24
|
type Tracer,
|
|
23
25
|
} from "@telorun/sdk";
|
|
24
26
|
import { RuntimeError } from "@telorun/sdk";
|
|
27
|
+
import { evalPathCovers } from "@telorun/analyzer";
|
|
25
28
|
|
|
26
29
|
export { resourceKey };
|
|
27
30
|
|
|
@@ -40,16 +43,28 @@ function isResolvedRef(value: unknown): value is ResourceRef {
|
|
|
40
43
|
return Object.keys(v).every((k) => k === "kind" || k === "name" || k === "alias");
|
|
41
44
|
}
|
|
42
45
|
|
|
46
|
+
/** The system kinds whose top-level `schema:` is, by definition, a JSON Schema
|
|
47
|
+
* document (with `examples` / `default` / `const`) rather than config — a
|
|
48
|
+
* `{kind, name}` inside one is documentation data, not a `!ref`. For these the
|
|
49
|
+
* `schema` field is skipped when walking for refs/properties; for every other
|
|
50
|
+
* kind a `schema` field is ordinary config and is walked normally, so a real
|
|
51
|
+
* `schema: !ref X` still resolves. Narrowly scoped (rather than skipping any
|
|
52
|
+
* field named `schema` on every kind) so the heuristic can't misfire. */
|
|
53
|
+
const SCHEMA_AS_CONTRACT_KINDS = new Set(["Telo.Definition", "Telo.Abstract", "Telo.Type"]);
|
|
54
|
+
|
|
43
55
|
/**
|
|
44
56
|
* Walk a resource manifest's config and collect every resolved `{kind, name,
|
|
45
57
|
* alias?}` reference it points at — the outbound edges for the dependency graph.
|
|
46
58
|
* Called at create time, before Phase-5 injection swaps refs for live instances,
|
|
47
59
|
* so the targets are still inspectable plain objects (and there are no instance
|
|
48
|
-
* cycles to guard against). `metadata` is skipped
|
|
49
|
-
*
|
|
60
|
+
* cycles to guard against). Deduped by alias+name. `metadata` is always skipped
|
|
61
|
+
* (the resource's own identity); `schema` is skipped only for the system kinds
|
|
62
|
+
* that carry a JSON-Schema contract there (see {@link SCHEMA_AS_CONTRACT_KINDS}).
|
|
63
|
+
* Ref leaves are not descended into.
|
|
50
64
|
*/
|
|
51
65
|
function collectResourceRefs(resource: ResourceManifest): ResourceRef[] {
|
|
52
66
|
const found = new Map<string, ResourceRef>();
|
|
67
|
+
const skipSchema = SCHEMA_AS_CONTRACT_KINDS.has(resource.kind as string);
|
|
53
68
|
const visit = (value: unknown): void => {
|
|
54
69
|
if (isResolvedRef(value)) {
|
|
55
70
|
const key = `${value.alias ?? ""}::${value.name}`;
|
|
@@ -60,18 +75,86 @@ function collectResourceRefs(resource: ResourceManifest): ResourceRef[] {
|
|
|
60
75
|
for (const item of value) visit(item);
|
|
61
76
|
} else if (value && typeof value === "object") {
|
|
62
77
|
for (const [k, v] of Object.entries(value as Record<string, unknown>)) {
|
|
63
|
-
if (k === "metadata") continue;
|
|
78
|
+
if (k === "metadata" || (skipSchema && k === "schema")) continue;
|
|
64
79
|
visit(v);
|
|
65
80
|
}
|
|
66
81
|
}
|
|
67
82
|
};
|
|
68
83
|
for (const [k, v] of Object.entries(resource as Record<string, unknown>)) {
|
|
69
|
-
if (k === "kind" || k === "metadata") continue;
|
|
84
|
+
if (k === "kind" || k === "metadata" || (skipSchema && k === "schema")) continue;
|
|
70
85
|
visit(v);
|
|
71
86
|
}
|
|
72
87
|
return [...found.values()];
|
|
73
88
|
}
|
|
74
89
|
|
|
90
|
+
/**
|
|
91
|
+
* Build a resource's resolved properties for the debug stream — its config "after
|
|
92
|
+
* templating", with `${{ }}` / `!cel` reduced to concrete values. The manifest is
|
|
93
|
+
* already compile-evaluated by the time it is created, so this just makes the
|
|
94
|
+
* remaining live forms wire-friendly:
|
|
95
|
+
* - a resolved `!ref` (`{kind, name, alias?}`) → its `{kind, name}` target;
|
|
96
|
+
* - a deferred runtime expression (a `CompiledValue` left for per-call eval, e.g.
|
|
97
|
+
* an Http.Api route reading `request`) → its `${{ source }}` text — there is no
|
|
98
|
+
* concrete value for it at the resource level;
|
|
99
|
+
* - a string carrying a known secret value → `[secret]` (substring-scrubbed), so
|
|
100
|
+
* a compile-time `${{ secrets.x }}` never lands in the stream verbatim.
|
|
101
|
+
* `metadata` / `schema` are omitted (identity and JSON-Schema, not config).
|
|
102
|
+
*/
|
|
103
|
+
/** Substring-scrubbing a secret shorter than this risks redacting unrelated
|
|
104
|
+
* content (a short/common-word value matches everywhere), so below it only a
|
|
105
|
+
* whole-value match is redacted. */
|
|
106
|
+
const MIN_SUBSTRING_SCRUB_LEN = 5;
|
|
107
|
+
|
|
108
|
+
export function buildResolvedProperties(
|
|
109
|
+
resource: ResourceManifest,
|
|
110
|
+
secretValues: Set<string>,
|
|
111
|
+
): Record<string, unknown> {
|
|
112
|
+
const skipSchema = SCHEMA_AS_CONTRACT_KINDS.has(resource.kind as string);
|
|
113
|
+
const scrub = (s: string): string => {
|
|
114
|
+
let out = s;
|
|
115
|
+
for (const secret of secretValues) {
|
|
116
|
+
if (!secret) continue;
|
|
117
|
+
// Exact match is always a secret; substring-redact only longer values so a
|
|
118
|
+
// short secret can't garble unrelated text it happens to appear in.
|
|
119
|
+
if (out === secret) out = "[secret]";
|
|
120
|
+
else if (secret.length >= MIN_SUBSTRING_SCRUB_LEN && out.includes(secret)) {
|
|
121
|
+
out = out.split(secret).join("[secret]");
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return out;
|
|
125
|
+
};
|
|
126
|
+
const visit = (value: unknown): unknown => {
|
|
127
|
+
if (isCompiledValue(value)) {
|
|
128
|
+
const src = (value as { source?: unknown }).source;
|
|
129
|
+
return typeof src === "string" ? `\${{ ${src} }}` : "[expression]";
|
|
130
|
+
}
|
|
131
|
+
if (isResolvedRef(value)) return { kind: value.kind, name: value.name };
|
|
132
|
+
if (typeof value === "string") return scrub(value);
|
|
133
|
+
if (Array.isArray(value)) return value.map(visit);
|
|
134
|
+
if (value && typeof value === "object") {
|
|
135
|
+
// A live instance injected into a ref slot (e.g. a template child whose
|
|
136
|
+
// `connection` was resolved to the real connection): show its identity, not
|
|
137
|
+
// its internals. Other class instances (streams, clients) get a marker.
|
|
138
|
+
const id = getRefIdentity(value);
|
|
139
|
+
if (id) return { kind: id.kind, name: id.name };
|
|
140
|
+
const proto = Object.getPrototypeOf(value);
|
|
141
|
+
if (proto !== Object.prototype && proto !== null) {
|
|
142
|
+
return `[${(value as { constructor?: { name?: string } }).constructor?.name ?? "Object"}]`;
|
|
143
|
+
}
|
|
144
|
+
const out: Record<string, unknown> = {};
|
|
145
|
+
for (const [k, v] of Object.entries(value as Record<string, unknown>)) out[k] = visit(v);
|
|
146
|
+
return out;
|
|
147
|
+
}
|
|
148
|
+
return value;
|
|
149
|
+
};
|
|
150
|
+
const out: Record<string, unknown> = {};
|
|
151
|
+
for (const [k, v] of Object.entries(resource as Record<string, unknown>)) {
|
|
152
|
+
if (k === "kind" || k === "metadata" || (skipSchema && k === "schema")) continue;
|
|
153
|
+
out[k] = visit(v);
|
|
154
|
+
}
|
|
155
|
+
return out;
|
|
156
|
+
}
|
|
157
|
+
|
|
75
158
|
/**
|
|
76
159
|
* Kernel-internal propagation of the current invocation tree's cancellation
|
|
77
160
|
* scope. NEVER the controller-facing contract — controllers always receive the
|
|
@@ -188,6 +271,38 @@ export class EvaluationContext implements IEvaluationContext {
|
|
|
188
271
|
*/
|
|
189
272
|
tracer?: Tracer;
|
|
190
273
|
|
|
274
|
+
/**
|
|
275
|
+
* The resource that owns this context's resources — stamped by a template
|
|
276
|
+
* controller on the child context it registers its `resources:` into.
|
|
277
|
+
* Propagated through spawnChild() so scoped/nested children inherit it. Drives
|
|
278
|
+
* the hierarchical `id` and `owner` every lifecycle/dispatch event carries, so
|
|
279
|
+
* a debug consumer nests children under their parent and two instances of the
|
|
280
|
+
* same templated kind don't collide by name. Undefined ⇒ top-level resources.
|
|
281
|
+
*/
|
|
282
|
+
owner?: ResourceOwner;
|
|
283
|
+
|
|
284
|
+
/** Id prefix for a resource created in this context: `owner.id + "/"`, or ""
|
|
285
|
+
* at the top level. A resource's full id is `ownerPrefix + kind + "." + name`. */
|
|
286
|
+
get ownerPrefix(): string {
|
|
287
|
+
return this.owner ? `${this.owner.id}/` : "";
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/** The full hierarchical id of a resource emitted from this context. */
|
|
291
|
+
private resourceId(kind: string, name: string): string {
|
|
292
|
+
return `${this.ownerPrefix}${kind}.${name}`;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/** Stamp each dependency ref with the target node's hierarchical id. A local
|
|
296
|
+
* (no-alias) sibling lives in this same context, so it carries this prefix; a
|
|
297
|
+
* cross-module (`alias`) target lives elsewhere, so it stays unqualified
|
|
298
|
+
* (best-effort — the renderer drops an edge that finds no node). */
|
|
299
|
+
private qualifyDeps(refs: ResourceRef[]): (ResourceRef & { id: string })[] {
|
|
300
|
+
return refs.map((ref) => ({
|
|
301
|
+
...ref,
|
|
302
|
+
id: ref.alias ? `${ref.kind}.${ref.name}` : this.resourceId(ref.kind, ref.name),
|
|
303
|
+
}));
|
|
304
|
+
}
|
|
305
|
+
|
|
191
306
|
constructor(
|
|
192
307
|
readonly source: string,
|
|
193
308
|
context: Record<string, unknown>,
|
|
@@ -271,6 +386,12 @@ export class EvaluationContext implements IEvaluationContext {
|
|
|
271
386
|
if (this.tracer && !child.tracer) {
|
|
272
387
|
child.tracer = this.tracer;
|
|
273
388
|
}
|
|
389
|
+
// Inherit ownership so a scope/import opened inside a template's child
|
|
390
|
+
// context keeps its resources nested under the same owner. A template
|
|
391
|
+
// controller overrides this on its own child context after spawning.
|
|
392
|
+
if (this.owner && !child.owner) {
|
|
393
|
+
child.owner = this.owner;
|
|
394
|
+
}
|
|
274
395
|
return child;
|
|
275
396
|
}
|
|
276
397
|
|
|
@@ -348,14 +469,29 @@ export class EvaluationContext implements IEvaluationContext {
|
|
|
348
469
|
if (idx >= 0) this.pendingResources.splice(idx, 1);
|
|
349
470
|
errors.delete(name);
|
|
350
471
|
progress = true;
|
|
351
|
-
|
|
472
|
+
const createdRes = created.resource;
|
|
473
|
+
const payload: Record<string, unknown> = {
|
|
352
474
|
resource: {
|
|
353
|
-
kind:
|
|
354
|
-
name:
|
|
355
|
-
module:
|
|
475
|
+
kind: createdRes.kind,
|
|
476
|
+
name: createdRes.metadata.name,
|
|
477
|
+
module: createdRes.metadata.module,
|
|
478
|
+
id: this.resourceId(createdRes.kind, createdRes.metadata.name),
|
|
356
479
|
},
|
|
357
|
-
|
|
480
|
+
...(this.owner ? { owner: this.owner } : {}),
|
|
481
|
+
dependencies: this.qualifyDeps(collectResourceRefs(createdRes)),
|
|
482
|
+
};
|
|
483
|
+
// `properties` (the resolved config) is a second full config walk plus
|
|
484
|
+
// a secret scrub. Build it lazily: the EventBus short-circuits when
|
|
485
|
+
// nothing is subscribed (the no-debug-consumer case), so this getter
|
|
486
|
+
// only runs when a consumer actually serializes the payload. Memoized
|
|
487
|
+
// so multiple sinks (JSONL + SSE) don't rebuild it.
|
|
488
|
+
let props: Record<string, unknown> | undefined;
|
|
489
|
+
Object.defineProperty(payload, "properties", {
|
|
490
|
+
enumerable: true,
|
|
491
|
+
configurable: true,
|
|
492
|
+
get: () => (props ??= buildResolvedProperties(createdRes, this.secretValues)),
|
|
358
493
|
});
|
|
494
|
+
await this.emit(`${createdRes.kind}.${createdRes.metadata.name}.Created`, payload);
|
|
359
495
|
}
|
|
360
496
|
} catch (error) {
|
|
361
497
|
if (error instanceof RuntimeError && (error.code === "ERR_VISIBILITY_DENIED" || error.code === "ERR_FATAL")) throw error;
|
|
@@ -387,7 +523,12 @@ export class EvaluationContext implements IEvaluationContext {
|
|
|
387
523
|
errors.delete(name);
|
|
388
524
|
progress = true;
|
|
389
525
|
await this.emit(`${resource.kind}.${resource.metadata.name}.Initialized`, {
|
|
390
|
-
resource: {
|
|
526
|
+
resource: {
|
|
527
|
+
kind: resource.kind,
|
|
528
|
+
name: resource.metadata.name,
|
|
529
|
+
id: this.resourceId(resource.kind, resource.metadata.name),
|
|
530
|
+
},
|
|
531
|
+
...(this.owner ? { owner: this.owner } : {}),
|
|
391
532
|
});
|
|
392
533
|
} catch (error) {
|
|
393
534
|
if (error instanceof RuntimeError && (error.code === "ERR_VISIBILITY_DENIED" || error.code === "ERR_FATAL")) throw error;
|
|
@@ -555,7 +696,12 @@ export class EvaluationContext implements IEvaluationContext {
|
|
|
555
696
|
for (const [key, { resource, instance }] of entries) {
|
|
556
697
|
if (instance.teardown) await instance.teardown();
|
|
557
698
|
await this.emit(`${resource.kind}.${resource.metadata.name}.Teardown`, {
|
|
558
|
-
resource: {
|
|
699
|
+
resource: {
|
|
700
|
+
kind: resource.kind,
|
|
701
|
+
name: resource.metadata.name,
|
|
702
|
+
id: this.resourceId(resource.kind, resource.metadata.name),
|
|
703
|
+
},
|
|
704
|
+
...(this.owner ? { owner: this.owner } : {}),
|
|
559
705
|
});
|
|
560
706
|
this.resourceInstances.delete(key);
|
|
561
707
|
}
|
|
@@ -673,7 +819,8 @@ export class EvaluationContext implements IEvaluationContext {
|
|
|
673
819
|
capability,
|
|
674
820
|
phase,
|
|
675
821
|
...(outcome !== undefined ? { outcome } : {}),
|
|
676
|
-
ref: { kind, name },
|
|
822
|
+
ref: { kind, name, id: this.resourceId(kind, name) },
|
|
823
|
+
...(this.owner ? { owner: this.owner } : {}),
|
|
677
824
|
...detail,
|
|
678
825
|
};
|
|
679
826
|
}
|
|
@@ -1124,10 +1271,12 @@ export class EvaluationContext implements IEvaluationContext {
|
|
|
1124
1271
|
}
|
|
1125
1272
|
}
|
|
1126
1273
|
|
|
1274
|
+
/** A compile path is excluded from compile-time expansion when it overlaps a
|
|
1275
|
+
* runtime path in either direction — the runtime path is a descendant of it, or
|
|
1276
|
+
* vice versa. Both directions go through the shared {@link evalPathCovers}
|
|
1277
|
+
* containment rule so this stays in lockstep with the analyzer's coverage check. */
|
|
1127
1278
|
function isExcluded(path: string, excludePaths: string[]): boolean {
|
|
1128
|
-
return excludePaths.some(
|
|
1129
|
-
(ep) => ep === path || ep === "**" || path.startsWith(ep + ".") || ep.startsWith(path + "."),
|
|
1130
|
-
);
|
|
1279
|
+
return excludePaths.some((ep) => evalPathCovers(ep, path) || evalPathCovers(path, ep));
|
|
1131
1280
|
}
|
|
1132
1281
|
|
|
1133
1282
|
function getNestedValue(obj: Record<string, unknown>, parts: string[]): unknown {
|
package/src/kernel.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AnalysisRegistry,
|
|
3
|
+
buildEvalPaths,
|
|
3
4
|
defaultSources,
|
|
4
5
|
flattenForAnalyzer,
|
|
5
6
|
flattenLoadedModule,
|
|
@@ -36,7 +37,6 @@ import { ModuleContext } from "./module-context.js";
|
|
|
36
37
|
import { ResourceContextImpl } from "./resource-context.js";
|
|
37
38
|
import { nodeCelHandlers } from "./cel-handlers.js";
|
|
38
39
|
import { parseRef, seedInvokeSource } from "./invoke-dispatch.js";
|
|
39
|
-
import { buildEvalPaths } from "./eval-paths.js";
|
|
40
40
|
import { stripCompiledValues } from "./schema-compiled-values.js";
|
|
41
41
|
import { injectAtPath } from "./dependency-injection.js";
|
|
42
42
|
import {
|
|
@@ -895,6 +895,7 @@ export class Kernel implements IKernel {
|
|
|
895
895
|
moduleContext: IModuleContext,
|
|
896
896
|
resource: ResourceManifest,
|
|
897
897
|
args?: ParsedArgs,
|
|
898
|
+
ownerPrefix = "",
|
|
898
899
|
): ResourceContext {
|
|
899
900
|
return new ResourceContextImpl(
|
|
900
901
|
this,
|
|
@@ -906,6 +907,7 @@ export class Kernel implements IKernel {
|
|
|
906
907
|
this.stdout,
|
|
907
908
|
this.stderr,
|
|
908
909
|
args,
|
|
910
|
+
ownerPrefix,
|
|
909
911
|
);
|
|
910
912
|
}
|
|
911
913
|
|
|
@@ -1043,7 +1045,12 @@ export class Kernel implements IKernel {
|
|
|
1043
1045
|
|
|
1044
1046
|
const parsedArgs = this.parseArgsForController(controller);
|
|
1045
1047
|
const moduleCtx = this.findModuleContext(evalContext);
|
|
1046
|
-
const ctx = this.createResourceContext(
|
|
1048
|
+
const ctx = this.createResourceContext(
|
|
1049
|
+
moduleCtx,
|
|
1050
|
+
processedResource,
|
|
1051
|
+
parsedArgs,
|
|
1052
|
+
evalContext.ownerPrefix,
|
|
1053
|
+
);
|
|
1047
1054
|
const instance = await controller.create(processedResource, ctx);
|
|
1048
1055
|
if (!instance) return null;
|
|
1049
1056
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { DEFAULT_MANIFEST_FILENAME, type ManifestSource } from "@telorun/analyzer";
|
|
2
|
+
import { selectByPatterns } from "@telorun/glob";
|
|
2
3
|
import * as fs from "fs/promises";
|
|
3
4
|
import * as path from "path";
|
|
4
5
|
import { fileURLToPath, pathToFileURL } from "url";
|
|
5
|
-
import { minimatch } from "minimatch";
|
|
6
6
|
|
|
7
7
|
function toFilePath(pathOrUrl: string): string {
|
|
8
8
|
return pathOrUrl.startsWith("file://") ? fileURLToPath(pathOrUrl) : pathOrUrl;
|
|
@@ -49,17 +49,18 @@ export class LocalFileSource implements ManifestSource {
|
|
|
49
49
|
async expandGlob(base: string, patterns: string[]): Promise<string[]> {
|
|
50
50
|
const baseDir = path.dirname(path.resolve(toFilePath(base)));
|
|
51
51
|
const entries = await fs.readdir(baseDir, { recursive: true, withFileTypes: true });
|
|
52
|
-
const
|
|
53
|
-
const matched: string[] = [];
|
|
52
|
+
const rels: string[] = [];
|
|
54
53
|
for (const entry of entries) {
|
|
55
54
|
if (!entry.isFile()) continue;
|
|
56
|
-
|
|
57
|
-
const normalized = relative.replace(/\\/g, "/");
|
|
58
|
-
if (normalizedPatterns.some((p) => minimatch(normalized, p))) {
|
|
59
|
-
matched.push(toFileUrl(path.resolve(baseDir, relative)));
|
|
60
|
-
}
|
|
55
|
+
rels.push(path.relative(baseDir, path.join(entry.parentPath, entry.name)).replace(/\\/g, "/"));
|
|
61
56
|
}
|
|
62
|
-
|
|
57
|
+
// `include:` resolution may reach any co-located partial, so it opts out of
|
|
58
|
+
// the soft default-ignore tier (parity with `telo publish`'s include path).
|
|
59
|
+
// The hard tier (`node_modules`/`.git`/`.telo`) is always denied, so a broad
|
|
60
|
+
// `**` include never recurses into the manifest cache.
|
|
61
|
+
return selectByPatterns(rels, patterns, { applyDefaultIgnore: false }).map((rel) =>
|
|
62
|
+
toFileUrl(path.resolve(baseDir, rel)),
|
|
63
|
+
);
|
|
63
64
|
}
|
|
64
65
|
|
|
65
66
|
async resolveOwnerOf(fileUrl: string): Promise<string | null> {
|
package/src/resource-context.ts
CHANGED
|
@@ -38,6 +38,10 @@ export class ResourceContextImpl implements ResourceContext {
|
|
|
38
38
|
readonly stdout: NodeJS.WritableStream;
|
|
39
39
|
readonly stderr: NodeJS.WritableStream;
|
|
40
40
|
readonly args: ParsedArgs;
|
|
41
|
+
/** Id prefix of the context this resource was created in. A controller that
|
|
42
|
+
* spawns sub-resources composes their ids as `ownerPrefix + kind + "." + name`
|
|
43
|
+
* and stamps the owner on the child context it registers them into. */
|
|
44
|
+
readonly ownerPrefix: string;
|
|
41
45
|
|
|
42
46
|
constructor(
|
|
43
47
|
readonly kernel: Kernel,
|
|
@@ -49,12 +53,14 @@ export class ResourceContextImpl implements ResourceContext {
|
|
|
49
53
|
stdout?: NodeJS.WritableStream,
|
|
50
54
|
stderr?: NodeJS.WritableStream,
|
|
51
55
|
args?: ParsedArgs,
|
|
56
|
+
ownerPrefix = "",
|
|
52
57
|
) {
|
|
53
58
|
this.env = env ?? process.env;
|
|
54
59
|
this.stdin = stdin ?? process.stdin;
|
|
55
60
|
this.stdout = stdout ?? process.stdout;
|
|
56
61
|
this.stderr = stderr ?? process.stderr;
|
|
57
62
|
this.args = args ?? { _: [] };
|
|
63
|
+
this.ownerPrefix = ownerPrefix;
|
|
58
64
|
}
|
|
59
65
|
|
|
60
66
|
createSchemaValidator(schema: any) {
|
package/dist/eval-paths.d.ts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Traverses a definition schema and collects all paths annotated with `x-telo-eval`.
|
|
3
|
-
* Root-level `x-telo-eval` produces the `"**"` wildcard (expand all fields).
|
|
4
|
-
* Property-level annotations produce the dot-notation path to that property.
|
|
5
|
-
*/
|
|
6
|
-
export declare function buildEvalPaths(schema: Record<string, any>): {
|
|
7
|
-
compile: string[];
|
|
8
|
-
runtime: string[];
|
|
9
|
-
};
|
|
10
|
-
//# sourceMappingURL=eval-paths.d.ts.map
|
package/dist/eval-paths.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"eval-paths.d.ts","sourceRoot":"","sources":["../src/eval-paths.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG;IAC3D,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB,CAcA"}
|
package/dist/eval-paths.js
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Traverses a definition schema and collects all paths annotated with `x-telo-eval`.
|
|
3
|
-
* Root-level `x-telo-eval` produces the `"**"` wildcard (expand all fields).
|
|
4
|
-
* Property-level annotations produce the dot-notation path to that property.
|
|
5
|
-
*/
|
|
6
|
-
export function buildEvalPaths(schema) {
|
|
7
|
-
const compile = [];
|
|
8
|
-
const runtime = [];
|
|
9
|
-
if (schema["x-telo-eval"] === "compile")
|
|
10
|
-
compile.push("**");
|
|
11
|
-
else if (schema["x-telo-eval"] === "runtime")
|
|
12
|
-
runtime.push("**");
|
|
13
|
-
if (schema.properties) {
|
|
14
|
-
for (const [key, propSchema] of Object.entries(schema.properties)) {
|
|
15
|
-
collectEvalPathsNode(propSchema, key, compile, runtime);
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
return { compile, runtime };
|
|
19
|
-
}
|
|
20
|
-
function collectEvalPathsNode(node, path, compile, runtime) {
|
|
21
|
-
if (node["x-telo-eval"] === "compile") {
|
|
22
|
-
compile.push(path);
|
|
23
|
-
return;
|
|
24
|
-
}
|
|
25
|
-
if (node["x-telo-eval"] === "runtime") {
|
|
26
|
-
runtime.push(path);
|
|
27
|
-
return;
|
|
28
|
-
}
|
|
29
|
-
if (node.properties) {
|
|
30
|
-
for (const [key, propSchema] of Object.entries(node.properties)) {
|
|
31
|
-
collectEvalPathsNode(propSchema, `${path}.${key}`, compile, runtime);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
//# sourceMappingURL=eval-paths.js.map
|
package/dist/eval-paths.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"eval-paths.js","sourceRoot":"","sources":["../src/eval-paths.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,MAA2B;IAIxD,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,MAAM,OAAO,GAAa,EAAE,CAAC;IAE7B,IAAI,MAAM,CAAC,aAAa,CAAC,KAAK,SAAS;QAAE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;SACvD,IAAI,MAAM,CAAC,aAAa,CAAC,KAAK,SAAS;QAAE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEjE,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;QACtB,KAAK,MAAM,CAAC,GAAG,EAAE,UAAU,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,UAAiC,CAAC,EAAE,CAAC;YACzF,oBAAoB,CAAC,UAAU,EAAE,GAAG,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QAC1D,CAAC;IACH,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;AAC9B,CAAC;AAED,SAAS,oBAAoB,CAC3B,IAAyB,EACzB,IAAY,EACZ,OAAiB,EACjB,OAAiB;IAEjB,IAAI,IAAI,CAAC,aAAa,CAAC,KAAK,SAAS,EAAE,CAAC;QACtC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnB,OAAO;IACT,CAAC;IACD,IAAI,IAAI,CAAC,aAAa,CAAC,KAAK,SAAS,EAAE,CAAC;QACtC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnB,OAAO;IACT,CAAC;IACD,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;QACpB,KAAK,MAAM,CAAC,GAAG,EAAE,UAAU,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,UAAiC,CAAC,EAAE,CAAC;YACvF,oBAAoB,CAAC,UAAU,EAAE,GAAG,IAAI,IAAI,GAAG,EAAE,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QACvE,CAAC;IACH,CAAC;AACH,CAAC"}
|
package/src/eval-paths.ts
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Traverses a definition schema and collects all paths annotated with `x-telo-eval`.
|
|
3
|
-
* Root-level `x-telo-eval` produces the `"**"` wildcard (expand all fields).
|
|
4
|
-
* Property-level annotations produce the dot-notation path to that property.
|
|
5
|
-
*/
|
|
6
|
-
export function buildEvalPaths(schema: Record<string, any>): {
|
|
7
|
-
compile: string[];
|
|
8
|
-
runtime: string[];
|
|
9
|
-
} {
|
|
10
|
-
const compile: string[] = [];
|
|
11
|
-
const runtime: string[] = [];
|
|
12
|
-
|
|
13
|
-
if (schema["x-telo-eval"] === "compile") compile.push("**");
|
|
14
|
-
else if (schema["x-telo-eval"] === "runtime") runtime.push("**");
|
|
15
|
-
|
|
16
|
-
if (schema.properties) {
|
|
17
|
-
for (const [key, propSchema] of Object.entries(schema.properties as Record<string, any>)) {
|
|
18
|
-
collectEvalPathsNode(propSchema, key, compile, runtime);
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
return { compile, runtime };
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
function collectEvalPathsNode(
|
|
26
|
-
node: Record<string, any>,
|
|
27
|
-
path: string,
|
|
28
|
-
compile: string[],
|
|
29
|
-
runtime: string[],
|
|
30
|
-
): void {
|
|
31
|
-
if (node["x-telo-eval"] === "compile") {
|
|
32
|
-
compile.push(path);
|
|
33
|
-
return;
|
|
34
|
-
}
|
|
35
|
-
if (node["x-telo-eval"] === "runtime") {
|
|
36
|
-
runtime.push(path);
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
39
|
-
if (node.properties) {
|
|
40
|
-
for (const [key, propSchema] of Object.entries(node.properties as Record<string, any>)) {
|
|
41
|
-
collectEvalPathsNode(propSchema, `${path}.${key}`, compile, runtime);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
}
|