@ttsc/graph 0.19.2 → 0.20.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 (92) hide show
  1. package/lib/TtscGraphApplication.js +5 -1
  2. package/lib/TtscGraphApplication.js.map +1 -1
  3. package/lib/bin.js +15 -3
  4. package/lib/bin.js.map +1 -1
  5. package/lib/index.d.ts +13 -2
  6. package/lib/index.js +25 -30
  7. package/lib/index.js.map +1 -1
  8. package/lib/launcherArgs.d.ts +24 -0
  9. package/lib/launcherArgs.js +136 -0
  10. package/lib/launcherArgs.js.map +1 -0
  11. package/lib/model/TtscGraphMemory.d.ts +9 -5
  12. package/lib/model/TtscGraphMemory.js +35 -58
  13. package/lib/model/TtscGraphMemory.js.map +1 -1
  14. package/lib/model/TtscGraphNodeId.d.ts +17 -0
  15. package/lib/model/TtscGraphNodeId.js +69 -0
  16. package/lib/model/TtscGraphNodeId.js.map +1 -0
  17. package/lib/model/TtscGraphSession.d.ts +23 -7
  18. package/lib/model/TtscGraphSession.js +423 -171
  19. package/lib/model/TtscGraphSession.js.map +1 -1
  20. package/lib/model/TtscGraphSourceReader.d.ts +27 -0
  21. package/lib/model/TtscGraphSourceReader.js +97 -0
  22. package/lib/model/TtscGraphSourceReader.js.map +1 -0
  23. package/lib/model/loadGraph.d.ts +14 -0
  24. package/lib/model/loadGraph.js +256 -143
  25. package/lib/model/loadGraph.js.map +1 -1
  26. package/lib/reduce.d.ts +4 -1
  27. package/lib/reduce.js +112 -29
  28. package/lib/reduce.js.map +1 -1
  29. package/lib/resolveGraphBinary.d.ts +9 -3
  30. package/lib/resolveGraphBinary.js +9 -3
  31. package/lib/resolveGraphBinary.js.map +1 -1
  32. package/lib/server/createServer.js +22 -11
  33. package/lib/server/createServer.js.map +1 -1
  34. package/lib/server/pathPolicy.d.ts +6 -0
  35. package/lib/server/pathPolicy.js +10 -1
  36. package/lib/server/pathPolicy.js.map +1 -1
  37. package/lib/server/resolveHandle.js +22 -18
  38. package/lib/server/resolveHandle.js.map +1 -1
  39. package/lib/server/resultAudit.d.ts +56 -14
  40. package/lib/server/resultAudit.js +90 -24
  41. package/lib/server/resultAudit.js.map +1 -1
  42. package/lib/server/resultNext.d.ts +5 -0
  43. package/lib/server/resultNext.js.map +1 -1
  44. package/lib/server/runDetails.d.ts +9 -2
  45. package/lib/server/runDetails.js +132 -157
  46. package/lib/server/runDetails.js.map +1 -1
  47. package/lib/server/runEntrypoints.js +1 -1
  48. package/lib/server/runEntrypoints.js.map +1 -1
  49. package/lib/server/runLookup.js +1 -1
  50. package/lib/server/runLookup.js.map +1 -1
  51. package/lib/server/runTour.js +113 -30
  52. package/lib/server/runTour.js.map +1 -1
  53. package/lib/server/runTrace.d.ts +22 -0
  54. package/lib/server/runTrace.js +293 -63
  55. package/lib/server/runTrace.js.map +1 -1
  56. package/lib/structures/ITtscGraphApplication.d.ts +8 -7
  57. package/lib/structures/ITtscGraphDetails.d.ts +18 -8
  58. package/lib/structures/ITtscGraphDump.d.ts +13 -13
  59. package/lib/structures/ITtscGraphNode.d.ts +71 -0
  60. package/lib/structures/ITtscGraphTour.d.ts +1 -1
  61. package/lib/structures/ITtscGraphTrace.d.ts +1 -1
  62. package/lib/view.js +18 -28
  63. package/lib/view.js.map +1 -1
  64. package/package.json +7 -4
  65. package/src/TtscGraphApplication.ts +8 -1
  66. package/src/bin.ts +13 -3
  67. package/src/index.ts +35 -27
  68. package/src/launcherArgs.ts +168 -0
  69. package/src/model/TtscGraphMemory.ts +34 -60
  70. package/src/model/TtscGraphNodeId.ts +77 -0
  71. package/src/model/TtscGraphSession.ts +253 -53
  72. package/src/model/TtscGraphSourceReader.ts +117 -0
  73. package/src/model/loadGraph.ts +6 -1
  74. package/src/reduce.ts +136 -31
  75. package/src/resolveGraphBinary.ts +9 -3
  76. package/src/server/createServer.ts +12 -2
  77. package/src/server/pathPolicy.ts +10 -1
  78. package/src/server/resolveHandle.ts +21 -22
  79. package/src/server/resultAudit.ts +93 -23
  80. package/src/server/resultNext.ts +6 -0
  81. package/src/server/runDetails.ts +134 -165
  82. package/src/server/runEntrypoints.ts +1 -1
  83. package/src/server/runLookup.ts +1 -1
  84. package/src/server/runTour.ts +133 -39
  85. package/src/server/runTrace.ts +401 -65
  86. package/src/structures/ITtscGraphApplication.ts +8 -7
  87. package/src/structures/ITtscGraphDetails.ts +18 -8
  88. package/src/structures/ITtscGraphDump.ts +13 -13
  89. package/src/structures/ITtscGraphNode.ts +80 -0
  90. package/src/structures/ITtscGraphTour.ts +1 -1
  91. package/src/structures/ITtscGraphTrace.ts +1 -1
  92. package/src/view.ts +25 -23
@@ -12,18 +12,18 @@ import { ITtscGraphSpan } from "./ITtscGraphSpan";
12
12
  * warm model while project inputs stay unchanged; the bundled 3D viewer reduces
13
13
  * the same dump.
14
14
  *
15
- * `project` is absolute. Every other path is relative to it — `tsconfig`, and
16
- * the `file` fields on nodes, edges, diagnostics, and the provenance manifest.
17
- *
18
- * Two kinds of path fall outside the project and so cannot be relative to it: a
19
- * dependency keeps its `node_modules/`-relative tail, which is what makes a
20
- * dependency leaf readable, and anything else the compiler loaded keeps the
21
- * identity the compiler gave it a virtual lib stays `bundled:///…`.
15
+ * `project` is the producer-local absolute locator. Every identity-bearing path
16
+ * uses one schema-v6 coordinate relative to it: project files are ordinary
17
+ * relative paths; same-filesystem siblings use `../` segments; package files
18
+ * keep their full resolution context (including version/peer-store segments);
19
+ * and a virtual compiler source stays `bundled:///…`. Raw absolute identities
20
+ * are never emitted. A source on another drive or UNC share makes the producer
21
+ * fail unless a future contract supplies a logical root for it.
22
22
  */
23
23
  export interface ITtscGraphDump {
24
24
  /** Absolute path of the project root the graph was built for. */
25
25
  project: string;
26
- /** The tsconfig the program was loaded from, relative to `project`. */
26
+ /** The tsconfig the program was loaded from, in the dump's path vocabulary. */
27
27
  tsconfig: string;
28
28
  /** Evidence about the one program that produced everything below. */
29
29
  provenance: ITtscGraphDump.IProvenance;
@@ -126,14 +126,14 @@ export declare namespace ITtscGraphDump {
126
126
  }
127
127
  /** A root file attributed to the config that named it. */
128
128
  interface IRootFile {
129
- /** The tsconfig that named this root, project-relative. */
129
+ /** The tsconfig that named this root, in the dump's path vocabulary. */
130
130
  config: string;
131
- /** The root file, project-relative. */
131
+ /** The root file, in the dump's path vocabulary. */
132
132
  file: string;
133
133
  }
134
134
  /** A file and the hex-encoded SHA-256 of its on-disk bytes. */
135
135
  interface IFileDigest {
136
- /** Project-relative. */
136
+ /** In the dump's path vocabulary. */
137
137
  file: string;
138
138
  /** Hex-encoded SHA-256. */
139
139
  digest: string;
@@ -148,7 +148,7 @@ export declare namespace ITtscGraphDump {
148
148
  * on every build.
149
149
  */
150
150
  interface ISourceDigest {
151
- /** Project-relative. */
151
+ /** In the dump's path vocabulary. */
152
152
  file: string;
153
153
  /**
154
154
  * Hex-encoded SHA-256 of the text the checker resolved against — the ground
@@ -175,7 +175,7 @@ export declare namespace ITtscGraphDump {
175
175
  }
176
176
  /** One compiler diagnostic from the generation that produced the facts. */
177
177
  interface IDiagnostic {
178
- /** Project-relative. */
178
+ /** In the dump's path vocabulary. */
179
179
  file: string;
180
180
  /** 1-based line. */
181
181
  line: number;
@@ -52,11 +52,58 @@ export interface ITtscGraphNode {
52
52
  closure?: boolean;
53
53
  /** Declaration modifiers, when the declaration pass recorded any. */
54
54
  modifiers?: TtscGraphNodeModifier[];
55
+ /**
56
+ * The complete value set of a type alias or enum whose declared type the
57
+ * checker resolved to literals, each in TypeScript source form (`"a"`, `1`,
58
+ * `true`, `null`).
59
+ *
60
+ * Present only when every constituent is enumerable, so the list is the whole
61
+ * type and never a sample of it: `type T = Kind | string` admits values no
62
+ * list can name and carries none. It is resolved from the type, not read off
63
+ * the declaration, so indirection (`type I = Kind | 'f'`) is followed and the
64
+ * answer does not depend on how the declaration is wrapped.
65
+ */
66
+ literals?: string[];
67
+ /**
68
+ * What an enum declares, in checker order: the name a caller writes and the
69
+ * value it carries. Absent on every other kind.
70
+ *
71
+ * `literals` says which values the enum admits, which is what a serializer
72
+ * asks. The code says `Colors.Red`, so the names are the other half, and
73
+ * without them a caller that had already named the enum still had to open the
74
+ * file to learn what to type. The members are not nodes — `Colors.Red` is a
75
+ * string a grep finds exactly — so this fills in the node the graph already
76
+ * holds instead of minting one per member.
77
+ */
78
+ enumMembers?: ITtscGraphNode.IEnumMember[];
79
+ /**
80
+ * Direct, statically named members when this variable is initialized with an
81
+ * object literal, in declaration order.
82
+ *
83
+ * The native builder takes identity from the compiler AST and renders the
84
+ * compact signature from the same Program-owned source snapshot. A spread or
85
+ * dynamic computed name has no declaration name it can report soundly, so it
86
+ * contributes no fabricated member.
87
+ */
88
+ objectMembers?: ITtscGraphNode.IObjectMember[];
55
89
  /**
56
90
  * Decorators written on this declaration, in source order: raw facts
57
91
  * (`@Controller`, `@Get`) a consumer interprets without re-parsing source.
58
92
  */
59
93
  decorators?: ITtscGraphDecorator[];
94
+ /**
95
+ * The declaration head, cut by the producer where the compiler says the body
96
+ * opens.
97
+ *
98
+ * Absent when the producer could not bound the head, in which case a consumer
99
+ * falls back to reading the declaration span. That fallback is a line scan,
100
+ * and a physical line is not a declaration boundary: it leaks implementation
101
+ * text when a declaration shares its line with its body, and it stops early
102
+ * when the head itself contains a brace — a type-literal parameter, an object
103
+ * return type, a destructured parameter. Prefer this field wherever it is
104
+ * present.
105
+ */
106
+ signature?: string;
60
107
  /** The declaration span, for display and signatures. */
61
108
  evidence?: ITtscGraphEvidence;
62
109
  /**
@@ -65,3 +112,27 @@ export interface ITtscGraphNode {
65
112
  */
66
113
  implementation?: ITtscGraphEvidence;
67
114
  }
115
+ export declare namespace ITtscGraphNode {
116
+ /** One member of an enum: the name a caller writes and the value it carries. */
117
+ interface IEnumMember {
118
+ /** The member's own name, unqualified (`Red` on `Colors.Red`). */
119
+ name: string;
120
+ /**
121
+ * The value it carries, in TypeScript source form (`"red"`, `1`). Absent
122
+ * for a computed member the checker could not fold to a constant; the name
123
+ * still stands.
124
+ */
125
+ value?: string;
126
+ }
127
+ /** One direct, statically named member of an object-literal variable. */
128
+ interface IObjectMember {
129
+ /** The source-visible static property name. */
130
+ name: string;
131
+ /** Whether the declaration is a data property or callable/accessor member. */
132
+ kind: "property" | "method";
133
+ /** 1-based declaration line in the node's file, when source was available. */
134
+ line?: number;
135
+ /** Compact declaration outline rendered from the compiler source snapshot. */
136
+ signature?: string;
137
+ }
138
+ }
@@ -56,7 +56,7 @@ export declare namespace ITtscGraphTour {
56
56
  * Central entrypoints to seed the tour. Raise only when the question names
57
57
  * several public paths that must all appear in one answer.
58
58
  *
59
- * @default 4
59
+ * @default 5
60
60
  */
61
61
  limit?: number;
62
62
  /**
@@ -11,7 +11,7 @@ export interface ITtscGraphTrace {
11
11
  hops: ITtscGraphTrace.IHop[];
12
12
  /** Unique nodes reached (excluding the start), each with its depth and roles. */
13
13
  reached: ITtscGraphTrace.INode[];
14
- /** True when the trace hit its node or depth cap; the returned flow stands. */
14
+ /** In an open trace, true when a bound omitted an eligible node or hop. */
15
15
  truncated: boolean;
16
16
  /** The resolved `to` target, when a path was requested. */
17
17
  target?: ITtscGraphTrace.INode;
package/lib/view.js CHANGED
@@ -8,39 +8,29 @@ const node_child_process_1 = require("node:child_process");
8
8
  const node_fs_1 = __importDefault(require("node:fs"));
9
9
  const node_http_1 = __importDefault(require("node:http"));
10
10
  const node_path_1 = __importDefault(require("node:path"));
11
+ const launcherArgs_1 = require("./launcherArgs");
11
12
  const nativeExecutable_1 = require("./nativeExecutable");
12
13
  const reduce_1 = require("./reduce");
13
14
  const resolveGraphBinary_1 = require("./resolveGraphBinary");
14
15
  function parseViewArgs(argv) {
15
- const opts = {
16
- cwd: process.cwd(),
17
- tsconfig: "tsconfig.json",
18
- port: 0,
19
- open: true,
20
- maxNodes: 1200,
16
+ const values = (0, launcherArgs_1.parseLauncherOptions)(argv, [
17
+ { key: "cwd", flags: ["--cwd"], kind: "value" },
18
+ { key: "tsconfig", flags: ["--tsconfig", "-p"], kind: "value" },
19
+ { key: "port", flags: ["--port"], kind: "value" },
20
+ { key: "open", flags: ["--no-open"], kind: "flag" },
21
+ { key: "max_nodes", flags: ["--max-nodes"], kind: "value" },
22
+ ]);
23
+ const project = (0, launcherArgs_1.projectOptions)(values);
24
+ return {
25
+ ...project,
26
+ port: values.has("port") === true
27
+ ? (0, launcherArgs_1.nonNegativeIntegerOption)(values, "port", 65535)
28
+ : 0,
29
+ open: values.get("open") !== true,
30
+ maxNodes: values.has("max_nodes") === true
31
+ ? (0, launcherArgs_1.positiveIntegerOption)(values, "max_nodes", Number.MAX_SAFE_INTEGER)
32
+ : 1200,
21
33
  };
22
- for (let i = 0; i < argv.length; i++) {
23
- const arg = argv[i];
24
- if (arg === "--cwd")
25
- opts.cwd = argv[++i] ?? opts.cwd;
26
- else if (arg.startsWith("--cwd="))
27
- opts.cwd = arg.slice("--cwd=".length);
28
- else if (arg === "--tsconfig" || arg === "-p")
29
- opts.tsconfig = argv[++i] ?? opts.tsconfig;
30
- else if (arg.startsWith("--tsconfig="))
31
- opts.tsconfig = arg.slice("--tsconfig=".length);
32
- else if (arg === "--port")
33
- opts.port = Number(argv[++i]);
34
- else if (arg.startsWith("--port="))
35
- opts.port = Number(arg.slice("--port=".length));
36
- else if (arg === "--no-open")
37
- opts.open = false;
38
- else if (arg === "--max-nodes")
39
- opts.maxNodes = Number(argv[++i]);
40
- else if (arg.startsWith("--max-nodes="))
41
- opts.maxNodes = Number(arg.slice("--max-nodes=".length));
42
- }
43
- return opts;
44
34
  }
45
35
  /**
46
36
  * `ttsc-graph view`: build the project's code graph, reduce it, and serve a
package/lib/view.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"view.js","sourceRoot":"","sources":["../src/view.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"view.js","sourceRoot":"","sources":["../src/view.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ttsc/graph",
3
- "version": "0.19.2",
3
+ "version": "0.20.0",
4
4
  "description": "Checker-resolved architecture graph over MCP for coding agents, backed by ttsc's in-process TypeScript-Go compiler.",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -16,8 +16,11 @@
16
16
  },
17
17
  "dependencies": {
18
18
  "@modelcontextprotocol/sdk": "^1.26.0",
19
- "@typia/mcp": "13.1.0",
20
- "typia": "13.1.0"
19
+ "@typia/mcp": "13.2.0",
20
+ "typia": "13.2.0"
21
+ },
22
+ "peerDependencies": {
23
+ "ttsc": "^0.20.0"
21
24
  },
22
25
  "keywords": [
23
26
  "ttsc",
@@ -39,7 +42,7 @@
39
42
  "three": "^0.184.0",
40
43
  "three-forcegraph": "^1.43.4",
41
44
  "typescript": "^7.0.2",
42
- "ttsc": "0.19.2"
45
+ "ttsc": "0.20.0"
43
46
  },
44
47
  "repository": {
45
48
  "type": "git",
@@ -1,6 +1,8 @@
1
1
  import { TtscGraphMemory } from "./model/TtscGraphMemory";
2
2
  import {
3
3
  RESULT_AUDIT,
4
+ RESULT_AUDIT_DETAILS,
5
+ RESULT_AUDIT_DETAILS_CAPPED,
4
6
  RESULT_AUDIT_ESCAPE,
5
7
  RESULT_AUDIT_SELECTION,
6
8
  } from "./server/resultAudit";
@@ -90,9 +92,14 @@ export class TtscGraphApplication implements ITtscGraphApplication {
90
92
  };
91
93
  }
92
94
  case "details": {
95
+ // details' identity is complete and its fan-out is a slice, which is
96
+ // not the walk-bounded-and-marked shape RESULT_AUDIT states.
93
97
  const r = runDetails(graph, props.request);
94
98
  return {
95
- audit: RESULT_AUDIT,
99
+ audit:
100
+ r.membersCapped === true
101
+ ? RESULT_AUDIT_DETAILS_CAPPED
102
+ : RESULT_AUDIT_DETAILS,
96
103
  next: r.next,
97
104
  result: r.result,
98
105
  };
package/src/bin.ts CHANGED
@@ -1,8 +1,18 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import { runGraph } from "./index";
4
+ import { GraphArgumentError } from "./launcherArgs";
4
5
 
5
- const code = runGraph(process.argv.slice(2));
6
- if (typeof code === "number") {
7
- process.exitCode = code;
6
+ try {
7
+ const code = runGraph(process.argv.slice(2));
8
+ if (typeof code === "number") {
9
+ process.exitCode = code;
10
+ }
11
+ } catch (error) {
12
+ if (error instanceof GraphArgumentError) {
13
+ process.stderr.write(`@ttsc/graph: ${error.message}\n`);
14
+ process.exitCode = 2;
15
+ } else {
16
+ throw error;
17
+ }
8
18
  }
package/src/index.ts CHANGED
@@ -1,6 +1,10 @@
1
1
  import { spawnSync } from "node:child_process";
2
- import path from "node:path";
3
2
 
3
+ import {
4
+ PROJECT_OPTIONS,
5
+ parseLauncherOptions,
6
+ projectOptions,
7
+ } from "./launcherArgs";
4
8
  import { ensureExecutable } from "./nativeExecutable";
5
9
  import { resolveGraphBinary } from "./resolveGraphBinary";
6
10
  import { startServer } from "./server/startServer";
@@ -9,6 +13,8 @@ import { runView } from "./view";
9
13
  /** What a graph result says about where its facts came from. */
10
14
  export {
11
15
  RESULT_AUDIT,
16
+ RESULT_AUDIT_DETAILS,
17
+ RESULT_AUDIT_DETAILS_CAPPED,
12
18
  RESULT_AUDIT_ESCAPE,
13
19
  RESULT_AUDIT_SELECTION,
14
20
  } from "./server/resultAudit";
@@ -18,34 +24,34 @@ export {
18
24
  // project other than its own process directory names it once and the binary is
19
25
  // found under that project's installed `ttsc`.
20
26
  export { resolveGraphBinary } from "./resolveGraphBinary";
27
+ /**
28
+ * The viewer reduction the `view` command runs before serving a payload.
29
+ *
30
+ * Exported because it is one of three copies of the same pure transform — the
31
+ * website's uploaded-dump viewer and the benchmark viewer hold the others — and
32
+ * a shared policy that cannot be measured from outside the package drifts. It
33
+ * already did: two of them filtered git-ignored generated code and this one did
34
+ * not.
35
+ */
36
+ export { reduce } from "./reduce";
37
+ export type { RawDump, RawEdge, RawNode, ViewerPayload } from "./reduce";
21
38
  export { loadGraph } from "./model/loadGraph";
22
- export { TtscGraphSession } from "./model/TtscGraphSession";
39
+ export {
40
+ TtscGraphSession,
41
+ type TtscGraphRequestOptions,
42
+ type TtscGraphSessionOptions,
43
+ } from "./model/TtscGraphSession";
23
44
 
24
45
  // The server version reported in the MCP handshake; read from this package.
25
46
  const VERSION: string = (require("../package.json") as { version: string })
26
47
  .version;
27
48
 
28
- /**
29
- * The project root and tsconfig to build the graph for, from the `--cwd` /
30
- * `--tsconfig` flags (the same ones `ttscgraph dump` accepts). Defaults are the
31
- * process working directory and `tsconfig.json`.
32
- */
33
- function parseProjectArgs(argv: readonly string[]): {
34
- cwd: string;
35
- tsconfig: string;
36
- } {
37
- let cwd = process.cwd();
38
- let tsconfig = "tsconfig.json";
39
- for (let i = 0; i < argv.length; i++) {
40
- const arg = argv[i]!;
41
- if (arg === "--cwd" && i + 1 < argv.length) cwd = argv[++i]!;
42
- else if (arg.startsWith("--cwd=")) cwd = arg.slice("--cwd=".length);
43
- else if (arg === "--tsconfig" && i + 1 < argv.length) tsconfig = argv[++i]!;
44
- else if (arg.startsWith("--tsconfig="))
45
- tsconfig = arg.slice("--tsconfig=".length);
46
- }
47
- return { cwd: path.resolve(cwd), tsconfig };
48
- }
49
+ const DUMP_OPTIONS = [
50
+ { key: "cwd", flags: ["--cwd", "-cwd"], kind: "value" },
51
+ { key: "tsconfig", flags: ["--tsconfig", "-tsconfig"], kind: "value" },
52
+ { key: "pretty", flags: ["--pretty", "-pretty"], kind: "boolean" },
53
+ { key: "help", flags: ["--help", "-help", "-h"], kind: "flag" },
54
+ ] as const;
49
55
 
50
56
  /**
51
57
  * Run the `@ttsc/graph` launcher.
@@ -62,9 +68,11 @@ export function runGraph(
62
68
  argv: readonly string[] = process.argv.slice(2),
63
69
  ): number | void {
64
70
  if (argv[0] === "view") return runView(argv.slice(1));
65
- if (argv[0] === "dump") return runDump(argv);
71
+ if (argv[0] === "dump") return runDump(argv.slice(1));
66
72
 
67
- const { cwd, tsconfig } = parseProjectArgs(argv);
73
+ const { cwd, tsconfig } = projectOptions(
74
+ parseLauncherOptions(argv, PROJECT_OPTIONS),
75
+ );
68
76
  void startServer({ cwd, tsconfig, version: VERSION }).catch(
69
77
  (error: unknown) => {
70
78
  process.stderr.write(
@@ -82,7 +90,7 @@ export function runGraph(
82
90
  function runDump(argv: readonly string[]): number {
83
91
  // Resolve the native binary from the target project the caller named with
84
92
  // `--cwd`, not from wherever the launcher process happened to start.
85
- const { cwd } = parseProjectArgs(argv);
93
+ const { cwd } = projectOptions(parseLauncherOptions(argv, DUMP_OPTIONS));
86
94
  const binary = resolveGraphBinary(process.env, cwd);
87
95
  if (binary === null) {
88
96
  process.stderr.write(
@@ -93,7 +101,7 @@ function runDump(argv: readonly string[]): number {
93
101
  return 1;
94
102
  }
95
103
  ensureExecutable(binary);
96
- const result = spawnSync(binary, [...argv], {
104
+ const result = spawnSync(binary, ["dump", ...argv], {
97
105
  stdio: "inherit",
98
106
  windowsHide: true,
99
107
  });
@@ -0,0 +1,168 @@
1
+ import path from "node:path";
2
+
3
+ export class GraphArgumentError extends Error {
4
+ public constructor(message: string) {
5
+ super(message);
6
+ this.name = "GraphArgumentError";
7
+ }
8
+ }
9
+
10
+ type OptionKind = "value" | "flag" | "boolean";
11
+
12
+ export interface ILauncherOption {
13
+ key: string;
14
+ flags: readonly string[];
15
+ kind: OptionKind;
16
+ }
17
+
18
+ export type ParsedLauncherOptions = ReadonlyMap<string, string | boolean>;
19
+
20
+ export interface IProjectOptions {
21
+ cwd: string;
22
+ tsconfig: string;
23
+ }
24
+
25
+ export const PROJECT_OPTIONS: readonly ILauncherOption[] = [
26
+ { key: "cwd", flags: ["--cwd"], kind: "value" },
27
+ { key: "tsconfig", flags: ["--tsconfig"], kind: "value" },
28
+ ];
29
+
30
+ /** Parse one complete launcher argument vector and reject every unknown token. */
31
+ export function parseLauncherOptions(
32
+ argv: readonly string[],
33
+ definitions: readonly ILauncherOption[],
34
+ ): ParsedLauncherOptions {
35
+ const flags = new Map<string, ILauncherOption>();
36
+ for (const definition of definitions) {
37
+ for (const flag of definition.flags) flags.set(flag, definition);
38
+ }
39
+
40
+ const parsed = new Map<string, string | boolean>();
41
+ for (let i = 0; i < argv.length; i++) {
42
+ const arg = argv[i]!;
43
+ const exact = flags.get(arg);
44
+ if (exact !== undefined) {
45
+ if (exact.kind === "value") {
46
+ const value = argv[++i];
47
+ if (value === undefined || value.startsWith("-")) {
48
+ throw new GraphArgumentError(`${arg} requires a non-empty value`);
49
+ }
50
+ parsed.set(exact.key, requireValue(arg, value));
51
+ } else {
52
+ parsed.set(exact.key, true);
53
+ }
54
+ continue;
55
+ }
56
+
57
+ const equals = findEqualsOption(arg, flags);
58
+ if (equals === undefined) {
59
+ throw new GraphArgumentError(`unknown option ${arg}`);
60
+ }
61
+ const { definition, flag, value } = equals;
62
+ if (definition.kind === "flag") {
63
+ throw new GraphArgumentError(`${flag} does not take a value`);
64
+ }
65
+ if (definition.kind === "boolean") {
66
+ parsed.set(definition.key, parseBoolean(flag, value));
67
+ } else {
68
+ parsed.set(definition.key, requireValue(flag, value));
69
+ }
70
+ }
71
+ return parsed;
72
+ }
73
+
74
+ /** Resolve the two project-selection values shared by every launcher lane. */
75
+ export function projectOptions(values: ParsedLauncherOptions): IProjectOptions {
76
+ return {
77
+ cwd: path.resolve(stringValue(values, "cwd") ?? process.cwd()),
78
+ tsconfig: stringValue(values, "tsconfig") ?? "tsconfig.json",
79
+ };
80
+ }
81
+
82
+ /** Read a bounded non-negative integer option without JavaScript coercion. */
83
+ export function nonNegativeIntegerOption(
84
+ values: ParsedLauncherOptions,
85
+ key: string,
86
+ maximum: number,
87
+ ): number {
88
+ const value = stringValue(values, key);
89
+ if (value === undefined) {
90
+ throw new Error(`Missing required parsed option ${key}`);
91
+ }
92
+ if (!/^\d+$/.test(value)) {
93
+ throw new GraphArgumentError(`${optionName(key)} must be an integer`);
94
+ }
95
+ const number = Number(value);
96
+ if (!Number.isSafeInteger(number) || number > maximum) {
97
+ throw new GraphArgumentError(
98
+ `${optionName(key)} must be between 0 and ${maximum}`,
99
+ );
100
+ }
101
+ return number;
102
+ }
103
+
104
+ /** Read a bounded positive integer option without JavaScript coercion. */
105
+ export function positiveIntegerOption(
106
+ values: ParsedLauncherOptions,
107
+ key: string,
108
+ maximum: number,
109
+ ): number {
110
+ const value = nonNegativeIntegerOption(values, key, maximum);
111
+ if (value === 0) {
112
+ throw new GraphArgumentError(`${optionName(key)} must be greater than 0`);
113
+ }
114
+ return value;
115
+ }
116
+
117
+ function findEqualsOption(
118
+ arg: string,
119
+ flags: ReadonlyMap<string, ILauncherOption>,
120
+ ): { definition: ILauncherOption; flag: string; value: string } | undefined {
121
+ for (const [flag, definition] of flags) {
122
+ const prefix = `${flag}=`;
123
+ if (arg.startsWith(prefix)) {
124
+ return { definition, flag, value: arg.slice(prefix.length) };
125
+ }
126
+ }
127
+ return undefined;
128
+ }
129
+
130
+ function requireValue(flag: string, value: string): string {
131
+ if (value.trim() === "") {
132
+ throw new GraphArgumentError(`${flag} requires a non-empty value`);
133
+ }
134
+ return value;
135
+ }
136
+
137
+ function parseBoolean(flag: string, value: string): boolean {
138
+ switch (value) {
139
+ case "1":
140
+ case "t":
141
+ case "T":
142
+ case "TRUE":
143
+ case "true":
144
+ case "True":
145
+ return true;
146
+ case "0":
147
+ case "f":
148
+ case "F":
149
+ case "FALSE":
150
+ case "false":
151
+ case "False":
152
+ return false;
153
+ default:
154
+ throw new GraphArgumentError(`${flag} requires a boolean value`);
155
+ }
156
+ }
157
+
158
+ function stringValue(
159
+ values: ParsedLauncherOptions,
160
+ key: string,
161
+ ): string | undefined {
162
+ const value = values.get(key);
163
+ return typeof value === "string" ? value : undefined;
164
+ }
165
+
166
+ function optionName(key: string): string {
167
+ return `--${key.replaceAll("_", "-")}`;
168
+ }