dsh-gitnexus-plus 0.1.2 → 0.1.4

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.
Files changed (72) hide show
  1. package/README-CN.md +189 -0
  2. package/README.md +219 -597
  3. package/lib/bin/graph-helper.d.ts +21 -0
  4. package/lib/bin/graph-helper.d.ts.map +1 -0
  5. package/lib/bin/graph-helper.js +71 -0
  6. package/lib/bin/graph-helper.js.map +1 -0
  7. package/lib/client.js +4107 -2029
  8. package/lib/gitnexus/analyze.d.ts +48 -8
  9. package/lib/gitnexus/analyze.d.ts.map +1 -1
  10. package/lib/gitnexus/analyze.js +376 -75
  11. package/lib/gitnexus/analyze.js.map +1 -1
  12. package/lib/gitnexus/commands.d.ts +8 -1
  13. package/lib/gitnexus/commands.d.ts.map +1 -1
  14. package/lib/gitnexus/commands.js +19 -0
  15. package/lib/gitnexus/commands.js.map +1 -1
  16. package/lib/gitnexus/coverage.d.ts +16 -0
  17. package/lib/gitnexus/coverage.d.ts.map +1 -1
  18. package/lib/gitnexus/coverage.js +58 -1
  19. package/lib/gitnexus/coverage.js.map +1 -1
  20. package/lib/gitnexus/delta.d.ts +144 -0
  21. package/lib/gitnexus/delta.d.ts.map +1 -0
  22. package/lib/gitnexus/delta.js +347 -0
  23. package/lib/gitnexus/delta.js.map +1 -0
  24. package/lib/gitnexus/git-activity.d.ts +77 -0
  25. package/lib/gitnexus/git-activity.d.ts.map +1 -1
  26. package/lib/gitnexus/git-activity.js +327 -8
  27. package/lib/gitnexus/git-activity.js.map +1 -1
  28. package/lib/gitnexus/graph.d.ts +126 -0
  29. package/lib/gitnexus/graph.d.ts.map +1 -0
  30. package/lib/gitnexus/graph.js +472 -0
  31. package/lib/gitnexus/graph.js.map +1 -0
  32. package/lib/gitnexus/root.d.ts +0 -3
  33. package/lib/gitnexus/root.d.ts.map +1 -1
  34. package/lib/gitnexus/root.js +64 -5
  35. package/lib/gitnexus/root.js.map +1 -1
  36. package/lib/gitnexus/scan.d.ts +2 -0
  37. package/lib/gitnexus/scan.d.ts.map +1 -1
  38. package/lib/gitnexus/scan.js +3 -2
  39. package/lib/gitnexus/scan.js.map +1 -1
  40. package/lib/gitnexus/search.d.ts +21 -8
  41. package/lib/gitnexus/search.d.ts.map +1 -1
  42. package/lib/gitnexus/search.js +87 -13
  43. package/lib/gitnexus/search.js.map +1 -1
  44. package/lib/index.d.ts +6 -0
  45. package/lib/index.d.ts.map +1 -1
  46. package/lib/index.js +170 -2
  47. package/lib/index.js.map +1 -1
  48. package/lib/routes/analyze.d.ts +3 -2
  49. package/lib/routes/analyze.d.ts.map +1 -1
  50. package/lib/routes/analyze.js +8 -2
  51. package/lib/routes/analyze.js.map +1 -1
  52. package/lib/routes/coverage.d.ts +2 -1
  53. package/lib/routes/coverage.d.ts.map +1 -1
  54. package/lib/routes/coverage.js +53 -1
  55. package/lib/routes/coverage.js.map +1 -1
  56. package/lib/routes/delta.d.ts +22 -0
  57. package/lib/routes/delta.d.ts.map +1 -0
  58. package/lib/routes/delta.js +50 -0
  59. package/lib/routes/delta.js.map +1 -0
  60. package/lib/routes/file-diff.d.ts +19 -0
  61. package/lib/routes/file-diff.d.ts.map +1 -0
  62. package/lib/routes/file-diff.js +69 -0
  63. package/lib/routes/file-diff.js.map +1 -0
  64. package/lib/routes/file-history.d.ts +21 -0
  65. package/lib/routes/file-history.d.ts.map +1 -0
  66. package/lib/routes/file-history.js +69 -0
  67. package/lib/routes/file-history.js.map +1 -0
  68. package/lib/routes/graph.d.ts +22 -0
  69. package/lib/routes/graph.d.ts.map +1 -0
  70. package/lib/routes/graph.js +71 -0
  71. package/lib/routes/graph.js.map +1 -0
  72. package/package.json +3 -2
@@ -0,0 +1,472 @@
1
+ /**
2
+ * Bounded graph projection for the panel's graph view.
3
+ *
4
+ * WHY A PROJECTION AND NOT CYPHER OVER HTTP
5
+ * -----------------------------------------
6
+ * The graph itself is the product here: it answers "what is in this index" better than
7
+ * any table. But a view that accepts Cypher from a browser turns a read-only panel into
8
+ * an arbitrary query endpoint over the user's code graph — and the roadmap's rule is a
9
+ * whitelist of projections, never raw forwarding. So this module exposes exactly two
10
+ * shapes:
11
+ *
12
+ * `communities` every community as a node, with aggregated cross-community edges
13
+ * `community` one community's member symbols and the relations among them
14
+ *
15
+ * Both are bounded by a node budget and an edge budget, and both report what they left
16
+ * out. A 93k-node repository must not be able to freeze the panel, and a view that
17
+ * silently drops half the graph is worse than one that says it did.
18
+ *
19
+ * WHERE THIS RUNS
20
+ * ---------------
21
+ * `projectGraph` talks to LadybugDB, so it can only run on the system Node — the host
22
+ * is Electron's Node and cannot load the native addon (see `search.ts`). The host calls
23
+ * `projectViaHelper`, which starts `lib/bin/graph-helper.js` and parses one JSON object,
24
+ * exactly like the search path. Keeping the query code in the helper process also means
25
+ * a query that crashes the native engine takes down a short-lived child, not the panel.
26
+ */
27
+ import { existsSync, statSync } from 'node:fs';
28
+ import path from 'node:path';
29
+ import { isProjectRoot, readIndexMeta } from './index-meta.js';
30
+ import { loadAdapter } from './search.js';
31
+ export const GRAPH_VIEWS = ['communities', 'community'];
32
+ export class GraphError extends Error {
33
+ code;
34
+ status;
35
+ constructor(code, status, message) {
36
+ super(message);
37
+ this.name = 'GraphError';
38
+ this.code = code;
39
+ this.status = status;
40
+ }
41
+ }
42
+ const DEFAULT_NODE_BUDGET = 220;
43
+ const DEFAULT_EDGE_BUDGET = 800;
44
+ /** The character set a node/community id is allowed to contain. */
45
+ const ID_PATTERN = /^[\p{L}\p{N}_.:@/#+\-~ ]{1,200}$/u;
46
+ /**
47
+ * Reduce a caller-supplied id to something safe inside a single-quoted Cypher literal.
48
+ *
49
+ * The id is interpolated rather than bound because LadybugDB's prepare path does not
50
+ * accept a parameter in every position this query needs (the same limitation `search.ts`
51
+ * documents for `CONTAINS`). Safety comes from **refusing** anything outside a known
52
+ * alphabet — quotes and backslashes cannot appear — rather than from escaping.
53
+ *
54
+ * @returns the id, or null when it is not acceptable
55
+ */
56
+ export function sanitizeGraphId(raw) {
57
+ if (typeof raw !== 'string')
58
+ return null;
59
+ const trimmed = raw.trim();
60
+ if (trimmed === '')
61
+ return null;
62
+ return ID_PATTERN.test(trimmed) ? trimmed : null;
63
+ }
64
+ /** Whether a value names a projection this module implements. */
65
+ export function isGraphView(value) {
66
+ return value === 'communities' || value === 'community';
67
+ }
68
+ function clampBudget(value, fallback, max) {
69
+ if (value === undefined || !Number.isFinite(value))
70
+ return fallback;
71
+ return Math.max(1, Math.min(max, Math.floor(value)));
72
+ }
73
+ function toLine(value) {
74
+ if (typeof value === 'number' && Number.isFinite(value))
75
+ return Math.trunc(value);
76
+ if (typeof value === 'bigint')
77
+ return Number(value);
78
+ return null;
79
+ }
80
+ function asString(value) {
81
+ return typeof value === 'string' ? value : '';
82
+ }
83
+ /** Rows from `executePrepared` are the driver's objects; narrow them field by field. */
84
+ function rowsOf(value) {
85
+ return Array.isArray(value)
86
+ ? value.filter((row) => row !== null && typeof row === 'object')
87
+ : [];
88
+ }
89
+ /** One scalar `count(*)` result, defaulting to 0 when the shape is unexpected. */
90
+ function countOf(value) {
91
+ const [first] = rowsOf(value);
92
+ const total = first === undefined ? undefined : first.total ?? first.count ?? Object.values(first)[0];
93
+ return typeof total === 'number' && Number.isFinite(total) ? total : 0;
94
+ }
95
+ /**
96
+ * Read one projection.
97
+ *
98
+ * @param repoPath absolute repository root
99
+ */
100
+ export async function projectGraph(repoPath, options = {}) {
101
+ const absRepo = path.resolve(repoPath);
102
+ const view = options.view ?? 'communities';
103
+ if (!isGraphView(view)) {
104
+ throw new GraphError('invalid-view', 400, `未知的图视图:${String(options.view)}`);
105
+ }
106
+ const nodeBudget = clampBudget(options.nodeBudget, DEFAULT_NODE_BUDGET, 1000);
107
+ const edgeBudget = clampBudget(options.edgeBudget, DEFAULT_EDGE_BUDGET, 4000);
108
+ if (!(await isProjectRoot(absRepo))) {
109
+ throw new GraphError('not-a-project', 404, '目录不是 GitNexus 索引,也不是 git 项目根。');
110
+ }
111
+ const meta = await readIndexMeta(absRepo);
112
+ if (meta === null) {
113
+ throw new GraphError('no-index', 409, '该项目还没有 GitNexus 索引;初始化后才能看图。');
114
+ }
115
+ const lbugPath = path.join(absRepo, '.gitnexus', 'lbug');
116
+ if (!existsSync(lbugPath)) {
117
+ throw new GraphError('no-index-store', 409, '索引缺少 .gitnexus/lbug 图存储,无法读图。');
118
+ }
119
+ let scope = null;
120
+ const notes = [];
121
+ if (view === 'community') {
122
+ scope = sanitizeGraphId(options.id);
123
+ if (scope === null) {
124
+ throw new GraphError('invalid-id', 400, 'community 视图需要合法的 id 参数。');
125
+ }
126
+ }
127
+ // One adapter load per projection, and one connection for both the page of rows and
128
+ // its total. Reopening the store per query would double the cost of every drill-down.
129
+ let adapter;
130
+ try {
131
+ adapter = await loadAdapter({ env: options.env, managedPrefix: options.managedPrefix });
132
+ }
133
+ catch (cause) {
134
+ const message = cause instanceof Error ? cause.message : String(cause);
135
+ throw new GraphError('graph-unavailable', 503, `图数据库适配器不可用:${message}`);
136
+ }
137
+ const runQuery = async (cypher) => {
138
+ try {
139
+ return await adapter.withLbugDb(lbugPath, async () => adapter.executePrepared(cypher, {}), {
140
+ readOnly: true,
141
+ skipFts: true,
142
+ });
143
+ }
144
+ catch (cause) {
145
+ const message = cause instanceof Error ? cause.message : String(cause);
146
+ if (/busy|locked|lock held|another process|timeout/i.test(message)) {
147
+ throw new GraphError('index-busy', 503, '索引正被另一个 GitNexus 操作占用,稍后重试。');
148
+ }
149
+ throw new GraphError('graph-failed', 500, `图查询失败:${message}`);
150
+ }
151
+ };
152
+ const nodes = [];
153
+ const edges = [];
154
+ let total = 0;
155
+ if (view === 'communities') {
156
+ const communityRows = rowsOf(await runQuery(`MATCH (c:Community)
157
+ RETURN c.id AS id, c.label AS label, c.symbolCount AS symbolCount
158
+ ORDER BY symbolCount DESC
159
+ LIMIT ${nodeBudget}`));
160
+ total = countOf(await runQuery('MATCH (c:Community) RETURN count(*) AS total'));
161
+ for (const row of communityRows) {
162
+ const id = asString(row.id);
163
+ if (id === '')
164
+ continue;
165
+ const label = asString(row.label);
166
+ nodes.push({
167
+ id,
168
+ kind: 'Community',
169
+ name: label === '' ? id : label,
170
+ filePath: null,
171
+ startLine: null,
172
+ symbolCount: typeof row.symbolCount === 'number' ? row.symbolCount : 0,
173
+ });
174
+ }
175
+ // Cross-community edges are aggregated from the member-to-member relations: one
176
+ // edge per pair of communities per relation type. Two directions are collapsed
177
+ // (`ca.id < cb.id`) so the view does not draw every link twice.
178
+ const edgeRows = rowsOf(await runQuery(`MATCH (a)-[r:CodeRelation]->(b)
179
+ MATCH (a)-[:CodeRelation {type:'MEMBER_OF'}]->(ca:Community)
180
+ MATCH (b)-[:CodeRelation {type:'MEMBER_OF'}]->(cb:Community)
181
+ WHERE ca.id < cb.id
182
+ RETURN ca.id AS source, cb.id AS target, r.type AS type, count(*) AS weight
183
+ ORDER BY weight DESC
184
+ LIMIT ${edgeBudget}`));
185
+ for (const row of edgeRows) {
186
+ const source = asString(row.source);
187
+ const target = asString(row.target);
188
+ if (source === '' || target === '')
189
+ continue;
190
+ edges.push({
191
+ source,
192
+ target,
193
+ type: asString(row.type),
194
+ weight: typeof row.weight === 'number' ? row.weight : 1,
195
+ });
196
+ }
197
+ }
198
+ else {
199
+ const scopeLiteral = scope;
200
+ const memberRows = rowsOf(await runQuery(`MATCH (s)-[:CodeRelation {type:'MEMBER_OF'}]->(c:Community {id:'${scopeLiteral}'})
201
+ RETURN s.id AS id, label(s) AS kind, s.name AS name,
202
+ s.filePath AS filePath, s.startLine AS startLine
203
+ ORDER BY name
204
+ LIMIT ${nodeBudget}`));
205
+ total = countOf(await runQuery(`MATCH (s)-[:CodeRelation {type:'MEMBER_OF'}]->(c:Community {id:'${scopeLiteral}'})
206
+ RETURN count(*) AS total`));
207
+ for (const row of memberRows) {
208
+ const id = asString(row.id);
209
+ if (id === '')
210
+ continue;
211
+ const { name, filePath, startLine, kind } = row;
212
+ nodes.push({
213
+ id,
214
+ kind: asString(kind),
215
+ name: asString(name) === '' ? id : asString(name),
216
+ filePath: typeof filePath === 'string' && filePath !== '' ? filePath : null,
217
+ startLine: toLine(startLine),
218
+ });
219
+ }
220
+ const edgeRows = rowsOf(await runQuery(`MATCH (a)-[r:CodeRelation]->(b)
221
+ MATCH (a)-[:CodeRelation {type:'MEMBER_OF'}]->(c:Community {id:'${scopeLiteral}'})
222
+ MATCH (b)-[:CodeRelation {type:'MEMBER_OF'}]->(c)
223
+ RETURN a.id AS source, b.id AS target, r.type AS type, count(*) AS weight
224
+ ORDER BY weight DESC
225
+ LIMIT ${edgeBudget}`));
226
+ for (const row of edgeRows) {
227
+ const source = asString(row.source);
228
+ const target = asString(row.target);
229
+ if (source === '' || target === '')
230
+ continue;
231
+ edges.push({
232
+ source,
233
+ target,
234
+ type: asString(row.type),
235
+ weight: typeof row.weight === 'number' ? row.weight : 1,
236
+ });
237
+ }
238
+ if (total === 0 && nodes.length === 0) {
239
+ notes.push('该社区没有成员符号;索引可能是旧版本,或社区已被重新划分。');
240
+ }
241
+ }
242
+ // An edge whose endpoint fell outside the node budget cannot be drawn. Dropping it
243
+ // here keeps the client from having to special-case dangling ids, and the count is
244
+ // reported rather than silently swallowed.
245
+ const present = new Set(nodes.map((node) => node.id));
246
+ const kept = edges.filter((edge) => present.has(edge.source) && present.has(edge.target));
247
+ const droppedEdges = edges.length - kept.length;
248
+ if (droppedEdges > 0) {
249
+ notes.push(`${droppedEdges} 条边因端点超出节点预算未显示`);
250
+ }
251
+ const truncated = total > nodes.length || edges.length >= edgeBudget;
252
+ if (total > nodes.length) {
253
+ notes.push(view === 'communities'
254
+ ? `共 ${total} 个社区,显示符号数最多的 ${nodes.length} 个`
255
+ : `该社区共 ${total} 个符号,显示前 ${nodes.length} 个`);
256
+ }
257
+ if (edges.length >= edgeBudget) {
258
+ notes.push(`边达到上限 ${edgeBudget},只保留了权重最高的部分`);
259
+ }
260
+ return {
261
+ view,
262
+ scope,
263
+ nodes,
264
+ edges: kept,
265
+ total,
266
+ truncated,
267
+ budget: { nodes: nodeBudget, edges: edgeBudget },
268
+ notes,
269
+ readAt: new Date().toISOString(),
270
+ };
271
+ }
272
+ function quoteFor(value) {
273
+ return process.platform === 'win32'
274
+ ? `'${value.replace(/'/g, "''")}'`
275
+ : `'${value.replace(/'/g, "'\\''")}'`;
276
+ }
277
+ function parseHelperOutput(text) {
278
+ const start = text.indexOf('{');
279
+ const end = text.lastIndexOf('}');
280
+ if (start < 0 || end <= start)
281
+ return null;
282
+ try {
283
+ const parsed = JSON.parse(text.slice(start, end + 1));
284
+ return parsed !== null && typeof parsed === 'object' ? parsed : null;
285
+ }
286
+ catch {
287
+ return null;
288
+ }
289
+ }
290
+ function graphErrorCode(value) {
291
+ switch (value) {
292
+ case 'invalid-view':
293
+ case 'invalid-id':
294
+ case 'not-a-project':
295
+ case 'no-index':
296
+ case 'no-index-store':
297
+ case 'graph-unavailable':
298
+ case 'index-busy':
299
+ case 'graph-failed':
300
+ return value;
301
+ default:
302
+ return 'graph-failed';
303
+ }
304
+ }
305
+ function asProjection(value) {
306
+ if (value === null || typeof value !== 'object')
307
+ return null;
308
+ const raw = value;
309
+ if (!Array.isArray(raw.nodes) || !Array.isArray(raw.edges))
310
+ return null;
311
+ if (!isGraphView(raw.view))
312
+ return null;
313
+ const nodes = [];
314
+ for (const item of raw.nodes) {
315
+ if (item === null || typeof item !== 'object')
316
+ continue;
317
+ const row = item;
318
+ if (typeof row.id !== 'string' || row.id === '')
319
+ continue;
320
+ nodes.push({
321
+ id: row.id,
322
+ kind: typeof row.kind === 'string' ? row.kind : 'Unknown',
323
+ name: typeof row.name === 'string' && row.name !== '' ? row.name : row.id,
324
+ filePath: typeof row.filePath === 'string' && row.filePath !== '' ? row.filePath : null,
325
+ startLine: toLine(row.startLine),
326
+ ...(typeof row.symbolCount === 'number' ? { symbolCount: row.symbolCount } : {}),
327
+ });
328
+ }
329
+ const edges = [];
330
+ for (const item of raw.edges) {
331
+ if (item === null || typeof item !== 'object')
332
+ continue;
333
+ const row = item;
334
+ if (typeof row.source !== 'string' || typeof row.target !== 'string')
335
+ continue;
336
+ edges.push({
337
+ source: row.source,
338
+ target: row.target,
339
+ type: typeof row.type === 'string' ? row.type : 'Related',
340
+ weight: typeof row.weight === 'number' && Number.isFinite(row.weight) ? row.weight : 1,
341
+ });
342
+ }
343
+ const budget = (raw.budget ?? {});
344
+ return {
345
+ view: raw.view,
346
+ scope: typeof raw.scope === 'string' ? raw.scope : null,
347
+ nodes,
348
+ edges,
349
+ total: typeof raw.total === 'number' ? raw.total : nodes.length,
350
+ truncated: raw.truncated === true,
351
+ budget: {
352
+ nodes: typeof budget.nodes === 'number' ? budget.nodes : nodes.length,
353
+ edges: typeof budget.edges === 'number' ? budget.edges : edges.length,
354
+ },
355
+ notes: Array.isArray(raw.notes) ? raw.notes.filter((note) => typeof note === 'string') : [],
356
+ readAt: typeof raw.readAt === 'string' ? raw.readAt : new Date().toISOString(),
357
+ };
358
+ }
359
+ /**
360
+ * Read a projection in a child Node process.
361
+ *
362
+ * Same execution boundary as `searchViaHelper`, for the same measured reason: the host
363
+ * cannot load `lbugjs.node`. A failure to start the child is reported as
364
+ * `graph-unavailable`, and this plugin never widens the sandbox to make it work.
365
+ */
366
+ export async function projectViaHelper(repoPath, view, id, options) {
367
+ const absRepo = path.resolve(repoPath);
368
+ if (!(await isProjectRoot(absRepo))) {
369
+ throw new GraphError('not-a-project', 404, '目录不是 GitNexus 索引,也不是 git 项目根。');
370
+ }
371
+ const meta = await readIndexMeta(absRepo);
372
+ if (meta === null) {
373
+ throw new GraphError('no-index', 409, '该项目还没有 GitNexus 索引;初始化后才能看图。');
374
+ }
375
+ if (!existsSync(path.join(absRepo, '.gitnexus', 'lbug'))) {
376
+ throw new GraphError('no-index-store', 409, '索引缺少 .gitnexus/lbug 图存储,无法读图。');
377
+ }
378
+ if (options.shell === null) {
379
+ throw new GraphError('graph-unavailable', 503, '当前部署没有 shell 执行器,无法启动图投影子进程;读图需要系统 Node 加载 GitNexus 原生模块。');
380
+ }
381
+ const budgetNodes = clampBudget(options.nodeBudget, DEFAULT_NODE_BUDGET, 1000);
382
+ const budgetEdges = clampBudget(options.edgeBudget, DEFAULT_EDGE_BUDGET, 4000);
383
+ // A projection is a pure function of the index, the view, the id and the budgets, and
384
+ // producing it costs a Node cold start plus the native open. Switching communities and
385
+ // pressing re-read are common; the index mtime is part of the key, so a refresh
386
+ // invalidates without any cross-module wiring.
387
+ const cacheKey = projectionCacheKey(absRepo, view, id, budgetNodes, budgetEdges);
388
+ const cached = cacheKey === null ? undefined : projectionCache.get(cacheKey);
389
+ if (cached !== undefined && Date.now() - cached.at < PROJECTION_CACHE_TTL_MS) {
390
+ return cached.value;
391
+ }
392
+ const args = [
393
+ options.helperPath,
394
+ absRepo,
395
+ view,
396
+ id ?? '',
397
+ options.managedPrefix ?? '',
398
+ String(budgetNodes),
399
+ String(budgetEdges),
400
+ ]
401
+ .map(quoteFor)
402
+ .join(' ');
403
+ const command = `node ${args}`;
404
+ let result;
405
+ try {
406
+ const spec = options.shell.resolve({
407
+ command,
408
+ workdir: absRepo,
409
+ timeoutMs: 25_000,
410
+ onExpiry: 'kill',
411
+ stdoutMaxBytes: 4 * 1024 * 1024,
412
+ });
413
+ const execution = await options.shell.execute(spec);
414
+ result = await execution.result();
415
+ }
416
+ catch (cause) {
417
+ throw new GraphError('graph-unavailable', 503, `无法启动图投影子进程:${cause instanceof Error ? cause.message : String(cause)}`);
418
+ }
419
+ if (result.timedOut === true) {
420
+ throw new GraphError('graph-failed', 504, '图投影子进程超时(25 秒)。');
421
+ }
422
+ const stdout = typeof result.stdout?.text === 'string' ? result.stdout.text : '';
423
+ const stderr = typeof result.stderr?.text === 'string' ? result.stderr.text : '';
424
+ const parsed = parseHelperOutput(stdout);
425
+ if (parsed === null) {
426
+ const tail = stderr.trim().slice(-600);
427
+ throw new GraphError('graph-failed', 500, `图投影子进程没有返回可解析结果${result.exitCode === undefined ? '' : ` (exit ${String(result.exitCode)})`}` + (tail === '' ? '' : `:${tail}`));
428
+ }
429
+ if (parsed.ok !== true) {
430
+ const status = typeof parsed.status === 'number' ? parsed.status : 500;
431
+ const message = typeof parsed.message === 'string' ? parsed.message : '读取图失败。';
432
+ throw new GraphError(graphErrorCode(parsed.code), status, message);
433
+ }
434
+ const projection = asProjection(parsed.projection);
435
+ if (projection === null) {
436
+ throw new GraphError('graph-failed', 500, '图投影子进程返回了无法识别的结果形状。');
437
+ }
438
+ if (cacheKey !== null)
439
+ rememberProjection(cacheKey, projection);
440
+ return projection;
441
+ }
442
+ /** How many projections to keep; each is bounded by the budgets, so this is small. */
443
+ const PROJECTION_CACHE_MAX = 8;
444
+ const PROJECTION_CACHE_TTL_MS = 60_000;
445
+ const projectionCache = new Map();
446
+ function rememberProjection(key, value) {
447
+ projectionCache.delete(key);
448
+ projectionCache.set(key, { at: Date.now(), value });
449
+ while (projectionCache.size > PROJECTION_CACHE_MAX) {
450
+ const oldest = projectionCache.keys().next().value;
451
+ if (oldest === undefined)
452
+ break;
453
+ projectionCache.delete(oldest);
454
+ }
455
+ }
456
+ /**
457
+ * Cache key for one projection, or `null` when the index cannot be statted.
458
+ *
459
+ * The index file's mtime is in the key: a refresh rewrites it, so a cached projection
460
+ * from before the refresh can never be served after it.
461
+ */
462
+ function projectionCacheKey(repoPath, view, id, nodes, edges) {
463
+ try {
464
+ const metaFile = path.join(repoPath, '.gitnexus', 'gitnexus.json');
465
+ const mtime = statSync(metaFile).mtimeMs;
466
+ return [repoPath, view, id ?? '', nodes, edges, mtime].join('\u0000');
467
+ }
468
+ catch {
469
+ return null;
470
+ }
471
+ }
472
+ //# sourceMappingURL=graph.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graph.js","sourceRoot":"","sources":["../../src/gitnexus/graph.ts"],"names":[],"mappings":"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"}
@@ -26,9 +26,6 @@ export interface RootDiscoveryOptions {
26
26
  */
27
27
  managedPrefix?: string;
28
28
  }
29
- /**
30
- * Resolve the GitNexus package root, or `null` when no usable install is found.
31
- */
32
29
  export declare function findGitnexusRoot(options?: RootDiscoveryOptions): string | null;
33
30
  /**
34
31
  * Read the installed GitNexus version. Returned for provenance so a report can
@@ -1 +1 @@
1
- {"version":3,"file":"root.d.ts","sourceRoot":"","sources":["../../src/gitnexus/root.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAcH,2EAA2E;AAC3E,MAAM,WAAW,oBAAoB;IACnC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AA4DD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,GAAE,oBAAyB,GAAG,MAAM,GAAG,IAAI,CAWlF;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAS/D;AAKD,oFAAoF;AACpF,MAAM,MAAM,mBAAmB,GAAG,CAChC,QAAQ,EAAE,MAAM,EAChB,UAAU,CAAC,EAAE,OAAO,EACpB,OAAO,CAAC,EAAE,MAAM,KACb,OAAO,CAAC,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC,CAAC;AAEpD,+EAA+E;AAC/E,MAAM,MAAM,kBAAkB,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;AAE1F,yDAAyD;AACzD,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;AA6BnF;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,IAAI,EAAE,YAAY,CAAC;IACnB,kBAAkB,EAAE,kBAAkB,CAAC;IACvC,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,mBAAmB,EAAE,MAAM,MAAM,CAAC;IAClC,2BAA2B,EAAE,MAAM,CAAC;IACpC,+BAA+B,EAAE,MAAM,CAAC;IACxC,MAAM,EAAE,UAAU,GAAG,UAAU,CAAC;CACjC;AAED,8DAA8D;AAC9D,MAAM,WAAW,yBAA0B,SAAQ,oBAAoB;IACrE,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;GAOG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,GAAE,yBAA8B,GACtC,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAiDhC"}
1
+ {"version":3,"file":"root.d.ts","sourceRoot":"","sources":["../../src/gitnexus/root.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAcH,2EAA2E;AAC3E,MAAM,WAAW,oBAAoB;IACnC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAoHD,wBAAgB,gBAAgB,CAAC,OAAO,GAAE,oBAAyB,GAAG,MAAM,GAAG,IAAI,CAmBlF;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAS/D;AAKD,oFAAoF;AACpF,MAAM,MAAM,mBAAmB,GAAG,CAChC,QAAQ,EAAE,MAAM,EAChB,UAAU,CAAC,EAAE,OAAO,EACpB,OAAO,CAAC,EAAE,MAAM,KACb,OAAO,CAAC,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC,CAAC;AAEpD,+EAA+E;AAC/E,MAAM,MAAM,kBAAkB,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;AAE1F,yDAAyD;AACzD,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;AA6BnF;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,IAAI,EAAE,YAAY,CAAC;IACnB,kBAAkB,EAAE,kBAAkB,CAAC;IACvC,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,mBAAmB,EAAE,MAAM,MAAM,CAAC;IAClC,2BAA2B,EAAE,MAAM,CAAC;IACpC,+BAA+B,EAAE,MAAM,CAAC;IACxC,MAAM,EAAE,UAAU,GAAG,UAAU,CAAC;CACjC;AAED,8DAA8D;AAC9D,MAAM,WAAW,yBAA0B,SAAQ,oBAAoB;IACrE,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;GAOG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,GAAE,yBAA8B,GACtC,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAiDhC"}
@@ -41,7 +41,14 @@ const DIST = Object.freeze({
41
41
  function candidateRoots(options = {}) {
42
42
  if (options.discover === false)
43
43
  return [];
44
- const env = { ...process.env, ...(options.env ?? {}) };
44
+ const override = options.env ?? {};
45
+ // `{ ...process.env }` turns Node's case-insensitive env proxy into an ordinary
46
+ // object, so on Windows the key is `Path` and `env.PATH` is `undefined` — the PATH
47
+ // probe then looked at nothing and reported "not installed" on a machine where
48
+ // `gitnexus` runs. Read every spelling, override first, like `toolchain.ts` does.
49
+ const overridePath = override.PATH ?? override.Path ?? override.path;
50
+ const env = { ...process.env, ...override };
51
+ const pathValue = overridePath ?? process.env.PATH ?? process.env.Path ?? '';
45
52
  const roots = [];
46
53
  if (env.GITNEXUS_PACKAGE_ROOT)
47
54
  roots.push(env.GITNEXUS_PACKAGE_ROOT);
@@ -58,13 +65,27 @@ function candidateRoots(options = {}) {
58
65
  // shim-based discovery silently finds nothing on the very machines where the
59
66
  // CLI is most likely to be installed. Testing the directory is
60
67
  // extension-independent and needs no PATHEXT reasoning.
61
- for (const dir of (env.PATH ?? '').split(path.delimiter)) {
68
+ //
69
+ // One exception, measured on this machine: a directory that CARRIES the shim owns
70
+ // the install the CLI actually runs, and an older copy sitting earlier on PATH wins
71
+ // the plain scan. That produced a graph helper loading 1.6.6 against an index written
72
+ // by 1.6.12 ("Database file version: 42, Current build storage version: 41"), so a
73
+ // shim-bearing entry is probed first.
74
+ const shimRoots = [];
75
+ const plainRoots = [];
76
+ for (const dir of pathValue.split(path.delimiter)) {
62
77
  if (dir === '')
63
78
  continue;
64
- roots.push(path.join(dir, 'node_modules', 'gitnexus'));
65
- roots.push(path.join(dir, '..', 'node_modules', 'gitnexus'));
66
- roots.push(path.join(dir, '..', '..', 'node_modules', 'gitnexus'));
79
+ const local = path.join(dir, 'node_modules', 'gitnexus');
80
+ const hasShim = existsSync(path.join(dir, 'gitnexus.cmd')) ||
81
+ existsSync(path.join(dir, 'gitnexus.exe')) ||
82
+ existsSync(path.join(dir, 'gitnexus.ps1')) ||
83
+ existsSync(path.join(dir, 'gitnexus'));
84
+ (hasShim ? shimRoots : plainRoots).push(local);
85
+ plainRoots.push(path.join(dir, '..', 'node_modules', 'gitnexus'));
86
+ plainRoots.push(path.join(dir, '..', '..', 'node_modules', 'gitnexus'));
67
87
  }
88
+ roots.push(...shimRoots, ...plainRoots);
68
89
  // nvm-for-windows keeps the real tree off PATH behind a junction.
69
90
  if (env.NVM_SYMLINK)
70
91
  roots.push(path.join(env.NVM_SYMLINK, 'node_modules', 'gitnexus'));
@@ -83,11 +104,49 @@ function candidateRoots(options = {}) {
83
104
  }
84
105
  /**
85
106
  * Resolve the GitNexus package root, or `null` when no usable install is found.
107
+ *
108
+ * The candidate list is cheap to build and expensive to probe: every call stats dozens
109
+ * of paths, and a single panel load asks several times (coverage, languages, search and
110
+ * graph helpers). A positive result is memoized for 30 s and re-validated with one
111
+ * `existsSync` before reuse, so an uninstall cannot leave a dead path in place.
112
+ *
113
+ * `null` is deliberately NOT memoized: the panel's install flow writes the managed tree
114
+ * and immediately re-reads the toolchain, and a cached "absent" would keep reporting
115
+ * that for half a minute after a successful install.
86
116
  */
117
+ const ROOT_CACHE_TTL_MS = 30_000;
118
+ const ROOT_CACHE_MAX = 8;
119
+ const rootCache = new Map();
120
+ function rootCacheKey(options) {
121
+ const override = options.env ?? {};
122
+ const pathValue = override.PATH ??
123
+ override.Path ??
124
+ override.path ??
125
+ process.env.PATH ??
126
+ process.env.Path ??
127
+ '';
128
+ return [
129
+ options.discover === false ? '0' : '1',
130
+ options.managedPrefix ?? '',
131
+ override.GITNEXUS_PACKAGE_ROOT ?? process.env.GITNEXUS_PACKAGE_ROOT ?? '',
132
+ options.moduleUrl ?? '',
133
+ pathValue,
134
+ ].join('\u0000');
135
+ }
87
136
  export function findGitnexusRoot(options = {}) {
137
+ const key = rootCacheKey(options);
138
+ const hit = rootCache.get(key);
139
+ if (hit !== undefined && Date.now() - hit.at < ROOT_CACHE_TTL_MS) {
140
+ if (existsSync(hit.root))
141
+ return hit.root;
142
+ rootCache.delete(key);
143
+ }
88
144
  for (const root of candidateRoots(options)) {
89
145
  try {
90
146
  if (existsSync(path.join(root, 'package.json')) && existsSync(path.join(root, DIST.walker))) {
147
+ if (rootCache.size >= ROOT_CACHE_MAX)
148
+ rootCache.clear();
149
+ rootCache.set(key, { root, at: Date.now() });
91
150
  return root;
92
151
  }
93
152
  }
@@ -1 +1 @@
1
- {"version":3,"file":"root.js","sourceRoot":"","sources":["../../src/gitnexus/root.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"root.js","sourceRoot":"","sources":["../../src/gitnexus/root.ts"],"names":[],"mappings":"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"}
@@ -64,5 +64,7 @@ export declare function scanRepository(repoPath: string, options?: {
64
64
  env?: NodeJS.ProcessEnv;
65
65
  primitives?: ScanPrimitives | null;
66
66
  managedPrefix?: string;
67
+ /** Called after each stat batch with the number of files examined. */
68
+ onProgress?: (done: number, total: number) => void;
67
69
  }): Promise<ScanReport>;
68
70
  //# sourceMappingURL=scan.d.ts.map