@telorun/analyzer 0.65.0 → 0.67.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/analyzer.d.ts +1 -1
- package/dist/analyzer.d.ts.map +1 -1
- package/dist/analyzer.js +194 -65
- package/dist/builtins.d.ts.map +1 -1
- package/dist/builtins.js +67 -16
- package/dist/call-graph.d.ts.map +1 -1
- package/dist/call-graph.js +7 -1
- package/dist/cel-environment.d.ts +12 -0
- package/dist/cel-environment.d.ts.map +1 -1
- package/dist/cel-environment.js +35 -19
- package/dist/cel-scope.d.ts +8 -0
- package/dist/cel-scope.d.ts.map +1 -1
- package/dist/cel-scope.js +89 -11
- package/dist/definition-registry.d.ts +41 -0
- package/dist/definition-registry.d.ts.map +1 -1
- package/dist/definition-registry.js +76 -0
- package/dist/dependency-graph.d.ts.map +1 -1
- package/dist/dependency-graph.js +65 -0
- package/dist/eval-paths.d.ts +68 -0
- package/dist/eval-paths.d.ts.map +1 -1
- package/dist/eval-paths.js +138 -0
- package/dist/flatten-for-analyzer.d.ts +37 -1
- package/dist/flatten-for-analyzer.d.ts.map +1 -1
- package/dist/flatten-for-analyzer.js +104 -5
- package/dist/import-resolution-diagnostics.d.ts +1 -1
- package/dist/import-resolution-diagnostics.js +1 -1
- package/dist/index.d.ts +12 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -6
- package/dist/inline-imports.d.ts.map +1 -1
- package/dist/inline-imports.js +1 -0
- package/dist/manifest-visitor.d.ts +4 -0
- package/dist/manifest-visitor.d.ts.map +1 -1
- package/dist/manifest-visitor.js +36 -1
- package/dist/migrations/entries/index.d.ts.map +1 -1
- package/dist/migrations/entries/index.js +2 -0
- package/dist/migrations/entries/schema-prepare-bucket.json +27 -0
- package/dist/peer-binding.d.ts +232 -0
- package/dist/peer-binding.d.ts.map +1 -0
- package/dist/peer-binding.js +418 -0
- package/dist/precompile.d.ts.map +1 -1
- package/dist/precompile.js +8 -0
- package/dist/ref-slot.d.ts +13 -0
- package/dist/ref-slot.d.ts.map +1 -1
- package/dist/ref-slot.js +26 -0
- package/dist/reference-field-map.d.ts +28 -0
- package/dist/reference-field-map.d.ts.map +1 -1
- package/dist/reference-field-map.js +25 -0
- package/dist/referrer-rule.d.ts +17 -0
- package/dist/referrer-rule.d.ts.map +1 -1
- package/dist/referrer-rule.js +4 -1
- package/dist/release/index.d.ts +1 -1
- package/dist/release/index.js +1 -1
- package/dist/resolve-ref-sentinels.d.ts.map +1 -1
- package/dist/resolve-ref-sentinels.js +14 -1
- package/dist/resource-input.d.ts +75 -0
- package/dist/resource-input.d.ts.map +1 -0
- package/dist/resource-input.js +90 -0
- package/dist/resource-rule.d.ts +40 -27
- package/dist/resource-rule.d.ts.map +1 -1
- package/dist/resource-rule.js +61 -7
- package/dist/rule-condition.d.ts +11 -0
- package/dist/rule-condition.d.ts.map +1 -1
- package/dist/rule-condition.js +13 -0
- package/dist/schema-projection.d.ts +119 -4
- package/dist/schema-projection.d.ts.map +1 -1
- package/dist/schema-projection.js +213 -18
- package/dist/system-kinds.d.ts +7 -2
- package/dist/system-kinds.d.ts.map +1 -1
- package/dist/system-kinds.js +7 -2
- package/dist/telo-version.d.ts +1 -1
- package/dist/telo-version.js +1 -1
- package/dist/template-body.d.ts +50 -0
- package/dist/template-body.d.ts.map +1 -0
- package/dist/template-body.js +58 -0
- package/dist/validate-cel-context.d.ts +1 -17
- package/dist/validate-cel-context.d.ts.map +1 -1
- package/dist/validate-cel-context.js +73 -78
- package/dist/validate-identifier-names.d.ts.map +1 -1
- package/dist/validate-identifier-names.js +17 -2
- package/dist/validate-reference-forms.d.ts +10 -0
- package/dist/validate-reference-forms.d.ts.map +1 -1
- package/dist/validate-reference-forms.js +23 -0
- package/dist/validate-references.d.ts +17 -0
- package/dist/validate-references.d.ts.map +1 -1
- package/dist/validate-references.js +77 -18
- package/dist/validate-referrer-rules.d.ts +38 -4
- package/dist/validate-referrer-rules.d.ts.map +1 -1
- package/dist/validate-referrer-rules.js +139 -31
- package/dist/validate-resource-inputs.d.ts +35 -0
- package/dist/validate-resource-inputs.d.ts.map +1 -0
- package/dist/validate-resource-inputs.js +319 -0
- package/dist/validate-resource-rules.d.ts +11 -2
- package/dist/validate-resource-rules.d.ts.map +1 -1
- package/dist/validate-resource-rules.js +18 -12
- package/dist/validate-schema-projection.d.ts.map +1 -1
- package/dist/validate-schema-projection.js +33 -2
- package/dist/validate-template-dispatch.d.ts +27 -0
- package/dist/validate-template-dispatch.d.ts.map +1 -0
- package/dist/validate-template-dispatch.js +95 -0
- package/dist/with-synthetic-positions.d.ts +1 -1
- package/dist/with-synthetic-positions.js +1 -1
- package/package.json +3 -3
- package/src/analyzer.ts +236 -70
- package/src/builtins.ts +69 -16
- package/src/call-graph.ts +7 -1
- package/src/cel-environment.ts +48 -19
- package/src/cel-scope.ts +113 -19
- package/src/definition-registry.ts +78 -0
- package/src/dependency-graph.ts +66 -0
- package/src/eval-paths.ts +152 -0
- package/src/flatten-for-analyzer.ts +117 -4
- package/src/import-resolution-diagnostics.ts +1 -1
- package/src/index.ts +57 -4
- package/src/inline-imports.ts +1 -0
- package/src/manifest-visitor.ts +41 -1
- package/src/migrations/entries/index.ts +2 -0
- package/src/migrations/entries/schema-prepare-bucket.json +27 -0
- package/src/peer-binding.ts +641 -0
- package/src/precompile.ts +8 -0
- package/src/ref-slot.ts +36 -0
- package/src/reference-field-map.ts +42 -0
- package/src/referrer-rule.ts +20 -1
- package/src/release/index.ts +1 -1
- package/src/resolve-ref-sentinels.ts +12 -1
- package/src/resource-input.ts +132 -0
- package/src/resource-rule.ts +69 -7
- package/src/rule-condition.ts +15 -0
- package/src/schema-projection.ts +302 -20
- package/src/system-kinds.ts +7 -2
- package/src/telo-version.ts +1 -1
- package/src/template-body.ts +104 -0
- package/src/validate-cel-context.ts +73 -78
- package/src/validate-identifier-names.ts +18 -3
- package/src/validate-reference-forms.ts +22 -0
- package/src/validate-references.ts +85 -16
- package/src/validate-referrer-rules.ts +215 -28
- package/src/validate-resource-inputs.ts +367 -0
- package/src/validate-resource-rules.ts +26 -12
- package/src/validate-schema-projection.ts +50 -1
- package/src/validate-template-dispatch.ts +99 -0
- package/src/with-synthetic-positions.ts +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema-projection.d.ts","sourceRoot":"","sources":["../src/schema-projection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;
|
|
1
|
+
{"version":3,"file":"schema-projection.d.ts","sourceRoot":"","sources":["../src/schema-projection.ts"],"names":[],"mappings":"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"}
|
|
@@ -34,6 +34,8 @@
|
|
|
34
34
|
* row shape lives in one instance's own `columns:`, which no definition-level
|
|
35
35
|
* derivation can reach.
|
|
36
36
|
*/
|
|
37
|
+
import { isRefSentinel } from "@telorun/templating";
|
|
38
|
+
import { isInjectedDeclaration } from "./resource-input.js";
|
|
37
39
|
function isObject(value) {
|
|
38
40
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
39
41
|
}
|
|
@@ -55,6 +57,20 @@ export function readSchemaProjection(definition) {
|
|
|
55
57
|
nameField: typeof raw.name === "string" ? raw.name : undefined,
|
|
56
58
|
nullable: typeof raw.nullable === "string" ? raw.nullable : undefined,
|
|
57
59
|
array: typeof raw.array === "string" ? raw.array : undefined,
|
|
60
|
+
reference: readProjectionReference(raw.reference),
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
function readProjectionReference(raw) {
|
|
64
|
+
if (!isObject(raw))
|
|
65
|
+
return undefined;
|
|
66
|
+
const { from, keyword, base, baseFrom } = raw;
|
|
67
|
+
if (typeof from !== "string" || typeof keyword !== "string")
|
|
68
|
+
return undefined;
|
|
69
|
+
return {
|
|
70
|
+
from,
|
|
71
|
+
keyword,
|
|
72
|
+
base: isObject(base) ? base : undefined,
|
|
73
|
+
baseFrom: typeof baseFrom === "string" ? baseFrom : undefined,
|
|
58
74
|
};
|
|
59
75
|
}
|
|
60
76
|
/** The annotation as written, from either position — the document (canonical)
|
|
@@ -79,7 +95,37 @@ export function schemaProjectionIsMisplaced(definition) {
|
|
|
79
95
|
const schema = definition.schema;
|
|
80
96
|
return isObject(schema) && schema["x-telo-schema-projection"] !== undefined;
|
|
81
97
|
}
|
|
98
|
+
/**
|
|
99
|
+
* The schema node that CARRIES the value vocabulary — the node itself, or the
|
|
100
|
+
* branch of a union that declares the map.
|
|
101
|
+
*
|
|
102
|
+
* A slot unioning a closed value vocabulary with a reference keeps its map on the
|
|
103
|
+
* value branch, exactly as the ref-slot reader peels the same union for its
|
|
104
|
+
* constraint. Exported because the strict half checks the map against the same
|
|
105
|
+
* branch's `enum`, and two implementations of "which branch is the value one"
|
|
106
|
+
* would eventually disagree — silently, since the failure of missing one is a
|
|
107
|
+
* completeness check that quietly stops running.
|
|
108
|
+
*/
|
|
109
|
+
export function schemaMapBranch(node) {
|
|
110
|
+
if (!isObject(node))
|
|
111
|
+
return undefined;
|
|
112
|
+
if (node["x-telo-schema-map"] !== undefined)
|
|
113
|
+
return node;
|
|
114
|
+
for (const key of ["oneOf", "anyOf"]) {
|
|
115
|
+
const branches = node[key];
|
|
116
|
+
if (!Array.isArray(branches))
|
|
117
|
+
continue;
|
|
118
|
+
for (const branch of branches) {
|
|
119
|
+
if (isObject(branch) && branch["x-telo-schema-map"] !== undefined)
|
|
120
|
+
return branch;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return undefined;
|
|
124
|
+
}
|
|
82
125
|
export function readSchemaMap(node) {
|
|
126
|
+
return ownSchemaMap(schemaMapBranch(node));
|
|
127
|
+
}
|
|
128
|
+
function ownSchemaMap(node) {
|
|
83
129
|
if (!isObject(node))
|
|
84
130
|
return undefined;
|
|
85
131
|
const raw = node["x-telo-schema-map"];
|
|
@@ -134,6 +180,66 @@ export function projectionKeyMap(kindSchema, projection) {
|
|
|
134
180
|
return undefined;
|
|
135
181
|
return readSchemaMap(entry.properties[projection.key]);
|
|
136
182
|
}
|
|
183
|
+
/**
|
|
184
|
+
* The node an entry whose keyed field holds a REFERENCE projects to.
|
|
185
|
+
*
|
|
186
|
+
* This is the one place a projection crosses to another declaration, and it is
|
|
187
|
+
* a deliberate exception to the projection's lossiness: length, precision and
|
|
188
|
+
* collation stop at the boundary because the database enforces them, while a
|
|
189
|
+
* domain crosses because it IS the type at the granularity a consumer acts on —
|
|
190
|
+
* the enum in a CRUD model's OpenAPI operation, a completion list in the editor,
|
|
191
|
+
* a filter a repository can reject before the query.
|
|
192
|
+
*
|
|
193
|
+
* **A reference that cannot be read projects OPEN, never to nothing**, and that
|
|
194
|
+
* is the opposite of the rule an unmapped VALUE follows. The two failures are
|
|
195
|
+
* not the same failure: an unmapped value is a gap in the kind's own vocabulary,
|
|
196
|
+
* so there is no entry to speak of, while an unreadable reference names an entry
|
|
197
|
+
* the declaration plainly HAS and only leaves its type unknown. Dropping it made
|
|
198
|
+
* the projection deny the entry exists — a table whose enum reference had a typo
|
|
199
|
+
* reported `'status' is not allowed` against a column declared three lines up,
|
|
200
|
+
* blaming the seed row for the reference's mistake. Open is the honest
|
|
201
|
+
* under-approximation, and the reason is reported alongside.
|
|
202
|
+
*/
|
|
203
|
+
function referencedNode(value, entryName, projection, map, options) {
|
|
204
|
+
const reference = projection.reference;
|
|
205
|
+
if (!reference || !isObject(value))
|
|
206
|
+
return undefined;
|
|
207
|
+
// Through the single reader, so the name in the diagnostic is the one the
|
|
208
|
+
// author wrote whichever shape the slot holds — reading `value.name` here
|
|
209
|
+
// reported `<unnamed>` for an unresolved `!ref`, which is precisely the case
|
|
210
|
+
// that produces the diagnostic.
|
|
211
|
+
const name = readProjectionRef(value)?.name ?? "<unnamed>";
|
|
212
|
+
const report = () => {
|
|
213
|
+
options?.failures?.push({
|
|
214
|
+
reason: "entry-reference",
|
|
215
|
+
// The EMPTY pointer means the projected declaration is the one carrying
|
|
216
|
+
// the diagnostic, so the entry's own path is a real anchor in that file —
|
|
217
|
+
// the column, not the document root. Any other pointer names a slot
|
|
218
|
+
// holding a reference to a DIFFERENT manifest, whose entry paths mean
|
|
219
|
+
// nothing here, so the slot stays the anchor.
|
|
220
|
+
pointer: options?.pointer === ""
|
|
221
|
+
? `${projection.entries}/${entryName}`
|
|
222
|
+
: (options?.pointer ?? projection.entries),
|
|
223
|
+
entry: entryName,
|
|
224
|
+
name,
|
|
225
|
+
});
|
|
226
|
+
return {};
|
|
227
|
+
};
|
|
228
|
+
const found = options?.scope?.resolveManifest(value);
|
|
229
|
+
if (!found || "ambiguous" in found)
|
|
230
|
+
return report();
|
|
231
|
+
const values = found.manifest[reference.from];
|
|
232
|
+
if (!Array.isArray(values) || values.length === 0)
|
|
233
|
+
return report();
|
|
234
|
+
let base = reference.base;
|
|
235
|
+
if (reference.baseFrom !== undefined) {
|
|
236
|
+
const declared = found.manifest[reference.baseFrom];
|
|
237
|
+
base = typeof declared === "string" ? map[declared] : undefined;
|
|
238
|
+
}
|
|
239
|
+
if (!base)
|
|
240
|
+
return report();
|
|
241
|
+
return { ...base, [reference.keyword]: values };
|
|
242
|
+
}
|
|
137
243
|
/**
|
|
138
244
|
* Project one declaration to an object schema.
|
|
139
245
|
*
|
|
@@ -148,7 +254,12 @@ export function projectionKeyMap(kindSchema, projection) {
|
|
|
148
254
|
* enough to double as a validator would move the domain's semantics into the
|
|
149
255
|
* type layer.
|
|
150
256
|
*/
|
|
151
|
-
export function projectEntries(manifest, projection, map
|
|
257
|
+
export function projectEntries(manifest, projection, map,
|
|
258
|
+
/** What a REFERENCE at the keyed field is resolved through, and where a
|
|
259
|
+
* failure to resolve one is reported. A caller with no scope cannot resolve
|
|
260
|
+
* one, so such an entry projects OPEN — present, untyped — rather than
|
|
261
|
+
* vanishing from the row. */
|
|
262
|
+
options) {
|
|
152
263
|
const entries = navigate(manifest, projection.entries);
|
|
153
264
|
if (entries === undefined)
|
|
154
265
|
return undefined;
|
|
@@ -157,7 +268,9 @@ export function projectEntries(manifest, projection, map) {
|
|
|
157
268
|
if (!isObject(entry) || name === undefined)
|
|
158
269
|
return;
|
|
159
270
|
const key = entry[projection.key];
|
|
160
|
-
const mapped = typeof key === "string"
|
|
271
|
+
const mapped = typeof key === "string"
|
|
272
|
+
? map[key]
|
|
273
|
+
: referencedNode(key, name, projection, map, options);
|
|
161
274
|
// A value with no map entry projects to nothing rather than to `any`: the
|
|
162
275
|
// vocabulary is the kind's own enum, so an unmapped value is a gap in the
|
|
163
276
|
// kind's declaration, not a shape to guess at.
|
|
@@ -193,11 +306,26 @@ export function projectEntries(manifest, projection, map) {
|
|
|
193
306
|
additionalProperties: false,
|
|
194
307
|
};
|
|
195
308
|
}
|
|
196
|
-
/**
|
|
197
|
-
*
|
|
309
|
+
/**
|
|
310
|
+
* The `{kind, name, alias?}` reference a value holds, or undefined. Exported so
|
|
311
|
+
* a host whose slot may hold EITHER shape can fall back to this reading.
|
|
312
|
+
*
|
|
313
|
+
* The unresolved `!ref` SENTINEL is read too. `resolveRefSentinels` normally
|
|
314
|
+
* rewrites one before this pass, but not when the reference names nothing — and
|
|
315
|
+
* that is exactly when a projection failure is reported, so reading only the
|
|
316
|
+
* resolved shape made the diagnostic name the target `<unnamed>`, which is the
|
|
317
|
+
* one fact the author needed from it. A round-trip host (`compile` off) carries
|
|
318
|
+
* the sentinel for every reference, resolved or not.
|
|
319
|
+
*/
|
|
198
320
|
export function readProjectionRef(value) {
|
|
199
321
|
if (!isObject(value))
|
|
200
322
|
return undefined;
|
|
323
|
+
if (isRefSentinel(value)) {
|
|
324
|
+
const dot = value.source.indexOf(".");
|
|
325
|
+
return dot > 0
|
|
326
|
+
? { name: value.source.slice(dot + 1), alias: value.source.slice(0, dot) }
|
|
327
|
+
: { name: value.source };
|
|
328
|
+
}
|
|
201
329
|
const name = value.name;
|
|
202
330
|
if (typeof name !== "string")
|
|
203
331
|
return undefined;
|
|
@@ -251,6 +379,9 @@ function refTarget(value, scope, pointer) {
|
|
|
251
379
|
if ("ambiguous" in found)
|
|
252
380
|
return { reason: "ambiguous", pointer, name };
|
|
253
381
|
const manifest = found.manifest;
|
|
382
|
+
if (isInjectedDeclaration(manifest)) {
|
|
383
|
+
return { reason: "injected", pointer, name };
|
|
384
|
+
}
|
|
254
385
|
if (typeof manifest.kind !== "string")
|
|
255
386
|
return { reason: "unresolved", pointer, name };
|
|
256
387
|
const definition = scope.resolveDefinition(manifest.kind);
|
|
@@ -258,18 +389,44 @@ function refTarget(value, scope, pointer) {
|
|
|
258
389
|
return { reason: "no-projection", pointer, kind: manifest.kind };
|
|
259
390
|
return { manifest, definition };
|
|
260
391
|
}
|
|
392
|
+
/** The declaration the annotation is written on, as a projection target. */
|
|
393
|
+
function ownTarget(manifest, scope) {
|
|
394
|
+
if (typeof manifest.kind !== "string") {
|
|
395
|
+
return { reason: "no-ref", pointer: "" };
|
|
396
|
+
}
|
|
397
|
+
const definition = scope.resolveDefinition(manifest.kind);
|
|
398
|
+
if (!definition)
|
|
399
|
+
return { reason: "no-projection", pointer: "", kind: manifest.kind };
|
|
400
|
+
return { manifest, definition };
|
|
401
|
+
}
|
|
261
402
|
export function describeProjectionFailure(failure) {
|
|
262
403
|
switch (failure.reason) {
|
|
263
404
|
case "no-ref":
|
|
264
|
-
return
|
|
405
|
+
return failure.pointer === ""
|
|
406
|
+
? "this resource declares no 'kind:', so there is no definition to project it through."
|
|
407
|
+
: `'${failure.pointer}' does not hold a reference, so there is no declaration to project.`;
|
|
265
408
|
case "unresolved":
|
|
266
409
|
return `'${failure.pointer}' references '${failure.name}', which resolves to no resource.`;
|
|
410
|
+
case "injected":
|
|
411
|
+
return (`'${failure.pointer}' references '${failure.name}', a resource input this module does ` +
|
|
412
|
+
`not declare — its entries belong to whoever supplies it.`);
|
|
267
413
|
case "ambiguous":
|
|
268
414
|
return (`'${failure.pointer}' references '${failure.name}', which matches more than one resource ` +
|
|
269
415
|
`in scope. Rename one of them so the reference names exactly one declaration.`);
|
|
270
416
|
case "no-projection":
|
|
271
417
|
return (`'${failure.pointer}' references a resource of kind '${failure.kind}', which declares no ` +
|
|
272
418
|
`'x-telo-schema-projection' — so there is nothing for this slot to be typed from.`);
|
|
419
|
+
case "no-projection-map":
|
|
420
|
+
return (`kind '${failure.kind}' declares an 'x-telo-schema-projection' whose key field carries ` +
|
|
421
|
+
`no 'x-telo-schema-map', so there is no vocabulary to project its entries through and ` +
|
|
422
|
+
`'${failure.pointer || "this declaration"}' cannot be typed from it.`);
|
|
423
|
+
case "no-entries":
|
|
424
|
+
return (`'${failure.entries}' holds no entry collection on this ${failure.kind}, so the ` +
|
|
425
|
+
`projection has nothing to type '${failure.pointer || "this declaration"}' from.`);
|
|
426
|
+
case "entry-reference":
|
|
427
|
+
return (`entry '${failure.entry}' at '${failure.pointer}' references '${failure.name}', which ` +
|
|
428
|
+
`resolves to no declaration this analysis can read — so that entry is projected as an ` +
|
|
429
|
+
`open value and nothing typed from it is checked against the shape it was meant to have.`);
|
|
273
430
|
}
|
|
274
431
|
}
|
|
275
432
|
/**
|
|
@@ -282,36 +439,74 @@ export function describeProjectionFailure(failure) {
|
|
|
282
439
|
* `failures`, because degrading SILENTLY is the failure this whole mechanism
|
|
283
440
|
* exists to move earlier: the consumer's contract quietly reopens and a
|
|
284
441
|
* misspelled field passes `telo check` exactly as it did before.
|
|
442
|
+
*
|
|
443
|
+
* **A node that projected NOTHING is returned by IDENTITY**, and that is a
|
|
444
|
+
* correctness property of the caller rather than a micro-optimization:
|
|
445
|
+
* `DefinitionRegistry` memoizes a compiled AJV validator per schema OBJECT,
|
|
446
|
+
* because every resource of a kind is checked against the same one at keystroke
|
|
447
|
+
* time. Rebuilding each node unconditionally — which this did — misses that memo
|
|
448
|
+
* for every resource in the analysis, so AJV recompiled the whole kind schema
|
|
449
|
+
* once per resource: on `apps/hub` that was 197 compiles instead of 54, and 723
|
|
450
|
+
* ms instead of 97. Returning the input where nothing changed restores it for
|
|
451
|
+
* every kind that declares no projection at all, which is nearly all of them.
|
|
285
452
|
*/
|
|
286
453
|
export function resolveSchemaProjections(schema, manifest, scope, failures) {
|
|
287
454
|
if (Array.isArray(schema)) {
|
|
288
|
-
|
|
455
|
+
let moved = false;
|
|
456
|
+
const items = schema.map((item) => {
|
|
457
|
+
const next = resolveSchemaProjections(item, manifest, scope, failures);
|
|
458
|
+
if (next !== item)
|
|
459
|
+
moved = true;
|
|
460
|
+
return next;
|
|
461
|
+
});
|
|
462
|
+
return moved ? items : schema;
|
|
289
463
|
}
|
|
290
464
|
if (!isObject(schema))
|
|
291
465
|
return schema;
|
|
292
466
|
const pointer = readProjectionFrom(schema);
|
|
293
|
-
if (pointer && manifest) {
|
|
294
|
-
|
|
467
|
+
if (pointer !== undefined && manifest) {
|
|
468
|
+
// The EMPTY pointer names the declaration this annotation is written on,
|
|
469
|
+
// rather than a slot holding a reference to another. Resolution is skipped
|
|
470
|
+
// because the declaration is already in hand — which is what lets a kind
|
|
471
|
+
// type its own data against its own entries (a table's seed rows against its
|
|
472
|
+
// columns), something no reference could reach.
|
|
473
|
+
const target = pointer === ""
|
|
474
|
+
? ownTarget(manifest, scope)
|
|
475
|
+
: refTarget(navigate(manifest, pointer), scope, pointer);
|
|
295
476
|
if ("reason" in target) {
|
|
296
477
|
failures?.push(target);
|
|
297
478
|
}
|
|
298
479
|
else {
|
|
480
|
+
const kind = String(target.manifest.kind ?? "<unknown>");
|
|
299
481
|
const projection = readSchemaProjection(target.definition);
|
|
300
482
|
const map = projection && projectionKeyMap(target.definition.schema, projection);
|
|
301
|
-
const projected = projection && map
|
|
483
|
+
const projected = projection && map
|
|
484
|
+
? projectEntries(target.manifest, projection, map, { scope, pointer, failures })
|
|
485
|
+
: undefined;
|
|
302
486
|
if (projected) {
|
|
303
487
|
const { ["x-telo-schema-projection-from"]: _dropped, ...rest } = schema;
|
|
304
488
|
return { ...rest, ...projected };
|
|
305
489
|
}
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
490
|
+
// Three distinct omissions, three repairs by three different authors: the
|
|
491
|
+
// kind declares no projection, the kind declares one the key field has no
|
|
492
|
+
// vocabulary for, or this DECLARATION simply lists no entries.
|
|
493
|
+
if (!projection)
|
|
494
|
+
failures?.push({ reason: "no-projection", pointer, kind });
|
|
495
|
+
else if (!map)
|
|
496
|
+
failures?.push({ reason: "no-projection-map", pointer, kind });
|
|
497
|
+
else {
|
|
498
|
+
failures?.push({ reason: "no-entries", pointer, kind, entries: projection.entries });
|
|
499
|
+
}
|
|
311
500
|
}
|
|
312
501
|
}
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
key.startsWith("x-telo-")
|
|
316
|
-
|
|
502
|
+
let moved = false;
|
|
503
|
+
const entries = Object.entries(schema).map(([key, value]) => {
|
|
504
|
+
const next = key.startsWith("x-telo-")
|
|
505
|
+
? value
|
|
506
|
+
: resolveSchemaProjections(value, manifest, scope, failures);
|
|
507
|
+
if (next !== value)
|
|
508
|
+
moved = true;
|
|
509
|
+
return [key, next];
|
|
510
|
+
});
|
|
511
|
+
return moved ? Object.fromEntries(entries) : schema;
|
|
317
512
|
}
|
package/dist/system-kinds.d.ts
CHANGED
|
@@ -19,7 +19,12 @@ export declare const DEPENDENCY_GRAPH_SKIP_KINDS: ReadonlySet<string>;
|
|
|
19
19
|
/** Skipped by `!ref` sentinel resolution: kinds whose bodies are
|
|
20
20
|
* blueprints or import-time metadata, not resource instances with
|
|
21
21
|
* user-referenced ref slots. Mirrors `REF_VALIDATION_SKIP_KINDS` but
|
|
22
|
-
* also
|
|
23
|
-
*
|
|
22
|
+
* also lists Telo.Import, because walking its field map is pointless —
|
|
23
|
+
* there is no registered kind behind it.
|
|
24
|
+
*
|
|
25
|
+
* `resolveRefSentinels` reaches Telo.Import's `resources:` block AHEAD of this
|
|
26
|
+
* set, deliberately: those are the references an importer supplies for a
|
|
27
|
+
* library's declared inputs, and they resolve exactly like any other. Nothing
|
|
28
|
+
* else on the document is a reference slot, so only that subtree is walked. */
|
|
24
29
|
export declare const REF_RESOLUTION_SKIP_KINDS: ReadonlySet<string>;
|
|
25
30
|
//# sourceMappingURL=system-kinds.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"system-kinds.d.ts","sourceRoot":"","sources":["../src/system-kinds.ts"],"names":[],"mappings":"AAAA;;;;sEAIsE;AAEtE;;;;;;0CAM0C;AAC1C,eAAO,MAAM,yBAAyB,EAAE,WAAW,CAAC,MAAM,CAGxD,CAAC;AAEH;;;4CAG4C;AAC5C,eAAO,MAAM,2BAA2B,EAAE,WAAW,CAAC,MAAM,CAG1D,CAAC;AAEH
|
|
1
|
+
{"version":3,"file":"system-kinds.d.ts","sourceRoot":"","sources":["../src/system-kinds.ts"],"names":[],"mappings":"AAAA;;;;sEAIsE;AAEtE;;;;;;0CAM0C;AAC1C,eAAO,MAAM,yBAAyB,EAAE,WAAW,CAAC,MAAM,CAGxD,CAAC;AAEH;;;4CAG4C;AAC5C,eAAO,MAAM,2BAA2B,EAAE,WAAW,CAAC,MAAM,CAG1D,CAAC;AAEH;;;;;;;;;gFASgF;AAChF,eAAO,MAAM,yBAAyB,EAAE,WAAW,CAAC,MAAM,CAIxD,CAAC"}
|
package/dist/system-kinds.js
CHANGED
|
@@ -25,8 +25,13 @@ export const DEPENDENCY_GRAPH_SKIP_KINDS = new Set([
|
|
|
25
25
|
/** Skipped by `!ref` sentinel resolution: kinds whose bodies are
|
|
26
26
|
* blueprints or import-time metadata, not resource instances with
|
|
27
27
|
* user-referenced ref slots. Mirrors `REF_VALIDATION_SKIP_KINDS` but
|
|
28
|
-
* also
|
|
29
|
-
*
|
|
28
|
+
* also lists Telo.Import, because walking its field map is pointless —
|
|
29
|
+
* there is no registered kind behind it.
|
|
30
|
+
*
|
|
31
|
+
* `resolveRefSentinels` reaches Telo.Import's `resources:` block AHEAD of this
|
|
32
|
+
* set, deliberately: those are the references an importer supplies for a
|
|
33
|
+
* library's declared inputs, and they resolve exactly like any other. Nothing
|
|
34
|
+
* else on the document is a reference slot, so only that subtree is walked. */
|
|
30
35
|
export const REF_RESOLUTION_SKIP_KINDS = new Set([
|
|
31
36
|
"Telo.Definition",
|
|
32
37
|
"Telo.Abstract",
|
package/dist/telo-version.d.ts
CHANGED
package/dist/telo-version.js
CHANGED
|
@@ -5,4 +5,4 @@
|
|
|
5
5
|
// its release identity, this is the scale a module's `requires.telo` range is
|
|
6
6
|
// written against, and every kernel in every language reports the same scale.
|
|
7
7
|
/** The surface generation this analyzer implements. */
|
|
8
|
-
export const TELO_SURFACE_VERSION = "0.
|
|
8
|
+
export const TELO_SURFACE_VERSION = "0.83.0";
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { ResourceDefinition, ResourceManifest } from "@telorun/sdk";
|
|
2
|
+
import type { AliasResolver } from "./alias-resolver.js";
|
|
3
|
+
import type { DefinitionRegistry } from "./definition-registry.js";
|
|
4
|
+
import type { ModuleScopes } from "./alias-resolver.js";
|
|
5
|
+
/**
|
|
6
|
+
* A `Telo.Definition`'s `resources:` entries — the bodies a kind writes for
|
|
7
|
+
* ANOTHER kind — read as what they are: declarations of that other kind.
|
|
8
|
+
*
|
|
9
|
+
* The consequence is the whole point. CEL inside such a body used to be typed in
|
|
10
|
+
* the ENCLOSING definition's scope, against one fixed permissive context
|
|
11
|
+
* (`self`, plus open `request` / `result` / `steps` / `error`). So `inputs` and
|
|
12
|
+
* `item` were undefined wherever the nested kind declares them, while `error`
|
|
13
|
+
* was offered everywhere regardless of whether a `catch:` was in scope — a body
|
|
14
|
+
* of more than one dispatch was unwritable, which is why no standard-library
|
|
15
|
+
* template has one.
|
|
16
|
+
*
|
|
17
|
+
* Resolving through the nested kind's OWN annotations — its `x-telo-context`
|
|
18
|
+
* regions, its step body, its error branches — makes a nested declaration answer
|
|
19
|
+
* exactly as the same declaration written at the top level does, with `self`
|
|
20
|
+
* merged in from the enclosing definition's `schema:`.
|
|
21
|
+
*
|
|
22
|
+
* Browser-safe.
|
|
23
|
+
*/
|
|
24
|
+
export interface TemplateBody {
|
|
25
|
+
/** Concrete path prefix of this entry (`resources[0]`), as CEL sites are
|
|
26
|
+
* addressed. */
|
|
27
|
+
prefix: string;
|
|
28
|
+
/** JSONPath prefix for context scopes (`$.resources[0]`). */
|
|
29
|
+
scopePrefix: string;
|
|
30
|
+
manifest: ResourceManifest;
|
|
31
|
+
definition: ResourceDefinition | undefined;
|
|
32
|
+
}
|
|
33
|
+
/** The template bodies a manifest declares — empty for anything that is not a
|
|
34
|
+
* `Telo.Definition` with a `resources:` array. */
|
|
35
|
+
export declare function templateBodies(m: ResourceManifest, registry: DefinitionRegistry, aliases: AliasResolver | undefined, scopes: ModuleScopes | undefined): TemplateBody[];
|
|
36
|
+
/** True when a CEL path lies at or inside a body's own subtree. */
|
|
37
|
+
export declare function pathInBody(path: string, prefix: string): boolean;
|
|
38
|
+
/** The body a CEL path belongs to, or undefined for a path in the definition's
|
|
39
|
+
* own fields. Generic over what the caller keyed to each body — the resolver
|
|
40
|
+
* carries a step context and an error map, the visitor carries the schema. */
|
|
41
|
+
export declare function bodyForPath<T extends {
|
|
42
|
+
prefix: string;
|
|
43
|
+
}>(bodies: readonly T[], path: string): T | undefined;
|
|
44
|
+
/** `self` is in scope throughout a template body — it is how the body reaches
|
|
45
|
+
* the configuration its enclosing kind was given — so it is merged into every
|
|
46
|
+
* context the nested kind declares, which knows nothing about it. Merged UNDER
|
|
47
|
+
* the nested kind's own properties: a name the nested kind declares wins, since
|
|
48
|
+
* that is what its controller will bind. */
|
|
49
|
+
export declare function withTemplateSelf(contextSchema: Record<string, any>): Record<string, any>;
|
|
50
|
+
//# sourceMappingURL=template-body.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template-body.d.ts","sourceRoot":"","sources":["../src/template-body.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,WAAW,YAAY;IAC3B;qBACiB;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,6DAA6D;IAC7D,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,UAAU,EAAE,kBAAkB,GAAG,SAAS,CAAC;CAC5C;AAED;mDACmD;AACnD,wBAAgB,cAAc,CAC5B,CAAC,EAAE,gBAAgB,EACnB,QAAQ,EAAE,kBAAkB,EAC5B,OAAO,EAAE,aAAa,GAAG,SAAS,EAClC,MAAM,EAAE,YAAY,GAAG,SAAS,GAC/B,YAAY,EAAE,CA8BhB;AAED,mEAAmE;AACnE,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAIhE;AAED;;+EAE+E;AAC/E,wBAAgB,WAAW,CAAC,CAAC,SAAS;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,EACtD,MAAM,EAAE,SAAS,CAAC,EAAE,EACpB,IAAI,EAAE,MAAM,GACX,CAAC,GAAG,SAAS,CAEf;AAED;;;;6CAI6C;AAC7C,wBAAgB,gBAAgB,CAAC,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAQxF"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/** The template bodies a manifest declares — empty for anything that is not a
|
|
2
|
+
* `Telo.Definition` with a `resources:` array. */
|
|
3
|
+
export function templateBodies(m, registry, aliases, scopes) {
|
|
4
|
+
if (m.kind !== "Telo.Definition")
|
|
5
|
+
return [];
|
|
6
|
+
const bodies = m.resources;
|
|
7
|
+
if (!Array.isArray(bodies))
|
|
8
|
+
return [];
|
|
9
|
+
// A nested kind is written through the alias scope of the module that DECLARED
|
|
10
|
+
// the definition, never the consumer's — the same rule every other kind
|
|
11
|
+
// resolution in a forwarded manifest follows.
|
|
12
|
+
const ownModule = m.metadata?.module;
|
|
13
|
+
const scope = (ownModule && scopes && !scopes.rootModules.has(ownModule)
|
|
14
|
+
? scopes.aliasesByModule.get(ownModule)
|
|
15
|
+
: undefined) ?? aliases;
|
|
16
|
+
const out = [];
|
|
17
|
+
for (let i = 0; i < bodies.length; i++) {
|
|
18
|
+
const body = bodies[i];
|
|
19
|
+
if (!body || typeof body !== "object" || Array.isArray(body))
|
|
20
|
+
continue;
|
|
21
|
+
const kind = body.kind;
|
|
22
|
+
if (typeof kind !== "string")
|
|
23
|
+
continue;
|
|
24
|
+
const canonical = scope?.resolveKind(kind);
|
|
25
|
+
const definition = registry.resolve(kind) ?? (canonical ? registry.resolve(canonical) : undefined);
|
|
26
|
+
out.push({
|
|
27
|
+
prefix: `resources[${i}]`,
|
|
28
|
+
scopePrefix: `$.resources[${i}]`,
|
|
29
|
+
manifest: body,
|
|
30
|
+
definition,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
return out;
|
|
34
|
+
}
|
|
35
|
+
/** True when a CEL path lies at or inside a body's own subtree. */
|
|
36
|
+
export function pathInBody(path, prefix) {
|
|
37
|
+
return (path === prefix || path.startsWith(`${prefix}.`) || path.startsWith(`${prefix}[`));
|
|
38
|
+
}
|
|
39
|
+
/** The body a CEL path belongs to, or undefined for a path in the definition's
|
|
40
|
+
* own fields. Generic over what the caller keyed to each body — the resolver
|
|
41
|
+
* carries a step context and an error map, the visitor carries the schema. */
|
|
42
|
+
export function bodyForPath(bodies, path) {
|
|
43
|
+
return bodies.find((b) => pathInBody(path, b.prefix));
|
|
44
|
+
}
|
|
45
|
+
/** `self` is in scope throughout a template body — it is how the body reaches
|
|
46
|
+
* the configuration its enclosing kind was given — so it is merged into every
|
|
47
|
+
* context the nested kind declares, which knows nothing about it. Merged UNDER
|
|
48
|
+
* the nested kind's own properties: a name the nested kind declares wins, since
|
|
49
|
+
* that is what its controller will bind. */
|
|
50
|
+
export function withTemplateSelf(contextSchema) {
|
|
51
|
+
return {
|
|
52
|
+
...contextSchema,
|
|
53
|
+
properties: {
|
|
54
|
+
self: { "x-telo-context-from-root": "schema" },
|
|
55
|
+
...(contextSchema.properties ?? {}),
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { extractAccessChains, validateChainAgainstSchema } from "@telorun/templating";
|
|
2
|
+
export { extractCelRegionScopes, pathMatchesScope } from "./eval-paths.js";
|
|
2
3
|
export interface ContextResolveOpts {
|
|
3
4
|
/** When provided, used to resolve `x-telo-context-from-root` annotations against the
|
|
4
5
|
* root manifest. When omitted, defaults to `manifestItem`. */
|
|
@@ -15,14 +16,6 @@ export interface ContextResolveOpts {
|
|
|
15
16
|
allManifests?: Record<string, any>[];
|
|
16
17
|
}
|
|
17
18
|
export declare function resolveTypeFieldToSchema(value: unknown, allManifests: Record<string, any>[], ancestry?: ReadonlySet<string>): Record<string, any> | undefined;
|
|
18
|
-
/**
|
|
19
|
-
* Returns true when a CEL expression path (from walkCelExpressions, e.g. "routes[0].inputs.q")
|
|
20
|
-
* falls within the scope of a context (e.g. "$.routes[*].inputs").
|
|
21
|
-
*
|
|
22
|
-
* The scope is matched directly (no sibling sharing): a context at "$.routes[*].inputs" only
|
|
23
|
-
* applies to expressions whose path starts with "routes[N].inputs", not to other sibling fields.
|
|
24
|
-
*/
|
|
25
|
-
export declare function pathMatchesScope(exprPath: string, scope: string): boolean;
|
|
26
19
|
/**
|
|
27
20
|
* Resolves `x-telo-context-*` annotations in a context schema using the concrete
|
|
28
21
|
* manifest item (per-scope) and the manifest root.
|
|
@@ -91,13 +84,4 @@ export declare function extractContextsFromSchema(schema: Record<string, any>, p
|
|
|
91
84
|
scope: string;
|
|
92
85
|
schema: Record<string, any>;
|
|
93
86
|
}>;
|
|
94
|
-
/**
|
|
95
|
-
* Walk a JSON Schema tree and collect the JSONPath scopes of every field that
|
|
96
|
-
* declares a CEL-bearing region (`x-telo-context` / `x-telo-step-context` /
|
|
97
|
-
* `x-telo-error-context`). Used — alongside `x-telo-eval` paths — to decide
|
|
98
|
-
* whether a `!cel` expression sits in a slot the runtime actually evaluates.
|
|
99
|
-
* Scopes use the same `$.a.b[*]` form as `extractContextsFromSchema`, matched
|
|
100
|
-
* against expression paths with `pathMatchesScope`.
|
|
101
|
-
*/
|
|
102
|
-
export declare function extractCelRegionScopes(schema: Record<string, any>, path?: string): string[];
|
|
103
87
|
//# sourceMappingURL=validate-cel-context.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate-cel-context.d.ts","sourceRoot":"","sources":["../src/validate-cel-context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"validate-cel-context.d.ts","sourceRoot":"","sources":["../src/validate-cel-context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AAatF,OAAO,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AA2B3E,MAAM,WAAW,kBAAkB;IACjC;mEAC+D;IAC/D,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACnC;;kDAE8C;IAC9C,IAAI,CAAC,EAAE;QACL,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,SAAS,CAAC;KACxD,CAAC;IACF,OAAO,CAAC,EAAE;QACR,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;KAC/C,CAAC;IACF,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,CAAC;CACtC;AA4CD,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,OAAO,EACd,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,EACnC,QAAQ,GAAE,WAAW,CAAC,MAAM,CAAa,GACxC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,SAAS,CA0EjC;AAyID;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC3B,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACjC,IAAI,CAAC,EAAE,kBAAkB,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,GAChD,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAoLrB;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAC5B,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAuBrB;AAqBD;;;;;;;;;GASG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC3B,IAAI,SAAM,GACT,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;CAAE,CAAC,CAGvD"}
|