@telorun/analyzer 0.18.0 → 0.19.1
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/README.md +1 -1
- package/dist/analysis-registry.d.ts +17 -0
- package/dist/analysis-registry.d.ts.map +1 -1
- package/dist/analysis-registry.js +48 -10
- package/dist/analyzer.d.ts.map +1 -1
- package/dist/analyzer.js +4 -1
- package/package.json +3 -3
- package/src/analysis-registry.ts +46 -10
- package/src/analyzer.ts +5 -1
package/README.md
CHANGED
|
@@ -64,6 +64,13 @@ export declare class AnalysisRegistry {
|
|
|
64
64
|
* type reference is left unresolved (returns undefined) so the caller can fall
|
|
65
65
|
* back to a freeform map. Undefined when the kind declares no input contract. */
|
|
66
66
|
inputTypeForKind(kind: string): Record<string, unknown> | undefined;
|
|
67
|
+
/** Resolves the JSON Schema for a kind's `invoke()` / `run()` output, for
|
|
68
|
+
* editor hosts that render a typed output signature. Mirrors
|
|
69
|
+
* {@link inputTypeForKind}: the definition's own `outputType`, then the
|
|
70
|
+
* `extends`-declared abstract's `outputType`. Resolves the inline and
|
|
71
|
+
* raw-schema forms; a bare named type reference is left unresolved. Undefined
|
|
72
|
+
* when the kind declares no output contract. */
|
|
73
|
+
outputTypeForKind(kind: string): Record<string, unknown> | undefined;
|
|
67
74
|
private capabilitiesForRefs;
|
|
68
75
|
/**
|
|
69
76
|
* Walks a manifest's annotation sites (refs, scopes, schema-from, CEL) via
|
|
@@ -96,6 +103,16 @@ export declare class AnalysisRegistry {
|
|
|
96
103
|
/** Returns the closest user-facing kind to `badKind`, or undefined when nothing
|
|
97
104
|
* is close enough (or multiple candidates tie). Case-sensitive. */
|
|
98
105
|
suggestKind(badKind: string): string | undefined;
|
|
106
|
+
/** Returns the **canonical** (`module.Type`) kinds that satisfy an `x-telo-ref`
|
|
107
|
+
* constraint — an abstract target expands to its implementations (via the
|
|
108
|
+
* extends / capability index), a concrete target yields just itself.
|
|
109
|
+
* Resolution mirrors `validateReferences.checkKind`. Unlike
|
|
110
|
+
* {@link userFacingKindsForRef} this is import-independent: it includes
|
|
111
|
+
* locally-defined kinds (no alias), so callers can test whether an existing
|
|
112
|
+
* resource's kind satisfies the ref by canonicalizing it (`resolveKind`) and
|
|
113
|
+
* membership-checking here. Returns `undefined` when the ref can't be
|
|
114
|
+
* resolved (e.g. unregistered identity). */
|
|
115
|
+
acceptedKindsForRef(xTeloRef: string): Set<string> | undefined;
|
|
99
116
|
/** Returns every user-facing (alias-form) kind that satisfies the given
|
|
100
117
|
* `x-telo-ref` constraint string (e.g. `"telo#Invocable"`, `"std/sql#Connection"`).
|
|
101
118
|
* Resolution mirrors `validateReferences.checkKind`: abstract targets expand to
|
|
@@ -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,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,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;;;;;gEAK4D;IAC5D,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS;
|
|
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,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;IAoB9D;;;;;gEAK4D;IAC5D,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS;IAiB7D,qFAAqF;IACrF,QAAQ,IAAI,eAAe;CAG5B"}
|
|
@@ -112,6 +112,29 @@ export class AnalysisRegistry {
|
|
|
112
112
|
}
|
|
113
113
|
return undefined;
|
|
114
114
|
}
|
|
115
|
+
/** Resolves the JSON Schema for a kind's `invoke()` / `run()` output, for
|
|
116
|
+
* editor hosts that render a typed output signature. Mirrors
|
|
117
|
+
* {@link inputTypeForKind}: the definition's own `outputType`, then the
|
|
118
|
+
* `extends`-declared abstract's `outputType`. Resolves the inline and
|
|
119
|
+
* raw-schema forms; a bare named type reference is left unresolved. Undefined
|
|
120
|
+
* when the kind declares no output contract. */
|
|
121
|
+
outputTypeForKind(kind) {
|
|
122
|
+
const def = this.resolveDefinition(kind);
|
|
123
|
+
if (!def)
|
|
124
|
+
return undefined;
|
|
125
|
+
const own = resolveTypeFieldToSchema(def.outputType, []);
|
|
126
|
+
if (own)
|
|
127
|
+
return own;
|
|
128
|
+
if (def.extends) {
|
|
129
|
+
const abstractDef = this.resolveDefinition(def.extends);
|
|
130
|
+
if (abstractDef) {
|
|
131
|
+
const inherited = resolveTypeFieldToSchema(abstractDef.outputType, []);
|
|
132
|
+
if (inherited)
|
|
133
|
+
return inherited;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return undefined;
|
|
137
|
+
}
|
|
115
138
|
capabilitiesForRefs(refs) {
|
|
116
139
|
const out = [];
|
|
117
140
|
for (const ref of refs) {
|
|
@@ -168,31 +191,46 @@ export class AnalysisRegistry {
|
|
|
168
191
|
suggestKind(badKind) {
|
|
169
192
|
return computeSuggestKind(badKind, this.aliases, this.defs);
|
|
170
193
|
}
|
|
171
|
-
/** Returns
|
|
172
|
-
*
|
|
173
|
-
*
|
|
174
|
-
*
|
|
175
|
-
*
|
|
176
|
-
*
|
|
177
|
-
|
|
194
|
+
/** Returns the **canonical** (`module.Type`) kinds that satisfy an `x-telo-ref`
|
|
195
|
+
* constraint — an abstract target expands to its implementations (via the
|
|
196
|
+
* extends / capability index), a concrete target yields just itself.
|
|
197
|
+
* Resolution mirrors `validateReferences.checkKind`. Unlike
|
|
198
|
+
* {@link userFacingKindsForRef} this is import-independent: it includes
|
|
199
|
+
* locally-defined kinds (no alias), so callers can test whether an existing
|
|
200
|
+
* resource's kind satisfies the ref by canonicalizing it (`resolveKind`) and
|
|
201
|
+
* membership-checking here. Returns `undefined` when the ref can't be
|
|
202
|
+
* resolved (e.g. unregistered identity). */
|
|
203
|
+
acceptedKindsForRef(xTeloRef) {
|
|
178
204
|
const targetKind = this.defs.resolveRef(xTeloRef);
|
|
179
205
|
if (!targetKind)
|
|
180
206
|
return undefined;
|
|
181
207
|
const targetDef = this.defs.resolve(targetKind);
|
|
182
208
|
if (!targetDef)
|
|
183
209
|
return undefined;
|
|
184
|
-
const
|
|
210
|
+
const out = new Set();
|
|
185
211
|
if (targetDef.kind === "Telo.Abstract") {
|
|
186
212
|
for (const def of this.defs.getByExtends(targetKind)) {
|
|
187
213
|
const module = def.metadata?.module;
|
|
188
214
|
if (module && def.metadata?.name) {
|
|
189
|
-
|
|
215
|
+
out.add(`${module}.${def.metadata.name}`);
|
|
190
216
|
}
|
|
191
217
|
}
|
|
192
218
|
}
|
|
193
219
|
else {
|
|
194
|
-
|
|
220
|
+
out.add(targetKind);
|
|
195
221
|
}
|
|
222
|
+
return out;
|
|
223
|
+
}
|
|
224
|
+
/** Returns every user-facing (alias-form) kind that satisfies the given
|
|
225
|
+
* `x-telo-ref` constraint string (e.g. `"telo#Invocable"`, `"std/sql#Connection"`).
|
|
226
|
+
* Resolution mirrors `validateReferences.checkKind`: abstract targets expand to
|
|
227
|
+
* the set of definitions extending them; concrete targets yield just themselves.
|
|
228
|
+
* Returns `undefined` when the ref can't be resolved (e.g. unregistered identity),
|
|
229
|
+
* so callers can fall back to the unfiltered kind list. */
|
|
230
|
+
userFacingKindsForRef(xTeloRef) {
|
|
231
|
+
const canonicalKinds = this.acceptedKindsForRef(xTeloRef);
|
|
232
|
+
if (!canonicalKinds)
|
|
233
|
+
return undefined;
|
|
196
234
|
const out = new Set();
|
|
197
235
|
for (const kind of canonicalKinds) {
|
|
198
236
|
const dot = kind.indexOf(".");
|
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;AAIzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAGL,KAAK,WAAW,EACjB,MAAM,sBAAsB,CAAC;AAiB9B,OAAO,EAAsB,KAAK,kBAAkB,EAAE,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"analyzer.d.ts","sourceRoot":"","sources":["../src/analyzer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAsB,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAIzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAGL,KAAK,WAAW,EACjB,MAAM,sBAAsB,CAAC;AAiB9B,OAAO,EAAsB,KAAK,kBAAkB,EAAE,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AA2hB/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;IAypBvB,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;IAqBrB,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
|
@@ -442,8 +442,11 @@ function collectCelTypeIssues(data, schema, path, definition, manifest, baseType
|
|
|
442
442
|
}
|
|
443
443
|
else if (data !== null && typeof data === "object") {
|
|
444
444
|
const props = (schema.properties ?? {});
|
|
445
|
+
const mapValueSchema = schema.additionalProperties && typeof schema.additionalProperties === "object"
|
|
446
|
+
? schema.additionalProperties
|
|
447
|
+
: {};
|
|
445
448
|
for (const [k, v] of Object.entries(data)) {
|
|
446
|
-
issues.push(...collectCelTypeIssues(v, (props[k] ??
|
|
449
|
+
issues.push(...collectCelTypeIssues(v, (props[k] ?? mapValueSchema), path ? `${path}.${k}` : k, definition, manifest, baseTypedEnv, rootEnv, rootModuleManifest));
|
|
447
450
|
}
|
|
448
451
|
}
|
|
449
452
|
return issues;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@telorun/analyzer",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.19.1",
|
|
4
4
|
"description": "Telo Analyzer - Static manifest validator for Telo manifests.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"telo",
|
|
@@ -42,13 +42,13 @@
|
|
|
42
42
|
"ajv-formats": "^3.0.1",
|
|
43
43
|
"jsonpath-plus": "^10.3.0",
|
|
44
44
|
"yaml": "^2.8.3",
|
|
45
|
-
"@telorun/templating": "0.
|
|
45
|
+
"@telorun/templating": "0.5.0"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"@types/node": "^20.0.0",
|
|
49
49
|
"typescript": "^5.0.0",
|
|
50
50
|
"vitest": "^2.1.8",
|
|
51
|
-
"@telorun/sdk": "0.
|
|
51
|
+
"@telorun/sdk": "0.21.0"
|
|
52
52
|
},
|
|
53
53
|
"peerDependencies": {
|
|
54
54
|
"@telorun/sdk": "*"
|
package/src/analysis-registry.ts
CHANGED
|
@@ -146,6 +146,27 @@ export class AnalysisRegistry {
|
|
|
146
146
|
return undefined;
|
|
147
147
|
}
|
|
148
148
|
|
|
149
|
+
/** Resolves the JSON Schema for a kind's `invoke()` / `run()` output, for
|
|
150
|
+
* editor hosts that render a typed output signature. Mirrors
|
|
151
|
+
* {@link inputTypeForKind}: the definition's own `outputType`, then the
|
|
152
|
+
* `extends`-declared abstract's `outputType`. Resolves the inline and
|
|
153
|
+
* raw-schema forms; a bare named type reference is left unresolved. Undefined
|
|
154
|
+
* when the kind declares no output contract. */
|
|
155
|
+
outputTypeForKind(kind: string): Record<string, unknown> | undefined {
|
|
156
|
+
const def = this.resolveDefinition(kind);
|
|
157
|
+
if (!def) return undefined;
|
|
158
|
+
const own = resolveTypeFieldToSchema(def.outputType, []);
|
|
159
|
+
if (own) return own;
|
|
160
|
+
if (def.extends) {
|
|
161
|
+
const abstractDef = this.resolveDefinition(def.extends);
|
|
162
|
+
if (abstractDef) {
|
|
163
|
+
const inherited = resolveTypeFieldToSchema(abstractDef.outputType, []);
|
|
164
|
+
if (inherited) return inherited;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
return undefined;
|
|
168
|
+
}
|
|
169
|
+
|
|
149
170
|
private capabilitiesForRefs(refs: string[]): string[] {
|
|
150
171
|
const out: string[] = [];
|
|
151
172
|
for (const ref of refs) {
|
|
@@ -213,29 +234,44 @@ export class AnalysisRegistry {
|
|
|
213
234
|
return computeSuggestKind(badKind, this.aliases, this.defs);
|
|
214
235
|
}
|
|
215
236
|
|
|
216
|
-
/** Returns
|
|
217
|
-
*
|
|
218
|
-
*
|
|
219
|
-
*
|
|
220
|
-
*
|
|
221
|
-
*
|
|
222
|
-
|
|
237
|
+
/** Returns the **canonical** (`module.Type`) kinds that satisfy an `x-telo-ref`
|
|
238
|
+
* constraint — an abstract target expands to its implementations (via the
|
|
239
|
+
* extends / capability index), a concrete target yields just itself.
|
|
240
|
+
* Resolution mirrors `validateReferences.checkKind`. Unlike
|
|
241
|
+
* {@link userFacingKindsForRef} this is import-independent: it includes
|
|
242
|
+
* locally-defined kinds (no alias), so callers can test whether an existing
|
|
243
|
+
* resource's kind satisfies the ref by canonicalizing it (`resolveKind`) and
|
|
244
|
+
* membership-checking here. Returns `undefined` when the ref can't be
|
|
245
|
+
* resolved (e.g. unregistered identity). */
|
|
246
|
+
acceptedKindsForRef(xTeloRef: string): Set<string> | undefined {
|
|
223
247
|
const targetKind = this.defs.resolveRef(xTeloRef);
|
|
224
248
|
if (!targetKind) return undefined;
|
|
225
249
|
const targetDef = this.defs.resolve(targetKind);
|
|
226
250
|
if (!targetDef) return undefined;
|
|
227
251
|
|
|
228
|
-
const
|
|
252
|
+
const out = new Set<string>();
|
|
229
253
|
if (targetDef.kind === "Telo.Abstract") {
|
|
230
254
|
for (const def of this.defs.getByExtends(targetKind)) {
|
|
231
255
|
const module = (def.metadata as { module?: string } | undefined)?.module;
|
|
232
256
|
if (module && def.metadata?.name) {
|
|
233
|
-
|
|
257
|
+
out.add(`${module}.${def.metadata.name as string}`);
|
|
234
258
|
}
|
|
235
259
|
}
|
|
236
260
|
} else {
|
|
237
|
-
|
|
261
|
+
out.add(targetKind);
|
|
238
262
|
}
|
|
263
|
+
return out;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/** Returns every user-facing (alias-form) kind that satisfies the given
|
|
267
|
+
* `x-telo-ref` constraint string (e.g. `"telo#Invocable"`, `"std/sql#Connection"`).
|
|
268
|
+
* Resolution mirrors `validateReferences.checkKind`: abstract targets expand to
|
|
269
|
+
* the set of definitions extending them; concrete targets yield just themselves.
|
|
270
|
+
* Returns `undefined` when the ref can't be resolved (e.g. unregistered identity),
|
|
271
|
+
* so callers can fall back to the unfiltered kind list. */
|
|
272
|
+
userFacingKindsForRef(xTeloRef: string): string[] | undefined {
|
|
273
|
+
const canonicalKinds = this.acceptedKindsForRef(xTeloRef);
|
|
274
|
+
if (!canonicalKinds) return undefined;
|
|
239
275
|
|
|
240
276
|
const out = new Set<string>();
|
|
241
277
|
for (const kind of canonicalKinds) {
|
package/src/analyzer.ts
CHANGED
|
@@ -540,11 +540,15 @@ function collectCelTypeIssues(
|
|
|
540
540
|
}
|
|
541
541
|
} else if (data !== null && typeof data === "object") {
|
|
542
542
|
const props = (schema.properties ?? {}) as Record<string, any>;
|
|
543
|
+
const mapValueSchema =
|
|
544
|
+
schema.additionalProperties && typeof schema.additionalProperties === "object"
|
|
545
|
+
? (schema.additionalProperties as Record<string, any>)
|
|
546
|
+
: {};
|
|
543
547
|
for (const [k, v] of Object.entries(data as Record<string, unknown>)) {
|
|
544
548
|
issues.push(
|
|
545
549
|
...collectCelTypeIssues(
|
|
546
550
|
v,
|
|
547
|
-
(props[k] ??
|
|
551
|
+
(props[k] ?? mapValueSchema) as Record<string, any>,
|
|
548
552
|
path ? `${path}.${k}` : k,
|
|
549
553
|
definition,
|
|
550
554
|
manifest,
|