@telorun/ide-support 0.24.0 → 0.103.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/completions/build.d.ts.map +1 -1
- package/dist/completions/build.js +26 -10
- package/dist/completions/detect-context.d.ts +4 -1
- package/dist/completions/detect-context.d.ts.map +1 -1
- package/dist/completions/detect-context.js +6 -3
- package/dist/import-upgrades/build-import-upgrades.d.ts +3 -3
- package/dist/import-upgrades/build-import-upgrades.d.ts.map +1 -1
- package/dist/import-upgrades/index.d.ts +0 -1
- package/dist/import-upgrades/index.d.ts.map +1 -1
- package/dist/import-upgrades/index.js +0 -1
- package/package.json +3 -3
- package/src/completions/build.ts +34 -10
- package/src/completions/detect-context.ts +12 -2
- package/src/import-upgrades/build-import-upgrades.ts +3 -3
- package/src/import-upgrades/index.ts +0 -1
- package/dist/import-upgrades/parse-module-versions.d.ts +0 -19
- package/dist/import-upgrades/parse-module-versions.d.ts.map +0 -1
- package/dist/import-upgrades/parse-module-versions.js +0 -29
- package/src/import-upgrades/parse-module-versions.ts +0 -30
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/completions/build.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,gBAAgB,EACrB,KAAK,WAAW,EAEhB,KAAK,gBAAgB,
|
|
1
|
+
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/completions/build.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,gBAAgB,EACrB,KAAK,WAAW,EAEhB,KAAK,gBAAgB,EAEtB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AA8L3E,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,gBAAgB,GAAG,SAAS,EACtC,OAAO,CAAC,EAAE,qBAAqB,EAC/B,IAAI,CAAC,EAAE,WAAW,EAAE;AACpB;;gCAEgC;AAChC,QAAQ,CAAC,EAAE,gBAAgB,GAC1B,OAAO,CAAC,gBAAgB,EAAE,CAAC,CA2D7B"}
|
|
@@ -2,7 +2,7 @@ import { parseToAst, } from "@telorun/analyzer";
|
|
|
2
2
|
import { callInputsAt } from "./call-inputs.js";
|
|
3
3
|
import { celCompletions } from "./cel-completions.js";
|
|
4
4
|
import { docIdentity } from "../doc-identity.js";
|
|
5
|
-
import { detectContext,
|
|
5
|
+
import { detectContext, lookupRefSlot, navigateSchema } from "./detect-context.js";
|
|
6
6
|
import { importSourceCompletions } from "./import-source.js";
|
|
7
7
|
import { moduleFileCompletions } from "./module-file-completions.js";
|
|
8
8
|
import { valueTagCompletions } from "./value-tag-completions.js";
|
|
@@ -27,8 +27,9 @@ function extractInFileResources(docs) {
|
|
|
27
27
|
* kind match. Falls back to listing every in-file resource so the
|
|
28
28
|
* user still sees something rather than nothing when the registry
|
|
29
29
|
* doesn't recognize the kind yet. */
|
|
30
|
-
function refNameCompletions(docs, refKind,
|
|
30
|
+
function refNameCompletions(docs, refKind, slot, registry, analysis, replaceRange) {
|
|
31
31
|
const resources = extractInFileResources(docs);
|
|
32
|
+
const refConstraints = slot?.kinds ?? [];
|
|
32
33
|
let acceptable;
|
|
33
34
|
if (refKind) {
|
|
34
35
|
acceptable = new Set([refKind]);
|
|
@@ -47,6 +48,11 @@ function refNameCompletions(docs, refKind, refConstraints, registry, replaceRang
|
|
|
47
48
|
for (const r of resources) {
|
|
48
49
|
if (acceptable && !acceptable.has(r.kind))
|
|
49
50
|
continue;
|
|
51
|
+
// A target `telo check` refuses for what it returns is not a candidate. The
|
|
52
|
+
// analysis resolves the instance's own contract; without one the kind's
|
|
53
|
+
// decides.
|
|
54
|
+
if (slot && outputRefused(slot, r, registry, analysis))
|
|
55
|
+
continue;
|
|
50
56
|
if (seen.has(r.name))
|
|
51
57
|
continue;
|
|
52
58
|
seen.add(r.name);
|
|
@@ -61,6 +67,14 @@ function refNameCompletions(docs, refKind, refConstraints, registry, replaceRang
|
|
|
61
67
|
}
|
|
62
68
|
return out;
|
|
63
69
|
}
|
|
70
|
+
function outputRefused(slot, candidate, registry, analysis) {
|
|
71
|
+
if (!slot.outputType)
|
|
72
|
+
return false;
|
|
73
|
+
const refusal = analysis
|
|
74
|
+
? analysis.outputRefusal(slot, { kind: candidate.kind, name: candidate.name })
|
|
75
|
+
: (registry?.outputRefusal(slot, { kind: candidate.kind }) ?? []);
|
|
76
|
+
return refusal.length > 0;
|
|
77
|
+
}
|
|
64
78
|
/** Resolve the kinds that satisfy the `x-telo-ref` slot at `parentDocKind` +
|
|
65
79
|
* `parentYamlPath`. Returns `undefined` (caller falls back to the full list)
|
|
66
80
|
* when there's no constraint, the path doesn't resolve, or the ref can't
|
|
@@ -69,13 +83,15 @@ function refConstrainedKinds(registry, parentDocKind, parentYamlPath) {
|
|
|
69
83
|
const definition = registry.resolveDefinition(parentDocKind);
|
|
70
84
|
if (!definition?.schema)
|
|
71
85
|
return undefined;
|
|
72
|
-
const
|
|
73
|
-
if (
|
|
86
|
+
const slot = lookupRefSlot(definition.schema, parentYamlPath, (from) => registry.resolveSchemaFrom(from, parentDocKind));
|
|
87
|
+
if (!slot || slot.kinds.length === 0)
|
|
74
88
|
return undefined;
|
|
75
|
-
const resolved =
|
|
89
|
+
const resolved = slot.kinds.map((c) => registry.userFacingKindsForRef(c));
|
|
76
90
|
if (!resolved.some(Boolean))
|
|
77
91
|
return undefined;
|
|
78
|
-
|
|
92
|
+
// An inline declaration of a kind whose output the slot refuses would be
|
|
93
|
+
// refused by `telo check` the moment it is written.
|
|
94
|
+
return [...new Set(resolved.flatMap((kinds) => kinds ?? []))].filter((kind) => !outputRefused(slot, { kind }, registry, undefined));
|
|
79
95
|
}
|
|
80
96
|
function kindCompletions(registry, docKind, yamlPath, replaceRange) {
|
|
81
97
|
let kinds;
|
|
@@ -166,10 +182,10 @@ analysis) {
|
|
|
166
182
|
}
|
|
167
183
|
if (ctx.type === "ref-name") {
|
|
168
184
|
const definition = registry?.resolveDefinition(ctx.docKind);
|
|
169
|
-
const
|
|
170
|
-
?
|
|
171
|
-
:
|
|
172
|
-
return refNameCompletions(astDocs, ctx.refKind,
|
|
185
|
+
const slot = registry && definition?.schema
|
|
186
|
+
? lookupRefSlot(definition.schema, ctx.yamlPath, (from) => registry.resolveSchemaFrom(from, ctx.docKind))
|
|
187
|
+
: undefined;
|
|
188
|
+
return refNameCompletions(astDocs, ctx.refKind, slot, registry, analysis, ctx.replaceRange);
|
|
173
189
|
}
|
|
174
190
|
if (ctx.type === "field-value") {
|
|
175
191
|
if (ctx.field === "import-source") {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type AstDocument, type CelSegment } from "@telorun/analyzer";
|
|
1
|
+
import { type AstDocument, type CelSegment, type RefSlot } from "@telorun/analyzer";
|
|
2
2
|
import type { ReplaceRange } from "../types.js";
|
|
3
3
|
export type { ReplaceRange };
|
|
4
4
|
export type CompletionCtx = {
|
|
@@ -137,6 +137,9 @@ export declare function fieldSchemaAt(schema: Record<string, any>, path: string[
|
|
|
137
137
|
* `anyOf` / `oneOf` branches alike, so completion now offers what the slot
|
|
138
138
|
* actually takes. */
|
|
139
139
|
export declare function lookupRefConstraints(definitionSchema: Record<string, any>, yamlPath: string[], schemaFrom?: SchemaFromResolver): string[];
|
|
140
|
+
/** The whole `x-telo-ref` slot at `yamlPath` — its kinds and what it asks of a
|
|
141
|
+
* target's output — or undefined when the path declares none. */
|
|
142
|
+
export declare function lookupRefSlot(definitionSchema: Record<string, any>, yamlPath: string[], schemaFrom?: SchemaFromResolver): RefSlot | undefined;
|
|
140
143
|
/** Derive a `CompletionCtx` from the AST-resolved cursor (Approach B). The
|
|
141
144
|
* structural resolution lives in `resolveNodeAtPosition`; this only maps a
|
|
142
145
|
* resolved slot onto the completion the editor should offer. `docs` lets a
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"detect-context.d.ts","sourceRoot":"","sources":["../../src/completions/detect-context.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,WAAW,EAChB,KAAK,UAAU,
|
|
1
|
+
{"version":3,"file":"detect-context.d.ts","sourceRoot":"","sources":["../../src/completions/detect-context.ts"],"names":[],"mappings":"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"}
|
|
@@ -230,10 +230,13 @@ function unionLeaves(parent, leaves) {
|
|
|
230
230
|
* `anyOf` / `oneOf` branches alike, so completion now offers what the slot
|
|
231
231
|
* actually takes. */
|
|
232
232
|
export function lookupRefConstraints(definitionSchema, yamlPath, schemaFrom) {
|
|
233
|
+
return lookupRefSlot(definitionSchema, yamlPath, schemaFrom)?.kinds ?? [];
|
|
234
|
+
}
|
|
235
|
+
/** The whole `x-telo-ref` slot at `yamlPath` — its kinds and what it asks of a
|
|
236
|
+
* target's output — or undefined when the path declares none. */
|
|
237
|
+
export function lookupRefSlot(definitionSchema, yamlPath, schemaFrom) {
|
|
233
238
|
const node = navigateSchema(definitionSchema, yamlPath, schemaFrom);
|
|
234
|
-
|
|
235
|
-
return [];
|
|
236
|
-
return readRefSlot(node)?.kinds ?? [];
|
|
239
|
+
return node ? readRefSlot(node) : undefined;
|
|
237
240
|
}
|
|
238
241
|
/** Derive a `CompletionCtx` from the AST-resolved cursor (Approach B). The
|
|
239
242
|
* structural resolution lives in `resolveNodeAtPosition`; this only maps a
|
|
@@ -20,9 +20,9 @@ export interface ModuleVersion {
|
|
|
20
20
|
*
|
|
21
21
|
* Deliberately NOT `adapter.listVersionsForRef`, which answers `string[]`:
|
|
22
22
|
* completion offers names, an upgrade writes a pin, so the two want different
|
|
23
|
-
* things from one route. A host backed by the hub
|
|
24
|
-
* `GET /module/versions`
|
|
25
|
-
*
|
|
23
|
+
* things from one route. A host backed by the hub reads
|
|
24
|
+
* `GET /module/versions`, carrying an `integrity` only when it is a canonical
|
|
25
|
+
* pin. */
|
|
26
26
|
export type ModuleVersionLookup = (baseRef: string) => Promise<ModuleVersion[]>;
|
|
27
27
|
/** Everything an upgrade needs from its host: what versions exist, and whether
|
|
28
28
|
* this runtime can host one.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-import-upgrades.d.ts","sourceRoot":"","sources":["../../src/import-upgrades/build-import-upgrades.ts"],"names":[],"mappings":"AAAA,OAAO,EAaL,KAAK,WAAW,EAChB,KAAK,KAAK,EACX,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAEL,KAAK,qBAAqB,EAC1B,KAAK,yBAAyB,EAC/B,MAAM,4BAA4B,CAAC;AAEpC;;;;;oEAKoE;AACpE,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"build-import-upgrades.d.ts","sourceRoot":"","sources":["../../src/import-upgrades/build-import-upgrades.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
export { buildImportUpgrades, describeReason, describeRemedy, } from "./build-import-upgrades.js";
|
|
2
2
|
export type { ImportPin, ImportUpgrade, ImportUpgradeEdit, ImportUpgradeEnvironment, ImportUpgradeSet, ImportUpgradeSkip, ModuleVersion, ModuleVersionLookup, } from "./build-import-upgrades.js";
|
|
3
3
|
export { moduleManifestCacheUrl } from "./manifest-cache-url.js";
|
|
4
|
-
export { parseModuleVersions } from "./parse-module-versions.js";
|
|
5
4
|
export { findImportEntries } from "./find-import-entries.js";
|
|
6
5
|
export type { ImportEntry, ImportEntryIntegrity, ImportsBlock, } from "./find-import-entries.js";
|
|
7
6
|
export { createVersionCompatibility, markVersionCompatibility, noneRunnableReason, selectCompatibleVersion, uncheckedVersionCompatibility, } from "./version-compatibility.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/import-upgrades/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,cAAc,EACd,cAAc,GACf,MAAM,4BAA4B,CAAC;AACpC,YAAY,EACV,SAAS,EACT,aAAa,EACb,iBAAiB,EACjB,wBAAwB,EACxB,gBAAgB,EAChB,iBAAiB,EACjB,aAAa,EACb,mBAAmB,GACpB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/import-upgrades/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,cAAc,EACd,cAAc,GACf,MAAM,4BAA4B,CAAC;AACpC,YAAY,EACV,SAAS,EACT,aAAa,EACb,iBAAiB,EACjB,wBAAwB,EACxB,gBAAgB,EAChB,iBAAiB,EACjB,aAAa,EACb,mBAAmB,GACpB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,YAAY,EACV,WAAW,EACX,oBAAoB,EACpB,YAAY,GACb,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,0BAA0B,EAC1B,wBAAwB,EACxB,kBAAkB,EAClB,uBAAuB,EACvB,6BAA6B,GAC9B,MAAM,4BAA4B,CAAC;AACpC,YAAY,EACV,qBAAqB,EACrB,aAAa,EACb,mBAAmB,EACnB,oBAAoB,EACpB,yBAAyB,EACzB,gBAAgB,GACjB,MAAM,4BAA4B,CAAC"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
export { buildImportUpgrades, describeReason, describeRemedy, } from "./build-import-upgrades.js";
|
|
2
2
|
export { moduleManifestCacheUrl } from "./manifest-cache-url.js";
|
|
3
|
-
export { parseModuleVersions } from "./parse-module-versions.js";
|
|
4
3
|
export { findImportEntries } from "./find-import-entries.js";
|
|
5
4
|
export { createVersionCompatibility, markVersionCompatibility, noneRunnableReason, selectCompatibleVersion, uncheckedVersionCompatibility, } from "./version-compatibility.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@telorun/ide-support",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.103.0",
|
|
4
4
|
"description": "Editor-host-agnostic IDE support (completions, diagnostic normalization) for Telo manifests.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"telo",
|
|
@@ -37,8 +37,8 @@
|
|
|
37
37
|
],
|
|
38
38
|
"dependencies": {
|
|
39
39
|
"yaml": "^2.8.3",
|
|
40
|
-
"@telorun/analyzer": "0.
|
|
41
|
-
"@telorun/templating": "0.
|
|
40
|
+
"@telorun/analyzer": "0.103.0",
|
|
41
|
+
"@telorun/templating": "0.103.0"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@types/node": "^20.0.0",
|
package/src/completions/build.ts
CHANGED
|
@@ -4,13 +4,14 @@ import {
|
|
|
4
4
|
type AstDocument,
|
|
5
5
|
type AstMap,
|
|
6
6
|
type ManifestAnalysis,
|
|
7
|
+
type RefSlot,
|
|
7
8
|
} from "@telorun/analyzer";
|
|
8
9
|
import type { CompletionResult, IdeEnvironmentAdapter } from "../types.js";
|
|
9
10
|
import type { ReplaceRange } from "./detect-context.js";
|
|
10
11
|
import { callInputsAt } from "./call-inputs.js";
|
|
11
12
|
import { celCompletions } from "./cel-completions.js";
|
|
12
13
|
import { docIdentity } from "../doc-identity.js";
|
|
13
|
-
import { detectContext,
|
|
14
|
+
import { detectContext, lookupRefSlot, navigateSchema } from "./detect-context.js";
|
|
14
15
|
import { importSourceCompletions } from "./import-source.js";
|
|
15
16
|
import { moduleFileCompletions } from "./module-file-completions.js";
|
|
16
17
|
import { valueTagCompletions } from "./value-tag-completions.js";
|
|
@@ -44,11 +45,13 @@ function extractInFileResources(docs: AstDocument[]): ResourceRecord[] {
|
|
|
44
45
|
function refNameCompletions(
|
|
45
46
|
docs: AstDocument[],
|
|
46
47
|
refKind: string | undefined,
|
|
47
|
-
|
|
48
|
+
slot: RefSlot | undefined,
|
|
48
49
|
registry: AnalysisRegistry | undefined,
|
|
50
|
+
analysis: ManifestAnalysis | undefined,
|
|
49
51
|
replaceRange: ReplaceRange,
|
|
50
52
|
): CompletionResult[] {
|
|
51
53
|
const resources = extractInFileResources(docs);
|
|
54
|
+
const refConstraints = slot?.kinds ?? [];
|
|
52
55
|
let acceptable: Set<string> | undefined;
|
|
53
56
|
|
|
54
57
|
if (refKind) {
|
|
@@ -67,6 +70,10 @@ function refNameCompletions(
|
|
|
67
70
|
const out: CompletionResult[] = [];
|
|
68
71
|
for (const r of resources) {
|
|
69
72
|
if (acceptable && !acceptable.has(r.kind)) continue;
|
|
73
|
+
// A target `telo check` refuses for what it returns is not a candidate. The
|
|
74
|
+
// analysis resolves the instance's own contract; without one the kind's
|
|
75
|
+
// decides.
|
|
76
|
+
if (slot && outputRefused(slot, r, registry, analysis)) continue;
|
|
70
77
|
if (seen.has(r.name)) continue;
|
|
71
78
|
seen.add(r.name);
|
|
72
79
|
out.push({
|
|
@@ -81,6 +88,19 @@ function refNameCompletions(
|
|
|
81
88
|
return out;
|
|
82
89
|
}
|
|
83
90
|
|
|
91
|
+
function outputRefused(
|
|
92
|
+
slot: RefSlot,
|
|
93
|
+
candidate: { kind: string; name?: string },
|
|
94
|
+
registry: AnalysisRegistry | undefined,
|
|
95
|
+
analysis: ManifestAnalysis | undefined,
|
|
96
|
+
): boolean {
|
|
97
|
+
if (!slot.outputType) return false;
|
|
98
|
+
const refusal = analysis
|
|
99
|
+
? analysis.outputRefusal(slot, { kind: candidate.kind, name: candidate.name })
|
|
100
|
+
: (registry?.outputRefusal(slot, { kind: candidate.kind }) ?? []);
|
|
101
|
+
return refusal.length > 0;
|
|
102
|
+
}
|
|
103
|
+
|
|
84
104
|
/** Resolve the kinds that satisfy the `x-telo-ref` slot at `parentDocKind` +
|
|
85
105
|
* `parentYamlPath`. Returns `undefined` (caller falls back to the full list)
|
|
86
106
|
* when there's no constraint, the path doesn't resolve, or the ref can't
|
|
@@ -92,15 +112,19 @@ function refConstrainedKinds(
|
|
|
92
112
|
): string[] | undefined {
|
|
93
113
|
const definition = registry.resolveDefinition(parentDocKind);
|
|
94
114
|
if (!definition?.schema) return undefined;
|
|
95
|
-
const
|
|
115
|
+
const slot = lookupRefSlot(
|
|
96
116
|
definition.schema as Record<string, any>,
|
|
97
117
|
parentYamlPath,
|
|
98
118
|
(from) => registry.resolveSchemaFrom(from, parentDocKind),
|
|
99
119
|
);
|
|
100
|
-
if (
|
|
101
|
-
const resolved =
|
|
120
|
+
if (!slot || slot.kinds.length === 0) return undefined;
|
|
121
|
+
const resolved = slot.kinds.map((c) => registry.userFacingKindsForRef(c));
|
|
102
122
|
if (!resolved.some(Boolean)) return undefined;
|
|
103
|
-
|
|
123
|
+
// An inline declaration of a kind whose output the slot refuses would be
|
|
124
|
+
// refused by `telo check` the moment it is written.
|
|
125
|
+
return [...new Set(resolved.flatMap((kinds) => kinds ?? []))].filter(
|
|
126
|
+
(kind) => !outputRefused(slot, { kind }, registry, undefined),
|
|
127
|
+
);
|
|
104
128
|
}
|
|
105
129
|
|
|
106
130
|
function kindCompletions(
|
|
@@ -213,13 +237,13 @@ export async function buildCompletions(
|
|
|
213
237
|
}
|
|
214
238
|
if (ctx.type === "ref-name") {
|
|
215
239
|
const definition = registry?.resolveDefinition(ctx.docKind);
|
|
216
|
-
const
|
|
240
|
+
const slot =
|
|
217
241
|
registry && definition?.schema
|
|
218
|
-
?
|
|
242
|
+
? lookupRefSlot(definition.schema as Record<string, any>, ctx.yamlPath, (from) =>
|
|
219
243
|
registry.resolveSchemaFrom(from, ctx.docKind),
|
|
220
244
|
)
|
|
221
|
-
:
|
|
222
|
-
return refNameCompletions(astDocs, ctx.refKind,
|
|
245
|
+
: undefined;
|
|
246
|
+
return refNameCompletions(astDocs, ctx.refKind, slot, registry, analysis, ctx.replaceRange);
|
|
223
247
|
}
|
|
224
248
|
if (ctx.type === "field-value") {
|
|
225
249
|
if (ctx.field === "import-source") {
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
refSlotAnnotation,
|
|
5
5
|
type AstDocument,
|
|
6
6
|
type CelSegment,
|
|
7
|
+
type RefSlot,
|
|
7
8
|
} from "@telorun/analyzer";
|
|
8
9
|
import type { ReplaceRange } from "../types.js";
|
|
9
10
|
import { valueTag } from "../value-tags/offered-value-tags.js";
|
|
@@ -366,9 +367,18 @@ export function lookupRefConstraints(
|
|
|
366
367
|
yamlPath: string[],
|
|
367
368
|
schemaFrom?: SchemaFromResolver,
|
|
368
369
|
): string[] {
|
|
370
|
+
return lookupRefSlot(definitionSchema, yamlPath, schemaFrom)?.kinds ?? [];
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
/** The whole `x-telo-ref` slot at `yamlPath` — its kinds and what it asks of a
|
|
374
|
+
* target's output — or undefined when the path declares none. */
|
|
375
|
+
export function lookupRefSlot(
|
|
376
|
+
definitionSchema: Record<string, any>,
|
|
377
|
+
yamlPath: string[],
|
|
378
|
+
schemaFrom?: SchemaFromResolver,
|
|
379
|
+
): RefSlot | undefined {
|
|
369
380
|
const node = navigateSchema(definitionSchema, yamlPath, schemaFrom);
|
|
370
|
-
|
|
371
|
-
return readRefSlot(node)?.kinds ?? [];
|
|
381
|
+
return node ? readRefSlot(node) : undefined;
|
|
372
382
|
}
|
|
373
383
|
|
|
374
384
|
/** Derive a `CompletionCtx` from the AST-resolved cursor (Approach B). The
|
|
@@ -42,9 +42,9 @@ export interface ModuleVersion {
|
|
|
42
42
|
*
|
|
43
43
|
* Deliberately NOT `adapter.listVersionsForRef`, which answers `string[]`:
|
|
44
44
|
* completion offers names, an upgrade writes a pin, so the two want different
|
|
45
|
-
* things from one route. A host backed by the hub
|
|
46
|
-
* `GET /module/versions`
|
|
47
|
-
*
|
|
45
|
+
* things from one route. A host backed by the hub reads
|
|
46
|
+
* `GET /module/versions`, carrying an `integrity` only when it is a canonical
|
|
47
|
+
* pin. */
|
|
48
48
|
export type ModuleVersionLookup = (baseRef: string) => Promise<ModuleVersion[]>;
|
|
49
49
|
|
|
50
50
|
/** Everything an upgrade needs from its host: what versions exist, and whether
|
|
@@ -14,7 +14,6 @@ export type {
|
|
|
14
14
|
ModuleVersionLookup,
|
|
15
15
|
} from "./build-import-upgrades.js";
|
|
16
16
|
export { moduleManifestCacheUrl } from "./manifest-cache-url.js";
|
|
17
|
-
export { parseModuleVersions } from "./parse-module-versions.js";
|
|
18
17
|
export { findImportEntries } from "./find-import-entries.js";
|
|
19
18
|
export type {
|
|
20
19
|
ImportEntry,
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import type { ModuleVersion } from "./build-import-upgrades.js";
|
|
2
|
-
/**
|
|
3
|
-
* Read the hub's `GET /module/versions` payload into {@link ModuleVersion}s,
|
|
4
|
-
* newest first (the route's own ordering, preserved).
|
|
5
|
-
*
|
|
6
|
-
* Pure — the host owns the `fetch`, as everything else in this package does.
|
|
7
|
-
* It lives here rather than in each host because the shape is this package's:
|
|
8
|
-
* three hosts parsing the same route by hand is how one of them was left
|
|
9
|
-
* filtering for strings after the route started returning objects, which
|
|
10
|
-
* TypeScript could not catch behind the response cast and which surfaced only
|
|
11
|
-
* as a silently empty version list.
|
|
12
|
-
*
|
|
13
|
-
* Tolerant by design: an entry with no usable `version` is dropped rather than
|
|
14
|
-
* throwing, and an `integrity` that is not a canonical `sha256-<base64url>` is
|
|
15
|
-
* discarded rather than carried — a pin is spliced into the author's YAML, so a
|
|
16
|
-
* malformed one has to become "no pin", never corrupt text.
|
|
17
|
-
*/
|
|
18
|
-
export declare function parseModuleVersions(payload: unknown): ModuleVersion[];
|
|
19
|
-
//# sourceMappingURL=parse-module-versions.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"parse-module-versions.d.ts","sourceRoot":"","sources":["../../src/import-upgrades/parse-module-versions.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAEhE;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,aAAa,EAAE,CAUrE"}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { isCanonicalIntegrity } from "@telorun/analyzer";
|
|
2
|
-
/**
|
|
3
|
-
* Read the hub's `GET /module/versions` payload into {@link ModuleVersion}s,
|
|
4
|
-
* newest first (the route's own ordering, preserved).
|
|
5
|
-
*
|
|
6
|
-
* Pure — the host owns the `fetch`, as everything else in this package does.
|
|
7
|
-
* It lives here rather than in each host because the shape is this package's:
|
|
8
|
-
* three hosts parsing the same route by hand is how one of them was left
|
|
9
|
-
* filtering for strings after the route started returning objects, which
|
|
10
|
-
* TypeScript could not catch behind the response cast and which surfaced only
|
|
11
|
-
* as a silently empty version list.
|
|
12
|
-
*
|
|
13
|
-
* Tolerant by design: an entry with no usable `version` is dropped rather than
|
|
14
|
-
* throwing, and an `integrity` that is not a canonical `sha256-<base64url>` is
|
|
15
|
-
* discarded rather than carried — a pin is spliced into the author's YAML, so a
|
|
16
|
-
* malformed one has to become "no pin", never corrupt text.
|
|
17
|
-
*/
|
|
18
|
-
export function parseModuleVersions(payload) {
|
|
19
|
-
const versions = payload?.versions;
|
|
20
|
-
if (!Array.isArray(versions))
|
|
21
|
-
return [];
|
|
22
|
-
return versions.flatMap((entry) => {
|
|
23
|
-
const version = entry?.version;
|
|
24
|
-
if (typeof version !== "string" || version === "")
|
|
25
|
-
return [];
|
|
26
|
-
const integrity = entry.integrity;
|
|
27
|
-
return [isCanonicalIntegrity(integrity) ? { version, integrity } : { version }];
|
|
28
|
-
});
|
|
29
|
-
}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { isCanonicalIntegrity } from "@telorun/analyzer";
|
|
2
|
-
import type { ModuleVersion } from "./build-import-upgrades.js";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Read the hub's `GET /module/versions` payload into {@link ModuleVersion}s,
|
|
6
|
-
* newest first (the route's own ordering, preserved).
|
|
7
|
-
*
|
|
8
|
-
* Pure — the host owns the `fetch`, as everything else in this package does.
|
|
9
|
-
* It lives here rather than in each host because the shape is this package's:
|
|
10
|
-
* three hosts parsing the same route by hand is how one of them was left
|
|
11
|
-
* filtering for strings after the route started returning objects, which
|
|
12
|
-
* TypeScript could not catch behind the response cast and which surfaced only
|
|
13
|
-
* as a silently empty version list.
|
|
14
|
-
*
|
|
15
|
-
* Tolerant by design: an entry with no usable `version` is dropped rather than
|
|
16
|
-
* throwing, and an `integrity` that is not a canonical `sha256-<base64url>` is
|
|
17
|
-
* discarded rather than carried — a pin is spliced into the author's YAML, so a
|
|
18
|
-
* malformed one has to become "no pin", never corrupt text.
|
|
19
|
-
*/
|
|
20
|
-
export function parseModuleVersions(payload: unknown): ModuleVersion[] {
|
|
21
|
-
const versions = (payload as { versions?: unknown } | null | undefined)?.versions;
|
|
22
|
-
if (!Array.isArray(versions)) return [];
|
|
23
|
-
|
|
24
|
-
return versions.flatMap((entry) => {
|
|
25
|
-
const version = (entry as { version?: unknown } | null)?.version;
|
|
26
|
-
if (typeof version !== "string" || version === "") return [];
|
|
27
|
-
const integrity = (entry as { integrity?: unknown }).integrity;
|
|
28
|
-
return [isCanonicalIntegrity(integrity) ? { version, integrity } : { version }];
|
|
29
|
-
});
|
|
30
|
-
}
|