@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.
- package/dist/import-resolution-diagnostics.d.ts +20 -0
- package/dist/import-resolution-diagnostics.d.ts.map +1 -0
- package/dist/import-resolution-diagnostics.js +59 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/loaded-types.d.ts +12 -1
- package/dist/loaded-types.d.ts.map +1 -1
- package/dist/manifest-loader.d.ts.map +1 -1
- package/dist/manifest-loader.js +11 -1
- package/dist/sources/local-path-ref.d.ts +4 -0
- package/dist/sources/local-path-ref.d.ts.map +1 -0
- package/dist/sources/local-path-ref.js +5 -0
- package/package.json +1 -1
- package/src/import-resolution-diagnostics.ts +66 -0
- package/src/index.ts +2 -0
- package/src/loaded-types.ts +12 -1
- package/src/manifest-loader.ts +11 -1
- package/src/sources/local-path-ref.ts +5 -0
|
@@ -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";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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";
|
package/dist/loaded-types.d.ts
CHANGED
|
@@ -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
|
|
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;
|
|
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"}
|
package/dist/manifest-loader.js
CHANGED
|
@@ -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({
|
|
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"}
|
package/package.json
CHANGED
|
@@ -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,
|
package/src/loaded-types.ts
CHANGED
|
@@ -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
|
}
|
package/src/manifest-loader.ts
CHANGED
|
@@ -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({
|
|
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
|
+
}
|