@trebired/code-insights 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/.trebired/logger/config.ts +4 -0
  2. package/CHANGELOG.md +11 -0
  3. package/LICENSE +661 -0
  4. package/README.md +139 -2
  5. package/dist/client/controller.d.ts +31 -0
  6. package/dist/client/controller.d.ts.map +1 -0
  7. package/dist/client/controller.js +136 -0
  8. package/dist/client/controller.js.map +1 -0
  9. package/dist/client/index.d.ts +5 -0
  10. package/dist/client/index.d.ts.map +1 -0
  11. package/dist/client/index.js +59 -0
  12. package/dist/client/index.js.map +1 -0
  13. package/dist/client/layout.d.ts +8 -0
  14. package/dist/client/layout.d.ts.map +1 -0
  15. package/dist/client/layout.js +30 -0
  16. package/dist/client/layout.js.map +1 -0
  17. package/dist/client/model.d.ts +27 -0
  18. package/dist/client/model.d.ts.map +1 -0
  19. package/dist/client/model.js +57 -0
  20. package/dist/client/model.js.map +1 -0
  21. package/dist/client/render.d.ts +20 -0
  22. package/dist/client/render.d.ts.map +1 -0
  23. package/dist/client/render.js +95 -0
  24. package/dist/client/render.js.map +1 -0
  25. package/dist/client/viewport.d.ts +12 -0
  26. package/dist/client/viewport.d.ts.map +1 -0
  27. package/dist/client/viewport.js +70 -0
  28. package/dist/client/viewport.js.map +1 -0
  29. package/dist/index.d.ts +3 -0
  30. package/dist/index.d.ts.map +1 -0
  31. package/dist/index.js +2 -0
  32. package/dist/index.js.map +1 -0
  33. package/dist/react/code_map.d.ts +17 -0
  34. package/dist/react/code_map.d.ts.map +1 -0
  35. package/dist/react/code_map.js +36 -0
  36. package/dist/react/code_map.js.map +1 -0
  37. package/dist/react/hotspots.d.ts +12 -0
  38. package/dist/react/hotspots.d.ts.map +1 -0
  39. package/dist/react/hotspots.js +28 -0
  40. package/dist/react/hotspots.js.map +1 -0
  41. package/dist/react/index.d.ts +5 -0
  42. package/dist/react/index.d.ts.map +1 -0
  43. package/dist/react/index.js +3 -0
  44. package/dist/react/index.js.map +1 -0
  45. package/dist/server/binary.d.ts +4 -0
  46. package/dist/server/binary.d.ts.map +1 -0
  47. package/dist/server/binary.js +46 -0
  48. package/dist/server/binary.js.map +1 -0
  49. package/dist/server/detect.d.ts +13 -0
  50. package/dist/server/detect.d.ts.map +1 -0
  51. package/dist/server/detect.js +15 -0
  52. package/dist/server/detect.js.map +1 -0
  53. package/dist/server/index.d.ts +10 -0
  54. package/dist/server/index.d.ts.map +1 -0
  55. package/dist/server/index.js +6 -0
  56. package/dist/server/index.js.map +1 -0
  57. package/dist/server/logging.d.ts +4 -0
  58. package/dist/server/logging.d.ts.map +1 -0
  59. package/dist/server/logging.js +12 -0
  60. package/dist/server/logging.js.map +1 -0
  61. package/dist/server/map.d.ts +8 -0
  62. package/dist/server/map.d.ts.map +1 -0
  63. package/dist/server/map.js +81 -0
  64. package/dist/server/map.js.map +1 -0
  65. package/dist/server/process.d.ts +13 -0
  66. package/dist/server/process.d.ts.map +1 -0
  67. package/dist/server/process.js +58 -0
  68. package/dist/server/process.js.map +1 -0
  69. package/dist/server/scan.d.ts +30 -0
  70. package/dist/server/scan.d.ts.map +1 -0
  71. package/dist/server/scan.js +63 -0
  72. package/dist/server/scan.js.map +1 -0
  73. package/dist/shared/constants.d.ts +5 -0
  74. package/dist/shared/constants.d.ts.map +1 -0
  75. package/dist/shared/constants.js +5 -0
  76. package/dist/shared/constants.js.map +1 -0
  77. package/dist/shared/copy.d.ts +40 -0
  78. package/dist/shared/copy.d.ts.map +1 -0
  79. package/dist/shared/copy.js +56 -0
  80. package/dist/shared/copy.js.map +1 -0
  81. package/dist/shared/types.d.ts +138 -0
  82. package/dist/shared/types.d.ts.map +1 -0
  83. package/dist/shared/types.js +2 -0
  84. package/dist/shared/types.js.map +1 -0
  85. package/native/linux-arm64-gnu/code-insights +0 -0
  86. package/native/linux-x64-gnu/code-insights +0 -0
  87. package/native/vendor/hyperpolyglot/LICENSE-MIT +21 -0
  88. package/package.json +107 -4
package/README.md CHANGED
@@ -1,3 +1,140 @@
1
- # Temporary Holding Version
1
+ # @trebired/code-insights
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Repository insights for Bun applications, scanned by a native engine that reads a git repository directly: languages, the file tree, a file import graph, a function call graph and hotspots, with live progress, plus an interactive code map and hotspot list for `@trebired/frontend`.
4
+
5
+ The package owns reading the repository at a ref, language detection, line counts, vendored and generated file rules, the tree, import resolution, call resolution, churn, the progress stream, the result format, the code map data, and the code map and hotspot interface. The application owns where repositories live, when a scan runs, where results are stored, who may see them, and the routes that serve them. The package does not own a job queue, storage, permissions, or any HTTP route.
6
+
7
+ ## Install
8
+
9
+ Runtime support: Bun 1+.
10
+
11
+ ```sh
12
+ bun i @trebired/code-insights
13
+ ```
14
+
15
+ ## Quick Start
16
+
17
+ ```ts
18
+ import { buildCodeMapData, scanRepository } from "@trebired/code-insights/server";
19
+
20
+ const result = await scanRepository({
21
+ gitDir: "/srv/repositories/app.git",
22
+ ref: "main",
23
+ onProgress: ({ phase, percent }) => broadcast("scan", { phase, percent }),
24
+ });
25
+
26
+ const files = buildCodeMapData(result, "file");
27
+ const functions = buildCodeMapData(result, "function");
28
+ ```
29
+
30
+ ```tsx
31
+ import { code_map, hotspot_list } from "@trebired/code-insights/react";
32
+
33
+ code_map({ dataUrl: "/repository/insights/graph", hrefTemplate: "/repository/edit?path={path}&line={line}", lang });
34
+ hotspot_list({ hotspots: result.hotspots, hrefFor: (path) => `/repository/edit?path=${encodeURIComponent(path)}`, lang });
35
+ ```
36
+
37
+ ```ts
38
+ import { bindCodeMaps } from "@trebired/code-insights/client";
39
+
40
+ bindCodeMaps(document);
41
+ ```
42
+
43
+ ## Concepts
44
+
45
+ ### Engine
46
+
47
+ The scan runs in a separate native process, not in the application's process. It reads the ref with the `git` command line, streams every blob through one `git cat-file --batch` process, and parses files in parallel. A crash, a huge repository or a cancelled scan never takes the application down, and the scan never blocks its event loop.
48
+
49
+ ### Phases
50
+
51
+ A scan runs these phases in order. Each one reports `{ phase, done, total, percent }` while it runs, and `percent` is the share of the whole scan, weighted by phase.
52
+
53
+ | Phase | Result |
54
+ | --- | --- |
55
+ | `listing` | the commit and every tree entry |
56
+ | `languages` | `languages`, `files`, `totals`, `unknown`, `skipped` |
57
+ | `tree` | `tree.nested` and `tree.ascii` |
58
+ | `imports` | `imports`: files as nodes, resolved imports as edges |
59
+ | `functions` | `functions`: definitions as nodes, resolved calls as edges |
60
+ | `hotspots` | `hotspots`: code lines times commits that touched the file |
61
+
62
+ `phases` limits a scan to the phases it names. `listing` always runs, `functions` brings `imports` with it, and `imports` and `hotspots` bring `languages`.
63
+
64
+ ### Languages
65
+
66
+ Detection follows GitHub Linguist's rules: file names, extensions, shebangs, heuristics and the classifier, with Linguist's colours and language types. Files are left out of the totals when they are binary, vendored (`node_modules`, `dist`, `vendor` and the rest of Linguist's list), generated (lockfiles, minified files, source maps, a generated header) or documentation. `.gitattributes` overrides all of these with `linguist-vendored`, `linguist-generated`, `linguist-documentation` and `linguist-language`.
67
+
68
+ ### Import Resolution
69
+
70
+ Imports resolve to files in the same repository. Package imports count as external, and imports that point inside the repository but match no file count as unresolved, with up to 50 samples in `imports.unresolved_samples`.
71
+
72
+ - TypeScript and JavaScript: relative paths, extensions and `index` files, `.js` specifiers that name a `.ts` file, tsconfig `paths` and `baseUrl` through `extends`, package.json `imports`, and Code Discipline alias maps in `.trebired/code-discipline/imports/*.json`.
73
+ - Python: relative imports, packages and modules from the importing file's directory upwards and from `src`.
74
+ - Rust: `mod` declarations, `#[path]` modules, `include!`, and `use` paths starting with `crate`, `self` or `super`.
75
+ - Go: import paths under a `go.mod` module, to every non-test file of the package.
76
+
77
+ ### Call Resolution
78
+
79
+ A call becomes an edge only when the engine can name its target: a function in the same file, an imported function, a method on `this` or `self`, a method of a type through `Type::method` or `Self::method`, a Go receiver method or a function of the same Go package. Anything else counts as unresolved and draws no edge. Each edge carries how it was resolved (`local`, `import`, `member` or `package`) and how often the call appears.
80
+
81
+ ### Code Map
82
+
83
+ `buildCodeMapData(result, level)` turns either graph into nodes grouped by folder, choosing a folder depth that gives a readable number of groups. The map starts with every folder collapsed into one node. Clicking a folder opens it, clicking a file or function highlights what it links to and what links to it, and clicking it again opens it through `hrefTemplate`. A cancellable `code-map:open` event fires first, so the application can take over the navigation.
84
+
85
+ ## Configuration
86
+
87
+ ### Limits
88
+
89
+ `scanRepository` takes `limits`:
90
+
91
+ | Option | Default | Effect |
92
+ | --- | --- | --- |
93
+ | `maxReadBytes` | 8 MB | larger files are counted by size only |
94
+ | `maxParseBytes` | 1 MB | larger files are not parsed for imports or calls |
95
+ | `maxImportEdges` | 50 000 | further edges are dropped and `imports.truncated` is set |
96
+ | `maxFunctionNodes` | 20 000 | further definitions are dropped and `functions.truncated` is set |
97
+ | `maxFunctionEdges` | 60 000 | the most frequent calls are kept |
98
+ | `historyCommits` | 1 000 | commits read for hotspots |
99
+
100
+ `buildCodeMapData` takes `maxNodes` (default 4 000) and keeps the most connected nodes of a larger graph.
101
+
102
+ ## Runtime
103
+
104
+ ### Engine Binary
105
+
106
+ The package ships the engine for Linux x64 and arm64 with glibc, in `native/<platform>/code-insights`. `TREBIRED_CODE_INSIGHTS_BINARY` points the package at another build. Other platforms fail with `code-insights-binary-missing`.
107
+
108
+ ### Errors and Cancelling
109
+
110
+ Failures reject with `CodeInsightsError` and a `code`: `not-a-repository`, `ref-not-found`, `git-unavailable`, `aborted`, `engine-failed` or `result-version-mismatch`. Passing an `AbortSignal` kills the engine process.
111
+
112
+ ### Logging
113
+
114
+ The package logs through `@trebired/logger-adapter` under `trebired.code-insights` and stays silent unless the application passes a logger.
115
+
116
+ ### Third-Party Code
117
+
118
+ The engine contains hyperpolyglot (MIT OR Apache-2.0), vendored with its detectors made public and shipped with its licence in `native/vendor/hyperpolyglot/LICENSE-MIT`, which carries GitHub Linguist's language data (MIT), and Tree-sitter with its TypeScript, JavaScript, Python, Rust and Go grammars (MIT). The client uses d3-force (ISC).
119
+
120
+ ## Public API
121
+
122
+ | Entry | Exports |
123
+ | --- | --- |
124
+ | `@trebired/code-insights` | `PACKAGE_NAME`, `RESULT_VERSION`, `SCAN_PHASES` and every result type |
125
+ | `@trebired/code-insights/server` | `scanRepository`, `detectLanguage`, `buildCodeMapData`, `resolveBinary`, `CodeInsightsError`, `BINARY_ENV` |
126
+ | `@trebired/code-insights/react` | `code_map`, `hotspot_list` |
127
+ | `@trebired/code-insights/client` | `bindCodeMaps`, `bindCodeMap`, `reloadCodeMaps` |
128
+
129
+ `detectLanguage({ path, content })` detects one file's language with the same rules as a scan. `reloadCodeMaps(scope)` fetches every bound map's data again at its current level, for after a rescan.
130
+
131
+ ## What It Does Not Do
132
+
133
+ This package does not:
134
+
135
+ - queue, schedule, store or cache scans;
136
+ - serve routes or check who may see a repository;
137
+ - run on macOS, Windows or musl Linux without a custom engine build;
138
+ - resolve calls through variables, interfaces, callbacks or dynamic dispatch;
139
+ - parse languages other than TypeScript, JavaScript, Python, Rust and Go for imports and calls;
140
+ - count vendored, generated, binary or documentation files in language totals.
@@ -0,0 +1,31 @@
1
+ import type { CodeMapData, CodeMapLevel } from "../shared/types.d.ts";
2
+ import { type ViewGraph } from "./model.js";
3
+ import { type Rendered } from "./render.js";
4
+ import { type Transform } from "./viewport.js";
5
+ type MapState = {
6
+ canvas: SVGSVGElement;
7
+ data: CodeMapData | null;
8
+ filter: string;
9
+ graph: ViewGraph | null;
10
+ level: CodeMapLevel;
11
+ open: Set<string>;
12
+ positions: Map<string, {
13
+ x: number;
14
+ y: number;
15
+ }>;
16
+ rendered: Rendered | null;
17
+ root: HTMLElement;
18
+ selected: string | null;
19
+ status: HTMLElement | null;
20
+ transform: Transform;
21
+ };
22
+ declare function refreshHighlight(state: MapState): void;
23
+ declare function draw(state: MapState, refit: boolean): void;
24
+ declare function load(state: MapState, level: CodeMapLevel): Promise<void>;
25
+ declare function onNodeClick(state: MapState, id: string): void;
26
+ declare function levelButtons(root: HTMLElement): HTMLElement[];
27
+ export { draw, levelButtons, load, onNodeClick, refreshHighlight };
28
+ export type { MapState };
29
+ export declare function createState(root: HTMLElement, canvas: SVGSVGElement): MapState;
30
+ export declare function bindState(state: MapState): void;
31
+ //# sourceMappingURL=controller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../../../src/client/controller.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE/D,OAAO,EAAwB,KAAK,SAAS,EAAE,MAAM,YAAY,CAAC;AAClE,OAAO,EAAkC,KAAK,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5E,OAAO,EAA2B,KAAK,SAAS,EAAE,MAAM,eAAe,CAAC;AAExE,KAAK,QAAQ,GAAG;IACd,MAAM,EAAE,aAAa,CAAC;IACtB,IAAI,EAAE,WAAW,GAAG,IAAI,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,SAAS,GAAG,IAAI,CAAC;IACxB,KAAK,EAAE,YAAY,CAAC;IACpB,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAClB,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE;QAAC,CAAC,EAAC,MAAM,CAAC;QAAA,CAAC,EAAC,MAAM,CAAA;KAAC,CAAC,CAAC;IAC5C,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAAC;IAC1B,IAAI,EAAE,WAAW,CAAC;IAClB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,WAAW,GAAG,IAAI,CAAC;IAC3B,SAAS,EAAE,SAAS,CAAC;CACtB,CAAC;AA8BF,iBAAS,gBAAgB,CAAC,KAAK,EAAE,QAAQ,QAKxC;AAED,iBAAS,IAAI,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,QAe5C;AAED,iBAAe,IAAI,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,YAAY,iBAqBvD;AAYD,iBAAS,WAAW,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,QAY/C;AAED,iBAAS,YAAY,CAAC,IAAI,EAAE,WAAW,GAAG,WAAW,EAAE,CAOtD;AAED,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,WAAW,EAAE,gBAAgB,EAAE,CAAC;AACnE,YAAY,EAAE,QAAQ,EAAE,CAAC;AAEzB,wBAAgB,WAAW,CAAC,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,aAAa,GAAG,QAAQ,CAO9E;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,QAAQ,QAOxC"}
@@ -0,0 +1,136 @@
1
+ import { copyFor } from "../shared/copy.js";
2
+ import { layout } from "./layout.js";
3
+ import { buildView, clusterId } from "./model.js";
4
+ import { highlight, render, scaleLabels } from "./render.js";
5
+ import { apply, bindZoomPan, fit } from "./viewport.js";
6
+ function copyOf(state) {
7
+ return copyFor(state.root.getAttribute("data-code-map-lang"));
8
+ }
9
+ function setStatus(state, text) {
10
+ if (state.status)
11
+ state.status.textContent = text;
12
+ }
13
+ function neighbours(state, id) {
14
+ const focus = new Set([id]);
15
+ for (const edge of state.graph?.edges || []) {
16
+ if (edge.source === id)
17
+ focus.add(edge.target);
18
+ if (edge.target === id)
19
+ focus.add(edge.source);
20
+ }
21
+ return focus;
22
+ }
23
+ function filterFocus(state) {
24
+ const query = state.filter.trim().toLowerCase();
25
+ if (!query || !state.data)
26
+ return null;
27
+ const focus = new Set();
28
+ for (const node of state.data.nodes) {
29
+ if (!node.label.toLowerCase().includes(query) && !node.path.toLowerCase().includes(query))
30
+ continue;
31
+ focus.add(state.open.has(node.group) ? node.id : clusterId(node.group));
32
+ }
33
+ return focus;
34
+ }
35
+ function refreshHighlight(state) {
36
+ if (!state.rendered)
37
+ return;
38
+ const focus = state.selected ? neighbours(state, state.selected) : filterFocus(state);
39
+ const members = state.graph ? state.graph.nodes.filter((node) => !node.cluster).length : 0;
40
+ highlight(state.rendered, focus, members <= 60);
41
+ }
42
+ function draw(state, refit) {
43
+ if (!state.data)
44
+ return;
45
+ const graph = buildView(state.data, state.open);
46
+ const box = state.canvas.getBoundingClientRect();
47
+ layout(graph, state.positions, box.width && box.height ? box.height / box.width : 1);
48
+ for (const node of graph.nodes)
49
+ state.positions.set(node.id, { x: node.x || 0, y: node.y || 0 });
50
+ state.graph = graph;
51
+ state.rendered = render(state.canvas, graph);
52
+ if (refit)
53
+ state.transform = fit(state.canvas, graph);
54
+ apply(state.rendered.viewport, state.transform);
55
+ scaleLabels(state.rendered, state.transform.k);
56
+ refreshHighlight(state);
57
+ const copy = copyOf(state);
58
+ const stats = `${state.data.nodes.length} ${copy("nodes")}, ${state.data.edges.length} ${copy("links")}`;
59
+ setStatus(state, state.data.nodes.length ? (state.data.truncated ? `${stats}. ${copy("truncated")}` : stats) : copy("empty"));
60
+ }
61
+ async function load(state, level) {
62
+ state.level = level;
63
+ state.selected = null;
64
+ state.open = new Set();
65
+ setStatus(state, copyOf(state)("loading"));
66
+ const url = String(state.root.getAttribute("data-code-map-url") || "");
67
+ try {
68
+ const response = await fetch(`${url}${url.includes("?") ? "&" : "?"}level=${level}`, { credentials: "same-origin", headers: { Accept: "application/json" } });
69
+ if (!response.ok)
70
+ throw new Error(String(response.status));
71
+ const body = await response.json();
72
+ state.data = (body && body.data) || body;
73
+ if (state.data && state.data.groups.length === 1)
74
+ state.open.add(state.data.groups[0].id);
75
+ draw(state, true);
76
+ }
77
+ catch {
78
+ state.data = null;
79
+ state.canvas.replaceChildren();
80
+ setStatus(state, copyOf(state)("failed"));
81
+ }
82
+ }
83
+ function navigate(state, id) {
84
+ const template = String(state.root.getAttribute("data-code-map-href") || "");
85
+ const node = state.graph?.nodes.find((item) => item.id === id);
86
+ if (!template || !node)
87
+ return;
88
+ const href = template.replace("{path}", encodeURIComponent(node.path)).replace("{line}", String(node.line || 1));
89
+ const detail = { href, line: node.line, path: node.path };
90
+ const event = new CustomEvent("code-map:open", { bubbles: true, cancelable: true, detail });
91
+ if (state.root.dispatchEvent(event))
92
+ window.location.assign(href);
93
+ }
94
+ function onNodeClick(state, id) {
95
+ const node = state.graph?.nodes.find((item) => item.id === id);
96
+ if (!node)
97
+ return;
98
+ if (node.cluster) {
99
+ state.open.add(node.group);
100
+ state.selected = null;
101
+ draw(state, true);
102
+ return;
103
+ }
104
+ if (state.selected === id)
105
+ return navigate(state, id);
106
+ state.selected = id;
107
+ refreshHighlight(state);
108
+ }
109
+ function levelButtons(root) {
110
+ let scope = root.parentElement;
111
+ for (let depth = 0; scope && depth < 8; depth += 1, scope = scope.parentElement) {
112
+ const found = Array.from(scope.querySelectorAll("[data-code-map-switch]"));
113
+ if (found.length)
114
+ return found;
115
+ }
116
+ return [];
117
+ }
118
+ export { draw, levelButtons, load, onNodeClick, refreshHighlight };
119
+ export function createState(root, canvas) {
120
+ return {
121
+ canvas, data: null, filter: "", graph: null,
122
+ level: root.getAttribute("data-code-map-level") === "function" ? "function" : "file",
123
+ open: new Set(), positions: new Map(), rendered: null, root, selected: null,
124
+ status: root.querySelector("[data-code-map-status]"), transform: { k: 1, x: 0, y: 0 },
125
+ };
126
+ }
127
+ export function bindState(state) {
128
+ bindZoomPan(state.canvas, () => state.transform, (next) => {
129
+ state.transform = next;
130
+ if (!state.rendered)
131
+ return;
132
+ apply(state.rendered.viewport, next);
133
+ scaleLabels(state.rendered, next.k);
134
+ });
135
+ }
136
+ //# sourceMappingURL=controller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"controller.js","sourceRoot":"","sources":["../../../src/client/controller.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ declare function bindCodeMap(root: HTMLElement): void;
2
+ declare function bindCodeMaps(scope?: ParentNode): void;
3
+ declare function reloadCodeMaps(scope?: ParentNode): void;
4
+ export { bindCodeMap, bindCodeMaps, reloadCodeMaps };
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/index.ts"],"names":[],"mappings":"AAkCA,iBAAS,WAAW,CAAC,IAAI,EAAE,WAAW,QAUrC;AAED,iBAAS,YAAY,CAAC,KAAK,GAAE,UAAqB,QAEjD;AAED,iBAAS,cAAc,CAAC,KAAK,GAAE,UAAqB,QAMnD;AAED,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,cAAc,EAAE,CAAC"}
@@ -0,0 +1,59 @@
1
+ import { bindState, createState, levelButtons, load, onNodeClick, refreshHighlight } from "./controller.js";
2
+ const bound = new WeakMap();
3
+ function bindClicks(state) {
4
+ let downAt = null;
5
+ state.canvas.addEventListener("pointerdown", (event) => { downAt = { x: event.clientX, y: event.clientY }; });
6
+ state.canvas.addEventListener("click", (event) => {
7
+ const moved = downAt && Math.hypot(event.clientX - downAt.x, event.clientY - downAt.y) > 4;
8
+ if (moved)
9
+ return;
10
+ const node = event.target.closest("[data-code-map-node]");
11
+ if (node)
12
+ return onNodeClick(state, String(node.getAttribute("data-code-map-node")));
13
+ state.selected = null;
14
+ refreshHighlight(state);
15
+ });
16
+ }
17
+ function bindControls(state) {
18
+ const filter = state.root.querySelector("[data-code-map-filter]");
19
+ filter?.addEventListener("input", () => {
20
+ state.filter = filter.value;
21
+ state.selected = null;
22
+ refreshHighlight(state);
23
+ });
24
+ const buttons = levelButtons(state.root);
25
+ for (const button of buttons) {
26
+ button.addEventListener("click", () => {
27
+ const level = button.getAttribute("data-code-map-switch") === "function" ? "function" : "file";
28
+ buttons.forEach((item) => item.setAttribute("aria-pressed", item === button ? "true" : "false"));
29
+ void load(state, level);
30
+ });
31
+ }
32
+ }
33
+ function bindCodeMap(root) {
34
+ if (bound.has(root))
35
+ return;
36
+ const canvas = root.querySelector("svg[data-code-map-canvas]");
37
+ if (!canvas)
38
+ return;
39
+ const state = createState(root, canvas);
40
+ bound.set(root, state);
41
+ bindState(state);
42
+ bindClicks(state);
43
+ bindControls(state);
44
+ void load(state, state.level);
45
+ }
46
+ function bindCodeMaps(scope = document) {
47
+ scope.querySelectorAll("[data-code-map-root]").forEach(bindCodeMap);
48
+ }
49
+ function reloadCodeMaps(scope = document) {
50
+ scope.querySelectorAll("[data-code-map-root]").forEach((root) => {
51
+ const state = bound.get(root);
52
+ if (state)
53
+ void load(state, state.level);
54
+ else
55
+ bindCodeMap(root);
56
+ });
57
+ }
58
+ export { bindCodeMap, bindCodeMaps, reloadCodeMaps };
59
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/client/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { ViewGraph, ViewNode } from "./model.js";
2
+ declare function radius(node: ViewNode): number;
3
+ declare function layout(graph: ViewGraph, previous: Map<string, {
4
+ x: number;
5
+ y: number;
6
+ }>, aspect?: number): void;
7
+ export { layout, radius };
8
+ //# sourceMappingURL=layout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../../../src/client/layout.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtD,iBAAS,MAAM,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAEtC;AAYD,iBAAS,MAAM,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE;IAAC,CAAC,EAAC,MAAM,CAAC;IAAA,CAAC,EAAC,MAAM,CAAA;CAAC,CAAC,EAAE,MAAM,SAAI,GAAG,IAAI,CAgB9F;AAED,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC"}
@@ -0,0 +1,30 @@
1
+ import { forceCenter, forceCollide, forceLink, forceManyBody, forceSimulation, forceX, forceY } from "d3-force";
2
+ function radius(node) {
3
+ return node.cluster ? 10 + Math.sqrt(node.count) * 2.4 : 4 + Math.min(10, Math.sqrt(node.size) / 2);
4
+ }
5
+ function seed(graph, previous) {
6
+ graph.nodes.forEach((node, index) => {
7
+ const known = previous.get(node.id) || previous.get(`group:${node.group}`);
8
+ const angle = index * 2.399963;
9
+ const spread = known ? 18 : 40 + Math.sqrt(index) * 30;
10
+ node.x = (known ? known.x : 0) + Math.cos(angle) * spread;
11
+ node.y = (known ? known.y : 0) + Math.sin(angle) * spread;
12
+ });
13
+ }
14
+ function layout(graph, previous, aspect = 1) {
15
+ seed(graph, previous);
16
+ const links = graph.edges.map((edge) => ({ ...edge }));
17
+ const simulation = forceSimulation(graph.nodes)
18
+ .force("link", forceLink(links).id((node) => node.id).distance((link) => 56 + radius(link.source) + radius(link.target)).strength(0.2))
19
+ .force("charge", forceManyBody().strength((node) => (node.cluster ? -320 : -150)))
20
+ .force("collide", forceCollide((node) => radius(node) + (node.cluster ? 26 : 22)).iterations(2))
21
+ .force("x", forceX(0).strength(0.04 * Math.max(1, aspect)))
22
+ .force("y", forceY(0).strength(0.04 / Math.max(1, 1 / aspect)))
23
+ .force("center", forceCenter(0, 0))
24
+ .stop();
25
+ const ticks = graph.nodes.length > 600 ? 160 : 300;
26
+ for (let tick = 0; tick < ticks; tick += 1)
27
+ simulation.tick();
28
+ }
29
+ export { layout, radius };
30
+ //# sourceMappingURL=layout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layout.js","sourceRoot":"","sources":["../../../src/client/layout.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import type { CodeMapData } from "../shared/types.d.ts";
2
+ type ViewNode = {
3
+ cluster: boolean;
4
+ count: number;
5
+ group: string;
6
+ id: string;
7
+ label: string;
8
+ line: number | null;
9
+ path: string;
10
+ size: number;
11
+ x?: number;
12
+ y?: number;
13
+ };
14
+ type ViewEdge = {
15
+ source: string;
16
+ target: string;
17
+ weight: number;
18
+ };
19
+ type ViewGraph = {
20
+ edges: ViewEdge[];
21
+ nodes: ViewNode[];
22
+ };
23
+ declare function clusterId(group: string): string;
24
+ declare function buildView(data: CodeMapData, open: Set<string>): ViewGraph;
25
+ export { buildView, clusterId };
26
+ export type { ViewEdge, ViewGraph, ViewNode };
27
+ //# sourceMappingURL=model.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../../src/client/model.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAe,MAAM,eAAe,CAAC;AAE9D,KAAK,QAAQ,GAAG;IACd,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,CAAC,CAAC,EAAE,MAAM,CAAC;CACZ,CAAC;AAEF,KAAK,QAAQ,GAAG;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,KAAK,SAAS,GAAG;IACf,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,KAAK,EAAE,QAAQ,EAAE,CAAC;CACnB,CAAC;AAIF,iBAAS,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAExC;AA0BD,iBAAS,SAAS,CAAC,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,SAAS,CA4BlE;AAED,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC;AAChC,YAAY,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC"}
@@ -0,0 +1,57 @@
1
+ const MAX_OPEN_GROUP_NODES = 400;
2
+ function clusterId(group) {
3
+ return `group:${group}`;
4
+ }
5
+ function clusterNode(group) {
6
+ const id = clusterId(group.id);
7
+ return { cluster: true, count: group.size, group: group.id, id, label: group.label, line: null, path: group.id, size: group.size };
8
+ }
9
+ function memberNode(node) {
10
+ return { cluster: false, count: 1, group: node.group, id: node.id, label: node.label, line: node.line, path: node.path, size: node.size };
11
+ }
12
+ function degreeOf(data) {
13
+ const degree = new Map();
14
+ for (const edge of data.edges) {
15
+ degree.set(edge.source, (degree.get(edge.source) || 0) + 1);
16
+ degree.set(edge.target, (degree.get(edge.target) || 0) + 1);
17
+ }
18
+ return degree;
19
+ }
20
+ function openMembers(data, group, degree) {
21
+ const members = data.nodes.filter((node) => node.group === group);
22
+ if (members.length <= MAX_OPEN_GROUP_NODES)
23
+ return members;
24
+ return members.sort((left, right) => (degree.get(right.id) || 0) - (degree.get(left.id) || 0)).slice(0, MAX_OPEN_GROUP_NODES);
25
+ }
26
+ function buildView(data, open) {
27
+ const degree = degreeOf(data);
28
+ const visible = new Map();
29
+ const nodes = [];
30
+ for (const group of data.groups) {
31
+ if (!open.has(group.id)) {
32
+ nodes.push(clusterNode(group));
33
+ continue;
34
+ }
35
+ for (const member of openMembers(data, group.id, degree)) {
36
+ nodes.push(memberNode(member));
37
+ visible.set(member.id, member.id);
38
+ }
39
+ }
40
+ const owner = new Map(data.nodes.map((node) => [node.id, visible.get(node.id) || (open.has(node.group) ? "" : clusterId(node.group))]));
41
+ const weights = new Map();
42
+ for (const edge of data.edges) {
43
+ const source = owner.get(edge.source);
44
+ const target = owner.get(edge.target);
45
+ if (!source || !target || source === target)
46
+ continue;
47
+ const key = `${source}\u0000${target}`;
48
+ weights.set(key, (weights.get(key) || 0) + edge.weight);
49
+ }
50
+ const edges = [...weights.entries()].map(([key, weight]) => {
51
+ const [source, target] = key.split("\u0000");
52
+ return { source, target, weight };
53
+ });
54
+ return { edges, nodes };
55
+ }
56
+ export { buildView, clusterId };
57
+ //# sourceMappingURL=model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model.js","sourceRoot":"","sources":["../../../src/client/model.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import type { ViewGraph, ViewNode } from "./model.js";
2
+ type Rendered = {
3
+ edges: {
4
+ element: SVGLineElement;
5
+ source: string;
6
+ target: string;
7
+ }[];
8
+ nodes: Map<string, {
9
+ element: SVGGElement;
10
+ label: SVGTextElement;
11
+ node: ViewNode;
12
+ }>;
13
+ viewport: SVGGElement;
14
+ };
15
+ declare function render(canvas: SVGSVGElement, graph: ViewGraph): Rendered;
16
+ declare function highlight(rendered: Rendered, focus: Set<string> | null, labelAll: boolean): void;
17
+ declare function scaleLabels(rendered: Rendered, zoom: number): void;
18
+ export { highlight, render, scaleLabels };
19
+ export type { Rendered };
20
+ //# sourceMappingURL=render.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../../src/client/render.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAItD,KAAK,QAAQ,GAAG;IACd,KAAK,EAAE;QAAE,OAAO,EAAE,cAAc,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACrE,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE;QAAC,OAAO,EAAC,WAAW,CAAC;QAAA,KAAK,EAAC,cAAc,CAAC;QAAA,IAAI,EAAC,QAAQ,CAAA;KAAC,CAAC,CAAC;IAC7E,QAAQ,EAAE,WAAW,CAAC;CACvB,CAAC;AA0DF,iBAAS,MAAM,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,SAAS,GAAG,QAAQ,CAkBjE;AAED,iBAAS,SAAS,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,GAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,QAUhF;AAED,iBAAS,WAAW,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,QAMpD;AAED,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;AAC1C,YAAY,EAAE,QAAQ,EAAE,CAAC"}