@telorun/analyzer 0.13.0 → 0.14.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/adapters/http-adapter.d.ts +10 -0
- package/dist/adapters/http-adapter.d.ts.map +1 -0
- package/dist/adapters/http-adapter.js +18 -0
- package/dist/adapters/node-adapter.d.ts +17 -0
- package/dist/adapters/node-adapter.d.ts.map +1 -0
- package/dist/adapters/node-adapter.js +71 -0
- package/dist/adapters/registry-adapter.d.ts +15 -0
- package/dist/adapters/registry-adapter.d.ts.map +1 -0
- package/dist/adapters/registry-adapter.js +53 -0
- package/dist/alias-resolver.d.ts +6 -0
- package/dist/alias-resolver.d.ts.map +1 -1
- package/dist/alias-resolver.js +8 -0
- package/dist/analysis-registry.d.ts +1 -0
- package/dist/analysis-registry.d.ts.map +1 -1
- package/dist/analyzer.d.ts +1 -1
- package/dist/analyzer.d.ts.map +1 -1
- package/dist/analyzer.js +113 -5
- package/dist/builtins.d.ts.map +1 -1
- package/dist/builtins.js +61 -0
- package/dist/flatten-for-analyzer.d.ts.map +1 -1
- package/dist/flatten-for-analyzer.js +13 -0
- package/dist/manifest-visitor.d.ts +15 -0
- package/dist/manifest-visitor.d.ts.map +1 -1
- package/dist/manifest-visitor.js +73 -2
- package/dist/reference-field-map.js +16 -0
- package/dist/resolve-ref-sentinels.d.ts +15 -17
- package/dist/resolve-ref-sentinels.d.ts.map +1 -1
- package/dist/resolve-ref-sentinels.js +94 -40
- package/dist/resolve-throws-union.d.ts +10 -0
- package/dist/resolve-throws-union.d.ts.map +1 -1
- package/dist/resolve-throws-union.js +35 -7
- package/dist/validate-references.d.ts.map +1 -1
- package/dist/validate-references.js +105 -7
- package/package.json +3 -3
- package/src/analysis-registry.ts +1 -1
- package/src/analyzer.ts +100 -0
- package/src/builtins.ts +60 -0
- package/src/manifest-visitor.ts +91 -2
- package/src/reference-field-map.ts +14 -0
- package/src/resolve-throws-union.ts +36 -8
- package/src/validate-references.ts +7 -0
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type ManifestAdapter } from "../types.js";
|
|
2
|
+
export declare class HttpAdapter implements ManifestAdapter {
|
|
3
|
+
supports(url: string): boolean;
|
|
4
|
+
read(url: string): Promise<{
|
|
5
|
+
text: string;
|
|
6
|
+
source: string;
|
|
7
|
+
}>;
|
|
8
|
+
resolveRelative(base: string, relative: string): string;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=http-adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-adapter.d.ts","sourceRoot":"","sources":["../../src/adapters/http-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAA6B,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9E,qBAAa,WAAY,YAAW,eAAe;IACjD,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAIxB,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAWlE,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM;CAIxD"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { DEFAULT_MANIFEST_FILENAME } from "../types.js";
|
|
2
|
+
export class HttpAdapter {
|
|
3
|
+
supports(url) {
|
|
4
|
+
return url.startsWith("http://") || url.startsWith("https://");
|
|
5
|
+
}
|
|
6
|
+
async read(url) {
|
|
7
|
+
const fetchUrl = url.includes(".yaml") ? url : `${url}/${DEFAULT_MANIFEST_FILENAME}`;
|
|
8
|
+
const response = await fetch(fetchUrl);
|
|
9
|
+
if (!response.ok) {
|
|
10
|
+
throw new Error(`Failed to fetch manifest from ${fetchUrl}: ${response.status} ${response.statusText}`);
|
|
11
|
+
}
|
|
12
|
+
return { text: await response.text(), source: fetchUrl };
|
|
13
|
+
}
|
|
14
|
+
resolveRelative(base, relative) {
|
|
15
|
+
const baseDir = base.endsWith("/") ? base : base.slice(0, base.lastIndexOf("/") + 1);
|
|
16
|
+
return new URL(relative, baseDir).href;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type ManifestAdapter } from "../types.js";
|
|
2
|
+
/** Node.js fs-based ManifestAdapter for local files. Not browser-compatible. */
|
|
3
|
+
export declare class NodeAdapter implements ManifestAdapter {
|
|
4
|
+
private readonly cwd;
|
|
5
|
+
constructor(cwd?: string);
|
|
6
|
+
supports(url: string): boolean;
|
|
7
|
+
read(url: string): Promise<{
|
|
8
|
+
text: string;
|
|
9
|
+
source: string;
|
|
10
|
+
}>;
|
|
11
|
+
resolveRelative(base: string, relative: string): string;
|
|
12
|
+
expandGlob(base: string, patterns: string[]): Promise<string[]>;
|
|
13
|
+
resolveOwnerOf(fileUrl: string): Promise<string | null>;
|
|
14
|
+
}
|
|
15
|
+
/** @deprecated Use `new NodeAdapter(cwd)` instead */
|
|
16
|
+
export declare function createNodeAdapter(cwd?: string): ManifestAdapter;
|
|
17
|
+
//# sourceMappingURL=node-adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node-adapter.d.ts","sourceRoot":"","sources":["../../src/adapters/node-adapter.ts"],"names":[],"mappings":"AAIA,OAAO,EAA6B,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AAM9E,gFAAgF;AAChF,qBAAa,WAAY,YAAW,eAAe;IACrC,OAAO,CAAC,QAAQ,CAAC,GAAG;gBAAH,GAAG,GAAE,MAAsB;IAExD,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAUxB,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IASlE,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM;IAKjD,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAc/D,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;CAoB9D;AAED,qDAAqD;AACrD,wBAAgB,iBAAiB,CAAC,GAAG,GAAE,MAAsB,GAAG,eAAe,CAE9E"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import * as fs from "fs/promises";
|
|
2
|
+
import * as path from "path";
|
|
3
|
+
import { fileURLToPath } from "url";
|
|
4
|
+
import { minimatch } from "minimatch";
|
|
5
|
+
import { DEFAULT_MANIFEST_FILENAME } from "../types.js";
|
|
6
|
+
function toFilePath(url) {
|
|
7
|
+
return url.startsWith("file://") ? fileURLToPath(url) : url;
|
|
8
|
+
}
|
|
9
|
+
/** Node.js fs-based ManifestAdapter for local files. Not browser-compatible. */
|
|
10
|
+
export class NodeAdapter {
|
|
11
|
+
cwd;
|
|
12
|
+
constructor(cwd = process.cwd()) {
|
|
13
|
+
this.cwd = cwd;
|
|
14
|
+
}
|
|
15
|
+
supports(url) {
|
|
16
|
+
return (url.startsWith("file://") ||
|
|
17
|
+
url.startsWith("/") ||
|
|
18
|
+
url.startsWith("./") ||
|
|
19
|
+
url.startsWith("../") ||
|
|
20
|
+
(!url.includes("://") && !url.includes("@")));
|
|
21
|
+
}
|
|
22
|
+
async read(url) {
|
|
23
|
+
const filePath = toFilePath(url);
|
|
24
|
+
const stat = await fs.stat(filePath).catch(() => null);
|
|
25
|
+
const resolvedPath = stat?.isDirectory() ? path.join(filePath, DEFAULT_MANIFEST_FILENAME) : filePath;
|
|
26
|
+
const text = await fs.readFile(resolvedPath, "utf8");
|
|
27
|
+
return { text, source: resolvedPath };
|
|
28
|
+
}
|
|
29
|
+
resolveRelative(base, relative) {
|
|
30
|
+
const baseDir = path.dirname(path.resolve(this.cwd, toFilePath(base)));
|
|
31
|
+
return path.resolve(baseDir, relative);
|
|
32
|
+
}
|
|
33
|
+
async expandGlob(base, patterns) {
|
|
34
|
+
const baseDir = path.dirname(path.resolve(this.cwd, toFilePath(base)));
|
|
35
|
+
const entries = await fs.readdir(baseDir, { recursive: true, encoding: "utf8" });
|
|
36
|
+
const normalizedPatterns = patterns.map((p) => p.replace(/\\/g, "/").replace(/^\.\//, ""));
|
|
37
|
+
const matched = [];
|
|
38
|
+
for (const entry of entries) {
|
|
39
|
+
const normalized = entry.replace(/\\/g, "/");
|
|
40
|
+
if (normalizedPatterns.some((p) => minimatch(normalized, p))) {
|
|
41
|
+
matched.push(path.resolve(baseDir, entry));
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return matched.sort();
|
|
45
|
+
}
|
|
46
|
+
async resolveOwnerOf(fileUrl) {
|
|
47
|
+
const resolved = path.resolve(this.cwd, toFilePath(fileUrl));
|
|
48
|
+
let dir = path.dirname(resolved);
|
|
49
|
+
while (true) {
|
|
50
|
+
const candidate = path.join(dir, DEFAULT_MANIFEST_FILENAME);
|
|
51
|
+
if (candidate !== resolved) {
|
|
52
|
+
try {
|
|
53
|
+
await fs.access(candidate);
|
|
54
|
+
return candidate;
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
// telo.yaml not found at this level
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
const parent = path.dirname(dir);
|
|
61
|
+
if (parent === dir)
|
|
62
|
+
break;
|
|
63
|
+
dir = parent;
|
|
64
|
+
}
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/** @deprecated Use `new NodeAdapter(cwd)` instead */
|
|
69
|
+
export function createNodeAdapter(cwd = process.cwd()) {
|
|
70
|
+
return new NodeAdapter(cwd);
|
|
71
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type ManifestAdapter } from "../types.js";
|
|
2
|
+
export declare class RegistryAdapter implements ManifestAdapter {
|
|
3
|
+
private registryUrl;
|
|
4
|
+
constructor(registryUrl?: string);
|
|
5
|
+
supports(url: string): boolean;
|
|
6
|
+
read(moduleRef: string): Promise<{
|
|
7
|
+
text: string;
|
|
8
|
+
source: string;
|
|
9
|
+
}>;
|
|
10
|
+
resolveRelative(base: string, relative: string): string;
|
|
11
|
+
private toRegistryModuleBase;
|
|
12
|
+
private toRegistryUrl;
|
|
13
|
+
private parseModuleRef;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=registry-adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry-adapter.d.ts","sourceRoot":"","sources":["../../src/adapters/registry-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAA6B,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AAI9E,qBAAa,eAAgB,YAAW,eAAe;IACzC,OAAO,CAAC,WAAW;gBAAX,WAAW,SAAuB;IAEtD,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAWxB,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAWxE,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM;IAMvD,OAAO,CAAC,oBAAoB;IAM5B,OAAO,CAAC,aAAa;IAIrB,OAAO,CAAC,cAAc;CAmBvB"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { DEFAULT_MANIFEST_FILENAME } from "../types.js";
|
|
2
|
+
const DEFAULT_REGISTRY_URL = "https://registry.telo.run";
|
|
3
|
+
export class RegistryAdapter {
|
|
4
|
+
registryUrl;
|
|
5
|
+
constructor(registryUrl = DEFAULT_REGISTRY_URL) {
|
|
6
|
+
this.registryUrl = registryUrl;
|
|
7
|
+
}
|
|
8
|
+
supports(url) {
|
|
9
|
+
return (!url.startsWith("http://") &&
|
|
10
|
+
!url.startsWith("https://") &&
|
|
11
|
+
!url.startsWith("/") &&
|
|
12
|
+
!url.startsWith(".") &&
|
|
13
|
+
url.includes("@") &&
|
|
14
|
+
url.includes("/"));
|
|
15
|
+
}
|
|
16
|
+
async read(moduleRef) {
|
|
17
|
+
const fetchUrl = this.toRegistryUrl(moduleRef);
|
|
18
|
+
const response = await fetch(fetchUrl);
|
|
19
|
+
if (!response.ok) {
|
|
20
|
+
throw new Error(`Failed to fetch manifest ${moduleRef}: ${response.status} ${response.statusText}`);
|
|
21
|
+
}
|
|
22
|
+
return { text: await response.text(), source: fetchUrl };
|
|
23
|
+
}
|
|
24
|
+
resolveRelative(base, relative) {
|
|
25
|
+
const baseUrl = this.supports(base) ? this.toRegistryModuleBase(base) : base;
|
|
26
|
+
const baseWithSlash = baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`;
|
|
27
|
+
return new URL(relative, baseWithSlash).href;
|
|
28
|
+
}
|
|
29
|
+
toRegistryModuleBase(moduleRef) {
|
|
30
|
+
const parsed = this.parseModuleRef(moduleRef);
|
|
31
|
+
const normalizedBase = this.registryUrl.replace(/\/+$/, "");
|
|
32
|
+
return `${normalizedBase}/${parsed.modulePath}/${parsed.version}`;
|
|
33
|
+
}
|
|
34
|
+
toRegistryUrl(moduleRef) {
|
|
35
|
+
return `${this.toRegistryModuleBase(moduleRef)}/${DEFAULT_MANIFEST_FILENAME}`;
|
|
36
|
+
}
|
|
37
|
+
parseModuleRef(moduleRef) {
|
|
38
|
+
const atIdx = moduleRef.lastIndexOf("@");
|
|
39
|
+
if (atIdx <= 0 || atIdx === moduleRef.length - 1) {
|
|
40
|
+
throw new Error(`Invalid module reference '${moduleRef}', expected namespace/name@version`);
|
|
41
|
+
}
|
|
42
|
+
const modulePath = moduleRef.slice(0, atIdx);
|
|
43
|
+
if (!modulePath.includes("/")) {
|
|
44
|
+
throw new Error(`Invalid module reference '${moduleRef}', expected namespace/name@version`);
|
|
45
|
+
}
|
|
46
|
+
const rawVersion = moduleRef.slice(atIdx + 1);
|
|
47
|
+
const version = rawVersion.startsWith("v") ? rawVersion.substring(1) : rawVersion;
|
|
48
|
+
if (!version) {
|
|
49
|
+
throw new Error(`Invalid module reference '${moduleRef}', expected namespace/name@version`);
|
|
50
|
+
}
|
|
51
|
+
return { modulePath, version };
|
|
52
|
+
}
|
|
53
|
+
}
|
package/dist/alias-resolver.d.ts
CHANGED
|
@@ -4,6 +4,12 @@ export declare class AliasResolver {
|
|
|
4
4
|
private readonly importAliases;
|
|
5
5
|
private readonly importedKinds;
|
|
6
6
|
registerImport(alias: string, targetModule: string, exportedKinds: string[]): void;
|
|
7
|
+
/** Real module name an alias points at (e.g. "Console" → "console"), or undefined.
|
|
8
|
+
* Used to resolve an alias-qualified instance reference "Console.writeLine" to the
|
|
9
|
+
* forwarded resource declared in that module. The `exports.resources` gate is enforced
|
|
10
|
+
* upstream by `flattenForAnalyzer` (only exported instances are forwarded), so a name
|
|
11
|
+
* that isn't exported simply won't be found. */
|
|
12
|
+
moduleForAlias(alias: string): string | undefined;
|
|
7
13
|
/** Resolves "Http.Api" → "http-server.Api". Returns undefined if alias is unknown. */
|
|
8
14
|
resolveKind(kind: string): string | undefined;
|
|
9
15
|
hasAlias(alias: string): boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"alias-resolver.d.ts","sourceRoot":"","sources":["../src/alias-resolver.ts"],"names":[],"mappings":"AAAA;gFACgF;AAChF,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA6B;IAC3D,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAkC;IAEhE,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,GAAG,IAAI;IAOlF,sFAAsF;IACtF,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAe7C,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAIhC,YAAY,IAAI,MAAM,EAAE;IAIxB;;qEAEiE;IACjE,UAAU,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,EAAE;CAO3C"}
|
|
1
|
+
{"version":3,"file":"alias-resolver.d.ts","sourceRoot":"","sources":["../src/alias-resolver.ts"],"names":[],"mappings":"AAAA;gFACgF;AAChF,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA6B;IAC3D,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAkC;IAEhE,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,GAAG,IAAI;IAOlF;;;;qDAIiD;IACjD,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAIjD,sFAAsF;IACtF,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAe7C,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAIhC,YAAY,IAAI,MAAM,EAAE;IAIxB;;qEAEiE;IACjE,UAAU,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,EAAE;CAO3C"}
|
package/dist/alias-resolver.js
CHANGED
|
@@ -9,6 +9,14 @@ export class AliasResolver {
|
|
|
9
9
|
this.importedKinds.set(alias, new Set(exportedKinds));
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
|
+
/** Real module name an alias points at (e.g. "Console" → "console"), or undefined.
|
|
13
|
+
* Used to resolve an alias-qualified instance reference "Console.writeLine" to the
|
|
14
|
+
* forwarded resource declared in that module. The `exports.resources` gate is enforced
|
|
15
|
+
* upstream by `flattenForAnalyzer` (only exported instances are forwarded), so a name
|
|
16
|
+
* that isn't exported simply won't be found. */
|
|
17
|
+
moduleForAlias(alias) {
|
|
18
|
+
return this.importAliases.get(alias);
|
|
19
|
+
}
|
|
12
20
|
/** Resolves "Http.Api" → "http-server.Api". Returns undefined if alias is unknown. */
|
|
13
21
|
resolveKind(kind) {
|
|
14
22
|
if (!kind) {
|
|
@@ -33,6 +33,7 @@ export declare class AnalysisRegistry {
|
|
|
33
33
|
visitManifest(resources: ResourceManifest[], visitor: ManifestVisitor, opts?: {
|
|
34
34
|
skipKinds?: ReadonlySet<string>;
|
|
35
35
|
expand?: boolean;
|
|
36
|
+
discoverNestedRefs?: boolean;
|
|
36
37
|
}): void;
|
|
37
38
|
/**
|
|
38
39
|
* Returns the built-in kernel definitions. The underlying DefinitionRegistry already
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analysis-registry.d.ts","sourceRoot":"","sources":["../src/analysis-registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAKzE,OAAO,EAAqC,KAAK,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAEhG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD;;;;GAIG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA4B;IACjD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAuB;IAC/C,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAoC;IAEpE,kBAAkB,CAAC,GAAG,EAAE,kBAAkB,GAAG,IAAI;IAIjD,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAIpE,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI;IAIpE,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAI7C;;;;;;;OAOG;IACH,mBAAmB,CACjB,QAAQ,EAAE,gBAAgB,EAC1B,KAAK,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,EAClC,OAAO,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,GACnC,IAAI;IAkBP;;;;;;OAMG;IACH,aAAa,CACX,SAAS,EAAE,gBAAgB,EAAE,EAC7B,OAAO,EAAE,eAAe,EACxB,IAAI,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,
|
|
1
|
+
{"version":3,"file":"analysis-registry.d.ts","sourceRoot":"","sources":["../src/analysis-registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAKzE,OAAO,EAAqC,KAAK,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAEhG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD;;;;GAIG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA4B;IACjD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAuB;IAC/C,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAoC;IAEpE,kBAAkB,CAAC,GAAG,EAAE,kBAAkB,GAAG,IAAI;IAIjD,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAIpE,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI;IAIpE,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAI7C;;;;;;;OAOG;IACH,mBAAmB,CACjB,QAAQ,EAAE,gBAAgB,EAC1B,KAAK,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,EAClC,OAAO,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,GACnC,IAAI;IAkBP;;;;;;OAMG;IACH,aAAa,CACX,SAAS,EAAE,gBAAgB,EAAE,EAC7B,OAAO,EAAE,eAAe,EACxB,IAAI,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,CAAC;QAAC,kBAAkB,CAAC,EAAE,OAAO,CAAA;KAAE,GACzF,IAAI;IAQP;;;;OAIG;IACH,kBAAkB,IAAI,kBAAkB,EAAE;IAI1C,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS;IAM/D,QAAQ,IAAI,MAAM,EAAE;IAIpB;mEAC+D;IAC/D,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE;IAIxC;;;gCAG4B;IAC5B,oBAAoB,IAAI,MAAM,EAAE;IAIhC;wEACoE;IACpE,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAIhD;;;;;gEAK4D;IAC5D,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS;IA+B7D,qFAAqF;IACrF,QAAQ,IAAI,eAAe;CAG5B"}
|
package/dist/analyzer.d.ts
CHANGED
|
@@ -25,7 +25,7 @@ export declare class StaticAnalyzer {
|
|
|
25
25
|
*/
|
|
26
26
|
analyze(manifests: ResourceManifest[], options?: AnalysisOptions, registry?: AnalysisRegistry): AnalysisDiagnostic[];
|
|
27
27
|
analyzeErrors(manifests: ResourceManifest[], options?: AnalysisOptions, registry?: AnalysisRegistry): AnalysisDiagnostic[];
|
|
28
|
-
normalize(manifests: ResourceManifest[], registry: AnalysisRegistry): ResourceManifest[];
|
|
28
|
+
normalize(manifests: ResourceManifest[], registry: AnalysisRegistry, crossModuleTargets?: ResourceManifest[]): ResourceManifest[];
|
|
29
29
|
prepare(manifests: ResourceManifest[], registry: AnalysisRegistry): {
|
|
30
30
|
diagnostics: AnalysisDiagnostic[];
|
|
31
31
|
order: string[] | null;
|
package/dist/analyzer.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analyzer.d.ts","sourceRoot":"","sources":["../src/analyzer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAsB,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAIzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAGL,KAAK,WAAW,EACjB,MAAM,sBAAsB,CAAC;AAiB9B,OAAO,EAAsB,KAAK,kBAAkB,EAAE,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"analyzer.d.ts","sourceRoot":"","sources":["../src/analyzer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAsB,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAIzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAGL,KAAK,WAAW,EACjB,MAAM,sBAAsB,CAAC;AAiB9B,OAAO,EAAsB,KAAK,kBAAkB,EAAE,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AAuhB/F,MAAM,WAAW,qBAAqB;IACpC,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAc;gBAEzB,OAAO,GAAE,qBAA0B;IAI/C;;;;;;;;;;;;;;OAcG;IACH,OAAO,CACL,SAAS,EAAE,gBAAgB,EAAE,EAC7B,OAAO,CAAC,EAAE,eAAe,EACzB,QAAQ,CAAC,EAAE,gBAAgB,GAC1B,kBAAkB,EAAE;IAmmBvB,aAAa,CACX,SAAS,EAAE,gBAAgB,EAAE,EAC7B,OAAO,CAAC,EAAE,eAAe,EACzB,QAAQ,CAAC,EAAE,gBAAgB,GAC1B,kBAAkB,EAAE;IAMvB,SAAS,CACP,SAAS,EAAE,gBAAgB,EAAE,EAC7B,QAAQ,EAAE,gBAAgB,EAI1B,kBAAkB,CAAC,EAAE,gBAAgB,EAAE,GACtC,gBAAgB,EAAE;IAqBrB,OAAO,CACL,SAAS,EAAE,gBAAgB,EAAE,EAC7B,QAAQ,EAAE,gBAAgB,GACzB;QAAE,WAAW,EAAE,kBAAkB,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;QAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE;CAsB5F"}
|
package/dist/analyzer.js
CHANGED
|
@@ -307,6 +307,73 @@ function buildStepContextSchema(manifest, defSchema, allManifests, defs, aliases
|
|
|
307
307
|
}
|
|
308
308
|
return undefined;
|
|
309
309
|
}
|
|
310
|
+
/**
|
|
311
|
+
* Collect every field annotated with `x-telo-error-context` anywhere in a
|
|
312
|
+
* definition schema (resolving local `$ref`s into `$defs`, cycle-safe), mapping
|
|
313
|
+
* the annotated field name to its declared error-shape schema. The field name
|
|
314
|
+
* is matched against CEL paths so the context applies at any nesting depth under
|
|
315
|
+
* that field — e.g. `error` inside a `catch:` nested inside another `try:`. No
|
|
316
|
+
* specific field name (or `Run.Sequence`) is hardcoded; any composer that tags
|
|
317
|
+
* its error-bearing branch fields opts in the same way.
|
|
318
|
+
*/
|
|
319
|
+
function collectErrorContextScopes(defSchema) {
|
|
320
|
+
const out = new Map();
|
|
321
|
+
if (!defSchema || typeof defSchema !== "object")
|
|
322
|
+
return out;
|
|
323
|
+
const seen = new Set();
|
|
324
|
+
const walk = (schema) => {
|
|
325
|
+
if (!schema || typeof schema !== "object" || seen.has(schema))
|
|
326
|
+
return;
|
|
327
|
+
seen.add(schema);
|
|
328
|
+
const props = schema.properties;
|
|
329
|
+
if (props) {
|
|
330
|
+
for (const [fieldName, fieldSchema] of Object.entries(props)) {
|
|
331
|
+
if (fieldSchema && typeof fieldSchema === "object") {
|
|
332
|
+
const errCtx = fieldSchema["x-telo-error-context"];
|
|
333
|
+
if (errCtx && typeof errCtx === "object" && !out.has(fieldName)) {
|
|
334
|
+
out.set(fieldName, errCtx);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
walk(resolveLocalRef(fieldSchema, defSchema));
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
if (schema.items)
|
|
341
|
+
walk(resolveLocalRef(schema.items, defSchema));
|
|
342
|
+
for (const key of ["oneOf", "anyOf", "allOf"]) {
|
|
343
|
+
const arr = schema[key];
|
|
344
|
+
if (Array.isArray(arr))
|
|
345
|
+
for (const sub of arr)
|
|
346
|
+
walk(resolveLocalRef(sub, defSchema));
|
|
347
|
+
}
|
|
348
|
+
if (schema.$defs && typeof schema.$defs === "object") {
|
|
349
|
+
for (const sub of Object.values(schema.$defs)) {
|
|
350
|
+
walk(sub);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
};
|
|
354
|
+
walk(defSchema);
|
|
355
|
+
return out;
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* Return the error-context schema for a CEL `path` when the path lies within
|
|
359
|
+
* (any depth under) one of the error-bearing fields, else undefined. A path is
|
|
360
|
+
* "within" field `f` when it contains a segment `f[<index>]`. When multiple
|
|
361
|
+
* error-bearing fields match (e.g. a `finally` nested inside a `catch`), the
|
|
362
|
+
* deepest — the one whose segment appears latest in the path — wins, so the
|
|
363
|
+
* innermost branch's schema governs.
|
|
364
|
+
*/
|
|
365
|
+
function errorContextForPath(path, scopes) {
|
|
366
|
+
let best;
|
|
367
|
+
for (const [fieldName, schema] of scopes) {
|
|
368
|
+
const escaped = fieldName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
369
|
+
for (const match of path.matchAll(new RegExp(`(^|\\.)${escaped}\\[\\d+\\]`, "g"))) {
|
|
370
|
+
if (best === undefined || match.index > best.index) {
|
|
371
|
+
best = { index: match.index, schema };
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
return best?.schema;
|
|
376
|
+
}
|
|
310
377
|
const CEL_PURE_RE = /^\s*\$\{\{[^}]*\}\}\s*$/;
|
|
311
378
|
const CEL_EXPR_RE = /\$\{\{\s*([^}]+?)\s*\}\}/;
|
|
312
379
|
/** Recursively walk `data`+`schema` together, type-checking every pure CEL template
|
|
@@ -444,9 +511,12 @@ export class StaticAnalyzer {
|
|
|
444
511
|
// through the same alias machinery as user-declared Telo.Imports —
|
|
445
512
|
// honours the library's `exports.kinds` list, no special cases.
|
|
446
513
|
if (moduleName) {
|
|
447
|
-
|
|
514
|
+
// `Self` resolves the library's own kinds UNGATED — a library may reference
|
|
515
|
+
// its own kinds regardless of `exports.kinds`, which gates importers, not
|
|
516
|
+
// internal use. This is what lets a library declare an instance of a kind it
|
|
517
|
+
// does not export (e.g. console's `writeLine`) to enforce a singleton.
|
|
448
518
|
if (rootModules.has(moduleName)) {
|
|
449
|
-
aliases.registerImport("Self", moduleName,
|
|
519
|
+
aliases.registerImport("Self", moduleName, []);
|
|
450
520
|
}
|
|
451
521
|
else {
|
|
452
522
|
let libResolver = aliasesByModule.get(moduleName);
|
|
@@ -454,7 +524,7 @@ export class StaticAnalyzer {
|
|
|
454
524
|
libResolver = new AliasResolver();
|
|
455
525
|
aliasesByModule.set(moduleName, libResolver);
|
|
456
526
|
}
|
|
457
|
-
libResolver.registerImport("Self", moduleName,
|
|
527
|
+
libResolver.registerImport("Self", moduleName, []);
|
|
458
528
|
}
|
|
459
529
|
}
|
|
460
530
|
}
|
|
@@ -626,6 +696,16 @@ export class StaticAnalyzer {
|
|
|
626
696
|
if (m.kind === "Telo.Abstract") {
|
|
627
697
|
continue;
|
|
628
698
|
}
|
|
699
|
+
// Forwarded foreign exports (an imported library's exported instances, whose
|
|
700
|
+
// metadata.module isn't a root module here) were already validated in their own
|
|
701
|
+
// module's standalone analysis, and their `kind`/CEL are authored in that module's
|
|
702
|
+
// scope (e.g. `Self.X` resolves to that module, not the consumer). Re-validating them
|
|
703
|
+
// against the consumer's scope yields false UNDEFINED_KIND / scope-mismatch errors, so
|
|
704
|
+
// skip — they participate in this analysis only as cross-module resolution targets.
|
|
705
|
+
const mModule = m.metadata?.module;
|
|
706
|
+
if (typeof mModule === "string" && !rootModules.has(mModule)) {
|
|
707
|
+
continue;
|
|
708
|
+
}
|
|
629
709
|
const resource = { kind: m.kind, name: m.metadata?.name };
|
|
630
710
|
// Resolve kind through alias if needed; direct lookup takes priority so that
|
|
631
711
|
// aliases whose name matches the module name (the common case) work without
|
|
@@ -784,6 +864,7 @@ export class StaticAnalyzer {
|
|
|
784
864
|
// context — which require analyzer state to build — are stashed here.
|
|
785
865
|
let celStepContextSchema;
|
|
786
866
|
let celInvocationContext;
|
|
867
|
+
let celErrorScopes = new Map();
|
|
787
868
|
visitManifest(allManifests, defs, {
|
|
788
869
|
onResourceEnter: (e) => {
|
|
789
870
|
const m = e.source;
|
|
@@ -791,6 +872,7 @@ export class StaticAnalyzer {
|
|
|
791
872
|
celStepContextSchema = e.definition?.schema
|
|
792
873
|
? buildStepContextSchema(m, e.definition.schema, allManifests, defs, aliases)
|
|
793
874
|
: undefined;
|
|
875
|
+
celErrorScopes = collectErrorContextScopes(e.definition?.schema);
|
|
794
876
|
},
|
|
795
877
|
onCel: (e) => {
|
|
796
878
|
const m = e.source;
|
|
@@ -808,6 +890,19 @@ export class StaticAnalyzer {
|
|
|
808
890
|
},
|
|
809
891
|
};
|
|
810
892
|
}
|
|
893
|
+
// `error` is only in scope inside an error-bearing branch (e.g. a
|
|
894
|
+
// `catch:` / `finally:`), so it's merged per-path, not resource-wide.
|
|
895
|
+
const errorSchema = celErrorScopes.size > 0 ? errorContextForPath(path, celErrorScopes) : undefined;
|
|
896
|
+
if (errorSchema) {
|
|
897
|
+
const base = matchedContext ?? { type: "object", properties: {}, additionalProperties: true };
|
|
898
|
+
matchedContext = {
|
|
899
|
+
...base,
|
|
900
|
+
properties: {
|
|
901
|
+
...(base.properties ?? {}),
|
|
902
|
+
error: errorSchema,
|
|
903
|
+
},
|
|
904
|
+
};
|
|
905
|
+
}
|
|
811
906
|
let effectiveContext = null;
|
|
812
907
|
if (matchedContext) {
|
|
813
908
|
const manifestItem = matchedScope
|
|
@@ -855,6 +950,15 @@ export class StaticAnalyzer {
|
|
|
855
950
|
data: { resource, filePath, path },
|
|
856
951
|
});
|
|
857
952
|
}
|
|
953
|
+
else if (f.code === "CEL_NULLABLE_ACCESS") {
|
|
954
|
+
diagnostics.push({
|
|
955
|
+
severity: DiagnosticSeverity.Error,
|
|
956
|
+
code: "CEL_NULLABLE_ACCESS",
|
|
957
|
+
source: SOURCE,
|
|
958
|
+
message: `${m.kind}/${resource.name}: CEL at '${path}': ${f.message}`,
|
|
959
|
+
data: { resource, filePath, path },
|
|
960
|
+
});
|
|
961
|
+
}
|
|
858
962
|
else {
|
|
859
963
|
// Unknown code from a future engine — pass the message through,
|
|
860
964
|
// tagged with a generic ENGINE_DIAGNOSTIC code so downstream
|
|
@@ -887,13 +991,17 @@ export class StaticAnalyzer {
|
|
|
887
991
|
analyzeErrors(manifests, options, registry) {
|
|
888
992
|
return this.analyze(manifests, options, registry).filter((d) => d.severity === DiagnosticSeverity.Error);
|
|
889
993
|
}
|
|
890
|
-
normalize(manifests, registry
|
|
994
|
+
normalize(manifests, registry,
|
|
995
|
+
// Forwarded foreign exports used only as cross-module resolution targets (see
|
|
996
|
+
// resolveRefSentinels). The kernel passes its analyzer-flattened set so the
|
|
997
|
+
// entry-only runtime pass can still resolve `!ref Alias.name`.
|
|
998
|
+
crossModuleTargets) {
|
|
891
999
|
const ctx = registry._context();
|
|
892
1000
|
const normalized = normalizeInlineResources(manifests, ctx.definitions, ctx.aliases, ctx.aliasesByModule);
|
|
893
1001
|
// Resolve !ref sentinels after normalize so both the original and
|
|
894
1002
|
// inline-extracted manifests get their refs canonicalized to
|
|
895
1003
|
// {kind, name} for the kernel that consumes this output.
|
|
896
|
-
resolveRefSentinels(normalized, ctx.definitions, ctx.aliases, ctx.aliasesByModule);
|
|
1004
|
+
resolveRefSentinels(normalized, ctx.definitions, ctx.aliases, ctx.aliasesByModule, crossModuleTargets ?? []);
|
|
897
1005
|
return normalized;
|
|
898
1006
|
}
|
|
899
1007
|
prepare(manifests, registry) {
|
package/dist/builtins.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builtins.d.ts","sourceRoot":"","sources":["../src/builtins.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAEvD,eAAO,MAAM,eAAe,EAAE,kBAAkB,
|
|
1
|
+
{"version":3,"file":"builtins.d.ts","sourceRoot":"","sources":["../src/builtins.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAEvD,eAAO,MAAM,eAAe,EAAE,kBAAkB,EAuZ/C,CAAC"}
|
package/dist/builtins.js
CHANGED
|
@@ -232,6 +232,66 @@ export const KERNEL_BUILTINS = [
|
|
|
232
232
|
},
|
|
233
233
|
additionalProperties: true,
|
|
234
234
|
},
|
|
235
|
+
// Gated reference: run() a Runnable/Service only when the
|
|
236
|
+
// `when` CEL guard holds. Discriminated by the `ref` key. `ref`
|
|
237
|
+
// is a bare name or a resolved `!ref` (`{ kind, name }`).
|
|
238
|
+
{
|
|
239
|
+
type: "object",
|
|
240
|
+
required: ["ref"],
|
|
241
|
+
properties: {
|
|
242
|
+
ref: {
|
|
243
|
+
anyOf: [
|
|
244
|
+
{ type: "string", "x-telo-ref": "telo#Runnable" },
|
|
245
|
+
{ type: "string", "x-telo-ref": "telo#Service" },
|
|
246
|
+
{
|
|
247
|
+
type: "object",
|
|
248
|
+
required: ["kind", "name"],
|
|
249
|
+
properties: {
|
|
250
|
+
kind: { type: "string" },
|
|
251
|
+
name: { type: "string" },
|
|
252
|
+
},
|
|
253
|
+
additionalProperties: true,
|
|
254
|
+
},
|
|
255
|
+
],
|
|
256
|
+
},
|
|
257
|
+
when: { type: "string" },
|
|
258
|
+
},
|
|
259
|
+
additionalProperties: false,
|
|
260
|
+
},
|
|
261
|
+
// Inline flat invoke step: invoke an Invocable / Runnable on boot
|
|
262
|
+
// with an optional `name` (for steps.<name>.result plumbing),
|
|
263
|
+
// `when` guard, and `inputs`. Discriminated by the `invoke` key.
|
|
264
|
+
// Control flow (if/while/switch/try) is not available here —
|
|
265
|
+
// reach for Run.Sequence. `invoke` is ref-only and must resolve
|
|
266
|
+
// to a `{ kind, name }` reference (a `!ref` / `{kind,name}`):
|
|
267
|
+
// requiring `name` rejects an inline `{ kind }` definition (no
|
|
268
|
+
// name) at analysis instead of failing at boot with an undefined
|
|
269
|
+
// resource name. The Invocable/Runnable kind set mirrors
|
|
270
|
+
// Run.Sequence invoke steps.
|
|
271
|
+
{
|
|
272
|
+
type: "object",
|
|
273
|
+
required: ["invoke"],
|
|
274
|
+
properties: {
|
|
275
|
+
name: { type: "string" },
|
|
276
|
+
invoke: {
|
|
277
|
+
"x-telo-topology-role": "invoke",
|
|
278
|
+
type: "object",
|
|
279
|
+
required: ["kind", "name"],
|
|
280
|
+
properties: {
|
|
281
|
+
kind: { type: "string" },
|
|
282
|
+
name: { type: "string" },
|
|
283
|
+
},
|
|
284
|
+
additionalProperties: true,
|
|
285
|
+
anyOf: [
|
|
286
|
+
{ "x-telo-ref": "telo#Invocable" },
|
|
287
|
+
{ "x-telo-ref": "telo#Runnable" },
|
|
288
|
+
],
|
|
289
|
+
},
|
|
290
|
+
inputs: { type: "object", additionalProperties: true },
|
|
291
|
+
when: { type: "string" },
|
|
292
|
+
},
|
|
293
|
+
additionalProperties: false,
|
|
294
|
+
},
|
|
235
295
|
],
|
|
236
296
|
},
|
|
237
297
|
},
|
|
@@ -336,6 +396,7 @@ export const KERNEL_BUILTINS = [
|
|
|
336
396
|
type: "object",
|
|
337
397
|
properties: {
|
|
338
398
|
kinds: { type: "array", items: { type: "string" } },
|
|
399
|
+
resources: { type: "array", items: { type: "string" } },
|
|
339
400
|
},
|
|
340
401
|
additionalProperties: true,
|
|
341
402
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flatten-for-analyzer.d.ts","sourceRoot":"","sources":["../src/flatten-for-analyzer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,KAAK,EAAc,WAAW,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAG/E;;;;;;;;;;;;;;;;;;6EAkB6E;AAC7E,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,WAAW,GAAG,gBAAgB,EAAE,
|
|
1
|
+
{"version":3,"file":"flatten-for-analyzer.d.ts","sourceRoot":"","sources":["../src/flatten-for-analyzer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,KAAK,EAAc,WAAW,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAG/E;;;;;;;;;;;;;;;;;;6EAkB6E;AAC7E,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,WAAW,GAAG,gBAAgB,EAAE,CAyEzE;AAED;;;;;6BAK6B;AAC7B,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,YAAY,GAAG,gBAAgB,EAAE,CAEzE"}
|
|
@@ -38,12 +38,25 @@ export function flattenForAnalyzer(graph) {
|
|
|
38
38
|
if (!targetModule)
|
|
39
39
|
continue;
|
|
40
40
|
const stamped = collectModuleManifests(targetModule);
|
|
41
|
+
const libDoc = stamped.find((m) => isModuleKind(m.kind));
|
|
42
|
+
const exportedResources = new Set(libDoc?.exports?.resources ?? []);
|
|
41
43
|
for (const m of stamped) {
|
|
42
44
|
if (m.kind === "Telo.Definition" ||
|
|
43
45
|
m.kind === "Telo.Abstract" ||
|
|
44
46
|
m.kind === "Telo.Import") {
|
|
45
47
|
result.push(m);
|
|
46
48
|
}
|
|
49
|
+
else if (!isModuleKind(m.kind) &&
|
|
50
|
+
typeof m.metadata?.name === "string" &&
|
|
51
|
+
exportedResources.has(m.metadata.name)) {
|
|
52
|
+
// Forward instances listed in the library's `exports.resources` so the
|
|
53
|
+
// consumer's analyzer can resolve, gate, kind-check, and draw topology edges
|
|
54
|
+
// for cross-module `!ref Alias.name`. The gate IS this forwarding — only
|
|
55
|
+
// exported names cross the boundary. `metadata.module` (stamped by
|
|
56
|
+
// collectModuleManifests) marks them foreign, so ref validation treats them
|
|
57
|
+
// as resolution targets, not as sources to re-validate.
|
|
58
|
+
result.push(m);
|
|
59
|
+
}
|
|
47
60
|
}
|
|
48
61
|
}
|
|
49
62
|
}
|
|
@@ -65,6 +65,13 @@ export interface RefSiteEvent {
|
|
|
65
65
|
inScope: boolean;
|
|
66
66
|
/** Scope manifests visible to this ref path (non-empty only when `inScope`). */
|
|
67
67
|
visibleScopeManifests: ResourceManifest[];
|
|
68
|
+
/** True when the site was found by value-tree scanning rather than the field
|
|
69
|
+
* map (only when `discoverNestedRefs` is set) — a ref nested behind a `$ref`
|
|
70
|
+
* the field map doesn't descend (e.g. `Run.Sequence` `steps[].invoke`).
|
|
71
|
+
* Nested sites carry no x-telo-ref constraint (`entry.refs` is empty) and no
|
|
72
|
+
* scope info; `concretePath` still points at the exact location, so consumers
|
|
73
|
+
* can anchor to it. */
|
|
74
|
+
nested?: boolean;
|
|
68
75
|
}
|
|
69
76
|
export interface SchemaFromSiteEvent {
|
|
70
77
|
source: ResourceManifest;
|
|
@@ -104,6 +111,14 @@ export interface VisitOptions {
|
|
|
104
111
|
* so refs nested behind `x-telo-schema-from` are surfaced. `SchemaFromSite`
|
|
105
112
|
* events are always emitted from the base map regardless of this flag. */
|
|
106
113
|
expand?: boolean;
|
|
114
|
+
/** When true, additionally discover refs by scanning each resource's value
|
|
115
|
+
* tree for `!ref` sentinels and `{kind, name}` reference objects — surfacing
|
|
116
|
+
* refs the field map never lists because they sit behind a `$ref` it doesn't
|
|
117
|
+
* descend (notably `Run.Sequence` step `invoke`s). Emitted as `RefSite`s with
|
|
118
|
+
* `nested: true`, deduped against the field-map sites by concrete path.
|
|
119
|
+
* Opt-in: the validators / dependency graph must NOT enable it (those refs
|
|
120
|
+
* are runtime-resolved, not boot dependencies). */
|
|
121
|
+
discoverNestedRefs?: boolean;
|
|
107
122
|
}
|
|
108
123
|
export declare function visitManifest(resources: ResourceManifest[], registry: DefinitionRegistry, visitor: ManifestVisitor, options?: VisitOptions): void;
|
|
109
124
|
//# sourceMappingURL=manifest-visitor.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifest-visitor.d.ts","sourceRoot":"","sources":["../src/manifest-visitor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,EAML,KAAK,aAAa,EAClB,KAAK,oBAAoB,EAC1B,MAAM,0BAA0B,CAAC;AAGlC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,gBAAgB,CAAC;IACzB,8EAA8E;IAC9E,UAAU,CAAC,EAAE,kBAAkB,CAAC;CACjC;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,gBAAgB,CAAC;CAC1B;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,gBAAgB,CAAC;IACzB,wEAAwE;IACxE,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,uEAAuE;IACvE,kBAAkB,EAAE,GAAG,CAAC,MAAM,EAAE,gBAAgB,EAAE,CAAC,CAAC;IACpD;iFAC6E;IAC7E,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CAC5B;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,gBAAgB,CAAC;IACzB,uEAAuE;IACvE,SAAS,EAAE,MAAM,CAAC;IAClB,+EAA+E;IAC/E,YAAY,EAAE,MAAM,CAAC;IACrB,gFAAgF;IAChF,KAAK,EAAE,OAAO,CAAC;IACf,oEAAoE;IACpE,KAAK,EAAE,aAAa,CAAC;IACrB;iEAC6D;IAC7D,OAAO,EAAE,OAAO,CAAC;IACjB,gFAAgF;IAChF,qBAAqB,EAAE,gBAAgB,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"manifest-visitor.d.ts","sourceRoot":"","sources":["../src/manifest-visitor.ts"],"names":[],"mappings":"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"}
|