@telorun/analyzer 0.12.1 → 1.0.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 +13 -0
- package/dist/analysis-registry.d.ts.map +1 -1
- package/dist/analysis-registry.js +15 -0
- package/dist/analyzer.d.ts.map +1 -1
- package/dist/analyzer.js +154 -83
- package/dist/builtins.d.ts.map +1 -1
- package/dist/builtins.js +85 -0
- package/dist/cel-environment.d.ts +1 -1
- package/dist/cel-environment.d.ts.map +1 -1
- package/dist/cel-environment.js +40 -2
- package/dist/dependency-graph.d.ts.map +1 -1
- package/dist/dependency-graph.js +41 -62
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/kernel-globals.d.ts +1 -1
- package/dist/kernel-globals.d.ts.map +1 -1
- package/dist/kernel-globals.js +19 -1
- package/dist/manifest-visitor.d.ts +124 -0
- package/dist/manifest-visitor.d.ts.map +1 -0
- package/dist/manifest-visitor.js +181 -0
- package/dist/reference-field-map.js +16 -0
- package/dist/resolve-throws-union.d.ts +10 -0
- package/dist/resolve-throws-union.d.ts.map +1 -1
- package/dist/resolve-throws-union.js +35 -7
- package/dist/schema-compat.d.ts +10 -0
- package/dist/schema-compat.d.ts.map +1 -1
- package/dist/schema-compat.js +32 -0
- package/dist/validate-cel-context.d.ts +14 -0
- package/dist/validate-cel-context.d.ts.map +1 -1
- package/dist/validate-cel-context.js +38 -0
- package/dist/validate-references.d.ts.map +1 -1
- package/dist/validate-references.js +124 -160
- package/dist/validate-unused-declarations.d.ts +25 -0
- package/dist/validate-unused-declarations.d.ts.map +1 -0
- package/dist/validate-unused-declarations.js +91 -0
- package/package.json +3 -3
- package/src/analysis-registry.ts +20 -0
- package/src/analyzer.ts +256 -168
- package/src/builtins.ts +85 -0
- package/src/cel-environment.ts +42 -1
- package/src/dependency-graph.ts +37 -52
- package/src/index.ts +11 -0
- package/src/kernel-globals.ts +22 -1
- package/src/manifest-visitor.ts +340 -0
- package/src/reference-field-map.ts +14 -0
- package/src/resolve-throws-union.ts +36 -8
- package/src/schema-compat.ts +32 -0
- package/src/validate-cel-context.ts +50 -0
- package/src/validate-references.ts +175 -211
- package/src/validate-unused-declarations.ts +95 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ResourceDefinition, ResourceManifest } from "@telorun/sdk";
|
|
2
|
+
import { type ManifestVisitor } from "./manifest-visitor.js";
|
|
2
3
|
import type { AnalysisContext } from "./types.js";
|
|
3
4
|
/**
|
|
4
5
|
* Accumulates type and alias knowledge for a running kernel or analysis session.
|
|
@@ -22,6 +23,18 @@ export declare class AnalysisRegistry {
|
|
|
22
23
|
* sub-schema (e.g. Server.notFoundHandler.returns[].content[mime].encoder).
|
|
23
24
|
*/
|
|
24
25
|
iterateFieldEntries(resource: ResourceManifest, onRef: (fieldPath: string) => void, onScope: (fieldPath: string) => void): void;
|
|
26
|
+
/**
|
|
27
|
+
* Walks a manifest's annotation sites (refs, scopes, schema-from, CEL) via
|
|
28
|
+
* the shared manifest visitor, bound to this registry's definitions and
|
|
29
|
+
* aliases. The public seam for hosts (editor overview graph, tooling) that
|
|
30
|
+
* need the same site discovery the analyzer's own passes use, without
|
|
31
|
+
* reaching into the internal DefinitionRegistry.
|
|
32
|
+
*/
|
|
33
|
+
visitManifest(resources: ResourceManifest[], visitor: ManifestVisitor, opts?: {
|
|
34
|
+
skipKinds?: ReadonlySet<string>;
|
|
35
|
+
expand?: boolean;
|
|
36
|
+
discoverNestedRefs?: boolean;
|
|
37
|
+
}): void;
|
|
25
38
|
/**
|
|
26
39
|
* Returns the built-in kernel definitions. The underlying DefinitionRegistry already
|
|
27
40
|
* seeds these on construction; this method exposes them so callers (e.g. the kernel's
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analysis-registry.d.ts","sourceRoot":"","sources":["../src/analysis-registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"analysis-registry.d.ts","sourceRoot":"","sources":["../src/analysis-registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAKzE,OAAO,EAAqC,KAAK,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAEhG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD;;;;GAIG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA4B;IACjD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAuB;IAC/C,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAoC;IAEpE,kBAAkB,CAAC,GAAG,EAAE,kBAAkB,GAAG,IAAI;IAIjD,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAIpE,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI;IAIpE,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAI7C;;;;;;;OAOG;IACH,mBAAmB,CACjB,QAAQ,EAAE,gBAAgB,EAC1B,KAAK,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,EAClC,OAAO,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,GACnC,IAAI;IAkBP;;;;;;OAMG;IACH,aAAa,CACX,SAAS,EAAE,gBAAgB,EAAE,EAC7B,OAAO,EAAE,eAAe,EACxB,IAAI,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,CAAC;QAAC,kBAAkB,CAAC,EAAE,OAAO,CAAA;KAAE,GACzF,IAAI;IAQP;;;;OAIG;IACH,kBAAkB,IAAI,kBAAkB,EAAE;IAI1C,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS;IAM/D,QAAQ,IAAI,MAAM,EAAE;IAIpB;mEAC+D;IAC/D,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE;IAIxC;;;gCAG4B;IAC5B,oBAAoB,IAAI,MAAM,EAAE;IAIhC;wEACoE;IACpE,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAIhD;;;;;gEAK4D;IAC5D,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS;IA+B7D,qFAAqF;IACrF,QAAQ,IAAI,eAAe;CAG5B"}
|
|
@@ -2,6 +2,7 @@ import { AliasResolver } from "./alias-resolver.js";
|
|
|
2
2
|
import { KERNEL_BUILTINS } from "./builtins.js";
|
|
3
3
|
import { DefinitionRegistry } from "./definition-registry.js";
|
|
4
4
|
import { computeSuggestKind, computeValidUserFacingKinds } from "./kind-suggest.js";
|
|
5
|
+
import { visitManifest as runVisitManifest } from "./manifest-visitor.js";
|
|
5
6
|
import { isRefEntry, isScopeEntry } from "./reference-field-map.js";
|
|
6
7
|
/**
|
|
7
8
|
* Accumulates type and alias knowledge for a running kernel or analysis session.
|
|
@@ -46,6 +47,20 @@ export class AnalysisRegistry {
|
|
|
46
47
|
}
|
|
47
48
|
}
|
|
48
49
|
}
|
|
50
|
+
/**
|
|
51
|
+
* Walks a manifest's annotation sites (refs, scopes, schema-from, CEL) via
|
|
52
|
+
* the shared manifest visitor, bound to this registry's definitions and
|
|
53
|
+
* aliases. The public seam for hosts (editor overview graph, tooling) that
|
|
54
|
+
* need the same site discovery the analyzer's own passes use, without
|
|
55
|
+
* reaching into the internal DefinitionRegistry.
|
|
56
|
+
*/
|
|
57
|
+
visitManifest(resources, visitor, opts) {
|
|
58
|
+
runVisitManifest(resources, this.defs, visitor, {
|
|
59
|
+
aliases: this.aliases,
|
|
60
|
+
aliasesByModule: this.aliasesByModule,
|
|
61
|
+
...opts,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
49
64
|
/**
|
|
50
65
|
* Returns the built-in kernel definitions. The underlying DefinitionRegistry already
|
|
51
66
|
* seeds these on construction; this method exposes them so callers (e.g. the kernel's
|
package/dist/analyzer.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analyzer.d.ts","sourceRoot":"","sources":["../src/analyzer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAsB,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAIzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAGL,KAAK,WAAW,EACjB,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"analyzer.d.ts","sourceRoot":"","sources":["../src/analyzer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAsB,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAIzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAGL,KAAK,WAAW,EACjB,MAAM,sBAAsB,CAAC;AAiB9B,OAAO,EAAsB,KAAK,kBAAkB,EAAE,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AAuhB/F,MAAM,WAAW,qBAAqB;IACpC,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAc;gBAEzB,OAAO,GAAE,qBAA0B;IAI/C;;;;;;;;;;;;;;OAcG;IACH,OAAO,CACL,SAAS,EAAE,gBAAgB,EAAE,EAC7B,OAAO,CAAC,EAAE,eAAe,EACzB,QAAQ,CAAC,EAAE,gBAAgB,GAC1B,kBAAkB,EAAE;IAqlBvB,aAAa,CACX,SAAS,EAAE,gBAAgB,EAAE,EAC7B,OAAO,CAAC,EAAE,eAAe,EACzB,QAAQ,CAAC,EAAE,gBAAgB,GAC1B,kBAAkB,EAAE;IAMvB,SAAS,CAAC,SAAS,EAAE,gBAAgB,EAAE,EAAE,QAAQ,EAAE,gBAAgB,GAAG,gBAAgB,EAAE;IAexF,OAAO,CACL,SAAS,EAAE,gBAAgB,EAAE,EAC7B,QAAQ,EAAE,gBAAgB,GACzB;QAAE,WAAW,EAAE,kBAAkB,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;QAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE;CAsB5F"}
|
package/dist/analyzer.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { defaultRegistry,
|
|
1
|
+
import { defaultRegistry, isTaggedSentinel } from "@telorun/templating";
|
|
2
2
|
import { AliasResolver } from "./alias-resolver.js";
|
|
3
3
|
import { buildCelEnvironment, buildTypedCelEnvironment, } from "./cel-environment.js";
|
|
4
4
|
import { DefinitionRegistry } from "./definition-registry.js";
|
|
5
5
|
import { buildDependencyGraph, formatCycle } from "./dependency-graph.js";
|
|
6
6
|
import { buildKernelGlobalsSchema, mergeKernelGlobalsIntoContext } from "./kernel-globals.js";
|
|
7
7
|
import { computeSuggestKind } from "./kind-suggest.js";
|
|
8
|
+
import { visitManifest } from "./manifest-visitor.js";
|
|
8
9
|
import { isModuleKind } from "./module-kinds.js";
|
|
9
10
|
import { normalizeInlineResources } from "./normalize-inline-resources.js";
|
|
10
11
|
import { REF_VALIDATION_SKIP_KINDS } from "./system-kinds.js";
|
|
@@ -12,11 +13,12 @@ import { resolveRefSentinels } from "./resolve-ref-sentinels.js";
|
|
|
12
13
|
import { rewriteSyntheticOrigins } from "./rewrite-synthetic-origins.js";
|
|
13
14
|
import { celTypeSatisfiesJsonSchema, substituteCelFields, validateAgainstSchema, } from "./schema-compat.js";
|
|
14
15
|
import { DiagnosticSeverity } from "./types.js";
|
|
15
|
-
import { getManifestItem, pathMatchesScope, resolveContextAnnotations, resolveTypeFieldToSchema, } from "./validate-cel-context.js";
|
|
16
|
+
import { extractContextsFromSchema, getManifestItem, pathMatchesScope, resolveContextAnnotations, resolveTypeFieldToSchema, } from "./validate-cel-context.js";
|
|
16
17
|
import { validateExtends } from "./validate-extends.js";
|
|
17
18
|
import { validateNestedInlineResources } from "./validate-nested-inline.js";
|
|
18
19
|
import { validateProviderCoherence } from "./validate-provider-coherence.js";
|
|
19
20
|
import { validateReferences } from "./validate-references.js";
|
|
21
|
+
import { validateUnusedDeclarations } from "./validate-unused-declarations.js";
|
|
20
22
|
import { validateThrowsCoverage } from "./validate-throws-coverage.js";
|
|
21
23
|
const SELF_PREFIX = "Self.";
|
|
22
24
|
/**
|
|
@@ -142,44 +144,6 @@ function manifestRootForResolver(m, defs, aliases, allManifests) {
|
|
|
142
144
|
...(inputs ? { inputType: inputs } : {}),
|
|
143
145
|
};
|
|
144
146
|
}
|
|
145
|
-
/**
|
|
146
|
-
* Walk a JSON Schema tree and collect all `x-telo-context` annotations,
|
|
147
|
-
* returning them as `{ scope, schema }` pairs using JSONPath-style scopes —
|
|
148
|
-
* the same format the analyzer uses for CEL context validation.
|
|
149
|
-
*
|
|
150
|
-
* Result is sorted by scope specificity (longer scope first) so that the
|
|
151
|
-
* per-expression resolver's first-match-wins logic picks the most-specific
|
|
152
|
-
* context. Without this, a broader ancestor scope (e.g. `$.resources[*]`)
|
|
153
|
-
* could shadow a narrower descendant scope whose activation differs.
|
|
154
|
-
*/
|
|
155
|
-
function extractContextsFromSchema(schema, path = "$") {
|
|
156
|
-
const all = collectContexts(schema, path);
|
|
157
|
-
return all.sort((a, b) => b.scope.length - a.scope.length);
|
|
158
|
-
}
|
|
159
|
-
function collectContexts(schema, path) {
|
|
160
|
-
if (!schema || typeof schema !== "object")
|
|
161
|
-
return [];
|
|
162
|
-
const results = [];
|
|
163
|
-
if (schema["x-telo-context"]) {
|
|
164
|
-
results.push({ scope: path, schema: schema["x-telo-context"] });
|
|
165
|
-
}
|
|
166
|
-
if (schema.properties) {
|
|
167
|
-
for (const [key, value] of Object.entries(schema.properties)) {
|
|
168
|
-
results.push(...collectContexts(value, `${path}.${key}`));
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
if (schema.items && typeof schema.items === "object") {
|
|
172
|
-
results.push(...collectContexts(schema.items, `${path}[*]`));
|
|
173
|
-
}
|
|
174
|
-
for (const key of ["oneOf", "anyOf", "allOf"]) {
|
|
175
|
-
if (Array.isArray(schema[key])) {
|
|
176
|
-
for (const subschema of schema[key]) {
|
|
177
|
-
results.push(...collectContexts(subschema, path));
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
return results;
|
|
182
|
-
}
|
|
183
147
|
/** Resolve a local `$ref` (only `#/$defs/<name>` form) against the root schema.
|
|
184
148
|
* Non-refs and unresolved refs pass through unchanged. */
|
|
185
149
|
function resolveLocalRef(schema, root) {
|
|
@@ -343,23 +307,101 @@ function buildStepContextSchema(manifest, defSchema, allManifests, defs, aliases
|
|
|
343
307
|
}
|
|
344
308
|
return undefined;
|
|
345
309
|
}
|
|
310
|
+
/**
|
|
311
|
+
* Collect every field annotated with `x-telo-error-context` anywhere in a
|
|
312
|
+
* definition schema (resolving local `$ref`s into `$defs`, cycle-safe), mapping
|
|
313
|
+
* the annotated field name to its declared error-shape schema. The field name
|
|
314
|
+
* is matched against CEL paths so the context applies at any nesting depth under
|
|
315
|
+
* that field — e.g. `error` inside a `catch:` nested inside another `try:`. No
|
|
316
|
+
* specific field name (or `Run.Sequence`) is hardcoded; any composer that tags
|
|
317
|
+
* its error-bearing branch fields opts in the same way.
|
|
318
|
+
*/
|
|
319
|
+
function collectErrorContextScopes(defSchema) {
|
|
320
|
+
const out = new Map();
|
|
321
|
+
if (!defSchema || typeof defSchema !== "object")
|
|
322
|
+
return out;
|
|
323
|
+
const seen = new Set();
|
|
324
|
+
const walk = (schema) => {
|
|
325
|
+
if (!schema || typeof schema !== "object" || seen.has(schema))
|
|
326
|
+
return;
|
|
327
|
+
seen.add(schema);
|
|
328
|
+
const props = schema.properties;
|
|
329
|
+
if (props) {
|
|
330
|
+
for (const [fieldName, fieldSchema] of Object.entries(props)) {
|
|
331
|
+
if (fieldSchema && typeof fieldSchema === "object") {
|
|
332
|
+
const errCtx = fieldSchema["x-telo-error-context"];
|
|
333
|
+
if (errCtx && typeof errCtx === "object" && !out.has(fieldName)) {
|
|
334
|
+
out.set(fieldName, errCtx);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
walk(resolveLocalRef(fieldSchema, defSchema));
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
if (schema.items)
|
|
341
|
+
walk(resolveLocalRef(schema.items, defSchema));
|
|
342
|
+
for (const key of ["oneOf", "anyOf", "allOf"]) {
|
|
343
|
+
const arr = schema[key];
|
|
344
|
+
if (Array.isArray(arr))
|
|
345
|
+
for (const sub of arr)
|
|
346
|
+
walk(resolveLocalRef(sub, defSchema));
|
|
347
|
+
}
|
|
348
|
+
if (schema.$defs && typeof schema.$defs === "object") {
|
|
349
|
+
for (const sub of Object.values(schema.$defs)) {
|
|
350
|
+
walk(sub);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
};
|
|
354
|
+
walk(defSchema);
|
|
355
|
+
return out;
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* Return the error-context schema for a CEL `path` when the path lies within
|
|
359
|
+
* (any depth under) one of the error-bearing fields, else undefined. A path is
|
|
360
|
+
* "within" field `f` when it contains a segment `f[<index>]`. When multiple
|
|
361
|
+
* error-bearing fields match (e.g. a `finally` nested inside a `catch`), the
|
|
362
|
+
* deepest — the one whose segment appears latest in the path — wins, so the
|
|
363
|
+
* innermost branch's schema governs.
|
|
364
|
+
*/
|
|
365
|
+
function errorContextForPath(path, scopes) {
|
|
366
|
+
let best;
|
|
367
|
+
for (const [fieldName, schema] of scopes) {
|
|
368
|
+
const escaped = fieldName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
369
|
+
for (const match of path.matchAll(new RegExp(`(^|\\.)${escaped}\\[\\d+\\]`, "g"))) {
|
|
370
|
+
if (best === undefined || match.index > best.index) {
|
|
371
|
+
best = { index: match.index, schema };
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
return best?.schema;
|
|
376
|
+
}
|
|
346
377
|
const CEL_PURE_RE = /^\s*\$\{\{[^}]*\}\}\s*$/;
|
|
347
378
|
const CEL_EXPR_RE = /\$\{\{\s*([^}]+?)\s*\}\}/;
|
|
348
379
|
/** Recursively walk `data`+`schema` together, type-checking every pure CEL template
|
|
349
380
|
* string via `env.check()`. Returns `SchemaIssue[]` for any type mismatches found. */
|
|
350
|
-
function collectCelTypeIssues(data, schema, path, definition, manifest, baseTypedEnv, rootEnv) {
|
|
381
|
+
function collectCelTypeIssues(data, schema, path, definition, manifest, baseTypedEnv, rootEnv, rootModuleManifest) {
|
|
351
382
|
const issues = [];
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
383
|
+
// A pure CEL value type-checks the same regardless of surface form: a
|
|
384
|
+
// `${{ … }}` string and a `!cel`-tagged sentinel must behave identically.
|
|
385
|
+
let celExpr;
|
|
386
|
+
if (isTaggedSentinel(data)) {
|
|
387
|
+
// Non-CEL engines (e.g. `!literal`) are analyzed by their own engine pass.
|
|
388
|
+
if (data.engine !== "cel")
|
|
389
|
+
return issues;
|
|
390
|
+
celExpr = data.source;
|
|
391
|
+
}
|
|
392
|
+
else if (typeof data === "string" && CEL_PURE_RE.test(data)) {
|
|
393
|
+
celExpr = data.match(CEL_EXPR_RE)?.[1]?.trim();
|
|
394
|
+
}
|
|
395
|
+
if (celExpr !== undefined) {
|
|
396
|
+
{
|
|
397
|
+
const expr = celExpr;
|
|
356
398
|
// Merge x-telo-context variables for this path if applicable
|
|
357
399
|
let typedEnv = baseTypedEnv;
|
|
358
400
|
if (definition.schema) {
|
|
359
401
|
for (const ctx of extractContextsFromSchema(definition.schema)) {
|
|
360
402
|
if (!pathMatchesScope(path, ctx.scope))
|
|
361
403
|
continue;
|
|
362
|
-
typedEnv = buildTypedCelEnvironment(rootEnv, manifest, ctx.schema);
|
|
404
|
+
typedEnv = buildTypedCelEnvironment(rootEnv, manifest, ctx.schema, rootModuleManifest);
|
|
363
405
|
break;
|
|
364
406
|
}
|
|
365
407
|
}
|
|
@@ -382,8 +424,9 @@ function collectCelTypeIssues(data, schema, path, definition, manifest, baseType
|
|
|
382
424
|
else if (checkResult?.valid && checkResult.type && schema) {
|
|
383
425
|
const celType = checkResult.type.split("<")[0];
|
|
384
426
|
if (!celTypeSatisfiesJsonSchema(celType, schema)) {
|
|
427
|
+
const expected = schema["x-telo-type"] ?? schema.type ?? "unknown";
|
|
385
428
|
issues.push({
|
|
386
|
-
message: `CEL returns '${checkResult.type}' but field expects '${
|
|
429
|
+
message: `CEL returns '${checkResult.type}' but field expects '${expected}'`,
|
|
387
430
|
path,
|
|
388
431
|
});
|
|
389
432
|
}
|
|
@@ -394,13 +437,13 @@ function collectCelTypeIssues(data, schema, path, definition, manifest, baseType
|
|
|
394
437
|
if (Array.isArray(data)) {
|
|
395
438
|
const itemSchema = (schema.items ?? {});
|
|
396
439
|
for (let i = 0; i < data.length; i++) {
|
|
397
|
-
issues.push(...collectCelTypeIssues(data[i], itemSchema, `${path}[${i}]`, definition, manifest, baseTypedEnv, rootEnv));
|
|
440
|
+
issues.push(...collectCelTypeIssues(data[i], itemSchema, `${path}[${i}]`, definition, manifest, baseTypedEnv, rootEnv, rootModuleManifest));
|
|
398
441
|
}
|
|
399
442
|
}
|
|
400
443
|
else if (data !== null && typeof data === "object") {
|
|
401
444
|
const props = (schema.properties ?? {});
|
|
402
445
|
for (const [k, v] of Object.entries(data)) {
|
|
403
|
-
issues.push(...collectCelTypeIssues(v, (props[k] ?? {}), path ? `${path}.${k}` : k, definition, manifest, baseTypedEnv, rootEnv));
|
|
446
|
+
issues.push(...collectCelTypeIssues(v, (props[k] ?? {}), path ? `${path}.${k}` : k, definition, manifest, baseTypedEnv, rootEnv, rootModuleManifest));
|
|
404
447
|
}
|
|
405
448
|
}
|
|
406
449
|
return issues;
|
|
@@ -625,6 +668,11 @@ export class StaticAnalyzer {
|
|
|
625
668
|
// Build typed kernel globals schema so x-telo-context chain validation
|
|
626
669
|
// recognises variables, secrets, resources, env automatically
|
|
627
670
|
const kernelGlobals = buildKernelGlobalsSchema(allManifests);
|
|
671
|
+
// The module doc (Application/Library) carries the Application-only `ports`
|
|
672
|
+
// namespace; threaded into per-resource CEL typing so `${{ ports.X }}`
|
|
673
|
+
// resolves its nominal brand cross-doc.
|
|
674
|
+
const moduleManifest = allManifests.find((mm) => mm.kind === "Telo.Application") ??
|
|
675
|
+
allManifests.find((mm) => mm.kind === "Telo.Library");
|
|
628
676
|
// Validate each non-definition, non-system resource
|
|
629
677
|
for (const m of allManifests) {
|
|
630
678
|
const filePath = m.metadata?.source;
|
|
@@ -678,8 +726,8 @@ export class StaticAnalyzer {
|
|
|
678
726
|
}
|
|
679
727
|
: definition.schema;
|
|
680
728
|
// Phase 1: CEL type checking — walk data+schema together, check env.check() return types
|
|
681
|
-
const baseTypedEnv = buildTypedCelEnvironment(this.celEnv, m);
|
|
682
|
-
const celIssues = collectCelTypeIssues(m, schema, "", definition, m, baseTypedEnv, this.celEnv);
|
|
729
|
+
const baseTypedEnv = buildTypedCelEnvironment(this.celEnv, m, undefined, moduleManifest);
|
|
730
|
+
const celIssues = collectCelTypeIssues(m, schema, "", definition, m, baseTypedEnv, this.celEnv, moduleManifest);
|
|
683
731
|
// Phase 2+3: AJV on substituted data — CEL fields replaced with typed placeholders
|
|
684
732
|
const ajvIssues = validateAgainstSchema(substituteCelFields(m, schema), schema);
|
|
685
733
|
const issues = [...celIssues, ...ajvIssues];
|
|
@@ -791,42 +839,54 @@ export class StaticAnalyzer {
|
|
|
791
839
|
}
|
|
792
840
|
}
|
|
793
841
|
}
|
|
794
|
-
// Validate CEL syntax and context variable access in all manifests
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
842
|
+
// Validate CEL syntax and context variable access in all manifests. The
|
|
843
|
+
// walker discovers every compiled CEL node by scanning the value tree and
|
|
844
|
+
// hands back the `x-telo-context` schema matched at the enclosing path; the
|
|
845
|
+
// per-path resolution (step context, kernel-globals merge, x-telo-context-*
|
|
846
|
+
// annotation resolution) stays here because it depends on analyzer-internal
|
|
847
|
+
// state (definitions, aliases, the typed CEL env).
|
|
848
|
+
// Per-resource state computed at enter and read by that resource's CEL
|
|
849
|
+
// sites. The manifest / resource / filePath come straight off each CelSite's
|
|
850
|
+
// `source` (no need to capture them); only the derived step / invocation
|
|
851
|
+
// context — which require analyzer state to build — are stashed here.
|
|
852
|
+
let celStepContextSchema;
|
|
853
|
+
let celInvocationContext;
|
|
854
|
+
let celErrorScopes = new Map();
|
|
855
|
+
visitManifest(allManifests, defs, {
|
|
856
|
+
onResourceEnter: (e) => {
|
|
857
|
+
const m = e.source;
|
|
858
|
+
celInvocationContext = m.metadata?.xTeloInvocationContext;
|
|
859
|
+
celStepContextSchema = e.definition?.schema
|
|
860
|
+
? buildStepContextSchema(m, e.definition.schema, allManifests, defs, aliases)
|
|
861
|
+
: undefined;
|
|
862
|
+
celErrorScopes = collectErrorContextScopes(e.definition?.schema);
|
|
863
|
+
},
|
|
864
|
+
onCel: (e) => {
|
|
865
|
+
const m = e.source;
|
|
866
|
+
const resource = { kind: m.kind, name: m.metadata?.name };
|
|
867
|
+
const filePath = m.metadata?.source;
|
|
868
|
+
const { expr, path, engineName, matchedScope } = e;
|
|
869
|
+
let matchedContext = e.contextSchema ?? celInvocationContext;
|
|
870
|
+
if (celStepContextSchema) {
|
|
871
|
+
const base = matchedContext ?? { type: "object", properties: {}, additionalProperties: true };
|
|
872
|
+
matchedContext = {
|
|
873
|
+
...base,
|
|
874
|
+
properties: {
|
|
875
|
+
...(base.properties ?? {}),
|
|
876
|
+
steps: celStepContextSchema,
|
|
877
|
+
},
|
|
878
|
+
};
|
|
820
879
|
}
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
880
|
+
// `error` is only in scope inside an error-bearing branch (e.g. a
|
|
881
|
+
// `catch:` / `finally:`), so it's merged per-path, not resource-wide.
|
|
882
|
+
const errorSchema = celErrorScopes.size > 0 ? errorContextForPath(path, celErrorScopes) : undefined;
|
|
883
|
+
if (errorSchema) {
|
|
824
884
|
const base = matchedContext ?? { type: "object", properties: {}, additionalProperties: true };
|
|
825
885
|
matchedContext = {
|
|
826
886
|
...base,
|
|
827
887
|
properties: {
|
|
828
888
|
...(base.properties ?? {}),
|
|
829
|
-
|
|
889
|
+
error: errorSchema,
|
|
830
890
|
},
|
|
831
891
|
};
|
|
832
892
|
}
|
|
@@ -877,6 +937,15 @@ export class StaticAnalyzer {
|
|
|
877
937
|
data: { resource, filePath, path },
|
|
878
938
|
});
|
|
879
939
|
}
|
|
940
|
+
else if (f.code === "CEL_NULLABLE_ACCESS") {
|
|
941
|
+
diagnostics.push({
|
|
942
|
+
severity: DiagnosticSeverity.Error,
|
|
943
|
+
code: "CEL_NULLABLE_ACCESS",
|
|
944
|
+
source: SOURCE,
|
|
945
|
+
message: `${m.kind}/${resource.name}: CEL at '${path}': ${f.message}`,
|
|
946
|
+
data: { resource, filePath, path },
|
|
947
|
+
});
|
|
948
|
+
}
|
|
880
949
|
else {
|
|
881
950
|
// Unknown code from a future engine — pass the message through,
|
|
882
951
|
// tagged with a generic ENGINE_DIAGNOSTIC code so downstream
|
|
@@ -890,8 +959,8 @@ export class StaticAnalyzer {
|
|
|
890
959
|
});
|
|
891
960
|
}
|
|
892
961
|
}
|
|
893
|
-
}
|
|
894
|
-
}
|
|
962
|
+
},
|
|
963
|
+
}, { aliases });
|
|
895
964
|
// Validate resource references (Phase 3)
|
|
896
965
|
diagnostics.push(...validateReferences(allManifests, { aliases, definitions: defs, aliasesByModule }));
|
|
897
966
|
// Validate `extends` fields and flag legacy `capability: <UserAbstract>` overload.
|
|
@@ -900,6 +969,8 @@ export class StaticAnalyzer {
|
|
|
900
969
|
diagnostics.push(...validateProviderCoherence(allManifests, defs, aliases));
|
|
901
970
|
// Validate throws: declarations and catches: coverage (rules 1, 2, 4, 7)
|
|
902
971
|
diagnostics.push(...validateThrowsCoverage(allManifests, defs, aliases, this.celEnv));
|
|
972
|
+
// Warn about declared variables / secrets / ports that no CEL references.
|
|
973
|
+
diagnostics.push(...validateUnusedDeclarations(allManifests, this.celEnv));
|
|
903
974
|
// Reroute diagnostics on synthetic (inline-extracted) resources back to
|
|
904
975
|
// the chain root so position-index lookups land on the parent doc.
|
|
905
976
|
return rewriteSyntheticOrigins(diagnostics, allManifests);
|
package/dist/builtins.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builtins.d.ts","sourceRoot":"","sources":["../src/builtins.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAEvD,eAAO,MAAM,eAAe,EAAE,kBAAkB,
|
|
1
|
+
{"version":3,"file":"builtins.d.ts","sourceRoot":"","sources":["../src/builtins.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAEvD,eAAO,MAAM,eAAe,EAAE,kBAAkB,EAsZ/C,CAAC"}
|
package/dist/builtins.js
CHANGED
|
@@ -232,6 +232,66 @@ export const KERNEL_BUILTINS = [
|
|
|
232
232
|
},
|
|
233
233
|
additionalProperties: true,
|
|
234
234
|
},
|
|
235
|
+
// Gated reference: run() a Runnable/Service only when the
|
|
236
|
+
// `when` CEL guard holds. Discriminated by the `ref` key. `ref`
|
|
237
|
+
// is a bare name or a resolved `!ref` (`{ kind, name }`).
|
|
238
|
+
{
|
|
239
|
+
type: "object",
|
|
240
|
+
required: ["ref"],
|
|
241
|
+
properties: {
|
|
242
|
+
ref: {
|
|
243
|
+
anyOf: [
|
|
244
|
+
{ type: "string", "x-telo-ref": "telo#Runnable" },
|
|
245
|
+
{ type: "string", "x-telo-ref": "telo#Service" },
|
|
246
|
+
{
|
|
247
|
+
type: "object",
|
|
248
|
+
required: ["kind", "name"],
|
|
249
|
+
properties: {
|
|
250
|
+
kind: { type: "string" },
|
|
251
|
+
name: { type: "string" },
|
|
252
|
+
},
|
|
253
|
+
additionalProperties: true,
|
|
254
|
+
},
|
|
255
|
+
],
|
|
256
|
+
},
|
|
257
|
+
when: { type: "string" },
|
|
258
|
+
},
|
|
259
|
+
additionalProperties: false,
|
|
260
|
+
},
|
|
261
|
+
// Inline flat invoke step: invoke an Invocable / Runnable on boot
|
|
262
|
+
// with an optional `name` (for steps.<name>.result plumbing),
|
|
263
|
+
// `when` guard, and `inputs`. Discriminated by the `invoke` key.
|
|
264
|
+
// Control flow (if/while/switch/try) is not available here —
|
|
265
|
+
// reach for Run.Sequence. `invoke` is ref-only and must resolve
|
|
266
|
+
// to a `{ kind, name }` reference (a `!ref` / `{kind,name}`):
|
|
267
|
+
// requiring `name` rejects an inline `{ kind }` definition (no
|
|
268
|
+
// name) at analysis instead of failing at boot with an undefined
|
|
269
|
+
// resource name. The Invocable/Runnable kind set mirrors
|
|
270
|
+
// Run.Sequence invoke steps.
|
|
271
|
+
{
|
|
272
|
+
type: "object",
|
|
273
|
+
required: ["invoke"],
|
|
274
|
+
properties: {
|
|
275
|
+
name: { type: "string" },
|
|
276
|
+
invoke: {
|
|
277
|
+
"x-telo-topology-role": "invoke",
|
|
278
|
+
type: "object",
|
|
279
|
+
required: ["kind", "name"],
|
|
280
|
+
properties: {
|
|
281
|
+
kind: { type: "string" },
|
|
282
|
+
name: { type: "string" },
|
|
283
|
+
},
|
|
284
|
+
additionalProperties: true,
|
|
285
|
+
anyOf: [
|
|
286
|
+
{ "x-telo-ref": "telo#Invocable" },
|
|
287
|
+
{ "x-telo-ref": "telo#Runnable" },
|
|
288
|
+
],
|
|
289
|
+
},
|
|
290
|
+
inputs: { type: "object", additionalProperties: true },
|
|
291
|
+
when: { type: "string" },
|
|
292
|
+
},
|
|
293
|
+
additionalProperties: false,
|
|
294
|
+
},
|
|
235
295
|
],
|
|
236
296
|
},
|
|
237
297
|
},
|
|
@@ -277,6 +337,31 @@ export const KERNEL_BUILTINS = [
|
|
|
277
337
|
},
|
|
278
338
|
},
|
|
279
339
|
},
|
|
340
|
+
// Inbound ports the Application listens on. A name-keyed map mirroring
|
|
341
|
+
// `variables`: each entry binds a host env var (`env:`) that supplies a
|
|
342
|
+
// port integer (implicitly typed `integer`, 1–65535), with an optional
|
|
343
|
+
// `default:` used when the env var is unset. `protocol:` (default `tcp`)
|
|
344
|
+
// selects the transport — the runner reads this list to know the
|
|
345
|
+
// exposed ports before launch, and the analyzer brands the resolved
|
|
346
|
+
// `ports.<name>` value (tcp → TcpPort, udp → UdpPort) for static wiring
|
|
347
|
+
// checks. Application-only. See kernel/nodejs/src/application-env.ts.
|
|
348
|
+
ports: {
|
|
349
|
+
type: "object",
|
|
350
|
+
additionalProperties: {
|
|
351
|
+
type: "object",
|
|
352
|
+
required: ["env"],
|
|
353
|
+
properties: {
|
|
354
|
+
env: { type: "string" },
|
|
355
|
+
protocol: {
|
|
356
|
+
type: "string",
|
|
357
|
+
enum: ["tcp", "udp"],
|
|
358
|
+
default: "tcp",
|
|
359
|
+
},
|
|
360
|
+
default: { type: "integer", minimum: 1, maximum: 65535 },
|
|
361
|
+
},
|
|
362
|
+
additionalProperties: false,
|
|
363
|
+
},
|
|
364
|
+
},
|
|
280
365
|
},
|
|
281
366
|
required: ["metadata"],
|
|
282
367
|
additionalProperties: false,
|
|
@@ -12,5 +12,5 @@ export type { CelHandlers } from "@telorun/templating";
|
|
|
12
12
|
*
|
|
13
13
|
* NOTE: The set of kernel globals registered here must match `KERNEL_GLOBAL_NAMES`
|
|
14
14
|
* in kernel-globals.ts, which is used for chain-access validation. */
|
|
15
|
-
export declare function buildTypedCelEnvironment(baseEnv: Environment, manifest: ResourceManifest, extraContextSchema?: Record<string, any> | null): Environment;
|
|
15
|
+
export declare function buildTypedCelEnvironment(baseEnv: Environment, manifest: ResourceManifest, extraContextSchema?: Record<string, any> | null, rootModuleManifest?: ResourceManifest): Environment;
|
|
16
16
|
//# sourceMappingURL=cel-environment.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cel-environment.d.ts","sourceRoot":"","sources":["../src/cel-environment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"cel-environment.d.ts","sourceRoot":"","sources":["../src/cel-environment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAUrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,YAAY,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAEvD;;;;;;;;;uEASuE;AACvE,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,WAAW,EACpB,QAAQ,EAAE,gBAAgB,EAC1B,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,EAI/C,kBAAkB,CAAC,EAAE,gBAAgB,GACpC,WAAW,CAuEb"}
|
package/dist/cel-environment.js
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import { jsonSchemaToCelType } from "./schema-compat.js";
|
|
1
|
+
import { jsonSchemaToCelType, VALUE_BRAND_BASE } from "./schema-compat.js";
|
|
2
|
+
/** Transport protocol on a `ports` entry → the nominal CEL brand its resolved
|
|
3
|
+
* value carries. Mirrors the `protocol` enum in the Application schema. */
|
|
4
|
+
const PORT_PROTOCOL_BRAND = {
|
|
5
|
+
tcp: "TcpPort",
|
|
6
|
+
udp: "UdpPort",
|
|
7
|
+
};
|
|
2
8
|
export { buildCelEnvironment } from "@telorun/templating";
|
|
3
9
|
/** Clone `baseEnv` and register typed variable declarations so that
|
|
4
10
|
* `env.check(expr)` can infer return types for expressions referencing known variables.
|
|
@@ -10,9 +16,21 @@ export { buildCelEnvironment } from "@telorun/templating";
|
|
|
10
16
|
*
|
|
11
17
|
* NOTE: The set of kernel globals registered here must match `KERNEL_GLOBAL_NAMES`
|
|
12
18
|
* in kernel-globals.ts, which is used for chain-access validation. */
|
|
13
|
-
export function buildTypedCelEnvironment(baseEnv, manifest, extraContextSchema
|
|
19
|
+
export function buildTypedCelEnvironment(baseEnv, manifest, extraContextSchema,
|
|
20
|
+
// The `ports` namespace is Application-only and lives on the module doc, not
|
|
21
|
+
// on the resource being analyzed. When validating a resource, the caller
|
|
22
|
+
// passes the module manifest here so `${{ ports.X }}` types cross-doc.
|
|
23
|
+
rootModuleManifest) {
|
|
14
24
|
try {
|
|
15
25
|
const env = baseEnv.clone();
|
|
26
|
+
// Register nominal value brands (TcpPort/UdpPort/…) on the *clone* so the
|
|
27
|
+
// type-checker can distinguish structurally-identical values. The base env
|
|
28
|
+
// (shared with the kernel runtime) is untouched — a branded value flows as
|
|
29
|
+
// a plain integer at runtime, so only static checking needs these. cel-js
|
|
30
|
+
// auto-generates a field-less wrapper class; no runtime constructor needed.
|
|
31
|
+
for (const brand of Object.keys(VALUE_BRAND_BASE)) {
|
|
32
|
+
env.registerType(brand, { fields: {} });
|
|
33
|
+
}
|
|
16
34
|
// Build typed ObjectSchema from manifest.variables if it looks like a schema map
|
|
17
35
|
const vars = manifest.variables;
|
|
18
36
|
if (vars !== null && typeof vars === "object" && !Array.isArray(vars)) {
|
|
@@ -31,6 +49,26 @@ export function buildTypedCelEnvironment(baseEnv, manifest, extraContextSchema)
|
|
|
31
49
|
else {
|
|
32
50
|
env.registerVariable("variables", "map");
|
|
33
51
|
}
|
|
52
|
+
// `ports` namespace: each entry types as the brand its `protocol` selects
|
|
53
|
+
// (tcp → TcpPort, udp → UdpPort), so `${{ ports.http }}` carries a nominal
|
|
54
|
+
// type that consuming fields can check against.
|
|
55
|
+
const portsManifest = (rootModuleManifest ?? manifest).ports;
|
|
56
|
+
if (portsManifest !== null && typeof portsManifest === "object" && !Array.isArray(portsManifest)) {
|
|
57
|
+
const portEntries = Object.entries(portsManifest).filter(([, v]) => v !== null && typeof v === "object" && !Array.isArray(v));
|
|
58
|
+
if (portEntries.length > 0) {
|
|
59
|
+
const schema = {};
|
|
60
|
+
for (const [k, v] of portEntries) {
|
|
61
|
+
schema[k] = PORT_PROTOCOL_BRAND[v.protocol ?? "tcp"] ?? "int";
|
|
62
|
+
}
|
|
63
|
+
env.registerVariable({ name: "ports", schema });
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
env.registerVariable("ports", "map");
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
env.registerVariable("ports", "map");
|
|
71
|
+
}
|
|
34
72
|
env.registerVariable("secrets", "map");
|
|
35
73
|
env.registerVariable("resources", "map");
|
|
36
74
|
env.registerVariable("env", "map");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dependency-graph.d.ts","sourceRoot":"","sources":["../src/dependency-graph.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAErD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAInE,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,eAAe;IAC9B;kDAC8C;IAC9C,KAAK,CAAC,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;IACpC;oFACgF;IAChF,KAAK,CAAC,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;CACrC;AAID;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,gBAAgB,EAAE,EAC7B,QAAQ,EAAE,kBAAkB,EAC5B,OAAO,CAAC,EAAE,aAAa,EACvB,eAAe,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,GAC3C,eAAe,
|
|
1
|
+
{"version":3,"file":"dependency-graph.d.ts","sourceRoot":"","sources":["../src/dependency-graph.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAErD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAInE,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,eAAe;IAC9B;kDAC8C;IAC9C,KAAK,CAAC,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;IACpC;oFACgF;IAChF,KAAK,CAAC,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;CACrC;AAID;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,gBAAgB,EAAE,EAC7B,QAAQ,EAAE,kBAAkB,EAC5B,OAAO,CAAC,EAAE,aAAa,EACvB,eAAe,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,GAC3C,eAAe,CAmGjB;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,aAAa,CAAC,YAAY,CAAC,GAAG,MAAM,CAOtE"}
|