@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
package/dist/zone-slot.js
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,8 +24,10 @@
|
|
|
17
24
|
* key: [/connection, /transaction/connection] # ordered, first hit wins
|
|
18
25
|
* reason: the statement would execute outside any transaction
|
|
19
26
|
*/
|
|
27
|
+
import { ZONE_ATTRIBUTES } from "@telorun/sdk";
|
|
20
28
|
const PROVIDES = "x-telo-provides-zone";
|
|
21
29
|
const REQUIRES = "x-telo-requires-zone";
|
|
30
|
+
const VIOLATES = "x-telo-violates-zone";
|
|
22
31
|
/** A self-relative JSON Pointer — the only correlation-key spelling the
|
|
23
32
|
* analyzer and the kernel read identically. Applied to BOTH the scalar and the
|
|
24
33
|
* list form: the kernel's walk splits on `/` and drops empty segments, so a
|
|
@@ -33,10 +42,38 @@ function isPointer(value) {
|
|
|
33
42
|
export function readProvidesZone(node) {
|
|
34
43
|
const raw = node?.[PROVIDES];
|
|
35
44
|
if (raw === true)
|
|
36
|
-
return {};
|
|
45
|
+
return { attributes: {} };
|
|
37
46
|
if (isPointer(raw))
|
|
38
|
-
return { key: raw };
|
|
39
|
-
|
|
47
|
+
return { key: raw, attributes: {} };
|
|
48
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw))
|
|
49
|
+
return undefined;
|
|
50
|
+
const obj = raw;
|
|
51
|
+
// A `key` that is present but unreadable makes the object form MEAN something
|
|
52
|
+
// different to the two halves — the correlation the author wrote is dropped
|
|
53
|
+
// here while the kernel's walk still resolves a bare name — so the whole
|
|
54
|
+
// annotation is refused rather than read as uncorrelated. Absent `key` is the
|
|
55
|
+
// legitimate uncorrelated case.
|
|
56
|
+
if (obj.key !== undefined && !isPointer(obj.key))
|
|
57
|
+
return undefined;
|
|
58
|
+
const attributes = {};
|
|
59
|
+
for (const [name, value] of Object.entries(obj)) {
|
|
60
|
+
if (name === "key")
|
|
61
|
+
continue;
|
|
62
|
+
// Unknown names and wrong-shaped values are reported by
|
|
63
|
+
// `validate-zone-slots`; skipped here so a typo degrades to an attribute
|
|
64
|
+
// this zone does not declare rather than to a consumer reading a name that
|
|
65
|
+
// means nothing to it.
|
|
66
|
+
if (!ZONE_ATTRIBUTES.has(name) || typeof value !== "string" || !value)
|
|
67
|
+
continue;
|
|
68
|
+
attributes[name] = value;
|
|
69
|
+
}
|
|
70
|
+
return { ...(isPointer(obj.key) ? { key: obj.key } : {}), attributes: attributes };
|
|
71
|
+
}
|
|
72
|
+
/** The attributes the zone a slot provides declares, or an empty record when the
|
|
73
|
+
* node provides no zone. The shape every containment consumer wants, so none of
|
|
74
|
+
* them repeats the `readProvidesZone(...)?.attributes ?? {}` dance. */
|
|
75
|
+
export function providedZoneAttributes(node) {
|
|
76
|
+
return readProvidesZone(node)?.attributes ?? {};
|
|
40
77
|
}
|
|
41
78
|
/** True when the node carries `x-telo-provides-zone` in any shape, valid or not
|
|
42
79
|
* — the recognition test validation needs before it judges the value. */
|
|
@@ -48,7 +85,7 @@ export function hasProvidesZone(node) {
|
|
|
48
85
|
export function readRequiresZone(node) {
|
|
49
86
|
const raw = node?.[REQUIRES];
|
|
50
87
|
if (typeof raw === "string" && raw)
|
|
51
|
-
return { zone: raw, key: [] };
|
|
88
|
+
return { zone: raw, key: [], attributes: [] };
|
|
52
89
|
if (!raw || typeof raw !== "object" || Array.isArray(raw))
|
|
53
90
|
return undefined;
|
|
54
91
|
const obj = raw;
|
|
@@ -56,11 +93,55 @@ export function readRequiresZone(node) {
|
|
|
56
93
|
return undefined;
|
|
57
94
|
// One filter for both spellings — see `isPointer`.
|
|
58
95
|
const key = (Array.isArray(obj.key) ? obj.key : [obj.key]).filter(isPointer);
|
|
59
|
-
|
|
96
|
+
// Unknown names are dropped here and reported by `validate-zone-slots`, the
|
|
97
|
+
// lenient-reader / strict-validator split this file has throughout: a typo
|
|
98
|
+
// degrades to a guarantee this requirement does not ask for, never to a
|
|
99
|
+
// consumer matching against a name that means nothing.
|
|
100
|
+
const attributes = (Array.isArray(obj.attributes) ? obj.attributes : []).filter((a) => typeof a === "string" && ZONE_ATTRIBUTES.has(a));
|
|
101
|
+
const slot = { zone: obj.zone, key, attributes };
|
|
60
102
|
if (typeof obj.reason === "string")
|
|
61
103
|
slot.reason = obj.reason;
|
|
62
104
|
return slot;
|
|
63
105
|
}
|
|
106
|
+
/**
|
|
107
|
+
* What this kind CANNOT honour about a region it is placed inside.
|
|
108
|
+
*
|
|
109
|
+
* The third relation, and the one the other two cannot express. `provides`
|
|
110
|
+
* declares what a region guarantees about its contents; `requires` declares what
|
|
111
|
+
* a resource needs of the region around it. Neither says *this resource breaks
|
|
112
|
+
* that guarantee* — and without it a zone attribute has a promise and no way to
|
|
113
|
+
* name what falsifies it: `noSuspend` would be enforced only when a parking kind
|
|
114
|
+
* happened to reach its runtime check, and `Durable.Sleep` would be
|
|
115
|
+
* indistinguishable from `Durable.Value`, which needs the same journal and parks
|
|
116
|
+
* nothing.
|
|
117
|
+
*
|
|
118
|
+
* Declared at the kind's SCHEMA ROOT, because it is a property of the kind
|
|
119
|
+
* rather than of one of its slots — a kind that suspends suspends however it is
|
|
120
|
+
* configured.
|
|
121
|
+
*
|
|
122
|
+
* Values are the author's REASON, exactly as on `provides`: a diagnostic prints
|
|
123
|
+
* the region's promise and this resource's rebuttal side by side, and both are
|
|
124
|
+
* their own authors' words.
|
|
125
|
+
*/
|
|
126
|
+
export function readViolatesZone(node) {
|
|
127
|
+
const raw = node?.[VIOLATES];
|
|
128
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw))
|
|
129
|
+
return {};
|
|
130
|
+
const out = {};
|
|
131
|
+
for (const [name, value] of Object.entries(raw)) {
|
|
132
|
+
// Lenient, like every reader here: `validate-zone-slots` reports a typo, and
|
|
133
|
+
// dropping it degrades to a violation nobody declared rather than to a
|
|
134
|
+
// consumer matching a name that means nothing.
|
|
135
|
+
if (!ZONE_ATTRIBUTES.has(name) || typeof value !== "string" || !value)
|
|
136
|
+
continue;
|
|
137
|
+
out[name] = value;
|
|
138
|
+
}
|
|
139
|
+
return out;
|
|
140
|
+
}
|
|
141
|
+
/** True when the node carries `x-telo-violates-zone` in any shape, valid or not. */
|
|
142
|
+
export function hasViolatesZone(node) {
|
|
143
|
+
return node?.[VIOLATES] !== undefined;
|
|
144
|
+
}
|
|
64
145
|
/** True when the node carries `x-telo-requires-zone` in any shape. */
|
|
65
146
|
export function hasRequiresZone(node) {
|
|
66
147
|
return node?.[REQUIRES] !== undefined;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@telorun/analyzer",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.64.0",
|
|
4
4
|
"description": "Telo Analyzer - Static manifest validator for Telo manifests.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"telo",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"@types/node": "^20.0.0",
|
|
50
50
|
"typescript": "^5.0.0",
|
|
51
51
|
"vitest": "^2.1.8",
|
|
52
|
-
"@telorun/sdk": "0.
|
|
52
|
+
"@telorun/sdk": "0.80.0"
|
|
53
53
|
},
|
|
54
54
|
"peerDependencies": {
|
|
55
55
|
"@telorun/sdk": "*"
|
package/src/analysis-registry.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ResourceDefinition, ResourceManifest } from "@telorun/sdk";
|
|
2
2
|
import { AliasResolver } from "./alias-resolver.js";
|
|
3
3
|
import { KERNEL_BUILTINS } from "./builtins.js";
|
|
4
|
+
import { ManifestAnalysis } from "./manifest-analysis.js";
|
|
4
5
|
import { DefinitionRegistry } from "./definition-registry.js";
|
|
5
6
|
import { computeSuggestKind, computeValidUserFacingKinds } from "./kind-suggest.js";
|
|
6
7
|
import { visitManifest as runVisitManifest, type ManifestVisitor } from "./manifest-visitor.js";
|
|
@@ -174,6 +175,12 @@ export class AnalysisRegistry {
|
|
|
174
175
|
): Record<string, unknown> | undefined {
|
|
175
176
|
const def = this.resolveDefinition(kind);
|
|
176
177
|
if (!def) return undefined;
|
|
178
|
+
// A KIND-level query: there is no instance, so a DECLARATION-derived slot
|
|
179
|
+
// (`x-telo-schema-projection-from`) has no reference to project from and is
|
|
180
|
+
// left as the kind declared it. That is the honest answer here — the
|
|
181
|
+
// projected shape is a property of one instance, not of the kind — and it is
|
|
182
|
+
// why passing no manifest cannot silently drop a projection: the per-resource
|
|
183
|
+
// analysis pass is what resolves and reports them.
|
|
177
184
|
return resolveContract(direction, undefined, def, {
|
|
178
185
|
resolveDefinition: this.scopedDefResolver(),
|
|
179
186
|
typeManifestsFor: () => [],
|
|
@@ -236,6 +243,42 @@ export class AnalysisRegistry {
|
|
|
236
243
|
});
|
|
237
244
|
}
|
|
238
245
|
|
|
246
|
+
/**
|
|
247
|
+
* Resolves an `x-telo-schema-from` annotation to the schema node it derives,
|
|
248
|
+
* in the scope of the kind that DECLARED it — anchors are alias-qualified, and
|
|
249
|
+
* the declaring definition's module is where those aliases mean something.
|
|
250
|
+
*
|
|
251
|
+
* The seam an IDE walks a schema through: a slot shaped entirely by this
|
|
252
|
+
* annotation (an `Http.Api` route's `request:`) carries no `properties` of its
|
|
253
|
+
* own, so a walker that only reads `properties` finds nothing there and
|
|
254
|
+
* silently offers no keys and no hover — a whole field of the standard library
|
|
255
|
+
* looking like an unknown one.
|
|
256
|
+
*/
|
|
257
|
+
resolveSchemaFrom(schemaFrom: string, declaringKind: string): Record<string, any> | undefined {
|
|
258
|
+
const def = this.resolveDefinition(declaringKind);
|
|
259
|
+
const ownerModule = (def?.metadata as { module?: string } | undefined)?.module;
|
|
260
|
+
const scope = (ownerModule ? this.aliasesByModule.get(ownerModule) : undefined) ?? this.aliases;
|
|
261
|
+
return this.defs.resolveSchemaFromNode(schemaFrom, scope);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* The queries that need this registry AND a manifest set: what CEL sees at a
|
|
266
|
+
* site, where a binding was declared, what a reference's contract is.
|
|
267
|
+
*
|
|
268
|
+
* The seam an IDE reaches all of them through, and one object rather than a
|
|
269
|
+
* factory per question — each answer has to be the one the analysis pass
|
|
270
|
+
* computed, or a completion list stops being a claim about what `telo check`
|
|
271
|
+
* accepts. Built per analysis, not per keystroke: the indices behind it are a
|
|
272
|
+
* function of the whole manifest set.
|
|
273
|
+
*/
|
|
274
|
+
analysisOf(manifests: ResourceManifest[]): ManifestAnalysis {
|
|
275
|
+
return new ManifestAnalysis(manifests, {
|
|
276
|
+
defs: this.defs,
|
|
277
|
+
aliases: this.aliases,
|
|
278
|
+
aliasesByModule: this.aliasesByModule,
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
|
|
239
282
|
/**
|
|
240
283
|
* Returns the built-in kernel definitions. The underlying DefinitionRegistry already
|
|
241
284
|
* seeds these on construction; this method exposes them so callers (e.g. the kernel's
|