ttsc 0.12.2 → 0.12.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cmd/platform/main.go +9 -0
- package/cmd/ttsc/api_compile.go +109 -101
- package/cmd/ttsc/api_compile_branches_test.go +55 -57
- package/cmd/ttsc/api_transform.go +54 -49
- package/cmd/ttsc/api_transform_branches_test.go +30 -32
- package/cmd/ttsc/build.go +111 -108
- package/cmd/ttsc/build_branches_test.go +95 -97
- package/cmd/ttsc/helpers_test.go +39 -28
- package/cmd/ttsc/main.go +111 -104
- package/cmd/ttsc/main_alias_branches_test.go +21 -23
- package/cmd/ttscserver/main.go +96 -90
- package/cmd/ttscserver/run_lsp_prefers_tsgo_flag_test.go +22 -22
- package/cmd/ttscserver/run_lsp_reports_server_error_test.go +22 -22
- package/cmd/ttscserver/run_lsp_uses_tsgo_environment_test.go +23 -23
- package/cmd/utility-host/main.go +30 -23
- package/driver/lsp.go +53 -7
- package/driver/plugins.go +88 -72
- package/driver/program.go +362 -339
- package/driver/rewrite.go +442 -380
- package/internal/lspserver/lsp_envelope.go +64 -64
- package/internal/lspserver/lsp_frame.go +60 -60
- package/internal/lspserver/lsp_plugin.go +57 -57
- package/internal/lspserver/lsp_proxy.go +265 -251
- package/internal/lspserver/lsp_server.go +155 -144
- package/lib/TtscCompiler.d.ts +7 -0
- package/lib/TtscCompiler.js +7 -0
- package/lib/TtscCompiler.js.map +1 -1
- package/lib/compiler/internal/buildNativeCompiler.d.ts +11 -1
- package/lib/compiler/internal/buildNativeCompiler.js +23 -3
- package/lib/compiler/internal/buildNativeCompiler.js.map +1 -1
- package/lib/compiler/internal/compileProjectInMemory.d.ts +9 -0
- package/lib/compiler/internal/compileProjectInMemory.js +36 -21
- package/lib/compiler/internal/compileProjectInMemory.js.map +1 -1
- package/lib/compiler/internal/paths.d.ts +27 -0
- package/lib/compiler/internal/paths.js +70 -0
- package/lib/compiler/internal/paths.js.map +1 -0
- package/lib/compiler/internal/project/readProjectConfig.d.ts +9 -1
- package/lib/compiler/internal/project/readProjectConfig.js +80 -1
- package/lib/compiler/internal/project/readProjectConfig.js.map +1 -1
- package/lib/compiler/internal/project/resolveProjectConfig.d.ts +13 -1
- package/lib/compiler/internal/project/resolveProjectConfig.js +24 -1
- package/lib/compiler/internal/project/resolveProjectConfig.js.map +1 -1
- package/lib/compiler/internal/resolveBinary.d.ts +9 -1
- package/lib/compiler/internal/resolveBinary.js +17 -1
- package/lib/compiler/internal/resolveBinary.js.map +1 -1
- package/lib/compiler/internal/resolveEmittedJavaScript.d.ts +16 -1
- package/lib/compiler/internal/resolveEmittedJavaScript.js +42 -10
- package/lib/compiler/internal/resolveEmittedJavaScript.js.map +1 -1
- package/lib/compiler/internal/resolveTsgo.d.ts +21 -1
- package/lib/compiler/internal/resolveTsgo.js +23 -1
- package/lib/compiler/internal/resolveTsgo.js.map +1 -1
- package/lib/compiler/internal/runBuild.d.ts +19 -0
- package/lib/compiler/internal/runBuild.js +112 -46
- package/lib/compiler/internal/runBuild.js.map +1 -1
- package/lib/compiler/internal/runSingleFileEmit.d.ts +10 -1
- package/lib/compiler/internal/runSingleFileEmit.js +14 -1
- package/lib/compiler/internal/runSingleFileEmit.js.map +1 -1
- package/lib/compiler/internal/sharedHostHelpers.d.ts +5 -0
- package/lib/compiler/internal/sharedHostHelpers.js +6 -2
- package/lib/compiler/internal/sharedHostHelpers.js.map +1 -1
- package/lib/compiler/internal/spawnNative.d.ts +21 -0
- package/lib/compiler/internal/spawnNative.js +59 -0
- package/lib/compiler/internal/spawnNative.js.map +1 -0
- package/lib/compiler/internal/transformProjectInMemory.d.ts +15 -1
- package/lib/compiler/internal/transformProjectInMemory.js +57 -61
- package/lib/compiler/internal/transformProjectInMemory.js.map +1 -1
- package/lib/launcher/internal/getCompilerVersionText.js +7 -0
- package/lib/launcher/internal/getCompilerVersionText.js.map +1 -1
- package/lib/launcher/internal/prepareExecution.js +32 -0
- package/lib/launcher/internal/prepareExecution.js.map +1 -1
- package/lib/launcher/internal/resolveCacheDir.d.ts +9 -0
- package/lib/launcher/internal/resolveCacheDir.js +22 -0
- package/lib/launcher/internal/resolveCacheDir.js.map +1 -0
- package/lib/launcher/internal/resolveTtscserverBinary.js +2 -0
- package/lib/launcher/internal/resolveTtscserverBinary.js.map +1 -1
- package/lib/launcher/internal/runTtsc.d.ts +10 -0
- package/lib/launcher/internal/runTtsc.js +101 -16
- package/lib/launcher/internal/runTtsc.js.map +1 -1
- package/lib/launcher/internal/runTtscserver.js +10 -35
- package/lib/launcher/internal/runTtscserver.js.map +1 -1
- package/lib/launcher/internal/runTtsx.d.ts +8 -0
- package/lib/launcher/internal/runTtsx.js +33 -7
- package/lib/launcher/internal/runTtsx.js.map +1 -1
- package/lib/plugin/internal/buildSourcePlugin.d.ts +38 -0
- package/lib/plugin/internal/buildSourcePlugin.js +40 -17
- package/lib/plugin/internal/buildSourcePlugin.js.map +1 -1
- package/lib/plugin/internal/loadProjectPlugins.d.ts +26 -0
- package/lib/plugin/internal/loadProjectPlugins.js +32 -18
- package/lib/plugin/internal/loadProjectPlugins.js.map +1 -1
- package/lib/structures/ITtscCompilerTransformation.d.ts +15 -2
- package/lib/structures/internal/TtscSingleFileEmitOptions.d.ts +0 -2
- package/package.json +9 -9
- package/shim/ast/go.mod +9 -0
- package/shim/ast/go.sum +20 -0
- package/shim/ast/safe_text.go +86 -0
- package/shim/ast/shim.go +24 -0
- package/shim/ast/test/node_text_joins_multi_hop_qualified_name_test.go +32 -0
- package/shim/ast/test/node_text_joins_one_hop_qualified_name_test.go +31 -0
- package/shim/ast/test/node_text_returns_empty_for_nil_test.go +23 -0
- package/shim/ast/test/node_text_returns_identifier_text_test.go +27 -0
- package/shim/ast/test/node_text_skips_empty_qualified_left_test.go +30 -0
- package/shim/checker/shim.go +35 -0
- package/shim/core/shim.go +17 -0
- package/shim/diagnosticwriter/shim.go +4 -0
- package/shim/lsp/shim.go +3 -3
- package/shim/printer/shim.go +20 -0
- package/src/TtscCompiler.ts +7 -0
- package/src/compiler/internal/buildNativeCompiler.ts +23 -3
- package/src/compiler/internal/compileProjectInMemory.ts +34 -25
- package/src/compiler/internal/paths.ts +68 -0
- package/src/compiler/internal/project/readProjectConfig.ts +86 -1
- package/src/compiler/internal/project/resolveProjectConfig.ts +24 -1
- package/src/compiler/internal/resolveBinary.ts +17 -1
- package/src/compiler/internal/resolveEmittedJavaScript.ts +43 -12
- package/src/compiler/internal/resolveTsgo.ts +29 -1
- package/src/compiler/internal/runBuild.ts +110 -55
- package/src/compiler/internal/runSingleFileEmit.ts +14 -1
- package/src/compiler/internal/sharedHostHelpers.ts +7 -7
- package/src/compiler/internal/spawnNative.ts +64 -0
- package/src/compiler/internal/transformProjectInMemory.ts +47 -67
- package/src/launcher/internal/getCompilerVersionText.ts +7 -0
- package/src/launcher/internal/prepareExecution.ts +32 -0
- package/src/launcher/internal/resolveCacheDir.ts +19 -0
- package/src/launcher/internal/resolveTtscserverBinary.ts +2 -0
- package/src/launcher/internal/runTtsc.ts +120 -20
- package/src/launcher/internal/runTtscserver.ts +9 -1
- package/src/launcher/internal/runTtsx.ts +33 -8
- package/src/plugin/internal/buildSourcePlugin.ts +40 -14
- package/src/plugin/internal/loadProjectPlugins.ts +42 -18
- package/src/structures/ITtscCompilerTransformation.ts +15 -2
- package/src/structures/ITtscPlugin.ts +0 -1
- package/src/structures/internal/TtscSingleFileEmitOptions.ts +0 -2
- package/tools/gen_shims/main.go +43 -8
- package/utility/host.go +294 -245
|
@@ -7,7 +7,14 @@ import { resolveEmittedJavaScript } from "../../compiler/internal/resolveEmitted
|
|
|
7
7
|
import { runBuild } from "../../compiler/internal/runBuild";
|
|
8
8
|
import type { TtscCommonOptions } from "../../structures/internal/TtscCommonOptions";
|
|
9
9
|
|
|
10
|
+
/** Subdirectory name that isolates concurrent ttsx processes by PID. */
|
|
10
11
|
const PROCESS_CACHE_KEY = String(process.pid);
|
|
12
|
+
/**
|
|
13
|
+
* Maximum number of ancestor directories above the project root that the
|
|
14
|
+
* virtual filesystem overlay mirrors. Three levels covers the common monorepo
|
|
15
|
+
* layout (workspace-root → packages → package-root) so `node_modules` symlinks
|
|
16
|
+
* resolve correctly without reaching an unsafe boundary.
|
|
17
|
+
*/
|
|
11
18
|
const MAX_VIRTUAL_PARENT_DEPTH = 3;
|
|
12
19
|
|
|
13
20
|
/** Build the owning project and locate the emitted JavaScript entry for `ttsx`. */
|
|
@@ -162,6 +169,7 @@ function linkVirtualEntry(
|
|
|
162
169
|
entry: fs.Dirent,
|
|
163
170
|
): void {
|
|
164
171
|
if (entry.isDirectory()) {
|
|
172
|
+
// Use junction points on Windows; plain symlinks elsewhere.
|
|
165
173
|
fs.symlinkSync(
|
|
166
174
|
realEntry,
|
|
167
175
|
virtualEntry,
|
|
@@ -171,15 +179,25 @@ function linkVirtualEntry(
|
|
|
171
179
|
}
|
|
172
180
|
if (entry.isFile()) {
|
|
173
181
|
try {
|
|
182
|
+
// Hard-link first: cheap, preserves inode, no extra disk usage.
|
|
174
183
|
fs.linkSync(realEntry, virtualEntry);
|
|
175
184
|
} catch {
|
|
185
|
+
// Cross-device or unsupported filesystem: fall back to a full copy.
|
|
176
186
|
fs.copyFileSync(realEntry, virtualEntry);
|
|
177
187
|
}
|
|
178
188
|
return;
|
|
179
189
|
}
|
|
190
|
+
// Symlinks (and other special entries) are re-symlinked as-is.
|
|
180
191
|
fs.symlinkSync(realEntry, virtualEntry);
|
|
181
192
|
}
|
|
182
193
|
|
|
194
|
+
/**
|
|
195
|
+
* Walk from `projectRoot` upward (up to `MAX_VIRTUAL_PARENT_DEPTH` steps),
|
|
196
|
+
* stopping early at a workspace root (`pnpm-workspace.yaml` or `.git`). The
|
|
197
|
+
* collected directories are reversed so callers can iterate outermost-first,
|
|
198
|
+
* which lets inner symlinks override outer ones without conflicting mkdir
|
|
199
|
+
* calls.
|
|
200
|
+
*/
|
|
183
201
|
function collectLinkDirectories(projectRoot: string): string[] {
|
|
184
202
|
const out: string[] = [];
|
|
185
203
|
let current = projectRoot;
|
|
@@ -207,6 +225,14 @@ function isUnsafeVirtualParent(directory: string): boolean {
|
|
|
207
225
|
return resolved === root || resolved === path.resolve(os.tmpdir());
|
|
208
226
|
}
|
|
209
227
|
|
|
228
|
+
/**
|
|
229
|
+
* Map an absolute path into a stable, filesystem-safe subtree under `root`.
|
|
230
|
+
*
|
|
231
|
+
* On POSIX the root is always `/`, so every path shares the same prefix —
|
|
232
|
+
* represented here as `"posix"`. On Windows, drive letters and UNC roots each
|
|
233
|
+
* get a sanitized label (e.g. `"C_"` for `C:\`), preventing collisions between
|
|
234
|
+
* paths from different drives inside the same virtual root.
|
|
235
|
+
*/
|
|
210
236
|
function virtualPath(root: string, absolute: string): string {
|
|
211
237
|
const parsed = path.parse(path.resolve(absolute));
|
|
212
238
|
const label =
|
|
@@ -218,6 +244,12 @@ function virtualPath(root: string, absolute: string): string {
|
|
|
218
244
|
return path.join(root, label, relative);
|
|
219
245
|
}
|
|
220
246
|
|
|
247
|
+
/**
|
|
248
|
+
* Heuristic: classify emitted JS as ESM when it contains top-level `import` or
|
|
249
|
+
* `export` statements but none of the well-known CJS patterns. The CJS checks
|
|
250
|
+
* run first so that re-exported CJS bundles with both `require` calls and an
|
|
251
|
+
* `export` declaration are conservatively treated as CJS.
|
|
252
|
+
*/
|
|
221
253
|
function looksLikeESM(output: string): boolean {
|
|
222
254
|
if (
|
|
223
255
|
/\bObject\.defineProperty\(exports\b/.test(output) ||
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Resolve a user-supplied `--cache-dir` value into an absolute path.
|
|
5
|
+
*
|
|
6
|
+
* When `cacheDir` is absent or empty, returns `undefined` so callers fall
|
|
7
|
+
* through to the environment variable and global-cache defaults handled inside
|
|
8
|
+
* `buildSourcePlugin`. When `cacheDir` is already absolute it is returned
|
|
9
|
+
* unchanged; otherwise it is resolved relative to `cwd`.
|
|
10
|
+
*/
|
|
11
|
+
export function resolveCacheDir(
|
|
12
|
+
cwd: string,
|
|
13
|
+
cacheDir?: string,
|
|
14
|
+
): string | undefined {
|
|
15
|
+
if (!cacheDir) {
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
return path.isAbsolute(cacheDir) ? cacheDir : path.resolve(cwd, cacheDir);
|
|
19
|
+
}
|
|
@@ -47,5 +47,7 @@ function defaultLocalBinaryPath(): string | null {
|
|
|
47
47
|
|
|
48
48
|
function packageRootDir(): string {
|
|
49
49
|
const moduleDir = path.resolve(__dirname, "..", "..");
|
|
50
|
+
// Prefer the faster native variant; fall back to the JS implementation on
|
|
51
|
+
// platforms (or environments) where `realpathSync.native` is unavailable.
|
|
50
52
|
return fs.realpathSync.native?.(moduleDir) ?? fs.realpathSync(moduleDir);
|
|
51
53
|
}
|
|
@@ -3,6 +3,7 @@ import fs from "node:fs";
|
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
|
|
5
5
|
import { TtscCompiler } from "../../TtscCompiler";
|
|
6
|
+
import { readProjectConfig } from "../../compiler/internal/project/readProjectConfig";
|
|
6
7
|
import { resolveProjectConfig } from "../../compiler/internal/project/resolveProjectConfig";
|
|
7
8
|
import { resolveBinary } from "../../compiler/internal/resolveBinary";
|
|
8
9
|
import { runBuild } from "../../compiler/internal/runBuild";
|
|
@@ -10,7 +11,18 @@ import { runSingleFileEmit } from "../../compiler/internal/runSingleFileEmit";
|
|
|
10
11
|
import { defaultPluginCacheCleanTargets } from "../../plugin/internal/buildSourcePlugin";
|
|
11
12
|
import type { TtscBuildOptions } from "../../structures/internal/TtscBuildOptions";
|
|
12
13
|
import { getCompilerVersionText } from "./getCompilerVersionText";
|
|
14
|
+
import { resolveCacheDir } from "./resolveCacheDir";
|
|
13
15
|
|
|
16
|
+
/**
|
|
17
|
+
* CLI entry point for `ttsc`. Dispatches argv to the appropriate build lane
|
|
18
|
+
* (build, check, fix, format, prepare, clean, or native-delegate) and returns
|
|
19
|
+
* an exit code. Errors thrown by any lane are caught here and written to stderr
|
|
20
|
+
* so the process can exit cleanly.
|
|
21
|
+
*
|
|
22
|
+
* @param argv - Command-line arguments (defaults to `process.argv.slice(2)`).
|
|
23
|
+
* @returns The exit code: `0` on success, `1` on binary-not-found, `2` on user
|
|
24
|
+
* error or build failure.
|
|
25
|
+
*/
|
|
14
26
|
export function runTtsc(
|
|
15
27
|
argv: readonly string[] = process.argv.slice(2),
|
|
16
28
|
): number {
|
|
@@ -66,6 +78,12 @@ export function runTtsc(
|
|
|
66
78
|
}
|
|
67
79
|
}
|
|
68
80
|
|
|
81
|
+
/**
|
|
82
|
+
* Return `true` when `command` looks like a build argument rather than a
|
|
83
|
+
* subcommand name — a flag (`-p`, `--watch`, …) or a TypeScript/config file
|
|
84
|
+
* path. These are forwarded to the build lane unchanged so users can write
|
|
85
|
+
* `ttsc -p tsconfig.json` without an explicit `build` subcommand.
|
|
86
|
+
*/
|
|
69
87
|
function isBuildAlias(command: string): boolean {
|
|
70
88
|
if (command.startsWith("-")) return true;
|
|
71
89
|
return [".json", ".ts", ".tsx", ".mts", ".cts"].some((ext) =>
|
|
@@ -361,6 +379,8 @@ function parseBuildArgs(argv: readonly string[], checkOnly: boolean) {
|
|
|
361
379
|
} else if (current.startsWith("--outDir=")) {
|
|
362
380
|
outDir = current.slice("--outDir=".length);
|
|
363
381
|
} else if (current === "-w") {
|
|
382
|
+
// Unreachable: `-w` is handled by the switch case above. Kept here
|
|
383
|
+
// as a guard in case the switch is refactored in the future.
|
|
364
384
|
watch = true;
|
|
365
385
|
} else if (current.startsWith("--tsconfig=")) {
|
|
366
386
|
tsconfig = current.slice("--tsconfig=".length);
|
|
@@ -374,6 +394,7 @@ function parseBuildArgs(argv: readonly string[], checkOnly: boolean) {
|
|
|
374
394
|
} else if (current.startsWith("--cache-dir=")) {
|
|
375
395
|
cacheDir = current.slice("--cache-dir=".length);
|
|
376
396
|
} else if (current === "--verbose") {
|
|
397
|
+
// Unreachable: `--verbose` is handled by the switch case above.
|
|
377
398
|
quiet = false;
|
|
378
399
|
} else if (current.startsWith("-")) {
|
|
379
400
|
throw new Error(`ttsc: unknown option ${current}`);
|
|
@@ -455,7 +476,12 @@ function runSingleFile(options: ReturnType<typeof parseBuildArgs>): number {
|
|
|
455
476
|
}
|
|
456
477
|
const cwd = path.resolve(options.cwd ?? process.cwd());
|
|
457
478
|
const file = path.resolve(cwd, options.files[0]!);
|
|
458
|
-
const out = resolveSingleFileOut(
|
|
479
|
+
const out = resolveSingleFileOut({
|
|
480
|
+
cliOutDir: options.outDir,
|
|
481
|
+
cwd,
|
|
482
|
+
file,
|
|
483
|
+
tsconfig: options.tsconfig,
|
|
484
|
+
});
|
|
459
485
|
const text = runSingleFileEmit({
|
|
460
486
|
binary: options.binary,
|
|
461
487
|
cwd,
|
|
@@ -471,17 +497,99 @@ function runSingleFile(options: ReturnType<typeof parseBuildArgs>): number {
|
|
|
471
497
|
return 0;
|
|
472
498
|
}
|
|
473
499
|
|
|
474
|
-
function resolveSingleFileOut(
|
|
475
|
-
|
|
476
|
-
cwd: string
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
const
|
|
481
|
-
|
|
482
|
-
|
|
500
|
+
function resolveSingleFileOut(opts: {
|
|
501
|
+
cliOutDir?: string;
|
|
502
|
+
cwd: string;
|
|
503
|
+
file: string;
|
|
504
|
+
tsconfig?: string;
|
|
505
|
+
}): string {
|
|
506
|
+
const jsBasename =
|
|
507
|
+
path.basename(opts.file).replace(/\.[cm]?tsx?$/i, "") +
|
|
508
|
+
singleFileJsExtension(opts.file);
|
|
509
|
+
|
|
510
|
+
// Explicit CLI --outDir wins. Mirrors the CWD-relative source layout under
|
|
511
|
+
// the requested directory so existing single-file invocations don't shift.
|
|
512
|
+
if (opts.cliOutDir) {
|
|
513
|
+
const relative = path.relative(opts.cwd, opts.file);
|
|
514
|
+
const jsRelative =
|
|
515
|
+
relative.slice(0, relative.length - path.extname(relative).length) +
|
|
516
|
+
singleFileJsExtension(opts.file);
|
|
517
|
+
return path.resolve(opts.cwd, opts.cliOutDir, jsRelative);
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
// No CLI override: honor tsconfig's outDir so `ttsc src/foo.ts` lands the
|
|
521
|
+
// emitted JS at `<outDir>/<relative-from-rootDir>.js` instead of dropping
|
|
522
|
+
// it next to the source file. This matches how project mode emits and how
|
|
523
|
+
// `tsc <file>` would behave with the same tsconfig.
|
|
524
|
+
const projectOutDir = readProjectOutDir({
|
|
525
|
+
cwd: opts.cwd,
|
|
526
|
+
file: opts.file,
|
|
527
|
+
tsconfig: opts.tsconfig,
|
|
528
|
+
});
|
|
529
|
+
if (projectOutDir !== null) {
|
|
530
|
+
const fromRoot = path.relative(projectOutDir.rootDir, opts.file);
|
|
531
|
+
if (fromRoot !== "" && !isOutsideSingleFileLayout(fromRoot)) {
|
|
532
|
+
const jsRelative =
|
|
533
|
+
fromRoot.slice(0, fromRoot.length - path.extname(fromRoot).length) +
|
|
534
|
+
singleFileJsExtension(opts.file);
|
|
535
|
+
return path.resolve(projectOutDir.outDir, jsRelative);
|
|
536
|
+
}
|
|
537
|
+
return path.resolve(projectOutDir.outDir, jsBasename);
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
// Last resort (no tsconfig outDir at all): emit next to the source. This
|
|
541
|
+
// preserves the legacy `ttsc <file.ts>` → `<file.js>` behavior for projects
|
|
542
|
+
// that intentionally don't configure outDir.
|
|
543
|
+
return opts.file.replace(/\.[cm]?tsx?$/i, singleFileJsExtension(opts.file));
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
function readProjectOutDir(opts: {
|
|
547
|
+
cwd: string;
|
|
548
|
+
file: string;
|
|
549
|
+
tsconfig?: string;
|
|
550
|
+
}): { outDir: string; rootDir: string } | null {
|
|
551
|
+
try {
|
|
552
|
+
const project = readProjectConfig({
|
|
553
|
+
cwd: opts.cwd,
|
|
554
|
+
file: opts.file,
|
|
555
|
+
tsconfig: opts.tsconfig,
|
|
556
|
+
});
|
|
557
|
+
const outDir = project.compilerOptions.outDir;
|
|
558
|
+
if (typeof outDir !== "string" || outDir.length === 0) {
|
|
559
|
+
return null;
|
|
560
|
+
}
|
|
561
|
+
const rawRoot = project.compilerOptions.rootDir;
|
|
562
|
+
const rootDir =
|
|
563
|
+
typeof rawRoot === "string" && rawRoot.length !== 0
|
|
564
|
+
? path.isAbsolute(rawRoot)
|
|
565
|
+
? rawRoot
|
|
566
|
+
: path.resolve(project.root, rawRoot)
|
|
567
|
+
: project.root;
|
|
568
|
+
return { outDir, rootDir };
|
|
569
|
+
} catch {
|
|
570
|
+
// Missing or unreadable tsconfig: fall back to the legacy behavior so
|
|
571
|
+
// `ttsc <file>` still works outside a configured project.
|
|
572
|
+
return null;
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
function isOutsideSingleFileLayout(relative: string): boolean {
|
|
577
|
+
return (
|
|
578
|
+
relative === ".." ||
|
|
579
|
+
relative.startsWith(`..${path.sep}`) ||
|
|
580
|
+
path.isAbsolute(relative)
|
|
581
|
+
);
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
function singleFileJsExtension(file: string): string {
|
|
585
|
+
switch (path.extname(file).toLowerCase()) {
|
|
586
|
+
case ".mts":
|
|
587
|
+
return ".mjs";
|
|
588
|
+
case ".cts":
|
|
589
|
+
return ".cjs";
|
|
590
|
+
default:
|
|
591
|
+
return ".js";
|
|
483
592
|
}
|
|
484
|
-
return file.replace(/\.[cm]?tsx?$/i, ".js");
|
|
485
593
|
}
|
|
486
594
|
|
|
487
595
|
function runWatch(
|
|
@@ -500,8 +608,7 @@ function runWatch(
|
|
|
500
608
|
tsconfig: options.tsconfig,
|
|
501
609
|
}),
|
|
502
610
|
);
|
|
503
|
-
const
|
|
504
|
-
const directories = collectWatchDirectories(watchRoot);
|
|
611
|
+
const directories = collectWatchDirectories(root);
|
|
505
612
|
const watchers = directories.map((dir) =>
|
|
506
613
|
fs.watch(dir, { persistent: true }, () => trigger()),
|
|
507
614
|
);
|
|
@@ -564,13 +671,6 @@ function runWatch(
|
|
|
564
671
|
return 0;
|
|
565
672
|
}
|
|
566
673
|
|
|
567
|
-
function resolveCacheDir(cwd: string, cacheDir?: string): string | undefined {
|
|
568
|
-
if (!cacheDir) {
|
|
569
|
-
return undefined;
|
|
570
|
-
}
|
|
571
|
-
return path.isAbsolute(cacheDir) ? cacheDir : path.resolve(cwd, cacheDir);
|
|
572
|
-
}
|
|
573
|
-
|
|
574
674
|
function collectWatchDirectories(root: string): string[] {
|
|
575
675
|
const out: string[] = [];
|
|
576
676
|
const stack: string[] = [root];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { spawnSync } from "node:child_process";
|
|
2
2
|
import fs from "node:fs";
|
|
3
|
-
import
|
|
3
|
+
import os from "node:os";
|
|
4
4
|
|
|
5
5
|
import { resolveTsgo } from "../../compiler/internal/resolveTsgo";
|
|
6
6
|
import { resolveTtscserverBinary } from "./resolveTtscserverBinary";
|
|
@@ -66,8 +66,16 @@ export function runTtscserver(
|
|
|
66
66
|
return result.status ?? 1;
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
+
/**
|
|
70
|
+
* Build the environment for the native binary. When running in `--stdio` (LSP)
|
|
71
|
+
* mode the Go binary needs to know which tsgo binary to wrap; inject
|
|
72
|
+
* `TTSC_TSGO_BINARY` so the native host does not have to re-resolve it from
|
|
73
|
+
* inside a potentially different working directory. Skip injection when the
|
|
74
|
+
* caller already provided the variable or passed an explicit `--tsgo` option.
|
|
75
|
+
*/
|
|
69
76
|
function resolveTtscserverEnv(argv: readonly string[]): NodeJS.ProcessEnv {
|
|
70
77
|
if (!argv.includes("--stdio")) {
|
|
78
|
+
// Non-LSP invocations (--version, --help) do not shell out to tsgo.
|
|
71
79
|
return process.env;
|
|
72
80
|
}
|
|
73
81
|
if (process.env.TTSC_TSGO_BINARY || hasTsgoOption(argv)) {
|
|
@@ -4,7 +4,16 @@ import path from "node:path";
|
|
|
4
4
|
|
|
5
5
|
import { getCompilerVersionText } from "./getCompilerVersionText";
|
|
6
6
|
import { prepareExecution } from "./prepareExecution";
|
|
7
|
-
|
|
7
|
+
import { resolveCacheDir } from "./resolveCacheDir";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* CLI entry point for `ttsx`. Type-checks the owning project via tsgo, emits
|
|
11
|
+
* JavaScript to a PID-isolated temp directory, rewrites ESM specifiers when
|
|
12
|
+
* needed, and executes the compiled entry with the current Node.js runtime.
|
|
13
|
+
*
|
|
14
|
+
* @param argv - Command-line arguments (defaults to `process.argv.slice(2)`).
|
|
15
|
+
* @returns The child-process exit code, or `2` on a ttsx-level error.
|
|
16
|
+
*/
|
|
8
17
|
export function runTtsx(
|
|
9
18
|
argv: readonly string[] = process.argv.slice(2),
|
|
10
19
|
): number {
|
|
@@ -172,13 +181,6 @@ function isRelativeSpecifier(specifier: string): boolean {
|
|
|
172
181
|
);
|
|
173
182
|
}
|
|
174
183
|
|
|
175
|
-
function resolveCacheDir(cwd: string, cacheDir?: string): string | undefined {
|
|
176
|
-
if (!cacheDir) {
|
|
177
|
-
return undefined;
|
|
178
|
-
}
|
|
179
|
-
return path.isAbsolute(cacheDir) ? cacheDir : path.resolve(cwd, cacheDir);
|
|
180
|
-
}
|
|
181
|
-
|
|
182
184
|
function takeValue(flag: string, rest: string[]): string {
|
|
183
185
|
const value = rest.shift();
|
|
184
186
|
if (!value) {
|
|
@@ -222,6 +224,12 @@ function runPreparedEntry(
|
|
|
222
224
|
return result.status ?? 1;
|
|
223
225
|
}
|
|
224
226
|
|
|
227
|
+
/**
|
|
228
|
+
* Walk every `.js`/`.mjs`/`.cjs` file in `root` and rewrite bare relative
|
|
229
|
+
* specifiers (e.g. `"./foo"`) to include the resolved file extension so Node
|
|
230
|
+
* can load them with `--input-type=module`. Files that did not change are not
|
|
231
|
+
* written back.
|
|
232
|
+
*/
|
|
225
233
|
function rewriteEsmSpecifiers(root: string): void {
|
|
226
234
|
const stack = [root];
|
|
227
235
|
while (stack.length !== 0) {
|
|
@@ -431,26 +439,37 @@ function findTemplateExpressionEnd(
|
|
|
431
439
|
return null;
|
|
432
440
|
}
|
|
433
441
|
|
|
442
|
+
/**
|
|
443
|
+
* Append or fix a file extension on a relative specifier so that Node's ESM
|
|
444
|
+
* loader can resolve it. The resolution order mirrors Node's own algorithm:
|
|
445
|
+
* exact file match → directory index → `.js` fallback. Non-relative specifiers
|
|
446
|
+
* and already-extensioned paths are returned unchanged.
|
|
447
|
+
*/
|
|
434
448
|
function withResolvableExtension(fromFile: string, specifier: string): string {
|
|
435
449
|
if (!specifier.startsWith(".")) {
|
|
450
|
+
// Bare specifiers (packages, builtins) need no rewriting.
|
|
436
451
|
return specifier;
|
|
437
452
|
}
|
|
438
453
|
if (/\.(?:[cm]?js|json|node)$/i.test(specifier)) {
|
|
454
|
+
// Already has a concrete extension the loader understands.
|
|
439
455
|
return specifier;
|
|
440
456
|
}
|
|
441
457
|
const [pathname, suffix = ""] = splitSpecifierSuffix(specifier);
|
|
442
458
|
const fromDir = path.dirname(fromFile);
|
|
459
|
+
// 1. Try the specifier as a file path with each JS extension.
|
|
443
460
|
for (const extension of [".js", ".mjs", ".cjs"]) {
|
|
444
461
|
if (fs.existsSync(path.resolve(fromDir, pathname + extension))) {
|
|
445
462
|
return pathname + extension + suffix;
|
|
446
463
|
}
|
|
447
464
|
}
|
|
465
|
+
// 2. Try interpreting it as a directory with an index file.
|
|
448
466
|
const directory = pathname.replace(/\/+$/, "");
|
|
449
467
|
for (const extension of [".js", ".mjs", ".cjs"]) {
|
|
450
468
|
if (fs.existsSync(path.resolve(fromDir, directory, "index" + extension))) {
|
|
451
469
|
return `${directory}/index${extension}${suffix}`;
|
|
452
470
|
}
|
|
453
471
|
}
|
|
472
|
+
// 3. Last resort: append `.js` and let Node surface the error if it's wrong.
|
|
454
473
|
return `${specifier}.js`;
|
|
455
474
|
}
|
|
456
475
|
|
|
@@ -553,6 +572,12 @@ function skipRegex(input: string, start: number): number {
|
|
|
553
572
|
return input.length;
|
|
554
573
|
}
|
|
555
574
|
|
|
575
|
+
/**
|
|
576
|
+
* Determine whether the `/` at `start` opens a regex literal rather than a
|
|
577
|
+
* division operator. This is a conservative approximation: check the preceding
|
|
578
|
+
* non-whitespace token — if it is an operator character or a keyword that must
|
|
579
|
+
* be followed by an expression, we assume regex.
|
|
580
|
+
*/
|
|
556
581
|
function looksLikeRegexStart(input: string, start: number): boolean {
|
|
557
582
|
let i = start - 1;
|
|
558
583
|
while (i >= 0 && /\s/.test(input[i]!)) {
|
|
@@ -5,6 +5,8 @@ import { createRequire } from "node:module";
|
|
|
5
5
|
import os from "node:os";
|
|
6
6
|
import path from "node:path";
|
|
7
7
|
|
|
8
|
+
import { findNearestGoMod } from "../../compiler/internal/paths";
|
|
9
|
+
|
|
8
10
|
const GO_MOD_SEARCH_MAX_DEPTH = 3;
|
|
9
11
|
const TTSC_GO_MODULE_PATH = "github.com/samchon/ttsc/packages/ttsc";
|
|
10
12
|
const TSGO_GO_MODULE_PATH = "github.com/microsoft/typescript-go";
|
|
@@ -397,20 +399,6 @@ function resolveSourceBuildTarget(opts: {
|
|
|
397
399
|
};
|
|
398
400
|
}
|
|
399
401
|
|
|
400
|
-
function findNearestGoMod(from: string, maxDepth: number): string | null {
|
|
401
|
-
let current = path.resolve(from);
|
|
402
|
-
let depth = 0;
|
|
403
|
-
while (true) {
|
|
404
|
-
const candidate = path.join(current, "go.mod");
|
|
405
|
-
if (fs.existsSync(candidate)) return candidate;
|
|
406
|
-
if (depth >= maxDepth) return null;
|
|
407
|
-
const parent = path.dirname(current);
|
|
408
|
-
if (parent === current) return null;
|
|
409
|
-
current = parent;
|
|
410
|
-
depth += 1;
|
|
411
|
-
}
|
|
412
|
-
}
|
|
413
|
-
|
|
414
402
|
function materializeScratchDir(source: string, scratch: string): void {
|
|
415
403
|
fs.mkdirSync(scratch, { recursive: true });
|
|
416
404
|
fs.cpSync(source, scratch, {
|
|
@@ -768,6 +756,19 @@ function walkForGoMod(dir: string, out: string[]): void {
|
|
|
768
756
|
}
|
|
769
757
|
}
|
|
770
758
|
|
|
759
|
+
/**
|
|
760
|
+
* Resolve the directory where compiled plugin binaries are cached.
|
|
761
|
+
*
|
|
762
|
+
* Priority order:
|
|
763
|
+
*
|
|
764
|
+
* 1. `cacheDir` option (resolved relative to `projectRoot`).
|
|
765
|
+
* 2. `TTSC_CACHE_DIR` environment variable.
|
|
766
|
+
* 3. Platform-specific global user cache (XDG / AppData / Library/Caches).
|
|
767
|
+
*
|
|
768
|
+
* When falling back to the global cache, a GC pass is triggered
|
|
769
|
+
* opportunistically to evict old or oversized entries before the cache is
|
|
770
|
+
* used.
|
|
771
|
+
*/
|
|
771
772
|
export function resolvePluginCacheRoot(
|
|
772
773
|
projectRoot: string,
|
|
773
774
|
cacheDir?: string,
|
|
@@ -783,6 +784,13 @@ export function resolvePluginCacheRoot(
|
|
|
783
784
|
return root;
|
|
784
785
|
}
|
|
785
786
|
|
|
787
|
+
/**
|
|
788
|
+
* Return the absolute path to the global plugin binary cache root.
|
|
789
|
+
*
|
|
790
|
+
* The path follows platform conventions (XDG on Linux, AppData on Windows,
|
|
791
|
+
* Library/Caches on macOS) and does not depend on project-local config. Used by
|
|
792
|
+
* `ttsc cache clean` to enumerate cache locations.
|
|
793
|
+
*/
|
|
786
794
|
export function resolveGlobalPluginCacheRoot(): string {
|
|
787
795
|
return path.join(
|
|
788
796
|
resolveUserCacheRoot(),
|
|
@@ -791,6 +799,13 @@ export function resolveGlobalPluginCacheRoot(): string {
|
|
|
791
799
|
);
|
|
792
800
|
}
|
|
793
801
|
|
|
802
|
+
/**
|
|
803
|
+
* Return all directories that `ttsc cache clean` should wipe for a project.
|
|
804
|
+
*
|
|
805
|
+
* Covers three locations where plugin binaries may accumulate: the global user
|
|
806
|
+
* cache, the project-local `node_modules/.ttsc` cache (legacy), and the
|
|
807
|
+
* project-local `.ttsc` cache.
|
|
808
|
+
*/
|
|
794
809
|
export function defaultPluginCacheCleanTargets(projectRoot: string): string[] {
|
|
795
810
|
return [
|
|
796
811
|
resolveGlobalPluginCacheRoot(),
|
|
@@ -878,6 +893,17 @@ function resolveGoCompiler(): string {
|
|
|
878
893
|
return "go";
|
|
879
894
|
}
|
|
880
895
|
|
|
896
|
+
/**
|
|
897
|
+
* Compute a deterministic SHA-256 cache key for a plugin build.
|
|
898
|
+
*
|
|
899
|
+
* The key covers every input that can produce a different binary: ttsc/tsgo
|
|
900
|
+
* versions, platform, entry package, Go compiler identity, Go build environment
|
|
901
|
+
* variables, overlay module sources, plugin source files, and contributor
|
|
902
|
+
* source files. Contributors are sorted by name so declaration order does not
|
|
903
|
+
* affect the key.
|
|
904
|
+
*
|
|
905
|
+
* Exposed for testing and for the `ttsc cache` CLI command.
|
|
906
|
+
*/
|
|
881
907
|
export function computeCacheKey(inputs: {
|
|
882
908
|
contributors?: readonly ITtscBuildContributor[];
|
|
883
909
|
dir: string;
|
|
@@ -2,9 +2,10 @@ import fs from "node:fs";
|
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
|
|
5
|
+
import { findNearestGoMod } from "../../compiler/internal/paths";
|
|
5
6
|
import { readProjectConfig } from "../../compiler/internal/project/readProjectConfig";
|
|
6
|
-
import type { ITtscPluginContributor } from "../../structures/ITtscPluginContributor";
|
|
7
7
|
import type { ITtscPlugin } from "../../structures/ITtscPlugin";
|
|
8
|
+
import type { ITtscPluginContributor } from "../../structures/ITtscPluginContributor";
|
|
8
9
|
import type { ITtscPluginFactoryContext } from "../../structures/ITtscPluginFactoryContext";
|
|
9
10
|
import type { ITtscProjectPluginConfig } from "../../structures/ITtscProjectPluginConfig";
|
|
10
11
|
import type { TtscPluginStage } from "../../structures/TtscPluginStage";
|
|
@@ -30,6 +31,24 @@ type PackageManifest = {
|
|
|
30
31
|
ttsc?: unknown;
|
|
31
32
|
};
|
|
32
33
|
|
|
34
|
+
/**
|
|
35
|
+
* Resolve, load, and build all native plugin sidecars for a TypeScript project.
|
|
36
|
+
*
|
|
37
|
+
* Reads the project config, discovers plugin entries (from tsconfig and package
|
|
38
|
+
* auto-discovery), validates and composes their descriptors, then invokes
|
|
39
|
+
* `buildSourcePlugin` to compile each Go source package into a cached binary.
|
|
40
|
+
* Returns the ordered set of loaded native plugins alongside the parsed project
|
|
41
|
+
* config.
|
|
42
|
+
*
|
|
43
|
+
* @param options.binary - Absolute path to the ttsc native helper binary.
|
|
44
|
+
* @param options.cacheDir - Override the plugin binary cache directory.
|
|
45
|
+
* @param options.cwd - Working directory for resolving relative paths.
|
|
46
|
+
* @param options.entries - Explicit plugin entries; `false` disables all
|
|
47
|
+
* plugins (skips both tsconfig entries and package auto-discovery).
|
|
48
|
+
* @param options.file - Path to the tsconfig/jsconfig file.
|
|
49
|
+
* @param options.projectRoot - Override the project root directory.
|
|
50
|
+
* @param options.tsconfig - Alias for `file`.
|
|
51
|
+
*/
|
|
33
52
|
export function loadProjectPlugins(options: {
|
|
34
53
|
binary: string;
|
|
35
54
|
cacheDir?: string;
|
|
@@ -85,14 +104,21 @@ export function loadProjectPlugins(options: {
|
|
|
85
104
|
validatePluginSource(plugin);
|
|
86
105
|
const contributors = validatePluginContributors(plugin);
|
|
87
106
|
const source = resolvePluginSource(plugin.source, context.projectRoot);
|
|
88
|
-
const kind = resolveNativeSourceKind(
|
|
107
|
+
const kind = resolveNativeSourceKind(
|
|
108
|
+
source,
|
|
109
|
+
plugin,
|
|
110
|
+
entries[index]!.config,
|
|
111
|
+
index,
|
|
112
|
+
);
|
|
89
113
|
if (kind === "linked" && stage !== "transform") {
|
|
90
114
|
throw new Error(
|
|
91
115
|
`ttsc: plugin "${pluginLabel(plugin, entries[index]!.config, index)}" source is a linked Go package, but only transform-stage plugins can be linked into a compiler host`,
|
|
92
116
|
);
|
|
93
117
|
}
|
|
94
118
|
const linkedContributorName =
|
|
95
|
-
kind === "linked"
|
|
119
|
+
kind === "linked"
|
|
120
|
+
? `linked_${String(index).padStart(6, "0")}`
|
|
121
|
+
: undefined;
|
|
96
122
|
return {
|
|
97
123
|
contributors,
|
|
98
124
|
config: entries[index]!.config,
|
|
@@ -261,6 +287,7 @@ function composePluginSources(
|
|
|
261
287
|
return {
|
|
262
288
|
...plugin,
|
|
263
289
|
source: aggregate.plugin.source,
|
|
290
|
+
contributors: aggregate.plugin.contributors,
|
|
264
291
|
};
|
|
265
292
|
});
|
|
266
293
|
}
|
|
@@ -276,6 +303,14 @@ function matchesPluginAlias(
|
|
|
276
303
|
);
|
|
277
304
|
}
|
|
278
305
|
|
|
306
|
+
/**
|
|
307
|
+
* Return `true` when the project has at least one enabled plugin entry.
|
|
308
|
+
*
|
|
309
|
+
* Used by callers that need to skip plugin-specific work when no plugins are
|
|
310
|
+
* configured, without paying the full cost of `loadProjectPlugins`.
|
|
311
|
+
*
|
|
312
|
+
* @param entries - Explicit entries; `false` always returns `false`.
|
|
313
|
+
*/
|
|
279
314
|
export function hasProjectPluginEntries(
|
|
280
315
|
project: ITtscParsedProjectConfig,
|
|
281
316
|
entries?: readonly ITtscProjectPluginConfig[] | false,
|
|
@@ -610,7 +645,10 @@ function resolveNativeSourceKind(
|
|
|
610
645
|
config: ITtscProjectPluginConfig,
|
|
611
646
|
index: number,
|
|
612
647
|
): "executable" | "linked" {
|
|
613
|
-
const packageDir = resolveGoPackageDir(
|
|
648
|
+
const packageDir = resolveGoPackageDir(
|
|
649
|
+
source,
|
|
650
|
+
pluginLabel(plugin, config, index),
|
|
651
|
+
);
|
|
614
652
|
if (findNearestGoMod(packageDir, GO_MOD_SEARCH_MAX_DEPTH) === null) {
|
|
615
653
|
throw new Error(
|
|
616
654
|
`ttsc: plugin "${pluginLabel(plugin, config, index)}" source must be inside a Go module with go.mod within ${GO_MOD_SEARCH_MAX_DEPTH} parent directories: ${source}`,
|
|
@@ -625,20 +663,6 @@ function resolveNativeSourceKind(
|
|
|
625
663
|
return packageName === "main" ? "executable" : "linked";
|
|
626
664
|
}
|
|
627
665
|
|
|
628
|
-
function findNearestGoMod(from: string, maxDepth: number): string | null {
|
|
629
|
-
let current = path.resolve(from);
|
|
630
|
-
let depth = 0;
|
|
631
|
-
while (true) {
|
|
632
|
-
const candidate = path.join(current, "go.mod");
|
|
633
|
-
if (fs.existsSync(candidate)) return candidate;
|
|
634
|
-
if (depth >= maxDepth) return null;
|
|
635
|
-
const parent = path.dirname(current);
|
|
636
|
-
if (parent === current) return null;
|
|
637
|
-
current = parent;
|
|
638
|
-
depth += 1;
|
|
639
|
-
}
|
|
640
|
-
}
|
|
641
|
-
|
|
642
666
|
function resolveGoPackageDir(source: string, label: string): string {
|
|
643
667
|
if (!fs.existsSync(source)) {
|
|
644
668
|
throw new Error(`ttsc: plugin "${label}" source does not exist: ${source}`);
|
|
@@ -22,7 +22,14 @@ export namespace ITtscCompilerTransformation {
|
|
|
22
22
|
/** Non-fatal diagnostics reported during transformation. */
|
|
23
23
|
diagnostics?: ITtscCompilerDiagnostic[];
|
|
24
24
|
|
|
25
|
-
/**
|
|
25
|
+
/**
|
|
26
|
+
* Transformed TypeScript source text keyed by project-relative file path.
|
|
27
|
+
*
|
|
28
|
+
* Values are TypeScript source text, never JavaScript, declaration files,
|
|
29
|
+
* or source maps. When no transform sidecar is configured, this map
|
|
30
|
+
* contains the unmodified TypeScript files loaded by the TypeScript-Go
|
|
31
|
+
* Program.
|
|
32
|
+
*/
|
|
26
33
|
typescript: Record<string, string>;
|
|
27
34
|
}
|
|
28
35
|
|
|
@@ -31,7 +38,13 @@ export namespace ITtscCompilerTransformation {
|
|
|
31
38
|
/** Indicates that transformation completed with diagnostics. */
|
|
32
39
|
type: "failure";
|
|
33
40
|
|
|
34
|
-
/**
|
|
41
|
+
/**
|
|
42
|
+
* Transformed or partially transformed TypeScript source text keyed by
|
|
43
|
+
* project-relative file path.
|
|
44
|
+
*
|
|
45
|
+
* May be empty or partial when diagnostics prevented the transform sidecar
|
|
46
|
+
* from completing its pass.
|
|
47
|
+
*/
|
|
35
48
|
typescript: Record<string, string>;
|
|
36
49
|
|
|
37
50
|
/** Diagnostics reported during transformation. */
|
|
@@ -10,6 +10,4 @@ export interface TtscSingleFileEmitOptions extends TtscCommonOptions {
|
|
|
10
10
|
out?: string;
|
|
11
11
|
/** Suppress summary banners from ttsc/native sidecars. Defaults to `true`. */
|
|
12
12
|
quiet?: boolean;
|
|
13
|
-
/** Normalize compiler output so diagnostics can be parsed structurally. */
|
|
14
|
-
structuredDiagnostics?: boolean;
|
|
15
13
|
}
|