@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
package/src/index.ts
CHANGED
|
@@ -110,6 +110,8 @@ export {
|
|
|
110
110
|
transfersControl,
|
|
111
111
|
} from "./ref-slot.js";
|
|
112
112
|
export type { RefSlot, RefUse, RefUseCases } from "./ref-slot.js";
|
|
113
|
+
export { isStepSlot, readStepSlot, STEP_FRAGMENT } from "./step-slot.js";
|
|
114
|
+
export type { StepSlot } from "./step-slot.js";
|
|
113
115
|
export {
|
|
114
116
|
ANNOTATION_KEYWORDS,
|
|
115
117
|
registerTeloKeywords,
|
|
@@ -131,6 +133,8 @@ export type {
|
|
|
131
133
|
RequiresIssue,
|
|
132
134
|
RequiresVerdict,
|
|
133
135
|
} from "./requires-block.js";
|
|
136
|
+
export { manifestCompatibility } from "./module-compatibility.js";
|
|
137
|
+
export type { ModuleCompatibility } from "./module-compatibility.js";
|
|
134
138
|
export { TELO_SURFACE_VERSION } from "./telo-version.js";
|
|
135
139
|
export { validateRequires } from "./validate-requires.js";
|
|
136
140
|
export type { ValidateRequiresOptions } from "./validate-requires.js";
|
|
@@ -150,8 +154,10 @@ export type {
|
|
|
150
154
|
export {
|
|
151
155
|
hasProvidesZone,
|
|
152
156
|
hasRequiresZone,
|
|
157
|
+
providedZoneAttributes,
|
|
153
158
|
readProvidesZone,
|
|
154
159
|
readRequiresZone,
|
|
160
|
+
readViolatesZone,
|
|
155
161
|
rewriteRequiresZoneKind,
|
|
156
162
|
} from "./zone-slot.js";
|
|
157
163
|
export type { ProvidesZoneSlot, RequiresZoneSlot } from "./zone-slot.js";
|
|
@@ -169,6 +175,73 @@ export type {
|
|
|
169
175
|
} from "./resolve-zone-requirements.js";
|
|
170
176
|
export type { ZoneModuleDocuments } from "./zone-module-documents.js";
|
|
171
177
|
export { validateZoneSlotDeclarations } from "./validate-zone-slots.js";
|
|
178
|
+
export {
|
|
179
|
+
RESOURCE_RULES_ANNOTATION,
|
|
180
|
+
readResourceRules,
|
|
181
|
+
readRawResourceRules,
|
|
182
|
+
resolveRuleSubjects,
|
|
183
|
+
findDynamicLeaf,
|
|
184
|
+
type ResourceRule,
|
|
185
|
+
type ResourceRuleSeverity,
|
|
186
|
+
type RuleSubject,
|
|
187
|
+
} from "./resource-rule.js";
|
|
188
|
+
export {
|
|
189
|
+
validateResourceRuleDeclarations,
|
|
190
|
+
evaluateResourceRules,
|
|
191
|
+
ruleExercised,
|
|
192
|
+
RESOURCE_RULE_BUDGET_MS,
|
|
193
|
+
type ResourceRuleIssue,
|
|
194
|
+
type ResourceRuleFinding,
|
|
195
|
+
} from "./validate-resource-rules.js";
|
|
196
|
+
export {
|
|
197
|
+
REFERRER_RULES_ANNOTATION,
|
|
198
|
+
readReferrerRules,
|
|
199
|
+
readRawReferrerRules,
|
|
200
|
+
hasReferrerRules,
|
|
201
|
+
rewriteReferrerRuleKinds,
|
|
202
|
+
type ReferrerRule,
|
|
203
|
+
} from "./referrer-rule.js";
|
|
204
|
+
export {
|
|
205
|
+
validateReferrerRuleDeclarations,
|
|
206
|
+
evaluateReferrerRules,
|
|
207
|
+
referrerRuleExercised,
|
|
208
|
+
reportReferrerRules,
|
|
209
|
+
reportUnexercisedReferrerRule,
|
|
210
|
+
type Referrer,
|
|
211
|
+
type ReferrerRuleIssue,
|
|
212
|
+
type ReferrerRuleFinding,
|
|
213
|
+
type ReferrerRuleDiagnostic,
|
|
214
|
+
} from "./validate-referrer-rules.js";
|
|
215
|
+
export { RULE_BUDGET_MS } from "./rule-condition.js";
|
|
216
|
+
export {
|
|
217
|
+
readSchemaProjection,
|
|
218
|
+
readSchemaMap,
|
|
219
|
+
readProjectionFrom,
|
|
220
|
+
readProjectionRef,
|
|
221
|
+
manifestListScope,
|
|
222
|
+
projectionKeyMap,
|
|
223
|
+
projectEntries,
|
|
224
|
+
resolveSchemaProjections,
|
|
225
|
+
describeProjectionFailure,
|
|
226
|
+
type SchemaProjection,
|
|
227
|
+
type SchemaMap,
|
|
228
|
+
type ProjectionRef,
|
|
229
|
+
type ProjectionLookup,
|
|
230
|
+
type ProjectionScope,
|
|
231
|
+
type ProjectionFailure,
|
|
232
|
+
} from "./schema-projection.js";
|
|
233
|
+
export { validateSchemaProjection, type SchemaProjectionIssue } from "./validate-schema-projection.js";
|
|
234
|
+
export { validateDurableRegions } from "./validate-durable-regions.js";
|
|
235
|
+
export { validateZoneViolations } from "./validate-zone-violations.js";
|
|
236
|
+
export {
|
|
237
|
+
containmentIndex,
|
|
238
|
+
findZoneRegions,
|
|
239
|
+
regionManifests,
|
|
240
|
+
type ContainedNode,
|
|
241
|
+
type DefinitionLookup,
|
|
242
|
+
type RegionBoundary,
|
|
243
|
+
type ZoneRegion,
|
|
244
|
+
} from "./resolve-zone-containment.js";
|
|
172
245
|
export type { ZoneSlotIssue } from "./validate-zone-slots.js";
|
|
173
246
|
export { validateDynamicSelectors, validateRefSlotDeclarations } from "./validate-ref-slots.js";
|
|
174
247
|
export type { RefSlotIssue } from "./validate-ref-slots.js";
|
|
@@ -6,6 +6,11 @@ import {
|
|
|
6
6
|
effectiveContractField,
|
|
7
7
|
} from "./extends-resolution.js";
|
|
8
8
|
import { resolveTypeFieldToSchema } from "./validate-cel-context.js";
|
|
9
|
+
import {
|
|
10
|
+
manifestListScope,
|
|
11
|
+
resolveSchemaProjections,
|
|
12
|
+
type ProjectionFailure,
|
|
13
|
+
} from "./schema-projection.js";
|
|
9
14
|
|
|
10
15
|
export type { ContractDirection };
|
|
11
16
|
|
|
@@ -80,11 +85,20 @@ export function resolveContract(
|
|
|
80
85
|
manifest: Record<string, any> | undefined,
|
|
81
86
|
definition: ResourceDefinition | undefined,
|
|
82
87
|
scope: ContractScope,
|
|
88
|
+
/** Collects declaration-derived slots that could not be projected. Omitted by
|
|
89
|
+
* every caller that only wants the schema; the one pass that REPORTS them
|
|
90
|
+
* passes an array. */
|
|
91
|
+
projectionFailures?: ProjectionFailure[],
|
|
83
92
|
): ResolvedContract | undefined {
|
|
84
93
|
const own = manifest?.[direction];
|
|
85
94
|
if (own !== undefined && own !== null) {
|
|
86
95
|
const schema = resolveTypeFieldToSchema(own, scope.typeManifestsFor(definition));
|
|
87
|
-
if (schema)
|
|
96
|
+
if (schema) {
|
|
97
|
+
return {
|
|
98
|
+
schema: projectionResolved(schema, manifest, scope, definition, projectionFailures),
|
|
99
|
+
origin: "instance",
|
|
100
|
+
};
|
|
101
|
+
}
|
|
88
102
|
}
|
|
89
103
|
|
|
90
104
|
const declared = effectiveContractField(definition, scope.resolveDefinition, direction);
|
|
@@ -92,7 +106,36 @@ export function resolveContract(
|
|
|
92
106
|
const declarer = contractDeclarer(definition, scope.resolveDefinition, direction);
|
|
93
107
|
const schema = resolveTypeFieldToSchema(declared, scope.typeManifestsFor(declarer));
|
|
94
108
|
if (!schema) return undefined;
|
|
95
|
-
return {
|
|
109
|
+
return {
|
|
110
|
+
schema: projectionResolved(schema, manifest, scope, declarer, projectionFailures),
|
|
111
|
+
origin: "kind",
|
|
112
|
+
declaredBy: declarer,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* A contract may be DECLARATION-derived: a kind whose `outputType` projects the
|
|
118
|
+
* declaration of a resource it references (a repository typing its rows from
|
|
119
|
+
* the table it reads). The manifest is in hand here and nowhere later, so this
|
|
120
|
+
* is where the projection is resolved — and it is resolved for a kind-declared
|
|
121
|
+
* contract and an instance-declared one alike, since either may carry one.
|
|
122
|
+
*/
|
|
123
|
+
function projectionResolved(
|
|
124
|
+
schema: Record<string, any>,
|
|
125
|
+
manifest: Record<string, any> | undefined,
|
|
126
|
+
scope: ContractScope,
|
|
127
|
+
declarer: ResourceDefinition | undefined,
|
|
128
|
+
failures?: ProjectionFailure[],
|
|
129
|
+
): Record<string, any> {
|
|
130
|
+
return resolveSchemaProjections(
|
|
131
|
+
schema,
|
|
132
|
+
manifest,
|
|
133
|
+
manifestListScope(
|
|
134
|
+
scope.typeManifestsFor(declarer),
|
|
135
|
+
(kind) => scope.resolveDefinition(kind) as Record<string, any> | undefined,
|
|
136
|
+
),
|
|
137
|
+
failures,
|
|
138
|
+
) as Record<string, any>;
|
|
96
139
|
}
|
|
97
140
|
|
|
98
141
|
/** {@link resolveContract}, falling back to {@link PERMISSIVE_CONTRACT}. For
|
package/src/loaded-types.ts
CHANGED
|
@@ -70,9 +70,11 @@ export interface ImportEdge {
|
|
|
70
70
|
* this (minus its version), since it names the module's location
|
|
71
71
|
* independently of what the module declares about itself. */
|
|
72
72
|
targetRef: string;
|
|
73
|
-
/** Target library's `metadata.name
|
|
74
|
-
*
|
|
75
|
-
|
|
73
|
+
/** Target library's `metadata.name`. Never absent: an import whose target
|
|
74
|
+
* names no library identity registers no edge at all and is reported in
|
|
75
|
+
* `LoadedGraph.errors`, so an edge that exists is one every consumer can
|
|
76
|
+
* resolve a kind through. */
|
|
77
|
+
targetModuleName: string;
|
|
76
78
|
/** DEPRECATED. Target library's `metadata.namespace`, or `null` when it
|
|
77
79
|
* declares none. Feeds only the legacy `<namespace>/<module>#<Kind>` form
|
|
78
80
|
* of `x-telo-ref`; nothing else reads it. */
|
|
@@ -137,5 +139,12 @@ export interface GraphLoadError {
|
|
|
137
139
|
alias?: string;
|
|
138
140
|
/** Line of the `Telo.Import` doc in `fromSource`, for position fallback. */
|
|
139
141
|
sourceLine?: number;
|
|
142
|
+
/** Why this import is unusable. `"unresolved"` (the default) means the target
|
|
143
|
+
* was never obtained — an unreachable or unrecognizable source, which the
|
|
144
|
+
* author fixes in their own file. `"unusable-target"` means it WAS obtained
|
|
145
|
+
* and is not an importable library, which is a defect in the target module.
|
|
146
|
+
* Kept apart because the two call for different actions; consumers phrase
|
|
147
|
+
* them differently rather than asserting one cause for both. */
|
|
148
|
+
reason?: "unresolved" | "unusable-target";
|
|
140
149
|
error: Error;
|
|
141
150
|
}
|
package/src/manifest-loader.ts
CHANGED
|
@@ -57,6 +57,62 @@ function collectMigrationDiagnostics(entry: LoadedModule): AnalysisDiagnostic[]
|
|
|
57
57
|
return diagnostics;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
+
/** The identity an import target contributes to its importer, or the reason it
|
|
61
|
+
* contributes none.
|
|
62
|
+
*
|
|
63
|
+
* Every way an import can be unusable answers here, in one place and without
|
|
64
|
+
* throwing: the target is an application, it carries no library document at
|
|
65
|
+
* all, or it carries one that never names itself. A name is not decoration —
|
|
66
|
+
* it is the kind prefix every `Alias.Kind` in the importer resolves through —
|
|
67
|
+
* so a target that has none is as unusable as one that was never fetched, and
|
|
68
|
+
* is reported the same way rather than left to surface later as an invented
|
|
69
|
+
* module nobody declared. */
|
|
70
|
+
type ImportTargetIdentity =
|
|
71
|
+
| { name: string; namespace: string | null }
|
|
72
|
+
| { unusable: string };
|
|
73
|
+
|
|
74
|
+
function importTargetIdentity(target: LoadedModule, importSource: string): ImportTargetIdentity {
|
|
75
|
+
const library = target.owner.manifests.find((m) => m?.kind === "Telo.Library");
|
|
76
|
+
const application = target.owner.manifests.find((m) => m?.kind === "Telo.Application");
|
|
77
|
+
|
|
78
|
+
if (!library && application) {
|
|
79
|
+
return {
|
|
80
|
+
unusable:
|
|
81
|
+
`Telo.Import target '${importSource}' is a Telo.Application. ` +
|
|
82
|
+
`Only Telo.Library modules may be imported. Applications are run directly, not imported. ` +
|
|
83
|
+
`Point this import at a library, or drop it and run that application on its own.`,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (!library) {
|
|
88
|
+
const kinds = target.owner.manifests
|
|
89
|
+
.map((m) => m?.kind)
|
|
90
|
+
.filter((k): k is string => typeof k === "string");
|
|
91
|
+
const detail = kinds.length
|
|
92
|
+
? `Fetched ${target.owner.manifests.length} document(s) with kinds [${kinds.join(", ")}].`
|
|
93
|
+
: `Fetched manifest contained no recognizable Telo documents — check that the source ` +
|
|
94
|
+
`serves a Telo.Library manifest and not an upstream error page.`;
|
|
95
|
+
return {
|
|
96
|
+
unusable:
|
|
97
|
+
`Telo.Import target '${importSource}' did not resolve to a Telo.Library. ` +
|
|
98
|
+
`Fetched from: ${target.owner.source}. ${detail}`,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const name = library.metadata?.name;
|
|
103
|
+
if (typeof name !== "string" || name === "") {
|
|
104
|
+
return {
|
|
105
|
+
unusable:
|
|
106
|
+
`Telo.Import target '${importSource}' resolved to a Telo.Library that declares no ` +
|
|
107
|
+
`'metadata.name'. Fetched from: ${target.owner.source}. A library's name is the kind ` +
|
|
108
|
+
`prefix its importers reference, so it cannot be imported until the target declares one.`,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const namespace = (library.metadata as { namespace?: string | null } | undefined)?.namespace;
|
|
113
|
+
return { name, namespace: typeof namespace === "string" ? namespace : null };
|
|
114
|
+
}
|
|
115
|
+
|
|
60
116
|
const SYSTEM_KINDS = new Set([
|
|
61
117
|
"Telo.Application",
|
|
62
118
|
"Telo.Library",
|
|
@@ -320,10 +376,10 @@ export class Loader {
|
|
|
320
376
|
// Resolve the file we'll fetch through the source chain to get the
|
|
321
377
|
// canonical `source` URL — same identity used as the modules-map key.
|
|
322
378
|
let targetCanonical: string;
|
|
323
|
-
let targetModule: LoadedModule
|
|
379
|
+
let targetModule: LoadedModule;
|
|
324
380
|
if (modules.has(resolvedTarget)) {
|
|
325
381
|
targetCanonical = resolvedTarget;
|
|
326
|
-
targetModule = modules.get(resolvedTarget)
|
|
382
|
+
targetModule = modules.get(resolvedTarget)!;
|
|
327
383
|
} else {
|
|
328
384
|
try {
|
|
329
385
|
const loaded = await this.loadModule(resolvedTarget, options);
|
|
@@ -332,7 +388,7 @@ export class Loader {
|
|
|
332
388
|
modules.set(targetCanonical, loaded);
|
|
333
389
|
targetModule = loaded;
|
|
334
390
|
} else {
|
|
335
|
-
targetModule = modules.get(targetCanonical)
|
|
391
|
+
targetModule = modules.get(targetCanonical)!;
|
|
336
392
|
}
|
|
337
393
|
} catch (err) {
|
|
338
394
|
const e = err instanceof Error ? err : new Error(String(err));
|
|
@@ -349,32 +405,42 @@ export class Loader {
|
|
|
349
405
|
}
|
|
350
406
|
}
|
|
351
407
|
|
|
352
|
-
// Resolve target identity from its Telo.Library doc and stamp it
|
|
353
|
-
//
|
|
354
|
-
//
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
408
|
+
// Resolve target identity from its Telo.Library doc and stamp it on
|
|
409
|
+
// the edge — flattenForAnalyzer reads from the edge directly, never
|
|
410
|
+
// re-deriving from manifest.metadata.
|
|
411
|
+
//
|
|
412
|
+
// Checked per IMPORT rather than per distinct target: an import
|
|
413
|
+
// pointing at a module something else already reached (the entry
|
|
414
|
+
// application above all) would otherwise skip the check entirely and
|
|
415
|
+
// register a nameless edge. An unusable target is recorded exactly
|
|
416
|
+
// like an unfetchable one — an error against this import, no edge,
|
|
417
|
+
// and the rest of the graph still loads — so no consumer has to know
|
|
418
|
+
// the difference between the two ways an import can fail.
|
|
419
|
+
const identity = importTargetIdentity(targetModule, importSource);
|
|
420
|
+
if ("unusable" in identity) {
|
|
421
|
+
const e = new Error(identity.unusable);
|
|
422
|
+
(e as { sourceLine?: number }).sourceLine = sourceLine;
|
|
423
|
+
errors.push({
|
|
424
|
+
url: targetCanonical,
|
|
425
|
+
source: importSource,
|
|
426
|
+
fromSource: file.source,
|
|
427
|
+
alias,
|
|
428
|
+
sourceLine,
|
|
429
|
+
reason: "unusable-target",
|
|
430
|
+
error: e,
|
|
431
|
+
});
|
|
432
|
+
continue;
|
|
366
433
|
}
|
|
367
434
|
|
|
368
435
|
aliases.set(alias, {
|
|
369
436
|
targetSource: targetCanonical,
|
|
370
437
|
targetRef: importSource,
|
|
371
|
-
targetModuleName,
|
|
372
|
-
targetNamespace,
|
|
438
|
+
targetModuleName: identity.name,
|
|
439
|
+
targetNamespace: identity.namespace,
|
|
373
440
|
});
|
|
374
441
|
|
|
375
|
-
if (
|
|
442
|
+
if (!visited.has(targetCanonical)) {
|
|
376
443
|
visited.add(targetCanonical);
|
|
377
|
-
this.assertImportTargetIsLibrary(targetModule, importSource, sourceLine);
|
|
378
444
|
queue.push(targetModule);
|
|
379
445
|
}
|
|
380
446
|
}
|
|
@@ -444,40 +510,6 @@ export class Loader {
|
|
|
444
510
|
}
|
|
445
511
|
}
|
|
446
512
|
|
|
447
|
-
private assertImportTargetIsLibrary(
|
|
448
|
-
target: LoadedModule,
|
|
449
|
-
importSource: string,
|
|
450
|
-
sourceLine: number,
|
|
451
|
-
): void {
|
|
452
|
-
const importedLibrary = target.owner.manifests.find((m) => m?.kind === "Telo.Library");
|
|
453
|
-
const importedApplication = target.owner.manifests.find(
|
|
454
|
-
(m) => m?.kind === "Telo.Application",
|
|
455
|
-
);
|
|
456
|
-
if (importedApplication) {
|
|
457
|
-
const e = new Error(
|
|
458
|
-
`Telo.Import target '${importSource}' is a Telo.Application. ` +
|
|
459
|
-
`Only Telo.Library modules may be imported. Applications are run directly, not imported.`,
|
|
460
|
-
);
|
|
461
|
-
(e as { sourceLine?: number }).sourceLine = sourceLine;
|
|
462
|
-
throw e;
|
|
463
|
-
}
|
|
464
|
-
if (!importedLibrary) {
|
|
465
|
-
const kinds = target.owner.manifests
|
|
466
|
-
.map((m) => m?.kind)
|
|
467
|
-
.filter((k): k is string => typeof k === "string");
|
|
468
|
-
const detail = kinds.length
|
|
469
|
-
? `Fetched ${target.owner.manifests.length} document(s) with kinds [${kinds.join(", ")}].`
|
|
470
|
-
: `Fetched manifest contained no recognizable Telo documents — check that the source ` +
|
|
471
|
-
`serves a Telo.Library manifest and not an upstream error page.`;
|
|
472
|
-
const e = new Error(
|
|
473
|
-
`Telo.Import target '${importSource}' did not resolve to a Telo.Library. ` +
|
|
474
|
-
`Fetched from: ${target.owner.source}. ${detail}`,
|
|
475
|
-
);
|
|
476
|
-
(e as { sourceLine?: number }).sourceLine = sourceLine;
|
|
477
|
-
throw e;
|
|
478
|
-
}
|
|
479
|
-
}
|
|
480
|
-
|
|
481
513
|
private async resolveIncludes(
|
|
482
514
|
ownerSource: string,
|
|
483
515
|
patterns: string[],
|