ttsc 0.18.3 → 0.19.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 (173) hide show
  1. package/README.md +5 -6
  2. package/cmd/graphbench/main.go +1 -1
  3. package/cmd/platform/main.go +1 -48
  4. package/cmd/ttsc/build_branches_test.go +5 -1
  5. package/cmd/ttsc/main.go +0 -50
  6. package/cmd/ttsc/main_alias_branches_test.go +6 -12
  7. package/cmd/ttscgraph/dump.go +13 -3
  8. package/cmd/ttscgraph/main.go +18 -12
  9. package/cmd/ttscgraph/run_help_version_and_bad_flags_exit_codes_test.go +23 -5
  10. package/cmd/ttscgraph/serve.go +863 -0
  11. package/cmd/ttscgraph/serve_protocol_rejects_invalid_request_line_test.go +43 -0
  12. package/cmd/ttscgraph/serve_protocol_retries_session_creation_test.go +83 -0
  13. package/cmd/ttscgraph/serve_protocol_reuses_session_test.go +35 -0
  14. package/cmd/ttscgraph/serve_session_applies_source_edit_incrementally_test.go +55 -0
  15. package/cmd/ttscgraph/serve_session_fails_closed_on_deleted_config_test.go +68 -0
  16. package/cmd/ttscgraph/serve_session_fails_closed_on_invalid_config_test.go +50 -0
  17. package/cmd/ttscgraph/serve_session_keeps_missing_literal_root_unchanged_test.go +46 -0
  18. package/cmd/ttscgraph/serve_session_rebuilds_import_graph_change_test.go +60 -0
  19. package/cmd/ttscgraph/serve_session_reloads_created_literal_root_test.go +44 -0
  20. package/cmd/ttscgraph/serve_session_reloads_extended_config_change_test.go +45 -0
  21. package/cmd/ttscgraph/serve_session_reloads_newly_resolved_conditional_export_test.go +60 -0
  22. package/cmd/ttscgraph/serve_session_reloads_newly_resolved_config_types_test.go +44 -0
  23. package/cmd/ttscgraph/serve_session_reloads_newly_resolved_excluded_import_test.go +62 -0
  24. package/cmd/ttscgraph/serve_session_reloads_newly_resolved_package_export_test.go +46 -0
  25. package/cmd/ttscgraph/serve_session_reloads_newly_resolved_package_import_test.go +46 -0
  26. package/cmd/ttscgraph/serve_session_reloads_newly_resolved_path_alias_test.go +47 -0
  27. package/cmd/ttscgraph/serve_session_reloads_newly_resolved_reference_path_test.go +42 -0
  28. package/cmd/ttscgraph/serve_session_reloads_newly_resolved_root_dirs_target_test.go +46 -0
  29. package/cmd/ttscgraph/serve_session_reloads_newly_resolved_type_reference_test.go +42 -0
  30. package/cmd/ttscgraph/serve_session_reloads_root_file_set_test.go +52 -0
  31. package/cmd/ttscgraph/serve_session_reloads_source_deleted_during_load_test.go +60 -0
  32. package/cmd/ttscgraph/serve_session_reloads_transitive_project_reference_test.go +55 -0
  33. package/cmd/ttscgraph/serve_session_reloads_when_program_plugin_linked_test.go +53 -0
  34. package/cmd/ttscgraph/serve_session_reuses_unchanged_preamble_source_test.go +45 -0
  35. package/cmd/ttscgraph/serve_session_reuses_unchanged_snapshot_test.go +52 -0
  36. package/cmd/ttscgraph/serve_session_revisits_source_edited_during_load_test.go +61 -0
  37. package/cmd/ttscgraph/serve_session_tolerates_os_invalid_resolution_candidate_test.go +56 -0
  38. package/cmd/ttscgraph/serve_session_tracks_all_module_specifier_forms_test.go +41 -0
  39. package/cmd/ttscgraph/serve_session_tracks_diamond_project_references_once_test.go +61 -0
  40. package/cmd/ttscserver/main.go +5 -3
  41. package/driver/lsp.go +13 -1
  42. package/driver/plugins.go +56 -5
  43. package/driver/program.go +25 -10
  44. package/driver/rewrite.go +381 -21
  45. package/driver/session.go +11 -3
  46. package/go.mod +1 -0
  47. package/internal/graph/build.go +297 -3
  48. package/internal/graph/build_records_a_node_per_top_level_declaration_test.go +16 -2
  49. package/internal/graph/diagnostics.go +5 -4
  50. package/internal/graph/dump.go +60 -4
  51. package/internal/graph/dump_is_a_function_of_the_source_test.go +71 -0
  52. package/internal/graph/dump_serializes_the_full_graph_test.go +16 -4
  53. package/internal/graph/edges.go +122 -11
  54. package/internal/graph/exports.go +74 -17
  55. package/internal/graph/graph.go +33 -1
  56. package/internal/graph/node_identity_is_position_invariant_test.go +4 -2
  57. package/internal/graph/resolve.go +24 -0
  58. package/internal/graphsymbols/provider.go +50 -14
  59. package/internal/lspserver/lsp_native_plugin_source.go +77 -23
  60. package/internal/lspserver/lsp_plugin.go +19 -2
  61. package/internal/lspserver/lsp_proxy.go +244 -52
  62. package/internal/lspserver/lsp_server.go +35 -27
  63. package/internal/lspserver/lsp_symbols.go +25 -16
  64. package/lib/TtscCompiler.d.ts +13 -2
  65. package/lib/TtscCompiler.js +30 -20
  66. package/lib/TtscCompiler.js.map +1 -1
  67. package/lib/TtscService.js +9 -7
  68. package/lib/TtscService.js.map +1 -1
  69. package/lib/compiler/internal/compileProjectInMemory.js +15 -1
  70. package/lib/compiler/internal/compileProjectInMemory.js.map +1 -1
  71. package/lib/compiler/internal/project/createNativeProjectContextArgs.d.ts +3 -0
  72. package/lib/compiler/internal/project/createNativeProjectContextArgs.js +14 -0
  73. package/lib/compiler/internal/project/createNativeProjectContextArgs.js.map +1 -0
  74. package/lib/compiler/internal/project/readProjectConfig.js +53 -4
  75. package/lib/compiler/internal/project/readProjectConfig.js.map +1 -1
  76. package/lib/compiler/internal/project/resolveProjectConfig.d.ts +9 -2
  77. package/lib/compiler/internal/project/resolveProjectConfig.js +45 -16
  78. package/lib/compiler/internal/project/resolveProjectConfig.js.map +1 -1
  79. package/lib/compiler/internal/residentTransformProcess.d.ts +16 -5
  80. package/lib/compiler/internal/residentTransformProcess.js +68 -20
  81. package/lib/compiler/internal/residentTransformProcess.js.map +1 -1
  82. package/lib/compiler/internal/runBuild.d.ts +18 -0
  83. package/lib/compiler/internal/runBuild.js +220 -24
  84. package/lib/compiler/internal/runBuild.js.map +1 -1
  85. package/lib/compiler/internal/runSingleFileEmit.js +7 -4
  86. package/lib/compiler/internal/runSingleFileEmit.js.map +1 -1
  87. package/lib/compiler/internal/sharedHostHelpers.d.ts +16 -0
  88. package/lib/compiler/internal/sharedHostHelpers.js +23 -0
  89. package/lib/compiler/internal/sharedHostHelpers.js.map +1 -1
  90. package/lib/compiler/internal/startResidentTransform.js +18 -1
  91. package/lib/compiler/internal/startResidentTransform.js.map +1 -1
  92. package/lib/compiler/internal/transformProjectInMemory.js +34 -8
  93. package/lib/compiler/internal/transformProjectInMemory.js.map +1 -1
  94. package/lib/flags/parser.d.ts +17 -0
  95. package/lib/flags/parser.js +11 -1
  96. package/lib/flags/parser.js.map +1 -1
  97. package/lib/flags/schema.js +7 -0
  98. package/lib/flags/schema.js.map +1 -1
  99. package/lib/launcher/internal/prepareExecution.js +21 -2
  100. package/lib/launcher/internal/prepareExecution.js.map +1 -1
  101. package/lib/launcher/internal/runTtsc.js +13 -53
  102. package/lib/launcher/internal/runTtsc.js.map +1 -1
  103. package/lib/launcher/internal/runTtscserver.js +11 -0
  104. package/lib/launcher/internal/runTtscserver.js.map +1 -1
  105. package/lib/launcher/internal/runTtsx.js +27 -11
  106. package/lib/launcher/internal/runTtsx.js.map +1 -1
  107. package/lib/launcher/internal/runtimeHooks.d.ts +81 -0
  108. package/lib/launcher/internal/runtimeHooks.js +632 -43
  109. package/lib/launcher/internal/runtimeHooks.js.map +1 -1
  110. package/lib/launcher/internal/servedSourceMap.d.ts +25 -0
  111. package/lib/launcher/internal/servedSourceMap.js +164 -0
  112. package/lib/launcher/internal/servedSourceMap.js.map +1 -0
  113. package/lib/plugin/internal/buildSourcePlugin.d.ts +146 -2
  114. package/lib/plugin/internal/buildSourcePlugin.js +651 -113
  115. package/lib/plugin/internal/buildSourcePlugin.js.map +1 -1
  116. package/lib/plugin/internal/loadProjectPlugins.d.ts +7 -0
  117. package/lib/plugin/internal/loadProjectPlugins.js +33 -10
  118. package/lib/plugin/internal/loadProjectPlugins.js.map +1 -1
  119. package/lib/structures/ITtscCompilerContext.d.ts +16 -2
  120. package/lib/structures/ITtscCompilerResult.d.ts +8 -5
  121. package/lib/structures/ITtscPluginCapabilities.d.ts +8 -0
  122. package/lib/structures/ITtscPluginFactoryContext.d.ts +14 -0
  123. package/lib/structures/internal/ITtscParsedProjectConfig.d.ts +3 -0
  124. package/lib/structures/internal/ITtscProjectIdentity.d.ts +17 -0
  125. package/lib/structures/internal/ITtscProjectIdentity.js +3 -0
  126. package/lib/structures/internal/ITtscProjectIdentity.js.map +1 -0
  127. package/lib/structures/internal/TtscCommonOptions.d.ts +8 -0
  128. package/package.json +11 -8
  129. package/shim/ast/lint.go +10 -0
  130. package/shim/ast/shim.go +44 -0
  131. package/shim/checker/enums_gen.go +19 -0
  132. package/shim/checker/shim.go +130 -0
  133. package/shim/diagnosticwriter/lint.go +30 -3
  134. package/shim/printer/shim.go +22 -4
  135. package/shim/scanner/regexp.go +27 -0
  136. package/src/TtscCompiler.ts +29 -22
  137. package/src/TtscService.ts +15 -7
  138. package/src/compiler/internal/compileProjectInMemory.ts +18 -1
  139. package/src/compiler/internal/project/createNativeProjectContextArgs.ts +15 -0
  140. package/src/compiler/internal/project/readProjectConfig.ts +61 -5
  141. package/src/compiler/internal/project/resolveProjectConfig.ts +51 -21
  142. package/src/compiler/internal/residentTransformProcess.ts +95 -21
  143. package/src/compiler/internal/runBuild.ts +313 -32
  144. package/src/compiler/internal/runSingleFileEmit.ts +7 -4
  145. package/src/compiler/internal/sharedHostHelpers.ts +24 -0
  146. package/src/compiler/internal/startResidentTransform.ts +21 -1
  147. package/src/compiler/internal/transformProjectInMemory.ts +49 -6
  148. package/src/flags/parser.ts +28 -1
  149. package/src/flags/schema.ts +8 -0
  150. package/src/launcher/internal/prepareExecution.ts +22 -2
  151. package/src/launcher/internal/runTtsc.ts +13 -61
  152. package/src/launcher/internal/runTtscserver.ts +14 -0
  153. package/src/launcher/internal/runTtsx.ts +28 -13
  154. package/src/launcher/internal/runtimeHooks.ts +771 -53
  155. package/src/launcher/internal/servedSourceMap.ts +183 -0
  156. package/src/plugin/internal/buildSourcePlugin.ts +859 -122
  157. package/src/plugin/internal/loadProjectPlugins.ts +36 -6
  158. package/src/structures/ITtscCompilerContext.ts +17 -2
  159. package/src/structures/ITtscCompilerResult.ts +8 -5
  160. package/src/structures/ITtscPluginCapabilities.ts +9 -0
  161. package/src/structures/ITtscPluginFactoryContext.ts +15 -0
  162. package/src/structures/internal/ITtscParsedProjectConfig.ts +3 -0
  163. package/src/structures/internal/ITtscProjectIdentity.ts +17 -0
  164. package/src/structures/internal/TtscCommonOptions.ts +8 -0
  165. package/tools/shim_audit/baseline.json +16 -7
  166. package/tools/shim_audit/main.go +777 -71
  167. package/tools/shim_audit/main_test.go +28 -1
  168. package/tools/shim_audit/producer_exemptions_require_rationale_test.go +42 -0
  169. package/tools/shim_audit/producer_surface_includes_exposed_methods_test.go +154 -0
  170. package/tools/shim_audit/producer_surface_rejects_unproducible_reference_test.go +142 -0
  171. package/utility/host.go +46 -20
  172. package/utility/serve.go +1 -1
  173. package/shim/checker/signature_api_completeness.go +0 -58
package/README.md CHANGED
@@ -8,8 +8,8 @@ A `typescript-go` toolchain for compiler-powered plugins and type-safe execution
8
8
 
9
9
  - **`ttsc`**: build, check, and transform.
10
10
  - **`ttsx`**: execute TypeScript with type checking.
11
- - **`@ttsc/lint`**: lint violations as compiler errors.
12
- - **`@ttsc/graph`**: MCP code graph that reduce token usage.
11
+ - [**`@ttsc/lint`**](https://github.com/samchon/ttsc/tree/master/packages/lint): lint violations as compiler errors.
12
+ - [**`@ttsc/graph`**](https://github.com/samchon/ttsc/tree/master/packages/graph): MCP code graph that reduce token usage.
13
13
  - **plugin support**: compiler-powered libraries, such as `typia`.
14
14
 
15
15
  ## Setup
@@ -76,6 +76,7 @@ Supported bundlers:
76
76
  - Webpack
77
77
  - Rspack
78
78
  - Next.js
79
+ - Turbopack
79
80
  - Farm
80
81
  - Bun
81
82
 
@@ -127,12 +128,10 @@ See [`@ttsc/vscode`](https://github.com/samchon/ttsc/tree/master/packages/vscode
127
128
 
128
129
  ### Coding Agents (MCP)
129
130
 
130
- `@ttsc/graph` gives a coding agent a checker-resolved map of your project, over MCP.
131
+ `@ttsc/graph` gives a coding agent a checker-resolved graph of your project, over MCP.
131
132
 
132
133
  It answers what relates to a symbol and what a change affects, straight from the type checker, so the agent stops grepping and re-reading files.
133
134
 
134
- It also carries the project's full diagnostics: type errors, `@ttsc/lint` violations, and plugin findings. They are fused onto the graph, so an agent sees a change's reach over what is already broken before editing.
135
-
136
135
  ```bash
137
136
  npm install -D ttsc @ttsc/graph typescript
138
137
  ```
@@ -266,7 +265,7 @@ See the [Programmatic API guide](https://ttsc.dev/docs/ttsc/api) for the full li
266
265
 
267
266
  - [`@ttsc/banner`](https://github.com/samchon/ttsc/tree/master/packages/banner): adds `@packageDocumentation` JSDoc banners.
268
267
  - [`@ttsc/lint`](https://github.com/samchon/ttsc/tree/master/packages/lint): lints and formats TypeScript source.
269
- - [`@ttsc/graph`](https://github.com/samchon/ttsc/tree/master/packages/graph): MCP server exposing a checker-resolved code graph and diagnostics to coding agents.
268
+ - [`@ttsc/graph`](https://github.com/samchon/ttsc/tree/master/packages/graph): MCP server exposing a checker-resolved code graph to coding agents.
270
269
  - [`@ttsc/paths`](https://github.com/samchon/ttsc/tree/master/packages/paths): rewrites source path aliases so JS and declaration emit receive relative imports.
271
270
  - [`@ttsc/strip`](https://github.com/samchon/ttsc/tree/master/packages/strip): removes configured calls and `debugger` statements.
272
271
  - [`@ttsc/unplugin`](https://github.com/samchon/ttsc/tree/master/packages/unplugin): runs `ttsc` plugins inside bundlers supported by `unplugin`.
@@ -6,7 +6,7 @@
6
6
  // it N times and take medians.
7
7
  //
8
8
  // Counts and coverage are deterministic; timings are indicative and only
9
- // meaningful on a quiet host (see .codex/skills/benchmark).
9
+ // meaningful on a quiet host (see .agents/skills/benchmark/SKILL.md).
10
10
  package main
11
11
 
12
12
  import (
@@ -2,12 +2,10 @@
2
2
  //
3
3
  // The real compiler and runner commands live in the JavaScript launchers so
4
4
  // they can resolve the consuming project's `typescript` and
5
- // plugin descriptors. This binary only supplies version/platform metadata and
6
- // a tiny demo command for package smoke tests.
5
+ // plugin descriptors. This binary only supplies version/platform metadata.
7
6
  package main
8
7
 
9
8
  import (
10
- "flag"
11
9
  "fmt"
12
10
  "io"
13
11
  "os"
@@ -50,8 +48,6 @@ func run(args []string) int {
50
48
  case "-v", "--version", "version":
51
49
  printVersion(stdout)
52
50
  return 0
53
- case "demo":
54
- return runDemo(args[1:])
55
51
  case "build", "check":
56
52
  fmt.Fprintf(
57
53
  stderr,
@@ -90,48 +86,5 @@ plugin-selected native sidecar.
90
86
 
91
87
  Usage:
92
88
  ttsc --version
93
- ttsc demo --type=string
94
89
  `))
95
90
  }
96
-
97
- // runDemo implements the demo sub-command, printing a synthetic JavaScript
98
- // arrow function for the requested atomic type. Smoke tests in CI invoke this
99
- // to verify the binary executes correctly.
100
- func runDemo(args []string) int {
101
- fs := flag.NewFlagSet("demo", flag.ContinueOnError)
102
- fs.SetOutput(stderr)
103
- typ := fs.String("type", "string", "atomic type to simulate")
104
- if err := fs.Parse(args); err != nil {
105
- return 2
106
- }
107
-
108
- arrow, err := demoArrow(*typ)
109
- if err != nil {
110
- fmt.Fprintf(stderr, "ttsc platform helper demo: %v\n", err)
111
- return 2
112
- }
113
-
114
- fmt.Fprintf(stdout, "// demo<%s> -> emitted by ttsc platform helper %s\n", *typ, version)
115
- fmt.Fprintln(stdout, arrow)
116
- return 0
117
- }
118
-
119
- // demoArrow returns a JavaScript arrow-function expression for the named
120
- // atomic TypeScript type. It is the platform-helper counterpart of the same
121
- // function in cmd/ttsc, kept separate to avoid a shared-binary dependency.
122
- func demoArrow(name string) (string, error) {
123
- switch strings.ToLower(name) {
124
- case "any":
125
- return "(input) => true", nil
126
- case "boolean":
127
- return `(input) => "boolean" === typeof input`, nil
128
- case "number":
129
- return `(input) => "number" === typeof input`, nil
130
- case "bigint":
131
- return `(input) => "bigint" === typeof input`, nil
132
- case "string", "":
133
- return `(input) => "string" === typeof input`, nil
134
- default:
135
- return "", fmt.Errorf("unknown --type value %q (want: string|number|boolean|bigint|any)", name)
136
- }
137
- }
@@ -84,7 +84,11 @@ export { value };
84
84
  code, _, errText = captureCommand(t, func() int {
85
85
  return runBuild([]string{"--cwd", root, "--tsconfig", "tsconfig.json", "--emit", "--outDir", "blocked"})
86
86
  })
87
- if code != 2 || !strings.Contains(errText, "not a directory") {
87
+ // The write fails because outDir is a regular file. Assert on the exit code
88
+ // and the platform-agnostic TS5033 "Could not write file" diagnostic prefix,
89
+ // not the OS errno, which differs by platform (POSIX ENOTDIR "not a
90
+ // directory" vs Windows "The system cannot find the path specified").
91
+ if code != 2 || !strings.Contains(errText, "Could not write file") {
88
92
  t.Fatalf("emit failure mismatch: code=%d stderr=%q", code, errText)
89
93
  }
90
94
 
package/cmd/ttsc/main.go CHANGED
@@ -2,8 +2,6 @@
2
2
  //
3
3
  // Current responsibilities:
4
4
  // - Report version and platform (`ttsc --version`).
5
- // - Exercise a native rewrite backend end-to-end (`ttsc demo --type=string`)
6
- // so smoke tests can verify the Go binary really runs.
7
5
  // - Host the native project build and check paths used by plugin-selected
8
6
  // sidecars and smoke tests.
9
7
  //
@@ -12,7 +10,6 @@
12
10
  package main
13
11
 
14
12
  import (
15
- "flag"
16
13
  "fmt"
17
14
  "io"
18
15
  "os"
@@ -51,8 +48,6 @@ func run(args []string) int {
51
48
  case "-v", "--version", "version":
52
49
  printVersion(stdout)
53
50
  return 0
54
- case "demo":
55
- return runDemo(args[1:])
56
51
  case "build":
57
52
  return runBuild(args[1:])
58
53
  case "api-compile":
@@ -126,7 +121,6 @@ Project build:
126
121
  ttsc compiles the current tsconfig.json, matching the tsc/tsgo shape.
127
122
  build Compatibility alias for the same project build lane.
128
123
  check Compatibility alias for --noEmit validation.
129
- demo Run a native backend smoke pipeline with synthetic input.
130
124
  version Print version, build info, and platform.
131
125
  help Show this help.
132
126
 
@@ -139,16 +133,11 @@ Build options:
139
133
  --verbose Print the per-call summary banner and emitted file list.
140
134
  --manifest=FILE Write emitted file paths as JSON to FILE after build --emit.
141
135
 
142
- Demo options:
143
- --type=T Atomic TypeScript type to simulate. One of:
144
- string, number, boolean, bigint, any (default: string).
145
-
146
136
  Examples:
147
137
  ttsc --version
148
138
  ttsc
149
139
  ttsc -p ./tsconfig.json
150
140
  ttsc --noEmit
151
- ttsc demo --type=number
152
141
 
153
142
  Integration guide (bundlers):
154
143
  - Next.js / Nuxt / Bun: "ttsc" in your pipeline replaces tsc and
@@ -157,42 +146,3 @@ Integration guide (bundlers):
157
146
  per-package tsconfig.json references work unchanged.
158
147
  `))
159
148
  }
160
-
161
- func runDemo(args []string) int {
162
- fs := flag.NewFlagSet("demo", flag.ContinueOnError)
163
- fs.SetOutput(stderr)
164
- typ := fs.String("type", "string", "atomic type to simulate")
165
- if err := fs.Parse(args); err != nil {
166
- return 2
167
- }
168
-
169
- arrow, err := demoArrow(*typ)
170
- if err != nil {
171
- fmt.Fprintf(stderr, "ttsc demo: %v\n", err)
172
- return 2
173
- }
174
-
175
- fmt.Fprintf(stdout, "// demo<%s> -> emitted by ttsc %s\n", *typ, version)
176
- fmt.Fprintln(stdout, arrow)
177
- return 0
178
- }
179
-
180
- // demoArrow returns a JavaScript arrow-function expression that validates the
181
- // named atomic TypeScript type at runtime. Used by the demo sub-command to
182
- // produce a small synthetic emit that smoke tests can assert on.
183
- func demoArrow(name string) (string, error) {
184
- switch strings.ToLower(name) {
185
- case "any":
186
- return "(input) => true", nil
187
- case "boolean":
188
- return `(input) => "boolean" === typeof input`, nil
189
- case "number":
190
- return `(input) => "number" === typeof input`, nil
191
- case "bigint":
192
- return `(input) => "bigint" === typeof input`, nil
193
- case "string", "":
194
- return `(input) => "string" === typeof input`, nil
195
- default:
196
- return "", fmt.Errorf("unknown --type value %q (want: string|number|boolean|bigint|any)", name)
197
- }
198
- }
@@ -2,23 +2,17 @@ package main
2
2
 
3
3
  import "testing"
4
4
 
5
- // TestMainAliasBranches verifies main command aliases cover flag-shaped demo and cts project inputs.
5
+ // TestMainAliasBranches verifies `.cts` project inputs remain build aliases.
6
6
  //
7
7
  // The top-level dispatcher treats extension-shaped arguments as build aliases
8
- // while demo owns its own flag parser. These small branches keep compatibility
9
- // with `ttsc ./tsconfig.cts`-style invocations and malformed demo flags.
8
+ // so `ttsc ./tsconfig.cts` stays compatible with tsc-style invocations instead
9
+ // of being rejected as an unknown command.
10
10
  //
11
- // 1. Run demo with a missing flag value.
12
- // 2. Dispatch a `.cts` argument through the build alias path.
13
- // 3. Assert both routes fail through their intended parser.
11
+ // 1. Dispatch a `.cts` argument through the build alias path.
12
+ // 2. Let project discovery inspect the missing file.
13
+ // 3. Assert the build lane reports its command-error status.
14
14
  func TestMainAliasBranches(t *testing.T) {
15
15
  code, _, _ := captureCommand(t, func() int {
16
- return run([]string{"demo", "--type"})
17
- })
18
- if code != 2 {
19
- t.Fatalf("demo flag status mismatch: %d", code)
20
- }
21
- code, _, _ = captureCommand(t, func() int {
22
16
  return run([]string{"project.cts"})
23
17
  })
24
18
  if code != 2 {
@@ -59,11 +59,21 @@ func runDump(args []string) int {
59
59
 
60
60
  g := graph.Build(prog)
61
61
  ignored := graph.GitIgnoredFiles(cwd, g)
62
- data, err := graph.MarshalDump(g, cwd, tsconfig, ignored, graph.SourceTexts(prog), *prettyFlag)
63
- if err != nil {
62
+ // Stream the document out instead of marshalling it into one byte slice and
63
+ // then copying that slice into a string: on VS Code the dump is 323 MB, so
64
+ // the string conversion alone was a second full copy of it, for nothing. The
65
+ // encoder writes through a buffer straight to stdout.
66
+ if err := graph.EncodeDump(
67
+ stdout,
68
+ g,
69
+ cwd,
70
+ tsconfig,
71
+ ignored,
72
+ graph.SourceTexts(prog),
73
+ *prettyFlag,
74
+ ); err != nil {
64
75
  fmt.Fprintf(stderr, "ttscgraph: %v\n", err)
65
76
  return 1
66
77
  }
67
- fmt.Fprintln(stdout, string(data))
68
78
  return 0
69
79
  }
@@ -1,9 +1,7 @@
1
- // Command ttscgraph builds the checker-resolved code graph for a project and
2
- // prints it as JSON (`ttscgraph dump`). It is the native data provider for
3
- // @ttsc/graph: the JavaScript launcher runs `ttscgraph dump` once, then serves
4
- // the Model Context Protocol from the in-memory graph itself. The MCP server,
5
- // its tools, and their schemas live in @ttsc/graph (TypeScript); nothing here
6
- // answers tool calls.
1
+ // Command ttscgraph builds the checker-resolved code graph for a project. The
2
+ // one-shot `dump` command prints JSON; the internal `serve` command keeps an
3
+ // incremental compiler session resident for @ttsc/graph. MCP tools and schemas
4
+ // remain in the TypeScript package.
7
5
  package main
8
6
 
9
7
  import (
@@ -35,9 +33,9 @@ func main() {
35
33
  os.Exit(run(os.Args[1:]))
36
34
  }
37
35
 
38
- // run dispatches the top-level command and returns an exit code. ttscgraph is
39
- // dump-only; anything that is not help/version/dump prints usage and exits 2,
40
- // since serving MCP is the launcher's job.
36
+ // run dispatches the top-level command and returns an exit code. Anything that
37
+ // is not help, version, dump, or the internal serve protocol prints usage and
38
+ // exits 2; serving MCP itself remains the launcher's job.
41
39
  func run(args []string) int {
42
40
  if len(args) > 0 {
43
41
  switch args[0] {
@@ -49,6 +47,8 @@ func run(args []string) int {
49
47
  return 0
50
48
  case "dump":
51
49
  return runDump(args[1:])
50
+ case "serve":
51
+ return runServe(args[1:])
52
52
  }
53
53
  }
54
54
  printHelp(stderr)
@@ -72,12 +72,12 @@ func printHelp(w io.Writer) {
72
72
  fmt.Fprintln(w, strings.TrimSpace(`
73
73
  ttscgraph — checker-resolved code graph for ttsc.
74
74
 
75
- Builds the project's code graph and prints it as JSON. The @ttsc/graph launcher
76
- runs this and serves the Model Context Protocol from the result; the MCP tools
77
- live in @ttsc/graph, not here.
75
+ Builds the project's code graph as JSON or keeps an incremental compiler session
76
+ for the @ttsc/graph launcher. The MCP tools live in @ttsc/graph, not here.
78
77
 
79
78
  Usage:
80
79
  ttscgraph dump [--cwd <dir>] [--tsconfig <path>] [--pretty] > graph.json
80
+ ttscgraph serve [--cwd <dir>] [--tsconfig <path>]
81
81
  ttscgraph --version
82
82
  ttscgraph --help
83
83
 
@@ -87,5 +87,11 @@ Dump:
87
87
  --cwd <dir> Project root (defaults to the process working directory).
88
88
  --tsconfig <path> Project tsconfig path (default: tsconfig.json).
89
89
  --pretty Indent the JSON output.
90
+
91
+ Serve:
92
+ serve Internal newline-delimited snapshot protocol used by
93
+ @ttsc/graph. Keeps the compiler Program resident, applies
94
+ source edits incrementally, and reloads on structural
95
+ project changes.
90
96
  `))
91
97
  }
@@ -8,9 +8,10 @@ import (
8
8
  )
9
9
 
10
10
  // TestRunHelpVersionAndBadFlagsExitCodes verifies the top-level run dispatcher
11
- // returns the documented exit codes for the dump-only command surface: help and
12
- // version short-circuit to 0, an unknown command prints usage and exits 2, and a
13
- // dump that cannot resolve its working directory exits 2 with an explanation.
11
+ // returns the documented exit codes for the command surface: help and version
12
+ // short-circuit to 0, an unknown command prints usage and exits 2, and dump or
13
+ // serve invocations that cannot parse flags or resolve their working directory
14
+ // exit 2 with an explanation.
14
15
  //
15
16
  // These are the non-load paths a user hits with a typo or `--help`; each must
16
17
  // resolve to a code without building a Program. The getwd seam stands in for an
@@ -19,8 +20,8 @@ import (
19
20
  //
20
21
  // 1. run --help and run --version exit 0, printing the command name / version.
21
22
  // 2. run --bogus (unknown command) exits 2 and prints usage.
22
- // 3. run dump --nope exits 2 (dump flag parse failure).
23
- // 4. With getwd forced to fail, run dump exits 2 and explains why.
23
+ // 3. run dump --nope and run serve --nope exit 2 (flag parse failure).
24
+ // 4. With getwd forced to fail, run dump and run serve exit 2 and explain why.
24
25
  func TestRunHelpVersionAndBadFlagsExitCodes(t *testing.T) {
25
26
  oldStdout, oldStderr, oldGetwd := stdout, stderr, getwd
26
27
  defer func() { stdout, stderr, getwd = oldStdout, oldStderr, oldGetwd }()
@@ -62,6 +63,13 @@ func TestRunHelpVersionAndBadFlagsExitCodes(t *testing.T) {
62
63
  t.Fatalf("run dump --nope exit = %d, want 2", code)
63
64
  }
64
65
 
66
+ // An unknown serve flag is an invalid invocation: serve's flag.Parse fails -> 2.
67
+ var serveFlagErr bytes.Buffer
68
+ stderr = &serveFlagErr
69
+ if code := run([]string{"serve", "--nope"}); code != 2 {
70
+ t.Fatalf("run serve --nope exit = %d, want 2", code)
71
+ }
72
+
65
73
  // A getwd failure (no --cwd given) is an invalid invocation -> 2, explained.
66
74
  var wdErr bytes.Buffer
67
75
  stderr = &wdErr
@@ -72,4 +80,14 @@ func TestRunHelpVersionAndBadFlagsExitCodes(t *testing.T) {
72
80
  if !strings.Contains(wdErr.String(), "could not resolve working directory") {
73
81
  t.Fatalf("getwd failure did not explain itself:\n%s", wdErr.String())
74
82
  }
83
+
84
+ // serve resolves the working directory the same way before touching stdin.
85
+ var serveWdErr bytes.Buffer
86
+ stderr = &serveWdErr
87
+ if code := run([]string{"serve"}); code != 2 {
88
+ t.Fatalf("run serve with getwd failure exit = %d, want 2", code)
89
+ }
90
+ if !strings.Contains(serveWdErr.String(), "could not resolve working directory") {
91
+ t.Fatalf("serve getwd failure did not explain itself:\n%s", serveWdErr.String())
92
+ }
75
93
  }