ttsc 0.4.2 → 0.4.3-dev.20260426
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/lib/api.d.ts +1 -1
- package/lib/api.js +217 -71
- package/lib/api.js.map +1 -1
- package/lib/cli.js +4 -4
- package/lib/cli.js.map +1 -1
- package/lib/index.d.ts +8 -7
- package/lib/index.js +8 -7
- package/lib/index.js.map +1 -1
- package/lib/runner/cli.js +1 -1
- package/lib/runner/cli.js.map +1 -1
- package/lib/runner/register.js +47 -113
- package/lib/runner/register.js.map +1 -1
- package/lib/tsgo.d.ts +24 -0
- package/lib/tsgo.js +103 -0
- package/lib/tsgo.js.map +1 -0
- package/package.json +9 -9
- package/src/api.ts +260 -74
- package/src/cli.ts +4 -4
- package/src/index.ts +8 -7
- package/src/runner/cli.ts +2 -2
- package/src/runner/register.ts +61 -131
- package/src/tsgo.ts +108 -0
- package/test/tsgo.test.ts +68 -0
package/src/api.ts
CHANGED
|
@@ -2,26 +2,26 @@
|
|
|
2
2
|
* Programmatic API for ttsc.
|
|
3
3
|
*
|
|
4
4
|
* This module is the TypeScript surface bundler adapters (unplugin, vite,
|
|
5
|
-
* webpack, rollup, esbuild, rspack, farm, next/swc, bun) consume.
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* webpack, rollup, esbuild, rspack, farm, next/swc, bun) consume. Project
|
|
6
|
+
* builds delegate to the consuming project's `@typescript/native-preview`
|
|
7
|
+
* `tsgo` binary, while plugin-selected native sidecars remain opt-in.
|
|
8
8
|
*
|
|
9
9
|
* Contract:
|
|
10
10
|
*
|
|
11
11
|
* - `transform()` emits one file's rewritten JS, returning the text.
|
|
12
12
|
* - `build()` runs the whole project (tsgo + ttsc rewrite + --emit).
|
|
13
13
|
* - `check()` runs the analysis pass without emitting (CI gate use).
|
|
14
|
-
* - `version()` returns the
|
|
14
|
+
* - `version()` returns the wrapper and resolved `tsgo` version banner.
|
|
15
15
|
*
|
|
16
16
|
* All helpers accept a `binary` override so tests can point at a specific
|
|
17
|
-
* executable without touching PATH or node_modules.
|
|
17
|
+
* `tsgo` executable without touching PATH or node_modules.
|
|
18
18
|
*/
|
|
19
19
|
import { spawnSync } from "node:child_process";
|
|
20
20
|
import * as fs from "node:fs";
|
|
21
21
|
import * as os from "node:os";
|
|
22
22
|
import * as path from "node:path";
|
|
23
23
|
|
|
24
|
-
import { type ResolveOptions,
|
|
24
|
+
import { type ResolveOptions, resolveBinary } from "./platform";
|
|
25
25
|
import {
|
|
26
26
|
type TtscPlugin,
|
|
27
27
|
applyPluginTransforms,
|
|
@@ -32,6 +32,7 @@ import {
|
|
|
32
32
|
resolveProjectConfig,
|
|
33
33
|
resolveProjectRoot,
|
|
34
34
|
} from "./project";
|
|
35
|
+
import { type ResolvedTsgo, resolveTsgo } from "./tsgo";
|
|
35
36
|
|
|
36
37
|
/**
|
|
37
38
|
* Options shared by every API call. `binary` takes precedence over platform
|
|
@@ -39,7 +40,7 @@ import {
|
|
|
39
40
|
* current process env.
|
|
40
41
|
*/
|
|
41
42
|
export interface CommonOptions extends ResolveOptions {
|
|
42
|
-
/** Absolute path to an already-resolved
|
|
43
|
+
/** Absolute path to an already-resolved tsgo binary. Skips package resolution. */
|
|
43
44
|
binary?: string;
|
|
44
45
|
/** Working directory passed to the child process. */
|
|
45
46
|
cwd?: string;
|
|
@@ -85,30 +86,13 @@ export interface BuildOptions extends CommonOptions {
|
|
|
85
86
|
outDir?: string;
|
|
86
87
|
/** Suppress the per-call summary banner. Default: `true`. */
|
|
87
88
|
quiet?: boolean;
|
|
89
|
+
/** @internal Caller already ran diagnostics and accepts responsibility. */
|
|
90
|
+
skipDiagnosticsCheck?: boolean;
|
|
88
91
|
}
|
|
89
92
|
|
|
90
93
|
/** Options for `check()`. */
|
|
91
94
|
export type CheckOptions = Omit<BuildOptions, "emit">;
|
|
92
95
|
|
|
93
|
-
/**
|
|
94
|
-
* Resolve the binary or throw a user-friendly error. Extracted so every API
|
|
95
|
-
* helper shares the same failure mode.
|
|
96
|
-
*/
|
|
97
|
-
function resolveOrThrow(opts: CommonOptions): string {
|
|
98
|
-
if (
|
|
99
|
-
opts.binary &&
|
|
100
|
-
path.isAbsolute(opts.binary) &&
|
|
101
|
-
fs.existsSync(opts.binary)
|
|
102
|
-
) {
|
|
103
|
-
return opts.binary;
|
|
104
|
-
}
|
|
105
|
-
const bin = resolveBinary(opts);
|
|
106
|
-
if (!bin) {
|
|
107
|
-
throw new Error(installHint(opts));
|
|
108
|
-
}
|
|
109
|
-
return bin;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
96
|
/** Merge spawn env without clobbering unrelated vars. */
|
|
113
97
|
function mergeEnv(extra?: NodeJS.ProcessEnv): NodeJS.ProcessEnv {
|
|
114
98
|
if (!extra) return process.env;
|
|
@@ -184,6 +168,62 @@ export function transform(options: TransformOptions): string {
|
|
|
184
168
|
? options.file
|
|
185
169
|
: path.resolve(options.cwd ?? process.cwd(), options.file),
|
|
186
170
|
);
|
|
171
|
+
if (execution.nativeBinary) {
|
|
172
|
+
return transformWithNativeBinary(options, execution, sourceFile);
|
|
173
|
+
}
|
|
174
|
+
if (execution.nativeMode !== "none") {
|
|
175
|
+
throw new Error(
|
|
176
|
+
`ttsc.transform: native rewrite mode "${execution.nativeMode}" requires a plugin-provided version-matched binary`,
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const tempOutDir = fs.mkdtempSync(path.join(os.tmpdir(), "ttsc-transform-"));
|
|
181
|
+
try {
|
|
182
|
+
const result = build({
|
|
183
|
+
...options,
|
|
184
|
+
emit: true,
|
|
185
|
+
outDir: tempOutDir,
|
|
186
|
+
plugins: false,
|
|
187
|
+
tsconfig: execution.tsconfig,
|
|
188
|
+
});
|
|
189
|
+
if (result.status !== 0) {
|
|
190
|
+
throw new Error(
|
|
191
|
+
"ttsc.transform exited " +
|
|
192
|
+
result.status +
|
|
193
|
+
"\n" +
|
|
194
|
+
(result.stderr || result.stdout),
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
const emitted = findEmittedFile(tempOutDir, execution.projectRoot, sourceFile);
|
|
198
|
+
if (!emitted) {
|
|
199
|
+
throw new Error(`ttsc.transform: no output produced for ${sourceFile}`);
|
|
200
|
+
}
|
|
201
|
+
const transformed = finalizeTransformText(
|
|
202
|
+
execution.plugins,
|
|
203
|
+
{
|
|
204
|
+
command: "transform",
|
|
205
|
+
cwd: execution.cwd,
|
|
206
|
+
projectRoot: execution.projectRoot,
|
|
207
|
+
sourceFile,
|
|
208
|
+
tsconfig: execution.tsconfig,
|
|
209
|
+
},
|
|
210
|
+
fs.readFileSync(emitted, "utf8"),
|
|
211
|
+
);
|
|
212
|
+
if (options.out) {
|
|
213
|
+
fs.mkdirSync(path.dirname(options.out), { recursive: true });
|
|
214
|
+
fs.writeFileSync(options.out, transformed, "utf8");
|
|
215
|
+
}
|
|
216
|
+
return transformed;
|
|
217
|
+
} finally {
|
|
218
|
+
fs.rmSync(tempOutDir, { recursive: true, force: true });
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function transformWithNativeBinary(
|
|
223
|
+
options: TransformOptions,
|
|
224
|
+
execution: ExecutionContext,
|
|
225
|
+
sourceFile: string,
|
|
226
|
+
): string {
|
|
187
227
|
const args = [
|
|
188
228
|
"transform",
|
|
189
229
|
"--file=" + sourceFile,
|
|
@@ -191,7 +231,7 @@ export function transform(options: TransformOptions): string {
|
|
|
191
231
|
"--rewrite-mode=" + execution.nativeMode,
|
|
192
232
|
];
|
|
193
233
|
|
|
194
|
-
const res = spawnBinary(execution.
|
|
234
|
+
const res = spawnBinary(execution.nativeBinary!, args, {
|
|
195
235
|
cwd: options.cwd,
|
|
196
236
|
env: mergeEnv(options.env),
|
|
197
237
|
encoding: "utf8",
|
|
@@ -199,7 +239,7 @@ export function transform(options: TransformOptions): string {
|
|
|
199
239
|
if (res.error) {
|
|
200
240
|
throw new Error(
|
|
201
241
|
"ttsc.transform: failed to spawn " +
|
|
202
|
-
execution.
|
|
242
|
+
execution.nativeBinary +
|
|
203
243
|
": " +
|
|
204
244
|
res.error.message,
|
|
205
245
|
);
|
|
@@ -249,45 +289,52 @@ export interface BuildResult {
|
|
|
249
289
|
*/
|
|
250
290
|
export function build(options: BuildOptions = {}): BuildResult {
|
|
251
291
|
const execution = resolveExecutionContext(options);
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
292
|
+
if (execution.nativeMode !== "none") {
|
|
293
|
+
return {
|
|
294
|
+
status: 2,
|
|
295
|
+
stdout: "",
|
|
296
|
+
stderr:
|
|
297
|
+
`ttsc.build: native rewrite mode "${execution.nativeMode}" requires ` +
|
|
298
|
+
"a version-matched sidecar build; project builds use the consuming project's @typescript/native-preview by default\n",
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
if (options.emit !== false && options.skipDiagnosticsCheck !== true) {
|
|
303
|
+
const checked = runTsgo(execution, ["--noEmit"], options);
|
|
304
|
+
if (checked.status !== 0) {
|
|
305
|
+
return checked;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
const args = createTsgoBuildArgs(execution, options, {
|
|
310
|
+
listEmittedFiles: options.emit !== false && execution.plugins.length > 0,
|
|
311
|
+
});
|
|
312
|
+
const res = spawnBinary(execution.tsgo.binary, args, {
|
|
313
|
+
cwd: execution.projectRoot,
|
|
268
314
|
env: mergeEnv(options.env),
|
|
269
315
|
encoding: "utf8",
|
|
270
316
|
});
|
|
271
317
|
if (res.error) {
|
|
272
318
|
throw new Error(
|
|
273
|
-
"ttsc.build: failed to spawn " +
|
|
319
|
+
"ttsc.build: failed to spawn " +
|
|
320
|
+
execution.tsgo.binary +
|
|
321
|
+
": " +
|
|
322
|
+
res.error.message,
|
|
274
323
|
);
|
|
275
324
|
}
|
|
276
|
-
|
|
277
|
-
try {
|
|
278
|
-
const emittedFiles = JSON.parse(
|
|
279
|
-
fs.readFileSync(manifest, "utf8"),
|
|
280
|
-
) as string[];
|
|
281
|
-
applyBuildPlugins(execution.plugins, execution, emittedFiles);
|
|
282
|
-
} finally {
|
|
283
|
-
fs.rmSync(path.dirname(manifest), { recursive: true, force: true });
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
return {
|
|
325
|
+
const result = {
|
|
287
326
|
status: res.status ?? 1,
|
|
288
327
|
stdout: outputText(res.stdout),
|
|
289
328
|
stderr: outputText(res.stderr),
|
|
290
329
|
};
|
|
330
|
+
const emittedFiles = parseEmittedFiles(result.stdout);
|
|
331
|
+
if (emittedFiles.length !== 0) {
|
|
332
|
+
result.stdout = stripEmittedFileLines(result.stdout);
|
|
333
|
+
}
|
|
334
|
+
if (result.status === 0 && options.emit !== false && execution.plugins.length > 0) {
|
|
335
|
+
applyBuildPlugins(execution.plugins, execution, emittedFiles);
|
|
336
|
+
}
|
|
337
|
+
return normalizeFailedDiagnostics(result);
|
|
291
338
|
}
|
|
292
339
|
|
|
293
340
|
/**
|
|
@@ -298,10 +345,56 @@ export function check(options: CheckOptions = {}): BuildResult {
|
|
|
298
345
|
return build({ ...options, emit: false });
|
|
299
346
|
}
|
|
300
347
|
|
|
348
|
+
function runTsgo(
|
|
349
|
+
execution: ExecutionContext,
|
|
350
|
+
extraArgs: readonly string[],
|
|
351
|
+
options: BuildOptions,
|
|
352
|
+
): BuildResult {
|
|
353
|
+
const res = spawnBinary(
|
|
354
|
+
execution.tsgo.binary,
|
|
355
|
+
["-p", execution.tsconfig, ...extraArgs],
|
|
356
|
+
{
|
|
357
|
+
cwd: execution.projectRoot,
|
|
358
|
+
env: mergeEnv(options.env),
|
|
359
|
+
encoding: "utf8",
|
|
360
|
+
},
|
|
361
|
+
);
|
|
362
|
+
if (res.error) {
|
|
363
|
+
throw new Error(
|
|
364
|
+
"ttsc: failed to spawn " + execution.tsgo.binary + ": " + res.error.message,
|
|
365
|
+
);
|
|
366
|
+
}
|
|
367
|
+
return normalizeFailedDiagnostics({
|
|
368
|
+
status: res.status ?? 1,
|
|
369
|
+
stdout: outputText(res.stdout),
|
|
370
|
+
stderr: outputText(res.stderr),
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
function createTsgoBuildArgs(
|
|
375
|
+
execution: ExecutionContext,
|
|
376
|
+
options: BuildOptions,
|
|
377
|
+
flags: { listEmittedFiles: boolean },
|
|
378
|
+
): string[] {
|
|
379
|
+
const args = ["-p", execution.tsconfig];
|
|
380
|
+
if (options.emit === true) {
|
|
381
|
+
args.push("--noEmit", "false", "--emitDeclarationOnly", "false");
|
|
382
|
+
} else if (options.emit === false) {
|
|
383
|
+
args.push("--noEmit");
|
|
384
|
+
}
|
|
385
|
+
if (options.outDir) {
|
|
386
|
+
args.push("--outDir", path.resolve(execution.cwd, options.outDir));
|
|
387
|
+
}
|
|
388
|
+
if (flags.listEmittedFiles) {
|
|
389
|
+
args.push("--listEmittedFiles");
|
|
390
|
+
}
|
|
391
|
+
return args;
|
|
392
|
+
}
|
|
393
|
+
|
|
301
394
|
/** Ask the binary for its version banner. Handy for user-agent strings. */
|
|
302
395
|
export function version(options: CommonOptions = {}): string {
|
|
303
|
-
const
|
|
304
|
-
const res = spawnBinary(
|
|
396
|
+
const tsgo = resolveTsgo(options);
|
|
397
|
+
const res = spawnBinary(tsgo.binary, ["--version"], {
|
|
305
398
|
encoding: "utf8",
|
|
306
399
|
});
|
|
307
400
|
if (res.error || res.status !== 0) {
|
|
@@ -309,7 +402,7 @@ export function version(options: CommonOptions = {}): string {
|
|
|
309
402
|
"ttsc.version: failed: " + (outputText(res.stderr) || res.error?.message),
|
|
310
403
|
);
|
|
311
404
|
}
|
|
312
|
-
return outputText(res.stdout).trim()
|
|
405
|
+
return `ttsc ${readOwnPackageVersion()} (${outputText(res.stdout).trim()})`;
|
|
313
406
|
}
|
|
314
407
|
|
|
315
408
|
/**
|
|
@@ -322,11 +415,12 @@ export function transformAsync(options: TransformOptions): Promise<string> {
|
|
|
322
415
|
}
|
|
323
416
|
|
|
324
417
|
interface ExecutionContext {
|
|
325
|
-
bin: string;
|
|
326
418
|
cwd: string;
|
|
419
|
+
nativeBinary: string | null;
|
|
327
420
|
nativeMode: string;
|
|
328
421
|
plugins: readonly TtscPlugin[];
|
|
329
422
|
projectRoot: string;
|
|
423
|
+
tsgo: ResolvedTsgo;
|
|
330
424
|
tsconfig: string;
|
|
331
425
|
}
|
|
332
426
|
|
|
@@ -334,33 +428,26 @@ function resolveExecutionContext(
|
|
|
334
428
|
options: CommonOptions & { tsconfig?: string },
|
|
335
429
|
): ExecutionContext {
|
|
336
430
|
const cwd = path.resolve(options.cwd ?? process.cwd());
|
|
337
|
-
const fallbackBinary =
|
|
338
|
-
options.binary &&
|
|
339
|
-
path.isAbsolute(options.binary) &&
|
|
340
|
-
fs.existsSync(options.binary)
|
|
341
|
-
? options.binary
|
|
342
|
-
: resolveBinary(options);
|
|
343
431
|
const tsconfig = resolveProjectConfig({
|
|
344
432
|
cwd,
|
|
345
433
|
tsconfig: options.tsconfig,
|
|
346
434
|
});
|
|
347
435
|
const projectRoot = resolveProjectRoot({ cwd, tsconfig });
|
|
436
|
+
const tsgo = resolveTsgo({ ...options, cwd: projectRoot });
|
|
437
|
+
const fallbackBinary = resolveBinary(options);
|
|
348
438
|
const loaded = loadProjectPlugins({
|
|
349
439
|
binary: fallbackBinary ?? "",
|
|
350
440
|
cwd,
|
|
351
441
|
entries: options.plugins,
|
|
352
442
|
tsconfig,
|
|
353
443
|
});
|
|
354
|
-
const bin = options.binary ?? loaded.nativeBinary ?? fallbackBinary;
|
|
355
|
-
if (!bin) {
|
|
356
|
-
throw new Error(installHint(options));
|
|
357
|
-
}
|
|
358
444
|
return {
|
|
359
|
-
bin,
|
|
360
445
|
cwd,
|
|
446
|
+
nativeBinary: loaded.nativeBinary ?? null,
|
|
361
447
|
nativeMode: options.rewriteMode ?? loaded.nativeMode,
|
|
362
448
|
plugins: loaded.plugins.filter((plugin) => plugin.transformOutput),
|
|
363
449
|
projectRoot,
|
|
450
|
+
tsgo,
|
|
364
451
|
tsconfig,
|
|
365
452
|
};
|
|
366
453
|
}
|
|
@@ -410,7 +497,106 @@ function isJavaScriptOutput(file: string): boolean {
|
|
|
410
497
|
return /\.(?:[cm]?js)$/i.test(file);
|
|
411
498
|
}
|
|
412
499
|
|
|
413
|
-
function
|
|
414
|
-
const
|
|
415
|
-
|
|
500
|
+
function parseEmittedFiles(stdout: string): string[] {
|
|
501
|
+
const out: string[] = [];
|
|
502
|
+
for (const line of stdout.split(/\r?\n/)) {
|
|
503
|
+
const match = line.match(/^TSFILE:\s*(.+)$/);
|
|
504
|
+
if (match?.[1]) {
|
|
505
|
+
out.push(path.resolve(match[1].trim()));
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
return out;
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
function stripEmittedFileLines(stdout: string): string {
|
|
512
|
+
return stdout
|
|
513
|
+
.split(/\r?\n/)
|
|
514
|
+
.filter((line) => !/^TSFILE:\s*/.test(line))
|
|
515
|
+
.join("\n")
|
|
516
|
+
.replace(/\n+$/, "");
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
function normalizeFailedDiagnostics(result: BuildResult): BuildResult {
|
|
520
|
+
if (result.status === 0 || result.stderr.trim().length !== 0) {
|
|
521
|
+
return result;
|
|
522
|
+
}
|
|
523
|
+
if (result.stdout.trim().length === 0) {
|
|
524
|
+
return result;
|
|
525
|
+
}
|
|
526
|
+
return {
|
|
527
|
+
status: result.status,
|
|
528
|
+
stdout: "",
|
|
529
|
+
stderr: result.stdout,
|
|
530
|
+
};
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
function findEmittedFile(
|
|
534
|
+
outDir: string,
|
|
535
|
+
projectRoot: string,
|
|
536
|
+
sourceFile: string,
|
|
537
|
+
): string | null {
|
|
538
|
+
let best: string | null = null;
|
|
539
|
+
let bestScore = 0;
|
|
540
|
+
for (const file of listJavaScriptFiles(outDir)) {
|
|
541
|
+
const score = sharedSourceStemSegments(file, sourceFile);
|
|
542
|
+
if (score > bestScore) {
|
|
543
|
+
best = file;
|
|
544
|
+
bestScore = score;
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
if (best) {
|
|
548
|
+
return best;
|
|
549
|
+
}
|
|
550
|
+
const relative = path.relative(projectRoot, sourceFile);
|
|
551
|
+
if (relative && !relative.startsWith("..") && !path.isAbsolute(relative)) {
|
|
552
|
+
const exact = path.resolve(outDir, relative).replace(/\.[cm]?tsx?$/i, ".js");
|
|
553
|
+
if (fs.existsSync(exact)) {
|
|
554
|
+
return exact;
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
return null;
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
function listJavaScriptFiles(root: string): string[] {
|
|
561
|
+
const out: string[] = [];
|
|
562
|
+
const stack = [root];
|
|
563
|
+
while (stack.length !== 0) {
|
|
564
|
+
const current = stack.pop()!;
|
|
565
|
+
if (!fs.existsSync(current)) continue;
|
|
566
|
+
for (const entry of fs.readdirSync(current, { withFileTypes: true })) {
|
|
567
|
+
const next = path.join(current, entry.name);
|
|
568
|
+
if (entry.isDirectory()) {
|
|
569
|
+
stack.push(next);
|
|
570
|
+
} else if (entry.isFile() && isJavaScriptOutput(next)) {
|
|
571
|
+
out.push(next);
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
return out;
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
function sharedSourceStemSegments(outPath: string, srcPath: string): number {
|
|
579
|
+
const trim = (value: string): string[] => {
|
|
580
|
+
const normalized = value.replace(/\\/g, "/");
|
|
581
|
+
return normalized.replace(/\.[^.]+$/, "").split("/");
|
|
582
|
+
};
|
|
583
|
+
const a = trim(outPath);
|
|
584
|
+
const b = trim(srcPath);
|
|
585
|
+
const n = Math.min(a.length, b.length);
|
|
586
|
+
let shared = 0;
|
|
587
|
+
for (let i = 1; i <= n; i += 1) {
|
|
588
|
+
if (a[a.length - i] !== b[b.length - i]) break;
|
|
589
|
+
shared += 1;
|
|
590
|
+
}
|
|
591
|
+
return shared;
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
function readOwnPackageVersion(): string {
|
|
595
|
+
try {
|
|
596
|
+
const file = path.resolve(__dirname, "..", "package.json");
|
|
597
|
+
const pkg = JSON.parse(fs.readFileSync(file, "utf8")) as { version?: string };
|
|
598
|
+
return pkg.version ?? "0.0.0";
|
|
599
|
+
} catch {
|
|
600
|
+
return "0.0.0";
|
|
601
|
+
}
|
|
416
602
|
}
|
package/src/cli.ts
CHANGED
|
@@ -311,11 +311,11 @@ function printHelp(): void {
|
|
|
311
311
|
" -w, --watch Rebuild when project files change",
|
|
312
312
|
" --preserveWatchOutput Do not clear the screen between watch rebuilds",
|
|
313
313
|
" --outDir <dir> Override compilerOptions.outDir for this invocation",
|
|
314
|
-
" --rewrite-mode <mode>
|
|
315
|
-
" --quiet Keep
|
|
316
|
-
" --verbose Print the
|
|
314
|
+
" --rewrite-mode <mode> Plugin-selected native rewrite backend id",
|
|
315
|
+
" --quiet Keep build output quiet (default)",
|
|
316
|
+
" --verbose Print the build summary and emitted files",
|
|
317
317
|
" --out <path> Write transform output to a file instead of stdout",
|
|
318
|
-
" --binary <path> Use an explicit
|
|
318
|
+
" --binary <path> Use an explicit tsgo binary",
|
|
319
319
|
"",
|
|
320
320
|
"Plugin contract:",
|
|
321
321
|
" ttsc reads compilerOptions.plugins from tsconfig.json.",
|
package/src/index.ts
CHANGED
|
@@ -2,18 +2,19 @@
|
|
|
2
2
|
* ttsc — public TypeScript entry.
|
|
3
3
|
*
|
|
4
4
|
* Exports:
|
|
5
|
-
* -
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* - tsgo helpers (`resolveTsgo`, …) — resolve the consuming project's
|
|
6
|
+
* `@typescript/native-preview` compiler binary.
|
|
7
|
+
* - platform helpers (`resolveBinary`, `installHint`, …) — legacy helpers
|
|
8
|
+
* for plugin-selected native sidecars.
|
|
8
9
|
* - programmatic API (`transform`, `build`, `check`, `version`) — a thin
|
|
9
|
-
* TS wrapper around the
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* a string or a result record.
|
|
10
|
+
* TS wrapper around the consumer `tsgo` binary plus JS output-plugin
|
|
11
|
+
* hooks. Adapters never have to shell out themselves; they call these
|
|
12
|
+
* helpers and get back a string or a result record.
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
15
|
export * from "./platform";
|
|
16
16
|
export * from "./api";
|
|
17
17
|
export * from "./project";
|
|
18
18
|
export * from "./plugin";
|
|
19
|
+
export * from "./tsgo";
|
|
19
20
|
export * from "./runner/register";
|
package/src/runner/cli.ts
CHANGED
|
@@ -133,7 +133,7 @@ function parseCLI(argv: readonly string[]): ParsedCLI | "help" | "version" {
|
|
|
133
133
|
binary = current.slice("--binary=".length);
|
|
134
134
|
} else if (current.startsWith("-")) {
|
|
135
135
|
throw new Error(`ttsx: unknown option ${current}`);
|
|
136
|
-
|
|
136
|
+
} else {
|
|
137
137
|
entry = current;
|
|
138
138
|
}
|
|
139
139
|
break;
|
|
@@ -167,7 +167,7 @@ function printHelp(): void {
|
|
|
167
167
|
" -P, --project <file> Use an explicit tsconfig.json",
|
|
168
168
|
" --cwd <dir> Resolve entry/project relative to this directory",
|
|
169
169
|
" --cache-dir <dir> Override the compiled JS cache directory",
|
|
170
|
-
" --binary <path> Use an explicit
|
|
170
|
+
" --binary <path> Use an explicit tsgo binary",
|
|
171
171
|
" -r, --require <file> Preload a module before the entrypoint",
|
|
172
172
|
" -h, --help Show this help",
|
|
173
173
|
" -v, --version Print the runner version",
|