@telorun/analyzer 0.68.0 → 0.69.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 +12 -0
- package/dist/analysis-registry.d.ts.map +1 -1
- package/dist/analysis-registry.js +26 -0
- package/dist/call-graph.d.ts +80 -1
- package/dist/call-graph.d.ts.map +1 -1
- package/dist/call-graph.js +145 -12
- package/dist/import-resolution-diagnostics.d.ts.map +1 -1
- package/dist/import-resolution-diagnostics.js +22 -8
- package/dist/index.d.ts +4 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -4
- package/dist/loaded-types.d.ts +4 -4
- package/dist/loaded-types.d.ts.map +1 -1
- package/dist/manifest-analysis.d.ts +19 -0
- package/dist/manifest-analysis.d.ts.map +1 -1
- package/dist/manifest-analysis.js +27 -0
- package/dist/manifest-loader.d.ts +3 -4
- package/dist/manifest-loader.d.ts.map +1 -1
- package/dist/manifest-loader.js +4 -5
- package/dist/manifest-schemas.d.ts +2 -0
- package/dist/manifest-schemas.d.ts.map +1 -1
- package/dist/manifest-schemas.js +4 -0
- package/dist/module-graph.d.ts +500 -0
- package/dist/module-graph.d.ts.map +1 -0
- package/dist/module-graph.js +1411 -0
- package/dist/reconcile-module-versions.d.ts.map +1 -1
- package/dist/reconcile-module-versions.js +10 -11
- package/dist/release/release-plan.d.ts +1 -1
- package/dist/resolve-zone-containment.d.ts +9 -1
- package/dist/resolve-zone-containment.d.ts.map +1 -1
- package/dist/resolve-zone-containment.js +34 -6
- package/dist/resolve-zone-requirements.d.ts.map +1 -1
- package/dist/resolve-zone-requirements.js +4 -2
- package/dist/sources/default-sources.d.ts +6 -6
- package/dist/sources/default-sources.d.ts.map +1 -1
- package/dist/sources/default-sources.js +7 -8
- package/dist/sources/integrity.d.ts +3 -2
- package/dist/sources/integrity.d.ts.map +1 -1
- package/dist/sources/integrity.js +26 -3
- package/dist/sources/versioned-ref.d.ts +17 -12
- package/dist/sources/versioned-ref.d.ts.map +1 -1
- package/dist/sources/versioned-ref.js +22 -24
- package/dist/telo-version.d.ts +1 -1
- package/dist/telo-version.js +1 -1
- package/package.json +1 -1
- package/src/analysis-registry.ts +37 -0
- package/src/call-graph.ts +207 -14
- package/src/import-resolution-diagnostics.ts +24 -7
- package/src/index.ts +38 -5
- package/src/loaded-types.ts +4 -4
- package/src/manifest-analysis.ts +39 -0
- package/src/manifest-loader.ts +4 -5
- package/src/manifest-schemas.ts +4 -0
- package/src/module-graph.ts +2005 -0
- package/src/reconcile-module-versions.ts +10 -11
- package/src/release/release-plan.ts +1 -1
- package/src/resolve-zone-containment.ts +49 -9
- package/src/resolve-zone-requirements.ts +7 -2
- package/src/sources/default-sources.ts +7 -8
- package/src/sources/integrity.ts +28 -3
- package/src/sources/versioned-ref.ts +26 -28
- package/src/telo-version.ts +1 -1
- package/dist/sources/module-ref.d.ts +0 -21
- package/dist/sources/module-ref.d.ts.map +0 -1
- package/dist/sources/module-ref.js +0 -36
- package/dist/sources/registry-source.d.ts +0 -14
- package/dist/sources/registry-source.d.ts.map +0 -1
- package/dist/sources/registry-source.js +0 -45
- package/src/sources/module-ref.ts +0 -49
- package/src/sources/registry-source.ts +0 -52
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reconcile-module-versions.d.ts","sourceRoot":"","sources":["../src/reconcile-module-versions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAOlE,OAAO,EAAsB,KAAK,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAIzE;;;;0CAI0C;AAC1C,MAAM,WAAW,qBAAqB;IACpC,gEAAgE;IAChE,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B;2EACuE;IACvE,WAAW,EAAE,kBAAkB,EAAE,CAAC;CACnC;
|
|
1
|
+
{"version":3,"file":"reconcile-module-versions.d.ts","sourceRoot":"","sources":["../src/reconcile-module-versions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAOlE,OAAO,EAAsB,KAAK,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAIzE;;;;0CAI0C;AAC1C,MAAM,WAAW,qBAAqB;IACpC,gEAAgE;IAChE,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B;2EACuE;IACvE,WAAW,EAAE,kBAAkB,EAAE,CAAC;CACnC;AA+ID;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,EAClC,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,GAChD,qBAAqB,CAsEvB"}
|
|
@@ -19,15 +19,14 @@ const SOURCE = "telo-analyzer";
|
|
|
19
19
|
* **What this key cannot relate.** It compares ref *spellings*, so it groups by
|
|
20
20
|
* origin exactly and nothing else. Two consequences, both accepted:
|
|
21
21
|
*
|
|
22
|
-
* - A module imported once by
|
|
23
|
-
* groups, so a version skew between them is not hoisted. Keying on what
|
|
24
|
-
* module declares about itself would catch that case, but only by
|
|
25
|
-
* self-declared identity — which is what this change removes, and
|
|
26
|
-
* cannot tell two same-named modules from different origins apart.
|
|
27
|
-
* -
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
* function does not have. */
|
|
22
|
+
* - A module imported once by an `oci://` ref and once by a relative path is
|
|
23
|
+
* two groups, so a version skew between them is not hoisted. Keying on what
|
|
24
|
+
* the module declares about itself would catch that case, but only by
|
|
25
|
+
* trusting a self-declared identity — which is what this change removes, and
|
|
26
|
+
* which cannot tell two same-named modules from different origins apart.
|
|
27
|
+
* - An `oci://` ref and a direct `https://…/telo.yaml` URL serving the same
|
|
28
|
+
* module are two groups. Relating them needs knowledge of the origin's
|
|
29
|
+
* layout, which this pure, browser-safe function does not have. */
|
|
31
30
|
function refIdentity(ref) {
|
|
32
31
|
const base = ref.split("#")[0];
|
|
33
32
|
if (!base || base.startsWith(".") || base.startsWith("/") || base.startsWith("file:")) {
|
|
@@ -137,8 +136,8 @@ export function reconcileModuleVersions(modules, importEdges) {
|
|
|
137
136
|
// source normally maps to exactly one identity; the entry module has no
|
|
138
137
|
// inbound edge and needs none (it is never reconciled against itself).
|
|
139
138
|
//
|
|
140
|
-
// One source CAN be reached by two spellings of the same location (a
|
|
141
|
-
//
|
|
139
|
+
// One source CAN be reached by two spellings of the same location (a ref and
|
|
140
|
+
// the direct URL it resolves to). Both name the same module
|
|
142
141
|
// at the same version, so either identity groups it correctly — but the choice
|
|
143
142
|
// must not depend on edge iteration order, or the same graph could reconcile
|
|
144
143
|
// differently across runs. First edge wins.
|
|
@@ -51,7 +51,7 @@ export interface ModuleEvidence {
|
|
|
51
51
|
readonly inlines: ReadonlyMap<ModuleKey, readonly string[]>;
|
|
52
52
|
/**
|
|
53
53
|
* Modules reached by an in-repo **relative** `imports:` source. A pinned
|
|
54
|
-
*
|
|
54
|
+
* remote ref is deliberately not an edge: pinning is the statement "I am not
|
|
55
55
|
* affected until I choose to be", and moving it is `telo upgrade`'s job.
|
|
56
56
|
*/
|
|
57
57
|
readonly imports: readonly ModuleKey[];
|
|
@@ -81,8 +81,15 @@ export interface ZoneRegion {
|
|
|
81
81
|
* DECLARED it — the same resolver the projection takes, passed in rather than
|
|
82
82
|
* rebuilt so both walks agree about what a kind means. */
|
|
83
83
|
export type DefinitionLookup = (kind: string, module?: string) => ResourceDefinition | undefined;
|
|
84
|
+
/** A region as the WALK finds it, before any attribute is asked for: the slot
|
|
85
|
+
* that opens it and everything it reaches. Every attribute query is a filter
|
|
86
|
+
* over these, so a consumer wanting regions regardless of what they declare —
|
|
87
|
+
* an editor drawing the enclosure, where a zone declaring no attribute is
|
|
88
|
+
* still a zone — reads them directly instead of enumerating the vocabulary and
|
|
89
|
+
* silently missing whatever is not in it. */
|
|
90
|
+
export type ZoneProvider = Omit<ZoneRegion, "attribute" | "reason">;
|
|
84
91
|
/**
|
|
85
|
-
* Every region in the graph
|
|
92
|
+
* Every region in the graph, keyed by the slot that opens it.
|
|
86
93
|
*
|
|
87
94
|
* The provider itself is NOT in `contents` — a zone constrains what runs inside
|
|
88
95
|
* its body, not the resource that establishes it. A transaction's own
|
|
@@ -90,6 +97,7 @@ export type DefinitionLookup = (kind: string, module?: string) => ResourceDefini
|
|
|
90
97
|
* treated the provider as contained would report the provider against its own
|
|
91
98
|
* constraint.
|
|
92
99
|
*/
|
|
100
|
+
export declare function findZoneProviders(graph: CallGraph, resolveDef: DefinitionLookup): ZoneProvider[];
|
|
93
101
|
export declare function findZoneRegions(graph: CallGraph, resolveDef: DefinitionLookup, attribute: string): ZoneRegion[];
|
|
94
102
|
/** Convenience for a consumer that only wants membership: every node id inside
|
|
95
103
|
* any region opened by `attribute`, mapped to the region that contains it. */
|
|
@@ -1 +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,
|
|
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;;;;;8CAK8C;AAC9C,MAAM,MAAM,YAAY,GAAG,IAAI,CAAC,UAAU,EAAE,WAAW,GAAG,QAAQ,CAAC,CAAC;AAEpE;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,SAAS,EAChB,UAAU,EAAE,gBAAgB,GAC3B,YAAY,EAAE,CA0DhB;AAmBD,wBAAgB,eAAe,CAC7B,KAAK,EAAE,SAAS,EAChB,UAAU,EAAE,gBAAgB,EAC5B,SAAS,EAAE,MAAM,GAChB,UAAU,EAAE,CAad;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"}
|
|
@@ -91,7 +91,7 @@ function collect(graph, entries, contents, boundaries) {
|
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
93
|
/**
|
|
94
|
-
* Every region in the graph
|
|
94
|
+
* Every region in the graph, keyed by the slot that opens it.
|
|
95
95
|
*
|
|
96
96
|
* The provider itself is NOT in `contents` — a zone constrains what runs inside
|
|
97
97
|
* its body, not the resource that establishes it. A transaction's own
|
|
@@ -99,7 +99,7 @@ function collect(graph, entries, contents, boundaries) {
|
|
|
99
99
|
* treated the provider as contained would report the provider against its own
|
|
100
100
|
* constraint.
|
|
101
101
|
*/
|
|
102
|
-
export function
|
|
102
|
+
export function findZoneProviders(graph, resolveDef) {
|
|
103
103
|
const regions = [];
|
|
104
104
|
for (const node of graph.nodes.values()) {
|
|
105
105
|
if (node.type !== "resource")
|
|
@@ -112,8 +112,7 @@ export function findZoneRegions(graph, resolveDef, attribute) {
|
|
|
112
112
|
// properties rather than by knowing any kind's field names.
|
|
113
113
|
for (const [slot, slotSchema] of providingSlots(rootSchema)) {
|
|
114
114
|
const provides = readProvidesZone(slotSchema);
|
|
115
|
-
|
|
116
|
-
if (!provides || typeof reason !== "string")
|
|
115
|
+
if (!provides)
|
|
117
116
|
continue;
|
|
118
117
|
const contents = new Map();
|
|
119
118
|
const boundaries = [];
|
|
@@ -147,8 +146,6 @@ export function findZoneRegions(graph, resolveDef, attribute) {
|
|
|
147
146
|
collect(graph, entries, contents, boundaries);
|
|
148
147
|
}
|
|
149
148
|
regions.push({
|
|
150
|
-
attribute,
|
|
151
|
-
reason,
|
|
152
149
|
provider: node,
|
|
153
150
|
slot,
|
|
154
151
|
attributes: provides.attributes,
|
|
@@ -159,6 +156,37 @@ export function findZoneRegions(graph, resolveDef, attribute) {
|
|
|
159
156
|
}
|
|
160
157
|
return regions;
|
|
161
158
|
}
|
|
159
|
+
/**
|
|
160
|
+
* Every region opened by a slot declaring `attribute`.
|
|
161
|
+
*
|
|
162
|
+
* A filter over {@link findZoneProviders}, so the walk is stated once: what an
|
|
163
|
+
* attribute query adds is which regions are in scope and the author's `reason`,
|
|
164
|
+
* which is the attribute's own value.
|
|
165
|
+
*
|
|
166
|
+
* **The provider list is memoized per graph**, because the filter made the walk
|
|
167
|
+
* unconditional: it used to skip the containment BFS for any provider not
|
|
168
|
+
* declaring the queried attribute, and six queries per analysis (four zone
|
|
169
|
+
* attributes plus two durable ones) became six full walks over every provider
|
|
170
|
+
* in the module. The cache is keyed on the CallGraph object, which is itself
|
|
171
|
+
* built once per analysis — so it lives exactly as long as the answer stays
|
|
172
|
+
* true, and a rebuilt graph gets a fresh one.
|
|
173
|
+
*/
|
|
174
|
+
const providersByGraph = new WeakMap();
|
|
175
|
+
export function findZoneRegions(graph, resolveDef, attribute) {
|
|
176
|
+
let providers = providersByGraph.get(graph);
|
|
177
|
+
if (!providers) {
|
|
178
|
+
providers = findZoneProviders(graph, resolveDef);
|
|
179
|
+
providersByGraph.set(graph, providers);
|
|
180
|
+
}
|
|
181
|
+
const out = [];
|
|
182
|
+
for (const region of providers) {
|
|
183
|
+
const reason = region.attributes[attribute];
|
|
184
|
+
if (typeof reason !== "string")
|
|
185
|
+
continue;
|
|
186
|
+
out.push({ ...region, attribute, reason });
|
|
187
|
+
}
|
|
188
|
+
return out;
|
|
189
|
+
}
|
|
162
190
|
/** Field-map paths of every slot in a kind's schema carrying a provides-zone
|
|
163
191
|
* annotation, with the schema node at each. Walks properties, array items and
|
|
164
192
|
* `additionalProperties`, resolving local `$ref`s — the paths the call graph's
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve-zone-requirements.d.ts","sourceRoot":"","sources":["../src/resolve-zone-requirements.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,KAAK,EAAsB,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAEL,KAAK,SAAS,EAEd,KAAK,iBAAiB,EACvB,MAAM,iBAAiB,CAAC;AACzB,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAMnE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAEtE,OAAO,EAAsB,KAAK,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAIzE;;uCAEuC;AACvC,MAAM,WAAW,mBAAmB;IAClC,wDAAwD;IACxD,IAAI,EAAE,MAAM,CAAC;IACb;;wBAEoB;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+EAA+E;IAC/E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;sDACkD;IAClD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;gCAG4B;IAC5B,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,gEAAgE;IAChE,MAAM,EAAE,MAAM,CAAC;IACf,mEAAmE;IACnE,GAAG,EAAE,MAAM,EAAE,CAAC;CACf;AAED,6EAA6E;AAC7E,MAAM,MAAM,sBAAsB,GAAG,GAAG,CAAC,MAAM,EAAE,mBAAmB,EAAE,CAAC,CAAC;AAExE,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,sBAAsB,CAAC;CACjC;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,eAAe,GAAG,GAAG,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC;AAkBhE,UAAU,cAAc;IACtB,KAAK,EAAE,SAAS,CAAC;IACjB,IAAI,EAAE,kBAAkB,CAAC;IACzB,OAAO,EAAE,aAAa,CAAC;IACvB,eAAe,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IAC5C;qEACiE;IACjE,aAAa,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACnC;0EACsE;IACtE,KAAK,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,mBAAmB,EAAE,CAAC,CAAC;IAC3C;2CACuC;IACvC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,iBAAiB,KAAK,MAAM,GAAG,SAAS,CAAC;CAC5D;AAED,UAAU,gBAAgB;IACxB,WAAW,EAAE,kBAAkB,EAAE,CAAC;IAClC,WAAW,EAAE,sBAAsB,CAAC;CACrC;AAwKD,yCAAyC;AACzC,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,cAAc,GAAG,gBAAgB,
|
|
1
|
+
{"version":3,"file":"resolve-zone-requirements.d.ts","sourceRoot":"","sources":["../src/resolve-zone-requirements.ts"],"names":[],"mappings":"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"}
|
|
@@ -175,7 +175,9 @@ export function projectZoneRequirements(args) {
|
|
|
175
175
|
if (local)
|
|
176
176
|
return local;
|
|
177
177
|
}
|
|
178
|
-
|
|
178
|
+
// In the scope that WROTE the name: a bare reference means the reader's own
|
|
179
|
+
// module, and two libraries may each declare one.
|
|
180
|
+
return graph.resourceByName(name, from.manifest.metadata?.module);
|
|
179
181
|
};
|
|
180
182
|
const acceptedFor = (zone) => {
|
|
181
183
|
const out = new Set([zone]);
|
|
@@ -550,7 +552,7 @@ export function runZoneAnalysis(args) {
|
|
|
550
552
|
for (const [exportName, specs] of openExports) {
|
|
551
553
|
if (!lib.exportedNames.has(exportName))
|
|
552
554
|
continue;
|
|
553
|
-
const node = graph.resourceByName(exportName);
|
|
555
|
+
const node = graph.resourceByName(exportName, lib.module);
|
|
554
556
|
if (!node || node.manifest.metadata?.module !== lib.module) {
|
|
555
557
|
continue;
|
|
556
558
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { ManifestSource } from "../types.js";
|
|
2
|
-
/** The browser-safe built-in sources
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
export declare function defaultSources(
|
|
2
|
+
/** The browser-safe built-in sources. Node-specific sources (local filesystem)
|
|
3
|
+
* are supplied by the consuming package and passed alongside these into the
|
|
4
|
+
* `Loader` constructor. Callers that only want a subset (e.g. the editor, which
|
|
5
|
+
* brings its own manifest-cache adapter) construct the individual sources
|
|
6
|
+
* directly. */
|
|
7
|
+
export declare function defaultSources(): ManifestSource[];
|
|
8
8
|
//# sourceMappingURL=default-sources.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"default-sources.d.ts","sourceRoot":"","sources":["../../src/sources/default-sources.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"default-sources.d.ts","sourceRoot":"","sources":["../../src/sources/default-sources.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAGlD;;;;gBAIgB;AAChB,wBAAgB,cAAc,IAAI,cAAc,EAAE,CAEjD"}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { HttpSource } from "./http-source.js";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
return [new HttpSource(), new RegistrySource(registryUrl)];
|
|
2
|
+
/** The browser-safe built-in sources. Node-specific sources (local filesystem)
|
|
3
|
+
* are supplied by the consuming package and passed alongside these into the
|
|
4
|
+
* `Loader` constructor. Callers that only want a subset (e.g. the editor, which
|
|
5
|
+
* brings its own manifest-cache adapter) construct the individual sources
|
|
6
|
+
* directly. */
|
|
7
|
+
export function defaultSources() {
|
|
8
|
+
return [new HttpSource()];
|
|
10
9
|
}
|
|
@@ -43,8 +43,9 @@ export declare function verifyIntegrity(bytes: Uint8Array, integrity: string, de
|
|
|
43
43
|
/** The single verified network read for remote manifests: fetch `fetchUrl`,
|
|
44
44
|
* verify the raw bytes against `integrity` (when pinned), and return both the
|
|
45
45
|
* bytes and the decoded text. The one choke point every network `ManifestSource`
|
|
46
|
-
* routes through, so verification cannot drift between them
|
|
47
|
-
* the
|
|
46
|
+
* routes through, so verification cannot drift between them — which is also why
|
|
47
|
+
* the object-storage non-manifest check lives here rather than in each source.
|
|
48
|
+
* `describe` names the artifact in error messages. */
|
|
48
49
|
export declare function verifiedFetch(fetchUrl: string, integrity: string | undefined, describe: string): Promise<{
|
|
49
50
|
bytes: Uint8Array;
|
|
50
51
|
text: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"integrity.d.ts","sourceRoot":"","sources":["../../src/sources/integrity.ts"],"names":[],"mappings":"AAAA;;;;;;6EAM6E;AAc7E;;;qDAGqD;AACrD,qBAAa,cAAe,SAAQ,KAAK;gBAC3B,OAAO,EAAE,MAAM;CAI5B;AAED;;2EAE2E;AAC3E,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAIhF;AAED;;;kFAGkF;AAClF,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,GAAG,MAAM,CAIxE;AAED;;;;;;;;8DAQ8D;AAC9D,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAEpE;AAcD,iFAAiF;AACjF,wBAAsB,eAAe,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAOxE;AAED;;gFAEgF;AAChF,wBAAsB,eAAe,CACnC,KAAK,EAAE,UAAU,EACjB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAkBf;
|
|
1
|
+
{"version":3,"file":"integrity.d.ts","sourceRoot":"","sources":["../../src/sources/integrity.ts"],"names":[],"mappings":"AAAA;;;;;;6EAM6E;AAc7E;;;qDAGqD;AACrD,qBAAa,cAAe,SAAQ,KAAK;gBAC3B,OAAO,EAAE,MAAM;CAI5B;AAED;;2EAE2E;AAC3E,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAIhF;AAED;;;kFAGkF;AAClF,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,GAAG,MAAM,CAIxE;AAED;;;;;;;;8DAQ8D;AAC9D,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAEpE;AAcD,iFAAiF;AACjF,wBAAsB,eAAe,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAOxE;AAED;;gFAEgF;AAChF,wBAAsB,eAAe,CACnC,KAAK,EAAE,UAAU,EACjB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAkBf;AAgBD;;;;;uDAKuD;AACvD,wBAAsB,aAAa,CACjC,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC;IAAE,KAAK,EAAE,UAAU,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAoB9C"}
|
|
@@ -93,18 +93,41 @@ export async function verifyIntegrity(bytes, integrity, describe) {
|
|
|
93
93
|
`the module may have been tampered with or republished.`);
|
|
94
94
|
}
|
|
95
95
|
}
|
|
96
|
+
/** Object-storage backends (Cloudflare R2, S3) surface auth and permission
|
|
97
|
+
* failures as a **200 with an XML error body**. Caught here rather than left to
|
|
98
|
+
* the loader, which would parse the XML as YAML and report a downstream
|
|
99
|
+
* `UNDEFINED_KIND` — naming the manifest's contents as the problem instead of
|
|
100
|
+
* the origin that refused to serve it. Returns the failure detail, or `null`
|
|
101
|
+
* when the body is not an XML error document. */
|
|
102
|
+
function objectStorageError(text) {
|
|
103
|
+
const head = text.trimStart();
|
|
104
|
+
if (!head.startsWith("<?xml") && !head.startsWith("<Error"))
|
|
105
|
+
return null;
|
|
106
|
+
const code = text.match(/<Code>([^<]+)<\/Code>/);
|
|
107
|
+
const message = text.match(/<Message>([^<]+)<\/Message>/);
|
|
108
|
+
return code && message ? `${code[1]}: ${message[1]}` : text.slice(0, 200);
|
|
109
|
+
}
|
|
96
110
|
/** The single verified network read for remote manifests: fetch `fetchUrl`,
|
|
97
111
|
* verify the raw bytes against `integrity` (when pinned), and return both the
|
|
98
112
|
* bytes and the decoded text. The one choke point every network `ManifestSource`
|
|
99
|
-
* routes through, so verification cannot drift between them
|
|
100
|
-
* the
|
|
113
|
+
* routes through, so verification cannot drift between them — which is also why
|
|
114
|
+
* the object-storage non-manifest check lives here rather than in each source.
|
|
115
|
+
* `describe` names the artifact in error messages. */
|
|
101
116
|
export async function verifiedFetch(fetchUrl, integrity, describe) {
|
|
102
117
|
const response = await fetch(fetchUrl);
|
|
103
118
|
if (!response.ok) {
|
|
104
119
|
throw new Error(`Failed to fetch manifest ${describe}: ${response.status} ${response.statusText} (${fetchUrl})`);
|
|
105
120
|
}
|
|
106
121
|
const bytes = new Uint8Array(await response.arrayBuffer());
|
|
122
|
+
const text = new TextDecoder().decode(bytes);
|
|
123
|
+
// Before the integrity check: a bucket's error page hashes to something, and
|
|
124
|
+
// reporting a pin mismatch would name the wrong cause just as the loader does.
|
|
125
|
+
const storageError = objectStorageError(text);
|
|
126
|
+
if (storageError) {
|
|
127
|
+
throw new Error(`The origin returned a non-manifest response for ${describe} ` +
|
|
128
|
+
`(URL: ${fetchUrl}): ${storageError}`);
|
|
129
|
+
}
|
|
107
130
|
if (integrity)
|
|
108
131
|
await verifyIntegrity(bytes, integrity, describe);
|
|
109
|
-
return { bytes, text
|
|
132
|
+
return { bytes, text };
|
|
110
133
|
}
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
* ref, the version segment it currently names, and any inline pin. */
|
|
3
3
|
export interface ParsedVersionedRef {
|
|
4
4
|
/** The ref with its `@version` segment and integrity fragment removed —
|
|
5
|
-
* `
|
|
6
|
-
*
|
|
5
|
+
* `oci://ghcr.io/telorun/timer`. This is the identity a version list is keyed
|
|
6
|
+
* by (the hub registers modules under exactly this form). */
|
|
7
7
|
baseRef: string;
|
|
8
|
-
/** The version segment, raw —
|
|
9
|
-
*
|
|
8
|
+
/** The version segment, raw — an OCI tag or an OCI digest reference
|
|
9
|
+
* (`sha256:…`). The caller applies its own SemVer check. */
|
|
10
10
|
version: string;
|
|
11
11
|
/** Telo's inline `sha256-<base64url>` pin, when the ref carried one. */
|
|
12
12
|
integrity?: string;
|
|
@@ -15,12 +15,17 @@ export interface ParsedVersionedRef {
|
|
|
15
15
|
* upgradeable version — a local path, a bare `https://` URL, or an OCI ref
|
|
16
16
|
* with no explicit reference (an implicit `latest` is not a pin).
|
|
17
17
|
*
|
|
18
|
-
* Browser-safe
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
18
|
+
* Browser-safe: this is the *grammar* half of an upgrade, shared by the kernel
|
|
19
|
+
* transports (whose `refVersion` / `withVersion` delegate here) and the editor,
|
|
20
|
+
* which cannot use a transport at all — the *network* half (enumerating
|
|
21
|
+
* versions) is scheme-specific and stays behind `Transport.listVersions` on
|
|
22
|
+
* Node and the hub's `/module/versions` in the browser.
|
|
23
|
+
*
|
|
24
|
+
* It is NOT transport-neutral: `oci://` is the only versionable grammar, named
|
|
25
|
+
* literally below. That was equally true when the registry ref was the second
|
|
26
|
+
* branch, and a third scheme still means editing this file — the versionable
|
|
27
|
+
* set would have to become data the transports contribute before that claim
|
|
28
|
+
* could be made honestly. */
|
|
24
29
|
export declare function parseVersionedRef(ref: string): ParsedVersionedRef | null;
|
|
25
30
|
/** `ref` rewritten to name `version`, dropping any integrity fragment (the
|
|
26
31
|
* caller re-pins the result). Appends the version when the ref carries none —
|
|
@@ -28,7 +33,7 @@ export declare function parseVersionedRef(ref: string): ParsedVersionedRef | nul
|
|
|
28
33
|
*
|
|
29
34
|
* Throws when the ref's grammar has no version segment at all — a relative
|
|
30
35
|
* path, a bare `https://` URL. Producing `../lib@0.4.0` for those would write
|
|
31
|
-
* a ref nothing can resolve, so this fails where the transport-specific
|
|
32
|
-
*
|
|
36
|
+
* a ref nothing can resolve, so this fails where the transport-specific parser
|
|
37
|
+
* it replaced (`parseOciRef`) also failed. */
|
|
33
38
|
export declare function withRefVersion(ref: string, version: string): string;
|
|
34
39
|
//# sourceMappingURL=versioned-ref.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"versioned-ref.d.ts","sourceRoot":"","sources":["../../src/sources/versioned-ref.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"versioned-ref.d.ts","sourceRoot":"","sources":["../../src/sources/versioned-ref.ts"],"names":[],"mappings":"AAGA;uEACuE;AACvE,MAAM,WAAW,kBAAkB;IACjC;;kEAE8D;IAC9D,OAAO,EAAE,MAAM,CAAC;IAChB;iEAC6D;IAC7D,OAAO,EAAE,MAAM,CAAC;IAChB,wEAAwE;IACxE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;;8BAc8B;AAC9B,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,kBAAkB,GAAG,IAAI,CAOxE;AAED;;;;;;;+CAO+C;AAC/C,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CASnE"}
|
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
import { splitIntegrity } from "./integrity.js";
|
|
2
|
-
import { isRegistryRef } from "./module-ref.js";
|
|
3
2
|
import { OCI_SCHEME } from "./oci-ref.js";
|
|
4
3
|
/** Split a versioned module ref. Returns `null` when the ref names no
|
|
5
4
|
* upgradeable version — a local path, a bare `https://` URL, or an OCI ref
|
|
6
5
|
* with no explicit reference (an implicit `latest` is not a pin).
|
|
7
6
|
*
|
|
8
|
-
* Browser-safe
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
7
|
+
* Browser-safe: this is the *grammar* half of an upgrade, shared by the kernel
|
|
8
|
+
* transports (whose `refVersion` / `withVersion` delegate here) and the editor,
|
|
9
|
+
* which cannot use a transport at all — the *network* half (enumerating
|
|
10
|
+
* versions) is scheme-specific and stays behind `Transport.listVersions` on
|
|
11
|
+
* Node and the hub's `/module/versions` in the browser.
|
|
12
|
+
*
|
|
13
|
+
* It is NOT transport-neutral: `oci://` is the only versionable grammar, named
|
|
14
|
+
* literally below. That was equally true when the registry ref was the second
|
|
15
|
+
* branch, and a third scheme still means editing this file — the versionable
|
|
16
|
+
* set would have to become data the transports contribute before that claim
|
|
17
|
+
* could be made honestly. */
|
|
14
18
|
export function parseVersionedRef(ref) {
|
|
15
19
|
const { base, integrity } = splitIntegrity(ref);
|
|
16
20
|
const at = versionSeparator(base);
|
|
@@ -27,34 +31,28 @@ export function parseVersionedRef(ref) {
|
|
|
27
31
|
*
|
|
28
32
|
* Throws when the ref's grammar has no version segment at all — a relative
|
|
29
33
|
* path, a bare `https://` URL. Producing `../lib@0.4.0` for those would write
|
|
30
|
-
* a ref nothing can resolve, so this fails where the transport-specific
|
|
31
|
-
*
|
|
34
|
+
* a ref nothing can resolve, so this fails where the transport-specific parser
|
|
35
|
+
* it replaced (`parseOciRef`) also failed. */
|
|
32
36
|
export function withRefVersion(ref, version) {
|
|
33
37
|
const { base } = splitIntegrity(ref);
|
|
34
|
-
if (
|
|
35
|
-
throw new Error(`Cannot set a version on '${ref}' — only
|
|
36
|
-
`and oci:// refs carry a version segment.`);
|
|
38
|
+
if (!isVersionableRef(base)) {
|
|
39
|
+
throw new Error(`Cannot set a version on '${ref}' — only oci:// refs carry a version segment.`);
|
|
37
40
|
}
|
|
38
41
|
const at = versionSeparator(base);
|
|
39
42
|
return `${at === null ? base : base.slice(0, at)}@${version}`;
|
|
40
43
|
}
|
|
41
|
-
/**
|
|
42
|
-
*
|
|
43
|
-
function
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
return base.indexOf("/", OCI_SCHEME.length) > OCI_SCHEME.length ? "oci" : null;
|
|
47
|
-
}
|
|
48
|
-
// `isRegistryRef` requires the `@`, so a version-less `std/console` is not a
|
|
49
|
-
// registry ref by this test — matching `parseModuleRef`, which throws on it.
|
|
50
|
-
return isRegistryRef(base) ? "registry" : null;
|
|
44
|
+
/** True when `base` is written in a grammar that carries a version segment — a
|
|
45
|
+
* relative/absolute path and a `file:`/`https://` URL are not. */
|
|
46
|
+
function isVersionableRef(base) {
|
|
47
|
+
// A host alone is not addressable; the repo path is what carries a version.
|
|
48
|
+
return base.startsWith(OCI_SCHEME) && base.indexOf("/", OCI_SCHEME.length) > OCI_SCHEME.length;
|
|
51
49
|
}
|
|
52
50
|
/** Index of the `@` that separates the version, or `null` when the ref names
|
|
53
51
|
* none. Split on the LAST `@` so a digest reference (`repo@sha256:…`) keeps
|
|
54
52
|
* everything before it as the ref. */
|
|
55
53
|
function versionSeparator(base) {
|
|
56
|
-
if (
|
|
54
|
+
if (!isVersionableRef(base))
|
|
57
55
|
return null;
|
|
58
56
|
const at = base.lastIndexOf("@");
|
|
59
|
-
return at >
|
|
57
|
+
return at > OCI_SCHEME.length ? at : null;
|
|
60
58
|
}
|
package/dist/telo-version.d.ts
CHANGED
package/dist/telo-version.js
CHANGED
|
@@ -5,4 +5,4 @@
|
|
|
5
5
|
// its release identity, this is the scale a module's `requires.telo` range is
|
|
6
6
|
// written against, and every kernel in every language reports the same scale.
|
|
7
7
|
/** The surface generation this analyzer implements. */
|
|
8
|
-
export const TELO_SURFACE_VERSION = "0.
|
|
8
|
+
export const TELO_SURFACE_VERSION = "0.85.0";
|
package/package.json
CHANGED
package/src/analysis-registry.ts
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import type { ResourceDefinition, ResourceManifest } from "@telorun/sdk";
|
|
2
2
|
import { AliasResolver } from "./alias-resolver.js";
|
|
3
3
|
import { KERNEL_BUILTINS } from "./builtins.js";
|
|
4
|
+
import type { BuildModuleGraphOptions, ModuleGraphDeps } from "./module-graph.js";
|
|
4
5
|
import { ManifestAnalysis } from "./manifest-analysis.js";
|
|
5
6
|
import { DefinitionRegistry } from "./definition-registry.js";
|
|
6
7
|
import { computeSuggestKind, computeValidUserFacingKinds } from "./kind-suggest.js";
|
|
7
8
|
import { visitManifest as runVisitManifest, type ManifestVisitor } from "./manifest-visitor.js";
|
|
8
9
|
import type { ContractDirection, DefResolver } from "./extends-resolution.js";
|
|
9
10
|
import { resolveContract } from "./invocation-contract.js";
|
|
11
|
+
import { createResolveCtx, resolveThrowsUnion } from "./resolve-throws-union.js";
|
|
10
12
|
import { isRefEntry, isScopeEntry } from "./reference-field-map.js";
|
|
11
13
|
import { resolveSchemaTypeRefs as resolveSchemaTypeRefsIn } from "./resolve-schema-type-refs.js";
|
|
12
14
|
import type { AnalysisContext } from "./types.js";
|
|
@@ -279,6 +281,41 @@ export class AnalysisRegistry {
|
|
|
279
281
|
});
|
|
280
282
|
}
|
|
281
283
|
|
|
284
|
+
/**
|
|
285
|
+
* What the projection needs that only this registry knows: how a kind
|
|
286
|
+
* resolves, what its reference slots are, which capabilities they target, and
|
|
287
|
+
* what a resource can raise.
|
|
288
|
+
*
|
|
289
|
+
* The GRAPH itself is built by `ManifestAnalysis.moduleGraph`, which is the
|
|
290
|
+
* pairing of a registry with a manifest set — a fifth
|
|
291
|
+
* `registry.x(manifests, …)` factory is the accretion naming that class
|
|
292
|
+
* stopped. This is the half the registry owns.
|
|
293
|
+
*/
|
|
294
|
+
moduleGraphDeps(
|
|
295
|
+
manifests: ResourceManifest[],
|
|
296
|
+
options: BuildModuleGraphOptions = {},
|
|
297
|
+
): ModuleGraphDeps {
|
|
298
|
+
// The error contract is resolved through the SAME resolver `telo check`
|
|
299
|
+
// uses, memoized across the whole graph — so what a box says it can raise
|
|
300
|
+
// is what a route's `catches:` is validated against.
|
|
301
|
+
const throwsCtx = createResolveCtx(
|
|
302
|
+
manifests,
|
|
303
|
+
this.defs,
|
|
304
|
+
this.aliases,
|
|
305
|
+
this.aliasesByModule,
|
|
306
|
+
new Set(options.entryModule ? [options.entryModule] : []),
|
|
307
|
+
);
|
|
308
|
+
return {
|
|
309
|
+
refFields: (resource) => this.refFieldsForResource(resource),
|
|
310
|
+
definition: (kind, module) => this.resolveDefinitionIn(kind, module),
|
|
311
|
+
aliasesForModule: (module) => this.aliases.aliasesFor(module),
|
|
312
|
+
throwsOf: (resource) => {
|
|
313
|
+
const union = resolveThrowsUnion(resource, throwsCtx);
|
|
314
|
+
return { codes: [...union.codes.keys()], unbounded: union.unbounded };
|
|
315
|
+
},
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
|
|
282
319
|
/**
|
|
283
320
|
* Returns the built-in kernel definitions. The underlying DefinitionRegistry already
|
|
284
321
|
* seeds these on construction; this method exposes them so callers (e.g. the kernel's
|