@telorun/analyzer 0.62.0 → 0.63.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/analysis-registry.d.ts.map +1 -1
- package/dist/analysis-registry.js +6 -0
- package/dist/analyzer.d.ts +1 -1
- package/dist/analyzer.d.ts.map +1 -1
- package/dist/analyzer.js +343 -13
- package/dist/call-graph.d.ts.map +1 -1
- package/dist/call-graph.js +2 -7
- package/dist/flatten-for-analyzer.js +1 -1
- package/dist/import-resolution-diagnostics.d.ts +9 -2
- package/dist/import-resolution-diagnostics.d.ts.map +1 -1
- package/dist/import-resolution-diagnostics.js +26 -7
- package/dist/index.d.ts +15 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -1
- package/dist/invocation-contract.d.ts +6 -1
- package/dist/invocation-contract.d.ts.map +1 -1
- package/dist/invocation-contract.js +27 -4
- package/dist/loaded-types.d.ts +12 -3
- package/dist/loaded-types.d.ts.map +1 -1
- package/dist/manifest-loader.d.ts +0 -1
- package/dist/manifest-loader.d.ts.map +1 -1
- package/dist/manifest-loader.js +62 -41
- package/dist/manifest-schemas.d.ts +699 -0
- package/dist/manifest-schemas.d.ts.map +1 -1
- package/dist/manifest-schemas.js +306 -14
- package/dist/module-compatibility.d.ts +40 -0
- package/dist/module-compatibility.d.ts.map +1 -0
- package/dist/module-compatibility.js +52 -0
- package/dist/ref-slot-reading.d.ts +30 -0
- package/dist/ref-slot-reading.d.ts.map +1 -0
- package/dist/ref-slot-reading.js +139 -0
- package/dist/referrer-rule.d.ts +67 -0
- package/dist/referrer-rule.d.ts.map +1 -0
- package/dist/referrer-rule.js +96 -0
- package/dist/release/index.d.ts +1 -1
- package/dist/release/index.d.ts.map +1 -1
- package/dist/release/index.js +1 -1
- package/dist/release/payload-digest.d.ts +7 -3
- package/dist/release/payload-digest.d.ts.map +1 -1
- package/dist/release/payload-digest.js +7 -3
- package/dist/release/version-stamp.d.ts +16 -0
- package/dist/release/version-stamp.d.ts.map +1 -1
- package/dist/release/version-stamp.js +52 -0
- package/dist/release/workspace-config.d.ts +10 -6
- package/dist/release/workspace-config.d.ts.map +1 -1
- package/dist/release/workspace-config.js +10 -6
- package/dist/resolve-schema-ref-kinds.d.ts +4 -3
- package/dist/resolve-schema-ref-kinds.d.ts.map +1 -1
- package/dist/resolve-schema-ref-kinds.js +16 -0
- package/dist/resolve-throws-union.d.ts.map +1 -1
- package/dist/resolve-throws-union.js +4 -3
- package/dist/resolve-zone-containment.d.ts +99 -0
- package/dist/resolve-zone-containment.d.ts.map +1 -0
- package/dist/resolve-zone-containment.js +212 -0
- package/dist/resolve-zone-requirements.d.ts +5 -0
- package/dist/resolve-zone-requirements.d.ts.map +1 -1
- package/dist/resolve-zone-requirements.js +48 -7
- package/dist/resource-rule.d.ts +106 -0
- package/dist/resource-rule.d.ts.map +1 -0
- package/dist/resource-rule.js +236 -0
- package/dist/rule-condition.d.ts +50 -0
- package/dist/rule-condition.d.ts.map +1 -0
- package/dist/rule-condition.js +108 -0
- package/dist/schema-keywords.d.ts.map +1 -1
- package/dist/schema-keywords.js +20 -0
- package/dist/schema-projection.d.ts +171 -0
- package/dist/schema-projection.d.ts.map +1 -0
- package/dist/schema-projection.js +317 -0
- package/dist/step-slot.d.ts +39 -0
- package/dist/step-slot.d.ts.map +1 -0
- package/dist/step-slot.js +49 -0
- package/dist/telo-version.d.ts +1 -1
- package/dist/telo-version.js +1 -1
- package/dist/validate-cel-context.d.ts.map +1 -1
- package/dist/validate-cel-context.js +17 -3
- package/dist/validate-durable-regions.d.ts +15 -0
- package/dist/validate-durable-regions.d.ts.map +1 -0
- package/dist/validate-durable-regions.js +336 -0
- package/dist/validate-references.d.ts.map +1 -1
- package/dist/validate-references.js +44 -2
- package/dist/validate-referrer-rules.d.ts +120 -0
- package/dist/validate-referrer-rules.d.ts.map +1 -0
- package/dist/validate-referrer-rules.js +255 -0
- package/dist/validate-resource-rules.d.ts +114 -0
- package/dist/validate-resource-rules.d.ts.map +1 -0
- package/dist/validate-resource-rules.js +283 -0
- package/dist/validate-schema-projection.d.ts +32 -0
- package/dist/validate-schema-projection.d.ts.map +1 -0
- package/dist/validate-schema-projection.js +110 -0
- package/dist/validate-step-inputs.d.ts +2 -1
- package/dist/validate-step-inputs.d.ts.map +1 -1
- package/dist/validate-step-inputs.js +5 -3
- package/dist/validate-throws-coverage.d.ts.map +1 -1
- package/dist/validate-throws-coverage.js +11 -5
- package/dist/validate-zone-slots.d.ts +2 -2
- package/dist/validate-zone-slots.d.ts.map +1 -1
- package/dist/validate-zone-slots.js +202 -6
- package/dist/validate-zone-violations.d.ts +12 -0
- package/dist/validate-zone-violations.d.ts.map +1 -0
- package/dist/validate-zone-violations.js +169 -0
- package/dist/value-type-keyword.d.ts +1 -1
- package/dist/value-type-keyword.d.ts.map +1 -1
- package/dist/value-type-keyword.js +4 -0
- package/dist/zone-slot.d.ts +61 -0
- package/dist/zone-slot.d.ts.map +1 -1
- package/dist/zone-slot.js +86 -5
- package/package.json +2 -2
- package/src/analysis-registry.ts +6 -0
- package/src/analyzer.ts +395 -14
- package/src/call-graph.ts +2 -8
- package/src/flatten-for-analyzer.ts +1 -1
- package/src/import-resolution-diagnostics.ts +25 -7
- package/src/index.ts +73 -0
- package/src/invocation-contract.ts +45 -2
- package/src/loaded-types.ts +12 -3
- package/src/manifest-loader.ts +87 -55
- package/src/manifest-schemas.ts +328 -14
- package/src/module-compatibility.ts +72 -0
- package/src/ref-slot-reading.ts +156 -0
- package/src/referrer-rule.ts +116 -0
- package/src/release/index.ts +1 -0
- package/src/release/payload-digest.ts +7 -3
- package/src/release/version-stamp.ts +58 -0
- package/src/release/workspace-config.ts +10 -6
- package/src/resolve-schema-ref-kinds.ts +28 -4
- package/src/resolve-throws-union.ts +4 -3
- package/src/resolve-zone-containment.ts +329 -0
- package/src/resolve-zone-requirements.ts +67 -7
- package/src/resource-rule.ts +252 -0
- package/src/rule-condition.ts +126 -0
- package/src/schema-keywords.ts +24 -0
- package/src/schema-projection.ts +403 -0
- package/src/step-slot.ts +64 -0
- package/src/telo-version.ts +1 -1
- package/src/validate-cel-context.ts +17 -3
- package/src/validate-durable-regions.ts +401 -0
- package/src/validate-references.ts +57 -2
- package/src/validate-referrer-rules.ts +373 -0
- package/src/validate-resource-rules.ts +401 -0
- package/src/validate-schema-projection.ts +184 -0
- package/src/validate-step-inputs.ts +5 -3
- package/src/validate-throws-coverage.ts +12 -5
- package/src/validate-zone-slots.ts +192 -8
- package/src/validate-zone-violations.ts +190 -0
- package/src/value-type-keyword.ts +4 -0
- package/src/zone-slot.ts +114 -5
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The single reader for `x-telo-referrer-rules` — a kind declaring, as data,
|
|
3
|
+
* what must be true of whoever REFERENCES one of its resources.
|
|
4
|
+
*
|
|
5
|
+
* `x-telo-resource-rules` relates the fields of one resource; this relates a
|
|
6
|
+
* resource to the one that reached it. `Http.Reference` renders the OpenAPI
|
|
7
|
+
* document its server collects, so a server mounting it without an `openapi:`
|
|
8
|
+
* block has nothing to render — a disagreement neither kind can state alone,
|
|
9
|
+
* and one that otherwise surfaces only at boot, after the port is bound.
|
|
10
|
+
*
|
|
11
|
+
* Declared by the kind that HAS the requirement, never by the kind that must
|
|
12
|
+
* satisfy it. That is what lets a third-party mount carry its own requirement
|
|
13
|
+
* without `Http.Server` knowing the kind exists — and it is what keeps the rule
|
|
14
|
+
* free of a kind literal on the subject side, where the spelling would be the
|
|
15
|
+
* consumer's import alias rather than anything the rule author controls.
|
|
16
|
+
*
|
|
17
|
+
* The CEL scope is `self` (the declaring resource) and `referrer` (the one that
|
|
18
|
+
* references it). Deliberately NOT `this`: in a resource rule `this` is an
|
|
19
|
+
* ELEMENT of a collection, and binding it to a whole foreign manifest would give
|
|
20
|
+
* one word two meanings across the two families.
|
|
21
|
+
*
|
|
22
|
+
* Lenient by design, the `ref-slot.ts` precedent: anything unreadable here reads
|
|
23
|
+
* as absent, and `validate-referrer-rules.ts` is the strict half that reports it.
|
|
24
|
+
*
|
|
25
|
+
* Browser-safe: no Node built-ins.
|
|
26
|
+
*/
|
|
27
|
+
import { type ResourceRuleSeverity } from "./resource-rule.js";
|
|
28
|
+
export declare const REFERRER_RULES_ANNOTATION = "x-telo-referrer-rules";
|
|
29
|
+
export interface ReferrerRule {
|
|
30
|
+
/**
|
|
31
|
+
* Kind the referring resource must be for this rule to apply, in the
|
|
32
|
+
* alias-qualified grammar `extends:` and `x-telo-ref` use — canonicalized in
|
|
33
|
+
* the declaring module's scope at registration, so evaluation never sees an
|
|
34
|
+
* alias. Absent = any referrer, which conflates "references me" with the
|
|
35
|
+
* relation the rule is about, so a kind should write it.
|
|
36
|
+
*/
|
|
37
|
+
readonly referrer?: string;
|
|
38
|
+
/** CEL source. TRUE when the rule holds. */
|
|
39
|
+
readonly condition: string;
|
|
40
|
+
/** The rule's own name, carried in `data.rule`. Never a diagnostic code —
|
|
41
|
+
* every violation reports under the analyzer-owned envelope. */
|
|
42
|
+
readonly code: string;
|
|
43
|
+
readonly message: string;
|
|
44
|
+
readonly severity: ResourceRuleSeverity;
|
|
45
|
+
/** Position in the annotation array — the anchor for a declaration defect. */
|
|
46
|
+
readonly index: number;
|
|
47
|
+
}
|
|
48
|
+
/** The annotation exactly as written, for the strict half. `undefined` when the
|
|
49
|
+
* kind declares none; a non-array is returned as-is so the shape can be
|
|
50
|
+
* reported rather than silently skipped. */
|
|
51
|
+
export declare function readRawReferrerRules(schema: unknown): unknown;
|
|
52
|
+
/** Every rule this kind declares that is well-formed enough to run. */
|
|
53
|
+
export declare function readReferrerRules(schema: unknown): ReferrerRule[];
|
|
54
|
+
/** True when this node carries the annotation — the recognizer the schema-kind
|
|
55
|
+
* canonicalization walk tests, so shape knowledge stays in this file. */
|
|
56
|
+
export declare function hasReferrerRules(node: Record<string, unknown>): boolean;
|
|
57
|
+
/**
|
|
58
|
+
* Rewrite each rule's `referrer:` kind through `rewrite`, in place.
|
|
59
|
+
*
|
|
60
|
+
* The mirror of `rewriteRequiresZoneKind`: the alias→canonical rule lives in
|
|
61
|
+
* `resolve-schema-ref-kinds.ts` and the shape lives here, so a filter is
|
|
62
|
+
* canonical everywhere downstream and a name that resolves to nothing is
|
|
63
|
+
* reported once, at the kind that wrote it. A rewrite returning `undefined`
|
|
64
|
+
* leaves the value as written — the caller reports it.
|
|
65
|
+
*/
|
|
66
|
+
export declare function rewriteReferrerRuleKinds(node: Record<string, unknown>, rewrite: (kind: string) => string | undefined): void;
|
|
67
|
+
//# sourceMappingURL=referrer-rule.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"referrer-rule.d.ts","sourceRoot":"","sources":["../src/referrer-rule.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,OAAO,EAAe,KAAK,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAE5E,eAAO,MAAM,yBAAyB,0BAA0B,CAAC;AAEjE,MAAM,WAAW,YAAY;IAC3B;;;;;;OAMG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,4CAA4C;IAC5C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;qEACiE;IACjE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,oBAAoB,CAAC;IACxC,8EAA8E;IAC9E,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAMD;;6CAE6C;AAC7C,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAG7D;AAED,uEAAuE;AACvE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,OAAO,GAAG,YAAY,EAAE,CAwBjE;AAED;0EAC0E;AAC1E,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAEvE;AAED;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,GAC5C,IAAI,CAQN"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The single reader for `x-telo-referrer-rules` — a kind declaring, as data,
|
|
3
|
+
* what must be true of whoever REFERENCES one of its resources.
|
|
4
|
+
*
|
|
5
|
+
* `x-telo-resource-rules` relates the fields of one resource; this relates a
|
|
6
|
+
* resource to the one that reached it. `Http.Reference` renders the OpenAPI
|
|
7
|
+
* document its server collects, so a server mounting it without an `openapi:`
|
|
8
|
+
* block has nothing to render — a disagreement neither kind can state alone,
|
|
9
|
+
* and one that otherwise surfaces only at boot, after the port is bound.
|
|
10
|
+
*
|
|
11
|
+
* Declared by the kind that HAS the requirement, never by the kind that must
|
|
12
|
+
* satisfy it. That is what lets a third-party mount carry its own requirement
|
|
13
|
+
* without `Http.Server` knowing the kind exists — and it is what keeps the rule
|
|
14
|
+
* free of a kind literal on the subject side, where the spelling would be the
|
|
15
|
+
* consumer's import alias rather than anything the rule author controls.
|
|
16
|
+
*
|
|
17
|
+
* The CEL scope is `self` (the declaring resource) and `referrer` (the one that
|
|
18
|
+
* references it). Deliberately NOT `this`: in a resource rule `this` is an
|
|
19
|
+
* ELEMENT of a collection, and binding it to a whole foreign manifest would give
|
|
20
|
+
* one word two meanings across the two families.
|
|
21
|
+
*
|
|
22
|
+
* Lenient by design, the `ref-slot.ts` precedent: anything unreadable here reads
|
|
23
|
+
* as absent, and `validate-referrer-rules.ts` is the strict half that reports it.
|
|
24
|
+
*
|
|
25
|
+
* Browser-safe: no Node built-ins.
|
|
26
|
+
*/
|
|
27
|
+
import { celSourceOf } from "./resource-rule.js";
|
|
28
|
+
export const REFERRER_RULES_ANNOTATION = "x-telo-referrer-rules";
|
|
29
|
+
function isObject(value) {
|
|
30
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
31
|
+
}
|
|
32
|
+
/** The annotation exactly as written, for the strict half. `undefined` when the
|
|
33
|
+
* kind declares none; a non-array is returned as-is so the shape can be
|
|
34
|
+
* reported rather than silently skipped. */
|
|
35
|
+
export function readRawReferrerRules(schema) {
|
|
36
|
+
if (!isObject(schema))
|
|
37
|
+
return undefined;
|
|
38
|
+
return schema[REFERRER_RULES_ANNOTATION];
|
|
39
|
+
}
|
|
40
|
+
/** Every rule this kind declares that is well-formed enough to run. */
|
|
41
|
+
export function readReferrerRules(schema) {
|
|
42
|
+
const raw = readRawReferrerRules(schema);
|
|
43
|
+
if (!Array.isArray(raw))
|
|
44
|
+
return [];
|
|
45
|
+
const rules = [];
|
|
46
|
+
raw.forEach((entry, index) => {
|
|
47
|
+
if (!isObject(entry))
|
|
48
|
+
return;
|
|
49
|
+
const condition = celSourceOf(entry.condition);
|
|
50
|
+
const { code, message, referrer } = entry;
|
|
51
|
+
if (!condition || typeof code !== "string" || typeof message !== "string")
|
|
52
|
+
return;
|
|
53
|
+
if (code.length === 0 || message.length === 0)
|
|
54
|
+
return;
|
|
55
|
+
if (referrer !== undefined && typeof referrer !== "string")
|
|
56
|
+
return;
|
|
57
|
+
if (entry.severity !== undefined && entry.severity !== "warning" && entry.severity !== "error") {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
rules.push({
|
|
61
|
+
...(referrer === undefined ? {} : { referrer }),
|
|
62
|
+
condition,
|
|
63
|
+
code,
|
|
64
|
+
message,
|
|
65
|
+
severity: entry.severity === "warning" ? "warning" : "error",
|
|
66
|
+
index,
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
return rules;
|
|
70
|
+
}
|
|
71
|
+
/** True when this node carries the annotation — the recognizer the schema-kind
|
|
72
|
+
* canonicalization walk tests, so shape knowledge stays in this file. */
|
|
73
|
+
export function hasReferrerRules(node) {
|
|
74
|
+
return Array.isArray(node[REFERRER_RULES_ANNOTATION]);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Rewrite each rule's `referrer:` kind through `rewrite`, in place.
|
|
78
|
+
*
|
|
79
|
+
* The mirror of `rewriteRequiresZoneKind`: the alias→canonical rule lives in
|
|
80
|
+
* `resolve-schema-ref-kinds.ts` and the shape lives here, so a filter is
|
|
81
|
+
* canonical everywhere downstream and a name that resolves to nothing is
|
|
82
|
+
* reported once, at the kind that wrote it. A rewrite returning `undefined`
|
|
83
|
+
* leaves the value as written — the caller reports it.
|
|
84
|
+
*/
|
|
85
|
+
export function rewriteReferrerRuleKinds(node, rewrite) {
|
|
86
|
+
const raw = node[REFERRER_RULES_ANNOTATION];
|
|
87
|
+
if (!Array.isArray(raw))
|
|
88
|
+
return;
|
|
89
|
+
for (const entry of raw) {
|
|
90
|
+
if (!isObject(entry) || typeof entry.referrer !== "string")
|
|
91
|
+
continue;
|
|
92
|
+
const rewritten = rewrite(entry.referrer);
|
|
93
|
+
if (rewritten !== undefined)
|
|
94
|
+
entry.referrer = rewritten;
|
|
95
|
+
}
|
|
96
|
+
}
|
package/dist/release/index.d.ts
CHANGED
|
@@ -20,7 +20,7 @@ export { LOCALLY_DERIVED_LAYERS, MANIFEST_LAYER, diffLayerDigests, layerDigestKe
|
|
|
20
20
|
export type { LayerChange, LayerDigests } from "./payload-digest.js";
|
|
21
21
|
export { orderByImports, planRelease } from "./release-plan.js";
|
|
22
22
|
export type { ArtifactKind, BumpReason, ChangelogEntry, ModuleEvidence, PlannedModule, ReleaseDiagnostic, ReleaseEvidence, ReleasePlan, } from "./release-plan.js";
|
|
23
|
-
export { VersionStampError, readManifestVersion, stampCrateVersion, stampManifestVersion, stampPackageVersion, } from "./version-stamp.js";
|
|
23
|
+
export { VersionStampError, readManifestVersion, stampCrateVersion, stampManifestVersion, stampSelfNpmPins, stampPackageVersion, } from "./version-stamp.js";
|
|
24
24
|
export { WORKSPACE_FILENAME, WorkspaceConfigError, parseWorkspaceConfig } from "./workspace-config.js";
|
|
25
25
|
export type { WorkspaceConfig } from "./workspace-config.js";
|
|
26
26
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/release/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EACL,cAAc,EACd,mBAAmB,EACnB,SAAS,EACT,eAAe,EACf,cAAc,EACd,gBAAgB,EAChB,WAAW,EACX,QAAQ,GACT,MAAM,iBAAiB,CAAC;AACzB,YAAY,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/D,OAAO,EACL,gBAAgB,EAChB,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,gBAAgB,CAAC;AACxB,YAAY,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAEvD,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACpG,YAAY,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnG,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAEvD,OAAO,EACL,sBAAsB,EACtB,cAAc,EACd,gBAAgB,EAChB,cAAc,GACf,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAErE,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChE,YAAY,EACV,YAAY,EACZ,UAAU,EACV,cAAc,EACd,cAAc,EACd,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,WAAW,GACZ,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,iBAAiB,EACjB,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AACvG,YAAY,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/release/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EACL,cAAc,EACd,mBAAmB,EACnB,SAAS,EACT,eAAe,EACf,cAAc,EACd,gBAAgB,EAChB,WAAW,EACX,QAAQ,GACT,MAAM,iBAAiB,CAAC;AACzB,YAAY,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/D,OAAO,EACL,gBAAgB,EAChB,uBAAuB,EACvB,sBAAsB,GACvB,MAAM,gBAAgB,CAAC;AACxB,YAAY,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAEvD,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACpG,YAAY,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnG,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAEvD,OAAO,EACL,sBAAsB,EACtB,cAAc,EACd,gBAAgB,EAChB,cAAc,GACf,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAErE,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChE,YAAY,EACV,YAAY,EACZ,UAAU,EACV,cAAc,EACd,cAAc,EACd,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,WAAW,GACZ,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,iBAAiB,EACjB,oBAAoB,EACpB,gBAAgB,EAChB,mBAAmB,GACpB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AACvG,YAAY,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC"}
|
package/dist/release/index.js
CHANGED
|
@@ -14,5 +14,5 @@ export { FragmentError, normalizeModuleKey, parseFragment, serializeFragment } f
|
|
|
14
14
|
export { EMPTY_LEDGER, LEDGER_PATH, LedgerError, parseLedger, serializeLedger } from "./ledger.js";
|
|
15
15
|
export { LOCALLY_DERIVED_LAYERS, MANIFEST_LAYER, diffLayerDigests, layerDigestKey, } from "./payload-digest.js";
|
|
16
16
|
export { orderByImports, planRelease } from "./release-plan.js";
|
|
17
|
-
export { VersionStampError, readManifestVersion, stampCrateVersion, stampManifestVersion, stampPackageVersion, } from "./version-stamp.js";
|
|
17
|
+
export { VersionStampError, readManifestVersion, stampCrateVersion, stampManifestVersion, stampSelfNpmPins, stampPackageVersion, } from "./version-stamp.js";
|
|
18
18
|
export { WORKSPACE_FILENAME, WorkspaceConfigError, parseWorkspaceConfig } from "./workspace-config.js";
|
|
@@ -25,9 +25,13 @@ export declare const MANIFEST_LAYER = "manifest";
|
|
|
25
25
|
* Exactly one today, and for a structural reason rather than an omission: the
|
|
26
26
|
* published `layers:` index lives *inside* `telo.yaml`, so it cannot carry that
|
|
27
27
|
* file's own digest — the entry would have to be computed over bytes containing
|
|
28
|
-
* it.
|
|
29
|
-
*
|
|
30
|
-
*
|
|
28
|
+
* it. `readPublishedDigests` reads that index, so it has no answer for this key.
|
|
29
|
+
*
|
|
30
|
+
* It is no longer *unknowable*, though, only absent from the index: the payload
|
|
31
|
+
* builder now writes the index, so its manifest is the published text and this
|
|
32
|
+
* digest is what hashing the served `telo.yaml` yields. Reconciling it would
|
|
33
|
+
* mean fetching the manifest per module rather than reading one index — worth
|
|
34
|
+
* doing, and a separate change from the one that made it possible.
|
|
31
35
|
*
|
|
32
36
|
* It stays in the ledger regardless, because it is the only thing that sees a
|
|
33
37
|
* **manifest-only change**: a schema edit, a new kind, a description, a
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"payload-digest.d.ts","sourceRoot":"","sources":["../../src/release/payload-digest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAiB,KAAK,gBAAgB,EAAE,KAAK,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAE/F,sDAAsD;AACtD,MAAM,MAAM,YAAY,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AAE5D,yDAAyD;AACzD,eAAO,MAAM,cAAc,aAAa,CAAC;AAEzC
|
|
1
|
+
{"version":3,"file":"payload-digest.d.ts","sourceRoot":"","sources":["../../src/release/payload-digest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAiB,KAAK,gBAAgB,EAAE,KAAK,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAE/F,sDAAsD;AACtD,MAAM,MAAM,YAAY,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AAE5D,yDAAyD;AACzD,eAAO,MAAM,cAAc,aAAa,CAAC;AAEzC;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,sBAAsB,EAAE,WAAW,CAAC,MAAM,CAA6B,CAAC;AAErF;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,EAAE,QAAQ,CAAC,EAAE,gBAAgB,GAAG,MAAM,CAM5F;AAED;;;mBAGmB;AACnB,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;mCACmC;AACnC,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,YAAY,GAAG,WAAW,EAAE,CAQzF"}
|
|
@@ -23,9 +23,13 @@ export const MANIFEST_LAYER = "manifest";
|
|
|
23
23
|
* Exactly one today, and for a structural reason rather than an omission: the
|
|
24
24
|
* published `layers:` index lives *inside* `telo.yaml`, so it cannot carry that
|
|
25
25
|
* file's own digest — the entry would have to be computed over bytes containing
|
|
26
|
-
* it.
|
|
27
|
-
*
|
|
28
|
-
*
|
|
26
|
+
* it. `readPublishedDigests` reads that index, so it has no answer for this key.
|
|
27
|
+
*
|
|
28
|
+
* It is no longer *unknowable*, though, only absent from the index: the payload
|
|
29
|
+
* builder now writes the index, so its manifest is the published text and this
|
|
30
|
+
* digest is what hashing the served `telo.yaml` yields. Reconciling it would
|
|
31
|
+
* mean fetching the manifest per module rather than reading one index — worth
|
|
32
|
+
* doing, and a separate change from the one that made it possible.
|
|
29
33
|
*
|
|
30
34
|
* It stays in the ledger regardless, because it is the only thing that sees a
|
|
31
35
|
* **manifest-only change**: a schema edit, a new kind, a description, a
|
|
@@ -25,6 +25,22 @@ export declare class VersionStampError extends Error {
|
|
|
25
25
|
* of how many lines it was allowed to hit.
|
|
26
26
|
*/
|
|
27
27
|
export declare function stampManifestVersion(text: string, version: string, where: string): string | undefined;
|
|
28
|
+
/**
|
|
29
|
+
* `pkg:npm/<name>@<version>` candidates naming the module's OWN package.
|
|
30
|
+
*
|
|
31
|
+
* A module has one version, and its manifest pins the package it ships itself —
|
|
32
|
+
* so the pin has to move with the rest of it. Left behind, the manifest names a
|
|
33
|
+
* tarball older than the module describing it, which is exactly how an
|
|
34
|
+
* npm-delivered module came to point at a years-old version of itself.
|
|
35
|
+
*
|
|
36
|
+
* Anchored on the `controllers:` SCALARS the YAML actually holds, not on a free
|
|
37
|
+
* text match: this file's whole rule is find the scalar, splice its span, touch
|
|
38
|
+
* nothing else, and a bare regex over the document would also reach a PURL
|
|
39
|
+
* written in a description, an example or a comment. Matched by exact package
|
|
40
|
+
* name, so a PURL naming a DIFFERENT package — a real dependency, pinned
|
|
41
|
+
* deliberately — is untouched.
|
|
42
|
+
*/
|
|
43
|
+
export declare function stampSelfNpmPins(text: string, packageName: string, version: string, where?: string): string;
|
|
28
44
|
/** Read the module doc's `metadata.version` without rewriting it. */
|
|
29
45
|
export declare function readManifestVersion(text: string): string | undefined;
|
|
30
46
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version-stamp.d.ts","sourceRoot":"","sources":["../../src/release/version-stamp.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAMH,qBAAa,iBAAkB,SAAQ,KAAK;CAAG;AAqB/C;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,GACZ,MAAM,GAAG,SAAS,CAYpB;AAED,qEAAqE;AACrE,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAMpE;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,GACZ,MAAM,GAAG,SAAS,CAKpB;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,GACZ,MAAM,GAAG,SAAS,CA+BpB"}
|
|
1
|
+
{"version":3,"file":"version-stamp.d.ts","sourceRoot":"","sources":["../../src/release/version-stamp.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAMH,qBAAa,iBAAkB,SAAQ,KAAK;CAAG;AAqB/C;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,GACZ,MAAM,GAAG,SAAS,CAYpB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EACf,KAAK,SAAgB,GACpB,MAAM,CAoCR;AAED,qEAAqE;AACrE,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAMpE;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,GACZ,MAAM,GAAG,SAAS,CAKpB;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,GACZ,MAAM,GAAG,SAAS,CA+BpB"}
|
|
@@ -56,6 +56,58 @@ export function stampManifestVersion(text, version, where) {
|
|
|
56
56
|
return undefined;
|
|
57
57
|
return spliceScalar(text, node, version, where);
|
|
58
58
|
}
|
|
59
|
+
/**
|
|
60
|
+
* `pkg:npm/<name>@<version>` candidates naming the module's OWN package.
|
|
61
|
+
*
|
|
62
|
+
* A module has one version, and its manifest pins the package it ships itself —
|
|
63
|
+
* so the pin has to move with the rest of it. Left behind, the manifest names a
|
|
64
|
+
* tarball older than the module describing it, which is exactly how an
|
|
65
|
+
* npm-delivered module came to point at a years-old version of itself.
|
|
66
|
+
*
|
|
67
|
+
* Anchored on the `controllers:` SCALARS the YAML actually holds, not on a free
|
|
68
|
+
* text match: this file's whole rule is find the scalar, splice its span, touch
|
|
69
|
+
* nothing else, and a bare regex over the document would also reach a PURL
|
|
70
|
+
* written in a description, an example or a comment. Matched by exact package
|
|
71
|
+
* name, so a PURL naming a DIFFERENT package — a real dependency, pinned
|
|
72
|
+
* deliberately — is untouched.
|
|
73
|
+
*/
|
|
74
|
+
export function stampSelfNpmPins(text, packageName, version, where = "controllers") {
|
|
75
|
+
const docs = parseAllDocuments(text, { customTags: defaultCustomTags() });
|
|
76
|
+
const prefix = `pkg:npm/${packageName}@`;
|
|
77
|
+
const edits = [];
|
|
78
|
+
for (const doc of docs) {
|
|
79
|
+
const controllers = doc.get("controllers", true);
|
|
80
|
+
const items = controllers?.items;
|
|
81
|
+
if (!Array.isArray(items))
|
|
82
|
+
continue;
|
|
83
|
+
for (const item of items) {
|
|
84
|
+
if (!isScalar(item) || typeof item.value !== "string")
|
|
85
|
+
continue;
|
|
86
|
+
const purl = item.value;
|
|
87
|
+
if (!purl.startsWith(prefix))
|
|
88
|
+
continue;
|
|
89
|
+
// Everything from the version up to the first qualifier or fragment is the
|
|
90
|
+
// pin; the rest of the PURL (`?local_path=…#Export`) is carried through.
|
|
91
|
+
const rest = purl.slice(prefix.length);
|
|
92
|
+
const tail = rest.search(/[?#]/);
|
|
93
|
+
const rewritten = `${prefix}${version}${tail === -1 ? "" : rest.slice(tail)}`;
|
|
94
|
+
if (rewritten === purl)
|
|
95
|
+
continue;
|
|
96
|
+
const range = item.range;
|
|
97
|
+
if (!range) {
|
|
98
|
+
throw new VersionStampError(`${where}: a controller PURL carries no source range.`);
|
|
99
|
+
}
|
|
100
|
+
const [start, end] = range;
|
|
101
|
+
const replacement = renderFixReplacement(text.slice(start, end), rewritten);
|
|
102
|
+
if (replacement === undefined) {
|
|
103
|
+
throw new VersionStampError(`${where}: the controller PURL '${purl}' cannot be rewritten in place. ` +
|
|
104
|
+
`Write it as a plain or quoted scalar on one line.`);
|
|
105
|
+
}
|
|
106
|
+
edits.push({ start, end, newText: replacement });
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return edits.length === 0 ? text : applyTextEdits(text, edits);
|
|
110
|
+
}
|
|
59
111
|
/** Read the module doc's `metadata.version` without rewriting it. */
|
|
60
112
|
export function readManifestVersion(text) {
|
|
61
113
|
const docs = parseAllDocuments(text, { customTags: defaultCustomTags() });
|
|
@@ -8,12 +8,16 @@
|
|
|
8
8
|
* would read every example and every cached `.telo/manifests` copy as a released
|
|
9
9
|
* module).
|
|
10
10
|
*
|
|
11
|
-
* The file is **optional and
|
|
12
|
-
* `
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
11
|
+
* The file is **optional**, and everything reading it is harmless without one.
|
|
12
|
+
* `telo release` requires one. `telo run` uses its LOCATION — never `modules:`,
|
|
13
|
+
* which is release scope — as the bound on the walk-up that collects `.env` /
|
|
14
|
+
* `.env.local`, and with no marker reads the manifest's own directory alone, as
|
|
15
|
+
* it did before this file existed; a bound is what keeps that walk out of a
|
|
16
|
+
* user's home directory. Nothing else — not `check`, `publish`, `install`,
|
|
17
|
+
* `upgrade`, `migrate`, `module`, and not the kernel — looks for it, so a
|
|
18
|
+
* single-manifest repo, a bare `examples/` directory and a third-party module
|
|
19
|
+
* checkout keep working with nothing added. Any field added later must be true
|
|
20
|
+
* of the whole tree, not derivable from it, and harmless by its absence.
|
|
17
21
|
*
|
|
18
22
|
* Parsing lives here, in the browser-safe half, because the editor answers
|
|
19
23
|
* "what does changing this library bump?" from the same model. Finding the file
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspace-config.d.ts","sourceRoot":"","sources":["../../src/release/workspace-config.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"workspace-config.d.ts","sourceRoot":"","sources":["../../src/release/workspace-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAIH,eAAO,MAAM,kBAAkB,wBAAwB,CAAC;AAExD,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;CACrC;AAED,qBAAa,oBAAqB,SAAQ,KAAK;CAAG;AAElD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,eAAe,CAoCjF"}
|
|
@@ -8,12 +8,16 @@
|
|
|
8
8
|
* would read every example and every cached `.telo/manifests` copy as a released
|
|
9
9
|
* module).
|
|
10
10
|
*
|
|
11
|
-
* The file is **optional and
|
|
12
|
-
* `
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
11
|
+
* The file is **optional**, and everything reading it is harmless without one.
|
|
12
|
+
* `telo release` requires one. `telo run` uses its LOCATION — never `modules:`,
|
|
13
|
+
* which is release scope — as the bound on the walk-up that collects `.env` /
|
|
14
|
+
* `.env.local`, and with no marker reads the manifest's own directory alone, as
|
|
15
|
+
* it did before this file existed; a bound is what keeps that walk out of a
|
|
16
|
+
* user's home directory. Nothing else — not `check`, `publish`, `install`,
|
|
17
|
+
* `upgrade`, `migrate`, `module`, and not the kernel — looks for it, so a
|
|
18
|
+
* single-manifest repo, a bare `examples/` directory and a third-party module
|
|
19
|
+
* checkout keep working with nothing added. Any field added later must be true
|
|
20
|
+
* of the whole tree, not derivable from it, and harmless by its absence.
|
|
17
21
|
*
|
|
18
22
|
* Parsing lives here, in the browser-safe half, because the editor answers
|
|
19
23
|
* "what does changing this library bump?" from the same model. Finding the file
|
|
@@ -21,9 +21,10 @@ export interface RefConstraintIssue {
|
|
|
21
21
|
manifest: ResourceManifest;
|
|
22
22
|
reason: RefConstraintReason;
|
|
23
23
|
/** Which annotation carried the unresolved name: an `x-telo-ref` constraint
|
|
24
|
-
* (the default)
|
|
25
|
-
*
|
|
26
|
-
|
|
24
|
+
* (the default), an `x-telo-requires-zone` provider kind, or an
|
|
25
|
+
* `x-telo-referrer-rules` `referrer:` filter — the caller reports those as
|
|
26
|
+
* ZONE_PROVIDER_UNRESOLVED and REFERRER_RULE_INVALID. */
|
|
27
|
+
annotation?: "ref" | "zone" | "referrer";
|
|
27
28
|
/** For `gated`: the target module and the kinds it does export. */
|
|
28
29
|
gate?: {
|
|
29
30
|
module: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve-schema-ref-kinds.d.ts","sourceRoot":"","sources":["../src/resolve-schema-ref-kinds.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"resolve-schema-ref-kinds.d.ts","sourceRoot":"","sources":["../src/resolve-schema-ref-kinds.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAWzD;;;;;;;;sDAQsD;AACtD,MAAM,MAAM,mBAAmB,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,CAAC;AAEjE,4DAA4D;AAC5D,MAAM,WAAW,kBAAkB;IACjC,iDAAiD;IACjD,GAAG,EAAE,MAAM,CAAC;IACZ;sFACkF;IAClF,IAAI,EAAE,MAAM,CAAC;IACb,0EAA0E;IAC1E,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,MAAM,EAAE,mBAAmB,CAAC;IAC5B;;;8DAG0D;IAC1D,UAAU,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,UAAU,CAAC;IACzC,mEAAmE;IACnE,IAAI,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAC9C;+BAC2B;IAC3B,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,sFAAsF;AACtF,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAExD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,qBAAqB,CACnC,UAAU,EAAE,gBAAgB,EAC5B,QAAQ,EAAE,IAAI,CAAC,aAAa,EAAE,mBAAmB,GAAG,cAAc,CAAC,GAClE,kBAAkB,EAAE,CAwFtB"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { rewriteRefSlotKinds } from "./ref-slot.js";
|
|
2
|
+
import { REFERRER_RULES_ANNOTATION, hasReferrerRules, rewriteReferrerRuleKinds, } from "./referrer-rule.js";
|
|
2
3
|
import { hasRequiresZone, rewriteRequiresZoneKind } from "./zone-slot.js";
|
|
3
4
|
const REF_ANNOTATION = "x-telo-ref";
|
|
4
5
|
/** True for the legacy identity form, which is split on `#` by the identity table. */
|
|
@@ -95,6 +96,21 @@ export function resolveSchemaRefKinds(definition, resolver) {
|
|
|
95
96
|
return undefined;
|
|
96
97
|
});
|
|
97
98
|
}
|
|
99
|
+
if (hasReferrerRules(obj)) {
|
|
100
|
+
// A referrer rule's `referrer:` filter names a kind through the identical
|
|
101
|
+
// alias-qualified grammar, resolved in the same declaring scope — so the
|
|
102
|
+
// evaluation pass compares canonical kinds and never has to know which
|
|
103
|
+
// alias the CONSUMER happened to import the kind under. That is the whole
|
|
104
|
+
// reason such a rule can be sound where the same test written on the
|
|
105
|
+
// referring kind cannot.
|
|
106
|
+
rewriteReferrerRuleKinds(obj, (kind) => {
|
|
107
|
+
const result = resolver.resolveKindResult(kind);
|
|
108
|
+
if (result.status === "ok")
|
|
109
|
+
return result.kind;
|
|
110
|
+
record(kind, `${path}.${REFERRER_RULES_ANNOTATION}`, "referrer");
|
|
111
|
+
return undefined;
|
|
112
|
+
});
|
|
113
|
+
}
|
|
98
114
|
for (const key of Object.keys(obj)) {
|
|
99
115
|
walk(obj[key], path ? `${path}.${key}` : key);
|
|
100
116
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve-throws-union.d.ts","sourceRoot":"","sources":["../src/resolve-throws-union.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAsB,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEzE,OAAO,EAA0B,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACjF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"resolve-throws-union.d.ts","sourceRoot":"","sources":["../src/resolve-throws-union.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAsB,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEzE,OAAO,EAA0B,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACjF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAGnE,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC5B;AAED;;gFAEgF;AAChF,eAAO,MAAM,gBAAgB,mBAAmB,CAAC;AAEjD,MAAM,WAAW,WAAW;IAC1B,gFAAgF;IAChF,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IACnC;;;8EAG0E;IAC1E,SAAS,EAAE,OAAO,CAAC;IACnB;;;;gDAI4C;IAC5C,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,UAAU;IACzB,YAAY,EAAE,gBAAgB,EAAE,CAAC;IACjC,IAAI,EAAE,kBAAkB,CAAC;IACzB,OAAO,EAAE,aAAa,CAAC;IACvB;;;wFAGoF;IACpF,eAAe,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IAC5C,0FAA0F;IAC1F,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACzB,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAC/B,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACzB;AAED,wBAAgB,gBAAgB,CAC9B,YAAY,EAAE,gBAAgB,EAAE,EAChC,IAAI,EAAE,kBAAkB,EACxB,OAAO,EAAE,aAAa,EACtB,eAAe,GAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAa,EACvD,WAAW,GAAE,GAAG,CAAC,MAAM,CAAa,GACnC,UAAU,CAUZ;AA6CD;;;;8CAI8C;AAC9C,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,gBAAgB,EAC1B,GAAG,EAAE,UAAU,GACd,WAAW,CAiDb"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { isTaggedSentinel } from "@telorun/templating";
|
|
2
2
|
import { scopeResolverForModule } from "./alias-resolver.js";
|
|
3
|
+
import { readStepSlot } from "./step-slot.js";
|
|
3
4
|
/** Code a non-`InvokeError` failure surfaces as inside a `catch` block. Mirrors
|
|
4
5
|
* `PLAIN_ERROR_CODE` in `@telorun/run`'s `toSequenceError`: any invoke can throw
|
|
5
6
|
* a plain error, which the catch sees as `error.code === "INTERNAL_ERROR"`. */
|
|
@@ -114,8 +115,8 @@ function resolveInherited(manifest, definition, ctx, ownerModule) {
|
|
|
114
115
|
if (!props)
|
|
115
116
|
return result;
|
|
116
117
|
for (const [fieldName, fieldSchema] of Object.entries(props)) {
|
|
117
|
-
const stepCtx = fieldSchema
|
|
118
|
-
if (!stepCtx
|
|
118
|
+
const stepCtx = readStepSlot(fieldSchema);
|
|
119
|
+
if (!stepCtx)
|
|
119
120
|
continue;
|
|
120
121
|
const steps = manifest[fieldName];
|
|
121
122
|
if (!Array.isArray(steps))
|
|
@@ -136,7 +137,7 @@ function collectStepArrayThrows(steps, invokeField, enclosingTryCodes, ctx, owne
|
|
|
136
137
|
/** Walk one step, dispatching by shape. Generic for any Run.Sequence-style
|
|
137
138
|
* composer: the step keys it recognises (`try` / `catch` / `finally` / `then`
|
|
138
139
|
* / `else` / `elseif` / `do` / `cases` / `default`) are the same set already
|
|
139
|
-
* traversed by the analyzer's
|
|
140
|
+
* traversed by the analyzer's step-body walk, so future
|
|
140
141
|
* composers that reuse those shape conventions work without changes here. */
|
|
141
142
|
function collectStepThrows(step, invokeField, enclosingTryCodes, ctx, ownerModule) {
|
|
142
143
|
if (step[invokeField]) {
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Zone containment — *what is inside this zone*, which is the opposite question
|
|
3
|
+
* from the one `resolve-zone-requirements.ts` answers.
|
|
4
|
+
*
|
|
5
|
+
* The landed projection propagates a requirement callee→caller and asks *is this
|
|
6
|
+
* requirement satisfied*. Every check built on zone ATTRIBUTES asks the reverse:
|
|
7
|
+
* a `noSuspend` region has to know what it contains before it can forbid parking
|
|
8
|
+
* inside it, a `replayed` region before it can reject a detached dispatch, an
|
|
9
|
+
* `idempotent` region before it can call impure CEL a broken promise. So this is
|
|
10
|
+
* a DOWNWARD walk from a providing slot to everything its body reaches.
|
|
11
|
+
*
|
|
12
|
+
* It is a second consumer of the shared call graph, not a second graph, and it
|
|
13
|
+
* is **parameterized over the attribute that opens the region** — so the durable
|
|
14
|
+
* zone (`replayed`) and the constraint zones (`noSuspend`, `atomic`,
|
|
15
|
+
* `idempotent`) share one traversal. It resolves an attribute NAME and nothing
|
|
16
|
+
* else: no kind is named here, which is what keeps `modules/durable` out of the
|
|
17
|
+
* analyzer's surface and satisfies the topology-driven constraint.
|
|
18
|
+
*
|
|
19
|
+
* **Two shapes of body slot, one region.** A slot may hold its body as a
|
|
20
|
+
* reference to an executable (`Sql.Transaction.steps`) or carry a step array
|
|
21
|
+
* natively (the shared `Step` fragment, which any kind may point at). Both are
|
|
22
|
+
* regions; the first is entered through the slot's edge, the second through the
|
|
23
|
+
* step nodes the slot declares. Handling only the first would have made the
|
|
24
|
+
* checks silently vacuous on exactly the kinds written after the grammar became
|
|
25
|
+
* shared vocabulary.
|
|
26
|
+
*
|
|
27
|
+
* **The walk under-approximates, and that is the safe direction — for a CHECK.**
|
|
28
|
+
* A dynamically dispatched edge is invisible here, so a check over the result
|
|
29
|
+
* may stay silent where it should have spoken, and the runtime enforcement is
|
|
30
|
+
* what closes it. A consumer at the OPPOSITE polarity — the durable manifest
|
|
31
|
+
* digest, whose blind spot is silent replay against changed code rather than a
|
|
32
|
+
* missed diagnostic — must not inherit this tolerance, and verifies its coverage
|
|
33
|
+
* against the journal instead of trusting this set.
|
|
34
|
+
*
|
|
35
|
+
* Browser-safe: no Node built-ins.
|
|
36
|
+
*/
|
|
37
|
+
import type { ResourceDefinition, ResourceManifest } from "@telorun/sdk";
|
|
38
|
+
import type { CallGraph, CallGraphEdge, CallGraphNode, ResourceGraphNode } from "./call-graph.js";
|
|
39
|
+
/** One node the region reaches, with the route taken to it. */
|
|
40
|
+
export interface ContainedNode {
|
|
41
|
+
node: CallGraphNode;
|
|
42
|
+
/** Labels of the hops from the body slot to this node, for a diagnostic that
|
|
43
|
+
* names the path rather than only the endpoint. */
|
|
44
|
+
via: string[];
|
|
45
|
+
}
|
|
46
|
+
/** A dispatch that leaves the region without extending it.
|
|
47
|
+
*
|
|
48
|
+
* Recorded rather than followed, because the two facts are different and both
|
|
49
|
+
* are wanted: the zone's lifetime does NOT reach the target (so nothing inside
|
|
50
|
+
* it is contained), while the dispatch itself is a site inside the region that
|
|
51
|
+
* a check may forbid outright — `DURABLE_DETACH_FORBIDDEN` is exactly that. */
|
|
52
|
+
export interface RegionBoundary {
|
|
53
|
+
edge: CallGraphEdge;
|
|
54
|
+
/** The resource whose slot dispatches this way. */
|
|
55
|
+
from: ResourceGraphNode;
|
|
56
|
+
via: string[];
|
|
57
|
+
/** Why the zone stops here: the uses that do not extend it. */
|
|
58
|
+
escaping: string[];
|
|
59
|
+
}
|
|
60
|
+
/** A region opened by one providing slot carrying the requested attribute. */
|
|
61
|
+
export interface ZoneRegion {
|
|
62
|
+
/** The attribute that opened it — the one the walk was asked for. */
|
|
63
|
+
attribute: string;
|
|
64
|
+
/** The author's reason, quoted verbatim by every diagnostic over this region.
|
|
65
|
+
* Present by construction: an attribute's value IS the reason. */
|
|
66
|
+
reason: string;
|
|
67
|
+
/** The resource whose slot establishes the zone. */
|
|
68
|
+
provider: ResourceGraphNode;
|
|
69
|
+
/** Field-map path of the body slot (`steps`, `invoke`). */
|
|
70
|
+
slot: string;
|
|
71
|
+
/** Every attribute the slot declares, not only the requested one — a consumer
|
|
72
|
+
* deciding collapse reads `atomic` and `idempotent` off one region. */
|
|
73
|
+
attributes: Readonly<Record<string, string>>;
|
|
74
|
+
/** Everything control reaches from the body, keyed by node id. Includes the
|
|
75
|
+
* step nodes of a native body, since a step is where a check anchors. */
|
|
76
|
+
contents: ReadonlyMap<string, ContainedNode>;
|
|
77
|
+
/** Dispatches inside the region that the zone does not extend through. */
|
|
78
|
+
boundaries: readonly RegionBoundary[];
|
|
79
|
+
}
|
|
80
|
+
/** Resolves a kind name to its definition in the scope of the module that
|
|
81
|
+
* DECLARED it — the same resolver the projection takes, passed in rather than
|
|
82
|
+
* rebuilt so both walks agree about what a kind means. */
|
|
83
|
+
export type DefinitionLookup = (kind: string, module?: string) => ResourceDefinition | undefined;
|
|
84
|
+
/**
|
|
85
|
+
* Every region in the graph opened by a slot declaring `attribute`.
|
|
86
|
+
*
|
|
87
|
+
* The provider itself is NOT in `contents` — a zone constrains what runs inside
|
|
88
|
+
* its body, not the resource that establishes it. A transaction's own
|
|
89
|
+
* `connection:` dependency is outside the region it opens, and a rule that
|
|
90
|
+
* treated the provider as contained would report the provider against its own
|
|
91
|
+
* constraint.
|
|
92
|
+
*/
|
|
93
|
+
export declare function findZoneRegions(graph: CallGraph, resolveDef: DefinitionLookup, attribute: string): ZoneRegion[];
|
|
94
|
+
/** Convenience for a consumer that only wants membership: every node id inside
|
|
95
|
+
* any region opened by `attribute`, mapped to the region that contains it. */
|
|
96
|
+
export declare function containmentIndex(regions: readonly ZoneRegion[]): ReadonlyMap<string, ZoneRegion>;
|
|
97
|
+
/** The manifests a region's contents belong to — what a diagnostic anchors on. */
|
|
98
|
+
export declare function regionManifests(region: ZoneRegion): ResourceManifest[];
|
|
99
|
+
//# sourceMappingURL=resolve-zone-containment.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve-zone-containment.d.ts","sourceRoot":"","sources":["../src/resolve-zone-containment.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,OAAO,KAAK,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACzE,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAKlG,+DAA+D;AAC/D,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,aAAa,CAAC;IACpB;wDACoD;IACpD,GAAG,EAAE,MAAM,EAAE,CAAC;CACf;AAED;;;;;gFAKgF;AAChF,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,aAAa,CAAC;IACpB,mDAAmD;IACnD,IAAI,EAAE,iBAAiB,CAAC;IACxB,GAAG,EAAE,MAAM,EAAE,CAAC;IACd,+DAA+D;IAC/D,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,8EAA8E;AAC9E,MAAM,WAAW,UAAU;IACzB,qEAAqE;IACrE,SAAS,EAAE,MAAM,CAAC;IAClB;uEACmE;IACnE,MAAM,EAAE,MAAM,CAAC;IACf,oDAAoD;IACpD,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,2DAA2D;IAC3D,IAAI,EAAE,MAAM,CAAC;IACb;4EACwE;IACxE,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC7C;8EAC0E;IAC1E,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IAC7C,0EAA0E;IAC1E,UAAU,EAAE,SAAS,cAAc,EAAE,CAAC;CACvC;AAED;;2DAE2D;AAC3D,MAAM,MAAM,gBAAgB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,kBAAkB,GAAG,SAAS,CAAC;AA4GjG;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,SAAS,EAChB,UAAU,EAAE,gBAAgB,EAC5B,SAAS,EAAE,MAAM,GAChB,UAAU,EAAE,CA6Dd;AAoCD;+EAC+E;AAC/E,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,SAAS,UAAU,EAAE,GAC7B,WAAW,CAAC,MAAM,EAAE,UAAU,CAAC,CAQjC;AAED,kFAAkF;AAClF,wBAAgB,eAAe,CAAC,MAAM,EAAE,UAAU,GAAG,gBAAgB,EAAE,CAMtE"}
|