@telorun/analyzer 0.62.0 → 0.63.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 +6 -0
- package/dist/analyzer.d.ts +1 -1
- package/dist/analyzer.d.ts.map +1 -1
- package/dist/analyzer.js +343 -13
- package/dist/call-graph.d.ts.map +1 -1
- package/dist/call-graph.js +2 -7
- package/dist/flatten-for-analyzer.js +1 -1
- package/dist/import-resolution-diagnostics.d.ts +9 -2
- package/dist/import-resolution-diagnostics.d.ts.map +1 -1
- package/dist/import-resolution-diagnostics.js +26 -7
- package/dist/index.d.ts +15 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -1
- package/dist/invocation-contract.d.ts +6 -1
- package/dist/invocation-contract.d.ts.map +1 -1
- package/dist/invocation-contract.js +27 -4
- package/dist/loaded-types.d.ts +12 -3
- package/dist/loaded-types.d.ts.map +1 -1
- package/dist/manifest-loader.d.ts +0 -1
- package/dist/manifest-loader.d.ts.map +1 -1
- package/dist/manifest-loader.js +62 -41
- package/dist/manifest-schemas.d.ts +699 -0
- package/dist/manifest-schemas.d.ts.map +1 -1
- package/dist/manifest-schemas.js +306 -14
- package/dist/module-compatibility.d.ts +40 -0
- package/dist/module-compatibility.d.ts.map +1 -0
- package/dist/module-compatibility.js +52 -0
- package/dist/ref-slot-reading.d.ts +30 -0
- package/dist/ref-slot-reading.d.ts.map +1 -0
- package/dist/ref-slot-reading.js +139 -0
- package/dist/referrer-rule.d.ts +67 -0
- package/dist/referrer-rule.d.ts.map +1 -0
- package/dist/referrer-rule.js +96 -0
- package/dist/release/index.d.ts +1 -1
- package/dist/release/index.d.ts.map +1 -1
- package/dist/release/index.js +1 -1
- package/dist/release/payload-digest.d.ts +7 -3
- package/dist/release/payload-digest.d.ts.map +1 -1
- package/dist/release/payload-digest.js +7 -3
- package/dist/release/version-stamp.d.ts +16 -0
- package/dist/release/version-stamp.d.ts.map +1 -1
- package/dist/release/version-stamp.js +52 -0
- package/dist/release/workspace-config.d.ts +10 -6
- package/dist/release/workspace-config.d.ts.map +1 -1
- package/dist/release/workspace-config.js +10 -6
- package/dist/resolve-schema-ref-kinds.d.ts +4 -3
- package/dist/resolve-schema-ref-kinds.d.ts.map +1 -1
- package/dist/resolve-schema-ref-kinds.js +16 -0
- package/dist/resolve-throws-union.d.ts.map +1 -1
- package/dist/resolve-throws-union.js +4 -3
- package/dist/resolve-zone-containment.d.ts +99 -0
- package/dist/resolve-zone-containment.d.ts.map +1 -0
- package/dist/resolve-zone-containment.js +212 -0
- package/dist/resolve-zone-requirements.d.ts +5 -0
- package/dist/resolve-zone-requirements.d.ts.map +1 -1
- package/dist/resolve-zone-requirements.js +48 -7
- package/dist/resource-rule.d.ts +106 -0
- package/dist/resource-rule.d.ts.map +1 -0
- package/dist/resource-rule.js +236 -0
- package/dist/rule-condition.d.ts +50 -0
- package/dist/rule-condition.d.ts.map +1 -0
- package/dist/rule-condition.js +108 -0
- package/dist/schema-keywords.d.ts.map +1 -1
- package/dist/schema-keywords.js +20 -0
- package/dist/schema-projection.d.ts +171 -0
- package/dist/schema-projection.d.ts.map +1 -0
- package/dist/schema-projection.js +317 -0
- package/dist/step-slot.d.ts +39 -0
- package/dist/step-slot.d.ts.map +1 -0
- package/dist/step-slot.js +49 -0
- package/dist/telo-version.d.ts +1 -1
- package/dist/telo-version.js +1 -1
- package/dist/validate-cel-context.d.ts.map +1 -1
- package/dist/validate-cel-context.js +17 -3
- package/dist/validate-durable-regions.d.ts +15 -0
- package/dist/validate-durable-regions.d.ts.map +1 -0
- package/dist/validate-durable-regions.js +336 -0
- package/dist/validate-references.d.ts.map +1 -1
- package/dist/validate-references.js +44 -2
- package/dist/validate-referrer-rules.d.ts +120 -0
- package/dist/validate-referrer-rules.d.ts.map +1 -0
- package/dist/validate-referrer-rules.js +255 -0
- package/dist/validate-resource-rules.d.ts +114 -0
- package/dist/validate-resource-rules.d.ts.map +1 -0
- package/dist/validate-resource-rules.js +283 -0
- package/dist/validate-schema-projection.d.ts +32 -0
- package/dist/validate-schema-projection.d.ts.map +1 -0
- package/dist/validate-schema-projection.js +110 -0
- package/dist/validate-step-inputs.d.ts +2 -1
- package/dist/validate-step-inputs.d.ts.map +1 -1
- package/dist/validate-step-inputs.js +5 -3
- package/dist/validate-throws-coverage.d.ts.map +1 -1
- package/dist/validate-throws-coverage.js +11 -5
- package/dist/validate-zone-slots.d.ts +2 -2
- package/dist/validate-zone-slots.d.ts.map +1 -1
- package/dist/validate-zone-slots.js +202 -6
- package/dist/validate-zone-violations.d.ts +12 -0
- package/dist/validate-zone-violations.d.ts.map +1 -0
- package/dist/validate-zone-violations.js +169 -0
- package/dist/value-type-keyword.d.ts +1 -1
- package/dist/value-type-keyword.d.ts.map +1 -1
- package/dist/value-type-keyword.js +4 -0
- package/dist/zone-slot.d.ts +61 -0
- package/dist/zone-slot.d.ts.map +1 -1
- package/dist/zone-slot.js +86 -5
- package/package.json +2 -2
- package/src/analysis-registry.ts +6 -0
- package/src/analyzer.ts +395 -14
- package/src/call-graph.ts +2 -8
- package/src/flatten-for-analyzer.ts +1 -1
- package/src/import-resolution-diagnostics.ts +25 -7
- package/src/index.ts +73 -0
- package/src/invocation-contract.ts +45 -2
- package/src/loaded-types.ts +12 -3
- package/src/manifest-loader.ts +87 -55
- package/src/manifest-schemas.ts +328 -14
- package/src/module-compatibility.ts +72 -0
- package/src/ref-slot-reading.ts +156 -0
- package/src/referrer-rule.ts +116 -0
- package/src/release/index.ts +1 -0
- package/src/release/payload-digest.ts +7 -3
- package/src/release/version-stamp.ts +58 -0
- package/src/release/workspace-config.ts +10 -6
- package/src/resolve-schema-ref-kinds.ts +28 -4
- package/src/resolve-throws-union.ts +4 -3
- package/src/resolve-zone-containment.ts +329 -0
- package/src/resolve-zone-requirements.ts +67 -7
- package/src/resource-rule.ts +252 -0
- package/src/rule-condition.ts +126 -0
- package/src/schema-keywords.ts +24 -0
- package/src/schema-projection.ts +403 -0
- package/src/step-slot.ts +64 -0
- package/src/telo-version.ts +1 -1
- package/src/validate-cel-context.ts +17 -3
- package/src/validate-durable-regions.ts +401 -0
- package/src/validate-references.ts +57 -2
- package/src/validate-referrer-rules.ts +373 -0
- package/src/validate-resource-rules.ts +401 -0
- package/src/validate-schema-projection.ts +184 -0
- package/src/validate-step-inputs.ts +5 -3
- package/src/validate-throws-coverage.ts +12 -5
- package/src/validate-zone-slots.ts +192 -8
- package/src/validate-zone-violations.ts +190 -0
- package/src/value-type-keyword.ts +4 -0
- package/src/zone-slot.ts +114 -5
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The single reader for `x-telo-resource-rules` — a kind declaring, as data,
|
|
3
|
+
* relationships between the fields of one resource that JSON Schema cannot
|
|
4
|
+
* state: an index naming a column its table does not declare, a foreign key
|
|
5
|
+
* whose two sides differ in length, a rename whose source is still declared.
|
|
6
|
+
*
|
|
7
|
+
* The predicate is CEL over `self` (the whole resource) and `this` (the element
|
|
8
|
+
* under test), so correlating two collections is a comprehension closure rather
|
|
9
|
+
* than a path language with wildcard bindings to design. `in:` names the
|
|
10
|
+
* collection to iterate and IS the diagnostic anchor: iterating what the pointer
|
|
11
|
+
* names is what makes a reported path exist by construction.
|
|
12
|
+
*
|
|
13
|
+
* Vocabulary borrowed from `Telo.JsonSchema.rules` — `condition` true when the
|
|
14
|
+
* rule HOLDS, the subject bound as `this`, plus `code` and `message` — because
|
|
15
|
+
* two CEL rule vocabularies with opposite polarity is a trap an author falls
|
|
16
|
+
* into once per rule. The two mechanisms stay separate: a `Telo.JsonSchema` rule
|
|
17
|
+
* runs at dispatch against a value, this one at `telo check` against a manifest.
|
|
18
|
+
*
|
|
19
|
+
* Lenient by design, the `ref-slot.ts` precedent: anything unreadable here reads
|
|
20
|
+
* as absent, and `validate-resource-rules.ts` is the strict half that reports it.
|
|
21
|
+
*
|
|
22
|
+
* Browser-safe: no Node built-ins.
|
|
23
|
+
*/
|
|
24
|
+
export const RESOURCE_RULES_ANNOTATION = "x-telo-resource-rules";
|
|
25
|
+
function isObject(value) {
|
|
26
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
27
|
+
}
|
|
28
|
+
/** True for a node the loader produced from a `!cel` tag or a `${{ }}` string.
|
|
29
|
+
* Both markers are tested because they are not always both present: a
|
|
30
|
+
* registered definition's schema reaches the analyzer with `call` and
|
|
31
|
+
* `__compiled` dropped, keeping only `__tagged` + `source`. Testing one would
|
|
32
|
+
* make a rule readable on some paths and invisible on others. */
|
|
33
|
+
function isCelNode(value) {
|
|
34
|
+
return isObject(value) && (value.__compiled === true || value.__tagged === true);
|
|
35
|
+
}
|
|
36
|
+
/** A precompiled `!cel` node keeps its author-written text on `source`; a plain
|
|
37
|
+
* string is taken verbatim so a rule reads the same however the loader was
|
|
38
|
+
* configured (a round-trip view runs with `compile` off). */
|
|
39
|
+
export function celSourceOf(value) {
|
|
40
|
+
if (typeof value === "string")
|
|
41
|
+
return value;
|
|
42
|
+
if (isCelNode(value) && typeof value.source === "string")
|
|
43
|
+
return value.source;
|
|
44
|
+
return undefined;
|
|
45
|
+
}
|
|
46
|
+
/** The annotation exactly as written, for the strict half. `undefined` when the
|
|
47
|
+
* kind declares none; a non-array is returned as-is so the shape can be
|
|
48
|
+
* reported rather than silently skipped. */
|
|
49
|
+
export function readRawResourceRules(schema) {
|
|
50
|
+
if (!isObject(schema))
|
|
51
|
+
return undefined;
|
|
52
|
+
return schema[RESOURCE_RULES_ANNOTATION];
|
|
53
|
+
}
|
|
54
|
+
/** Every rule this kind declares that is well-formed enough to run. */
|
|
55
|
+
export function readResourceRules(schema) {
|
|
56
|
+
const raw = readRawResourceRules(schema);
|
|
57
|
+
if (!Array.isArray(raw))
|
|
58
|
+
return [];
|
|
59
|
+
const rules = [];
|
|
60
|
+
raw.forEach((entry, index) => {
|
|
61
|
+
if (!isObject(entry))
|
|
62
|
+
return;
|
|
63
|
+
const condition = celSourceOf(entry.condition);
|
|
64
|
+
const { code, message } = entry;
|
|
65
|
+
if (!condition || typeof code !== "string" || typeof message !== "string")
|
|
66
|
+
return;
|
|
67
|
+
if (code.length === 0 || message.length === 0)
|
|
68
|
+
return;
|
|
69
|
+
const severity = entry.severity === "warning" ? "warning" : "error";
|
|
70
|
+
if (entry.severity !== undefined && entry.severity !== "warning" && entry.severity !== "error") {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const pointer = entry.in;
|
|
74
|
+
if (pointer !== undefined && typeof pointer !== "string")
|
|
75
|
+
return;
|
|
76
|
+
rules.push({
|
|
77
|
+
...(pointer === undefined ? {} : { in: pointer }),
|
|
78
|
+
condition,
|
|
79
|
+
code,
|
|
80
|
+
message,
|
|
81
|
+
severity,
|
|
82
|
+
index,
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
return rules;
|
|
86
|
+
}
|
|
87
|
+
/** Split a JSON Pointer into its unescaped segments. `/` alone is the root. */
|
|
88
|
+
export function pointerSegments(pointer) {
|
|
89
|
+
if (pointer === "" || pointer === "/")
|
|
90
|
+
return [];
|
|
91
|
+
if (!pointer.startsWith("/"))
|
|
92
|
+
return undefined;
|
|
93
|
+
return pointer
|
|
94
|
+
.slice(1)
|
|
95
|
+
.split("/")
|
|
96
|
+
.map((segment) => segment.replace(/~1/g, "/").replace(/~0/g, "~"));
|
|
97
|
+
}
|
|
98
|
+
/** Navigate a pointer within a value, stopping at anything that is not a plain
|
|
99
|
+
* container. Returns `undefined` for a pointer that does not resolve — which a
|
|
100
|
+
* resource legitimately produces by omitting an optional collection. */
|
|
101
|
+
export function resolvePointer(value, pointer) {
|
|
102
|
+
const segments = pointerSegments(pointer);
|
|
103
|
+
if (!segments)
|
|
104
|
+
return undefined;
|
|
105
|
+
let current = value;
|
|
106
|
+
for (const segment of segments) {
|
|
107
|
+
if (Array.isArray(current)) {
|
|
108
|
+
const index = Number(segment);
|
|
109
|
+
if (!Number.isInteger(index))
|
|
110
|
+
return undefined;
|
|
111
|
+
current = current[index];
|
|
112
|
+
}
|
|
113
|
+
else if (isObject(current)) {
|
|
114
|
+
current = current[segment];
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
return undefined;
|
|
118
|
+
}
|
|
119
|
+
if (current === undefined)
|
|
120
|
+
return undefined;
|
|
121
|
+
}
|
|
122
|
+
return current;
|
|
123
|
+
}
|
|
124
|
+
/** Path prefix for a pointer, in the dotted/bracketed spelling diagnostics use
|
|
125
|
+
* (`foreignKeys[0].references`), so `data.path` is one grammar throughout. */
|
|
126
|
+
export function pointerToPath(pointer) {
|
|
127
|
+
const segments = pointerSegments(pointer) ?? [];
|
|
128
|
+
return segments.reduce((acc, segment) => {
|
|
129
|
+
if (/^\d+$/.test(segment))
|
|
130
|
+
return `${acc}[${segment}]`;
|
|
131
|
+
return acc === "" ? segment : `${acc}.${segment}`;
|
|
132
|
+
}, "");
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* The elements a rule iterates. An array yields one subject per item, a map one
|
|
136
|
+
* per entry with its key bound; a collection that is absent yields none, which
|
|
137
|
+
* is a rule that had nothing to say rather than a rule that failed.
|
|
138
|
+
*
|
|
139
|
+
* A scalar at the pointer is `undefined` — not an empty list — because that is a
|
|
140
|
+
* declaration defect the strict half reports, and an empty list would hide it.
|
|
141
|
+
*/
|
|
142
|
+
export function resolveRuleSubjects(config, pointer) {
|
|
143
|
+
const collection = resolvePointer(config, pointer);
|
|
144
|
+
if (collection === undefined || collection === null)
|
|
145
|
+
return [];
|
|
146
|
+
const base = pointerToPath(pointer);
|
|
147
|
+
if (Array.isArray(collection)) {
|
|
148
|
+
return collection.map((value, index) => ({ path: `${base}[${index}]`, value }));
|
|
149
|
+
}
|
|
150
|
+
if (isObject(collection)) {
|
|
151
|
+
return Object.entries(collection).map(([key, value]) => ({
|
|
152
|
+
path: `${base}.${key}`,
|
|
153
|
+
value,
|
|
154
|
+
key,
|
|
155
|
+
}));
|
|
156
|
+
}
|
|
157
|
+
return undefined;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Path of the first CEL leaf inside a value, or `undefined` when every leaf is
|
|
161
|
+
* literal. A rule reading an expression would be evaluating a placeholder, so
|
|
162
|
+
* the subject is skipped — and the skip is reported, never silent.
|
|
163
|
+
*
|
|
164
|
+
* Stops at nested inline `{ kind }` declarations for the reason every other walk
|
|
165
|
+
* does: that CEL belongs to the nested kind, evaluated in its own scope.
|
|
166
|
+
*/
|
|
167
|
+
export function findDynamicLeaf(value, base = "") {
|
|
168
|
+
if (isObject(value)) {
|
|
169
|
+
if (isCelNode(value))
|
|
170
|
+
return base || "(value)";
|
|
171
|
+
if (typeof value.kind === "string" && base !== "")
|
|
172
|
+
return undefined;
|
|
173
|
+
for (const [key, child] of Object.entries(value)) {
|
|
174
|
+
const found = findDynamicLeaf(child, base === "" ? key : `${base}.${key}`);
|
|
175
|
+
if (found)
|
|
176
|
+
return found;
|
|
177
|
+
}
|
|
178
|
+
return undefined;
|
|
179
|
+
}
|
|
180
|
+
if (Array.isArray(value)) {
|
|
181
|
+
for (let i = 0; i < value.length; i++) {
|
|
182
|
+
const found = findDynamicLeaf(value[i], `${base}[${i}]`);
|
|
183
|
+
if (found)
|
|
184
|
+
return found;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
return undefined;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* The nodes a condition actually READS, resolved against the resource and the
|
|
191
|
+
* element under test — the input to the dynamic-leaf check.
|
|
192
|
+
*
|
|
193
|
+
* Scanning the whole subject instead would make the check useless in exactly
|
|
194
|
+
* the shape it matters most: a resource-wide rule takes the whole resource as
|
|
195
|
+
* its subject, so one unrelated `!cel` anywhere (a `version:` read from
|
|
196
|
+
* `module.version`, which is the conventional spelling) would switch off every
|
|
197
|
+
* such rule. Chains are the same primitive the binding-order derivation uses:
|
|
198
|
+
* parsed, never lexed, so a name inside a string literal reads nothing.
|
|
199
|
+
*
|
|
200
|
+
* A chain stops at a computed index (`INDEX_SEGMENT`): what it selects is not
|
|
201
|
+
* known statically, so the node reached so far is what gets checked — the
|
|
202
|
+
* over-approximating direction, which errs toward skipping rather than toward
|
|
203
|
+
* evaluating a placeholder.
|
|
204
|
+
*/
|
|
205
|
+
export function readNodes(chains,
|
|
206
|
+
/** The bindings in scope, by name — `self`/`this`/`key` for a resource rule,
|
|
207
|
+
* `self`/`referrer` for a referrer rule. A chain rooted at a name that is not
|
|
208
|
+
* bound reads nothing. */
|
|
209
|
+
roots) {
|
|
210
|
+
const nodes = [];
|
|
211
|
+
for (const chain of chains) {
|
|
212
|
+
const root = chain[0];
|
|
213
|
+
let current = root !== undefined && root in roots ? roots[root] : undefined;
|
|
214
|
+
if (current === undefined)
|
|
215
|
+
continue;
|
|
216
|
+
for (const segment of chain.slice(1)) {
|
|
217
|
+
if (segment === "[*]")
|
|
218
|
+
break;
|
|
219
|
+
if (Array.isArray(current)) {
|
|
220
|
+
const index = Number(segment);
|
|
221
|
+
current = Number.isInteger(index) ? current[index] : undefined;
|
|
222
|
+
}
|
|
223
|
+
else if (isObject(current)) {
|
|
224
|
+
current = current[segment];
|
|
225
|
+
}
|
|
226
|
+
else {
|
|
227
|
+
current = undefined;
|
|
228
|
+
}
|
|
229
|
+
if (current === undefined)
|
|
230
|
+
break;
|
|
231
|
+
}
|
|
232
|
+
if (current !== undefined)
|
|
233
|
+
nodes.push(current);
|
|
234
|
+
}
|
|
235
|
+
return nodes;
|
|
236
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A rule's CEL condition: compiling it once, and refusing the ones that cannot
|
|
3
|
+
* be checks.
|
|
4
|
+
*
|
|
5
|
+
* Shared by `x-telo-resource-rules` (fields of one resource) and
|
|
6
|
+
* `x-telo-referrer-rules` (a requirement on whoever references it). The two
|
|
7
|
+
* families differ in what they bind — `this` and `key` versus `referrer` — and
|
|
8
|
+
* in nothing else: same polarity, same cache, same refusals, same budget. Two
|
|
9
|
+
* copies would eventually disagree about which functions a rule may call, which
|
|
10
|
+
* is a soundness property rather than a style one.
|
|
11
|
+
*
|
|
12
|
+
* Browser-safe: no Node built-ins.
|
|
13
|
+
*/
|
|
14
|
+
import { buildCelEnvironment } from "@telorun/templating";
|
|
15
|
+
/**
|
|
16
|
+
* Wall-clock ceiling for one rule over one resource. The rules run on the
|
|
17
|
+
* kernel's boot path and at the editor's keystroke-time analysis, and the
|
|
18
|
+
* comprehension nesting is the RULE AUTHOR's — a dependency's quadratic rule
|
|
19
|
+
* must not be able to hang a consumer's `telo check`.
|
|
20
|
+
*
|
|
21
|
+
* It bounds the SUBJECT LOOP, not one expression: cel-js offers no step limit,
|
|
22
|
+
* so a single pathological expression over one huge element still runs to
|
|
23
|
+
* completion. Stated rather than hidden — the budget catches the shape that
|
|
24
|
+
* actually occurs (a cheap expression over many subjects) and reports the rule
|
|
25
|
+
* as defective rather than truncating coverage silently.
|
|
26
|
+
*/
|
|
27
|
+
export declare const RULE_BUDGET_MS = 50;
|
|
28
|
+
/** The analyzer's own environment — no host handlers, so every `hostBacked`
|
|
29
|
+
* entry is a throwing stub. Built once; it is stateless. */
|
|
30
|
+
export declare function ruleEnv(): ReturnType<typeof buildCelEnvironment>;
|
|
31
|
+
export type CompiledRule = {
|
|
32
|
+
parsed: (ctx: Record<string, unknown>) => unknown;
|
|
33
|
+
chains: readonly (readonly string[])[];
|
|
34
|
+
} | {
|
|
35
|
+
reason: string;
|
|
36
|
+
};
|
|
37
|
+
export declare function compileRuleCondition(condition: string,
|
|
38
|
+
/** Chain roots to assume when the parse yields no AST — "unknown", not
|
|
39
|
+
* "reads nothing", so the caller checks the whole of every binding. */
|
|
40
|
+
fallbackRoots: readonly string[]): CompiledRule;
|
|
41
|
+
/**
|
|
42
|
+
* Why a condition cannot serve as a check, as messages for the declaring kind.
|
|
43
|
+
*
|
|
44
|
+
* Two refusals beyond the CEL diagnostics themselves: a function the kernel
|
|
45
|
+
* supplies at boot (a throwing stub here, so the rule could never run at
|
|
46
|
+
* `telo check`), and a non-deterministic one (a verdict that depends on when it
|
|
47
|
+
* ran is not a verdict).
|
|
48
|
+
*/
|
|
49
|
+
export declare function conditionRefusals(condition: string): string[];
|
|
50
|
+
//# sourceMappingURL=rule-condition.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rule-condition.d.ts","sourceRoot":"","sources":["../src/rule-condition.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAEL,mBAAmB,EAGpB,MAAM,qBAAqB,CAAC;AAE7B;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,cAAc,KAAK,CAAC;AAQjC;6DAC6D;AAC7D,wBAAgB,OAAO,IAAI,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAGhE;AAED,MAAM,MAAM,YAAY,GACpB;IAAE,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC;IAAC,MAAM,EAAE,SAAS,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,CAAA;CAAE,GAC7F;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAsBvB,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,MAAM;AACjB;wEACwE;AACxE,aAAa,EAAE,SAAS,MAAM,EAAE,GAC/B,YAAY,CAoBd;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,CAmB7D"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A rule's CEL condition: compiling it once, and refusing the ones that cannot
|
|
3
|
+
* be checks.
|
|
4
|
+
*
|
|
5
|
+
* Shared by `x-telo-resource-rules` (fields of one resource) and
|
|
6
|
+
* `x-telo-referrer-rules` (a requirement on whoever references it). The two
|
|
7
|
+
* families differ in what they bind — `this` and `key` versus `referrer` — and
|
|
8
|
+
* in nothing else: same polarity, same cache, same refusals, same budget. Two
|
|
9
|
+
* copies would eventually disagree about which functions a rule may call, which
|
|
10
|
+
* is a soundness property rather than a style one.
|
|
11
|
+
*
|
|
12
|
+
* Browser-safe: no Node built-ins.
|
|
13
|
+
*/
|
|
14
|
+
import { CEL_FUNCTIONS, buildCelEnvironment, celEngine, extractAccessChains, } from "@telorun/templating";
|
|
15
|
+
/**
|
|
16
|
+
* Wall-clock ceiling for one rule over one resource. The rules run on the
|
|
17
|
+
* kernel's boot path and at the editor's keystroke-time analysis, and the
|
|
18
|
+
* comprehension nesting is the RULE AUTHOR's — a dependency's quadratic rule
|
|
19
|
+
* must not be able to hang a consumer's `telo check`.
|
|
20
|
+
*
|
|
21
|
+
* It bounds the SUBJECT LOOP, not one expression: cel-js offers no step limit,
|
|
22
|
+
* so a single pathological expression over one huge element still runs to
|
|
23
|
+
* completion. Stated rather than hidden — the budget catches the shape that
|
|
24
|
+
* actually occurs (a cheap expression over many subjects) and reports the rule
|
|
25
|
+
* as defective rather than truncating coverage silently.
|
|
26
|
+
*/
|
|
27
|
+
export const RULE_BUDGET_MS = 50;
|
|
28
|
+
const HOST_BACKED = new Set(CEL_FUNCTIONS.filter((f) => f.hostBacked).map((f) => f.name));
|
|
29
|
+
const NON_DETERMINISTIC = new Set(CEL_FUNCTIONS.filter((f) => !f.deterministic).map((f) => f.name));
|
|
30
|
+
let sharedEnv;
|
|
31
|
+
/** The analyzer's own environment — no host handlers, so every `hostBacked`
|
|
32
|
+
* entry is a throwing stub. Built once; it is stateless. */
|
|
33
|
+
export function ruleEnv() {
|
|
34
|
+
sharedEnv ??= buildCelEnvironment();
|
|
35
|
+
return sharedEnv;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* A rule's condition, parsed once per process rather than once per resource.
|
|
39
|
+
*
|
|
40
|
+
* The pass runs over every resource of a kind and at the editor's
|
|
41
|
+
* keystroke-time analysis, so a workspace with fifty tables parsed the same
|
|
42
|
+
* six conditions fifty times each. The source string is the whole key: the
|
|
43
|
+
* environment is stateless and shared, so two identical conditions genuinely
|
|
44
|
+
* compile to the same program. A parse FAILURE is cached too — it is a property
|
|
45
|
+
* of the condition, and re-deriving it per resource costs the same as the
|
|
46
|
+
* success it replaced.
|
|
47
|
+
*
|
|
48
|
+
* BOUNDED, because the editor analyses on every keystroke: a kind author editing
|
|
49
|
+
* a `condition:` interns one entry per character typed, and every one of those
|
|
50
|
+
* intermediate strings is dead the moment the next arrives. Insertion-ordered
|
|
51
|
+
* eviction is enough — the working set is the conditions a workspace actually
|
|
52
|
+
* declares, and a stale entry costs one re-parse.
|
|
53
|
+
*/
|
|
54
|
+
const RULE_CACHE_LIMIT = 512;
|
|
55
|
+
const compiledRules = new Map();
|
|
56
|
+
export function compileRuleCondition(condition,
|
|
57
|
+
/** Chain roots to assume when the parse yields no AST — "unknown", not
|
|
58
|
+
* "reads nothing", so the caller checks the whole of every binding. */
|
|
59
|
+
fallbackRoots) {
|
|
60
|
+
const cached = compiledRules.get(condition);
|
|
61
|
+
if (cached)
|
|
62
|
+
return cached;
|
|
63
|
+
let result;
|
|
64
|
+
try {
|
|
65
|
+
const parsed = ruleEnv().parse(condition);
|
|
66
|
+
const ast = parsed.ast;
|
|
67
|
+
result = {
|
|
68
|
+
parsed,
|
|
69
|
+
chains: ast ? extractAccessChains(ast) : fallbackRoots.map((root) => [root]),
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
catch (err) {
|
|
73
|
+
result = { reason: err instanceof Error ? err.message : String(err) };
|
|
74
|
+
}
|
|
75
|
+
if (compiledRules.size >= RULE_CACHE_LIMIT) {
|
|
76
|
+
const oldest = compiledRules.keys().next();
|
|
77
|
+
if (!oldest.done)
|
|
78
|
+
compiledRules.delete(oldest.value);
|
|
79
|
+
}
|
|
80
|
+
compiledRules.set(condition, result);
|
|
81
|
+
return result;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Why a condition cannot serve as a check, as messages for the declaring kind.
|
|
85
|
+
*
|
|
86
|
+
* Two refusals beyond the CEL diagnostics themselves: a function the kernel
|
|
87
|
+
* supplies at boot (a throwing stub here, so the rule could never run at
|
|
88
|
+
* `telo check`), and a non-deterministic one (a verdict that depends on when it
|
|
89
|
+
* ran is not a verdict).
|
|
90
|
+
*/
|
|
91
|
+
export function conditionRefusals(condition) {
|
|
92
|
+
const out = [];
|
|
93
|
+
const result = celEngine.analyze(condition, { celEnv: ruleEnv(), contextSchema: null });
|
|
94
|
+
for (const diagnostic of result.diagnostics)
|
|
95
|
+
out.push(`Rule condition: ${diagnostic.message}`);
|
|
96
|
+
for (const call of result.calls) {
|
|
97
|
+
if (HOST_BACKED.has(call.name)) {
|
|
98
|
+
out.push(`Rule condition calls '${call.name}()', which the kernel supplies at boot ` +
|
|
99
|
+
"(it needs Node crypto / Buffer). The analyzer registers a throwing stub, so " +
|
|
100
|
+
"the rule cannot run at telo check.");
|
|
101
|
+
}
|
|
102
|
+
else if (NON_DETERMINISTIC.has(call.name) || call.deterministic === false) {
|
|
103
|
+
out.push(`Rule condition calls '${call.name}()', which re-evaluates per call. A check ` +
|
|
104
|
+
"whose verdict depends on when it ran is not a check.");
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return out;
|
|
108
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema-keywords.d.ts","sourceRoot":"","sources":["../src/schema-keywords.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAE9D;iDACiD;AACjD,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AASrE;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,CAuJ/D;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,uBAAuB,EAAE,MAAM,CAC1C,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,GAAG,OAAO,WAAW,EACzD,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"schema-keywords.d.ts","sourceRoot":"","sources":["../src/schema-keywords.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAE9D;iDACiD;AACjD,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AASrE;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,CAuJ/D;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,uBAAuB,EAAE,MAAM,CAC1C,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,GAAG,OAAO,WAAW,EACzD,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAwJxB,CAAC"}
|
package/dist/schema-keywords.js
CHANGED
|
@@ -245,6 +245,26 @@ export const TELO_SCHEMA_ANNOTATIONS = {
|
|
|
245
245
|
description: "Derive this field's validation schema from a sibling ref's definition schema.",
|
|
246
246
|
type: "string",
|
|
247
247
|
},
|
|
248
|
+
"x-telo-schema-map": {
|
|
249
|
+
title: "Schema map",
|
|
250
|
+
description: "On the field a projection keys on: the JSON Schema node each of its values means. A lookup, never a computed expression.",
|
|
251
|
+
type: "object",
|
|
252
|
+
},
|
|
253
|
+
"x-telo-schema-projection": {
|
|
254
|
+
title: "Schema projection",
|
|
255
|
+
description: "How a collection of typed entries projects to a JSON Schema object — which collection, which field keys it, and which fields modify it. Belongs on the kind DOCUMENT, beside 'schema:' rather than inside it, because it describes the whole declaration and not one field; written here it still works and is reported so it can be moved.",
|
|
256
|
+
type: "object",
|
|
257
|
+
},
|
|
258
|
+
"x-telo-resource-rules": {
|
|
259
|
+
title: "Resource rules",
|
|
260
|
+
description: "Relationships between this kind's own fields that JSON Schema cannot state, as CEL over `self` (the resource) and `this` (the element `in:` iterates). `condition` is TRUE when the rule holds.",
|
|
261
|
+
type: "array",
|
|
262
|
+
},
|
|
263
|
+
"x-telo-schema-projection-from": {
|
|
264
|
+
title: "Schema projection from",
|
|
265
|
+
description: "Replace this node with the projection of the entry collection declared by the kind referenced at the named field.",
|
|
266
|
+
type: "string",
|
|
267
|
+
},
|
|
248
268
|
"x-telo-value-schema-from": {
|
|
249
269
|
title: "Value schema from",
|
|
250
270
|
description: "The value here must satisfy the type declared at the named field — checked for EVERY such slot, not only the branch a given input selects.",
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The schema-projection annotations' single reader — the `ref-slot.ts` /
|
|
3
|
+
* `zone-slot.ts` precedent.
|
|
4
|
+
*
|
|
5
|
+
* A kind whose configuration is a COLLECTION OF TYPED ENTRIES can say what that
|
|
6
|
+
* collection means as a JSON Schema object, so a consumer can type the values
|
|
7
|
+
* it will read without the analyzer learning anything about the domain. A SQL
|
|
8
|
+
* table's columns are the first consumer; nothing in either annotation says
|
|
9
|
+
* SQL, column or table.
|
|
10
|
+
*
|
|
11
|
+
* Two halves, because the two facts have different owners:
|
|
12
|
+
*
|
|
13
|
+
* - `x-telo-schema-map`, on the field a projection keys on, gives the schema
|
|
14
|
+
* node each of its values means (`citext → {type: string}`). It sits with the
|
|
15
|
+
* field because that is where the value vocabulary is declared.
|
|
16
|
+
* - `x-telo-schema-projection`, on the KIND DOCUMENT (a sibling of `schema:`,
|
|
17
|
+
* not a keyword inside it), names the entry collection, the keying field, and
|
|
18
|
+
* the fields that MODIFY the mapped node. It sits on the document because it
|
|
19
|
+
* describes the kind's whole declaration rather than one field of it — but
|
|
20
|
+
* `schema:` is where every other `x-telo-*` keyword lives, so the reader
|
|
21
|
+
* accepts it in both positions and `validate-schema-projection.ts` reports the
|
|
22
|
+
* inner one. Silently ignoring a misplaced annotation is the exact failure the
|
|
23
|
+
* strict half exists to prevent: the projection stops typing its consumers and
|
|
24
|
+
* the diagnostic lands on the CONSUMER, blaming the wrong author.
|
|
25
|
+
*
|
|
26
|
+
* It is a declared LOOKUP, never a computed expression. The analyzer
|
|
27
|
+
* type-checks CEL and substitutes placeholders; it never evaluates, and a
|
|
28
|
+
* `base:`-style mapping is evaluated by the kernel at `create()` — too late for
|
|
29
|
+
* `telo check` to type the rows a consumer reads, which is the projection's
|
|
30
|
+
* whole purpose.
|
|
31
|
+
*
|
|
32
|
+
* Distinct from `x-telo-schema-from`, which derives a field's schema from a
|
|
33
|
+
* referenced KIND's definition schema. A projection is DECLARATION-derived: the
|
|
34
|
+
* row shape lives in one instance's own `columns:`, which no definition-level
|
|
35
|
+
* derivation can reach.
|
|
36
|
+
*/
|
|
37
|
+
/** How a kind's entry collection projects to an object schema. */
|
|
38
|
+
export interface SchemaProjection {
|
|
39
|
+
/** JSON Pointer, from the resource root, to the entries. */
|
|
40
|
+
readonly entries: string;
|
|
41
|
+
/** The entry field whose value keys the `x-telo-schema-map` lookup. */
|
|
42
|
+
readonly key: string;
|
|
43
|
+
/** The entry field naming an entry's identity, when entries are an ARRAY.
|
|
44
|
+
* Absent for a keyed map, where the map key is the identity. */
|
|
45
|
+
readonly nameField?: string;
|
|
46
|
+
/** Entry field that widens the mapped node to admit null. */
|
|
47
|
+
readonly nullable?: string;
|
|
48
|
+
/** Entry field that wraps the mapped node in an array. */
|
|
49
|
+
readonly array?: string;
|
|
50
|
+
}
|
|
51
|
+
export type SchemaMap = Readonly<Record<string, Record<string, unknown>>>;
|
|
52
|
+
/** The projection a kind declares, or undefined. Invalid shapes read as absent;
|
|
53
|
+
* `validate-schema-projection.ts` is the half that reports them. */
|
|
54
|
+
export declare function readSchemaProjection(definition: unknown): SchemaProjection | undefined;
|
|
55
|
+
/** The annotation as written, from either position — the document (canonical)
|
|
56
|
+
* or `schema:` (accepted, and reported by the strict half). The document wins:
|
|
57
|
+
* a kind spelling it in both places is describing its own document. */
|
|
58
|
+
export declare function rawSchemaProjection(definition: unknown): unknown;
|
|
59
|
+
/** True when the annotation was found inside `schema:` rather than on the
|
|
60
|
+
* document — the misplacement the strict half reports. */
|
|
61
|
+
export declare function schemaProjectionIsMisplaced(definition: unknown): boolean;
|
|
62
|
+
export declare function readSchemaMap(node: unknown): SchemaMap | undefined;
|
|
63
|
+
/** The consumer-side annotation: a JSON Pointer to this resource's ref slot
|
|
64
|
+
* whose target declares the projection. */
|
|
65
|
+
export declare function readProjectionFrom(node: unknown): string | undefined;
|
|
66
|
+
/**
|
|
67
|
+
* Find the `x-telo-schema-map` a projection keys on. The map sits on the entry
|
|
68
|
+
* field's schema, which is reached through the collection's own schema — a
|
|
69
|
+
* keyed map's `additionalProperties`, or an array's `items`.
|
|
70
|
+
*/
|
|
71
|
+
export declare function projectionKeyMap(kindSchema: unknown, projection: SchemaProjection): SchemaMap | undefined;
|
|
72
|
+
/**
|
|
73
|
+
* Project one declaration to an object schema.
|
|
74
|
+
*
|
|
75
|
+
* Modifiers are a CLOSED set applied in a FIXED order — `array` wraps, then
|
|
76
|
+
* `nullable` widens. Closed because each changes how the schema is assembled,
|
|
77
|
+
* so a third-party modifier would be a name nothing acts on; ordered because
|
|
78
|
+
* leaving it implicit is how two implementations come to disagree.
|
|
79
|
+
*
|
|
80
|
+
* The projection is deliberately LOSSY. Length, precision, collation and check
|
|
81
|
+
* constraints do not reach it: a consumer needs the type, its nullability and
|
|
82
|
+
* its repetition, and the database enforces the rest. A per-entry schema rich
|
|
83
|
+
* enough to double as a validator would move the domain's semantics into the
|
|
84
|
+
* type layer.
|
|
85
|
+
*/
|
|
86
|
+
export declare function projectEntries(manifest: unknown, projection: SchemaProjection, map: SchemaMap): Record<string, unknown> | undefined;
|
|
87
|
+
/** A reference as the analyzer sees it: the internal `{kind, name, alias?}`
|
|
88
|
+
* shape `resolveRefSentinels` rewrites `!ref` to. */
|
|
89
|
+
export interface ProjectionRef {
|
|
90
|
+
readonly name: string;
|
|
91
|
+
readonly kind?: string;
|
|
92
|
+
readonly alias?: string;
|
|
93
|
+
}
|
|
94
|
+
/** The `{kind, name, alias?}` reference a value holds, or undefined. Exported so
|
|
95
|
+
* a host whose slot may hold EITHER shape can fall back to this reading. */
|
|
96
|
+
export declare function readProjectionRef(value: unknown): ProjectionRef | undefined;
|
|
97
|
+
/** What a reference resolved to. `"ambiguous"` is distinct from `undefined`
|
|
98
|
+
* because the two need different advice: one says disambiguate, the other says
|
|
99
|
+
* the name resolves to nothing. */
|
|
100
|
+
export type ProjectionLookup = {
|
|
101
|
+
readonly manifest: Record<string, any>;
|
|
102
|
+
} | {
|
|
103
|
+
readonly ambiguous: true;
|
|
104
|
+
} | undefined;
|
|
105
|
+
/**
|
|
106
|
+
* What projecting a consumer's slot needs: resolving a reference to the manifest
|
|
107
|
+
* it names, and the definition that manifest's `kind` names.
|
|
108
|
+
*
|
|
109
|
+
* A RESOLVER rather than a list of manifests, because resolution is scoped and
|
|
110
|
+
* only the host knows the scope: an alias-qualified `!ref Alias.users` names an
|
|
111
|
+
* import's exported instance, and a bare name means the enclosing module's — a
|
|
112
|
+
* distinction a name filter over one flattened list erases, which is how an
|
|
113
|
+
* unambiguous cross-module reference came to read as ambiguous. It is also what
|
|
114
|
+
* lets the kernel supply its own context lookup, so the contract the analyzer
|
|
115
|
+
* types and the contract the kernel enforces are the same schema.
|
|
116
|
+
*/
|
|
117
|
+
export interface ProjectionScope {
|
|
118
|
+
/**
|
|
119
|
+
* The declaration the value at a projected slot names.
|
|
120
|
+
*
|
|
121
|
+
* Takes the RAW slot value rather than a parsed reference, because what sits
|
|
122
|
+
* there depends on the host and only the host can read it: the analyzer sees
|
|
123
|
+
* the `{kind, name, alias?}` reference the loader produced, while the kernel
|
|
124
|
+
* binds contracts AFTER Phase-5 injection has replaced that reference with the
|
|
125
|
+
* live instance. Parsing it here would have hardcoded the analyzer's shape and
|
|
126
|
+
* left the kernel unable to resolve anything — which is a contract enforced
|
|
127
|
+
* statically and not at dispatch.
|
|
128
|
+
*/
|
|
129
|
+
resolveManifest(value: unknown): ProjectionLookup;
|
|
130
|
+
resolveDefinition(kind: string): Record<string, any> | undefined;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* The resolver for a FLATTENED manifest list — the analyzer's own shape.
|
|
134
|
+
*
|
|
135
|
+
* An alias narrows to the manifests forwarded from that import (stamped
|
|
136
|
+
* `metadata.alias` by flatten), so two libraries each exporting a `users` table
|
|
137
|
+
* stay distinguishable. Only when nothing carries the alias does it fall back to
|
|
138
|
+
* matching by name alone, which is the pre-flatten shape a standalone module
|
|
139
|
+
* analysis has.
|
|
140
|
+
*/
|
|
141
|
+
export declare function manifestListScope(manifests: readonly Record<string, any>[], resolveDefinition: (kind: string) => Record<string, any> | undefined): ProjectionScope;
|
|
142
|
+
export type ProjectionFailure = {
|
|
143
|
+
readonly reason: "no-ref";
|
|
144
|
+
readonly pointer: string;
|
|
145
|
+
} | {
|
|
146
|
+
readonly reason: "unresolved";
|
|
147
|
+
readonly pointer: string;
|
|
148
|
+
readonly name: string;
|
|
149
|
+
} | {
|
|
150
|
+
readonly reason: "ambiguous";
|
|
151
|
+
readonly pointer: string;
|
|
152
|
+
readonly name: string;
|
|
153
|
+
} | {
|
|
154
|
+
readonly reason: "no-projection";
|
|
155
|
+
readonly pointer: string;
|
|
156
|
+
readonly kind: string;
|
|
157
|
+
};
|
|
158
|
+
export declare function describeProjectionFailure(failure: ProjectionFailure): string;
|
|
159
|
+
/**
|
|
160
|
+
* Replace every `x-telo-schema-projection-from` node with the projection of the
|
|
161
|
+
* declaration it points at.
|
|
162
|
+
*
|
|
163
|
+
* Structural: returns a new schema and never mutates the one handed in. A node
|
|
164
|
+
* that cannot be projected is left exactly as it was — degrading to the slot's
|
|
165
|
+
* own schema rather than to a wrong one — and the reason is pushed to
|
|
166
|
+
* `failures`, because degrading SILENTLY is the failure this whole mechanism
|
|
167
|
+
* exists to move earlier: the consumer's contract quietly reopens and a
|
|
168
|
+
* misspelled field passes `telo check` exactly as it did before.
|
|
169
|
+
*/
|
|
170
|
+
export declare function resolveSchemaProjections(schema: unknown, manifest: Record<string, any> | undefined, scope: ProjectionScope, failures?: ProjectionFailure[]): unknown;
|
|
171
|
+
//# sourceMappingURL=schema-projection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-projection.d.ts","sourceRoot":"","sources":["../src/schema-projection.ts"],"names":[],"mappings":"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"}
|