ai-spector 0.2.0 → 0.2.2
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/README.md +1 -0
- package/dist/cli.js +16 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/graphify-update.d.ts +4 -0
- package/dist/commands/graphify-update.d.ts.map +1 -1
- package/dist/commands/graphify-update.js +64 -10
- package/dist/commands/graphify-update.js.map +1 -1
- package/dist/commands/index.d.ts.map +1 -1
- package/dist/commands/index.js +33 -1
- package/dist/commands/index.js.map +1 -1
- package/dist/graph/InMemoryGraph.d.ts.map +1 -1
- package/dist/graph/InMemoryGraph.js +4 -4
- package/dist/graph/InMemoryGraph.js.map +1 -1
- package/dist/graph/merge.d.ts.map +1 -1
- package/dist/graph/merge.js +13 -5
- package/dist/graph/merge.js.map +1 -1
- package/dist/graph/path-target-edges.d.ts +5 -0
- package/dist/graph/path-target-edges.d.ts.map +1 -0
- package/dist/graph/path-target-edges.js +9 -0
- package/dist/graph/path-target-edges.js.map +1 -0
- package/dist/graph/provenance.d.ts +20 -0
- package/dist/graph/provenance.d.ts.map +1 -0
- package/dist/graph/provenance.js +221 -0
- package/dist/graph/provenance.js.map +1 -0
- package/dist/graph/query.d.ts +1 -0
- package/dist/graph/query.d.ts.map +1 -1
- package/dist/graph/query.js +16 -3
- package/dist/graph/query.js.map +1 -1
- package/dist/graph/source-refs.d.ts +2 -0
- package/dist/graph/source-refs.d.ts.map +1 -0
- package/dist/graph/source-refs.js +30 -0
- package/dist/graph/source-refs.js.map +1 -0
- package/dist/graphify/graph-index.d.ts +28 -0
- package/dist/graphify/graph-index.d.ts.map +1 -0
- package/dist/graphify/graph-index.js +52 -0
- package/dist/graphify/graph-index.js.map +1 -0
- package/dist/graphify/sources.d.ts +26 -0
- package/dist/graphify/sources.d.ts.map +1 -1
- package/dist/graphify/sources.js +120 -2
- package/dist/graphify/sources.js.map +1 -1
- package/dist/visualize/html.d.ts.map +1 -1
- package/dist/visualize/html.js +82 -7
- package/dist/visualize/html.js.map +1 -1
- package/package.json +1 -1
- package/scaffold/.cursor/commands/_cli-failures.md +14 -6
- package/scaffold/.cursor/commands/index.md +3 -1
- package/schemas/rules.impact.json +2 -1
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { defaultGraphifyJsonPath, graphifyNodeTargetId, isGraphifyNodeTarget, loadGraphifyIndex, } from "../graphify/graph-index.js";
|
|
4
|
+
import { isKnowledgePayload, knowledgeHasDomainEntries } from "./knowledge.js";
|
|
5
|
+
import { mergePatch } from "./merge.js";
|
|
6
|
+
import { loadInMemoryGraph } from "./loadGraph.js";
|
|
7
|
+
import { pathExists, readJson, writeJson } from "../util/fs.js";
|
|
8
|
+
import { discoverMarkdownFiles } from "../index/docs-build.js";
|
|
9
|
+
import { indexDocsConfigPath } from "../index/docs-config.js";
|
|
10
|
+
import { extractSourceRefsFromMarkdown } from "./source-refs.js";
|
|
11
|
+
function collectKnowledgeRefs(item) {
|
|
12
|
+
const out = [];
|
|
13
|
+
const fields = ["derivedFrom", "sourceRefs", "sources", "sourceFiles", "source"];
|
|
14
|
+
for (const key of fields) {
|
|
15
|
+
const v = item[key];
|
|
16
|
+
if (typeof v === "string" && v.trim()) {
|
|
17
|
+
out.push(v.trim());
|
|
18
|
+
}
|
|
19
|
+
else if (Array.isArray(v)) {
|
|
20
|
+
for (const x of v) {
|
|
21
|
+
if (typeof x === "string" && x.trim()) {
|
|
22
|
+
out.push(x.trim());
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return out;
|
|
28
|
+
}
|
|
29
|
+
function resolveRefToTargets(ref, dataSourceRoot, graphify) {
|
|
30
|
+
const targets = new Set();
|
|
31
|
+
if (ref.startsWith("graphify:") && graphify) {
|
|
32
|
+
const id = ref.slice("graphify:".length);
|
|
33
|
+
if (graphify.nodes.some((n) => n.id === id)) {
|
|
34
|
+
targets.add(ref);
|
|
35
|
+
}
|
|
36
|
+
return [...targets];
|
|
37
|
+
}
|
|
38
|
+
const normalized = normalizeDataSourcePath(ref, dataSourceRoot);
|
|
39
|
+
if (normalized) {
|
|
40
|
+
targets.add(normalized);
|
|
41
|
+
const nodeIds = graphify?.byRepoPath.get(normalized);
|
|
42
|
+
if (nodeIds?.length === 1) {
|
|
43
|
+
targets.add(graphifyNodeTargetId(nodeIds[0]));
|
|
44
|
+
}
|
|
45
|
+
return [...targets];
|
|
46
|
+
}
|
|
47
|
+
if (graphify && !ref.includes("/")) {
|
|
48
|
+
const key = ref.trim().toLowerCase();
|
|
49
|
+
const byLabel = graphify.byLabel.get(key);
|
|
50
|
+
if (byLabel?.length === 1) {
|
|
51
|
+
targets.add(graphifyNodeTargetId(byLabel[0]));
|
|
52
|
+
}
|
|
53
|
+
const idMatch = graphify.nodes.find((n) => n.id === ref);
|
|
54
|
+
if (idMatch) {
|
|
55
|
+
targets.add(graphifyNodeTargetId(idMatch.id));
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return [...targets];
|
|
59
|
+
}
|
|
60
|
+
/** Normalize to repo-relative path under docs/data-source when possible. */
|
|
61
|
+
export function normalizeDataSourcePath(ref, dataSourceRoot) {
|
|
62
|
+
let s = ref
|
|
63
|
+
.trim()
|
|
64
|
+
.replace(/^[`'"]+|[`'"]+$/g, "")
|
|
65
|
+
.replace(/\\/g, "/");
|
|
66
|
+
if (!s || s.includes("://")) {
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
69
|
+
const root = dataSourceRoot.replace(/\\/g, "/").replace(/\/$/, "");
|
|
70
|
+
if (s.startsWith(root + "/")) {
|
|
71
|
+
return s;
|
|
72
|
+
}
|
|
73
|
+
if (s.startsWith("docs/data-source/")) {
|
|
74
|
+
return s.replace(/\/+/g, "/");
|
|
75
|
+
}
|
|
76
|
+
if (!s.includes("/") && /\.[a-z0-9]{1,8}$/i.test(s)) {
|
|
77
|
+
return `${root}/${s}`;
|
|
78
|
+
}
|
|
79
|
+
if (!s.startsWith("docs/") && !s.startsWith("/")) {
|
|
80
|
+
const candidate = `${root}/${s.replace(/^\.\//, "")}`;
|
|
81
|
+
if (candidate.startsWith(root)) {
|
|
82
|
+
return candidate;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return undefined;
|
|
86
|
+
}
|
|
87
|
+
function domainIdFromDetailContent(content, kind) {
|
|
88
|
+
if (kind === "useCase") {
|
|
89
|
+
const m = content.match(/\*\*Use Case ID:\*\*\s*(UC-\d+)/i);
|
|
90
|
+
return m?.[1] ? m[1].replace(/(UC-)(\d+)/i, (_, p, n) => `${p}${n.padStart(2, "0")}`) : null;
|
|
91
|
+
}
|
|
92
|
+
const m = content.match(/\*\*Feature ID:\*\*\s*(F-\d+)/i);
|
|
93
|
+
return m?.[1] ? m[1].replace(/(F-)(\d+)/i, (_, p, n) => `${p}${n.padStart(2, "0")}`) : null;
|
|
94
|
+
}
|
|
95
|
+
function buildProvenancePatch(domainRefs, dataSourceRoot, graphify, validDomainIds) {
|
|
96
|
+
const edges = [];
|
|
97
|
+
const edgeKeys = new Set();
|
|
98
|
+
for (const [domainId, refs] of domainRefs) {
|
|
99
|
+
if (!validDomainIds.has(domainId)) {
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
for (const ref of refs) {
|
|
103
|
+
for (const to of resolveRefToTargets(ref, dataSourceRoot, graphify)) {
|
|
104
|
+
if (isGraphifyNodeTarget(to) && !graphify) {
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
const key = `${domainId}|derivedFrom|${to}`;
|
|
108
|
+
if (edgeKeys.has(key)) {
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
edgeKeys.add(key);
|
|
112
|
+
edges.push({ type: "derivedFrom", from: domainId, to });
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return { version: 1, nodes: [], edges };
|
|
117
|
+
}
|
|
118
|
+
export async function collectDomainProvenanceRefs(opts) {
|
|
119
|
+
const domainRefs = new Map();
|
|
120
|
+
const addRef = (domainId, ref) => {
|
|
121
|
+
if (!domainId || !ref.trim()) {
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
const set = domainRefs.get(domainId) ?? new Set();
|
|
125
|
+
set.add(ref.trim());
|
|
126
|
+
domainRefs.set(domainId, set);
|
|
127
|
+
};
|
|
128
|
+
const knowledgePath = opts.knowledgePath ??
|
|
129
|
+
join(opts.projectRoot, ".ai-spector/.docflow/analysis/knowledge.json");
|
|
130
|
+
if (await pathExists(knowledgePath)) {
|
|
131
|
+
const raw = await readJson(knowledgePath);
|
|
132
|
+
if (isKnowledgePayload(raw) && knowledgeHasDomainEntries(raw)) {
|
|
133
|
+
const k = raw;
|
|
134
|
+
const lists = [
|
|
135
|
+
{ items: k.useCases },
|
|
136
|
+
{ items: k.features },
|
|
137
|
+
{ items: k.actors },
|
|
138
|
+
{ items: k.functionalRequirements },
|
|
139
|
+
{ items: k.nfrs },
|
|
140
|
+
{ items: k.entities },
|
|
141
|
+
];
|
|
142
|
+
for (const { items } of lists) {
|
|
143
|
+
for (const item of items ?? []) {
|
|
144
|
+
const id = String(item.id ?? "");
|
|
145
|
+
for (const ref of collectKnowledgeRefs(item)) {
|
|
146
|
+
addRef(id, ref);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
const configPath = indexDocsConfigPath(opts.projectRoot);
|
|
153
|
+
if (await pathExists(configPath)) {
|
|
154
|
+
const config = await readJson(configPath);
|
|
155
|
+
const entries = [];
|
|
156
|
+
for (const key of ["srs", "basicDesign"]) {
|
|
157
|
+
const source = config.sources[key];
|
|
158
|
+
if (!source?.root) {
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
const files = await discoverMarkdownFiles(opts.projectRoot, source.root, source.glob ?? "**/*.md");
|
|
162
|
+
for (const f of files) {
|
|
163
|
+
const content = await readFile(join(opts.projectRoot, f.relativePath), "utf8");
|
|
164
|
+
entries.push({ relativePath: f.relativePath, content });
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
for (const e of entries) {
|
|
168
|
+
const refs = extractSourceRefsFromMarkdown(e.content);
|
|
169
|
+
if (refs.length === 0) {
|
|
170
|
+
continue;
|
|
171
|
+
}
|
|
172
|
+
let domainId = null;
|
|
173
|
+
if (/\/03-use-cases\//i.test(e.relativePath) || /\/uc-\d+/i.test(e.relativePath)) {
|
|
174
|
+
domainId = domainIdFromDetailContent(e.content, "useCase");
|
|
175
|
+
}
|
|
176
|
+
else if (/\/04-system-features\/f-\d+/i.test(e.relativePath)) {
|
|
177
|
+
domainId = domainIdFromDetailContent(e.content, "feature");
|
|
178
|
+
}
|
|
179
|
+
if (!domainId) {
|
|
180
|
+
continue;
|
|
181
|
+
}
|
|
182
|
+
for (const ref of refs) {
|
|
183
|
+
addRef(domainId, ref);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
return domainRefs;
|
|
188
|
+
}
|
|
189
|
+
export async function runProvenanceLink(opts) {
|
|
190
|
+
const dataSourceRoot = opts.dataSourceRoot ?? "docs/data-source";
|
|
191
|
+
const graphifyPath = opts.graphifyJsonPath ?? defaultGraphifyJsonPath(opts.projectRoot);
|
|
192
|
+
const graphify = await loadGraphifyIndex(graphifyPath, dataSourceRoot);
|
|
193
|
+
const domainRefs = await collectDomainProvenanceRefs({
|
|
194
|
+
...opts,
|
|
195
|
+
dataSourceRoot,
|
|
196
|
+
});
|
|
197
|
+
const graph = await loadInMemoryGraph(opts.graphPath);
|
|
198
|
+
const validDomainIds = new Set([...graph.nodesById.values()]
|
|
199
|
+
.filter((n) => ["actor", "useCase", "feature", "requirement", "dataEntity"].includes(n.type))
|
|
200
|
+
.map((n) => n.id));
|
|
201
|
+
const patch = buildProvenancePatch(domainRefs, dataSourceRoot, graphify, validDomainIds);
|
|
202
|
+
if (patch.edges.length === 0) {
|
|
203
|
+
return {
|
|
204
|
+
merged: false,
|
|
205
|
+
detail: "No provenance evidence found (derivedFrom not added)",
|
|
206
|
+
edgesAdded: 0,
|
|
207
|
+
domainNodesLinked: 0,
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
const linkedDomains = new Set(patch.edges.map((e) => e.from));
|
|
211
|
+
const { stats } = mergePatch(graph, patch);
|
|
212
|
+
await writeJson(opts.graphPath, graph.toTraceabilityGraph());
|
|
213
|
+
const existing = [...linkedDomains].filter((id) => graph.nodesById.has(id));
|
|
214
|
+
return {
|
|
215
|
+
merged: true,
|
|
216
|
+
detail: `linked ${existing.length} domain node(s), +${stats.edgesAdded} derivedFrom edge(s)`,
|
|
217
|
+
edgesAdded: stats.edgesAdded,
|
|
218
|
+
domainNodesLinked: existing.length,
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
//# sourceMappingURL=provenance.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provenance.js","sourceRoot":"","sources":["../../src/graph/provenance.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EACL,uBAAuB,EACvB,oBAAoB,EACpB,oBAAoB,EACpB,iBAAiB,GAElB,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EAAE,kBAAkB,EAAE,yBAAyB,EAAE,MAAM,gBAAgB,CAAC;AAC/E,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAGnD,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAChE,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EAAE,mBAAmB,EAAwB,MAAM,yBAAyB,CAAC;AACpF,OAAO,EAAE,6BAA6B,EAAE,MAAM,kBAAkB,CAAC;AAiBjE,SAAS,oBAAoB,CAC3B,IAA6B;IAE7B,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,MAAM,MAAM,GAAG,CAAC,aAAa,EAAE,YAAY,EAAE,SAAS,EAAE,aAAa,EAAE,QAAQ,CAAC,CAAC;IACjF,KAAK,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;QACzB,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;QACpB,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;YACtC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QACrB,CAAC;aAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;YAC5B,KAAK,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;gBAClB,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;oBACtC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;gBACrB,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,mBAAmB,CAC1B,GAAW,EACX,cAAsB,EACtB,QAA8B;IAE9B,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAElC,IAAI,GAAG,CAAC,UAAU,CAAC,WAAW,CAAC,IAAI,QAAQ,EAAE,CAAC;QAC5C,MAAM,EAAE,GAAG,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QACzC,IAAI,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;YAC5C,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACnB,CAAC;QACD,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC;IACtB,CAAC;IAED,MAAM,UAAU,GAAG,uBAAuB,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;IAChE,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QACxB,MAAM,OAAO,GAAG,QAAQ,EAAE,UAAU,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QACrD,IAAI,OAAO,EAAE,MAAM,KAAK,CAAC,EAAE,CAAC;YAC1B,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC;QACjD,CAAC;QACD,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC;IACtB,CAAC;IAED,IAAI,QAAQ,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACnC,MAAM,GAAG,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QACrC,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC1C,IAAI,OAAO,EAAE,MAAM,KAAK,CAAC,EAAE,CAAC;YAC1B,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC;QACjD,CAAC;QACD,MAAM,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC;QACzD,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC;QAChD,CAAC;IACH,CAAC;IAED,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC;AACtB,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,uBAAuB,CACrC,GAAW,EACX,cAAsB;IAEtB,IAAI,CAAC,GAAG,GAAG;SACR,IAAI,EAAE;SACN,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC;SAC/B,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IACvB,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QAC5B,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,IAAI,GAAG,cAAc,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACnE,IAAI,CAAC,CAAC,UAAU,CAAC,IAAI,GAAG,GAAG,CAAC,EAAE,CAAC;QAC7B,OAAO,CAAC,CAAC;IACX,CAAC;IACD,IAAI,CAAC,CAAC,UAAU,CAAC,mBAAmB,CAAC,EAAE,CAAC;QACtC,OAAO,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAChC,CAAC;IACD,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,mBAAmB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QACpD,OAAO,GAAG,IAAI,IAAI,CAAC,EAAE,CAAC;IACxB,CAAC;IACD,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACjD,MAAM,SAAS,GAAG,GAAG,IAAI,IAAI,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,CAAC;QACtD,IAAI,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YAC/B,OAAO,SAAS,CAAC;QACnB,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,yBAAyB,CAChC,OAAe,EACf,IAA2B;IAE3B,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,MAAM,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,kCAAkC,CAAC,CAAC;QAC5D,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC/F,CAAC;IACD,MAAM,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,gCAAgC,CAAC,CAAC;IAC1D,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AAC9F,CAAC;AAED,SAAS,oBAAoB,CAC3B,UAAoC,EACpC,cAAsB,EACtB,QAA8B,EAC9B,cAA2B;IAE3B,MAAM,KAAK,GAAgB,EAAE,CAAC;IAC9B,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAC;IAEnC,KAAK,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,UAAU,EAAE,CAAC;QAC1C,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YAClC,SAAS;QACX,CAAC;QACD,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,KAAK,MAAM,EAAE,IAAI,mBAAmB,CAAC,GAAG,EAAE,cAAc,EAAE,QAAQ,CAAC,EAAE,CAAC;gBACpE,IAAI,oBAAoB,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;oBAC1C,SAAS;gBACX,CAAC;gBACD,MAAM,GAAG,GAAG,GAAG,QAAQ,gBAAgB,EAAE,EAAE,CAAC;gBAC5C,IAAI,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;oBACtB,SAAS;gBACX,CAAC;gBACD,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;gBAClB,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC;YAC1D,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC;AAC1C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAC/C,IAAwD;IAExD,MAAM,UAAU,GAAG,IAAI,GAAG,EAAuB,CAAC;IAClD,MAAM,MAAM,GAAG,CAAC,QAAgB,EAAE,GAAW,EAAE,EAAE;QAC/C,IAAI,CAAC,QAAQ,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC;YAC7B,OAAO;QACT,CAAC;QACD,MAAM,GAAG,GAAG,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,IAAI,GAAG,EAAU,CAAC;QAC1D,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;QACpB,UAAU,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;IAChC,CAAC,CAAC;IAEF,MAAM,aAAa,GACjB,IAAI,CAAC,aAAa;QAClB,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,8CAA8C,CAAC,CAAC;IACzE,IAAI,MAAM,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;QACpC,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAU,aAAa,CAAC,CAAC;QACnD,IAAI,kBAAkB,CAAC,GAAG,CAAC,IAAI,yBAAyB,CAAC,GAAwB,CAAC,EAAE,CAAC;YACnF,MAAM,CAAC,GAAG,GAAwB,CAAC;YACnC,MAAM,KAAK,GAAsD;gBAC/D,EAAE,KAAK,EAAE,CAAC,CAAC,QAAsD,EAAE;gBACnE,EAAE,KAAK,EAAE,CAAC,CAAC,QAAsD,EAAE;gBACnE,EAAE,KAAK,EAAE,CAAC,CAAC,MAAoD,EAAE;gBACjE,EAAE,KAAK,EAAE,CAAC,CAAC,sBAAoE,EAAE;gBACjF,EAAE,KAAK,EAAE,CAAC,CAAC,IAAkD,EAAE;gBAC/D,EAAE,KAAK,EAAE,CAAC,CAAC,QAAsD,EAAE;aACpE,CAAC;YACF,KAAK,MAAM,EAAE,KAAK,EAAE,IAAI,KAAK,EAAE,CAAC;gBAC9B,KAAK,MAAM,IAAI,IAAI,KAAK,IAAI,EAAE,EAAE,CAAC;oBAC/B,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;oBACjC,KAAK,MAAM,GAAG,IAAI,oBAAoB,CAAC,IAAI,CAAC,EAAE,CAAC;wBAC7C,MAAM,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;oBAClB,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,UAAU,GAAG,mBAAmB,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACzD,IAAI,MAAM,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QACjC,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAkB,UAAU,CAAC,CAAC;QAC3D,MAAM,OAAO,GAAqD,EAAE,CAAC;QACrE,KAAK,MAAM,GAAG,IAAI,CAAC,KAAK,EAAE,aAAa,CAAU,EAAE,CAAC;YAClD,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YACnC,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC;gBAClB,SAAS;YACX,CAAC;YACD,MAAM,KAAK,GAAG,MAAM,qBAAqB,CACvC,IAAI,CAAC,WAAW,EAChB,MAAM,CAAC,IAAI,EACX,MAAM,CAAC,IAAI,IAAI,SAAS,CACzB,CAAC;YACF,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;gBACtB,MAAM,OAAO,GAAG,MAAM,QAAQ,CAC5B,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,YAAY,CAAC,EACtC,MAAM,CACP,CAAC;gBACF,OAAO,CAAC,IAAI,CAAC,EAAE,YAAY,EAAE,CAAC,CAAC,YAAY,EAAE,OAAO,EAAE,CAAC,CAAC;YAC1D,CAAC;QACH,CAAC;QAED,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;YACxB,MAAM,IAAI,GAAG,6BAA6B,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;YACtD,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACtB,SAAS;YACX,CAAC;YACD,IAAI,QAAQ,GAAkB,IAAI,CAAC;YACnC,IAAI,mBAAmB,CAAC,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC;gBACjF,QAAQ,GAAG,yBAAyB,CAAC,CAAC,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;YAC7D,CAAC;iBAAM,IAAI,8BAA8B,CAAC,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC;gBAC/D,QAAQ,GAAG,yBAAyB,CAAC,CAAC,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;YAC7D,CAAC;YACD,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,SAAS;YACX,CAAC;YACD,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;gBACvB,MAAM,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;YACxB,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,IAA2B;IAE3B,MAAM,cAAc,GAAG,IAAI,CAAC,cAAc,IAAI,kBAAkB,CAAC;IACjE,MAAM,YAAY,GAChB,IAAI,CAAC,gBAAgB,IAAI,uBAAuB,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACrE,MAAM,QAAQ,GAAG,MAAM,iBAAiB,CAAC,YAAY,EAAE,cAAc,CAAC,CAAC;IAEvE,MAAM,UAAU,GAAG,MAAM,2BAA2B,CAAC;QACnD,GAAG,IAAI;QACP,cAAc;KACf,CAAC,CAAC;IAEH,MAAM,KAAK,GAAG,MAAM,iBAAiB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACtD,MAAM,cAAc,GAAG,IAAI,GAAG,CAC5B,CAAC,GAAG,KAAK,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC;SAC1B,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CACZ,CAAC,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,aAAa,EAAE,YAAY,CAAC,CAAC,QAAQ,CACnE,CAAC,CAAC,IAAI,CACP,CACF;SACA,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CACpB,CAAC;IAEF,MAAM,KAAK,GAAG,oBAAoB,CAChC,UAAU,EACV,cAAc,EACd,QAAQ,EACR,cAAc,CACf,CAAC;IACF,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7B,OAAO;YACL,MAAM,EAAE,KAAK;YACb,MAAM,EAAE,sDAAsD;YAC9D,UAAU,EAAE,CAAC;YACb,iBAAiB,EAAE,CAAC;SACrB,CAAC;IACJ,CAAC;IAED,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAC9D,MAAM,EAAE,KAAK,EAAE,GAAG,UAAU,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IAC3C,MAAM,SAAS,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,mBAAmB,EAAE,CAAC,CAAC;IAE7D,MAAM,QAAQ,GAAG,CAAC,GAAG,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IAC5E,OAAO;QACL,MAAM,EAAE,IAAI;QACZ,MAAM,EAAE,UAAU,QAAQ,CAAC,MAAM,qBAAqB,KAAK,CAAC,UAAU,sBAAsB;QAC5F,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,iBAAiB,EAAE,QAAQ,CAAC,MAAM;KACnC,CAAC;AACJ,CAAC"}
|
package/dist/graph/query.d.ts
CHANGED
|
@@ -14,5 +14,6 @@ export interface GraphQueryResult {
|
|
|
14
14
|
}
|
|
15
15
|
export declare function resolveDocumentForNode(g: InMemoryGraph, nodeId: string): GraphNode | undefined;
|
|
16
16
|
export declare function projectionPathForNode(g: InMemoryGraph, nodeId: string): string | undefined;
|
|
17
|
+
export declare function dataSourcePathsForNode(g: InMemoryGraph, nodeId: string): string[];
|
|
17
18
|
export declare function querySubgraph(g: InMemoryGraph, seedId: string, opts?: QueryOptions): GraphQueryResult;
|
|
18
19
|
//# sourceMappingURL=query.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../src/graph/query.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,MAAM,WAAW,YAAY;IAC3B,SAAS,CAAC,EAAE,KAAK,GAAG,IAAI,GAAG,MAAM,CAAC;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAC;IACvB,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B;
|
|
1
|
+
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../src/graph/query.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,MAAM,WAAW,YAAY;IAC3B,SAAS,CAAC,EAAE,KAAK,GAAG,IAAI,GAAG,MAAM,CAAC;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAC;IACvB,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B;AAgBD,wBAAgB,sBAAsB,CACpC,CAAC,EAAE,aAAa,EAChB,MAAM,EAAE,MAAM,GACb,SAAS,GAAG,SAAS,CAgCvB;AAED,wBAAgB,qBAAqB,CACnC,CAAC,EAAE,aAAa,EAChB,MAAM,EAAE,MAAM,GACb,MAAM,GAAG,SAAS,CAiCpB;AAED,wBAAgB,sBAAsB,CACpC,CAAC,EAAE,aAAa,EAChB,MAAM,EAAE,MAAM,GACb,MAAM,EAAE,CAQV;AAED,wBAAgB,aAAa,CAC3B,CAAC,EAAE,aAAa,EAChB,MAAM,EAAE,MAAM,EACd,IAAI,GAAE,YAAiB,GACtB,gBAAgB,CAkElB"}
|
package/dist/graph/query.js
CHANGED
|
@@ -9,6 +9,7 @@ const DEFAULT_GENERATE_EDGES = [
|
|
|
9
9
|
"dependsOn",
|
|
10
10
|
"references",
|
|
11
11
|
"rendersTo",
|
|
12
|
+
"derivedFrom",
|
|
12
13
|
];
|
|
13
14
|
export function resolveDocumentForNode(g, nodeId) {
|
|
14
15
|
const node = g.nodesById.get(nodeId);
|
|
@@ -77,6 +78,15 @@ export function projectionPathForNode(g, nodeId) {
|
|
|
77
78
|
}
|
|
78
79
|
return undefined;
|
|
79
80
|
}
|
|
81
|
+
export function dataSourcePathsForNode(g, nodeId) {
|
|
82
|
+
const paths = [];
|
|
83
|
+
for (const e of g.outEdges.get(nodeId) ?? []) {
|
|
84
|
+
if (e.type === "derivedFrom" && !e.to.startsWith("graphify:")) {
|
|
85
|
+
paths.push(e.to);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return paths;
|
|
89
|
+
}
|
|
80
90
|
export function querySubgraph(g, seedId, opts = {}) {
|
|
81
91
|
if (!g.nodesById.has(seedId)) {
|
|
82
92
|
throw new Error(`Unknown node id: ${seedId}`);
|
|
@@ -123,9 +133,12 @@ export function querySubgraph(g, seedId, opts = {}) {
|
|
|
123
133
|
.filter((n) => !nodeTypeFilter || nodeTypeFilter.has(n.type));
|
|
124
134
|
const edges = [...visitedEdges.values()];
|
|
125
135
|
const projectionPaths = [
|
|
126
|
-
...new Set([
|
|
127
|
-
|
|
128
|
-
|
|
136
|
+
...new Set([
|
|
137
|
+
...[...visitedNodes]
|
|
138
|
+
.map((id) => projectionPathForNode(g, id))
|
|
139
|
+
.filter((p) => Boolean(p && !p.includes("{"))),
|
|
140
|
+
...[...visitedNodes].flatMap((id) => dataSourcePathsForNode(g, id)),
|
|
141
|
+
]),
|
|
129
142
|
];
|
|
130
143
|
return { seed: seedId, nodes, edges, projectionPaths };
|
|
131
144
|
}
|
package/dist/graph/query.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query.js","sourceRoot":"","sources":["../../src/graph/query.ts"],"names":[],"mappings":"AAiBA,MAAM,sBAAsB,GAAe;IACzC,QAAQ;IACR,UAAU;IACV,SAAS;IACT,UAAU;IACV,WAAW;IACX,aAAa;IACb,WAAW;IACX,WAAW;IACX,YAAY;IACZ,WAAW;
|
|
1
|
+
{"version":3,"file":"query.js","sourceRoot":"","sources":["../../src/graph/query.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"source-refs.d.ts","sourceRoot":"","sources":["../../src/graph/source-refs.ts"],"names":[],"mappings":"AASA,wBAAgB,6BAA6B,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CA4BvE"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/** Repo-relative paths under docs/data-source mentioned in markdown. */
|
|
2
|
+
const DATA_SOURCE_PATH_RE = /(?:^|[\s`(\[])(docs\/data-source\/[^\s`)\]>]+)/gi;
|
|
3
|
+
const SOURCE_LINE_RE = /^\s*(?:\*\*)?(?:Source|Data\s+source|Provenance|Origin)(?:\*\*)?\s*:\s*(.+)$/gim;
|
|
4
|
+
const BACKTICK_PATH_RE = /`([^`]+\.(?:md|ts|tsx|js|py|go|rs|json|yaml|yml))`/gi;
|
|
5
|
+
export function extractSourceRefsFromMarkdown(content) {
|
|
6
|
+
const refs = new Set();
|
|
7
|
+
for (const m of content.matchAll(DATA_SOURCE_PATH_RE)) {
|
|
8
|
+
const p = (m[1] ?? m[0]).replace(/^[(\[`\s]+/, "").trim();
|
|
9
|
+
if (p.startsWith("docs/data-source/")) {
|
|
10
|
+
refs.add(p);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
for (const m of content.matchAll(SOURCE_LINE_RE)) {
|
|
14
|
+
const line = m[1].trim();
|
|
15
|
+
for (const part of line.split(/[,;]/)) {
|
|
16
|
+
const t = part.trim().replace(/^[`'"]+|[`'"]+$/g, "");
|
|
17
|
+
if (t) {
|
|
18
|
+
refs.add(t);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
for (const m of content.matchAll(BACKTICK_PATH_RE)) {
|
|
23
|
+
const t = m[1].trim();
|
|
24
|
+
if (t.includes("data-source") || t.startsWith("docs/")) {
|
|
25
|
+
refs.add(t);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return [...refs];
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=source-refs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"source-refs.js","sourceRoot":"","sources":["../../src/graph/source-refs.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,MAAM,mBAAmB,GACvB,kDAAkD,CAAC;AAErD,MAAM,cAAc,GAClB,iFAAiF,CAAC;AAEpF,MAAM,gBAAgB,GAAG,sDAAsD,CAAC;AAEhF,MAAM,UAAU,6BAA6B,CAAC,OAAe;IAC3D,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAE/B,KAAK,MAAM,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAAC;QACtD,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QAC1D,IAAI,CAAC,CAAC,UAAU,CAAC,mBAAmB,CAAC,EAAE,CAAC;YACtC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACd,CAAC;IACH,CAAC;IAED,KAAK,MAAM,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC;QACjD,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,CAAE,CAAC,IAAI,EAAE,CAAC;QAC1B,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;YACtC,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC,CAAC;YACtD,IAAI,CAAC,EAAE,CAAC;gBACN,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YACd,CAAC;QACH,CAAC;IACH,CAAC;IAED,KAAK,MAAM,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC;QACnD,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAE,CAAC,IAAI,EAAE,CAAC;QACvB,IAAI,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YACvD,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACd,CAAC;IACH,CAAC;IAED,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC;AACnB,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export interface GraphifyGraphNode {
|
|
2
|
+
id: string;
|
|
3
|
+
label?: string;
|
|
4
|
+
norm_label?: string;
|
|
5
|
+
source_file?: string;
|
|
6
|
+
file_type?: string;
|
|
7
|
+
community?: number;
|
|
8
|
+
}
|
|
9
|
+
export interface GraphifyGraphFile {
|
|
10
|
+
nodes: GraphifyGraphNode[];
|
|
11
|
+
links?: Array<{
|
|
12
|
+
source: string;
|
|
13
|
+
target: string;
|
|
14
|
+
}>;
|
|
15
|
+
}
|
|
16
|
+
export interface GraphifyIndex {
|
|
17
|
+
nodes: GraphifyGraphNode[];
|
|
18
|
+
/** Repo-relative path (under data-source root) → graphify node ids in that file */
|
|
19
|
+
byRepoPath: Map<string, string[]>;
|
|
20
|
+
/** Lowercased label / norm_label → graphify node ids */
|
|
21
|
+
byLabel: Map<string, string[]>;
|
|
22
|
+
}
|
|
23
|
+
export declare function graphifyNodeTargetId(nodeId: string): string;
|
|
24
|
+
export declare function isGraphifyNodeTarget(to: string): boolean;
|
|
25
|
+
export declare function repoPathForGraphifyNode(node: GraphifyGraphNode, dataSourceRoot: string): string | undefined;
|
|
26
|
+
export declare function loadGraphifyIndex(graphJsonPath: string, dataSourceRoot: string): Promise<GraphifyIndex | null>;
|
|
27
|
+
export declare function defaultGraphifyJsonPath(projectRoot: string): string;
|
|
28
|
+
//# sourceMappingURL=graph-index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph-index.d.ts","sourceRoot":"","sources":["../../src/graphify/graph-index.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,iBAAiB,EAAE,CAAC;IAC3B,KAAK,CAAC,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACnD;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,iBAAiB,EAAE,CAAC;IAC3B,mFAAmF;IACnF,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAClC,wDAAwD;IACxD,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;CAChC;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAExD;AAED,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,iBAAiB,EACvB,cAAc,EAAE,MAAM,GACrB,MAAM,GAAG,SAAS,CAUpB;AAED,wBAAsB,iBAAiB,CACrC,aAAa,EAAE,MAAM,EACrB,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CA8B/B;AAED,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAKnE"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { pathExists } from "../util/fs.js";
|
|
4
|
+
export function graphifyNodeTargetId(nodeId) {
|
|
5
|
+
return `graphify:${nodeId}`;
|
|
6
|
+
}
|
|
7
|
+
export function isGraphifyNodeTarget(to) {
|
|
8
|
+
return to.startsWith("graphify:");
|
|
9
|
+
}
|
|
10
|
+
export function repoPathForGraphifyNode(node, dataSourceRoot) {
|
|
11
|
+
const sf = node.source_file?.replace(/\\/g, "/").trim();
|
|
12
|
+
if (!sf) {
|
|
13
|
+
return undefined;
|
|
14
|
+
}
|
|
15
|
+
const root = dataSourceRoot.replace(/\\/g, "/").replace(/\/$/, "");
|
|
16
|
+
if (sf.startsWith("docs/")) {
|
|
17
|
+
return sf;
|
|
18
|
+
}
|
|
19
|
+
return `${root}/${sf.replace(/^\.\//, "")}`;
|
|
20
|
+
}
|
|
21
|
+
export async function loadGraphifyIndex(graphJsonPath, dataSourceRoot) {
|
|
22
|
+
if (!(await pathExists(graphJsonPath))) {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
const raw = JSON.parse(await readFile(graphJsonPath, "utf8"));
|
|
26
|
+
const nodes = raw.nodes ?? [];
|
|
27
|
+
const byRepoPath = new Map();
|
|
28
|
+
const byLabel = new Map();
|
|
29
|
+
const addToMap = (map, key, id) => {
|
|
30
|
+
const list = map.get(key) ?? [];
|
|
31
|
+
if (!list.includes(id)) {
|
|
32
|
+
list.push(id);
|
|
33
|
+
map.set(key, list);
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
for (const node of nodes) {
|
|
37
|
+
const path = repoPathForGraphifyNode(node, dataSourceRoot);
|
|
38
|
+
if (path) {
|
|
39
|
+
addToMap(byRepoPath, path, node.id);
|
|
40
|
+
}
|
|
41
|
+
for (const label of [node.label, node.norm_label]) {
|
|
42
|
+
if (label?.trim()) {
|
|
43
|
+
addToMap(byLabel, label.trim().toLowerCase(), node.id);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return { nodes, byRepoPath, byLabel };
|
|
48
|
+
}
|
|
49
|
+
export function defaultGraphifyJsonPath(projectRoot) {
|
|
50
|
+
return join(projectRoot, ".ai-spector/.docflow/graph/graphify-out/graph.json");
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=graph-index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph-index.js","sourceRoot":"","sources":["../../src/graphify/graph-index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extensions Graphify `update` / `watch` index via AST (graphify.detect.CODE_EXTENSIONS).
|
|
3
|
+
* Markdown-only doc trees (docs/srs, docs/basic-design) have no matches → skip before spawn.
|
|
4
|
+
*/
|
|
5
|
+
export declare const GRAPHIFY_CODE_EXTENSIONS: Set<string>;
|
|
6
|
+
export type GraphifySourceSkipReason = "empty" | "no-code-files";
|
|
1
7
|
export interface SourceFileFingerprint {
|
|
2
8
|
relativePath: string;
|
|
3
9
|
contentHash: string;
|
|
@@ -14,6 +20,26 @@ export interface GraphifySourcesConfig {
|
|
|
14
20
|
include?: string[];
|
|
15
21
|
docSources?: string[];
|
|
16
22
|
}
|
|
23
|
+
/** Central graphify-out under project root (absolute path for GRAPHIFY_OUT). */
|
|
24
|
+
export declare function resolveGraphifyOutputPath(projectRoot: string, outputPathRel?: string): string;
|
|
25
|
+
/** True when the source dir exists but has no files to fingerprint (empty tree). */
|
|
26
|
+
export declare function isGraphifySourceEmpty(projectRoot: string, sourceRel: string): Promise<boolean>;
|
|
27
|
+
/** True when Graphify `update` would find no AST-indexable code files under the source. */
|
|
28
|
+
export declare function hasGraphifyCodeFiles(projectRoot: string, sourceRel: string): Promise<boolean>;
|
|
29
|
+
/**
|
|
30
|
+
* Why a source should not run `graphify update` (empty dir or markdown/docs only).
|
|
31
|
+
* Returns null when the path is missing, not a directory, or has code files to index.
|
|
32
|
+
*/
|
|
33
|
+
export declare function getGraphifySourceSkipReason(projectRoot: string, sourceRel: string): Promise<GraphifySourceSkipReason | null>;
|
|
34
|
+
/** Pre-check before spawning Graphify CLI (empty tree or no code extensions). */
|
|
35
|
+
export declare function isGraphifySourceSkippable(projectRoot: string, sourceRel: string): Promise<{
|
|
36
|
+
skip: true;
|
|
37
|
+
reason: GraphifySourceSkipReason;
|
|
38
|
+
} | {
|
|
39
|
+
skip: false;
|
|
40
|
+
}>;
|
|
41
|
+
/** Graphify watch/update exit 1 when the tree has nothing to rebuild. */
|
|
42
|
+
export declare function isGraphifyNoCodeFilesOutput(stdout: string, stderr: string, exitCode: number): boolean;
|
|
17
43
|
export declare function resolveGraphifySources(config: GraphifySourcesConfig): GraphifySourceSpec[];
|
|
18
44
|
export declare function computeSourceContentHash(projectRoot: string, sourceRel: string): Promise<string | undefined>;
|
|
19
45
|
export declare function filterSourcesByHashChange(projectRoot: string, specs: GraphifySourceSpec[], storedHashes: Record<string, string> | undefined, force: boolean): Promise<{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sources.d.ts","sourceRoot":"","sources":["../../src/graphify/sources.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,qBAAqB;IACpC,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,wBAAsB,0BAA0B,CAC9C,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,qBAAqB,EAAE,CAAC,CAiClC;AAED,MAAM,WAAW,kBAAkB;IACjC,wCAAwC;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,0CAA0C;IAC1C,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,qBAAqB;IACpC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,qBAAqB,GAC5B,kBAAkB,EAAE,CAwBtB;AAED,wBAAsB,wBAAwB,CAC5C,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAW7B;AAED,wBAAsB,yBAAyB,CAC7C,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,kBAAkB,EAAE,EAC3B,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,EAChD,KAAK,EAAE,OAAO,GACb,OAAO,CAAC;IAAE,KAAK,EAAE,kBAAkB,EAAE,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,CAAC,CAgB1E"}
|
|
1
|
+
{"version":3,"file":"sources.d.ts","sourceRoot":"","sources":["../../src/graphify/sources.ts"],"names":[],"mappings":"AAOA;;;GAGG;AACH,eAAO,MAAM,wBAAwB,aAkEnC,CAAC;AAEH,MAAM,MAAM,wBAAwB,GAAG,OAAO,GAAG,eAAe,CAAC;AAEjE,MAAM,WAAW,qBAAqB;IACpC,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,wBAAsB,0BAA0B,CAC9C,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,qBAAqB,EAAE,CAAC,CAiClC;AAED,MAAM,WAAW,kBAAkB;IACjC,wCAAwC;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,0CAA0C;IAC1C,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,qBAAqB;IACpC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,gFAAgF;AAChF,wBAAgB,yBAAyB,CACvC,WAAW,EAAE,MAAM,EACnB,aAAa,CAAC,EAAE,MAAM,GACrB,MAAM,CAIR;AAED,oFAAoF;AACpF,wBAAsB,qBAAqB,CACzC,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,OAAO,CAAC,CAElB;AAED,2FAA2F;AAC3F,wBAAsB,oBAAoB,CACxC,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,OAAO,CAAC,CAKlB;AAED;;;GAGG;AACH,wBAAsB,2BAA2B,CAC/C,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,wBAAwB,GAAG,IAAI,CAAC,CAiB1C;AAED,iFAAiF;AACjF,wBAAsB,yBAAyB,CAC7C,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,wBAAwB,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,KAAK,CAAA;CAAE,CAAC,CAM7E;AAID,yEAAyE;AACzE,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GACf,OAAO,CAET;AAED,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,qBAAqB,GAC5B,kBAAkB,EAAE,CAwBtB;AAED,wBAAsB,wBAAwB,CAC5C,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAW7B;AAED,wBAAsB,yBAAyB,CAC7C,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,kBAAkB,EAAE,EAC3B,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,EAChD,KAAK,EAAE,OAAO,GACb,OAAO,CAAC;IAAE,KAAK,EAAE,kBAAkB,EAAE,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,CAAC,CAgB1E"}
|
package/dist/graphify/sources.js
CHANGED
|
@@ -1,8 +1,79 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
|
-
import { readdir, readFile } from "node:fs/promises";
|
|
3
|
-
import { join, relative, resolve } from "node:path";
|
|
2
|
+
import { readdir, readFile, stat } from "node:fs/promises";
|
|
3
|
+
import { extname, join, relative, resolve } from "node:path";
|
|
4
4
|
import { pathExists } from "../util/fs.js";
|
|
5
5
|
const SKIP_DIRS = new Set(["node_modules", ".git", "graphify-out", ".ai-spector"]);
|
|
6
|
+
/**
|
|
7
|
+
* Extensions Graphify `update` / `watch` index via AST (graphify.detect.CODE_EXTENSIONS).
|
|
8
|
+
* Markdown-only doc trees (docs/srs, docs/basic-design) have no matches → skip before spawn.
|
|
9
|
+
*/
|
|
10
|
+
export const GRAPHIFY_CODE_EXTENSIONS = new Set([
|
|
11
|
+
".py",
|
|
12
|
+
".ts",
|
|
13
|
+
".js",
|
|
14
|
+
".jsx",
|
|
15
|
+
".tsx",
|
|
16
|
+
".mjs",
|
|
17
|
+
".ejs",
|
|
18
|
+
".go",
|
|
19
|
+
".rs",
|
|
20
|
+
".java",
|
|
21
|
+
".groovy",
|
|
22
|
+
".gradle",
|
|
23
|
+
".cpp",
|
|
24
|
+
".cc",
|
|
25
|
+
".cxx",
|
|
26
|
+
".c",
|
|
27
|
+
".h",
|
|
28
|
+
".hpp",
|
|
29
|
+
".rb",
|
|
30
|
+
".swift",
|
|
31
|
+
".kt",
|
|
32
|
+
".kts",
|
|
33
|
+
".cs",
|
|
34
|
+
".scala",
|
|
35
|
+
".php",
|
|
36
|
+
".lua",
|
|
37
|
+
".luau",
|
|
38
|
+
".toc",
|
|
39
|
+
".zig",
|
|
40
|
+
".ps1",
|
|
41
|
+
".ex",
|
|
42
|
+
".exs",
|
|
43
|
+
".m",
|
|
44
|
+
".mm",
|
|
45
|
+
".jl",
|
|
46
|
+
".vue",
|
|
47
|
+
".svelte",
|
|
48
|
+
".astro",
|
|
49
|
+
".dart",
|
|
50
|
+
".v",
|
|
51
|
+
".sv",
|
|
52
|
+
".sql",
|
|
53
|
+
".r",
|
|
54
|
+
".f",
|
|
55
|
+
".F",
|
|
56
|
+
".f90",
|
|
57
|
+
".F90",
|
|
58
|
+
".f95",
|
|
59
|
+
".F95",
|
|
60
|
+
".f03",
|
|
61
|
+
".F03",
|
|
62
|
+
".f08",
|
|
63
|
+
".F08",
|
|
64
|
+
".pas",
|
|
65
|
+
".pp",
|
|
66
|
+
".dpr",
|
|
67
|
+
".dpk",
|
|
68
|
+
".lpr",
|
|
69
|
+
".inc",
|
|
70
|
+
".dfm",
|
|
71
|
+
".lfm",
|
|
72
|
+
".lpk",
|
|
73
|
+
".sh",
|
|
74
|
+
".bash",
|
|
75
|
+
".json",
|
|
76
|
+
]);
|
|
6
77
|
export async function discoverSourceFingerprints(projectRoot, sourceRoot) {
|
|
7
78
|
const rootAbs = resolve(projectRoot, sourceRoot);
|
|
8
79
|
const files = [];
|
|
@@ -36,6 +107,53 @@ export async function discoverSourceFingerprints(projectRoot, sourceRoot) {
|
|
|
36
107
|
files.sort((a, b) => a.relativePath.localeCompare(b.relativePath));
|
|
37
108
|
return files;
|
|
38
109
|
}
|
|
110
|
+
/** Central graphify-out under project root (absolute path for GRAPHIFY_OUT). */
|
|
111
|
+
export function resolveGraphifyOutputPath(projectRoot, outputPathRel) {
|
|
112
|
+
const rel = outputPathRel ?? ".ai-spector/.docflow/graph/graphify-out";
|
|
113
|
+
return resolve(projectRoot, rel);
|
|
114
|
+
}
|
|
115
|
+
/** True when the source dir exists but has no files to fingerprint (empty tree). */
|
|
116
|
+
export async function isGraphifySourceEmpty(projectRoot, sourceRel) {
|
|
117
|
+
return (await getGraphifySourceSkipReason(projectRoot, sourceRel)) === "empty";
|
|
118
|
+
}
|
|
119
|
+
/** True when Graphify `update` would find no AST-indexable code files under the source. */
|
|
120
|
+
export async function hasGraphifyCodeFiles(projectRoot, sourceRel) {
|
|
121
|
+
const files = await discoverSourceFingerprints(projectRoot, sourceRel);
|
|
122
|
+
return files.some((f) => GRAPHIFY_CODE_EXTENSIONS.has(extname(f.relativePath).toLowerCase()));
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Why a source should not run `graphify update` (empty dir or markdown/docs only).
|
|
126
|
+
* Returns null when the path is missing, not a directory, or has code files to index.
|
|
127
|
+
*/
|
|
128
|
+
export async function getGraphifySourceSkipReason(projectRoot, sourceRel) {
|
|
129
|
+
const abs = resolve(projectRoot, sourceRel);
|
|
130
|
+
if (!(await pathExists(abs))) {
|
|
131
|
+
return null;
|
|
132
|
+
}
|
|
133
|
+
const st = await stat(abs).catch(() => null);
|
|
134
|
+
if (!st?.isDirectory()) {
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
const files = await discoverSourceFingerprints(projectRoot, sourceRel);
|
|
138
|
+
if (files.length === 0) {
|
|
139
|
+
return "empty";
|
|
140
|
+
}
|
|
141
|
+
const hasCode = files.some((f) => GRAPHIFY_CODE_EXTENSIONS.has(extname(f.relativePath).toLowerCase()));
|
|
142
|
+
return hasCode ? null : "no-code-files";
|
|
143
|
+
}
|
|
144
|
+
/** Pre-check before spawning Graphify CLI (empty tree or no code extensions). */
|
|
145
|
+
export async function isGraphifySourceSkippable(projectRoot, sourceRel) {
|
|
146
|
+
const reason = await getGraphifySourceSkipReason(projectRoot, sourceRel);
|
|
147
|
+
if (reason) {
|
|
148
|
+
return { skip: true, reason };
|
|
149
|
+
}
|
|
150
|
+
return { skip: false };
|
|
151
|
+
}
|
|
152
|
+
const GRAPHIFY_NO_CODE_FILES_RE = /no code files found/i;
|
|
153
|
+
/** Graphify watch/update exit 1 when the tree has nothing to rebuild. */
|
|
154
|
+
export function isGraphifyNoCodeFilesOutput(stdout, stderr, exitCode) {
|
|
155
|
+
return exitCode !== 0 && GRAPHIFY_NO_CODE_FILES_RE.test(`${stdout}\n${stderr}`);
|
|
156
|
+
}
|
|
39
157
|
export function resolveGraphifySources(config) {
|
|
40
158
|
const seen = new Set();
|
|
41
159
|
const out = [];
|