@ttsc/graph 0.16.4 → 0.16.5

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 (109) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +24 -53
  3. package/lib/TtscGraphApplication.js +46 -0
  4. package/lib/TtscGraphApplication.js.map +1 -0
  5. package/lib/index.js +31 -108
  6. package/lib/index.js.map +1 -1
  7. package/lib/model/TtscGraphMemory.js +185 -0
  8. package/lib/model/TtscGraphMemory.js.map +1 -0
  9. package/lib/model/loadGraph.js +418 -0
  10. package/lib/model/loadGraph.js.map +1 -0
  11. package/lib/reduce.js +101 -0
  12. package/lib/reduce.js.map +1 -0
  13. package/lib/resolveGraphBinary.js +42 -0
  14. package/lib/resolveGraphBinary.js.map +1 -0
  15. package/lib/server/createServer.js +1227 -0
  16. package/lib/server/createServer.js.map +1 -0
  17. package/lib/server/instructions.js +32 -0
  18. package/lib/server/instructions.js.map +1 -0
  19. package/lib/server/resolveHandle.js +25 -0
  20. package/lib/server/resolveHandle.js.map +1 -0
  21. package/lib/server/runExpand.js +177 -0
  22. package/lib/server/runExpand.js.map +1 -0
  23. package/lib/server/runIndex.js +146 -0
  24. package/lib/server/runIndex.js.map +1 -0
  25. package/lib/server/runOverview.js +150 -0
  26. package/lib/server/runOverview.js.map +1 -0
  27. package/lib/server/runQuery.js +147 -0
  28. package/lib/server/runQuery.js.map +1 -0
  29. package/lib/server/runTrace.js +219 -0
  30. package/lib/server/runTrace.js.map +1 -0
  31. package/lib/server/startServer.js +21 -0
  32. package/lib/server/startServer.js.map +1 -0
  33. package/lib/structures/ITtscGraphApplication.js +3 -0
  34. package/lib/structures/ITtscGraphApplication.js.map +1 -0
  35. package/lib/structures/ITtscGraphDecorator.js +3 -0
  36. package/lib/structures/ITtscGraphDecorator.js.map +1 -0
  37. package/lib/structures/ITtscGraphDiagnostic.js +3 -0
  38. package/lib/structures/ITtscGraphDiagnostic.js.map +1 -0
  39. package/lib/structures/ITtscGraphDump.js +3 -0
  40. package/lib/structures/ITtscGraphDump.js.map +1 -0
  41. package/lib/structures/ITtscGraphEdge.js +3 -0
  42. package/lib/structures/ITtscGraphEdge.js.map +1 -0
  43. package/lib/structures/ITtscGraphEvidence.js +3 -0
  44. package/lib/structures/ITtscGraphEvidence.js.map +1 -0
  45. package/lib/structures/ITtscGraphExpand.js +3 -0
  46. package/lib/structures/ITtscGraphExpand.js.map +1 -0
  47. package/lib/structures/ITtscGraphIndex.js +3 -0
  48. package/lib/structures/ITtscGraphIndex.js.map +1 -0
  49. package/lib/structures/ITtscGraphNode.js +3 -0
  50. package/lib/structures/ITtscGraphNode.js.map +1 -0
  51. package/lib/structures/ITtscGraphOverview.js +3 -0
  52. package/lib/structures/ITtscGraphOverview.js.map +1 -0
  53. package/lib/structures/ITtscGraphQuery.js +3 -0
  54. package/lib/structures/ITtscGraphQuery.js.map +1 -0
  55. package/lib/structures/ITtscGraphTrace.js +3 -0
  56. package/lib/structures/ITtscGraphTrace.js.map +1 -0
  57. package/lib/structures/TtscGraphEdgeKind.js +3 -0
  58. package/lib/structures/TtscGraphEdgeKind.js.map +1 -0
  59. package/lib/structures/TtscGraphNodeKind.js +3 -0
  60. package/lib/structures/TtscGraphNodeKind.js.map +1 -0
  61. package/lib/structures/TtscGraphNodeModifier.js +3 -0
  62. package/lib/structures/TtscGraphNodeModifier.js.map +1 -0
  63. package/lib/structures/index.js +37 -0
  64. package/lib/structures/index.js.map +1 -0
  65. package/lib/view.js +140 -0
  66. package/lib/view.js.map +1 -0
  67. package/lib/viewer/index.html +123 -0
  68. package/lib/viewer/viewer.js +4610 -0
  69. package/package.json +17 -4
  70. package/src/TtscGraphApplication.ts +57 -0
  71. package/src/index.ts +40 -126
  72. package/src/model/TtscGraphMemory.ts +204 -0
  73. package/src/model/loadGraph.ts +85 -0
  74. package/src/reduce.ts +165 -0
  75. package/src/resolveGraphBinary.ts +40 -0
  76. package/src/server/createServer.ts +104 -0
  77. package/src/server/instructions.ts +28 -0
  78. package/src/server/resolveHandle.ts +34 -0
  79. package/src/server/runExpand.ts +186 -0
  80. package/src/server/runIndex.ts +181 -0
  81. package/src/server/runOverview.ts +154 -0
  82. package/src/server/runQuery.ts +150 -0
  83. package/src/server/runTrace.ts +233 -0
  84. package/src/server/startServer.ts +25 -0
  85. package/src/structures/ITtscGraphApplication.ts +68 -0
  86. package/src/structures/ITtscGraphDecorator.ts +33 -0
  87. package/src/structures/ITtscGraphDiagnostic.ts +34 -0
  88. package/src/structures/ITtscGraphDump.ts +35 -0
  89. package/src/structures/ITtscGraphEdge.ts +24 -0
  90. package/src/structures/ITtscGraphEvidence.ts +29 -0
  91. package/src/structures/ITtscGraphExpand.ts +85 -0
  92. package/src/structures/ITtscGraphIndex.ts +100 -0
  93. package/src/structures/ITtscGraphNode.ts +64 -0
  94. package/src/structures/ITtscGraphOverview.ts +79 -0
  95. package/src/structures/ITtscGraphQuery.ts +49 -0
  96. package/src/structures/ITtscGraphTrace.ts +97 -0
  97. package/src/structures/TtscGraphEdgeKind.ts +23 -0
  98. package/src/structures/TtscGraphNodeKind.ts +26 -0
  99. package/src/structures/TtscGraphNodeModifier.ts +19 -0
  100. package/src/structures/index.ts +21 -0
  101. package/src/view.ts +155 -0
  102. package/src/viewer/index.html +123 -0
  103. package/src/viewer/main.ts +209 -0
  104. package/lib/bin.d.ts +0 -2
  105. package/lib/diagnostics.d.ts +0 -23
  106. package/lib/diagnostics.js +0 -84
  107. package/lib/diagnostics.js.map +0 -1
  108. package/lib/index.d.ts +0 -29
  109. package/src/diagnostics.ts +0 -93
@@ -0,0 +1,209 @@
1
+ // Vanilla 3D code-graph viewer bundled into @ttsc/graph by esbuild and served by
2
+ // `ttsc-graph view`. Mirrors website/src/components/graph/GraphViewer3D.tsx, but
3
+ // standalone (no React): fetch the reduced graph the CLI serves, render it on
4
+ // three.js + three-forcegraph, and let the user orbit it.
5
+ import * as THREE from "three";
6
+ import ThreeForceGraph from "three-forcegraph";
7
+ import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
8
+
9
+ interface GNode {
10
+ id: string;
11
+ name: string;
12
+ kind: string;
13
+ file: string;
14
+ degree: number;
15
+ }
16
+
17
+ interface GLink {
18
+ source: string;
19
+ target: string;
20
+ kind: string;
21
+ }
22
+
23
+ interface Payload {
24
+ project: string;
25
+ counts: { nodes: number; links: number };
26
+ nodes: GNode[];
27
+ links: GLink[];
28
+ }
29
+
30
+ const NODE_COLORS: Record<string, string> = {
31
+ class: "#36e2ee",
32
+ interface: "#6ea8ff",
33
+ function: "#3fb950",
34
+ method: "#2bb673",
35
+ type: "#f5b042",
36
+ enum: "#c792ea",
37
+ variable: "#8b97a8",
38
+ };
39
+
40
+ const LINK_COLORS: Record<string, string> = {
41
+ "value-call": "#3fb950",
42
+ "type-ref": "#f5b042",
43
+ heritage: "#6ea8ff",
44
+ };
45
+
46
+ function escapeHtml(value: string): string {
47
+ return value
48
+ .replace(/&/g, "&amp;")
49
+ .replace(/</g, "&lt;")
50
+ .replace(/>/g, "&gt;");
51
+ }
52
+
53
+ function setText(id: string, text: string): void {
54
+ const el = document.getElementById(id);
55
+ if (el) el.textContent = text;
56
+ }
57
+
58
+ async function main(): Promise<void> {
59
+ const container = document.getElementById("graph");
60
+ if (!container) return;
61
+
62
+ let data: Payload;
63
+ try {
64
+ const res = await fetch("graph.json");
65
+ if (!res.ok) throw new Error(`HTTP ${res.status}`);
66
+ data = (await res.json()) as Payload;
67
+ } catch (err) {
68
+ container.textContent = `could not load the graph (${String(err)})`;
69
+ return;
70
+ }
71
+
72
+ if (data.project) setText("project", data.project);
73
+ setText(
74
+ "counts",
75
+ `${data.nodes.length.toLocaleString()} nodes · ${data.links.length.toLocaleString()} edges`,
76
+ );
77
+
78
+ const width = container.clientWidth || 800;
79
+ const height = container.clientHeight || 600;
80
+
81
+ const scene = new THREE.Scene();
82
+ scene.background = new THREE.Color(0x0a0c10);
83
+ scene.add(new THREE.AmbientLight(0xffffff, 2));
84
+ const keyLight = new THREE.DirectionalLight(0xffffff, 0.8);
85
+ keyLight.position.set(1, 1, 1);
86
+ scene.add(keyLight);
87
+
88
+ const camera = new THREE.PerspectiveCamera(50, width / height, 0.1, 1e6);
89
+ camera.position.set(0, 0, 320);
90
+
91
+ const renderer = new THREE.WebGLRenderer({ antialias: true });
92
+ renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
93
+ renderer.setSize(width, height);
94
+ container.appendChild(renderer.domElement);
95
+
96
+ const controls = new OrbitControls(camera, renderer.domElement);
97
+ controls.enableDamping = true;
98
+ controls.dampingFactor = 0.18;
99
+
100
+ const graph = new ThreeForceGraph<GNode, GLink>()
101
+ .nodeId("id")
102
+ .nodeRelSize(4)
103
+ .nodeResolution(12)
104
+ .nodeOpacity(0.95)
105
+ .nodeVal((node) => 1 + Math.sqrt(node.degree))
106
+ .nodeColor((node) => NODE_COLORS[node.kind] ?? "#8b97a8")
107
+ .linkColor((link) => LINK_COLORS[link.kind] ?? "#ffffff55")
108
+ .linkOpacity(0.4)
109
+ .linkWidth(0)
110
+ .warmupTicks(20)
111
+ .cooldownTicks(160);
112
+ scene.add(graph);
113
+
114
+ const fit = (): void => {
115
+ const b = graph.getGraphBbox();
116
+ if (!b) return;
117
+ const cx = (b.x[0] + b.x[1]) / 2;
118
+ const cy = (b.y[0] + b.y[1]) / 2;
119
+ const cz = (b.z[0] + b.z[1]) / 2;
120
+ const radius = Math.max(
121
+ (b.x[1] - b.x[0]) / 2,
122
+ (b.y[1] - b.y[0]) / 2,
123
+ (b.z[1] - b.z[0]) / 2,
124
+ 10,
125
+ );
126
+ const dist = radius * 2.6;
127
+ camera.position.set(cx + dist * 0.5, cy + dist * 0.32, cz + dist * 0.8);
128
+ camera.near = Math.max(0.1, dist / 200);
129
+ camera.far = dist * 20;
130
+ camera.updateProjectionMatrix();
131
+ controls.target.set(cx, cy, cz);
132
+ controls.update();
133
+ };
134
+ // `?static` settles the layout, frames it, then stops the render loop, for a
135
+ // low-CPU snapshot (and headless screenshots). Default mode keeps animating.
136
+ const staticMode = new URLSearchParams(window.location.search).has("static");
137
+ let stopAtFrame = -1;
138
+ let frame = 0;
139
+ graph.onEngineStop(() => {
140
+ fit();
141
+ if (staticMode && stopAtFrame < 0) stopAtFrame = frame + 4;
142
+ });
143
+
144
+ // Hover tooltip via raycasting the node objects (each carries __data).
145
+ const tooltip = document.createElement("div");
146
+ tooltip.className = "tooltip";
147
+ container.appendChild(tooltip);
148
+ const raycaster = new THREE.Raycaster();
149
+ const pointer = new THREE.Vector2();
150
+ renderer.domElement.addEventListener("pointermove", (event) => {
151
+ const rect = renderer.domElement.getBoundingClientRect();
152
+ pointer.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;
153
+ pointer.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;
154
+ raycaster.setFromCamera(pointer, camera);
155
+ const hits = raycaster.intersectObjects(graph.children, true);
156
+ let node: GNode | null = null;
157
+ for (const hit of hits) {
158
+ let obj: THREE.Object3D | null = hit.object;
159
+ while (obj) {
160
+ const meta = obj as { __graphObjType?: string; __data?: unknown };
161
+ if (meta.__graphObjType === "node" && meta.__data) {
162
+ node = meta.__data as GNode;
163
+ break;
164
+ }
165
+ obj = obj.parent;
166
+ }
167
+ if (node) break;
168
+ }
169
+ if (!node) {
170
+ tooltip.style.display = "none";
171
+ return;
172
+ }
173
+ tooltip.style.display = "block";
174
+ tooltip.style.left = `${event.clientX - rect.left + 12}px`;
175
+ tooltip.style.top = `${event.clientY - rect.top + 12}px`;
176
+ tooltip.innerHTML =
177
+ `${escapeHtml(node.name)}<br/>` +
178
+ `<span class="muted">${escapeHtml(node.kind)} · ${escapeHtml(node.file)}</span>`;
179
+ });
180
+ renderer.domElement.addEventListener("pointerleave", () => {
181
+ tooltip.style.display = "none";
182
+ });
183
+
184
+ const animate = (): void => {
185
+ if (stopAtFrame >= 0 && frame > stopAtFrame) {
186
+ renderer.render(scene, camera);
187
+ return;
188
+ }
189
+ requestAnimationFrame(animate);
190
+ graph.tickFrame();
191
+ controls.update();
192
+ renderer.render(scene, camera);
193
+ frame++;
194
+ };
195
+ animate();
196
+
197
+ window.addEventListener("resize", () => {
198
+ const w = container.clientWidth || width;
199
+ const h = container.clientHeight || height;
200
+ camera.aspect = w / h;
201
+ camera.updateProjectionMatrix();
202
+ renderer.setSize(w, h);
203
+ });
204
+
205
+ graph.graphData({ nodes: data.nodes, links: data.links });
206
+ window.setTimeout(fit, 700);
207
+ }
208
+
209
+ void main();
package/lib/bin.d.ts DELETED
@@ -1,2 +0,0 @@
1
- #!/usr/bin/env node
2
- export {};
@@ -1,23 +0,0 @@
1
- /**
2
- * Background worker that computes the project's plugin diagnostics and writes
3
- * them where the ttscgraph server reads them.
4
- *
5
- * The graph binary runs only the TypeScript semantic pass. Everything a plugin
6
- * adds — `@ttsc/lint` rule violations and transform-plugin (typia, nestia, …)
7
- * findings — comes from `ttsc`'s own check, which runs whatever plugins the
8
- * project configured. This worker invokes that check through the public
9
- * `TtscCompiler`, so nothing here is specific to any plugin: it forwards
10
- * whatever diagnostics ttsc produces.
11
- *
12
- * A native plugin reports its findings with a string `code` (tsc uses numeric
13
- * codes), so the string-coded diagnostics are exactly the plugin/lint set the
14
- * graph does not already have. They are serialized with code 0 and the rule
15
- * folded into the message, the shape ttscgraph's injected-diagnostics provider
16
- * consumes.
17
- *
18
- * Every failure is swallowed: a missing `ttsc`, a go toolchain that cannot
19
- * build a plugin, a project that does not compile — any of these simply leaves
20
- * no file, and the graph shows its tsc diagnostics alone. The worker must never
21
- * be able to break the server it feeds.
22
- */
23
- export declare function runDiagnosticsWorker(argv?: readonly string[]): void;
@@ -1,84 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.runDiagnosticsWorker = runDiagnosticsWorker;
7
- const node_fs_1 = __importDefault(require("node:fs"));
8
- const node_module_1 = require("node:module");
9
- /**
10
- * Background worker that computes the project's plugin diagnostics and writes
11
- * them where the ttscgraph server reads them.
12
- *
13
- * The graph binary runs only the TypeScript semantic pass. Everything a plugin
14
- * adds — `@ttsc/lint` rule violations and transform-plugin (typia, nestia, …)
15
- * findings — comes from `ttsc`'s own check, which runs whatever plugins the
16
- * project configured. This worker invokes that check through the public
17
- * `TtscCompiler`, so nothing here is specific to any plugin: it forwards
18
- * whatever diagnostics ttsc produces.
19
- *
20
- * A native plugin reports its findings with a string `code` (tsc uses numeric
21
- * codes), so the string-coded diagnostics are exactly the plugin/lint set the
22
- * graph does not already have. They are serialized with code 0 and the rule
23
- * folded into the message, the shape ttscgraph's injected-diagnostics provider
24
- * consumes.
25
- *
26
- * Every failure is swallowed: a missing `ttsc`, a go toolchain that cannot
27
- * build a plugin, a project that does not compile — any of these simply leaves
28
- * no file, and the graph shows its tsc diagnostics alone. The worker must never
29
- * be able to break the server it feeds.
30
- */
31
- function runDiagnosticsWorker(argv = process.argv.slice(2)) {
32
- const [cwd, tsconfig, outPath] = argv;
33
- if (!cwd || !outPath) {
34
- return;
35
- }
36
- try {
37
- const ttscPackageJson = require.resolve("ttsc/package.json", {
38
- paths: [cwd],
39
- });
40
- const fromProject = (0, node_module_1.createRequire)(ttscPackageJson);
41
- const { TtscCompiler } = fromProject("ttsc");
42
- const result = new TtscCompiler({
43
- cwd,
44
- tsconfig: tsconfig || undefined,
45
- }).compile();
46
- const raw = result &&
47
- typeof result === "object" &&
48
- Array.isArray(result.diagnostics)
49
- ? (result.diagnostics)
50
- : [];
51
- const out = raw
52
- .filter((d) => typeof d.file === "string" &&
53
- (typeof d.line === "number" || typeof d.start === "number"))
54
- .map((d) => ({
55
- file: d.file,
56
- // A byte offset when the structured lane gives one; otherwise null and
57
- // the server attributes by line. @ttsc/lint and transform plugins reach
58
- // the result through ttsc's text banner, which carries a line but no
59
- // offset.
60
- start: typeof d.start === "number" ? d.start : null,
61
- line: typeof d.line === "number" ? d.line : 1,
62
- column: typeof d.character === "number" ? d.character : 1,
63
- // tsc diagnostics use numeric codes; @ttsc/lint and native plugins hash
64
- // their rule to a code >= 9000. A rare string id is marked non-tsc (the
65
- // server then drops the "TS" prefix); the rule name travels in the
66
- // message regardless.
67
- code: typeof d.code === "number" ? d.code : 9000,
68
- message: String(d.messageText ?? ""),
69
- }));
70
- // Atomic publish: write to a sibling temp file and rename, so the server
71
- // never reads a half-written file (a partial read would drop every finding
72
- // for that query).
73
- const tmp = `${outPath}.${process.pid}.tmp`;
74
- node_fs_1.default.writeFileSync(tmp, JSON.stringify(out));
75
- node_fs_1.default.renameSync(tmp, outPath);
76
- }
77
- catch {
78
- // Resilient by contract: no file means the graph shows tsc-only diagnostics.
79
- }
80
- }
81
- if (require.main === module) {
82
- runDiagnosticsWorker();
83
- }
84
- //# sourceMappingURL=diagnostics.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"diagnostics.js","sourceRoot":"","sources":["../src/diagnostics.ts"],"names":[],"mappings":";;;;;;AAAA,sDAAyB;AACzB,6CAA4C;AAE5C;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,8BACE,IAAI,GAAsB,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IAE/C,MAAM,CAAC,GAAG,EAAE,QAAQ,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACtC,IAAI,CAAC,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;QACrB,OAAO;IACT,CAAC;IACD,IAAI,CAAC;QACH,MAAM,eAAe,GAAG,OAAO,CAAC,OAAO,CAAC,mBAAmB,EAAE;YAC3D,KAAK,EAAE,CAAC,GAAG,CAAC;SACb,CAAC,CAAC;QACH,MAAM,WAAW,GAAG,IAAA,2BAAa,EAAC,eAAe,CAAC,CAAC;QACnD,MAAM,EAAE,YAAY,EAAE,GAAG,WAAW,CAAC,MAAM,CAK1C,CAAC;QAEF,MAAM,MAAM,GAAG,IAAI,YAAY,CAAC;YAC9B,GAAG;YACH,QAAQ,EAAE,QAAQ,IAAI,SAAS;SAChC,CAAC,CAAC,OAAO,EAAE,CAAC;QAEb,MAAM,GAAG,GACP,MAAM;YACN,OAAO,MAAM,KAAK,QAAQ;YAC1B,KAAK,CAAC,OAAO,CAAE,MAAoC,CAAC,WAAW,CAAC;YAC9D,CAAC,CAAC,CAAE,MAAqD,CAAC,WAAW,CAAC;YACtE,CAAC,CAAC,EAAE,CAAC;QAET,MAAM,GAAG,GAAG,GAAG;aACZ,MAAM,CACL,CAAC,CAAC,EAAE,EAAE,CACJ,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ;YAC1B,CAAC,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,KAAK,KAAK,QAAQ,CAAC,CAC9D;aACA,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACX,IAAI,EAAE,CAAC,CAAC,IAAc;YACtB,uEAAuE;YACvE,wEAAwE;YACxE,qEAAqE;YACrE,UAAU;YACV,KAAK,EAAE,OAAO,CAAC,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAE,CAAC,CAAC,KAAgB,CAAC,CAAC,CAAC,IAAI;YAC/D,IAAI,EAAE,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAE,CAAC,CAAC,IAAe,CAAC,CAAC,CAAC,CAAC;YACzD,MAAM,EAAE,OAAO,CAAC,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAE,CAAC,CAAC,SAAoB,CAAC,CAAC,CAAC,CAAC;YACrE,wEAAwE;YACxE,wEAAwE;YACxE,mEAAmE;YACnE,sBAAsB;YACtB,IAAI,EAAE,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAE,CAAC,CAAC,IAAe,CAAC,CAAC,CAAC,IAAI;YAC5D,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,WAAW,IAAI,EAAE,CAAC;SACrC,CAAC,CAAC,CAAC;QAEN,yEAAyE;QACzE,2EAA2E;QAC3E,mBAAmB;QACnB,MAAM,GAAG,GAAG,GAAG,OAAO,IAAI,OAAO,CAAC,GAAG,MAAM,CAAC;QAC5C,iBAAE,CAAC,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;QAC3C,iBAAE,CAAC,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAC9B,CAAC;IAAC,MAAM,CAAC;QACP,6EAA6E;IAC/E,CAAC;AACH,CAAC;AAED,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;IAC5B,oBAAoB,EAAE,CAAC;AACzB,CAAC"}
package/lib/index.d.ts DELETED
@@ -1,29 +0,0 @@
1
- /**
2
- * Resolve the per-platform `ttscgraph` MCP server binary, or `null` when it
3
- * cannot be located.
4
- *
5
- * `ttsc` is a peer the user installs alongside `@ttsc/graph` (not a dependency
6
- * of this launcher), so resolution starts from the user's project, not from
7
- * this package's own tree.
8
- *
9
- * Resolution order:
10
- *
11
- * 1. `TTSC_GRAPH_BINARY` env var, when set to an absolute path.
12
- * 2. The per-platform npm package `@ttsc/<platform>-<arch>/bin/ttscgraph[.exe]`.
13
- * That package carries `ttsc`, `ttscserver`, and `ttscgraph` together and is
14
- * an `optionalDependency` of `ttsc`, so it is resolved from `ttsc`'s
15
- * location — found from `process.cwd()` (the project where the agent ran the
16
- * server).
17
- */
18
- export declare function resolveGraphBinary(env?: NodeJS.ProcessEnv, cwd?: string): string | null;
19
- /**
20
- * Spawn the resident MCP server, inheriting stdio so the agent's MCP client
21
- * speaks JSON-RPC to it directly over this process's stdin/stdout. Returns the
22
- * child's exit code.
23
- *
24
- * Before spawning, it kicks off the background diagnostics worker (except in
25
- * `--connect` proxy mode) and points the server at its output file, so a
26
- * plugin-using project's lint and transform-plugin diagnostics fuse onto the
27
- * graph without blocking startup.
28
- */
29
- export declare function runGraph(argv?: readonly string[]): number;
@@ -1,93 +0,0 @@
1
- import fs from "node:fs";
2
- import { createRequire } from "node:module";
3
-
4
- /**
5
- * Background worker that computes the project's plugin diagnostics and writes
6
- * them where the ttscgraph server reads them.
7
- *
8
- * The graph binary runs only the TypeScript semantic pass. Everything a plugin
9
- * adds — `@ttsc/lint` rule violations and transform-plugin (typia, nestia, …)
10
- * findings — comes from `ttsc`'s own check, which runs whatever plugins the
11
- * project configured. This worker invokes that check through the public
12
- * `TtscCompiler`, so nothing here is specific to any plugin: it forwards
13
- * whatever diagnostics ttsc produces.
14
- *
15
- * A native plugin reports its findings with a string `code` (tsc uses numeric
16
- * codes), so the string-coded diagnostics are exactly the plugin/lint set the
17
- * graph does not already have. They are serialized with code 0 and the rule
18
- * folded into the message, the shape ttscgraph's injected-diagnostics provider
19
- * consumes.
20
- *
21
- * Every failure is swallowed: a missing `ttsc`, a go toolchain that cannot
22
- * build a plugin, a project that does not compile — any of these simply leaves
23
- * no file, and the graph shows its tsc diagnostics alone. The worker must never
24
- * be able to break the server it feeds.
25
- */
26
- export function runDiagnosticsWorker(
27
- argv: readonly string[] = process.argv.slice(2),
28
- ): void {
29
- const [cwd, tsconfig, outPath] = argv;
30
- if (!cwd || !outPath) {
31
- return;
32
- }
33
- try {
34
- const ttscPackageJson = require.resolve("ttsc/package.json", {
35
- paths: [cwd],
36
- });
37
- const fromProject = createRequire(ttscPackageJson);
38
- const { TtscCompiler } = fromProject("ttsc") as {
39
- TtscCompiler: new (context: {
40
- cwd: string;
41
- tsconfig?: string;
42
- }) => { compile: () => unknown };
43
- };
44
-
45
- const result = new TtscCompiler({
46
- cwd,
47
- tsconfig: tsconfig || undefined,
48
- }).compile();
49
-
50
- const raw: ReadonlyArray<Record<string, unknown>> =
51
- result &&
52
- typeof result === "object" &&
53
- Array.isArray((result as { diagnostics?: unknown }).diagnostics)
54
- ? ((result as { diagnostics: Record<string, unknown>[] }).diagnostics)
55
- : [];
56
-
57
- const out = raw
58
- .filter(
59
- (d) =>
60
- typeof d.file === "string" &&
61
- (typeof d.line === "number" || typeof d.start === "number"),
62
- )
63
- .map((d) => ({
64
- file: d.file as string,
65
- // A byte offset when the structured lane gives one; otherwise null and
66
- // the server attributes by line. @ttsc/lint and transform plugins reach
67
- // the result through ttsc's text banner, which carries a line but no
68
- // offset.
69
- start: typeof d.start === "number" ? (d.start as number) : null,
70
- line: typeof d.line === "number" ? (d.line as number) : 1,
71
- column: typeof d.character === "number" ? (d.character as number) : 1,
72
- // tsc diagnostics use numeric codes; @ttsc/lint and native plugins hash
73
- // their rule to a code >= 9000. A rare string id is marked non-tsc (the
74
- // server then drops the "TS" prefix); the rule name travels in the
75
- // message regardless.
76
- code: typeof d.code === "number" ? (d.code as number) : 9000,
77
- message: String(d.messageText ?? ""),
78
- }));
79
-
80
- // Atomic publish: write to a sibling temp file and rename, so the server
81
- // never reads a half-written file (a partial read would drop every finding
82
- // for that query).
83
- const tmp = `${outPath}.${process.pid}.tmp`;
84
- fs.writeFileSync(tmp, JSON.stringify(out));
85
- fs.renameSync(tmp, outPath);
86
- } catch {
87
- // Resilient by contract: no file means the graph shows tsc-only diagnostics.
88
- }
89
- }
90
-
91
- if (require.main === module) {
92
- runDiagnosticsWorker();
93
- }