@intentius/chant 0.124.22 → 0.124.23
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/audit/rules-doc.js +1 -1
- package/dist/cli/handlers/graph.js +24 -1
- package/dist/graph-ir.d.ts +43 -0
- package/dist/graph-ir.d.ts.map +1 -1
- package/dist/graph-ir.js +27 -0
- package/dist/lexicon.d.ts +25 -1
- package/dist/lexicon.d.ts.map +1 -1
- package/dist/wave-runtime.mjs +222 -206
- package/dist/workspace/checks/links.d.ts +5 -0
- package/dist/workspace/checks/links.d.ts.map +1 -1
- package/dist/workspace/checks/links.js +54 -8
- package/dist/workspace/checks.d.ts +4 -1
- package/dist/workspace/checks.d.ts.map +1 -1
- package/dist/workspace/checks.js +6 -2
- package/dist/workspace/compose-graph.d.ts +4 -1
- package/dist/workspace/compose-graph.d.ts.map +1 -1
- package/dist/workspace/compose-graph.js +3 -2
- package/dist/workspace/dbt-project-reader.d.ts +36 -0
- package/dist/workspace/dbt-project-reader.d.ts.map +1 -0
- package/dist/workspace/dbt-project-reader.js +290 -0
- package/dist/workspace/graph-cli.d.ts.map +1 -1
- package/dist/workspace/graph-cli.js +3 -1
- package/dist/workspace/graph.schema.json +41 -3
- package/dist/workspace/intent.js +7 -2
- package/dist/workspace/kind-link-readers.d.ts +84 -0
- package/dist/workspace/kind-link-readers.d.ts.map +1 -0
- package/dist/workspace/kind-link-readers.js +53 -0
- package/dist/workspace/kinds.d.ts +15 -0
- package/dist/workspace/kinds.d.ts.map +1 -1
- package/dist/workspace/kinds.js +11 -0
- package/dist/workspace/lexicon-outputs.d.ts +63 -0
- package/dist/workspace/lexicon-outputs.d.ts.map +1 -0
- package/dist/workspace/lexicon-outputs.js +241 -0
- package/dist/workspace/links.d.ts +29 -7
- package/dist/workspace/links.d.ts.map +1 -1
- package/dist/workspace/links.js +109 -34
- package/dist/workspace/member-handles.d.ts +18 -1
- package/dist/workspace/member-handles.d.ts.map +1 -1
- package/dist/workspace/member-handles.js +31 -14
- package/dist/workspace/records-checkout.d.ts +11 -1
- package/dist/workspace/records-checkout.d.ts.map +1 -1
- package/dist/workspace/records-checkout.js +38 -2
- package/dist/workspace/status.d.ts.map +1 -1
- package/dist/workspace/status.js +3 -2
- package/dist/workspace/workspace-kinds.schema.json +5 -0
- package/package.json +1 -1
- package/src/audit/rules-doc.ts +1 -1
- package/src/cli/handlers/graph.ts +22 -1
- package/src/graph-ir.test.ts +23 -1
- package/src/graph-ir.ts +65 -0
- package/src/lexicon.ts +26 -1
- package/src/wave-loop-golden.test.ts +3 -0
- package/src/workspace/checks/links.ts +57 -8
- package/src/workspace/checks.e2e.test.ts +1 -1
- package/src/workspace/checks.ts +9 -2
- package/src/workspace/compose-graph.ts +5 -3
- package/src/workspace/dbt-kind.e2e.test.ts +95 -0
- package/src/workspace/dbt-kind.test.ts +283 -0
- package/src/workspace/dbt-project-reader.ts +291 -0
- package/src/workspace/graph-cli.ts +3 -1
- package/src/workspace/graph.schema.json +41 -3
- package/src/workspace/intent.ts +7 -2
- package/src/workspace/kind-link-readers.ts +109 -0
- package/src/workspace/kinds.ts +21 -1
- package/src/workspace/lexicon-outputs.ts +272 -0
- package/src/workspace/links.test.ts +22 -0
- package/src/workspace/links.ts +129 -34
- package/src/workspace/member-handles.ts +28 -8
- package/src/workspace/records-checkout.ts +36 -2
- package/src/workspace/records-uncommitted.test.ts +5 -1
- package/src/workspace/status.ts +3 -2
- package/src/workspace/workspace-kinds.schema.json +5 -0
|
@@ -17,6 +17,11 @@
|
|
|
17
17
|
* | WSP096 | a consumer states the same link twice |
|
|
18
18
|
* | WSP097 | an entry lists `outputs` for a kind that doesn't take them from the entry |
|
|
19
19
|
* | WSP098 | a link states a `protocol` and its kind is not `telemetry` (#2558) |
|
|
20
|
+
* | WSP099 | a kind's link reader could not read part of a member's files without guessing (#3932) |
|
|
21
|
+
*
|
|
22
|
+
* Links a kind's reader finds in a member's own files (#3932), such as a dbt
|
|
23
|
+
* project's sources, are checked by WSP093 to WSP095 like declared ones, and
|
|
24
|
+
* their findings name the member's file and line instead of the declaration.
|
|
20
25
|
*/
|
|
21
26
|
import type { WorkspaceCheck, WorkspaceCheckContext } from "../checks.js";
|
|
22
27
|
import { type LinkTableRow } from "../links.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"links.d.ts","sourceRoot":"","sources":["../../../src/workspace/checks/links.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"links.d.ts","sourceRoot":"","sources":["../../../src/workspace/checks/links.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,qBAAqB,EAAuB,MAAM,WAAW,CAAC;AAI5F,OAAO,EAAwH,KAAK,YAAY,EAAE,MAAM,UAAU,CAAC;AAenK,mFAAmF;AACnF,wBAAgB,SAAS,CAAC,GAAG,EAAE,qBAAqB,GAAG,YAAY,EAAE,CAOpE;AAoBD,eAAO,MAAM,WAAW,EAAE,SAAS,cAAc,EAmLhD,CAAC"}
|
|
@@ -17,23 +17,48 @@
|
|
|
17
17
|
* | WSP096 | a consumer states the same link twice |
|
|
18
18
|
* | WSP097 | an entry lists `outputs` for a kind that doesn't take them from the entry |
|
|
19
19
|
* | WSP098 | a link states a `protocol` and its kind is not `telemetry` (#2558) |
|
|
20
|
+
* | WSP099 | a kind's link reader could not read part of a member's files without guessing (#3932) |
|
|
21
|
+
*
|
|
22
|
+
* Links a kind's reader finds in a member's own files (#3932), such as a dbt
|
|
23
|
+
* project's sources, are checked by WSP093 to WSP095 like declared ones, and
|
|
24
|
+
* their findings name the member's file and line instead of the declaration.
|
|
20
25
|
*/
|
|
21
26
|
import { sourceMemberHandles } from "../member-handles.js";
|
|
27
|
+
import { readKindLinks } from "../kind-link-readers.js";
|
|
22
28
|
import { DEFAULT_LINK_KIND, LINK_KINDS, TELEMETRY_LINK_KIND, linkTargetProblem, resolveLinks } from "../links.js";
|
|
23
29
|
const tables = new WeakMap();
|
|
30
|
+
const reads = new WeakMap();
|
|
31
|
+
/** What each member's kind reader found (#3932), read once per check run. */
|
|
32
|
+
function kindReads(ctx) {
|
|
33
|
+
let read = reads.get(ctx);
|
|
34
|
+
if (!read) {
|
|
35
|
+
read = readKindLinks(ctx.declaration, ctx.tree, ctx.kinds);
|
|
36
|
+
reads.set(ctx, read);
|
|
37
|
+
}
|
|
38
|
+
return read;
|
|
39
|
+
}
|
|
24
40
|
/** The link rows for a check run, resolved once and shared by every link check. */
|
|
25
41
|
export function linkTable(ctx) {
|
|
26
42
|
let rows = tables.get(ctx);
|
|
27
43
|
if (!rows) {
|
|
28
|
-
rows = resolveLinks(ctx.declaration, sourceMemberHandles(ctx.declaration, ctx.tree, ctx.groups, ctx.kinds));
|
|
44
|
+
rows = resolveLinks(ctx.declaration, sourceMemberHandles(ctx.declaration, ctx.tree, ctx.groups, ctx.kinds, ctx.facts?.lexiconOutputs), undefined, kindReads(ctx));
|
|
29
45
|
tables.set(ctx, rows);
|
|
30
46
|
}
|
|
31
47
|
return rows;
|
|
32
48
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
49
|
+
/** The declared links, and the links a kind's reader found: the rows a member states. */
|
|
50
|
+
const statedRows = (ctx) => linkTable(ctx).filter((r) => r.status !== "ambiguous" && r.origin !== "inferred:joinKey");
|
|
51
|
+
/** A finding at a declared link's field in the declaration, or at the file and line a reader's link came from. */
|
|
52
|
+
function linkFinding(check, ctx, row, field, message) {
|
|
53
|
+
const base = { checkId: check.id, severity: check.severity, message, entity: row.consumer };
|
|
54
|
+
if (row.origin === "kind-reader" && row.file !== undefined) {
|
|
55
|
+
const member = ctx.declaration.members.find((m) => m.name === row.consumer);
|
|
56
|
+
return { ...base, pointer: member?.pointer ?? "", treeFile: row.file, line: row.line ?? 1, column: 1 };
|
|
57
|
+
}
|
|
58
|
+
return { ...base, pointer: `${row.pointer}/${field}` };
|
|
36
59
|
}
|
|
60
|
+
/** Where a reader's link came from, for its message; empty for a declared link. */
|
|
61
|
+
const statedAt = (row) => (row.origin === "kind-reader" ? ` (read by ${row.reader} from ${row.file}:${row.line})` : "");
|
|
37
62
|
const describeLink = (row) => `${row.consumer}'s link to ${row.producer} output ${row.output}`;
|
|
38
63
|
export const LINK_CHECKS = [
|
|
39
64
|
{
|
|
@@ -74,9 +99,9 @@ export const LINK_CHECKS = [
|
|
|
74
99
|
severity: "error",
|
|
75
100
|
configurable: true,
|
|
76
101
|
check(ctx) {
|
|
77
|
-
return
|
|
102
|
+
return statedRows(ctx)
|
|
78
103
|
.filter((r) => r.status === "missing")
|
|
79
|
-
.map((r) => linkFinding(this, r, "output", `${describeLink(r)} does not resolve: ${r.reason}`));
|
|
104
|
+
.map((r) => linkFinding(this, ctx, r, "output", `${describeLink(r)}${statedAt(r)} does not resolve: ${r.reason}`));
|
|
80
105
|
},
|
|
81
106
|
},
|
|
82
107
|
{
|
|
@@ -86,9 +111,9 @@ export const LINK_CHECKS = [
|
|
|
86
111
|
severity: "info",
|
|
87
112
|
configurable: true,
|
|
88
113
|
check(ctx) {
|
|
89
|
-
return
|
|
114
|
+
return statedRows(ctx)
|
|
90
115
|
.filter((r) => r.status === "unresolved")
|
|
91
|
-
.map((r) => linkFinding(this, r, "output", `${describeLink(r)} is kept unresolved: ${r.reason}`));
|
|
116
|
+
.map((r) => linkFinding(this, ctx, r, "output", `${describeLink(r)}${statedAt(r)} is kept unresolved: ${r.reason}`));
|
|
92
117
|
},
|
|
93
118
|
},
|
|
94
119
|
{
|
|
@@ -102,6 +127,10 @@ export const LINK_CHECKS = [
|
|
|
102
127
|
return linkTable(ctx)
|
|
103
128
|
.filter((r) => r.status === "ambiguous")
|
|
104
129
|
.map((r) => {
|
|
130
|
+
if (r.origin === "kind-reader") {
|
|
131
|
+
const choices = r.candidates.map((c) => c.producer).join(", ");
|
|
132
|
+
return linkFinding(this, ctx, r, "", `${r.consumer}'s link to ${r.input} (read by ${r.reader}) has no single producer: ${r.reason}${choices ? `. Candidates: ${choices}` : ""}`);
|
|
133
|
+
}
|
|
105
134
|
const choices = r.candidates.map((c) => `${c.producer} output ${c.output} (${c.label})`).join(", ");
|
|
106
135
|
const first = r.candidates[0];
|
|
107
136
|
return {
|
|
@@ -188,4 +217,21 @@ export const LINK_CHECKS = [
|
|
|
188
217
|
})));
|
|
189
218
|
},
|
|
190
219
|
},
|
|
220
|
+
{
|
|
221
|
+
id: "WSP099",
|
|
222
|
+
name: "kind-reader-gap",
|
|
223
|
+
description: "A kind's link reader read every link in a member's files that it could read without guessing (#3932). A value it would have to render, such as a Jinja template in a dbt source, is reported here with its file and line, and the links it would state are not checked.",
|
|
224
|
+
severity: "info",
|
|
225
|
+
configurable: true,
|
|
226
|
+
check(ctx) {
|
|
227
|
+
const out = [];
|
|
228
|
+
for (const [member, read] of kindReads(ctx)) {
|
|
229
|
+
const pointer = ctx.declaration.members.find((m) => m.name === member)?.pointer ?? "";
|
|
230
|
+
for (const gap of read.gaps) {
|
|
231
|
+
out.push({ checkId: this.id, severity: this.severity, message: `${member} (read by ${read.reader}): ${gap.message}`, entity: member, pointer, treeFile: gap.file, line: gap.line, column: 1 });
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
return out;
|
|
235
|
+
},
|
|
236
|
+
},
|
|
191
237
|
];
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
* | WSP001 to WSP011 | the declaration and member kinds (this file) |
|
|
25
25
|
* | WSP071, WSP072 | member ledgers |
|
|
26
26
|
* | WSP081 to WSP083 | recorded pipelines |
|
|
27
|
-
* | WSP091 to
|
|
27
|
+
* | WSP091 to WSP099 | member links (#2539, #2558), and those a kind's reader finds in a member's files (#3932) |
|
|
28
28
|
* | WSP101 to WSP106 | generated files |
|
|
29
29
|
* | WSP111 to WSP114 | records read with `--kind` (#2549) |
|
|
30
30
|
* | WSP115 | the record kinds the declaration names (#2680) |
|
|
@@ -52,6 +52,7 @@ import { type LiveLinkFacts } from "./checks/live.js";
|
|
|
52
52
|
import { type RecordFacts } from "./checks/records.js";
|
|
53
53
|
import { type DeclaredKind } from "./declared-kinds.js";
|
|
54
54
|
import { type ResolvedBoxIntent } from "./box-intent.js";
|
|
55
|
+
import { type MemberLexiconOutputs } from "./lexicon-outputs.js";
|
|
55
56
|
/**
|
|
56
57
|
* What the checks beyond the declaration read, gathered from the checkout
|
|
57
58
|
* before any check runs. A field left out was not gathered, and the checks
|
|
@@ -72,6 +73,8 @@ export interface WorkspaceFacts {
|
|
|
72
73
|
live?: LiveLinkFacts;
|
|
73
74
|
/** The decision record each box's intent names, read from the working tree (#2850). */
|
|
74
75
|
boxIntents?: readonly ResolvedBoxIntent[];
|
|
76
|
+
/** The outputs linked members' lexicons report about their declarations, read by folding their source (#3931). */
|
|
77
|
+
lexiconOutputs?: ReadonlyMap<string, MemberLexiconOutputs>;
|
|
75
78
|
}
|
|
76
79
|
/** What every declaration check reads. */
|
|
77
80
|
export interface WorkspaceCheckContext {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"checks.d.ts","sourceRoot":"","sources":["../../src/workspace/checks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACvE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAsD,KAAK,WAAW,EAAkC,KAAK,aAAa,EAAE,MAAM,eAAe,CAAC;AACzJ,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEjD,OAAO,EAAiE,KAAK,eAAe,EAAE,KAAK,YAAY,EAAE,MAAM,SAAS,CAAC;AACjI,OAAO,EAA6D,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpH,OAAO,EAAuB,KAAK,aAAa,EAAE,MAAM,QAAQ,CAAC;AAEjE,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACrD,OAAO,EAA0C,KAAK,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACrG,OAAO,EAAoC,KAAK,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAC5F,OAAO,EAAwC,KAAK,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACpG,OAAO,EAAoC,KAAK,aAAa,EAAE,MAAM,eAAe,CAAC;AACrF,OAAO,EAAiB,KAAK,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAGnE,OAAO,EAAqB,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACxE,OAAO,EAAqB,KAAK,iBAAiB,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"checks.d.ts","sourceRoot":"","sources":["../../src/workspace/checks.ts"],"names":[],"mappings":"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"}
|
package/dist/workspace/checks.js
CHANGED
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
* | WSP001 to WSP011 | the declaration and member kinds (this file) |
|
|
25
25
|
* | WSP071, WSP072 | member ledgers |
|
|
26
26
|
* | WSP081 to WSP083 | recorded pipelines |
|
|
27
|
-
* | WSP091 to
|
|
27
|
+
* | WSP091 to WSP099 | member links (#2539, #2558), and those a kind's reader finds in a member's files (#3932) |
|
|
28
28
|
* | WSP101 to WSP106 | generated files |
|
|
29
29
|
* | WSP111 to WSP114 | records read with `--kind` (#2549) |
|
|
30
30
|
* | WSP115 | the record kinds the declaration names (#2680) |
|
|
@@ -54,6 +54,7 @@ import { BOX_CHECKS } from "./checks/boxes.js";
|
|
|
54
54
|
import { DIAGRAM_CHECKS } from "./checks/diagrams.js";
|
|
55
55
|
import { loadDeclaredKinds } from "./declared-kinds.js";
|
|
56
56
|
import { resolveBoxIntents } from "./box-intent.js";
|
|
57
|
+
import { gatherLexiconOutputs } from "./lexicon-outputs.js";
|
|
57
58
|
const HELP = "https://intentius.io/chant/cli/workspace-check/#declaration-checks";
|
|
58
59
|
const memberDir = (dir) => (dir === "." ? "" : dir);
|
|
59
60
|
function entryFinding(check, entry, field, message) {
|
|
@@ -256,7 +257,7 @@ export const WORKSPACE_CHECKS = [
|
|
|
256
257
|
...LEDGER_CHECKS,
|
|
257
258
|
// Recorded pipelines (#2542).
|
|
258
259
|
...PIPELINE_CHECKS,
|
|
259
|
-
// Member links (#2539, #2558), WSP091 to
|
|
260
|
+
// Member links (#2539, #2558, #3932), WSP091 to WSP099.
|
|
260
261
|
...LINK_CHECKS,
|
|
261
262
|
// Generated files (#2541).
|
|
262
263
|
...GENERATED_CHECKS,
|
|
@@ -388,7 +389,10 @@ export async function runDeclarationChecks(root, display = (f) => f, options = {
|
|
|
388
389
|
const declaredKinds = options.gather === false ? undefined : await loadDeclaredKinds(declaration, tree, root, { load: !options.tree, acceptance: !options.tree });
|
|
389
390
|
// A box's intent is read from the working tree's records, so not under --at (#2850).
|
|
390
391
|
const boxIntents = declaredKinds && !options.tree ? await resolveBoxIntents(declaration, root, declaredKinds) : undefined;
|
|
392
|
+
// A linked member's lexicons name its tables and columns as outputs (#3931); reading them folds its source, never runs it.
|
|
393
|
+
const lexiconOutputs = options.gather === false ? undefined : await gatherLexiconOutputs(root, declaration, options.tree ? workingTree(root) : tree, groups, registry, { atRevision: options.tree !== undefined });
|
|
391
394
|
const facts = {
|
|
395
|
+
...(lexiconOutputs && lexiconOutputs.size > 0 ? { lexiconOutputs } : {}),
|
|
392
396
|
...gathered,
|
|
393
397
|
...(options.records ? { records: options.records } : {}),
|
|
394
398
|
...(declaredKinds ? { declaredKinds } : {}),
|
|
@@ -32,6 +32,7 @@ import type { FactoryView, ListingView } from "./box-factory.js";
|
|
|
32
32
|
import type { Declaration } from "./declaration.js";
|
|
33
33
|
import type { KindRegistry } from "./kinds.js";
|
|
34
34
|
import { type LinkTableRow } from "./links.js";
|
|
35
|
+
import type { KindLinkRead } from "./kind-link-readers.js";
|
|
35
36
|
import type { RecordLinkRow } from "./record-assets.js";
|
|
36
37
|
import { type GraphIR, type IRExport, type IRGroups, type IRImport, type IREdge, type IRNode } from "../graph-ir.js";
|
|
37
38
|
/** The version of the composed document `chant workspace graph` writes. */
|
|
@@ -205,7 +206,8 @@ export interface ComposeInput {
|
|
|
205
206
|
* Compose the members' IRs into the workspace document. Members keep the
|
|
206
207
|
* order they are given in. With `links`, the `links` section is filled from
|
|
207
208
|
* the declaration; `kinds` lets a member that isn't composed but whose kind
|
|
208
|
-
* lists its outputs (`other`, kinds from a package) be a link target
|
|
209
|
+
* lists its outputs (`other`, kinds from a package) be a link target, and
|
|
210
|
+
* `read` holds the links each member's kind reader found in its files (#3932).
|
|
209
211
|
*/
|
|
210
212
|
export declare function composeWorkspaceGraph(workspace: {
|
|
211
213
|
name: string;
|
|
@@ -213,5 +215,6 @@ export declare function composeWorkspaceGraph(workspace: {
|
|
|
213
215
|
}, inputs: ComposeInput[], links?: {
|
|
214
216
|
declaration: Declaration;
|
|
215
217
|
kinds?: KindRegistry;
|
|
218
|
+
read?: ReadonlyMap<string, KindLinkRead>;
|
|
216
219
|
}): WorkspaceGraph;
|
|
217
220
|
//# sourceMappingURL=compose-graph.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compose-graph.d.ts","sourceRoot":"","sources":["../../src/workspace/compose-graph.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"compose-graph.d.ts","sourceRoot":"","sources":["../../src/workspace/compose-graph.ts"],"names":[],"mappings":"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"}
|
|
@@ -145,7 +145,8 @@ function sorted(rec) {
|
|
|
145
145
|
* Compose the members' IRs into the workspace document. Members keep the
|
|
146
146
|
* order they are given in. With `links`, the `links` section is filled from
|
|
147
147
|
* the declaration; `kinds` lets a member that isn't composed but whose kind
|
|
148
|
-
* lists its outputs (`other`, kinds from a package) be a link target
|
|
148
|
+
* lists its outputs (`other`, kinds from a package) be a link target, and
|
|
149
|
+
* `read` holds the links each member's kind reader found in its files (#3932).
|
|
149
150
|
*/
|
|
150
151
|
export function composeWorkspaceGraph(workspace, inputs, links) {
|
|
151
152
|
const nodes = [];
|
|
@@ -223,7 +224,7 @@ export function composeWorkspaceGraph(workspace, inputs, links) {
|
|
|
223
224
|
exports,
|
|
224
225
|
imports,
|
|
225
226
|
links: links
|
|
226
|
-
? graphLinks(links.declaration, { composed: inputs.filter((i) => i.ir).map((i) => i.member.name), collectors, exports, imports }, links.kinds)
|
|
227
|
+
? graphLinks(links.declaration, { composed: inputs.filter((i) => i.ir).map((i) => i.member.name), collectors, exports, imports }, links.kinds, links.read)
|
|
227
228
|
: [],
|
|
228
229
|
collectors,
|
|
229
230
|
records: [],
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `dbt-project` link reader (#3932): a dbt project's sources, as links to
|
|
3
|
+
* the tables and columns a sql member exposes (#3931).
|
|
4
|
+
*
|
|
5
|
+
* The reader parses YAML and nothing else. It never runs dbt, never renders
|
|
6
|
+
* Jinja and never reads `profiles.yml` or a target, so the links it derives
|
|
7
|
+
* are the same in every environment.
|
|
8
|
+
*
|
|
9
|
+
* - The project is `dbt_project.yml`. Sources are read from every `.yml` and
|
|
10
|
+
* `.yaml` file under its `model-paths` (`source-paths` in older projects;
|
|
11
|
+
* `models` when it names neither), as dbt reads them.
|
|
12
|
+
* - Each enabled source table links to `<schema>.<table>`, and each of its
|
|
13
|
+
* `columns` to `<schema>.<table>.<column>`. The schema is the source's
|
|
14
|
+
* `schema`, or the source's `name` when it sets none, which is dbt's own
|
|
15
|
+
* fallback. The table is its `identifier`, or its `name`. `database` is not
|
|
16
|
+
* part of the name: a Postgres output has none, and dbt-clickhouse reads a
|
|
17
|
+
* source's `schema` as the ClickHouse database.
|
|
18
|
+
* - Case follows the member's `dialect` field. For `postgres`, an unquoted
|
|
19
|
+
* name folds to lowercase and a quoted one keeps its case. dbt quotes a
|
|
20
|
+
* source's schema and identifier on Postgres unless `quoting:` (in
|
|
21
|
+
* `dbt_project.yml`, on the source, or on the table) turns it off, and a
|
|
22
|
+
* column is quoted only with `quote: true`. For `clickhouse`, names are
|
|
23
|
+
* kept as written.
|
|
24
|
+
* - A value that is a Jinja template (`{{ ... }}` or `{% ... %}`) is not
|
|
25
|
+
* resolved: the reader records a gap and leaves that source, table or
|
|
26
|
+
* column out, rather than guess what a target would render.
|
|
27
|
+
* - The producer is the member the `sqlMember` field names. Unset, each link
|
|
28
|
+
* leaves the producer to `resolveLinks`, which picks the one member that
|
|
29
|
+
* exposes the table.
|
|
30
|
+
*/
|
|
31
|
+
import type { KindLinkRead, KindReaderInput } from "./kind-link-readers.js";
|
|
32
|
+
export declare const DBT_PROJECT_FILE = "dbt_project.yml";
|
|
33
|
+
/** The dialects whose naming the reader follows; the member's `dialect` field picks one. */
|
|
34
|
+
export declare const DBT_DIALECTS: readonly ["postgres", "clickhouse"];
|
|
35
|
+
export declare function readDbtProject(input: KindReaderInput): KindLinkRead;
|
|
36
|
+
//# sourceMappingURL=dbt-project-reader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dbt-project-reader.d.ts","sourceRoot":"","sources":["../../src/workspace/dbt-project-reader.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAIH,OAAO,KAAK,EAAE,YAAY,EAA6B,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAGpG,eAAO,MAAM,gBAAgB,oBAAoB,CAAC;AAGlD,4FAA4F;AAC5F,eAAO,MAAM,YAAY,YAAI,UAAU,EAAE,YAAY,CAAU,CAAC;AAWhE,wBAAgB,cAAc,CAAC,KAAK,EAAE,eAAe,GAAG,YAAY,CAqJnE"}
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `dbt-project` link reader (#3932): a dbt project's sources, as links to
|
|
3
|
+
* the tables and columns a sql member exposes (#3931).
|
|
4
|
+
*
|
|
5
|
+
* The reader parses YAML and nothing else. It never runs dbt, never renders
|
|
6
|
+
* Jinja and never reads `profiles.yml` or a target, so the links it derives
|
|
7
|
+
* are the same in every environment.
|
|
8
|
+
*
|
|
9
|
+
* - The project is `dbt_project.yml`. Sources are read from every `.yml` and
|
|
10
|
+
* `.yaml` file under its `model-paths` (`source-paths` in older projects;
|
|
11
|
+
* `models` when it names neither), as dbt reads them.
|
|
12
|
+
* - Each enabled source table links to `<schema>.<table>`, and each of its
|
|
13
|
+
* `columns` to `<schema>.<table>.<column>`. The schema is the source's
|
|
14
|
+
* `schema`, or the source's `name` when it sets none, which is dbt's own
|
|
15
|
+
* fallback. The table is its `identifier`, or its `name`. `database` is not
|
|
16
|
+
* part of the name: a Postgres output has none, and dbt-clickhouse reads a
|
|
17
|
+
* source's `schema` as the ClickHouse database.
|
|
18
|
+
* - Case follows the member's `dialect` field. For `postgres`, an unquoted
|
|
19
|
+
* name folds to lowercase and a quoted one keeps its case. dbt quotes a
|
|
20
|
+
* source's schema and identifier on Postgres unless `quoting:` (in
|
|
21
|
+
* `dbt_project.yml`, on the source, or on the table) turns it off, and a
|
|
22
|
+
* column is quoted only with `quote: true`. For `clickhouse`, names are
|
|
23
|
+
* kept as written.
|
|
24
|
+
* - A value that is a Jinja template (`{{ ... }}` or `{% ... %}`) is not
|
|
25
|
+
* resolved: the reader records a gap and leaves that source, table or
|
|
26
|
+
* column out, rather than guess what a target would render.
|
|
27
|
+
* - The producer is the member the `sqlMember` field names. Unset, each link
|
|
28
|
+
* leaves the producer to `resolveLinks`, which picks the one member that
|
|
29
|
+
* exposes the table.
|
|
30
|
+
*/
|
|
31
|
+
import { posix } from "node:path";
|
|
32
|
+
import { parseYAMLDocument, YAMLParseError } from "../yaml.js";
|
|
33
|
+
import { joinPath, skippedDir } from "./tree.js";
|
|
34
|
+
export const DBT_PROJECT_FILE = "dbt_project.yml";
|
|
35
|
+
const DEFAULT_MODEL_PATHS = ["models"];
|
|
36
|
+
/** The dialects whose naming the reader follows; the member's `dialect` field picks one. */
|
|
37
|
+
export const DBT_DIALECTS = ["postgres", "clickhouse"];
|
|
38
|
+
const isTemplated = (v) => /\{\{|\{%/.test(v);
|
|
39
|
+
const isObject = (v) => v !== null && typeof v === "object" && !Array.isArray(v);
|
|
40
|
+
export function readDbtProject(input) {
|
|
41
|
+
const { dir, tree, fields } = input;
|
|
42
|
+
const links = [];
|
|
43
|
+
const gaps = [];
|
|
44
|
+
const result = { reader: "dbt-project", links, gaps, producerField: "sqlMember" };
|
|
45
|
+
const projectFile = joinPath(dir, DBT_PROJECT_FILE);
|
|
46
|
+
const producer = typeof fields?.sqlMember === "string" && fields.sqlMember !== "" ? fields.sqlMember : null;
|
|
47
|
+
const dialect = fields?.dialect === "clickhouse" ? "clickhouse" : "postgres";
|
|
48
|
+
let project;
|
|
49
|
+
try {
|
|
50
|
+
project = parseYAMLDocument(tree.read(projectFile));
|
|
51
|
+
}
|
|
52
|
+
catch (err) {
|
|
53
|
+
gaps.push({ file: projectFile, line: err instanceof YAMLParseError ? err.line : 1, message: `${DBT_PROJECT_FILE} could not be read (${err.message}), so no source was read` });
|
|
54
|
+
return result;
|
|
55
|
+
}
|
|
56
|
+
if (!isObject(project)) {
|
|
57
|
+
gaps.push({ file: projectFile, line: 1, message: `${DBT_PROJECT_FILE} is not a mapping, so no source was read` });
|
|
58
|
+
return result;
|
|
59
|
+
}
|
|
60
|
+
const projectLines = lines(tree.read(projectFile));
|
|
61
|
+
// Where sources live: model-paths, or the older source-paths.
|
|
62
|
+
const key = project["model-paths"] !== undefined ? "model-paths" : project["source-paths"] !== undefined ? "source-paths" : null;
|
|
63
|
+
const rawPaths = key ? project[key] : DEFAULT_MODEL_PATHS;
|
|
64
|
+
const paths = [];
|
|
65
|
+
if (!Array.isArray(rawPaths)) {
|
|
66
|
+
gaps.push({ file: projectFile, line: keyLine(projectLines, key ?? ""), message: `${key} is not a list, so no source was read` });
|
|
67
|
+
return result;
|
|
68
|
+
}
|
|
69
|
+
for (const p of rawPaths) {
|
|
70
|
+
if (typeof p !== "string" || isTemplated(p)) {
|
|
71
|
+
gaps.push({ file: projectFile, line: keyLine(projectLines, key ?? ""), message: `${key} entry ${JSON.stringify(p)} is not a plain path; its sources were not read` });
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
const at = posix.normalize(joinPath(dir, p));
|
|
75
|
+
if (at.startsWith("../") || at === ".." || posix.isAbsolute(p)) {
|
|
76
|
+
gaps.push({ file: projectFile, line: keyLine(projectLines, key ?? ""), message: `${key} entry ${p} lies outside the workspace; its sources were not read` });
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
paths.push(at === "." ? "" : at);
|
|
80
|
+
}
|
|
81
|
+
const quoting = readQuoting({ schema: true, identifier: true }, project.quoting, projectFile, keyLine(projectLines, "quoting"), "dbt_project.yml quoting", gaps);
|
|
82
|
+
const files = new Set();
|
|
83
|
+
for (const p of paths)
|
|
84
|
+
for (const f of yamlFiles(tree, p))
|
|
85
|
+
files.add(f);
|
|
86
|
+
const name = (v, quoted) => (dialect === "postgres" && !quoted ? v.toLowerCase() : v);
|
|
87
|
+
for (const file of [...files].sort()) {
|
|
88
|
+
let text;
|
|
89
|
+
let doc;
|
|
90
|
+
try {
|
|
91
|
+
text = tree.read(file);
|
|
92
|
+
doc = parseYAMLDocument(text);
|
|
93
|
+
}
|
|
94
|
+
catch (err) {
|
|
95
|
+
gaps.push({ file, line: err instanceof YAMLParseError ? err.line : 1, message: `the file could not be read as YAML (${err.message}); any sources in it were not read` });
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
if (!isObject(doc) || doc.sources === undefined || doc.sources === null)
|
|
99
|
+
continue;
|
|
100
|
+
const fileLines = lines(text);
|
|
101
|
+
const sourcesLine = keyLine(fileLines, "sources");
|
|
102
|
+
if (!Array.isArray(doc.sources)) {
|
|
103
|
+
gaps.push({ file, line: sourcesLine, message: "sources is not a list; its sources were not read" });
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
let cursor = sourcesLine;
|
|
107
|
+
for (const source of doc.sources) {
|
|
108
|
+
if (!isObject(source))
|
|
109
|
+
continue;
|
|
110
|
+
const sourceName = scalar(source.name);
|
|
111
|
+
const sourceLine = nameLine(fileLines, sourceName, cursor);
|
|
112
|
+
cursor = sourceLine;
|
|
113
|
+
if (sourceName === undefined) {
|
|
114
|
+
gaps.push({ file, line: sourceLine, message: "a source has no name; its tables were not read" });
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
const where = `source ${sourceName}`;
|
|
118
|
+
if (isTemplated(sourceName)) {
|
|
119
|
+
gaps.push({ file, line: sourceLine, message: `${where}: its name is a Jinja template, which chant does not render; its tables were not read` });
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
const enabled = readEnabled(source, file, sourceLine, where, gaps);
|
|
123
|
+
if (enabled !== true)
|
|
124
|
+
continue;
|
|
125
|
+
const schema = source.schema === undefined || source.schema === null ? sourceName : scalar(source.schema);
|
|
126
|
+
if (schema === undefined || isTemplated(schema)) {
|
|
127
|
+
gaps.push({
|
|
128
|
+
file,
|
|
129
|
+
line: valueLine(fileLines, "schema", sourceLine),
|
|
130
|
+
message: `${where}: schema ${JSON.stringify(source.schema)} is a Jinja template or not a name; chant reads names as declared and never renders them for a target, so its tables were not read`,
|
|
131
|
+
});
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
const sourceQuoting = readQuoting(quoting, source.quoting, file, sourceLine, `${where} quoting`, gaps);
|
|
135
|
+
if (source.tables === undefined || source.tables === null)
|
|
136
|
+
continue;
|
|
137
|
+
if (!Array.isArray(source.tables)) {
|
|
138
|
+
gaps.push({ file, line: sourceLine, message: `${where}: tables is not a list; its tables were not read` });
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
let tableCursor = sourceLine;
|
|
142
|
+
for (const table of source.tables) {
|
|
143
|
+
if (!isObject(table))
|
|
144
|
+
continue;
|
|
145
|
+
const tableName = scalar(table.name);
|
|
146
|
+
const tableLine = nameLine(fileLines, tableName, tableCursor);
|
|
147
|
+
tableCursor = tableLine;
|
|
148
|
+
if (tableName === undefined) {
|
|
149
|
+
gaps.push({ file, line: tableLine, message: `${where}: a table has no name; it was not read` });
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
const tableWhere = `${where} table ${tableName}`;
|
|
153
|
+
if (isTemplated(tableName)) {
|
|
154
|
+
gaps.push({ file, line: tableLine, message: `${tableWhere}: its name is a Jinja template, which chant does not render; it was not read` });
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
if (readEnabled(table, file, tableLine, tableWhere, gaps) !== true)
|
|
158
|
+
continue;
|
|
159
|
+
const identifier = table.identifier === undefined || table.identifier === null ? tableName : scalar(table.identifier);
|
|
160
|
+
if (identifier === undefined || isTemplated(identifier)) {
|
|
161
|
+
gaps.push({
|
|
162
|
+
file,
|
|
163
|
+
line: valueLine(fileLines, "identifier", tableLine),
|
|
164
|
+
message: `${tableWhere}: identifier ${JSON.stringify(table.identifier)} is a Jinja template or not a name, which chant does not render; it was not read`,
|
|
165
|
+
});
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
const q = readQuoting(sourceQuoting, table.quoting, file, tableLine, `${tableWhere} quoting`, gaps);
|
|
169
|
+
const tableOutput = `${name(schema, q.schema)}.${name(identifier, q.identifier)}`;
|
|
170
|
+
links.push({ member: producer, output: tableOutput, file, line: tableLine });
|
|
171
|
+
if (table.columns === undefined || table.columns === null)
|
|
172
|
+
continue;
|
|
173
|
+
if (!Array.isArray(table.columns)) {
|
|
174
|
+
gaps.push({ file, line: tableLine, message: `${tableWhere}: columns is not a list; its columns were not read` });
|
|
175
|
+
continue;
|
|
176
|
+
}
|
|
177
|
+
let columnCursor = tableLine;
|
|
178
|
+
for (const column of table.columns) {
|
|
179
|
+
if (!isObject(column))
|
|
180
|
+
continue;
|
|
181
|
+
const columnName = scalar(column.name);
|
|
182
|
+
const columnLine = nameLine(fileLines, columnName, columnCursor);
|
|
183
|
+
columnCursor = columnLine;
|
|
184
|
+
if (columnName === undefined || isTemplated(columnName)) {
|
|
185
|
+
gaps.push({ file, line: columnLine, message: `${tableWhere}: column ${JSON.stringify(column.name)} is a Jinja template or not a name, which chant does not render; it was not read` });
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
const quoted = column.quote === true;
|
|
189
|
+
links.push({ member: producer, output: `${tableOutput}.${name(columnName, quoted)}`, anchor: tableOutput, file, line: columnLine });
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
return result;
|
|
195
|
+
}
|
|
196
|
+
/** A name as text: a string, or a number or boolean YAML read as one. */
|
|
197
|
+
function scalar(v) {
|
|
198
|
+
if (typeof v === "string")
|
|
199
|
+
return v;
|
|
200
|
+
if (typeof v === "number" || typeof v === "boolean")
|
|
201
|
+
return String(v);
|
|
202
|
+
return undefined;
|
|
203
|
+
}
|
|
204
|
+
/** Whether an entry is enabled: `enabled`, or `config.enabled`. A templated value is a gap, and the entry is left out. */
|
|
205
|
+
function readEnabled(entry, file, line, where, gaps) {
|
|
206
|
+
const config = isObject(entry.config) ? entry.config : {};
|
|
207
|
+
const raw = entry.enabled ?? config.enabled;
|
|
208
|
+
if (raw === undefined || raw === null || raw === true)
|
|
209
|
+
return true;
|
|
210
|
+
if (raw === false)
|
|
211
|
+
return false;
|
|
212
|
+
gaps.push({ file, line, message: `${where}: enabled is ${JSON.stringify(raw)}, which chant does not render; it was not read` });
|
|
213
|
+
return false;
|
|
214
|
+
}
|
|
215
|
+
/** `base` with a `quoting:` block's schema and identifier applied. A value that isn't a boolean is a gap and keeps the base. */
|
|
216
|
+
function readQuoting(base, raw, file, line, where, gaps) {
|
|
217
|
+
if (raw === undefined || raw === null)
|
|
218
|
+
return base;
|
|
219
|
+
if (!isObject(raw)) {
|
|
220
|
+
gaps.push({ file, line, message: `${where} is not a mapping; the quoting above it applies` });
|
|
221
|
+
return base;
|
|
222
|
+
}
|
|
223
|
+
const out = { ...base };
|
|
224
|
+
for (const key of ["schema", "identifier"]) {
|
|
225
|
+
const v = raw[key];
|
|
226
|
+
if (v === undefined)
|
|
227
|
+
continue;
|
|
228
|
+
if (typeof v === "boolean")
|
|
229
|
+
out[key] = v;
|
|
230
|
+
else
|
|
231
|
+
gaps.push({ file, line, message: `${where}.${key} is ${JSON.stringify(v)}, not true or false; the quoting above it applies` });
|
|
232
|
+
}
|
|
233
|
+
return out;
|
|
234
|
+
}
|
|
235
|
+
/** Every `.yml` and `.yaml` file under tree-relative directory `dir`, skipping dot directories and node_modules. */
|
|
236
|
+
function yamlFiles(tree, dir) {
|
|
237
|
+
if (dir !== "" && tree.stat(dir) !== "dir")
|
|
238
|
+
return [];
|
|
239
|
+
const out = [];
|
|
240
|
+
const walk = (at) => {
|
|
241
|
+
for (const e of tree.list(at) ?? []) {
|
|
242
|
+
const path = joinPath(at, e.name);
|
|
243
|
+
if (e.type === "dir") {
|
|
244
|
+
if (!skippedDir(e.name))
|
|
245
|
+
walk(path);
|
|
246
|
+
}
|
|
247
|
+
else if (/\.ya?ml$/.test(e.name)) {
|
|
248
|
+
out.push(path);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
};
|
|
252
|
+
walk(dir);
|
|
253
|
+
return out;
|
|
254
|
+
}
|
|
255
|
+
function lines(text) {
|
|
256
|
+
return text.replace(/\r\n/g, "\n").split("\n");
|
|
257
|
+
}
|
|
258
|
+
function escapeRegExp(text) {
|
|
259
|
+
return text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
260
|
+
}
|
|
261
|
+
/** The line (from 1) of top-level key `key`, or 1. */
|
|
262
|
+
function keyLine(fileLines, key) {
|
|
263
|
+
const re = new RegExp(`^${escapeRegExp(key)}\\s*:`);
|
|
264
|
+
const i = fileLines.findIndex((l) => re.test(l));
|
|
265
|
+
return i < 0 ? 1 : i + 1;
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* The line of the first `name: <value>` entry after line `from`, or `from`
|
|
269
|
+
* itself. Sources, tables and columns are listed in file order, so
|
|
270
|
+
* searching on from the parent's line finds each one's own line. A file in
|
|
271
|
+
* flow style has no such lines, and its entries are reported at the parent.
|
|
272
|
+
*/
|
|
273
|
+
function nameLine(fileLines, value, from) {
|
|
274
|
+
return value === undefined ? from : valueLineOf(fileLines, "name", value, from);
|
|
275
|
+
}
|
|
276
|
+
/** The line of the first `<key>:` after line `from`, or `from`. */
|
|
277
|
+
function valueLine(fileLines, key, from) {
|
|
278
|
+
const re = new RegExp(`^\\s*(?:-\\s+)?${escapeRegExp(key)}\\s*:`);
|
|
279
|
+
for (let i = Math.max(from, 0); i < fileLines.length; i++)
|
|
280
|
+
if (re.test(fileLines[i]))
|
|
281
|
+
return i + 1;
|
|
282
|
+
return from;
|
|
283
|
+
}
|
|
284
|
+
function valueLineOf(fileLines, key, value, from) {
|
|
285
|
+
const re = new RegExp(`^\\s*(?:-\\s+)?${escapeRegExp(key)}\\s*:\\s*(["']?)${escapeRegExp(value)}\\1\\s*(?:#.*)?$`);
|
|
286
|
+
for (let i = Math.max(from, 0); i < fileLines.length; i++)
|
|
287
|
+
if (re.test(fileLines[i]))
|
|
288
|
+
return i + 1;
|
|
289
|
+
return from;
|
|
290
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"graph-cli.d.ts","sourceRoot":"","sources":["../../src/workspace/graph-cli.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAOH,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClE,OAAO,EAA0B,KAAK,SAAS,EAAE,MAAM,eAAe,CAAC;AACvE,OAAO,EAA+E,KAAK,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEnI,OAAO,EAA6E,KAAK,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9H,OAAO,EAAgF,KAAK,UAAU,EAAE,KAAK,SAAS,EAAE,KAAK,UAAU,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"graph-cli.d.ts","sourceRoot":"","sources":["../../src/workspace/graph-cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -34,6 +34,7 @@ import { openGraphCache, splitCached, storeReads, withoutUnits } from "./graph-c
|
|
|
34
34
|
import { readDeclaration, readerVersion, WORKSPACE_ERROR_CODES, WorkspaceReadError } from "./declaration.js";
|
|
35
35
|
import { describePlan, emitDocument, executePlan, memberStatus, planJson, planMembers } from "./member-commands.js";
|
|
36
36
|
import { loadKindRegistry } from "./kinds.js";
|
|
37
|
+
import { readKindLinks } from "./kind-link-readers.js";
|
|
37
38
|
import { prepareKindReaders } from "./kind-readers.js";
|
|
38
39
|
import { recordLinkRows } from "./record-assets.js";
|
|
39
40
|
import { RecordReadError } from "./records.js";
|
|
@@ -198,7 +199,8 @@ export async function workspaceGraph(query) {
|
|
|
198
199
|
member.stamp = split?.stamps.get(member.name) ?? null;
|
|
199
200
|
}
|
|
200
201
|
// Links (#2539) resolve against the declaration that was read, the revision's for --at, and the kinds installed now.
|
|
201
|
-
|
|
202
|
+
// A kind's link reader (#3932) reads the member's files in the tree read, as check does.
|
|
203
|
+
const graph = composeWorkspaceGraph({ name: declaration.name, root: located.root }, inputs, { declaration, kinds, read: readKindLinks(declaration, located.tree, kinds) });
|
|
202
204
|
// The box's factory and listing (#3146), from the declaration read, so --at gives them at that revision.
|
|
203
205
|
for (const member of graph.members)
|
|
204
206
|
member.box = graphBox(declaration.members.find((m) => m.name === member.name)?.box ?? null, located.tree, declaration.members);
|