@telorun/analyzer 0.62.1 → 0.64.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 +24 -0
- package/dist/analysis-registry.d.ts.map +1 -1
- package/dist/analysis-registry.js +41 -0
- package/dist/analyzer.d.ts +3 -37
- package/dist/analyzer.d.ts.map +1 -1
- package/dist/analyzer.js +396 -476
- package/dist/call-graph.d.ts.map +1 -1
- package/dist/call-graph.js +2 -7
- package/dist/cel-scope-query.d.ts +109 -0
- package/dist/cel-scope-query.d.ts.map +1 -0
- package/dist/cel-scope-query.js +270 -0
- package/dist/cel-scope.d.ts +166 -0
- package/dist/cel-scope.d.ts.map +1 -0
- package/dist/cel-scope.js +377 -0
- package/dist/definition-registry.d.ts +15 -0
- package/dist/definition-registry.d.ts.map +1 -1
- package/dist/definition-registry.js +25 -9
- package/dist/find-manifest.d.ts +10 -0
- package/dist/find-manifest.d.ts.map +1 -0
- package/dist/find-manifest.js +12 -0
- 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 +22 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +22 -1
- package/dist/invocation-contract.d.ts +17 -1
- package/dist/invocation-contract.d.ts.map +1 -1
- package/dist/invocation-contract.js +42 -4
- package/dist/loaded-types.d.ts +12 -3
- package/dist/loaded-types.d.ts.map +1 -1
- package/dist/manifest-analysis.d.ts +73 -0
- package/dist/manifest-analysis.d.ts.map +1 -0
- package/dist/manifest-analysis.js +78 -0
- 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-path.d.ts +18 -0
- package/dist/manifest-path.d.ts.map +1 -0
- package/dist/manifest-path.js +37 -0
- 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/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/schema-walk.d.ts +25 -0
- package/dist/schema-walk.d.ts.map +1 -0
- package/dist/schema-walk.js +126 -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 +19 -1
- package/dist/validate-step-inputs.d.ts.map +1 -1
- package/dist/validate-step-inputs.js +102 -9
- 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 +43 -0
- package/src/analyzer.ts +452 -595
- package/src/call-graph.ts +2 -8
- package/src/cel-scope-query.ts +337 -0
- package/src/cel-scope.ts +570 -0
- package/src/definition-registry.ts +31 -13
- package/src/find-manifest.ts +19 -0
- package/src/flatten-for-analyzer.ts +1 -1
- package/src/import-resolution-diagnostics.ts +25 -7
- package/src/index.ts +86 -0
- package/src/invocation-contract.ts +67 -2
- package/src/loaded-types.ts +12 -3
- package/src/manifest-analysis.ts +132 -0
- package/src/manifest-loader.ts +87 -55
- package/src/manifest-path.ts +34 -0
- 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/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/schema-walk.ts +144 -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 +148 -10
- 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
|
@@ -1,5 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Static validation of the two execution-zone annotations themselves — the
|
|
3
|
+
* strict half of the accessor split, mirroring `validate-ref-slots.ts`.
|
|
4
|
+
*
|
|
5
|
+
* `readProvidesZone` / `readRequiresZone` are deliberately lenient: they return
|
|
6
|
+
* `undefined` for anything they cannot read. Without this pass that leniency is
|
|
7
|
+
* silent in the worst possible direction, because the two annotations fail in
|
|
8
|
+
* OPPOSITE ways:
|
|
9
|
+
*
|
|
10
|
+
* - an unreadable **requires** annotation drops the requirement entirely, so a
|
|
11
|
+
* safety constraint the author wrote is never enforced — and the resource
|
|
12
|
+
* then throws `ERR_ZONE_REQUIRED` / `ERR_ZONE_ANNOTATION_MISSING` at
|
|
13
|
+
* dispatch. That is exactly the silent-non-enforcement `ZONE_PROVIDER_UNRESOLVED`
|
|
14
|
+
* exists to prevent, reached by a different route.
|
|
15
|
+
* - an unreadable **provides** annotation drops the discharge, so the pass
|
|
16
|
+
* reports `ZONE_REQUIREMENT_UNSATISFIED` on manifests that are correct.
|
|
17
|
+
*
|
|
18
|
+
* A third shape is worse than either: a `key` the analyzer skips but the kernel
|
|
19
|
+
* accepts (a pointer with no leading `/` — the kernel's walk splits on `/` and
|
|
20
|
+
* drops empty segments, so it resolves) makes the two halves disagree about what
|
|
21
|
+
* the manifest MEANS, which is the one outcome neither severity can express.
|
|
22
|
+
*
|
|
23
|
+
* Scoping follows `X_TELO_REF_UNRESOLVED`: reported only for definitions in the
|
|
24
|
+
* entry's own modules — a published dependency's slot is not the consumer's to
|
|
25
|
+
* fix.
|
|
26
|
+
*
|
|
27
|
+
* Browser-safe: no Node built-ins.
|
|
28
|
+
*/
|
|
29
|
+
import { ZONE_ATTRIBUTES, zoneAttributeNames } from "@telorun/sdk";
|
|
30
|
+
import { distance } from "./levenshtein.js";
|
|
1
31
|
const PROVIDES = "x-telo-provides-zone";
|
|
2
32
|
const REQUIRES = "x-telo-requires-zone";
|
|
33
|
+
const VIOLATES = "x-telo-violates-zone";
|
|
3
34
|
/** A self-relative JSON Pointer, the only correlation-key spelling both halves
|
|
4
35
|
* read identically. `""` (whole document) is meaningless as a key, so a
|
|
5
36
|
* pointer must name at least one segment. */
|
|
@@ -15,20 +46,133 @@ function describe(value) {
|
|
|
15
46
|
return "null";
|
|
16
47
|
return typeof value;
|
|
17
48
|
}
|
|
49
|
+
/** The closest declared attribute name within an edit-distance threshold, or
|
|
50
|
+
* undefined. Mirrors `suggestValueType`: case-sensitive, and silent on a tie,
|
|
51
|
+
* because a coin-flip suggestion is worse than none. */
|
|
52
|
+
function suggestAttribute(name) {
|
|
53
|
+
if (!name)
|
|
54
|
+
return undefined;
|
|
55
|
+
const threshold = Math.min(3, Math.floor(name.length / 3));
|
|
56
|
+
if (threshold < 1)
|
|
57
|
+
return undefined;
|
|
58
|
+
let best;
|
|
59
|
+
let bestDist = threshold + 1;
|
|
60
|
+
let tied = false;
|
|
61
|
+
for (const candidate of ZONE_ATTRIBUTES.keys()) {
|
|
62
|
+
const d = distance(name, candidate);
|
|
63
|
+
if (d < bestDist) {
|
|
64
|
+
best = candidate;
|
|
65
|
+
bestDist = d;
|
|
66
|
+
tied = false;
|
|
67
|
+
}
|
|
68
|
+
else if (d === bestDist) {
|
|
69
|
+
tied = true;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return !best || bestDist > threshold || tied ? undefined : best;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* The attributes half of the object form.
|
|
76
|
+
*
|
|
77
|
+
* The composed `additionalProperties: false` schema would already reject an
|
|
78
|
+
* unknown name; the dedicated code earns its place by NAMING the valid ones and
|
|
79
|
+
* suggesting a spelling, instead of reporting a schema violation on a key the
|
|
80
|
+
* author believed was real — the same standing `X_TELO_TYPE_UNKNOWN` has over
|
|
81
|
+
* the value-type vocabulary it is modelled on.
|
|
82
|
+
*/
|
|
83
|
+
function checkAttributes(obj, definition, path, issues, annotation = PROVIDES) {
|
|
84
|
+
const declared = new Set();
|
|
85
|
+
for (const [name, value] of Object.entries(obj)) {
|
|
86
|
+
if (name === "key")
|
|
87
|
+
continue;
|
|
88
|
+
const entry = ZONE_ATTRIBUTES.get(name);
|
|
89
|
+
if (!entry) {
|
|
90
|
+
const suggestion = suggestAttribute(name);
|
|
91
|
+
issues.push({
|
|
92
|
+
code: "ZONE_ATTRIBUTE_UNKNOWN",
|
|
93
|
+
manifest: definition,
|
|
94
|
+
path,
|
|
95
|
+
message: `${annotation} at '${path}' declares '${name}', which is not a zone attribute. ` +
|
|
96
|
+
(suggestion ? `Did you mean '${suggestion}'? ` : "") +
|
|
97
|
+
`The vocabulary is closed: ${zoneAttributeNames().join(", ")}. An attribute ` +
|
|
98
|
+
`states a property of everything executed inside this zone, and every reader ` +
|
|
99
|
+
`of one is core — a name outside the set would be read by nothing.`,
|
|
100
|
+
});
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
// Each value is the REASON, and it is required by being the value itself
|
|
104
|
+
// rather than a sibling of a boolean. That is also what makes a type check
|
|
105
|
+
// possible at all: there is no `true` to accept, so `atomic: true` is caught
|
|
106
|
+
// here rather than reading as a valid declaration with nothing to say.
|
|
107
|
+
if (typeof value !== "string" || !value) {
|
|
108
|
+
issues.push({
|
|
109
|
+
code: "ZONE_ANNOTATION_INVALID",
|
|
110
|
+
manifest: definition,
|
|
111
|
+
path,
|
|
112
|
+
message: `${annotation} at '${path}' declares '${name}' as ${describe(value)}. Every zone ` +
|
|
113
|
+
`attribute's value is the author's REASON — a non-empty sentence, quoted verbatim ` +
|
|
114
|
+
`by the diagnostics that enforce it (${entry.description}).`,
|
|
115
|
+
});
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
declared.add(name);
|
|
119
|
+
}
|
|
120
|
+
// The completeness rule is about what a region PROMISES: declaring `atomic`
|
|
121
|
+
// without `noSuspend` is an incomplete promise. A VIOLATION is not a promise —
|
|
122
|
+
// breaking one guarantee implies nothing about breaking another — so the rule
|
|
123
|
+
// does not apply there.
|
|
124
|
+
if (annotation !== PROVIDES)
|
|
125
|
+
return;
|
|
126
|
+
// `requires:` lives in the vocabulary entry rather than as a hardcoded pair of
|
|
127
|
+
// names here, so the completeness rule sits beside the thing it constrains.
|
|
128
|
+
for (const name of declared) {
|
|
129
|
+
for (const dependency of ZONE_ATTRIBUTES.get(name).requires) {
|
|
130
|
+
if (declared.has(dependency))
|
|
131
|
+
continue;
|
|
132
|
+
issues.push({
|
|
133
|
+
code: "ZONE_ATTRIBUTE_INCOMPLETE",
|
|
134
|
+
manifest: definition,
|
|
135
|
+
path,
|
|
136
|
+
message: `${PROVIDES} at '${path}' declares '${name}' without '${dependency}', which it ` +
|
|
137
|
+
`requires. ${ZONE_ATTRIBUTES.get(dependency).description} Declare it with its own ` +
|
|
138
|
+
`reason — a generic message is exactly what the required reason exists to prevent.`,
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
18
143
|
function checkProvides(raw, definition, path, issues) {
|
|
19
144
|
if (raw === true)
|
|
20
145
|
return;
|
|
21
146
|
if (isPointer(raw))
|
|
22
147
|
return;
|
|
148
|
+
if (raw && typeof raw === "object" && !Array.isArray(raw)) {
|
|
149
|
+
const obj = raw;
|
|
150
|
+
// `key` keeps the meaning it has in the scalar spelling; only its absence is
|
|
151
|
+
// legitimate here (an uncorrelated zone that still declares attributes).
|
|
152
|
+
if (obj.key !== undefined && !isPointer(obj.key)) {
|
|
153
|
+
issues.push({
|
|
154
|
+
code: "ZONE_ANNOTATION_INVALID",
|
|
155
|
+
manifest: definition,
|
|
156
|
+
path,
|
|
157
|
+
message: `${PROVIDES} at '${path}' declares the correlation key ${describe(obj.key)}, which ` +
|
|
158
|
+
`is not a self-relative JSON Pointer. Write '/connection'. A bare field name is ` +
|
|
159
|
+
`read as a pointer by the runtime but skipped by the checker, so the two halves ` +
|
|
160
|
+
`would disagree about what this manifest means.`,
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
checkAttributes(obj, definition, path, issues);
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
23
166
|
issues.push({
|
|
24
167
|
code: "ZONE_ANNOTATION_INVALID",
|
|
25
168
|
manifest: definition,
|
|
26
169
|
path,
|
|
27
170
|
message: `${PROVIDES} at '${path}' is ${describe(raw)}. It takes 'true' (the zone is ` +
|
|
28
|
-
`uncorrelated)
|
|
171
|
+
`uncorrelated), a self-relative JSON Pointer naming this kind's own field ` +
|
|
29
172
|
`whose resolved reference the zone carries as its correlation payload ` +
|
|
30
|
-
`(e.g. '/connection')
|
|
31
|
-
`
|
|
173
|
+
`(e.g. '/connection'), or an object carrying that pointer as 'key' beside the ` +
|
|
174
|
+
`zone attributes this region declares (${zoneAttributeNames().join(", ")}). It ` +
|
|
175
|
+
`never names the zone — the zone a slot provides is always the declaring kind.`,
|
|
32
176
|
});
|
|
33
177
|
}
|
|
34
178
|
function checkRequires(raw, definition, path, issues) {
|
|
@@ -72,13 +216,61 @@ function checkRequires(raw, definition, path, issues) {
|
|
|
72
216
|
if (obj.reason !== undefined && typeof obj.reason !== "string") {
|
|
73
217
|
fail(`${REQUIRES} at '${path}' declares a non-string 'reason'.`);
|
|
74
218
|
}
|
|
219
|
+
// `attributes` is the GUARANTEE half — what the satisfying zone must declare,
|
|
220
|
+
// as opposed to which kind it is. It is a list of NAMES with no reasons: the
|
|
221
|
+
// reason belongs to whoever makes the promise, and a requirer restating it
|
|
222
|
+
// would be a second sentence to keep in step with the one that is enforced.
|
|
223
|
+
if (obj.attributes !== undefined) {
|
|
224
|
+
if (!Array.isArray(obj.attributes) || obj.attributes.length === 0) {
|
|
225
|
+
fail(`${REQUIRES} at '${path}' declares 'attributes' as ${describe(obj.attributes)}. It ` +
|
|
226
|
+
`takes a non-empty list of zone attribute names; omit it to require the kind alone.`);
|
|
227
|
+
}
|
|
228
|
+
else {
|
|
229
|
+
for (const name of obj.attributes) {
|
|
230
|
+
if (typeof name === "string" && ZONE_ATTRIBUTES.has(name))
|
|
231
|
+
continue;
|
|
232
|
+
const suggestion = typeof name === "string" ? suggestAttribute(name) : undefined;
|
|
233
|
+
issues.push({
|
|
234
|
+
code: "ZONE_ATTRIBUTE_UNKNOWN",
|
|
235
|
+
manifest: definition,
|
|
236
|
+
path,
|
|
237
|
+
message: `${REQUIRES} at '${path}' requires '${String(name)}', which is not a zone ` +
|
|
238
|
+
`attribute. ` +
|
|
239
|
+
(suggestion ? `Did you mean '${suggestion}'? ` : "") +
|
|
240
|
+
`The vocabulary is closed: ${zoneAttributeNames().join(", ")}.`,
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
75
245
|
for (const key of Object.keys(obj)) {
|
|
76
|
-
if (key === "zone" || key === "key" || key === "reason") {
|
|
246
|
+
if (key === "zone" || key === "key" || key === "reason" || key === "attributes") {
|
|
77
247
|
continue;
|
|
78
248
|
}
|
|
79
249
|
fail(`${REQUIRES} at '${path}' declares an unknown property '${key}'. The object form takes ` +
|
|
80
|
-
`'zone', 'key' and '
|
|
250
|
+
`'zone', 'key', 'reason' and 'attributes'.`);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* The third annotation: what this kind cannot honour.
|
|
255
|
+
*
|
|
256
|
+
* Only the object form, because a violation without a reason is exactly the
|
|
257
|
+
* shape the vocabulary refuses everywhere else — the diagnostic that fires on it
|
|
258
|
+
* prints the region's promise and this resource's rebuttal side by side, and one
|
|
259
|
+
* of the two would otherwise be a generated sentence.
|
|
260
|
+
*/
|
|
261
|
+
function checkViolates(raw, definition, path, issues) {
|
|
262
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
263
|
+
issues.push({
|
|
264
|
+
code: "ZONE_ANNOTATION_INVALID",
|
|
265
|
+
manifest: definition,
|
|
266
|
+
path,
|
|
267
|
+
message: `${VIOLATES} at '${path}' is ${describe(raw)}. It takes a map of zone attribute ` +
|
|
268
|
+
`names to the reason this kind cannot honour each — ` +
|
|
269
|
+
`\`noSuspend: this waits for a delivery that may be days away\`.`,
|
|
270
|
+
});
|
|
271
|
+
return;
|
|
81
272
|
}
|
|
273
|
+
checkAttributes(raw, definition, path, issues, VIOLATES);
|
|
82
274
|
}
|
|
83
275
|
/** Walk a definition schema, reporting every zone annotation it cannot read.
|
|
84
276
|
* Pure-schema walk, so it needs a visited guard for cyclic `$defs`. */
|
|
@@ -97,8 +289,12 @@ function walkSchema(node, path, visited, definition, issues) {
|
|
|
97
289
|
checkProvides(obj[PROVIDES], definition, path, issues);
|
|
98
290
|
if (obj[REQUIRES] !== undefined)
|
|
99
291
|
checkRequires(obj[REQUIRES], definition, path, issues);
|
|
292
|
+
if (obj[VIOLATES] !== undefined)
|
|
293
|
+
checkViolates(obj[VIOLATES], definition, path, issues);
|
|
100
294
|
for (const [key, value] of Object.entries(obj)) {
|
|
101
|
-
if (key === PROVIDES || key === REQUIRES || key ===
|
|
295
|
+
if (key === PROVIDES || key === REQUIRES || key === VIOLATES)
|
|
296
|
+
continue;
|
|
297
|
+
if (key === "examples" || key === "default")
|
|
102
298
|
continue;
|
|
103
299
|
walkSchema(value, path ? `${path}.${key}` : key, visited, definition, issues);
|
|
104
300
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { CallGraph } from "./call-graph.js";
|
|
2
|
+
import { type DefinitionLookup } from "./resolve-zone-containment.js";
|
|
3
|
+
import { type AnalysisDiagnostic } from "./types.js";
|
|
4
|
+
export interface ZoneViolationArgs {
|
|
5
|
+
graph: CallGraph;
|
|
6
|
+
resolveDef: DefinitionLookup;
|
|
7
|
+
/** Only report against modules the entry owns — a published dependency's
|
|
8
|
+
* placement is not the consumer's to fix. */
|
|
9
|
+
reportModules: ReadonlySet<string>;
|
|
10
|
+
}
|
|
11
|
+
export declare function validateZoneViolations(args: ZoneViolationArgs): AnalysisDiagnostic[];
|
|
12
|
+
//# sourceMappingURL=validate-zone-violations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-zone-violations.d.ts","sourceRoot":"","sources":["../src/validate-zone-violations.ts"],"names":[],"mappings":"AA0CA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAmB,KAAK,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAsB,KAAK,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAKzE,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,SAAS,CAAC;IACjB,UAAU,EAAE,gBAAgB,CAAC;IAC7B;kDAC8C;IAC9C,aAAa,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CACpC;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,iBAAiB,GAAG,kBAAkB,EAAE,CA8FpF"}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `ZONE_ATTRIBUTE_VIOLATED` — a resource inside a region whose guarantee it
|
|
3
|
+
* declares it cannot honour.
|
|
4
|
+
*
|
|
5
|
+
* The third leg of the zone-attribute mechanism, and the one that makes the
|
|
6
|
+
* other two enforceable. `x-telo-provides-zone` says what a region guarantees
|
|
7
|
+
* about its contents and `x-telo-requires-zone` says what a resource needs of
|
|
8
|
+
* the region around it — but neither says *this resource breaks that
|
|
9
|
+
* guarantee*, so until now an attribute could be declared, resolved and read
|
|
10
|
+
* with nothing able to report the one thing it exists to prevent.
|
|
11
|
+
*
|
|
12
|
+
* **Generic over the whole vocabulary, and it names no kind.** The rule is one
|
|
13
|
+
* sentence — *a region declaring attribute A must not contain a resource
|
|
14
|
+
* declaring it violates A* — and it is run once per attribute in
|
|
15
|
+
* `sdk/zone-attributes/`. So `noSuspend` (a parking kind inside a lease) and any
|
|
16
|
+
* attribute added later are covered by the same traversal, and `modules/durable`
|
|
17
|
+
* stays outside the analyzer's surface exactly as the topology-driven constraint
|
|
18
|
+
* requires.
|
|
19
|
+
*
|
|
20
|
+
* **Both sentences are their authors' own.** The diagnostic prints the region's
|
|
21
|
+
* declared reason and the violating kind's declared reason side by side, because
|
|
22
|
+
* the useful message is the collision between two written claims — "this
|
|
23
|
+
* transaction holds a connection a parked run would lose" against "this waits
|
|
24
|
+
* for a delivery that may be days away" — and neither half is anything the
|
|
25
|
+
* analyzer could generate.
|
|
26
|
+
*
|
|
27
|
+
* **Enforced at runtime, warned early**, like every other containment rule: the
|
|
28
|
+
* walk under-approximates (an edge the call graph cannot see is invisible here),
|
|
29
|
+
* and the runtime check in the violating controller is the real enforcement. It
|
|
30
|
+
* is an ERROR rather than a warning nonetheless: where the walk *can* see the
|
|
31
|
+
* path, the placement is decidably wrong — the region's promise and the
|
|
32
|
+
* resource's rebuttal are both declarations, so nothing about the runtime can
|
|
33
|
+
* reconcile them.
|
|
34
|
+
*
|
|
35
|
+
* Browser-safe: no Node built-ins.
|
|
36
|
+
*/
|
|
37
|
+
import { SUSPENDING_BACKOFF_MS, ZONE_ATTRIBUTES, retryBackoffMs, } from "@telorun/sdk";
|
|
38
|
+
import { findZoneRegions } from "./resolve-zone-containment.js";
|
|
39
|
+
import { DiagnosticSeverity } from "./types.js";
|
|
40
|
+
import { readViolatesZone } from "./zone-slot.js";
|
|
41
|
+
const SOURCE = "telo";
|
|
42
|
+
export function validateZoneViolations(args) {
|
|
43
|
+
const { graph, resolveDef, reportModules } = args;
|
|
44
|
+
const diagnostics = [];
|
|
45
|
+
const reported = new Set();
|
|
46
|
+
// What each kind in the graph declares it cannot honour, resolved once. A
|
|
47
|
+
// graph holds many instances of few kinds, and this is a schema read.
|
|
48
|
+
const violationsOf = new Map();
|
|
49
|
+
const violations = (kind, module) => {
|
|
50
|
+
const key = `${module ?? ""}\0${kind}`;
|
|
51
|
+
let found = violationsOf.get(key);
|
|
52
|
+
if (!found) {
|
|
53
|
+
const def = resolveDef(kind, module);
|
|
54
|
+
found = readViolatesZone(def?.schema);
|
|
55
|
+
violationsOf.set(key, found);
|
|
56
|
+
}
|
|
57
|
+
return found;
|
|
58
|
+
};
|
|
59
|
+
for (const attribute of ZONE_ATTRIBUTES.keys()) {
|
|
60
|
+
for (const region of findZoneRegions(graph, resolveDef, attribute)) {
|
|
61
|
+
for (const contained of region.contents.values()) {
|
|
62
|
+
// The one step-level rule, and it is separate because it is a property
|
|
63
|
+
// of the STEP rather than of its target: a retry whose backoff is long
|
|
64
|
+
// enough to park suspends the run from inside a region that promised
|
|
65
|
+
// nothing in it would. Only `noSuspend` has such a rule, because only
|
|
66
|
+
// `noSuspend` is broken by waiting.
|
|
67
|
+
if (attribute === "noSuspend" && contained.node.type === "step") {
|
|
68
|
+
const ownerNode = graph.nodes.get(contained.node.owner);
|
|
69
|
+
const owner = ownerNode?.type === "resource" ? ownerNode : undefined;
|
|
70
|
+
if (owner &&
|
|
71
|
+
owned(owner.manifest, reportModules) &&
|
|
72
|
+
suspendingBackoff(contained.node.step.retry)) {
|
|
73
|
+
const dedupe = `retry\0${contained.node.id}`;
|
|
74
|
+
if (!reported.has(dedupe)) {
|
|
75
|
+
reported.add(dedupe);
|
|
76
|
+
diagnostics.push({
|
|
77
|
+
severity: DiagnosticSeverity.Error,
|
|
78
|
+
code: "ZONE_ATTRIBUTE_VIOLATED",
|
|
79
|
+
source: SOURCE,
|
|
80
|
+
message: `Step '${contained.node.name ?? contained.node.path}' declares a retry ` +
|
|
81
|
+
`whose last backoff reaches ${SUSPENDING_BACKOFF_MS}ms, at which point a ` +
|
|
82
|
+
`re-attempt waits by PARKING the run rather than by sleeping — but it is ` +
|
|
83
|
+
`inside a ${region.provider.kind} ` +
|
|
84
|
+
`'${region.provider.name}' region that declares 'noSuspend' ` +
|
|
85
|
+
`(${region.reason}). Shorten the backoff, or move the retry outside the ` +
|
|
86
|
+
`region so it re-attempts the region as a whole.`,
|
|
87
|
+
data: {
|
|
88
|
+
resource: { kind: owner.kind, name: owner.name },
|
|
89
|
+
filePath: owner.manifest.metadata?.source,
|
|
90
|
+
path: contained.node.path,
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
// A step node is a dispatch site, not a resource — whatever it reaches
|
|
97
|
+
// is in `contents` in its own right, so judging the step too would
|
|
98
|
+
// report one placement twice.
|
|
99
|
+
if (contained.node.type !== "resource")
|
|
100
|
+
continue;
|
|
101
|
+
const manifest = contained.node.manifest;
|
|
102
|
+
const module = manifest.metadata?.module;
|
|
103
|
+
const rebuttal = violations(contained.node.kind, module)[attribute];
|
|
104
|
+
if (!rebuttal)
|
|
105
|
+
continue;
|
|
106
|
+
if (!owned(manifest, reportModules))
|
|
107
|
+
continue;
|
|
108
|
+
const dedupe = `${region.provider.id}\0${region.slot}\0${contained.node.id}\0${attribute}`;
|
|
109
|
+
if (reported.has(dedupe))
|
|
110
|
+
continue;
|
|
111
|
+
reported.add(dedupe);
|
|
112
|
+
const path = [`${region.provider.name}.${region.slot}`, ...contained.via].join(" → ");
|
|
113
|
+
diagnostics.push({
|
|
114
|
+
severity: DiagnosticSeverity.Error,
|
|
115
|
+
code: "ZONE_ATTRIBUTE_VIOLATED",
|
|
116
|
+
source: SOURCE,
|
|
117
|
+
message: `${contained.node.kind} '${contained.node.name}' is inside a ` +
|
|
118
|
+
`${region.provider.kind} '${region.provider.name}' region that declares ` +
|
|
119
|
+
`'${attribute}' (${region.reason}), but ${contained.node.kind} cannot honour ` +
|
|
120
|
+
`it: ${rebuttal}. Reached by ${path}. Move it outside the region, or use a ` +
|
|
121
|
+
`region that does not make that promise.`,
|
|
122
|
+
data: {
|
|
123
|
+
resource: { kind: contained.node.kind, name: contained.node.name },
|
|
124
|
+
filePath: manifest.metadata?.source,
|
|
125
|
+
},
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return diagnostics;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Does this declared retry policy back off far enough to park?
|
|
134
|
+
*
|
|
135
|
+
* EXACT, not an estimate, and it is the runtime's own arithmetic
|
|
136
|
+
* (`retryBackoffMs`) rather than a second copy of it — a static rule that
|
|
137
|
+
* re-derives what it describes drifts from the behaviour the first time either
|
|
138
|
+
* side gains a knob. It is exact for a second reason too: the runtime branches
|
|
139
|
+
* on the UN-JITTERED backoff, so there is no coin flip for this to
|
|
140
|
+
* approximate. The last attempt has the largest backoff, so it decides.
|
|
141
|
+
*
|
|
142
|
+
* Only a STATICALLY KNOWN policy is judged — the `LIVE_VALUE_RETRIED` posture,
|
|
143
|
+
* and for its reason: a CEL budget says nothing, and guessing would report a
|
|
144
|
+
* conflict against a manifest that may never wait that long. An unreadable
|
|
145
|
+
* policy is left to the runtime check, which sees the real number.
|
|
146
|
+
*/
|
|
147
|
+
function suspendingBackoff(raw) {
|
|
148
|
+
if (!raw || typeof raw !== "object")
|
|
149
|
+
return false;
|
|
150
|
+
const policy = raw;
|
|
151
|
+
if (!Object.values(policy).every(isStaticValue))
|
|
152
|
+
return false;
|
|
153
|
+
const attempts = policy.attempts;
|
|
154
|
+
if (typeof attempts !== "number" || attempts <= 0)
|
|
155
|
+
return false;
|
|
156
|
+
return retryBackoffMs(policy, attempts - 1) >= SUSPENDING_BACKOFF_MS;
|
|
157
|
+
}
|
|
158
|
+
/** A CEL leaf reaches here as a compiled value or a tagged sentinel, and either
|
|
159
|
+
* way the policy is not statically known. Refusing the whole policy rather than
|
|
160
|
+
* the one field is the conservative direction: `maxDelay` alone decides the
|
|
161
|
+
* answer, so reading around an unresolved one would report a bound the manifest
|
|
162
|
+
* may never reach. */
|
|
163
|
+
function isStaticValue(value) {
|
|
164
|
+
return value === undefined || typeof value === "number" || typeof value === "string";
|
|
165
|
+
}
|
|
166
|
+
function owned(manifest, reportModules) {
|
|
167
|
+
const module = manifest.metadata?.module;
|
|
168
|
+
return !module || reportModules.size === 0 || reportModules.has(module);
|
|
169
|
+
}
|
|
@@ -28,7 +28,7 @@ import type { KeywordDefinition } from "ajv";
|
|
|
28
28
|
*
|
|
29
29
|
* `x-telo-type` is deliberately absent — it is the one that emits code.
|
|
30
30
|
*/
|
|
31
|
-
export declare const ANNOTATION_KEYWORDS: readonly ["x-telo-bindings-from", "x-telo-catches-for", "x-telo-context", "x-telo-context-collection-from", "x-telo-context-element-from", "x-telo-context-from", "x-telo-context-from-ref-kind", "x-telo-context-from-root", "x-telo-context-ref-from", "x-telo-error-context", "x-telo-eval", "x-telo-inline", "x-telo-outcome-list", "x-telo-provides-zone", "x-telo-ref", "x-telo-requires-zone", "x-telo-schema-from", "x-telo-scope", "x-telo-step-context", "x-telo-topology-role", "x-telo-value-schema-from", "x-telo-widget"];
|
|
31
|
+
export declare const ANNOTATION_KEYWORDS: readonly ["x-telo-bindings-from", "x-telo-catches-for", "x-telo-context", "x-telo-context-collection-from", "x-telo-context-element-from", "x-telo-context-from", "x-telo-context-from-ref-kind", "x-telo-context-from-root", "x-telo-context-ref-from", "x-telo-error-context", "x-telo-eval", "x-telo-inline", "x-telo-outcome-list", "x-telo-provides-zone", "x-telo-ref", "x-telo-requires-zone", "x-telo-resource-rules", "x-telo-schema-from", "x-telo-schema-map", "x-telo-schema-projection", "x-telo-schema-projection-from", "x-telo-scope", "x-telo-step-context", "x-telo-topology-role", "x-telo-value-schema-from", "x-telo-widget"];
|
|
32
32
|
/**
|
|
33
33
|
* The `x-telo-type` keyword.
|
|
34
34
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"value-type-keyword.d.ts","sourceRoot":"","sources":["../src/value-type-keyword.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;+EAqB+E;AAG/E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,KAAK,CAAC;AAiB7C;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,
|
|
1
|
+
{"version":3,"file":"value-type-keyword.d.ts","sourceRoot":"","sources":["../src/value-type-keyword.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;+EAqB+E;AAG/E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,KAAK,CAAC;AAiB7C;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,onBA2BtB,CAAC;AAEX;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,gBAAgB,IAAI,iBAAiB,CA+BpD;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE;IACxC,UAAU,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,UAAU,CAAC,EAAE,GAAG,KAAK,OAAO,CAAC;CACzD,GAAG,IAAI,CAGP"}
|
|
@@ -48,7 +48,11 @@ export const ANNOTATION_KEYWORDS = [
|
|
|
48
48
|
"x-telo-provides-zone",
|
|
49
49
|
"x-telo-ref",
|
|
50
50
|
"x-telo-requires-zone",
|
|
51
|
+
"x-telo-resource-rules",
|
|
51
52
|
"x-telo-schema-from",
|
|
53
|
+
"x-telo-schema-map",
|
|
54
|
+
"x-telo-schema-projection",
|
|
55
|
+
"x-telo-schema-projection-from",
|
|
52
56
|
"x-telo-scope",
|
|
53
57
|
"x-telo-step-context",
|
|
54
58
|
"x-telo-topology-role",
|
package/dist/zone-slot.d.ts
CHANGED
|
@@ -10,6 +10,13 @@
|
|
|
10
10
|
*
|
|
11
11
|
* x-telo-provides-zone: true # uncorrelated — the zone is the kind
|
|
12
12
|
* x-telo-provides-zone: /connection # correlation-key pointer (own field)
|
|
13
|
+
* x-telo-provides-zone: # correlation key + zone attributes
|
|
14
|
+
* key: /connection
|
|
15
|
+
* atomic: a rollback erases writes a journal recorded as done
|
|
16
|
+
* noSuspend: the transaction holds a connection a parked run would lose
|
|
17
|
+
*
|
|
18
|
+
* x-telo-violates-zone: # what this kind cannot honour
|
|
19
|
+
* noSuspend: this waits for a delivery that may be days away
|
|
13
20
|
*
|
|
14
21
|
* x-telo-requires-zone: Self.Transaction # uncorrelated string form
|
|
15
22
|
* x-telo-requires-zone: # object form
|
|
@@ -17,6 +24,7 @@
|
|
|
17
24
|
* key: [/connection, /transaction/connection] # ordered, first hit wins
|
|
18
25
|
* reason: the statement would execute outside any transaction
|
|
19
26
|
*/
|
|
27
|
+
import { type ZoneAttributes } from "@telorun/sdk";
|
|
20
28
|
/** A body slot that establishes the declaring kind's zone when dispatched
|
|
21
29
|
* through. The zone's identity is always the declaring kind — the annotation
|
|
22
30
|
* never names one, so provision-on-behalf-of is unrepresentable. */
|
|
@@ -25,6 +33,16 @@ export interface ProvidesZoneSlot {
|
|
|
25
33
|
* reference the zone carries as its correlation payload. Absent =
|
|
26
34
|
* uncorrelated (`true`). */
|
|
27
35
|
key?: string;
|
|
36
|
+
/** What this zone declares about everything executed inside it, keyed by the
|
|
37
|
+
* closed vocabulary's bare names with the author's REASON as each value (see
|
|
38
|
+
* `sdk/zone-attributes/`). Empty for the two scalar spellings, which say
|
|
39
|
+
* nothing about their contents.
|
|
40
|
+
*
|
|
41
|
+
* Read here and interpreted nowhere in this file: an attribute's meaning is
|
|
42
|
+
* entirely its consumer's — the containment walk, the step engine's collapse
|
|
43
|
+
* rule, the parking kinds — exactly as `readRefSlot` hands back `use` without
|
|
44
|
+
* acting on it. */
|
|
45
|
+
attributes: ZoneAttributes;
|
|
28
46
|
}
|
|
29
47
|
/** A field declaring that its resource must be reached through a zone. */
|
|
30
48
|
export interface RequiresZoneSlot {
|
|
@@ -38,16 +56,59 @@ export interface RequiresZoneSlot {
|
|
|
38
56
|
key: string[];
|
|
39
57
|
/** The runtime consequence, quoted after the path in diagnostics. */
|
|
40
58
|
reason?: string;
|
|
59
|
+
/**
|
|
60
|
+
* Zone attributes the satisfying zone must DECLARE — what it must guarantee,
|
|
61
|
+
* as opposed to which kind it is.
|
|
62
|
+
*
|
|
63
|
+
* The two are different questions and the kind test alone cannot answer the
|
|
64
|
+
* second. A kind may extend the required abstract, and so satisfy every kind
|
|
65
|
+
* check, while its body slot omits the attribute the requirer actually depends
|
|
66
|
+
* on — a durable workflow whose body does not declare `replayed` is a zone the
|
|
67
|
+
* durable checks never look inside, and a run parking there parks against
|
|
68
|
+
* nothing. Naming the attribute is what makes the requirement say what it
|
|
69
|
+
* means.
|
|
70
|
+
*
|
|
71
|
+
* Names come from the closed vocabulary (`sdk/zone-attributes/`), so the
|
|
72
|
+
* analyzer reads its own words here and no module's kind is named.
|
|
73
|
+
*/
|
|
74
|
+
attributes: string[];
|
|
41
75
|
}
|
|
42
76
|
/** Reads a schema node's provides-zone declaration, or undefined when it has
|
|
43
77
|
* none or the value is malformed (`validate-zone-slots` reports those). */
|
|
44
78
|
export declare function readProvidesZone(node: Record<string, any> | undefined): ProvidesZoneSlot | undefined;
|
|
79
|
+
/** The attributes the zone a slot provides declares, or an empty record when the
|
|
80
|
+
* node provides no zone. The shape every containment consumer wants, so none of
|
|
81
|
+
* them repeats the `readProvidesZone(...)?.attributes ?? {}` dance. */
|
|
82
|
+
export declare function providedZoneAttributes(node: Record<string, any> | undefined): ZoneAttributes;
|
|
45
83
|
/** True when the node carries `x-telo-provides-zone` in any shape, valid or not
|
|
46
84
|
* — the recognition test validation needs before it judges the value. */
|
|
47
85
|
export declare function hasProvidesZone(node: Record<string, any> | undefined): boolean;
|
|
48
86
|
/** Reads a schema node's requires-zone declaration, or undefined when it has
|
|
49
87
|
* none or the value is malformed (`validate-zone-slots` reports those). */
|
|
50
88
|
export declare function readRequiresZone(node: Record<string, any> | undefined): RequiresZoneSlot | undefined;
|
|
89
|
+
/**
|
|
90
|
+
* What this kind CANNOT honour about a region it is placed inside.
|
|
91
|
+
*
|
|
92
|
+
* The third relation, and the one the other two cannot express. `provides`
|
|
93
|
+
* declares what a region guarantees about its contents; `requires` declares what
|
|
94
|
+
* a resource needs of the region around it. Neither says *this resource breaks
|
|
95
|
+
* that guarantee* — and without it a zone attribute has a promise and no way to
|
|
96
|
+
* name what falsifies it: `noSuspend` would be enforced only when a parking kind
|
|
97
|
+
* happened to reach its runtime check, and `Durable.Sleep` would be
|
|
98
|
+
* indistinguishable from `Durable.Value`, which needs the same journal and parks
|
|
99
|
+
* nothing.
|
|
100
|
+
*
|
|
101
|
+
* Declared at the kind's SCHEMA ROOT, because it is a property of the kind
|
|
102
|
+
* rather than of one of its slots — a kind that suspends suspends however it is
|
|
103
|
+
* configured.
|
|
104
|
+
*
|
|
105
|
+
* Values are the author's REASON, exactly as on `provides`: a diagnostic prints
|
|
106
|
+
* the region's promise and this resource's rebuttal side by side, and both are
|
|
107
|
+
* their own authors' words.
|
|
108
|
+
*/
|
|
109
|
+
export declare function readViolatesZone(node: Record<string, any> | undefined): ZoneAttributes;
|
|
110
|
+
/** True when the node carries `x-telo-violates-zone` in any shape, valid or not. */
|
|
111
|
+
export declare function hasViolatesZone(node: Record<string, any> | undefined): boolean;
|
|
51
112
|
/** True when the node carries `x-telo-requires-zone` in any shape. */
|
|
52
113
|
export declare function hasRequiresZone(node: Record<string, any> | undefined): boolean;
|
|
53
114
|
/**
|
package/dist/zone-slot.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"zone-slot.d.ts","sourceRoot":"","sources":["../src/zone-slot.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"zone-slot.d.ts","sourceRoot":"","sources":["../src/zone-slot.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAmB,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC;AAMpE;;qEAEqE;AACrE,MAAM,WAAW,gBAAgB;IAC/B;;iCAE6B;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;;;;;;wBAQoB;IACpB,UAAU,EAAE,cAAc,CAAC;CAC5B;AAED,0EAA0E;AAC1E,MAAM,WAAW,gBAAgB;IAC/B;;2EAEuE;IACvE,IAAI,EAAE,MAAM,CAAC;IACb;;gCAE4B;IAC5B,GAAG,EAAE,MAAM,EAAE,CAAC;IACd,qEAAqE;IACrE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;;;;;;;;;;OAcG;IACH,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAYD;4EAC4E;AAC5E,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,SAAS,GAAG,gBAAgB,GAAG,SAAS,CAyBpG;AAED;;wEAEwE;AACxE,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,SAAS,GAAG,cAAc,CAE5F;AAED;0EAC0E;AAC1E,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,SAAS,GAAG,OAAO,CAE9E;AAED;4EAC4E;AAC5E,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,SAAS,GAAG,gBAAgB,GAAG,SAAS,CAkBpG;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,SAAS,GAAG,cAAc,CAYtF;AAED,oFAAoF;AACpF,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,SAAS,GAAG,OAAO,CAE9E;AAED,sEAAsE;AACtE,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,SAAS,GAAG,OAAO,CAE9E;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CACrC,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACrC,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,GACxC,IAAI,CAaN"}
|