@telorun/analyzer 0.66.0 → 0.68.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/analyzer.d.ts.map +1 -1
- package/dist/analyzer.js +60 -2
- package/dist/builtins.d.ts.map +1 -1
- package/dist/builtins.js +67 -16
- package/dist/cel-scope.d.ts +8 -0
- package/dist/cel-scope.d.ts.map +1 -1
- package/dist/cel-scope.js +66 -8
- package/dist/definition-registry.d.ts +17 -0
- package/dist/definition-registry.d.ts.map +1 -1
- package/dist/definition-registry.js +35 -0
- package/dist/dependency-graph.d.ts.map +1 -1
- package/dist/dependency-graph.js +65 -0
- package/dist/extends-resolution.d.ts +20 -0
- package/dist/extends-resolution.d.ts.map +1 -1
- package/dist/extends-resolution.js +29 -0
- package/dist/flatten-for-analyzer.d.ts +36 -0
- package/dist/flatten-for-analyzer.d.ts.map +1 -1
- package/dist/flatten-for-analyzer.js +103 -4
- package/dist/index.d.ts +8 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -4
- package/dist/inline-imports.d.ts.map +1 -1
- package/dist/inline-imports.js +1 -0
- package/dist/invocation-contract.d.ts +20 -0
- package/dist/invocation-contract.d.ts.map +1 -1
- package/dist/invocation-contract.js +74 -0
- package/dist/manifest-visitor.d.ts +4 -0
- package/dist/manifest-visitor.d.ts.map +1 -1
- package/dist/manifest-visitor.js +28 -0
- package/dist/precompile.d.ts.map +1 -1
- package/dist/precompile.js +8 -0
- package/dist/resolve-ref-sentinels.d.ts.map +1 -1
- package/dist/resolve-ref-sentinels.js +14 -1
- package/dist/resource-input.d.ts +75 -0
- package/dist/resource-input.d.ts.map +1 -0
- package/dist/resource-input.js +90 -0
- package/dist/schema-keywords.d.ts +16 -1
- package/dist/schema-keywords.d.ts.map +1 -1
- package/dist/schema-keywords.js +20 -0
- package/dist/schema-projection.d.ts +13 -0
- package/dist/schema-projection.d.ts.map +1 -1
- package/dist/schema-projection.js +7 -0
- package/dist/system-kinds.d.ts +7 -2
- package/dist/system-kinds.d.ts.map +1 -1
- package/dist/system-kinds.js +7 -2
- package/dist/telo-version.d.ts +1 -1
- package/dist/telo-version.js +1 -1
- package/dist/template-body.d.ts +50 -0
- package/dist/template-body.d.ts.map +1 -0
- package/dist/template-body.js +58 -0
- package/dist/validate-cel-context.d.ts.map +1 -1
- package/dist/validate-cel-context.js +68 -8
- package/dist/validate-extends.d.ts.map +1 -1
- package/dist/validate-extends.js +42 -1
- package/dist/validate-identifier-names.d.ts.map +1 -1
- package/dist/validate-identifier-names.js +17 -2
- package/dist/validate-references.d.ts +17 -0
- package/dist/validate-references.d.ts.map +1 -1
- package/dist/validate-references.js +68 -16
- package/dist/validate-resource-inputs.d.ts +35 -0
- package/dist/validate-resource-inputs.d.ts.map +1 -0
- package/dist/validate-resource-inputs.js +319 -0
- package/dist/validate-sensitive-slots.d.ts +28 -0
- package/dist/validate-sensitive-slots.d.ts.map +1 -0
- package/dist/validate-sensitive-slots.js +75 -0
- package/dist/validate-template-dispatch.d.ts +27 -0
- package/dist/validate-template-dispatch.d.ts.map +1 -0
- package/dist/validate-template-dispatch.js +95 -0
- package/dist/value-type-keyword.d.ts +1 -1
- package/dist/value-type-keyword.d.ts.map +1 -1
- package/dist/value-type-keyword.js +1 -0
- package/package.json +3 -3
- package/src/analyzer.ts +71 -2
- package/src/builtins.ts +69 -16
- package/src/cel-scope.ts +90 -14
- package/src/definition-registry.ts +36 -0
- package/src/dependency-graph.ts +66 -0
- package/src/extends-resolution.ts +33 -0
- package/src/flatten-for-analyzer.ts +116 -3
- package/src/index.ts +16 -0
- package/src/inline-imports.ts +1 -0
- package/src/invocation-contract.ts +71 -0
- package/src/manifest-visitor.ts +33 -0
- package/src/precompile.ts +8 -0
- package/src/resolve-ref-sentinels.ts +12 -1
- package/src/resource-input.ts +132 -0
- package/src/schema-keywords.ts +33 -1
- package/src/schema-projection.ts +19 -0
- package/src/system-kinds.ts +7 -2
- package/src/telo-version.ts +1 -1
- package/src/template-body.ts +104 -0
- package/src/validate-cel-context.ts +67 -7
- package/src/validate-extends.ts +51 -1
- package/src/validate-identifier-names.ts +18 -3
- package/src/validate-references.ts +70 -14
- package/src/validate-resource-inputs.ts +367 -0
- package/src/validate-sensitive-slots.ts +109 -0
- package/src/validate-template-dispatch.ts +99 -0
- package/src/value-type-keyword.ts +1 -0
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;AAiBzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAKL,KAAK,WAAW,EACjB,MAAM,sBAAsB,CAAC;AA8B9B,OAAO,EAAmB,KAAK,eAAe,EAAE,MAAM,gCAAgC,CAAC;AAWvF,OAAO,EAAE,qBAAqB,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACzF,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"analyzer.d.ts","sourceRoot":"","sources":["../src/analyzer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAsB,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAiBzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAKL,KAAK,WAAW,EACjB,MAAM,sBAAsB,CAAC;AA8B9B,OAAO,EAAmB,KAAK,eAAe,EAAE,MAAM,gCAAgC,CAAC;AAWvF,OAAO,EAAE,qBAAqB,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACzF,OAAO,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AA4DjE,OAAO,EAAsB,KAAK,kBAAkB,EAAE,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AAkG/F;0CAC0C;AAC1C,eAAO,MAAM,eAAe,GAAI,OAAO;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,KAAG,OACT,CAAC;AAErD;8EAC8E;AAC9E,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGhD;AAqUD,8DAA8D;AAC9D,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CACtC;AA6DD,MAAM,WAAW,qBAAqB;IACpC,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B;AAkFD,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,EAC3B,eAAe,CAAC,EAAE,eAAe,GAChC,kBAAkB,EAAE;IAq8DvB,aAAa,CACX,SAAS,EAAE,gBAAgB,EAAE,EAC7B,OAAO,CAAC,EAAE,eAAe,EACzB,QAAQ,CAAC,EAAE,gBAAgB,EAC3B,eAAe,CAAC,EAAE,eAAe,GAChC,kBAAkB,EAAE;IAMvB,SAAS,CACP,SAAS,EAAE,gBAAgB,EAAE,EAC7B,QAAQ,EAAE,gBAAgB,EAI1B,kBAAkB,CAAC,EAAE,gBAAgB,EAAE,GACtC,gBAAgB,EAAE;IAyBrB,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
|
@@ -37,6 +37,7 @@ import { analyzerPeerBinder, analyzerPeersTarget } from "./peer-binding.js";
|
|
|
37
37
|
import { describeProjectionFailure, manifestListScope, resolveSchemaProjections, } from "./schema-projection.js";
|
|
38
38
|
import { validateDynamicSelectors, validateRefSlotDeclarations, } from "./validate-ref-slots.js";
|
|
39
39
|
import { validateValueTypeSlots, } from "./validate-value-type-slots.js";
|
|
40
|
+
import { validateSensitiveSlots, } from "./validate-sensitive-slots.js";
|
|
40
41
|
import { resolveSchemaTypeRefs } from "./resolve-schema-type-refs.js";
|
|
41
42
|
import { validateSchemaTypeRefs } from "./validate-schema-type-refs.js";
|
|
42
43
|
import { rewriteSyntheticOrigins } from "./rewrite-synthetic-origins.js";
|
|
@@ -59,8 +60,11 @@ import { validateInvocationContract } from "./validate-invocation-contract.js";
|
|
|
59
60
|
import { collectRefInputIssues, collectStepInputIssues } from "./validate-step-inputs.js";
|
|
60
61
|
import { validateNestedInlineResources } from "./validate-nested-inline.js";
|
|
61
62
|
import { validateProviderCoherence } from "./validate-provider-coherence.js";
|
|
62
|
-
import { validateReferences } from "./validate-references.js";
|
|
63
|
+
import { kindSatisfies, validateReferences } from "./validate-references.js";
|
|
63
64
|
import { validateReferenceForms } from "./validate-reference-forms.js";
|
|
65
|
+
import { isInjectedDeclaration } from "./resource-input.js";
|
|
66
|
+
import { validateResourceInputs } from "./validate-resource-inputs.js";
|
|
67
|
+
import { validateTemplateDispatch } from "./validate-template-dispatch.js";
|
|
64
68
|
import { validateUnusedDeclarations } from "./validate-unused-declarations.js";
|
|
65
69
|
import { validateThrowsCoverage } from "./validate-throws-coverage.js";
|
|
66
70
|
import { readStepSlot } from "./step-slot.js";
|
|
@@ -797,10 +801,16 @@ export class StaticAnalyzer {
|
|
|
797
801
|
// definition's `schema:` does. Same scoping as every other schema issue —
|
|
798
802
|
// the entry's own modules, since a dependency is not the consumer's to fix.
|
|
799
803
|
const valueTypeSlotIssues = [];
|
|
804
|
+
// `x-telo-sensitive` rides the same walk and the same scoping. It is read by
|
|
805
|
+
// ONE consumer — the kernel, off a bound contract — so an occurrence outside
|
|
806
|
+
// `inputType` / `outputType` is inert; for a security control, inert-and-
|
|
807
|
+
// silent is the failure worth reporting.
|
|
808
|
+
const sensitiveSlotIssues = [];
|
|
800
809
|
for (const m of manifests) {
|
|
801
810
|
const declaringModule = m.metadata?.module;
|
|
802
811
|
if (!declaringModule || rootModules.has(declaringModule)) {
|
|
803
812
|
valueTypeSlotIssues.push(...validateValueTypeSlots(m));
|
|
813
|
+
sensitiveSlotIssues.push(...validateSensitiveSlots(m));
|
|
804
814
|
}
|
|
805
815
|
}
|
|
806
816
|
for (const m of manifests) {
|
|
@@ -1017,6 +1027,22 @@ export class StaticAnalyzer {
|
|
|
1017
1027
|
},
|
|
1018
1028
|
});
|
|
1019
1029
|
}
|
|
1030
|
+
for (const issue of sensitiveSlotIssues) {
|
|
1031
|
+
diagnostics.push({
|
|
1032
|
+
severity: DiagnosticSeverity.Error,
|
|
1033
|
+
code: issue.code,
|
|
1034
|
+
source: SOURCE,
|
|
1035
|
+
message: issue.message,
|
|
1036
|
+
data: {
|
|
1037
|
+
resource: {
|
|
1038
|
+
kind: issue.manifest.kind,
|
|
1039
|
+
name: issue.manifest.metadata?.name,
|
|
1040
|
+
},
|
|
1041
|
+
filePath: issue.manifest.metadata?.source,
|
|
1042
|
+
path: issue.path,
|
|
1043
|
+
},
|
|
1044
|
+
});
|
|
1045
|
+
}
|
|
1020
1046
|
// Same split for the two zone annotations. Unreadable ones fail in
|
|
1021
1047
|
// OPPOSITE directions — a dropped requirement is silently unenforced, a
|
|
1022
1048
|
// dropped provision invents failures — so neither can be left to
|
|
@@ -1399,6 +1425,17 @@ export class StaticAnalyzer {
|
|
|
1399
1425
|
const runReachable = reportsObservedState
|
|
1400
1426
|
? collectRunReachableNames(getCallGraph())
|
|
1401
1427
|
: new Set();
|
|
1428
|
+
// "Nothing starts this" is DECLARATION-derived, and a library does not
|
|
1429
|
+
// declare its injected inputs — whether the application starts the instance
|
|
1430
|
+
// it hands down is answerable only where that instance is declared. Inside
|
|
1431
|
+
// the library the question has no answer, so the name is treated as
|
|
1432
|
+
// reachable rather than reported on a `targets:` list the author cannot
|
|
1433
|
+
// write. The check still runs at the injection site, against the real
|
|
1434
|
+
// declaration.
|
|
1435
|
+
for (const m of allManifests) {
|
|
1436
|
+
if (isInjectedDeclaration(m))
|
|
1437
|
+
runReachable.add(m.metadata?.name);
|
|
1438
|
+
}
|
|
1402
1439
|
// Build typed kernel globals schema so x-telo-context chain validation
|
|
1403
1440
|
// recognises variables, secrets, resources, env automatically
|
|
1404
1441
|
const kernelGlobals = buildKernelGlobalsIndex(allManifests, observedState);
|
|
@@ -1511,6 +1548,15 @@ export class StaticAnalyzer {
|
|
|
1511
1548
|
if (m.metadata?.forwardedExport === true) {
|
|
1512
1549
|
continue;
|
|
1513
1550
|
}
|
|
1551
|
+
// A kind-only stand-in for a `resources:` entry is a DECLARATION, not an
|
|
1552
|
+
// instantiation: its kind is routinely an abstract and its configuration
|
|
1553
|
+
// is the importer's to supply, so validating it here would report a
|
|
1554
|
+
// non-instantiable kind and a page of missing required fields against a
|
|
1555
|
+
// block that is correct. Its kind is checked where it was written, by
|
|
1556
|
+
// `validate-resource-inputs`; it participates here only as a resolution
|
|
1557
|
+
// target and as a CEL type.
|
|
1558
|
+
if (isInjectedDeclaration(m))
|
|
1559
|
+
continue;
|
|
1514
1560
|
const resource = { kind: m.kind, name: m.metadata?.name };
|
|
1515
1561
|
// Resolve kind through alias if needed; direct lookup takes priority so that
|
|
1516
1562
|
// aliases whose name matches the module name (the common case) work without
|
|
@@ -1599,6 +1645,12 @@ export class StaticAnalyzer {
|
|
|
1599
1645
|
const projected = resolveSchemaProjections(schema, m, resourceProjectionScope, projectionFailures);
|
|
1600
1646
|
if (!ownModule || rootModules.has(ownModule)) {
|
|
1601
1647
|
for (const failure of projectionFailures) {
|
|
1648
|
+
// A projection through a library's own resource INPUT is
|
|
1649
|
+
// unanswerable here — the entries belong to the declaration the
|
|
1650
|
+
// importer supplies — so it is not a defect in the block that named
|
|
1651
|
+
// it. The check runs at the injection site instead.
|
|
1652
|
+
if (failure.reason === "injected")
|
|
1653
|
+
continue;
|
|
1602
1654
|
diagnostics.push({
|
|
1603
1655
|
severity: DiagnosticSeverity.Error,
|
|
1604
1656
|
code: "SCHEMA_PROJECTION_FROM_UNRESOLVED",
|
|
@@ -2199,7 +2251,7 @@ export class StaticAnalyzer {
|
|
|
2199
2251
|
}
|
|
2200
2252
|
}
|
|
2201
2253
|
},
|
|
2202
|
-
}, { aliases });
|
|
2254
|
+
}, { aliases, aliasesByModule, rootModules });
|
|
2203
2255
|
// The two halves of "does this expression fit the slot it flows into" meet
|
|
2204
2256
|
// here: the engine resolved the expression's type during the walk above,
|
|
2205
2257
|
// and the schema walk recorded the slot. An expression that failed to check
|
|
@@ -2269,6 +2321,12 @@ export class StaticAnalyzer {
|
|
|
2269
2321
|
diagnostics.push(...validateThrowsCoverage(allManifests, defs, aliases, this.celEnv, aliasesByModule, rootModules));
|
|
2270
2322
|
// Warn about declared variables / secrets / ports that no CEL references.
|
|
2271
2323
|
diagnostics.push(...validateUnusedDeclarations(allManifests, this.celEnv));
|
|
2324
|
+
// A `!ref` at a definition's dispatch slot must name a sibling `resources:`
|
|
2325
|
+
// entry — the slot no reference pass reaches, so the tag would otherwise
|
|
2326
|
+
// advertise a resolution nothing performs.
|
|
2327
|
+
diagnostics.push(...validateTemplateDispatch(allManifests, rootModules));
|
|
2328
|
+
// A library's declared resource inputs, and every import that supplies them.
|
|
2329
|
+
diagnostics.push(...validateResourceInputs(allManifests, defs, aliases, rootModules, (supplied, required) => kindSatisfies(supplied, required, defs)));
|
|
2272
2330
|
// Reroute diagnostics on synthetic (inline-extracted) resources back to
|
|
2273
2331
|
// the chain root so position-index lookups land on the parent doc.
|
|
2274
2332
|
return rewriteSyntheticOrigins(suppressUnreadableModuleDiagnostics(diagnostics, unreadableFiles), allManifests);
|
package/dist/builtins.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builtins.d.ts","sourceRoot":"","sources":["../src/builtins.ts"],"names":[],"mappings":"AAyBA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"builtins.d.ts","sourceRoot":"","sources":["../src/builtins.ts"],"names":[],"mappings":"AAyBA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AA8OvD,eAAO,MAAM,eAAe,EAAE,kBAAkB,EA+tB/C,CAAC"}
|
package/dist/builtins.js
CHANGED
|
@@ -215,6 +215,33 @@ const ROOT_LOGGING_SCHEMA = {
|
|
|
215
215
|
},
|
|
216
216
|
additionalProperties: false,
|
|
217
217
|
};
|
|
218
|
+
/** A `Telo.Library`'s declared resource inputs — the instances it requires from
|
|
219
|
+
* whoever imports it, the inward half of the symmetry `exports.resources`
|
|
220
|
+
* already had outward. Each entry is constrained by KIND ONLY, through the same
|
|
221
|
+
* alias-qualified grammar `extends:` and `x-telo-ref` use; there is no `use:`,
|
|
222
|
+
* because the boundary is a dependency edge for init order whatever the library
|
|
223
|
+
* does with the instance. See `analyzer/nodejs/src/resource-input.ts`. */
|
|
224
|
+
const LIBRARY_RESOURCE_INPUTS_SCHEMA = {
|
|
225
|
+
type: "object",
|
|
226
|
+
additionalProperties: {
|
|
227
|
+
type: "object",
|
|
228
|
+
required: ["kind"],
|
|
229
|
+
properties: {
|
|
230
|
+
kind: { type: "string" },
|
|
231
|
+
description: { type: "string" },
|
|
232
|
+
},
|
|
233
|
+
additionalProperties: false,
|
|
234
|
+
},
|
|
235
|
+
};
|
|
236
|
+
/** The importer's side of the same block: entry name → `!ref` to the instance
|
|
237
|
+
* supplied for it. Left open because the accepted KIND is declared by the
|
|
238
|
+
* target library, not by this schema — the constraint is checked by
|
|
239
|
+
* `validate-resource-inputs.ts`, which reads the target's declared block off
|
|
240
|
+
* the `metadata.requiredResources` stamp. */
|
|
241
|
+
const IMPORT_RESOURCE_INPUTS_SCHEMA = {
|
|
242
|
+
type: "object",
|
|
243
|
+
additionalProperties: {},
|
|
244
|
+
};
|
|
218
245
|
export const KERNEL_BUILTINS = [
|
|
219
246
|
{ kind: "Telo.Abstract", metadata: { name: "Template", module: "Telo" } },
|
|
220
247
|
// "Control can be transferred to this" — the parent of Invocable and Runnable,
|
|
@@ -408,28 +435,26 @@ export const KERNEL_BUILTINS = [
|
|
|
408
435
|
items: {
|
|
409
436
|
type: "object",
|
|
410
437
|
additionalProperties: true,
|
|
411
|
-
//
|
|
412
|
-
//
|
|
413
|
-
//
|
|
414
|
-
//
|
|
415
|
-
//
|
|
438
|
+
// A `resources:` entry is a DECLARATION of another kind, so the
|
|
439
|
+
// CEL inside it belongs to THAT kind: its `x-telo-context` regions
|
|
440
|
+
// are rebased under this entry's path and take precedence (they are
|
|
441
|
+
// deeper), which is what puts `inputs`, `item`, `request`, `steps`
|
|
442
|
+
// and a `catch:`'s `error` in scope exactly where the nested kind
|
|
443
|
+
// declares them — see `analyzer/nodejs/src/template-body.ts`.
|
|
416
444
|
//
|
|
417
|
-
//
|
|
418
|
-
//
|
|
419
|
-
//
|
|
420
|
-
//
|
|
421
|
-
//
|
|
422
|
-
//
|
|
423
|
-
//
|
|
445
|
+
// What stays here is `self` alone, in force throughout the entry:
|
|
446
|
+
// it is how a body reaches the configuration its enclosing template
|
|
447
|
+
// was given, and no nested kind knows about it. The four names that
|
|
448
|
+
// used to sit beside it (`request` / `result` / `steps` / `error`)
|
|
449
|
+
// were a fixed permissive stand-in for the nested kind's own
|
|
450
|
+
// regions — which is why `error` was offered outside every `catch:`
|
|
451
|
+
// while `inputs` and `item` were undefined wherever a body actually
|
|
452
|
+
// reads them.
|
|
424
453
|
"x-telo-context": {
|
|
425
454
|
type: "object",
|
|
426
455
|
additionalProperties: false,
|
|
427
456
|
properties: {
|
|
428
457
|
self: { "x-telo-context-from-root": "schema" },
|
|
429
|
-
request: {},
|
|
430
|
-
result: {},
|
|
431
|
-
steps: {},
|
|
432
|
-
error: {},
|
|
433
458
|
},
|
|
434
459
|
},
|
|
435
460
|
},
|
|
@@ -592,6 +617,7 @@ export const KERNEL_BUILTINS = [
|
|
|
592
617
|
integrity: { type: "string" },
|
|
593
618
|
variables: { type: "object" },
|
|
594
619
|
secrets: { type: "object" },
|
|
620
|
+
resources: IMPORT_RESOURCE_INPUTS_SCHEMA,
|
|
595
621
|
runtime: {
|
|
596
622
|
oneOf: [
|
|
597
623
|
{ type: "string" },
|
|
@@ -738,6 +764,7 @@ export const KERNEL_BUILTINS = [
|
|
|
738
764
|
integrity: { type: "string" },
|
|
739
765
|
variables: { type: "object" },
|
|
740
766
|
secrets: { type: "object" },
|
|
767
|
+
resources: IMPORT_RESOURCE_INPUTS_SCHEMA,
|
|
741
768
|
runtime: {
|
|
742
769
|
oneOf: [
|
|
743
770
|
{ type: "string" },
|
|
@@ -853,6 +880,29 @@ export const KERNEL_BUILTINS = [
|
|
|
853
880
|
},
|
|
854
881
|
variables: { type: "object" },
|
|
855
882
|
secrets: { type: "object" },
|
|
883
|
+
// How many times this library is instantiated in one application.
|
|
884
|
+
//
|
|
885
|
+
// `isolated` (the default) is what every published module was written
|
|
886
|
+
// against: each import declaration builds its own child scope with its
|
|
887
|
+
// own instances, so two libraries importing a third get two of
|
|
888
|
+
// everything in it. `shared` makes the library a SINGLETON — every
|
|
889
|
+
// import of it resolves to one instantiation, owned by the root and
|
|
890
|
+
// torn down after everything that borrowed it.
|
|
891
|
+
//
|
|
892
|
+
// Default `isolated` rather than `shared` — the opposite of the
|
|
893
|
+
// Application field's — because flipping it would silently collapse
|
|
894
|
+
// every existing app's resource graph and turn per-import `variables:`
|
|
895
|
+
// into a conflict. The `exports.kinds` precedent: private-by-default is
|
|
896
|
+
// the better end state and still needs the ecosystem republished first.
|
|
897
|
+
lifecycle: {
|
|
898
|
+
type: "string",
|
|
899
|
+
enum: ["shared", "isolated"],
|
|
900
|
+
default: "isolated",
|
|
901
|
+
},
|
|
902
|
+
// The inward half of `exports.resources`: instances this library
|
|
903
|
+
// requires from whoever imports it. Library-only — an Application is a
|
|
904
|
+
// root with no importer, so it owns its instances outright.
|
|
905
|
+
resources: LIBRARY_RESOURCE_INPUTS_SCHEMA,
|
|
856
906
|
include: {
|
|
857
907
|
type: "array",
|
|
858
908
|
items: { type: "string" },
|
|
@@ -883,6 +933,7 @@ export const KERNEL_BUILTINS = [
|
|
|
883
933
|
integrity: { type: "string" },
|
|
884
934
|
variables: { type: "object" },
|
|
885
935
|
secrets: { type: "object" },
|
|
936
|
+
resources: IMPORT_RESOURCE_INPUTS_SCHEMA,
|
|
886
937
|
runtime: {
|
|
887
938
|
oneOf: [
|
|
888
939
|
{ type: "string" },
|
package/dist/cel-scope.d.ts
CHANGED
|
@@ -132,6 +132,14 @@ export declare class CelScopeResolver {
|
|
|
132
132
|
private stepContext;
|
|
133
133
|
private invocationContext;
|
|
134
134
|
private errorScopes;
|
|
135
|
+
/** The same two facts per `resources:` entry of a `Telo.Definition` — a
|
|
136
|
+
* template body is a declaration of ANOTHER kind, so its step body and its
|
|
137
|
+
* error branches are that kind's, not the enclosing definition's. */
|
|
138
|
+
private bodyScopes;
|
|
139
|
+
/** The enclosing definition's `self` schema, resolved once per resource. A
|
|
140
|
+
* template body's contexts resolve against the BODY, so `self` — the one
|
|
141
|
+
* binding anchored on the definition — is substituted before they do. */
|
|
142
|
+
private selfSchema;
|
|
135
143
|
constructor(inputs: CelScopeInputs);
|
|
136
144
|
/** The `steps` context schema for the current resource, or undefined when its
|
|
137
145
|
* kind declares no step body. Exposed because the step-inputs check needs the
|
package/dist/cel-scope.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cel-scope.d.ts","sourceRoot":"","sources":["../src/cel-scope.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,KAAK,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACzE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,KAAK,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAQvE,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAO9D,OAAO,EAEL,KAAK,kBAAkB,EACxB,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"cel-scope.d.ts","sourceRoot":"","sources":["../src/cel-scope.ts"],"names":[],"mappings":"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"}
|
package/dist/cel-scope.js
CHANGED
|
@@ -5,6 +5,7 @@ import { analyzerContractScope, PERMISSIVE_CONTRACT, resolveContract, } from "./
|
|
|
5
5
|
import { mergeKernelGlobalsIntoContext, } from "./kernel-globals.js";
|
|
6
6
|
import { resolveLocalRef, walkStepArray } from "./schema-walk.js";
|
|
7
7
|
import { readStepSlot } from "./step-slot.js";
|
|
8
|
+
import { bodyForPath, templateBodies } from "./template-body.js";
|
|
8
9
|
import { getManifestItem, resolveContextAnnotations, resolveTypeFieldToSchema, } from "./validate-cel-context.js";
|
|
9
10
|
/** Build a closed JSON Schema for the `self` CEL variable available inside a
|
|
10
11
|
* `Telo.Definition` template body. Mirrors the runtime template controller's
|
|
@@ -268,6 +269,14 @@ export class CelScopeResolver {
|
|
|
268
269
|
stepContext;
|
|
269
270
|
invocationContext;
|
|
270
271
|
errorScopes = new Map();
|
|
272
|
+
/** The same two facts per `resources:` entry of a `Telo.Definition` — a
|
|
273
|
+
* template body is a declaration of ANOTHER kind, so its step body and its
|
|
274
|
+
* error branches are that kind's, not the enclosing definition's. */
|
|
275
|
+
bodyScopes = [];
|
|
276
|
+
/** The enclosing definition's `self` schema, resolved once per resource. A
|
|
277
|
+
* template body's contexts resolve against the BODY, so `self` — the one
|
|
278
|
+
* binding anchored on the definition — is substituted before they do. */
|
|
279
|
+
selfSchema;
|
|
271
280
|
constructor(inputs) {
|
|
272
281
|
this.inputs = inputs;
|
|
273
282
|
}
|
|
@@ -303,6 +312,20 @@ export class CelScopeResolver {
|
|
|
303
312
|
? buildStepContextSchema(m, authorSchema, allManifests, defs, aliases, scopes)
|
|
304
313
|
: undefined;
|
|
305
314
|
this.errorScopes = collectErrorContextScopes(authorSchema);
|
|
315
|
+
this.selfSchema =
|
|
316
|
+
m.kind === "Telo.Definition" ? buildSelfSchema(m, defs, aliases) : undefined;
|
|
317
|
+
this.bodyScopes = templateBodies(m, defs, aliases, scopes).map((body) => {
|
|
318
|
+
const bodySchema = defs.effectiveSchemaOf(body.definition);
|
|
319
|
+
return {
|
|
320
|
+
prefix: body.prefix,
|
|
321
|
+
scopePrefix: body.scopePrefix,
|
|
322
|
+
manifest: body.manifest,
|
|
323
|
+
stepContext: bodySchema
|
|
324
|
+
? buildStepContextSchema(body.manifest, bodySchema, allManifests, defs, aliases, scopes)
|
|
325
|
+
: undefined,
|
|
326
|
+
errorScopes: collectErrorContextScopes(bodySchema),
|
|
327
|
+
};
|
|
328
|
+
});
|
|
306
329
|
}
|
|
307
330
|
/**
|
|
308
331
|
* What the expression at `site` is typed against.
|
|
@@ -339,7 +362,13 @@ export class CelScopeResolver {
|
|
|
339
362
|
const { path } = site;
|
|
340
363
|
const m = site.source;
|
|
341
364
|
let matched = site.contextSchema ?? this.invocationContext;
|
|
342
|
-
|
|
365
|
+
// Inside a template body the step and error regions are the NESTED kind's.
|
|
366
|
+
// Its `steps` accumulator and its `catch:` branches are declared there, and
|
|
367
|
+
// the enclosing definition's (there are none) would say nothing about them.
|
|
368
|
+
const inBody = this.bodyScopes.length > 0 ? bodyForPath(this.bodyScopes, path) : undefined;
|
|
369
|
+
const stepContext = inBody ? inBody.stepContext : this.stepContext;
|
|
370
|
+
const errorScopes = inBody ? inBody.errorScopes : this.errorScopes;
|
|
371
|
+
if (stepContext) {
|
|
343
372
|
const base = matched ?? { type: "object", properties: {}, additionalProperties: true };
|
|
344
373
|
matched = {
|
|
345
374
|
...base,
|
|
@@ -356,13 +385,13 @@ export class CelScopeResolver {
|
|
|
356
385
|
// which is a separate decision from knowing the name is legal.
|
|
357
386
|
inputs: { type: "object", additionalProperties: true },
|
|
358
387
|
...(base.properties ?? {}),
|
|
359
|
-
steps:
|
|
388
|
+
steps: stepContext,
|
|
360
389
|
},
|
|
361
390
|
};
|
|
362
391
|
}
|
|
363
392
|
// `error` is only in scope inside an error-bearing branch (e.g. a
|
|
364
393
|
// `catch:` / `finally:`), so it's merged per-path, not resource-wide.
|
|
365
|
-
const errorSchema =
|
|
394
|
+
const errorSchema = errorScopes.size > 0 ? errorContextForPath(path, errorScopes) : undefined;
|
|
366
395
|
if (errorSchema) {
|
|
367
396
|
const base = matched ?? { type: "object", properties: {}, additionalProperties: true };
|
|
368
397
|
matched = {
|
|
@@ -378,17 +407,46 @@ export class CelScopeResolver {
|
|
|
378
407
|
return this.inputs.observedStateContext;
|
|
379
408
|
}
|
|
380
409
|
const { defs, aliases, scopes, allManifests, kernelGlobals } = this.inputs;
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
410
|
+
// A template body's context annotations are the NESTED kind's, and every one
|
|
411
|
+
// that anchors at a root — `x-telo-context-element-from`,
|
|
412
|
+
// `-collection-from`, `-from-root`, `x-telo-bindings-from` — means the root
|
|
413
|
+
// of the DECLARATION they were written for. Resolving them against the
|
|
414
|
+
// enclosing `Telo.Definition` looked `collection:` up on a document that has
|
|
415
|
+
// no such field, so `item` typed open and a typo below it went unreported —
|
|
416
|
+
// the one place a nested declaration did not answer as the same declaration
|
|
417
|
+
// written at the top level.
|
|
418
|
+
//
|
|
419
|
+
// So the path and the scope are rebased into the body and the body becomes
|
|
420
|
+
// the resolution root. `self` is the single binding that genuinely belongs to
|
|
421
|
+
// the enclosing definition, and it is substituted below rather than left as
|
|
422
|
+
// an annotation the rebased root would misread.
|
|
423
|
+
const body = inBody;
|
|
424
|
+
const localPath = body ? path.slice(body.prefix.length + 1) : path;
|
|
425
|
+
const localScope = body && site.matchedScope?.startsWith(`${body.scopePrefix}.`)
|
|
426
|
+
? `$.${site.matchedScope.slice(body.scopePrefix.length + 1)}`
|
|
427
|
+
: body
|
|
428
|
+
? undefined
|
|
429
|
+
: site.matchedScope;
|
|
430
|
+
const rootManifest = body ? body.manifest : m;
|
|
431
|
+
if (body && this.selfSchema && matched.properties?.self) {
|
|
432
|
+
matched = {
|
|
433
|
+
...matched,
|
|
434
|
+
properties: { ...matched.properties, self: this.selfSchema },
|
|
435
|
+
};
|
|
436
|
+
}
|
|
437
|
+
const manifestItem = localScope
|
|
438
|
+
? getManifestItem(localPath, localScope, rootManifest)
|
|
439
|
+
: rootManifest;
|
|
440
|
+
const rootForResolver = body
|
|
441
|
+
? rootManifest
|
|
442
|
+
: manifestRootForResolver(m, defs, aliases, allManifests, scopes);
|
|
385
443
|
const resolved = resolveContextAnnotations(matched, manifestItem, {
|
|
386
444
|
manifestRoot: rootForResolver,
|
|
387
445
|
defs,
|
|
388
446
|
aliases,
|
|
389
447
|
allManifests: allManifests,
|
|
390
448
|
});
|
|
391
|
-
return mergeKernelGlobalsIntoContext(withBindingNames(resolved,
|
|
449
|
+
return mergeKernelGlobalsIntoContext(withBindingNames(resolved, rootManifest),
|
|
392
450
|
// Typed in the module that DECLARED this resource — for a manifest
|
|
393
451
|
// forwarded from an imported library, that is its `moduleGlobals` stamp,
|
|
394
452
|
// not the consuming application's block.
|
|
@@ -190,6 +190,23 @@ export declare class DefinitionRegistry {
|
|
|
190
190
|
*/
|
|
191
191
|
resolveSchemaFromNode(schemaFrom: string, ownerScope: AliasResolver): Record<string, any> | undefined;
|
|
192
192
|
private resolveSchemaFromSubMap;
|
|
193
|
+
/** The kinds a definition descends from DIRECTLY — the same two edges
|
|
194
|
+
* `register` feeds into `extendedBy`, read the other way.
|
|
195
|
+
*
|
|
196
|
+
* Both spellings, because either can carry the edge that satisfies a slot:
|
|
197
|
+
* `capability:` is the legacy implements-this form, `extends:` the canonical
|
|
198
|
+
* one. A consumer walking these by hand would be a second reading of what an
|
|
199
|
+
* inheritance edge IS, and the downward index and the upward walk have to
|
|
200
|
+
* agree about that forever. */
|
|
201
|
+
parentsOf(kind: string): string[];
|
|
202
|
+
/** Whether every kind this one descends from is registered.
|
|
203
|
+
*
|
|
204
|
+
* When it is, what the kind implements is FULLY KNOWN: a target it does not
|
|
205
|
+
* reach is one it genuinely does not implement, so a mismatch is a verdict.
|
|
206
|
+
* When a hop is missing — an unimported abstract, an alias the declaring file
|
|
207
|
+
* could not resolve — a mismatch cannot be told from a missing dependency,
|
|
208
|
+
* which is the partial context every reference check stays lenient in. */
|
|
209
|
+
ancestryResolved(kind: string): boolean;
|
|
193
210
|
/** Returns all definitions that transitively extend the given abstract kind.
|
|
194
211
|
* Follows the capability chain to any depth (equivalent to instanceof in OOP).
|
|
195
212
|
* Definitions are included regardless of registration order. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"definition-registry.d.ts","sourceRoot":"","sources":["../src/definition-registry.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"definition-registry.d.ts","sourceRoot":"","sources":["../src/definition-registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -409,6 +409,41 @@ export class DefinitionRegistry {
|
|
|
409
409
|
return null;
|
|
410
410
|
return buildFieldMapAtPath(subSchema, fieldPath);
|
|
411
411
|
}
|
|
412
|
+
/** The kinds a definition descends from DIRECTLY — the same two edges
|
|
413
|
+
* `register` feeds into `extendedBy`, read the other way.
|
|
414
|
+
*
|
|
415
|
+
* Both spellings, because either can carry the edge that satisfies a slot:
|
|
416
|
+
* `capability:` is the legacy implements-this form, `extends:` the canonical
|
|
417
|
+
* one. A consumer walking these by hand would be a second reading of what an
|
|
418
|
+
* inheritance edge IS, and the downward index and the upward walk have to
|
|
419
|
+
* agree about that forever. */
|
|
420
|
+
parentsOf(kind) {
|
|
421
|
+
const def = this.defs.get(kind);
|
|
422
|
+
if (!def)
|
|
423
|
+
return [];
|
|
424
|
+
return [def.capability, def.extends].filter((parent) => typeof parent === "string" && parent.length > 0);
|
|
425
|
+
}
|
|
426
|
+
/** Whether every kind this one descends from is registered.
|
|
427
|
+
*
|
|
428
|
+
* When it is, what the kind implements is FULLY KNOWN: a target it does not
|
|
429
|
+
* reach is one it genuinely does not implement, so a mismatch is a verdict.
|
|
430
|
+
* When a hop is missing — an unimported abstract, an alias the declaring file
|
|
431
|
+
* could not resolve — a mismatch cannot be told from a missing dependency,
|
|
432
|
+
* which is the partial context every reference check stays lenient in. */
|
|
433
|
+
ancestryResolved(kind) {
|
|
434
|
+
const queue = [kind];
|
|
435
|
+
const seen = new Set();
|
|
436
|
+
while (queue.length > 0) {
|
|
437
|
+
const current = queue.shift();
|
|
438
|
+
if (seen.has(current))
|
|
439
|
+
continue;
|
|
440
|
+
seen.add(current);
|
|
441
|
+
if (!this.defs.has(current))
|
|
442
|
+
return false;
|
|
443
|
+
queue.push(...this.parentsOf(current));
|
|
444
|
+
}
|
|
445
|
+
return true;
|
|
446
|
+
}
|
|
412
447
|
/** Returns all definitions that transitively extend the given abstract kind.
|
|
413
448
|
* Follows the capability chain to any depth (equivalent to instanceof in OOP).
|
|
414
449
|
* Definitions are included regardless of registration order. */
|
|
@@ -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;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;
|
|
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;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAGnE,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;;;;;;;;;;;;;;;;;;;;;GAqBG;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,CA2DjB;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,aAAa,CAAC,YAAY,CAAC,GAAG,MAAM,CAOtE"}
|
package/dist/dependency-graph.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { buildCallGraph, projectToPairs } from "./call-graph.js";
|
|
2
|
+
import { readSuppliedResources } from "./resource-input.js";
|
|
2
3
|
const nodeKey = (kind, name) => `${kind}\0${name}`;
|
|
3
4
|
/**
|
|
4
5
|
* Builds a directed acyclic graph (DAG) of boot-time resource dependencies and
|
|
@@ -45,6 +46,7 @@ export function buildDependencyGraph(resources, registry, aliases, aliasesByModu
|
|
|
45
46
|
for (const key of nodes.keys())
|
|
46
47
|
if (!deps.has(key))
|
|
47
48
|
deps.set(key, new Set());
|
|
49
|
+
addResourceInputEdges(resources, nodes, deps);
|
|
48
50
|
// --- Kahn's topological sort ---
|
|
49
51
|
// in-degree[X] = number of X's dependencies (size of deps[X])
|
|
50
52
|
// reverse[dep] = set of nodes that depend on dep (for degree decrement)
|
|
@@ -130,3 +132,66 @@ function findCycle(nodes, deps) {
|
|
|
130
132
|
}
|
|
131
133
|
return [];
|
|
132
134
|
}
|
|
135
|
+
/**
|
|
136
|
+
* Boot-order edges for the one thing a `Telo.Import` does hold: the instances it
|
|
137
|
+
* hands DOWN to its target library's declared `resources:` inputs.
|
|
138
|
+
*
|
|
139
|
+
* An import is otherwise module wiring rather than a runtime node — it is in
|
|
140
|
+
* `DEPENDENCY_GRAPH_SKIP_KINDS` and the call graph gives it no node at all — but
|
|
141
|
+
* a borrowed instance must exist before the import initializes, and a cycle
|
|
142
|
+
* through one is a cycle like any other. The edges are added here rather than
|
|
143
|
+
* read off the reference field map because the accepted KIND at this slot is
|
|
144
|
+
* declared by the TARGET library, not by the `Telo.Import` schema, so there is
|
|
145
|
+
* no `x-telo-ref` for the map to read; the constraint itself is checked by
|
|
146
|
+
* `validate-resource-inputs`.
|
|
147
|
+
*/
|
|
148
|
+
function addResourceInputEdges(resources, nodes, deps) {
|
|
149
|
+
// Every import that supplies inputs becomes a node FIRST, so a cross-module
|
|
150
|
+
// reference below can resolve to the import that exports its target.
|
|
151
|
+
const imports = [];
|
|
152
|
+
for (const m of resources) {
|
|
153
|
+
if (m.kind !== "Telo.Import")
|
|
154
|
+
continue;
|
|
155
|
+
const alias = m.metadata?.name;
|
|
156
|
+
const supplied = readSuppliedResources(m);
|
|
157
|
+
if (!alias || Object.keys(supplied).length === 0)
|
|
158
|
+
continue;
|
|
159
|
+
const key = nodeKey(m.kind, alias);
|
|
160
|
+
nodes.set(key, { kind: m.kind, name: alias });
|
|
161
|
+
if (!deps.has(key))
|
|
162
|
+
deps.set(key, new Set());
|
|
163
|
+
imports.push({ key, supplied });
|
|
164
|
+
}
|
|
165
|
+
if (imports.length === 0)
|
|
166
|
+
return;
|
|
167
|
+
const byName = new Map();
|
|
168
|
+
for (const [key, node] of nodes)
|
|
169
|
+
byName.set(node.name, key);
|
|
170
|
+
// An import is keyed by its alias, and that is also how a cross-module
|
|
171
|
+
// reference names it — index those so one resolves.
|
|
172
|
+
for (const m of resources) {
|
|
173
|
+
if (m.kind !== "Telo.Import")
|
|
174
|
+
continue;
|
|
175
|
+
const alias = m.metadata?.name;
|
|
176
|
+
const key = alias ? nodeKey(m.kind, alias) : undefined;
|
|
177
|
+
if (alias && key && nodes.has(key))
|
|
178
|
+
byName.set(alias, key);
|
|
179
|
+
}
|
|
180
|
+
for (const { key, supplied } of imports) {
|
|
181
|
+
const set = deps.get(key);
|
|
182
|
+
for (const value of Object.values(supplied)) {
|
|
183
|
+
const ref = value;
|
|
184
|
+
// A CROSS-MODULE reference (`!ref Other.db`) names an instance exported by
|
|
185
|
+
// another import, never a local resource. Looking it up in the local name
|
|
186
|
+
// map would find an unrelated resource of the same name — a wrong edge,
|
|
187
|
+
// and possibly a phantom cycle — or nothing at all. What it depends on is
|
|
188
|
+
// the IMPORT that exports it, which is the projection
|
|
189
|
+
// `localDependencyNames` already makes at runtime.
|
|
190
|
+
const alias = typeof ref?.alias === "string" ? ref.alias : undefined;
|
|
191
|
+
const targetName = alias && alias !== "Self" ? alias : typeof ref?.name === "string" ? ref.name : undefined;
|
|
192
|
+
const target = targetName ? byName.get(targetName) : undefined;
|
|
193
|
+
if (target && target !== key)
|
|
194
|
+
set.add(target);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
@@ -36,6 +36,26 @@ export declare function inheritedCapability(def: ResourceDefinition | undefined,
|
|
|
36
36
|
* `mergeTypeSchemas` that `Type.JsonSchema.extends` uses.
|
|
37
37
|
* - no `extends` → the own schema unchanged. */
|
|
38
38
|
export declare function effectiveAuthorSchema(def: ResourceDefinition | undefined, resolve: DefResolver): Record<string, any>;
|
|
39
|
+
/**
|
|
40
|
+
* The fields a merge-form inheriting child publishes over its parent's reading.
|
|
41
|
+
*
|
|
42
|
+
* A child that inherits its controller by delegation and declares no `base:` IS
|
|
43
|
+
* the parent instance, so `resources.<child>` is the parent's `snapshot()` — and
|
|
44
|
+
* a field the parent has never heard of would be readable from nowhere. These
|
|
45
|
+
* are exactly those fields: the ones the effective (merged) schema declares that
|
|
46
|
+
* the controller-bearing ancestor's does not.
|
|
47
|
+
*
|
|
48
|
+
* A REDECLARED name is deliberately excluded. Narrowing an inherited field (a
|
|
49
|
+
* description, a pattern, a widget hint) is ordinary in an additive extension and
|
|
50
|
+
* says nothing about publication, while the parent's `snapshot()` is the sole
|
|
51
|
+
* authority on what a parent instance publishes — its normalizations, its
|
|
52
|
+
* deliberate omissions, and its redactions. Republishing such a field from raw
|
|
53
|
+
* config would silently undo a provider's decision to keep it out.
|
|
54
|
+
*
|
|
55
|
+
* Empty for the `base:` form, whose fields are construction inputs consumed by
|
|
56
|
+
* the mapping, and for a child with its own controller, which publishes itself.
|
|
57
|
+
*/
|
|
58
|
+
export declare function publishedOwnFields(def: ResourceDefinition | undefined, resolve: DefResolver): string[];
|
|
39
59
|
/** The two directions of a kind's invocation contract. `inputType` is what a
|
|
40
60
|
* caller sends to `invoke()`; `outputType` is what `invoke()` / `provide()`
|
|
41
61
|
* returns. */
|