@telorun/analyzer 0.33.0 → 0.34.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/analysis-registry.d.ts.map +1 -1
- package/dist/analysis-registry.js +10 -9
- package/dist/analyzer.d.ts.map +1 -1
- package/dist/analyzer.js +21 -9
- package/dist/builtins.d.ts.map +1 -1
- package/dist/builtins.js +15 -0
- package/dist/definition-registry.d.ts +4 -1
- package/dist/definition-registry.d.ts.map +1 -1
- package/dist/definition-registry.js +20 -3
- package/dist/extends-resolution.d.ts +33 -0
- package/dist/extends-resolution.d.ts.map +1 -0
- package/dist/extends-resolution.js +82 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/validate-base-mapping.d.ts +21 -0
- package/dist/validate-base-mapping.d.ts.map +1 -0
- package/dist/validate-base-mapping.js +130 -0
- package/dist/validate-extends.d.ts.map +1 -1
- package/dist/validate-extends.js +20 -9
- package/dist/validate-provider-coherence.d.ts.map +1 -1
- package/dist/validate-provider-coherence.js +8 -1
- package/dist/validate-references.d.ts.map +1 -1
- package/dist/validate-references.js +15 -9
- package/package.json +2 -2
- package/src/analysis-registry.ts +9 -8
- package/src/analyzer.ts +32 -9
- package/src/builtins.ts +15 -0
- package/src/definition-registry.ts +18 -3
- package/src/extends-resolution.ts +124 -0
- package/src/index.ts +12 -0
- package/src/validate-base-mapping.ts +154 -0
- package/src/validate-extends.ts +24 -11
- package/src/validate-provider-coherence.ts +12 -2
- package/src/validate-references.ts +13 -9
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analysis-registry.d.ts","sourceRoot":"","sources":["../src/analysis-registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAKzE,OAAO,EAAqC,KAAK,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAEhG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAGlD;;wDAEwD;AACxD,MAAM,WAAW,YAAY;IAC3B;0CACsC;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,uDAAuD;IACvD,OAAO,EAAE,OAAO,CAAC;IACjB,uEAAuE;IACvE,IAAI,EAAE,MAAM,EAAE,CAAC;IACf;;;8EAG0E;IAC1E,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAED;;;;GAIG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA4B;IACjD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAuB;IAC/C,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAoC;IAEpE,kBAAkB,CAAC,GAAG,EAAE,kBAAkB,GAAG,IAAI;IAIjD,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAIpE,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI;IAIpE,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAI7C;;;;;;;OAOG;IACH,mBAAmB,CACjB,QAAQ,EAAE,gBAAgB,EAC1B,KAAK,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,EAClC,OAAO,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,GACnC,IAAI;IAkBP;;;;;;OAMG;IACH,oBAAoB,CAAC,QAAQ,EAAE,gBAAgB,GAAG,YAAY,EAAE;IAoBhE;;;;;;wBAMoB;IACpB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAQtD;;;;;;sFAMkF;IAClF,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS;IAenE;;;;;qDAKiD;IACjD,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS;IAepE,OAAO,CAAC,mBAAmB;IAS3B;;;;;;OAMG;IACH,aAAa,CACX,SAAS,EAAE,gBAAgB,EAAE,EAC7B,OAAO,EAAE,eAAe,EACxB,IAAI,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,CAAC;QAAC,kBAAkB,CAAC,EAAE,OAAO,CAAA;KAAE,GACzF,IAAI;IAQP;;;;OAIG;IACH,kBAAkB,IAAI,kBAAkB,EAAE;IAI1C,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS;IAM/D;;qFAEiF;IACjF,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE;IAUzC,QAAQ,IAAI,MAAM,EAAE;IAIpB;mEAC+D;IAC/D,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE;IAIxC;;;gCAG4B;IAC5B,oBAAoB,IAAI,MAAM,EAAE;IAIhC;wEACoE;IACpE,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAIhD;;;;;;;;iDAQ6C;IAC7C,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,GAAG,SAAS;
|
|
1
|
+
{"version":3,"file":"analysis-registry.d.ts","sourceRoot":"","sources":["../src/analysis-registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -220,17 +220,18 @@ export class AnalysisRegistry {
|
|
|
220
220
|
const targetDef = this.defs.resolve(targetKind);
|
|
221
221
|
if (!targetDef)
|
|
222
222
|
return undefined;
|
|
223
|
+
// General single inheritance: the accepted set is the target kind plus every
|
|
224
|
+
// kind that transitively extends it (subtypes are substitutable). A concrete
|
|
225
|
+
// target contributes itself and any specializations; an abstract contributes
|
|
226
|
+
// its implementations. Same transitive index for both.
|
|
223
227
|
const out = new Set();
|
|
224
|
-
if (targetDef.kind
|
|
225
|
-
for (const def of this.defs.getByExtends(targetKind)) {
|
|
226
|
-
const module = def.metadata?.module;
|
|
227
|
-
if (module && def.metadata?.name) {
|
|
228
|
-
out.add(`${module}.${def.metadata.name}`);
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
else {
|
|
228
|
+
if (targetDef.kind !== "Telo.Abstract")
|
|
233
229
|
out.add(targetKind);
|
|
230
|
+
for (const def of this.defs.getByExtends(targetKind)) {
|
|
231
|
+
const module = def.metadata?.module;
|
|
232
|
+
if (module && def.metadata?.name) {
|
|
233
|
+
out.add(`${module}.${def.metadata.name}`);
|
|
234
|
+
}
|
|
234
235
|
}
|
|
235
236
|
return out;
|
|
236
237
|
}
|
package/dist/analyzer.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analyzer.d.ts","sourceRoot":"","sources":["../src/analyzer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAsB,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAKzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAIL,KAAK,WAAW,EACjB,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"analyzer.d.ts","sourceRoot":"","sources":["../src/analyzer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAsB,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAKzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAIL,KAAK,WAAW,EACjB,MAAM,sBAAsB,CAAC;AAoB9B,OAAO,EAAsB,KAAK,kBAAkB,EAAE,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AAwxB/F,MAAM,WAAW,qBAAqB;IACpC,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAc;gBAEzB,OAAO,GAAE,qBAA0B;IAI/C;;;;;;;;;;;;;;OAcG;IACH,OAAO,CACL,SAAS,EAAE,gBAAgB,EAAE,EAC7B,OAAO,CAAC,EAAE,eAAe,EACzB,QAAQ,CAAC,EAAE,gBAAgB,GAC1B,kBAAkB,EAAE;IAmzBvB,aAAa,CACX,SAAS,EAAE,gBAAgB,EAAE,EAC7B,OAAO,CAAC,EAAE,eAAe,EACzB,QAAQ,CAAC,EAAE,gBAAgB,GAC1B,kBAAkB,EAAE;IAMvB,SAAS,CACP,SAAS,EAAE,gBAAgB,EAAE,EAC7B,QAAQ,EAAE,gBAAgB,EAI1B,kBAAkB,CAAC,EAAE,gBAAgB,EAAE,GACtC,gBAAgB,EAAE;IAmBrB,OAAO,CACL,SAAS,EAAE,gBAAgB,EAAE,EAC7B,QAAQ,EAAE,gBAAgB,GACzB;QAAE,WAAW,EAAE,kBAAkB,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;QAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE;CAsB5F"}
|
package/dist/analyzer.js
CHANGED
|
@@ -3,6 +3,7 @@ import { defaultRegistry, isRefSentinel, isTaggedSentinel } from "@telorun/templ
|
|
|
3
3
|
import { AliasResolver, scopeResolverForModule } from "./alias-resolver.js";
|
|
4
4
|
import { buildCelEnvironment, buildImportInputCelEnvironment, buildTypedCelEnvironment, } from "./cel-environment.js";
|
|
5
5
|
import { DefinitionRegistry } from "./definition-registry.js";
|
|
6
|
+
import { effectiveAuthorSchema } from "./extends-resolution.js";
|
|
6
7
|
import { buildDependencyGraph, formatCycle } from "./dependency-graph.js";
|
|
7
8
|
import { buildKernelGlobalsSchema, mergeKernelGlobalsIntoContext } from "./kernel-globals.js";
|
|
8
9
|
import { computeSuggestKind } from "./kind-suggest.js";
|
|
@@ -19,6 +20,7 @@ import { DiagnosticSeverity } from "./types.js";
|
|
|
19
20
|
import { extractCelRegionScopes, extractContextsFromSchema, getManifestItem, pathMatchesScope, resolveContextAnnotations, resolveTypeFieldToSchema, } from "./validate-cel-context.js";
|
|
20
21
|
import { buildEvalPaths, evalPathsCover } from "./eval-paths.js";
|
|
21
22
|
import { validateExtends } from "./validate-extends.js";
|
|
23
|
+
import { validateBaseMapping } from "./validate-base-mapping.js";
|
|
22
24
|
import { validateNestedInlineResources } from "./validate-nested-inline.js";
|
|
23
25
|
import { validateKindDescriptions } from "./validate-kind-descriptions.js";
|
|
24
26
|
import { validateProviderCoherence } from "./validate-provider-coherence.js";
|
|
@@ -88,8 +90,12 @@ const SOURCE = "telo-analyzer";
|
|
|
88
90
|
* property the user declared in `schema:` plus synthetic `name` / `kind` and
|
|
89
91
|
* the metadata sub-object (kept open since metadata legitimately carries
|
|
90
92
|
* arbitrary user-added fields). */
|
|
91
|
-
function buildSelfSchema(definition) {
|
|
92
|
-
|
|
93
|
+
function buildSelfSchema(definition, defs, aliases) {
|
|
94
|
+
// The author-facing schema resolves inheritance: with `base:` the child's own
|
|
95
|
+
// schema (the parent's config is internal); without it, `merge(parent, own)`.
|
|
96
|
+
const userSchema = (defs
|
|
97
|
+
? effectiveAuthorSchema(definition, (k) => defs.resolve(aliases?.resolveKind(k) ?? k) ?? defs.resolve(k))
|
|
98
|
+
: (definition.schema ?? {}));
|
|
93
99
|
const userProps = (userSchema.properties ?? {});
|
|
94
100
|
const userRequired = Array.isArray(userSchema.required) ? userSchema.required : [];
|
|
95
101
|
return {
|
|
@@ -146,7 +152,7 @@ function manifestRootForResolver(m, defs, aliases, allManifests) {
|
|
|
146
152
|
const inputs = lookupTemplateInputsSchema(m, defs, aliases, allManifests);
|
|
147
153
|
return {
|
|
148
154
|
...m,
|
|
149
|
-
schema: buildSelfSchema(m),
|
|
155
|
+
schema: buildSelfSchema(m, defs, aliases),
|
|
150
156
|
...(inputs ? { inputType: inputs } : {}),
|
|
151
157
|
};
|
|
152
158
|
}
|
|
@@ -1051,20 +1057,25 @@ export class StaticAnalyzer {
|
|
|
1051
1057
|
});
|
|
1052
1058
|
continue;
|
|
1053
1059
|
}
|
|
1054
|
-
// Validate resource config against definition schema
|
|
1060
|
+
// Validate resource config against the definition's AUTHOR-FACING schema —
|
|
1061
|
+
// inheritance-resolved: with `base:` the child's own schema (parent config
|
|
1062
|
+
// is internal), else `merge(parent, own)` so a `base:`-less `extends` child
|
|
1063
|
+
// is validated against the inherited fields it may set. For a definition
|
|
1064
|
+
// that neither extends nor uses `base:` this is exactly its own schema.
|
|
1055
1065
|
// `kind` and `metadata` are implicit on every resource — inject them so module
|
|
1056
1066
|
// authors don't have to repeat them when using additionalProperties: false.
|
|
1057
|
-
|
|
1058
|
-
|
|
1067
|
+
const authorSchema = effectiveAuthorSchema(definition, (k) => defs.resolve(aliases.resolveKind(k) ?? k) ?? defs.resolve(k));
|
|
1068
|
+
if (authorSchema && Object.keys(authorSchema).length > 0) {
|
|
1069
|
+
const schema = authorSchema.additionalProperties === false
|
|
1059
1070
|
? {
|
|
1060
|
-
...
|
|
1071
|
+
...authorSchema,
|
|
1061
1072
|
properties: {
|
|
1062
1073
|
kind: { type: "string" },
|
|
1063
1074
|
metadata: { type: "object" },
|
|
1064
|
-
...
|
|
1075
|
+
...authorSchema.properties,
|
|
1065
1076
|
},
|
|
1066
1077
|
}
|
|
1067
|
-
:
|
|
1078
|
+
: authorSchema;
|
|
1068
1079
|
// Phase 1: CEL type checking — walk data+schema together, check env.check() return types.
|
|
1069
1080
|
// A Telo.Import's variables/secrets are a config-only contract evaluated against the
|
|
1070
1081
|
// IMPORTING module's scope, so type them from the owning module doc (matched by
|
|
@@ -1369,6 +1380,7 @@ export class StaticAnalyzer {
|
|
|
1369
1380
|
diagnostics.push(...validateStepInvokeReferences(allManifests, defs, aliases));
|
|
1370
1381
|
// Validate `extends` fields and flag legacy `capability: <UserAbstract>` overload.
|
|
1371
1382
|
diagnostics.push(...validateExtends(allManifests, defs, aliases));
|
|
1383
|
+
diagnostics.push(...validateBaseMapping(allManifests, defs, aliases));
|
|
1372
1384
|
// Validate provider coherence rules for `provide:` template-target definitions.
|
|
1373
1385
|
diagnostics.push(...validateProviderCoherence(allManifests, defs, aliases));
|
|
1374
1386
|
// Warn about exported kinds lacking a metadata.description (semantic-search input).
|
package/dist/builtins.d.ts.map
CHANGED
|
@@ -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;AAEvD,eAAO,MAAM,eAAe,EAAE,kBAAkB,
|
|
1
|
+
{"version":3,"file":"builtins.d.ts","sourceRoot":"","sources":["../src/builtins.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAEvD,eAAO,MAAM,eAAe,EAAE,kBAAkB,EAujB/C,CAAC"}
|
package/dist/builtins.js
CHANGED
|
@@ -207,6 +207,21 @@ export const KERNEL_BUILTINS = [
|
|
|
207
207
|
},
|
|
208
208
|
},
|
|
209
209
|
},
|
|
210
|
+
// `base:` ("super(...)") — construction mapping for an inherited
|
|
211
|
+
// (concrete-`extends`) definition. Its CEL is evaluated once against
|
|
212
|
+
// `self` (typed from this definition's `schema:`) to build the parent
|
|
213
|
+
// kind's config. Same `self`-only scope as a resource body.
|
|
214
|
+
base: {
|
|
215
|
+
type: "object",
|
|
216
|
+
additionalProperties: true,
|
|
217
|
+
"x-telo-context": {
|
|
218
|
+
type: "object",
|
|
219
|
+
additionalProperties: false,
|
|
220
|
+
properties: {
|
|
221
|
+
self: { "x-telo-context-from-root": "schema" },
|
|
222
|
+
},
|
|
223
|
+
},
|
|
224
|
+
},
|
|
210
225
|
},
|
|
211
226
|
},
|
|
212
227
|
},
|
|
@@ -65,7 +65,10 @@ export declare class DefinitionRegistry {
|
|
|
65
65
|
* Returns undefined when the string is malformed or the identity is not registered. */
|
|
66
66
|
resolveRef(xTeloRef: string): string | undefined;
|
|
67
67
|
resolve(kind: string): ResourceDefinition | undefined;
|
|
68
|
-
/** Returns the
|
|
68
|
+
/** Returns the reference field map for the given kind, computed lazily from the
|
|
69
|
+
* kind's AUTHOR-FACING (inheritance-resolved) schema and memoized. Lazy so a
|
|
70
|
+
* child registered before its parent still sees the parent's inherited ref
|
|
71
|
+
* slots once both are present. */
|
|
69
72
|
getFieldMap(kind: string): ReferenceFieldMap | undefined;
|
|
70
73
|
/** Returns the field map for `kind`, falling back to the alias-resolved kind when not found. */
|
|
71
74
|
getFieldMapForKind(kind: string, aliases?: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"definition-registry.d.ts","sourceRoot":"","sources":["../src/definition-registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD,OAAO,EAIL,KAAK,iBAAiB,EACvB,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"definition-registry.d.ts","sourceRoot":"","sources":["../src/definition-registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD,OAAO,EAIL,KAAK,iBAAiB,EACvB,MAAM,0BAA0B,CAAC;AAIlC,+EAA+E;AAC/E,qBAAa,kBAAkB;;IAK7B;;sFAEkF;IAClF,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;IACnC,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAqB;IAEzD,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAyC;IAC9D,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAwC;IAClE,mEAAmE;IACnE,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA+B;IAC1D;6DACyD;IACzD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA6B;IACzD;;0EAEsE;IACtE,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAA6B;IAEhE,QAAQ,CAAC,UAAU,EAAE,kBAAkB,GAAG,IAAI;IAqC9C,OAAO,CAAC,aAAa;IASrB;;;yFAGqF;IACrF,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI;IA+B1E;;;;iFAI6E;IAC7E,uBAAuB,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI;IAMtE;uFACmF;IACnF,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAIhC;4EACwE;IACxE,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAMnE;;;;oFAIgF;IAChF,gBAAgB,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,EAAE;IAWtE;;;;;;iCAM6B;IAC7B,kBAAkB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,GAAG,SAAS;IASnE,OAAO,CAAC,iBAAiB;IAczB;;;;;;;;4FAQwF;IACxF,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAUhD,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS;IAIrD;;;uCAGmC;IACnC,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,GAAG,SAAS;IAWxD,gGAAgG;IAChG,kBAAkB,CAChB,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE;QAAE,WAAW,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAA;KAAE,GACvD,iBAAiB,GAAG,SAAS;IAOhC;;;;;;;;qFAQiF;IACjF,2BAA2B,CACzB,QAAQ,EAAE,gBAAgB,EAC1B,OAAO,EAAE,aAAa,EACtB,eAAe,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,GAC1C,iBAAiB,GAAG,SAAS;IAkChC,OAAO,CAAC,uBAAuB;IA+B/B;;qEAEiE;IACjE,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,kBAAkB,EAAE;IAgBxD,KAAK,IAAI,MAAM,EAAE;CAGlB"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { KERNEL_BUILTINS } from "./builtins.js";
|
|
2
2
|
import { buildFieldMapAtPath, buildReferenceFieldMap, isSchemaFromEntry, } from "./reference-field-map.js";
|
|
3
3
|
import { createAjv, formatSingleError, navigateJsonPointer } from "./schema-compat.js";
|
|
4
|
+
import { effectiveAuthorSchema } from "./extends-resolution.js";
|
|
4
5
|
/** Pure kind → ResourceDefinition map. No controller loading, no lifecycle. */
|
|
5
6
|
export class DefinitionRegistry {
|
|
6
7
|
constructor() {
|
|
@@ -27,7 +28,11 @@ export class DefinitionRegistry {
|
|
|
27
28
|
const { name, module: mod } = definition.metadata;
|
|
28
29
|
const key = mod ? `${mod}.${name}` : name;
|
|
29
30
|
this.defs.set(key, definition);
|
|
30
|
-
|
|
31
|
+
// Field maps derive from the AUTHOR-FACING (inheritance-resolved) schema, which
|
|
32
|
+
// depends on the parent — possibly registered after this child. Clear the cache
|
|
33
|
+
// so any already-computed map recomputes against the now-larger def set; the
|
|
34
|
+
// maps rebuild lazily on first `getFieldMap` (after all defs are registered).
|
|
35
|
+
this.fieldMaps.clear();
|
|
31
36
|
// `capability` populates extendedBy for backward-compat with the legacy pattern where
|
|
32
37
|
// a concrete definition overloaded `capability: <AbstractKind>` to mean "implements
|
|
33
38
|
// this abstract." The canonical pattern is `extends` (below). Both populate the index,
|
|
@@ -186,9 +191,21 @@ export class DefinitionRegistry {
|
|
|
186
191
|
resolve(kind) {
|
|
187
192
|
return this.defs.get(kind);
|
|
188
193
|
}
|
|
189
|
-
/** Returns the
|
|
194
|
+
/** Returns the reference field map for the given kind, computed lazily from the
|
|
195
|
+
* kind's AUTHOR-FACING (inheritance-resolved) schema and memoized. Lazy so a
|
|
196
|
+
* child registered before its parent still sees the parent's inherited ref
|
|
197
|
+
* slots once both are present. */
|
|
190
198
|
getFieldMap(kind) {
|
|
191
|
-
|
|
199
|
+
const cached = this.fieldMaps.get(kind);
|
|
200
|
+
if (cached)
|
|
201
|
+
return cached;
|
|
202
|
+
const def = this.defs.get(kind);
|
|
203
|
+
if (!def)
|
|
204
|
+
return undefined;
|
|
205
|
+
const schema = effectiveAuthorSchema(def, (k) => this.resolve(k));
|
|
206
|
+
const map = buildReferenceFieldMap(schema ?? {});
|
|
207
|
+
this.fieldMaps.set(kind, map);
|
|
208
|
+
return map;
|
|
192
209
|
}
|
|
193
210
|
/** Returns the field map for `kind`, falling back to the alias-resolved kind when not found. */
|
|
194
211
|
getFieldMapForKind(kind, aliases) {
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { ResourceDefinition } from "@telorun/sdk";
|
|
2
|
+
/** Resolves a kind string (canonical or alias form, depending on the caller's
|
|
3
|
+
* registry) to its `Telo.Definition` / `Telo.Abstract`, or undefined. */
|
|
4
|
+
export type DefResolver = (kind: string) => ResourceDefinition | undefined;
|
|
5
|
+
/** The definition a given definition directly `extends`, or undefined when it
|
|
6
|
+
* extends nothing / the target can't be resolved. */
|
|
7
|
+
export declare function resolveParent(def: ResourceDefinition | undefined, resolve: DefResolver): ResourceDefinition | undefined;
|
|
8
|
+
/** The `extends` ancestor chain, nearest-first, excluding `def` itself.
|
|
9
|
+
* Cycle-guarded so a malformed self/mutual `extends` can't loop forever. */
|
|
10
|
+
export declare function ancestorChain(def: ResourceDefinition | undefined, resolve: DefResolver): ResourceDefinition[];
|
|
11
|
+
/** True when a definition carries its own controller (`controllers:`) or a
|
|
12
|
+
* template body (`invoke:` / `run:` / `provide:` / `mount:` / `resources:`). */
|
|
13
|
+
export declare function hasOwnControllerOrTemplate(def: ResourceDefinition | undefined): boolean;
|
|
14
|
+
/** The nearest concrete ancestor that provides a controller (own `controllers:`
|
|
15
|
+
* or a template body) — the definition whose controller an inherited child
|
|
16
|
+
* delegates to. Undefined when no controller-bearing concrete ancestor exists. */
|
|
17
|
+
export declare function controllerBearingAncestor(def: ResourceDefinition | undefined, resolve: DefResolver): ResourceDefinition | undefined;
|
|
18
|
+
/** True when this definition inherits its controller by delegation: it declares
|
|
19
|
+
* `extends`, has no own controller/template body, and its nearest concrete
|
|
20
|
+
* ancestor is controller-bearing. */
|
|
21
|
+
export declare function isInheritedDelegation(def: ResourceDefinition | undefined, resolve: DefResolver): boolean;
|
|
22
|
+
/** The effective (possibly inherited) capability: the nearest self-or-ancestor
|
|
23
|
+
* that declares a `capability`. Undefined when none in the chain does. */
|
|
24
|
+
export declare function inheritedCapability(def: ResourceDefinition | undefined, resolve: DefResolver): string | undefined;
|
|
25
|
+
/** The author-facing schema for a definition:
|
|
26
|
+
* - with `base:` present → the definition's **own** schema (the parent's config
|
|
27
|
+
* fields are internal, set solely through `base:`).
|
|
28
|
+
* - without `base:` but with `extends` → `merge(parent-effective, own)` (a pure
|
|
29
|
+
* additive extension; child overrides on key conflicts), reusing the same
|
|
30
|
+
* `mergeTypeSchemas` that `Type.JsonSchema.extends` uses.
|
|
31
|
+
* - no `extends` → the own schema unchanged. */
|
|
32
|
+
export declare function effectiveAuthorSchema(def: ResourceDefinition | undefined, resolve: DefResolver): Record<string, any>;
|
|
33
|
+
//# sourceMappingURL=extends-resolution.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extends-resolution.d.ts","sourceRoot":"","sources":["../src/extends-resolution.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAGvD;0EAC0E;AAC1E,MAAM,MAAM,WAAW,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,kBAAkB,GAAG,SAAS,CAAC;AAqB3E;sDACsD;AACtD,wBAAgB,aAAa,CAC3B,GAAG,EAAE,kBAAkB,GAAG,SAAS,EACnC,OAAO,EAAE,WAAW,GACnB,kBAAkB,GAAG,SAAS,CAIhC;AAED;6EAC6E;AAC7E,wBAAgB,aAAa,CAC3B,GAAG,EAAE,kBAAkB,GAAG,SAAS,EACnC,OAAO,EAAE,WAAW,GACnB,kBAAkB,EAAE,CAUtB;AAED;iFACiF;AACjF,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,kBAAkB,GAAG,SAAS,GAAG,OAAO,CAUvF;AAED;;mFAEmF;AACnF,wBAAgB,yBAAyB,CACvC,GAAG,EAAE,kBAAkB,GAAG,SAAS,EACnC,OAAO,EAAE,WAAW,GACnB,kBAAkB,GAAG,SAAS,CAMhC;AAED;;sCAEsC;AACtC,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,kBAAkB,GAAG,SAAS,EACnC,OAAO,EAAE,WAAW,GACnB,OAAO,CAGT;AAED;2EAC2E;AAC3E,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,kBAAkB,GAAG,SAAS,EACnC,OAAO,EAAE,WAAW,GACnB,MAAM,GAAG,SAAS,CAMpB;AAED;;;;;;iDAMiD;AACjD,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,kBAAkB,GAAG,SAAS,EACnC,OAAO,EAAE,WAAW,GACnB,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAOrB"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { mergeTypeSchemas } from "@telorun/sdk";
|
|
2
|
+
const body = (def) => (def ?? {});
|
|
3
|
+
/** The definition a given definition directly `extends`, or undefined when it
|
|
4
|
+
* extends nothing / the target can't be resolved. */
|
|
5
|
+
export function resolveParent(def, resolve) {
|
|
6
|
+
const ext = body(def).extends;
|
|
7
|
+
if (typeof ext !== "string" || ext.length === 0)
|
|
8
|
+
return undefined;
|
|
9
|
+
return resolve(ext);
|
|
10
|
+
}
|
|
11
|
+
/** The `extends` ancestor chain, nearest-first, excluding `def` itself.
|
|
12
|
+
* Cycle-guarded so a malformed self/mutual `extends` can't loop forever. */
|
|
13
|
+
export function ancestorChain(def, resolve) {
|
|
14
|
+
const chain = [];
|
|
15
|
+
const seen = new Set();
|
|
16
|
+
let cur = resolveParent(def, resolve);
|
|
17
|
+
while (cur && !seen.has(cur)) {
|
|
18
|
+
seen.add(cur);
|
|
19
|
+
chain.push(cur);
|
|
20
|
+
cur = resolveParent(cur, resolve);
|
|
21
|
+
}
|
|
22
|
+
return chain;
|
|
23
|
+
}
|
|
24
|
+
/** True when a definition carries its own controller (`controllers:`) or a
|
|
25
|
+
* template body (`invoke:` / `run:` / `provide:` / `mount:` / `resources:`). */
|
|
26
|
+
export function hasOwnControllerOrTemplate(def) {
|
|
27
|
+
const d = body(def);
|
|
28
|
+
return !!((d.controllers && d.controllers.length) ||
|
|
29
|
+
d.invoke ||
|
|
30
|
+
d.run ||
|
|
31
|
+
d.provide ||
|
|
32
|
+
d.mount ||
|
|
33
|
+
d.resources);
|
|
34
|
+
}
|
|
35
|
+
/** The nearest concrete ancestor that provides a controller (own `controllers:`
|
|
36
|
+
* or a template body) — the definition whose controller an inherited child
|
|
37
|
+
* delegates to. Undefined when no controller-bearing concrete ancestor exists. */
|
|
38
|
+
export function controllerBearingAncestor(def, resolve) {
|
|
39
|
+
for (const a of ancestorChain(def, resolve)) {
|
|
40
|
+
if (a.kind === "Telo.Abstract")
|
|
41
|
+
continue;
|
|
42
|
+
if (hasOwnControllerOrTemplate(a))
|
|
43
|
+
return a;
|
|
44
|
+
}
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
47
|
+
/** True when this definition inherits its controller by delegation: it declares
|
|
48
|
+
* `extends`, has no own controller/template body, and its nearest concrete
|
|
49
|
+
* ancestor is controller-bearing. */
|
|
50
|
+
export function isInheritedDelegation(def, resolve) {
|
|
51
|
+
if (!body(def).extends || hasOwnControllerOrTemplate(def))
|
|
52
|
+
return false;
|
|
53
|
+
return controllerBearingAncestor(def, resolve) !== undefined;
|
|
54
|
+
}
|
|
55
|
+
/** The effective (possibly inherited) capability: the nearest self-or-ancestor
|
|
56
|
+
* that declares a `capability`. Undefined when none in the chain does. */
|
|
57
|
+
export function inheritedCapability(def, resolve) {
|
|
58
|
+
if (body(def).capability)
|
|
59
|
+
return body(def).capability;
|
|
60
|
+
for (const a of ancestorChain(def, resolve)) {
|
|
61
|
+
if (body(a).capability)
|
|
62
|
+
return body(a).capability;
|
|
63
|
+
}
|
|
64
|
+
return undefined;
|
|
65
|
+
}
|
|
66
|
+
/** The author-facing schema for a definition:
|
|
67
|
+
* - with `base:` present → the definition's **own** schema (the parent's config
|
|
68
|
+
* fields are internal, set solely through `base:`).
|
|
69
|
+
* - without `base:` but with `extends` → `merge(parent-effective, own)` (a pure
|
|
70
|
+
* additive extension; child overrides on key conflicts), reusing the same
|
|
71
|
+
* `mergeTypeSchemas` that `Type.JsonSchema.extends` uses.
|
|
72
|
+
* - no `extends` → the own schema unchanged. */
|
|
73
|
+
export function effectiveAuthorSchema(def, resolve) {
|
|
74
|
+
const own = (body(def).schema ?? {});
|
|
75
|
+
const parent = resolveParent(def, resolve);
|
|
76
|
+
if (!parent)
|
|
77
|
+
return own;
|
|
78
|
+
if (body(def).base)
|
|
79
|
+
return own;
|
|
80
|
+
const parentSchema = effectiveAuthorSchema(parent, resolve);
|
|
81
|
+
return mergeTypeSchemas([parentSchema, own]);
|
|
82
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -4,6 +4,10 @@ export { StaticAnalyzer } from "./analyzer.js";
|
|
|
4
4
|
export type { GraphLoadError, ImportEdge, LoadedFile, LoadedGraph, LoadedModule, ParseError, } from "./loaded-types.js";
|
|
5
5
|
export { flattenForAnalyzer, flattenLoadedModule, forwardReExportManifests, parseExportEntry, reExportSpecsFromExports, resolveExportedKinds, selectModuleManifestsForAnalysis, stampReExportedKinds, type ParsedExportEntry, type ReExportSpec, } from "./flatten-for-analyzer.js";
|
|
6
6
|
export { buildEvalPaths, evalPathCovers } from "./eval-paths.js";
|
|
7
|
+
export { ancestorChain, controllerBearingAncestor, effectiveAuthorSchema, hasOwnControllerOrTemplate, inheritedCapability, isInheritedDelegation, resolveParent, } from "./extends-resolution.js";
|
|
8
|
+
export type { DefResolver } from "./extends-resolution.js";
|
|
9
|
+
export { buildReferenceFieldMap, isRefEntry, isScopeEntry } from "./reference-field-map.js";
|
|
10
|
+
export type { ReferenceFieldMap, RefFieldEntry } from "./reference-field-map.js";
|
|
7
11
|
export { visitManifest } from "./manifest-visitor.js";
|
|
8
12
|
export type { CelSiteEvent, ManifestVisitor, RefSiteEvent, ResourceEnterEvent, ResourceExitEvent, ScopeBoundaryEvent, SchemaFromSiteEvent, VisitOptions, } from "./manifest-visitor.js";
|
|
9
13
|
export { Loader } from "./manifest-loader.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,YAAY,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,YAAY,EACR,cAAc,EACd,UAAU,EACV,UAAU,EACV,WAAW,EACX,YAAY,EACZ,UAAU,GACb,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACH,kBAAkB,EAClB,mBAAmB,EACnB,wBAAwB,EACxB,gBAAgB,EAChB,wBAAwB,EACxB,oBAAoB,EACpB,gCAAgC,EAChC,oBAAoB,EACpB,KAAK,iBAAiB,EACtB,KAAK,YAAY,GACpB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,YAAY,EACR,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,EAClB,mBAAmB,EACnB,YAAY,GACf,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAC/D,YAAY,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,YAAY,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC/E,YAAY,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AACzE,YAAY,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AAC5E,OAAO,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AACnF,OAAO,EACH,sBAAsB,EACtB,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,GACtB,MAAM,wBAAwB,CAAC;AAChC,YAAY,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EACL,cAAc,EACd,aAAa,EACb,eAAe,EACf,aAAa,EACb,eAAe,EACf,cAAc,GACf,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxE,YAAY,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AACvE,OAAO,EAAE,yBAAyB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAC3E,YAAY,EACR,kBAAkB,EAClB,eAAe,EACf,iBAAiB,EACjB,WAAW,EACX,cAAc,EACd,QAAQ,EACR,aAAa,EACb,KAAK,EACR,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -2,6 +2,8 @@ export { AnalysisRegistry } from "./analysis-registry.js";
|
|
|
2
2
|
export { StaticAnalyzer } from "./analyzer.js";
|
|
3
3
|
export { flattenForAnalyzer, flattenLoadedModule, forwardReExportManifests, parseExportEntry, reExportSpecsFromExports, resolveExportedKinds, selectModuleManifestsForAnalysis, stampReExportedKinds, } from "./flatten-for-analyzer.js";
|
|
4
4
|
export { buildEvalPaths, evalPathCovers } from "./eval-paths.js";
|
|
5
|
+
export { ancestorChain, controllerBearingAncestor, effectiveAuthorSchema, hasOwnControllerOrTemplate, inheritedCapability, isInheritedDelegation, resolveParent, } from "./extends-resolution.js";
|
|
6
|
+
export { buildReferenceFieldMap, isRefEntry, isScopeEntry } from "./reference-field-map.js";
|
|
5
7
|
export { visitManifest } from "./manifest-visitor.js";
|
|
6
8
|
export { Loader } from "./manifest-loader.js";
|
|
7
9
|
export { isModuleKind, MODULE_KINDS } from "./module-kinds.js";
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ResourceManifest } from "@telorun/sdk";
|
|
2
|
+
import type { AliasResolver } from "./alias-resolver.js";
|
|
3
|
+
import type { DefinitionRegistry } from "./definition-registry.js";
|
|
4
|
+
import { type AnalysisDiagnostic } from "./types.js";
|
|
5
|
+
/**
|
|
6
|
+
* Phase 3c — Static validation of a definition's `base:` construction mapping
|
|
7
|
+
* against the parent kind's config schema. The kernel evaluates `base:` and
|
|
8
|
+
* passes the result to the inherited controller's `create()`, which validates it
|
|
9
|
+
* at boot; this mirrors that check statically so an omitted required field or a
|
|
10
|
+
* wrong literal type surfaces at `telo check`, not first boot.
|
|
11
|
+
*
|
|
12
|
+
* Diagnostics:
|
|
13
|
+
* - BASE_MISSING_REQUIRED: `base:` omits a field the parent schema requires.
|
|
14
|
+
* - BASE_UNKNOWN_FIELD: `base:` sets a field the parent schema (with
|
|
15
|
+
* `additionalProperties: false`) does not declare.
|
|
16
|
+
* - BASE_SCHEMA_MISMATCH: a CEL-free `base:` value violates the parent field's
|
|
17
|
+
* schema (wrong type / constraint). CEL-bearing values are skipped — their
|
|
18
|
+
* runtime value is unknown — but still count as present for required checks.
|
|
19
|
+
*/
|
|
20
|
+
export declare function validateBaseMapping(manifests: ResourceManifest[], registry: DefinitionRegistry, aliases: AliasResolver): AnalysisDiagnostic[];
|
|
21
|
+
//# sourceMappingURL=validate-base-mapping.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-base-mapping.d.ts","sourceRoot":"","sources":["../src/validate-base-mapping.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAsB,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAEnE,OAAO,EAAsB,KAAK,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAezE;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,gBAAgB,EAAE,EAC7B,QAAQ,EAAE,kBAAkB,EAC5B,OAAO,EAAE,aAAa,GACrB,kBAAkB,EAAE,CAwCtB"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { isCompiledValue } from "@telorun/sdk";
|
|
2
|
+
import { effectiveAuthorSchema, resolveParent } from "./extends-resolution.js";
|
|
3
|
+
import { DiagnosticSeverity } from "./types.js";
|
|
4
|
+
const SOURCE = "telo-analyzer";
|
|
5
|
+
/** True when a value subtree contains a compiled CEL leaf — such a value can
|
|
6
|
+
* produce anything at runtime, so its type is not statically checkable. */
|
|
7
|
+
function containsCel(value) {
|
|
8
|
+
if (isCompiledValue(value))
|
|
9
|
+
return true;
|
|
10
|
+
if (Array.isArray(value))
|
|
11
|
+
return value.some(containsCel);
|
|
12
|
+
if (value && typeof value === "object") {
|
|
13
|
+
return Object.values(value).some(containsCel);
|
|
14
|
+
}
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Phase 3c — Static validation of a definition's `base:` construction mapping
|
|
19
|
+
* against the parent kind's config schema. The kernel evaluates `base:` and
|
|
20
|
+
* passes the result to the inherited controller's `create()`, which validates it
|
|
21
|
+
* at boot; this mirrors that check statically so an omitted required field or a
|
|
22
|
+
* wrong literal type surfaces at `telo check`, not first boot.
|
|
23
|
+
*
|
|
24
|
+
* Diagnostics:
|
|
25
|
+
* - BASE_MISSING_REQUIRED: `base:` omits a field the parent schema requires.
|
|
26
|
+
* - BASE_UNKNOWN_FIELD: `base:` sets a field the parent schema (with
|
|
27
|
+
* `additionalProperties: false`) does not declare.
|
|
28
|
+
* - BASE_SCHEMA_MISMATCH: a CEL-free `base:` value violates the parent field's
|
|
29
|
+
* schema (wrong type / constraint). CEL-bearing values are skipped — their
|
|
30
|
+
* runtime value is unknown — but still count as present for required checks.
|
|
31
|
+
*/
|
|
32
|
+
export function validateBaseMapping(manifests, registry, aliases) {
|
|
33
|
+
const diagnostics = [];
|
|
34
|
+
const resolveDef = (k) => registry.resolve(aliases.resolveKind(k) ?? k) ?? registry.resolve(k);
|
|
35
|
+
const importedModules = new Set();
|
|
36
|
+
for (const m of manifests) {
|
|
37
|
+
if (m.kind !== "Telo.Import")
|
|
38
|
+
continue;
|
|
39
|
+
const resolved = m.metadata?.resolvedModuleName;
|
|
40
|
+
if (resolved)
|
|
41
|
+
importedModules.add(resolved);
|
|
42
|
+
}
|
|
43
|
+
for (const m of manifests) {
|
|
44
|
+
if (m.kind !== "Telo.Definition")
|
|
45
|
+
continue;
|
|
46
|
+
const base = m.base;
|
|
47
|
+
if (!base || typeof base !== "object" || Array.isArray(base))
|
|
48
|
+
continue;
|
|
49
|
+
const name = m.metadata?.name;
|
|
50
|
+
if (!name)
|
|
51
|
+
continue;
|
|
52
|
+
const ownModule = m.metadata?.module;
|
|
53
|
+
if (ownModule && importedModules.has(ownModule))
|
|
54
|
+
continue;
|
|
55
|
+
const parent = resolveParent(m, resolveDef);
|
|
56
|
+
// Missing / unresolved `extends` is already reported by validateExtends.
|
|
57
|
+
if (!parent)
|
|
58
|
+
continue;
|
|
59
|
+
const parentSchema = effectiveAuthorSchema(parent, resolveDef);
|
|
60
|
+
if (!parentSchema || typeof parentSchema !== "object")
|
|
61
|
+
continue;
|
|
62
|
+
const filePath = m.metadata?.source;
|
|
63
|
+
const resource = { kind: m.kind, name };
|
|
64
|
+
const label = `${m.kind}/${name}`;
|
|
65
|
+
checkObject(base, parentSchema, "base", {
|
|
66
|
+
diagnostics,
|
|
67
|
+
registry,
|
|
68
|
+
label,
|
|
69
|
+
resource,
|
|
70
|
+
filePath,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
return diagnostics;
|
|
74
|
+
}
|
|
75
|
+
function checkObject(value, schema, path, ctx) {
|
|
76
|
+
const properties = (schema.properties ?? {});
|
|
77
|
+
const required = Array.isArray(schema.required) ? schema.required : [];
|
|
78
|
+
const additionalFalse = schema.additionalProperties === false;
|
|
79
|
+
for (const req of required) {
|
|
80
|
+
if (!(req in value)) {
|
|
81
|
+
ctx.diagnostics.push({
|
|
82
|
+
severity: DiagnosticSeverity.Error,
|
|
83
|
+
code: "BASE_MISSING_REQUIRED",
|
|
84
|
+
source: SOURCE,
|
|
85
|
+
message: `${ctx.label}: '${path}' does not set required parent field '${req}'.`,
|
|
86
|
+
data: { resource: ctx.resource, filePath: ctx.filePath, path },
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
for (const [key, fieldValue] of Object.entries(value)) {
|
|
91
|
+
const fieldPath = `${path}.${key}`;
|
|
92
|
+
const propSchema = properties[key];
|
|
93
|
+
if (!propSchema) {
|
|
94
|
+
if (additionalFalse) {
|
|
95
|
+
ctx.diagnostics.push({
|
|
96
|
+
severity: DiagnosticSeverity.Error,
|
|
97
|
+
code: "BASE_UNKNOWN_FIELD",
|
|
98
|
+
source: SOURCE,
|
|
99
|
+
message: `${ctx.label}: '${fieldPath}' is not a field of the parent kind's schema.`,
|
|
100
|
+
data: { resource: ctx.resource, filePath: ctx.filePath, path: fieldPath },
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
// A CEL-bearing value produces its shape at runtime — not statically
|
|
106
|
+
// checkable. Recurse into a partially-CEL nested object so its literal
|
|
107
|
+
// sub-fields still get validated; fully-literal values validate directly.
|
|
108
|
+
if (containsCel(fieldValue)) {
|
|
109
|
+
if (fieldValue &&
|
|
110
|
+
typeof fieldValue === "object" &&
|
|
111
|
+
!Array.isArray(fieldValue) &&
|
|
112
|
+
!isCompiledValue(fieldValue) &&
|
|
113
|
+
propSchema.type === "object" &&
|
|
114
|
+
propSchema.properties) {
|
|
115
|
+
checkObject(fieldValue, propSchema, fieldPath, ctx);
|
|
116
|
+
}
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
const issues = ctx.registry.validateWithRefs(fieldValue, propSchema);
|
|
120
|
+
for (const issue of issues) {
|
|
121
|
+
ctx.diagnostics.push({
|
|
122
|
+
severity: DiagnosticSeverity.Error,
|
|
123
|
+
code: "BASE_SCHEMA_MISMATCH",
|
|
124
|
+
source: SOURCE,
|
|
125
|
+
message: `${ctx.label}: '${fieldPath}' does not match the parent field's schema: ${issue}`,
|
|
126
|
+
data: { resource: ctx.resource, filePath: ctx.filePath, path: fieldPath },
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate-extends.d.ts","sourceRoot":"","sources":["../src/validate-extends.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"validate-extends.d.ts","sourceRoot":"","sources":["../src/validate-extends.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAsB,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAEnE,OAAO,EAAsB,KAAK,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAOzE;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,eAAe,CAC7B,SAAS,EAAE,gBAAgB,EAAE,EAC7B,QAAQ,EAAE,kBAAkB,EAC5B,OAAO,EAAE,aAAa,GACrB,kBAAkB,EAAE,CAwJtB"}
|
package/dist/validate-extends.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { inheritedCapability } from "./extends-resolution.js";
|
|
1
2
|
import { DiagnosticSeverity } from "./types.js";
|
|
2
3
|
const SOURCE = "telo-analyzer";
|
|
3
4
|
/** Alias-form pattern for `extends`: "<Alias>.<AbstractName>", two PascalCase segments. */
|
|
@@ -114,15 +115,25 @@ export function validateExtends(manifests, registry, aliases) {
|
|
|
114
115
|
data: { resource, filePath, path: "extends" },
|
|
115
116
|
});
|
|
116
117
|
}
|
|
117
|
-
else
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
118
|
+
else {
|
|
119
|
+
// General single inheritance: any concrete or abstract kind may be
|
|
120
|
+
// extended. What inheritance must NOT do is change the lifecycle
|
|
121
|
+
// role — a child that restates `capability` differently from an
|
|
122
|
+
// ancestor is a hard error (no silent capability change).
|
|
123
|
+
const resolveDef = (k) => registry.resolve(aliases.resolveKind(k) ?? k) ?? registry.resolve(k);
|
|
124
|
+
const ownCap = m.capability;
|
|
125
|
+
const ownCapResolved = typeof ownCap === "string" ? aliases.resolveKind(ownCap) ?? ownCap : undefined;
|
|
126
|
+
const ancestorCap = inheritedCapability(targetDef, resolveDef);
|
|
127
|
+
if (ownCapResolved && ancestorCap && ownCapResolved !== ancestorCap) {
|
|
128
|
+
diagnostics.push({
|
|
129
|
+
severity: DiagnosticSeverity.Error,
|
|
130
|
+
code: "EXTENDS_CAPABILITY_MISMATCH",
|
|
131
|
+
source: SOURCE,
|
|
132
|
+
message: `${label}: declares 'capability: ${ownCap}' but extends '${extendsValue}' whose inherited capability is '${ancestorCap}'. ` +
|
|
133
|
+
`Capability is inherited and immutable — omit 'capability' or restate it identically.`,
|
|
134
|
+
data: { resource, filePath, path: "capability" },
|
|
135
|
+
});
|
|
136
|
+
}
|
|
126
137
|
}
|
|
127
138
|
}
|
|
128
139
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate-provider-coherence.d.ts","sourceRoot":"","sources":["../src/validate-provider-coherence.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"validate-provider-coherence.d.ts","sourceRoot":"","sources":["../src/validate-provider-coherence.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAsB,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAEnE,OAAO,EAAsB,KAAK,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAIzE;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,yBAAyB,CACvC,SAAS,EAAE,gBAAgB,EAAE,EAC7B,QAAQ,EAAE,kBAAkB,EAC5B,OAAO,EAAE,aAAa,GACrB,kBAAkB,EAAE,CA+NtB"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { controllerBearingAncestor } from "./extends-resolution.js";
|
|
1
2
|
import { DiagnosticSeverity } from "./types.js";
|
|
2
3
|
const SOURCE = "telo-analyzer";
|
|
3
4
|
/**
|
|
@@ -214,7 +215,13 @@ export function validateProviderCoherence(manifests, registry, aliases) {
|
|
|
214
215
|
}
|
|
215
216
|
}
|
|
216
217
|
}
|
|
217
|
-
|
|
218
|
+
// A definition that inherits a controller by delegation (concrete `extends`,
|
|
219
|
+
// no own controller/template) satisfies the implementation requirement
|
|
220
|
+
// through its parent — `base:` supplies the parent's config.
|
|
221
|
+
const resolveDef = (k) => registry.resolve(aliases.resolveKind(k) ?? k) ?? registry.resolve(k);
|
|
222
|
+
const inheritsController = typeof md.extends === "string" &&
|
|
223
|
+
controllerBearingAncestor(m, resolveDef) !== undefined;
|
|
224
|
+
if (capability === "Telo.Provider" && !hasControllers && !hasProvide && !inheritsController) {
|
|
218
225
|
diagnostics.push({
|
|
219
226
|
severity: DiagnosticSeverity.Error,
|
|
220
227
|
code: "PROVIDER_MISSING_IMPLEMENTATION",
|
|
@@ -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;
|
|
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"}
|