@telorun/analyzer 0.39.0 → 0.40.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.
@@ -0,0 +1,20 @@
1
+ import type { LoadedGraph } from "./loaded-types.js";
2
+ import { type AnalysisDiagnostic } from "./types.js";
3
+ /**
4
+ * Convert a graph's import-resolution failures (`graph.errors`) into structured,
5
+ * coded diagnostics. This is the single source of truth for surfacing a broken
6
+ * import — every host (CLI, VS Code, telo-editor) routes these instead of each
7
+ * re-deriving the channel and drifting (the VS Code extension used to drop it
8
+ * entirely, showing nothing for a broken import).
9
+ *
10
+ * The analyzer owns only this raw channel conversion; the *presentation* policy
11
+ * — which analysis cascade to hold back for a compromised file — lives in
12
+ * `@telorun/ide-support`'s `assembleGraphDiagnostics`.
13
+ *
14
+ * Each diagnostic adopts the same `data` shape as version-reconciliation
15
+ * diagnostics — `{ filePath, path: "imports.<alias>" }` — so the shared
16
+ * `findPositions` / `resolveRange` routing anchors it on the offending import
17
+ * line with no host-specific code.
18
+ */
19
+ export declare function importResolutionDiagnostics(graph: LoadedGraph): AnalysisDiagnostic[];
20
+ //# sourceMappingURL=import-resolution-diagnostics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"import-resolution-diagnostics.d.ts","sourceRoot":"","sources":["../src/import-resolution-diagnostics.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAkB,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAIrE,OAAO,EAAsB,KAAK,kBAAkB,EAAE,MAAM,YAAY,CAAC;AA8BzE;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,WAAW,GAAG,kBAAkB,EAAE,CAepF"}
@@ -0,0 +1,59 @@
1
+ import { isLocalPathSource } from "./sources/local-path-ref.js";
2
+ import { isRegistryRef } from "./sources/module-ref.js";
3
+ import { isOciRef } from "./sources/oci-ref.js";
4
+ import { DiagnosticSeverity } from "./types.js";
5
+ const SOURCE = "telo-analyzer";
6
+ /** True when `source` is a shape some transport claims — a registry ref, an OCI
7
+ * ref, an HTTP(S) URL, or a relative/absolute path. A source matching none of
8
+ * these is malformed (no transport can ever resolve it), which we report
9
+ * differently from a well-formed ref that simply failed to fetch. */
10
+ function isRecognizedSourceShape(source) {
11
+ return (isRegistryRef(source) ||
12
+ isOciRef(source) ||
13
+ source.startsWith("http://") ||
14
+ source.startsWith("https://") ||
15
+ isLocalPathSource(source));
16
+ }
17
+ function messageFor(e, malformed) {
18
+ const authored = e.source ?? e.url;
19
+ const via = e.alias ? `import '${e.alias}' → '${authored}'` : `'${authored}'`;
20
+ if (malformed) {
21
+ return (`Cannot resolve ${via}: not a recognized module reference. Expected ` +
22
+ `'namespace/name@version', 'oci://host/repo@tag', 'https://…', or a relative path.`);
23
+ }
24
+ return `Cannot resolve ${via}: ${e.error.message}`;
25
+ }
26
+ /**
27
+ * Convert a graph's import-resolution failures (`graph.errors`) into structured,
28
+ * coded diagnostics. This is the single source of truth for surfacing a broken
29
+ * import — every host (CLI, VS Code, telo-editor) routes these instead of each
30
+ * re-deriving the channel and drifting (the VS Code extension used to drop it
31
+ * entirely, showing nothing for a broken import).
32
+ *
33
+ * The analyzer owns only this raw channel conversion; the *presentation* policy
34
+ * — which analysis cascade to hold back for a compromised file — lives in
35
+ * `@telorun/ide-support`'s `assembleGraphDiagnostics`.
36
+ *
37
+ * Each diagnostic adopts the same `data` shape as version-reconciliation
38
+ * diagnostics — `{ filePath, path: "imports.<alias>" }` — so the shared
39
+ * `findPositions` / `resolveRange` routing anchors it on the offending import
40
+ * line with no host-specific code.
41
+ */
42
+ export function importResolutionDiagnostics(graph) {
43
+ return graph.errors.map((e) => {
44
+ const filePath = e.fromSource ?? graph.entry.owner.source;
45
+ const malformed = !isRecognizedSourceShape(e.source ?? e.url);
46
+ const data = { filePath };
47
+ if (e.alias)
48
+ data.path = `imports.${e.alias}`;
49
+ if (e.sourceLine !== undefined)
50
+ data.sourceLine = e.sourceLine;
51
+ return {
52
+ severity: DiagnosticSeverity.Error,
53
+ code: malformed ? "INVALID_IMPORT_SOURCE" : "IMPORT_UNRESOLVED",
54
+ source: SOURCE,
55
+ message: messageFor(e, malformed),
56
+ data,
57
+ };
58
+ });
59
+ }
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  export { AnalysisRegistry } from "./analysis-registry.js";
2
2
  export type { RefFieldInfo } from "./analysis-registry.js";
3
3
  export { StaticAnalyzer } from "./analyzer.js";
4
+ export { importResolutionDiagnostics } from "./import-resolution-diagnostics.js";
4
5
  export type { GraphLoadError, ImportEdge, LoadedFile, LoadedGraph, LoadedModule, ParseError, } from "./loaded-types.js";
5
6
  export { flattenForAnalyzer, flattenLoadedModule, forwardReExportManifests, parseExportEntry, reExportSpecsFromExports, resolveExportedKinds, selectModuleManifestsForAnalysis, stampExportedKinds, stampReExportedKinds, type ParsedExportEntry, type ReExportSpec, } from "./flatten-for-analyzer.js";
6
7
  export { buildEvalPaths, evalPathCovers } from "./eval-paths.js";
@@ -32,6 +33,7 @@ export { parseModuleRef, isRegistryRef } from "./sources/module-ref.js";
32
33
  export type { ParsedModuleRef } from "./sources/module-ref.js";
33
34
  export { OCI_SCHEME, isOciRef, parseOciRef } from "./sources/oci-ref.js";
34
35
  export type { ParsedOciRef } from "./sources/oci-ref.js";
36
+ export { isLocalPathSource } from "./sources/local-path-ref.js";
35
37
  export { MANIFEST_CACHE_BASE_URL, ManifestCacheSource, isHttpsModuleRef, manifestCacheKey, manifestCacheUrl, ociManifestCacheCoords, urlManifestCacheCoords, } from "./sources/manifest-cache.js";
36
38
  export type { ManifestCacheCoords } from "./sources/manifest-cache.js";
37
39
  export { withSyntheticPositions } from "./with-synthetic-positions.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  export { AnalysisRegistry } from "./analysis-registry.js";
2
2
  export { StaticAnalyzer } from "./analyzer.js";
3
+ export { importResolutionDiagnostics } from "./import-resolution-diagnostics.js";
3
4
  export { flattenForAnalyzer, flattenLoadedModule, forwardReExportManifests, parseExportEntry, reExportSpecsFromExports, resolveExportedKinds, selectModuleManifestsForAnalysis, stampExportedKinds, stampReExportedKinds, } from "./flatten-for-analyzer.js";
4
5
  export { buildEvalPaths, evalPathCovers } from "./eval-paths.js";
5
6
  export { ancestorChain, controllerBearingAncestor, effectiveAuthorSchema, hasOwnControllerOrTemplate, inheritedCapability, isInheritedDelegation, resolveParent, } from "./extends-resolution.js";
@@ -19,6 +20,7 @@ export { defaultSources } from "./sources/default-sources.js";
19
20
  export { splitIntegrity, foldIntegrity, verifyIntegrity, verifiedFetch, sha256Base64Url, IntegrityError, } from "./sources/integrity.js";
20
21
  export { parseModuleRef, isRegistryRef } from "./sources/module-ref.js";
21
22
  export { OCI_SCHEME, isOciRef, parseOciRef } from "./sources/oci-ref.js";
23
+ export { isLocalPathSource } from "./sources/local-path-ref.js";
22
24
  export { MANIFEST_CACHE_BASE_URL, ManifestCacheSource, isHttpsModuleRef, manifestCacheKey, manifestCacheUrl, ociManifestCacheCoords, urlManifestCacheCoords, } from "./sources/manifest-cache.js";
23
25
  export { withSyntheticPositions } from "./with-synthetic-positions.js";
24
26
  export { DEFAULT_MANIFEST_FILENAME, DiagnosticSeverity } from "./types.js";
@@ -90,10 +90,21 @@ export interface LoadedGraph {
90
90
  errors: GraphLoadError[];
91
91
  }
92
92
  export interface GraphLoadError {
93
- /** URL of the file that failed to load. */
93
+ /** URL of the file that failed to load (resolved — may be a `file://` URL for
94
+ * a relative import). */
94
95
  url: string;
96
+ /** The import source string exactly as authored (`./lib`, `std/x@1.0.0`),
97
+ * before relative-path resolution. Preferred over `url` for classification
98
+ * and display, so a diagnostic quotes what the author wrote. */
99
+ source?: string;
95
100
  /** Source of the import that triggered the load, or null for the entry. */
96
101
  fromSource: string | null;
102
+ /** Import alias the failed source was bound to in `fromSource`'s `imports:`
103
+ * map, when the failure is a transitive import (absent for an entry-load
104
+ * failure). Lets a consumer anchor the diagnostic at `imports.<alias>`. */
105
+ alias?: string;
106
+ /** Line of the `Telo.Import` doc in `fromSource`, for position fallback. */
107
+ sourceLine?: number;
97
108
  error: Error;
98
109
  }
99
110
  //# sourceMappingURL=loaded-types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"loaded-types.d.ts","sourceRoot":"","sources":["../src/loaded-types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,KAAK,EAAE,kBAAkB,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAE5D;;;;4EAI4E;AAC5E,MAAM,WAAW,UAAU;IACzB;+DAC2D;IAC3D,MAAM,EAAE,MAAM,CAAC;IACf;gEAC4D;IAC5D,YAAY,EAAE,MAAM,CAAC;IACrB,gDAAgD;IAChD,IAAI,EAAE,MAAM,CAAC;IACb,gDAAgD;IAChD,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,6EAA6E;IAC7E,SAAS,EAAE,KAAK,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;IAC1C,0EAA0E;IAC1E,SAAS,EAAE,gBAAgB,EAAE,CAAC;IAC9B,0EAA0E;IAC1E,WAAW,EAAE,UAAU,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,UAAU;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,wEAAwE;IACxE,KAAK,CAAC,EAAE,KAAK,CAAC;CACf;AAED;mCACmC;AACnC,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,UAAU,CAAC;IAClB;oEACgE;IAChE,QAAQ,EAAE,UAAU,EAAE,CAAC;CACxB;AAED;;;;;2EAK2E;AAC3E,MAAM,WAAW,UAAU;IACzB,mEAAmE;IACnE,YAAY,EAAE,MAAM,CAAC;IACrB;6EACyE;IACzE,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,oEAAoE;IACpE,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAED;0BAC0B;AAC1B,MAAM,WAAW,WAAW;IAC1B,4DAA4D;IAC5D,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,YAAY,CAAC;IACpB;;wBAEoB;IACpB,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IACnC;;;;2BAIuB;IACvB,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;IAClD;;;iFAG6E;IAC7E,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B;;;iDAG6C;IAC7C,kBAAkB,EAAE,kBAAkB,EAAE,CAAC;IACzC;;;8EAG0E;IAC1E,gBAAgB,EAAE,kBAAkB,EAAE,CAAC;IACvC;yCACqC;IACrC,MAAM,EAAE,cAAc,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,cAAc;IAC7B,2CAA2C;IAC3C,GAAG,EAAE,MAAM,CAAC;IACZ,2EAA2E;IAC3E,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,KAAK,EAAE,KAAK,CAAC;CACd"}
1
+ {"version":3,"file":"loaded-types.d.ts","sourceRoot":"","sources":["../src/loaded-types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,KAAK,EAAE,kBAAkB,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAE5D;;;;4EAI4E;AAC5E,MAAM,WAAW,UAAU;IACzB;+DAC2D;IAC3D,MAAM,EAAE,MAAM,CAAC;IACf;gEAC4D;IAC5D,YAAY,EAAE,MAAM,CAAC;IACrB,gDAAgD;IAChD,IAAI,EAAE,MAAM,CAAC;IACb,gDAAgD;IAChD,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,6EAA6E;IAC7E,SAAS,EAAE,KAAK,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;IAC1C,0EAA0E;IAC1E,SAAS,EAAE,gBAAgB,EAAE,CAAC;IAC9B,0EAA0E;IAC1E,WAAW,EAAE,UAAU,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,UAAU;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,wEAAwE;IACxE,KAAK,CAAC,EAAE,KAAK,CAAC;CACf;AAED;mCACmC;AACnC,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,UAAU,CAAC;IAClB;oEACgE;IAChE,QAAQ,EAAE,UAAU,EAAE,CAAC;CACxB;AAED;;;;;2EAK2E;AAC3E,MAAM,WAAW,UAAU;IACzB,mEAAmE;IACnE,YAAY,EAAE,MAAM,CAAC;IACrB;6EACyE;IACzE,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,oEAAoE;IACpE,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAED;0BAC0B;AAC1B,MAAM,WAAW,WAAW;IAC1B,4DAA4D;IAC5D,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,YAAY,CAAC;IACpB;;wBAEoB;IACpB,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IACnC;;;;2BAIuB;IACvB,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;IAClD;;;iFAG6E;IAC7E,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B;;;iDAG6C;IAC7C,kBAAkB,EAAE,kBAAkB,EAAE,CAAC;IACzC;;;8EAG0E;IAC1E,gBAAgB,EAAE,kBAAkB,EAAE,CAAC;IACvC;yCACqC;IACrC,MAAM,EAAE,cAAc,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,cAAc;IAC7B;8BAC0B;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ;;qEAEiE;IACjE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2EAA2E;IAC3E,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B;;gFAE4E;IAC5E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4EAA4E;IAC5E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,KAAK,CAAC;CACd"}
@@ -1 +1 @@
1
- {"version":3,"file":"manifest-loader.d.ts","sourceRoot":"","sources":["../src/manifest-loader.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAGV,UAAU,EACV,WAAW,EACX,YAAY,EACb,MAAM,mBAAmB,CAAC;AAK3B,OAAO,EAIL,KAAK,WAAW,EAChB,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACpB,MAAM,YAAY,CAAC;AAwCpB,qBAAa,MAAM;IACjB;;;yEAGqE;IACrE,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAiC;IAE3D;;;;;8BAK0B;IAC1B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA6B;IAEzD,SAAS,CAAC,OAAO,EAAE,cAAc,EAAE,CAAC;IACpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAc;IAErC;;;;mBAIe;gBACH,OAAO,GAAE,cAAc,EAAO,EAAE,OAAO,GAAE,iBAAsB;IAK3E,QAAQ,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI;IAKtC,OAAO,CAAC,IAAI;IAMN,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAUrD;;;;2CAIuC;IACvC,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAM7C;;;+BAG2B;IACrB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC;IAyCvE;;;;gEAI4D;IAC5D,OAAO,CAAC,oBAAoB;IAa5B;gFAC4E;IAC5E,OAAO,CAAC,cAAc;IAQtB;;wEAEoE;IAC9D,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;IAsB3E;;;qCAGiC;IAC3B,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;IAsH9E;;;;;;;;sBAQkB;IAClB,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM;IAOlE,OAAO,CAAC,6BAA6B;IAarC,OAAO,CAAC,mCAAmC;IAc3C,OAAO,CAAC,2BAA2B;YAkCrB,eAAe;IAmB7B;;;0CAGsC;IAChC,gBAAgB,CACpB,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC;QAAE,KAAK,EAAE,WAAW,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CA0B5D"}
1
+ {"version":3,"file":"manifest-loader.d.ts","sourceRoot":"","sources":["../src/manifest-loader.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAGV,UAAU,EACV,WAAW,EACX,YAAY,EACb,MAAM,mBAAmB,CAAC;AAK3B,OAAO,EAIL,KAAK,WAAW,EAChB,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACpB,MAAM,YAAY,CAAC;AAwCpB,qBAAa,MAAM;IACjB;;;yEAGqE;IACrE,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAiC;IAE3D;;;;;8BAK0B;IAC1B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA6B;IAEzD,SAAS,CAAC,OAAO,EAAE,cAAc,EAAE,CAAC;IACpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAc;IAErC;;;;mBAIe;gBACH,OAAO,GAAE,cAAc,EAAO,EAAE,OAAO,GAAE,iBAAsB;IAK3E,QAAQ,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI;IAKtC,OAAO,CAAC,IAAI;IAMN,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAUrD;;;;2CAIuC;IACvC,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAM7C;;;+BAG2B;IACrB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC;IAyCvE;;;;gEAI4D;IAC5D,OAAO,CAAC,oBAAoB;IAa5B;gFAC4E;IAC5E,OAAO,CAAC,cAAc;IAQtB;;wEAEoE;IAC9D,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;IAsB3E;;;qCAGiC;IAC3B,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;IAgI9E;;;;;;;;sBAQkB;IAClB,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM;IAOlE,OAAO,CAAC,6BAA6B;IAarC,OAAO,CAAC,mCAAmC;IAc3C,OAAO,CAAC,2BAA2B;YAkCrB,eAAe;IAmB7B;;;0CAGsC;IAChC,gBAAgB,CACpB,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC;QAAE,KAAK,EAAE,WAAW,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CA0B5D"}
@@ -215,7 +215,10 @@ export class Loader {
215
215
  catch (err) {
216
216
  errors.push({
217
217
  url: importSource,
218
+ source: importSource,
218
219
  fromSource: file.source,
220
+ alias,
221
+ sourceLine,
219
222
  error: err instanceof Error ? err : new Error(String(err)),
220
223
  });
221
224
  continue;
@@ -243,7 +246,14 @@ export class Loader {
243
246
  catch (err) {
244
247
  const e = err instanceof Error ? err : new Error(String(err));
245
248
  e.sourceLine = sourceLine;
246
- errors.push({ url: resolvedTarget, fromSource: file.source, error: e });
249
+ errors.push({
250
+ url: resolvedTarget,
251
+ source: importSource,
252
+ fromSource: file.source,
253
+ alias,
254
+ sourceLine,
255
+ error: e,
256
+ });
247
257
  continue;
248
258
  }
249
259
  }
@@ -0,0 +1,4 @@
1
+ /** True when `source` names an on-disk sibling manifest — a relative (`./`,
2
+ * `../`) or absolute (`/`) path — rather than a transport-owned remote ref. */
3
+ export declare function isLocalPathSource(source: string): boolean;
4
+ //# sourceMappingURL=local-path-ref.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-path-ref.d.ts","sourceRoot":"","sources":["../../src/sources/local-path-ref.ts"],"names":[],"mappings":"AAAA;gFACgF;AAChF,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEzD"}
@@ -0,0 +1,5 @@
1
+ /** True when `source` names an on-disk sibling manifest — a relative (`./`,
2
+ * `../`) or absolute (`/`) path — rather than a transport-owned remote ref. */
3
+ export function isLocalPathSource(source) {
4
+ return source.startsWith(".") || source.startsWith("/");
5
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@telorun/analyzer",
3
- "version": "0.39.0",
3
+ "version": "0.40.0",
4
4
  "description": "Telo Analyzer - Static manifest validator for Telo manifests.",
5
5
  "keywords": [
6
6
  "telo",
@@ -0,0 +1,66 @@
1
+ import type { GraphLoadError, LoadedGraph } from "./loaded-types.js";
2
+ import { isLocalPathSource } from "./sources/local-path-ref.js";
3
+ import { isRegistryRef } from "./sources/module-ref.js";
4
+ import { isOciRef } from "./sources/oci-ref.js";
5
+ import { DiagnosticSeverity, type AnalysisDiagnostic } from "./types.js";
6
+
7
+ const SOURCE = "telo-analyzer";
8
+
9
+ /** True when `source` is a shape some transport claims — a registry ref, an OCI
10
+ * ref, an HTTP(S) URL, or a relative/absolute path. A source matching none of
11
+ * these is malformed (no transport can ever resolve it), which we report
12
+ * differently from a well-formed ref that simply failed to fetch. */
13
+ function isRecognizedSourceShape(source: string): boolean {
14
+ return (
15
+ isRegistryRef(source) ||
16
+ isOciRef(source) ||
17
+ source.startsWith("http://") ||
18
+ source.startsWith("https://") ||
19
+ isLocalPathSource(source)
20
+ );
21
+ }
22
+
23
+ function messageFor(e: GraphLoadError, malformed: boolean): string {
24
+ const authored = e.source ?? e.url;
25
+ const via = e.alias ? `import '${e.alias}' → '${authored}'` : `'${authored}'`;
26
+ if (malformed) {
27
+ return (
28
+ `Cannot resolve ${via}: not a recognized module reference. Expected ` +
29
+ `'namespace/name@version', 'oci://host/repo@tag', 'https://…', or a relative path.`
30
+ );
31
+ }
32
+ return `Cannot resolve ${via}: ${e.error.message}`;
33
+ }
34
+
35
+ /**
36
+ * Convert a graph's import-resolution failures (`graph.errors`) into structured,
37
+ * coded diagnostics. This is the single source of truth for surfacing a broken
38
+ * import — every host (CLI, VS Code, telo-editor) routes these instead of each
39
+ * re-deriving the channel and drifting (the VS Code extension used to drop it
40
+ * entirely, showing nothing for a broken import).
41
+ *
42
+ * The analyzer owns only this raw channel conversion; the *presentation* policy
43
+ * — which analysis cascade to hold back for a compromised file — lives in
44
+ * `@telorun/ide-support`'s `assembleGraphDiagnostics`.
45
+ *
46
+ * Each diagnostic adopts the same `data` shape as version-reconciliation
47
+ * diagnostics — `{ filePath, path: "imports.<alias>" }` — so the shared
48
+ * `findPositions` / `resolveRange` routing anchors it on the offending import
49
+ * line with no host-specific code.
50
+ */
51
+ export function importResolutionDiagnostics(graph: LoadedGraph): AnalysisDiagnostic[] {
52
+ return graph.errors.map((e) => {
53
+ const filePath = e.fromSource ?? graph.entry.owner.source;
54
+ const malformed = !isRecognizedSourceShape(e.source ?? e.url);
55
+ const data: { filePath: string; path?: string; sourceLine?: number } = { filePath };
56
+ if (e.alias) data.path = `imports.${e.alias}`;
57
+ if (e.sourceLine !== undefined) data.sourceLine = e.sourceLine;
58
+ return {
59
+ severity: DiagnosticSeverity.Error,
60
+ code: malformed ? "INVALID_IMPORT_SOURCE" : "IMPORT_UNRESOLVED",
61
+ source: SOURCE,
62
+ message: messageFor(e, malformed),
63
+ data,
64
+ };
65
+ });
66
+ }
package/src/index.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  export { AnalysisRegistry } from "./analysis-registry.js";
2
2
  export type { RefFieldInfo } from "./analysis-registry.js";
3
3
  export { StaticAnalyzer } from "./analyzer.js";
4
+ export { importResolutionDiagnostics } from "./import-resolution-diagnostics.js";
4
5
  export type {
5
6
  GraphLoadError,
6
7
  ImportEdge,
@@ -84,6 +85,7 @@ export { parseModuleRef, isRegistryRef } from "./sources/module-ref.js";
84
85
  export type { ParsedModuleRef } from "./sources/module-ref.js";
85
86
  export { OCI_SCHEME, isOciRef, parseOciRef } from "./sources/oci-ref.js";
86
87
  export type { ParsedOciRef } from "./sources/oci-ref.js";
88
+ export { isLocalPathSource } from "./sources/local-path-ref.js";
87
89
  export {
88
90
  MANIFEST_CACHE_BASE_URL,
89
91
  ManifestCacheSource,
@@ -96,9 +96,20 @@ export interface LoadedGraph {
96
96
  }
97
97
 
98
98
  export interface GraphLoadError {
99
- /** URL of the file that failed to load. */
99
+ /** URL of the file that failed to load (resolved — may be a `file://` URL for
100
+ * a relative import). */
100
101
  url: string;
102
+ /** The import source string exactly as authored (`./lib`, `std/x@1.0.0`),
103
+ * before relative-path resolution. Preferred over `url` for classification
104
+ * and display, so a diagnostic quotes what the author wrote. */
105
+ source?: string;
101
106
  /** Source of the import that triggered the load, or null for the entry. */
102
107
  fromSource: string | null;
108
+ /** Import alias the failed source was bound to in `fromSource`'s `imports:`
109
+ * map, when the failure is a transitive import (absent for an entry-load
110
+ * failure). Lets a consumer anchor the diagnostic at `imports.<alias>`. */
111
+ alias?: string;
112
+ /** Line of the `Telo.Import` doc in `fromSource`, for position fallback. */
113
+ sourceLine?: number;
103
114
  error: Error;
104
115
  }
@@ -258,7 +258,10 @@ export class Loader {
258
258
  } catch (err) {
259
259
  errors.push({
260
260
  url: importSource,
261
+ source: importSource,
261
262
  fromSource: file.source,
263
+ alias,
264
+ sourceLine,
262
265
  error: err instanceof Error ? err : new Error(String(err)),
263
266
  });
264
267
  continue;
@@ -284,7 +287,14 @@ export class Loader {
284
287
  } catch (err) {
285
288
  const e = err instanceof Error ? err : new Error(String(err));
286
289
  (e as { sourceLine?: number }).sourceLine = sourceLine;
287
- errors.push({ url: resolvedTarget, fromSource: file.source, error: e });
290
+ errors.push({
291
+ url: resolvedTarget,
292
+ source: importSource,
293
+ fromSource: file.source,
294
+ alias,
295
+ sourceLine,
296
+ error: e,
297
+ });
288
298
  continue;
289
299
  }
290
300
  }
@@ -0,0 +1,5 @@
1
+ /** True when `source` names an on-disk sibling manifest — a relative (`./`,
2
+ * `../`) or absolute (`/`) path — rather than a transport-owned remote ref. */
3
+ export function isLocalPathSource(source: string): boolean {
4
+ return source.startsWith(".") || source.startsWith("/");
5
+ }