@telorun/analyzer 0.41.1 → 0.42.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.
@@ -1 +1 @@
1
- {"version":3,"file":"builtins.d.ts","sourceRoot":"","sources":["../src/builtins.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AA2GvD,eAAO,MAAM,eAAe,EAAE,kBAAkB,EA8nB/C,CAAC"}
1
+ {"version":3,"file":"builtins.d.ts","sourceRoot":"","sources":["../src/builtins.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AA2GvD,eAAO,MAAM,eAAe,EAAE,kBAAkB,EA6nB/C,CAAC"}
package/dist/builtins.js CHANGED
@@ -431,7 +431,6 @@ export const KERNEL_BUILTINS = [
431
431
  enum: ["shared", "isolated"],
432
432
  default: "shared",
433
433
  },
434
- keepAlive: { type: "boolean", default: false },
435
434
  targets: {
436
435
  type: "array",
437
436
  items: {
@@ -49,6 +49,13 @@ export interface ScopeBoundaryEvent {
49
49
  /** Names of every resource declared inside this resource's scopes. Used by
50
50
  * the dependency graph to drop boot edges to scoped (on-demand) targets. */
51
51
  enclosedNames: Set<string>;
52
+ /** Scope entries that are references (`!ref`) rather than inline resource
53
+ * definitions — a category error, since a scope declares its own resources.
54
+ * Each carries the concrete path (e.g. `with[0]`) for diagnostics. */
55
+ scopeRefEntries: {
56
+ path: string;
57
+ refName: string;
58
+ }[];
52
59
  }
53
60
  export interface RefSiteEvent {
54
61
  source: ResourceManifest;
@@ -1 +1 @@
1
- {"version":3,"file":"manifest-visitor.d.ts","sourceRoot":"","sources":["../src/manifest-visitor.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"manifest-visitor.d.ts","sourceRoot":"","sources":["../src/manifest-visitor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,EAML,KAAK,aAAa,EAClB,KAAK,oBAAoB,EAC1B,MAAM,0BAA0B,CAAC;AAGlC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,gBAAgB,CAAC;IACzB,8EAA8E;IAC9E,UAAU,CAAC,EAAE,kBAAkB,CAAC;CACjC;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,gBAAgB,CAAC;CAC1B;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,gBAAgB,CAAC;IACzB,wEAAwE;IACxE,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,uEAAuE;IACvE,kBAAkB,EAAE,GAAG,CAAC,MAAM,EAAE,gBAAgB,EAAE,CAAC,CAAC;IACpD;iFAC6E;IAC7E,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC3B;;2EAEuE;IACvE,eAAe,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACtD;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,gBAAgB,CAAC;IACzB,uEAAuE;IACvE,SAAS,EAAE,MAAM,CAAC;IAClB,+EAA+E;IAC/E,YAAY,EAAE,MAAM,CAAC;IACrB,gFAAgF;IAChF,KAAK,EAAE,OAAO,CAAC;IACf,oEAAoE;IACpE,KAAK,EAAE,aAAa,CAAC;IACrB;iEAC6D;IAC7D,OAAO,EAAE,OAAO,CAAC;IACjB,gFAAgF;IAChF,qBAAqB,EAAE,gBAAgB,EAAE,CAAC;IAC1C;;;;;4BAKwB;IACxB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,gBAAgB,CAAC;IACzB,uDAAuD;IACvD,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,oBAAoB,CAAC;CAC7B;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,gBAAgB,CAAC;IACzB,0EAA0E;IAC1E,IAAI,EAAE,MAAM,CAAC;IACb,iCAAiC;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,6DAA6D;IAC7D,UAAU,EAAE,MAAM,CAAC;IACnB;;mEAE+D;IAC/D,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACpC,6EAA6E;IAC7E,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,eAAe;IAC9B,eAAe,CAAC,CAAC,CAAC,EAAE,kBAAkB,GAAG,IAAI,CAAC;IAC9C,OAAO,CAAC,CAAC,CAAC,EAAE,kBAAkB,GAAG,IAAI,CAAC;IACtC,KAAK,CAAC,CAAC,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;IAC9B,YAAY,CAAC,CAAC,CAAC,EAAE,mBAAmB,GAAG,IAAI,CAAC;IAC5C,KAAK,CAAC,CAAC,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;IAC9B,cAAc,CAAC,CAAC,CAAC,EAAE,iBAAiB,GAAG,IAAI,CAAC;CAC7C;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,eAAe,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IAC7C,6EAA6E;IAC7E,SAAS,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAChC;;+EAE2E;IAC3E,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;;;;wDAMoD;IACpD,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAsDD,wBAAgB,aAAa,CAC3B,SAAS,EAAE,gBAAgB,EAAE,EAC7B,QAAQ,EAAE,kBAAkB,EAC5B,OAAO,EAAE,eAAe,EACxB,OAAO,GAAE,YAAiB,GACzB,IAAI,CAuKN"}
@@ -1,5 +1,5 @@
1
1
  import { isRefSentinel, isTaggedSentinel, walkCelExpressions } from "@telorun/templating";
2
- import { isRefEntry, isSchemaFromEntry, isScopeEntry, resolveFieldEntries, resolveFieldValues, } from "./reference-field-map.js";
2
+ import { isRefEntry, isSchemaFromEntry, isScopeEntry, resolveFieldEntries, } from "./reference-field-map.js";
3
3
  import { extractContextsFromSchema, pathMatchesScope } from "./validate-cel-context.js";
4
4
  /** Synthetic entry for a value-tree-discovered ref — these carry no declared
5
5
  * x-telo-ref constraint. */
@@ -77,12 +77,32 @@ export function visitManifest(resources, registry, visitor, options = {}) {
77
77
  : baseMap;
78
78
  if (refScopeMap && (wantsRefs || wantsScope)) {
79
79
  const manifestsByPointer = new Map();
80
+ const scopeRefEntries = [];
80
81
  for (const [fieldPath, entry] of refScopeMap) {
81
82
  if (!isScopeEntry(entry))
82
83
  continue;
83
- const raw = resolveFieldValues(r, fieldPath)
84
- .flatMap((v) => (Array.isArray(v) ? v : [v]))
85
- .filter((v) => !!v && typeof v === "object");
84
+ const raw = [];
85
+ for (const fe of resolveFieldEntries(r, fieldPath)) {
86
+ const items = Array.isArray(fe.value) ? fe.value : [fe.value];
87
+ items.forEach((v, i) => {
88
+ if (!v || typeof v !== "object")
89
+ return;
90
+ // A scope entry must be an inline resource definition; a `!ref`
91
+ // (tagged sentinel or resolved `{kind, name}`) is not — record it
92
+ // so a static diagnostic flags it instead of registering a
93
+ // config-less manifest.
94
+ const rec = v;
95
+ if (isRefSentinel(v) ||
96
+ (typeof rec.kind === "string" && typeof rec.name === "string")) {
97
+ scopeRefEntries.push({
98
+ path: Array.isArray(fe.value) ? `${fe.path}[${i}]` : fe.path,
99
+ refName: isRefSentinel(v) ? v.source : String(rec.name),
100
+ });
101
+ return;
102
+ }
103
+ raw.push(v);
104
+ });
105
+ }
86
106
  const pointers = Array.isArray(entry.scope) ? entry.scope : [entry.scope];
87
107
  for (const pointer of pointers)
88
108
  manifestsByPointer.set(pointer, raw);
@@ -97,7 +117,13 @@ export function visitManifest(resources, registry, visitor, options = {}) {
97
117
  enclosedNames.add(name);
98
118
  }
99
119
  }
100
- visitor.onScope({ source: r, scopePrefixes, manifestsByPointer, enclosedNames });
120
+ visitor.onScope({
121
+ source: r,
122
+ scopePrefixes,
123
+ manifestsByPointer,
124
+ enclosedNames,
125
+ scopeRefEntries,
126
+ });
101
127
  }
102
128
  if (wantsRefs) {
103
129
  for (const [fieldPath, entry] of refScopeMap) {
@@ -1 +1 @@
1
- {"version":3,"file":"validate-references.d.ts","sourceRoot":"","sources":["../src/validate-references.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAMrD,OAAO,EAAsB,KAAK,kBAAkB,EAAE,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AAgD/F;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,gBAAgB,EAAE,EAC7B,OAAO,EAAE,eAAe,GACvB,kBAAkB,EAAE,CA6ctB"}
1
+ {"version":3,"file":"validate-references.d.ts","sourceRoot":"","sources":["../src/validate-references.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAMrD,OAAO,EAAsB,KAAK,kBAAkB,EAAE,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AAgD/F;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,gBAAgB,EAAE,EAC7B,OAAO,EAAE,eAAe,GACvB,kBAAkB,EAAE,CA6dtB"}
@@ -341,6 +341,22 @@ export function validateReferences(resources, context) {
341
341
  });
342
342
  }
343
343
  },
344
+ onScope: (e) => {
345
+ const r = e.source;
346
+ const resourceLabel = `${r.kind}/${r.metadata.name}`;
347
+ const resourceData = { kind: r.kind, name: r.metadata.name };
348
+ const filePath = r.metadata?.source;
349
+ for (const { path: concretePath, refName } of e.scopeRefEntries) {
350
+ const scopeField = concretePath.split(/[.[]/)[0];
351
+ diagnostics.push({
352
+ severity: DiagnosticSeverity.Error,
353
+ code: "SCOPE_ENTRY_NOT_INLINE",
354
+ source: SOURCE,
355
+ message: `${resourceLabel}: scope entry at '${concretePath}' is a reference (\`!ref ${refName}\`), but a scope declares inline resource definitions (a \`kind:\` with its config). Declare the resource inline under '${scopeField}:', or reference an outer resource from a sibling field such as 'targets:'.`,
356
+ data: { resource: resourceData, filePath, path: concretePath },
357
+ });
358
+ }
359
+ },
344
360
  }, { aliases, aliasesByModule, skipKinds: SYSTEM_KINDS, expand: true });
345
361
  // Phase 3b — x-telo-schema-from validation.
346
362
  // For each field with a schemaFrom path expression, resolve the anchor ref to get the
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@telorun/analyzer",
3
- "version": "0.41.1",
3
+ "version": "0.42.0",
4
4
  "description": "Telo Analyzer - Static manifest validator for Telo manifests.",
5
5
  "keywords": [
6
6
  "telo",
package/src/builtins.ts CHANGED
@@ -440,7 +440,6 @@ export const KERNEL_BUILTINS: ResourceDefinition[] = [
440
440
  enum: ["shared", "isolated"],
441
441
  default: "shared",
442
442
  },
443
- keepAlive: { type: "boolean", default: false },
444
443
  targets: {
445
444
  type: "array",
446
445
  items: {
@@ -63,6 +63,10 @@ export interface ScopeBoundaryEvent {
63
63
  /** Names of every resource declared inside this resource's scopes. Used by
64
64
  * the dependency graph to drop boot edges to scoped (on-demand) targets. */
65
65
  enclosedNames: Set<string>;
66
+ /** Scope entries that are references (`!ref`) rather than inline resource
67
+ * definitions — a category error, since a scope declares its own resources.
68
+ * Each carries the concrete path (e.g. `with[0]`) for diagnostics. */
69
+ scopeRefEntries: { path: string; refName: string }[];
66
70
  }
67
71
 
68
72
  export interface RefSiteEvent {
@@ -235,11 +239,32 @@ export function visitManifest(
235
239
 
236
240
  if (refScopeMap && (wantsRefs || wantsScope)) {
237
241
  const manifestsByPointer = new Map<string, ResourceManifest[]>();
242
+ const scopeRefEntries: { path: string; refName: string }[] = [];
238
243
  for (const [fieldPath, entry] of refScopeMap) {
239
244
  if (!isScopeEntry(entry)) continue;
240
- const raw = resolveFieldValues(r, fieldPath)
241
- .flatMap((v) => (Array.isArray(v) ? v : [v]))
242
- .filter((v): v is ResourceManifest => !!v && typeof v === "object");
245
+ const raw: ResourceManifest[] = [];
246
+ for (const fe of resolveFieldEntries(r, fieldPath)) {
247
+ const items = Array.isArray(fe.value) ? fe.value : [fe.value];
248
+ items.forEach((v, i) => {
249
+ if (!v || typeof v !== "object") return;
250
+ // A scope entry must be an inline resource definition; a `!ref`
251
+ // (tagged sentinel or resolved `{kind, name}`) is not — record it
252
+ // so a static diagnostic flags it instead of registering a
253
+ // config-less manifest.
254
+ const rec = v as Record<string, unknown>;
255
+ if (
256
+ isRefSentinel(v) ||
257
+ (typeof rec.kind === "string" && typeof rec.name === "string")
258
+ ) {
259
+ scopeRefEntries.push({
260
+ path: Array.isArray(fe.value) ? `${fe.path}[${i}]` : fe.path,
261
+ refName: isRefSentinel(v) ? v.source : String(rec.name),
262
+ });
263
+ return;
264
+ }
265
+ raw.push(v as ResourceManifest);
266
+ });
267
+ }
243
268
  const pointers = Array.isArray(entry.scope) ? entry.scope : [entry.scope];
244
269
  for (const pointer of pointers) manifestsByPointer.set(pointer, raw);
245
270
  }
@@ -253,7 +278,13 @@ export function visitManifest(
253
278
  if (typeof name === "string") enclosedNames.add(name);
254
279
  }
255
280
  }
256
- visitor.onScope!({ source: r, scopePrefixes, manifestsByPointer, enclosedNames });
281
+ visitor.onScope!({
282
+ source: r,
283
+ scopePrefixes,
284
+ manifestsByPointer,
285
+ enclosedNames,
286
+ scopeRefEntries,
287
+ });
257
288
  }
258
289
 
259
290
  if (wantsRefs) {
@@ -357,6 +357,22 @@ export function validateReferences(
357
357
  });
358
358
  }
359
359
  },
360
+ onScope: (e) => {
361
+ const r = e.source;
362
+ const resourceLabel = `${r.kind}/${r.metadata!.name as string}`;
363
+ const resourceData = { kind: r.kind, name: r.metadata!.name as string };
364
+ const filePath = (r.metadata as { source?: string } | undefined)?.source;
365
+ for (const { path: concretePath, refName } of e.scopeRefEntries) {
366
+ const scopeField = concretePath.split(/[.[]/)[0];
367
+ diagnostics.push({
368
+ severity: DiagnosticSeverity.Error,
369
+ code: "SCOPE_ENTRY_NOT_INLINE",
370
+ source: SOURCE,
371
+ message: `${resourceLabel}: scope entry at '${concretePath}' is a reference (\`!ref ${refName}\`), but a scope declares inline resource definitions (a \`kind:\` with its config). Declare the resource inline under '${scopeField}:', or reference an outer resource from a sibling field such as 'targets:'.`,
372
+ data: { resource: resourceData, filePath, path: concretePath },
373
+ });
374
+ }
375
+ },
360
376
  },
361
377
  { aliases, aliasesByModule, skipKinds: SYSTEM_KINDS, expand: true },
362
378
  );