ttsc 0.6.0 → 0.7.1
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 +1 -1
- package/cmd/ttsc/api_compile.go +134 -0
- package/cmd/ttsc/api_transform.go +64 -0
- package/cmd/ttsc/build.go +1 -7
- package/cmd/ttsc/main.go +6 -20
- package/driver/program.go +13 -3
- package/lib/TtscCompiler.d.ts +96 -0
- package/lib/TtscCompiler.js +294 -0
- package/lib/TtscCompiler.js.map +1 -0
- package/lib/compiler/internal/buildNativeCompiler.d.ts +6 -0
- package/lib/compiler/internal/buildNativeCompiler.js +72 -0
- package/lib/compiler/internal/buildNativeCompiler.js.map +1 -0
- package/lib/compiler/internal/compileProjectInMemory.d.ts +7 -0
- package/lib/compiler/internal/compileProjectInMemory.js +176 -0
- package/lib/compiler/internal/compileProjectInMemory.js.map +1 -0
- package/lib/compiler/internal/project/readProjectConfig.d.ts +4 -0
- package/lib/{project.js → compiler/internal/project/readProjectConfig.js} +12 -82
- package/lib/compiler/internal/project/readProjectConfig.js.map +1 -0
- package/lib/compiler/internal/project/resolveProjectConfig.d.ts +3 -0
- package/lib/compiler/internal/project/resolveProjectConfig.js +94 -0
- package/lib/compiler/internal/project/resolveProjectConfig.js.map +1 -0
- package/lib/compiler/internal/resolveBinary.d.ts +4 -0
- package/lib/compiler/internal/resolveBinary.js +65 -0
- package/lib/compiler/internal/resolveBinary.js.map +1 -0
- package/lib/compiler/internal/resolveEmittedJavaScript.d.ts +7 -0
- package/lib/compiler/internal/resolveEmittedJavaScript.js +118 -0
- package/lib/compiler/internal/resolveEmittedJavaScript.js.map +1 -0
- package/lib/compiler/internal/resolveTsgo.d.ts +20 -0
- package/lib/{tsgo.js → compiler/internal/resolveTsgo.js} +5 -10
- package/lib/compiler/internal/resolveTsgo.js.map +1 -0
- package/lib/compiler/internal/runBuild.d.ts +10 -0
- package/lib/compiler/internal/runBuild.js +480 -0
- package/lib/compiler/internal/runBuild.js.map +1 -0
- package/lib/compiler/internal/runSingleFileEmit.d.ts +3 -0
- package/lib/compiler/internal/runSingleFileEmit.js +102 -0
- package/lib/compiler/internal/runSingleFileEmit.js.map +1 -0
- package/lib/compiler/internal/transformProjectInMemory.d.ts +7 -0
- package/lib/compiler/internal/transformProjectInMemory.js +275 -0
- package/lib/compiler/internal/transformProjectInMemory.js.map +1 -0
- package/lib/index.d.ts +6 -15
- package/lib/index.js +6 -15
- package/lib/index.js.map +1 -1
- package/lib/launcher/internal/getCompilerVersionText.d.ts +3 -0
- package/lib/launcher/internal/getCompilerVersionText.js +71 -0
- package/lib/launcher/internal/getCompilerVersionText.js.map +1 -0
- package/lib/launcher/internal/prepareExecution.d.ts +10 -0
- package/lib/launcher/internal/prepareExecution.js +120 -0
- package/lib/launcher/internal/prepareExecution.js.map +1 -0
- package/lib/launcher/internal/runTtsc.d.ts +1 -0
- package/lib/{cli.js → launcher/internal/runTtsc.js} +45 -118
- package/lib/launcher/internal/runTtsc.js.map +1 -0
- package/lib/launcher/internal/runTtsx.d.ts +1 -0
- package/lib/{runner/cli.js → launcher/internal/runTtsx.js} +13 -35
- package/lib/launcher/internal/runTtsx.js.map +1 -0
- package/lib/launcher/ttsc.js +2 -2
- package/lib/launcher/ttsc.js.map +1 -1
- package/lib/launcher/ttsx.js +2 -2
- package/lib/launcher/ttsx.js.map +1 -1
- package/lib/plugin/internal/buildSourcePlugin.d.ts +12 -0
- package/lib/{source-build.js → plugin/internal/buildSourcePlugin.js} +77 -84
- package/lib/plugin/internal/buildSourcePlugin.js.map +1 -0
- package/lib/plugin/internal/loadProjectPlugins.d.ts +14 -0
- package/lib/{plugin.js → plugin/internal/loadProjectPlugins.js} +38 -76
- package/lib/plugin/internal/loadProjectPlugins.js.map +1 -0
- package/lib/structures/ITtscCompilerContext.d.ts +78 -0
- package/lib/structures/ITtscCompilerContext.js +3 -0
- package/lib/structures/ITtscCompilerContext.js.map +1 -0
- package/lib/structures/ITtscCompilerDiagnostic.d.ts +83 -0
- package/lib/structures/ITtscCompilerDiagnostic.js +3 -0
- package/lib/structures/ITtscCompilerDiagnostic.js.map +1 -0
- package/lib/structures/ITtscCompilerResult.d.ts +83 -0
- package/lib/structures/{ITtscCacheKeyInput.js → ITtscCompilerResult.js} +1 -1
- package/lib/structures/ITtscCompilerResult.js.map +1 -0
- package/lib/structures/ITtscCompilerTransformation.d.ts +35 -0
- package/lib/structures/ITtscCompilerTransformation.js +3 -0
- package/lib/structures/ITtscCompilerTransformation.js.map +1 -0
- package/lib/structures/ITtscPlugin.d.ts +52 -7
- package/lib/structures/ITtscPluginFactoryContext.d.ts +47 -0
- package/lib/structures/ITtscProjectPluginConfig.d.ts +41 -0
- package/lib/structures/TtscPluginStage.d.ts +18 -0
- package/lib/structures/{ITtscBuildResult.js → TtscPluginStage.js} +1 -1
- package/lib/structures/TtscPluginStage.js.map +1 -0
- package/lib/structures/index.d.ts +8 -0
- package/lib/structures/index.js +25 -0
- package/lib/structures/index.js.map +1 -0
- package/lib/structures/internal/ITtscLoadedNativePlugin.d.ts +13 -0
- package/lib/structures/internal/ITtscLoadedNativePlugin.js.map +1 -0
- package/lib/structures/internal/ITtscParsedProjectConfig.d.ts +15 -0
- package/lib/structures/internal/ITtscParsedProjectConfig.js.map +1 -0
- package/lib/structures/internal/ITtscProjectLocatorOptions.d.ts +9 -0
- package/lib/structures/internal/ITtscProjectLocatorOptions.js.map +1 -0
- package/lib/structures/internal/TtscBuildOptions.d.ts +18 -0
- package/lib/structures/{ITtscBuildOptions.js → internal/TtscBuildOptions.js} +1 -1
- package/lib/structures/internal/TtscBuildOptions.js.map +1 -0
- package/lib/structures/internal/TtscBuildResult.d.ts +14 -0
- package/lib/structures/{ITtscCheckOptions.js → internal/TtscBuildResult.js} +1 -1
- package/lib/structures/internal/TtscBuildResult.js.map +1 -0
- package/lib/structures/internal/TtscCommonOptions.d.ts +27 -0
- package/lib/structures/{ITtscNativeSource.js → internal/TtscCommonOptions.js} +1 -1
- package/lib/structures/internal/TtscCommonOptions.js.map +1 -0
- package/lib/structures/internal/TtscSingleFileEmitOptions.d.ts +14 -0
- package/lib/structures/internal/TtscSingleFileEmitOptions.js +3 -0
- package/lib/structures/internal/TtscSingleFileEmitOptions.js.map +1 -0
- package/package.json +9 -9
- package/src/TtscCompiler.ts +305 -0
- package/src/compiler/internal/buildNativeCompiler.ts +43 -0
- package/src/compiler/internal/compileProjectInMemory.ts +189 -0
- package/src/{project.ts → compiler/internal/project/readProjectConfig.ts} +36 -111
- package/src/compiler/internal/project/resolveProjectConfig.ts +67 -0
- package/src/compiler/internal/resolveBinary.ts +41 -0
- package/src/compiler/internal/resolveEmittedJavaScript.ts +102 -0
- package/src/{tsgo.ts → compiler/internal/resolveTsgo.ts} +20 -23
- package/src/compiler/internal/runBuild.ts +644 -0
- package/src/compiler/internal/runSingleFileEmit.ts +73 -0
- package/src/compiler/internal/transformProjectInMemory.ts +368 -0
- package/src/index.ts +6 -15
- package/src/launcher/internal/getCompilerVersionText.ts +44 -0
- package/src/launcher/internal/prepareExecution.ts +115 -0
- package/src/{cli.ts → launcher/internal/runTtsc.ts} +58 -140
- package/src/{runner/cli.ts → launcher/internal/runTtsx.ts} +21 -49
- package/src/launcher/ttsc.ts +2 -2
- package/src/launcher/ttsx.ts +2 -2
- package/src/{source-build.ts → plugin/internal/buildSourcePlugin.ts} +121 -115
- package/src/plugin/internal/loadProjectPlugins.ts +214 -0
- package/src/structures/ITtscCompilerContext.ts +84 -0
- package/src/structures/ITtscCompilerDiagnostic.ts +91 -0
- package/src/structures/ITtscCompilerResult.ts +94 -0
- package/src/structures/ITtscCompilerTransformation.ts +46 -0
- package/src/structures/ITtscPlugin.ts +54 -7
- package/src/structures/ITtscPluginFactoryContext.ts +51 -0
- package/src/structures/ITtscProjectPluginConfig.ts +43 -0
- package/src/structures/TtscPluginStage.ts +18 -0
- package/src/structures/index.ts +8 -0
- package/src/structures/internal/ITtscLoadedNativePlugin.ts +14 -0
- package/src/structures/internal/ITtscParsedProjectConfig.ts +16 -0
- package/src/structures/internal/ITtscProjectLocatorOptions.ts +9 -0
- package/src/structures/internal/TtscBuildOptions.ts +19 -0
- package/src/structures/internal/TtscBuildResult.ts +15 -0
- package/src/structures/internal/TtscCommonOptions.ts +28 -0
- package/src/structures/internal/TtscSingleFileEmitOptions.ts +15 -0
- package/test/compiler.test.ts +422 -0
- package/test/platform.test.ts +1 -45
- package/test/project.test.ts +3 -1
- package/test/source-build.test.ts +33 -220
- package/test/tsgo.test.ts +1 -8
- package/cmd/ttsc/transform.go +0 -166
- package/lib/api.d.ts +0 -40
- package/lib/api.js +0 -680
- package/lib/api.js.map +0 -1
- package/lib/cli.d.ts +0 -1
- package/lib/cli.js.map +0 -1
- package/lib/native.d.ts +0 -8
- package/lib/native.js +0 -42
- package/lib/native.js.map +0 -1
- package/lib/platform.d.ts +0 -52
- package/lib/platform.js +0 -175
- package/lib/platform.js.map +0 -1
- package/lib/plugin.d.ts +0 -13
- package/lib/plugin.js.map +0 -1
- package/lib/project.d.ts +0 -14
- package/lib/project.js.map +0 -1
- package/lib/runner/cli.d.ts +0 -1
- package/lib/runner/cli.js.map +0 -1
- package/lib/runner/register.d.ts +0 -6
- package/lib/runner/register.js +0 -358
- package/lib/runner/register.js.map +0 -1
- package/lib/source-build.d.ts +0 -19
- package/lib/source-build.js.map +0 -1
- package/lib/structures/ITtscBuildOptions.d.ts +0 -14
- package/lib/structures/ITtscBuildOptions.js.map +0 -1
- package/lib/structures/ITtscBuildResult.d.ts +0 -6
- package/lib/structures/ITtscBuildResult.js.map +0 -1
- package/lib/structures/ITtscBuildSourcePluginOptions.d.ts +0 -8
- package/lib/structures/ITtscBuildSourcePluginOptions.js +0 -3
- package/lib/structures/ITtscBuildSourcePluginOptions.js.map +0 -1
- package/lib/structures/ITtscCacheKeyInput.d.ts +0 -7
- package/lib/structures/ITtscCacheKeyInput.js.map +0 -1
- package/lib/structures/ITtscCheckOptions.d.ts +0 -2
- package/lib/structures/ITtscCheckOptions.js.map +0 -1
- package/lib/structures/ITtscCommonOptions.d.ts +0 -22
- package/lib/structures/ITtscCommonOptions.js +0 -3
- package/lib/structures/ITtscCommonOptions.js.map +0 -1
- package/lib/structures/ITtscLoadPluginsOptions.d.ts +0 -8
- package/lib/structures/ITtscLoadPluginsOptions.js +0 -3
- package/lib/structures/ITtscLoadPluginsOptions.js.map +0 -1
- package/lib/structures/ITtscLoadedNativePlugin.d.ts +0 -7
- package/lib/structures/ITtscLoadedNativePlugin.js.map +0 -1
- package/lib/structures/ITtscLoadedPlugins.d.ts +0 -11
- package/lib/structures/ITtscLoadedPlugins.js +0 -3
- package/lib/structures/ITtscLoadedPlugins.js.map +0 -1
- package/lib/structures/ITtscNativeBackend.d.ts +0 -10
- package/lib/structures/ITtscNativeBackend.js +0 -3
- package/lib/structures/ITtscNativeBackend.js.map +0 -1
- package/lib/structures/ITtscNativePluginContractVersion.d.ts +0 -1
- package/lib/structures/ITtscNativePluginContractVersion.js +0 -3
- package/lib/structures/ITtscNativePluginContractVersion.js.map +0 -1
- package/lib/structures/ITtscNativePluginShape.d.ts +0 -8
- package/lib/structures/ITtscNativePluginShape.js +0 -3
- package/lib/structures/ITtscNativePluginShape.js.map +0 -1
- package/lib/structures/ITtscNativeRewriteMode.d.ts +0 -1
- package/lib/structures/ITtscNativeRewriteMode.js +0 -3
- package/lib/structures/ITtscNativeRewriteMode.js.map +0 -1
- package/lib/structures/ITtscNativeSource.d.ts +0 -4
- package/lib/structures/ITtscNativeSource.js.map +0 -1
- package/lib/structures/ITtscParsedProjectConfig.d.ts +0 -9
- package/lib/structures/ITtscParsedProjectConfig.js.map +0 -1
- package/lib/structures/ITtscPluginFactory.d.ts +0 -4
- package/lib/structures/ITtscPluginFactory.js +0 -3
- package/lib/structures/ITtscPluginFactory.js.map +0 -1
- package/lib/structures/ITtscPluginModule.d.ts +0 -3
- package/lib/structures/ITtscPluginModule.js +0 -3
- package/lib/structures/ITtscPluginModule.js.map +0 -1
- package/lib/structures/ITtscPreparedExecution.d.ts +0 -5
- package/lib/structures/ITtscPreparedExecution.js +0 -3
- package/lib/structures/ITtscPreparedExecution.js.map +0 -1
- package/lib/structures/ITtscProjectLocatorOptions.d.ts +0 -5
- package/lib/structures/ITtscProjectLocatorOptions.js.map +0 -1
- package/lib/structures/ITtscRegisterOptions.d.ts +0 -6
- package/lib/structures/ITtscRegisterOptions.js +0 -3
- package/lib/structures/ITtscRegisterOptions.js.map +0 -1
- package/lib/structures/ITtscResolveGoBinaryOptions.d.ts +0 -7
- package/lib/structures/ITtscResolveGoBinaryOptions.js +0 -3
- package/lib/structures/ITtscResolveGoBinaryOptions.js.map +0 -1
- package/lib/structures/ITtscResolveOptions.d.ts +0 -20
- package/lib/structures/ITtscResolveOptions.js +0 -3
- package/lib/structures/ITtscResolveOptions.js.map +0 -1
- package/lib/structures/ITtscResolvedTsgo.d.ts +0 -8
- package/lib/structures/ITtscResolvedTsgo.js +0 -3
- package/lib/structures/ITtscResolvedTsgo.js.map +0 -1
- package/lib/structures/ITtscTransformOptions.d.ts +0 -12
- package/lib/structures/ITtscTransformOptions.js +0 -3
- package/lib/structures/ITtscTransformOptions.js.map +0 -1
- package/lib/structures/ITtscTsgoResolveOptions.d.ts +0 -14
- package/lib/structures/ITtscTsgoResolveOptions.js +0 -3
- package/lib/structures/ITtscTsgoResolveOptions.js.map +0 -1
- package/lib/tsgo.d.ts +0 -6
- package/lib/tsgo.js.map +0 -1
- package/src/api.ts +0 -872
- package/src/native.ts +0 -64
- package/src/platform.ts +0 -151
- package/src/plugin.ts +0 -253
- package/src/runner/register.ts +0 -406
- package/src/structures/ITtscBuildOptions.ts +0 -19
- package/src/structures/ITtscBuildResult.ts +0 -6
- package/src/structures/ITtscBuildSourcePluginOptions.ts +0 -9
- package/src/structures/ITtscCacheKeyInput.ts +0 -7
- package/src/structures/ITtscCheckOptions.ts +0 -3
- package/src/structures/ITtscCommonOptions.ts +0 -23
- package/src/structures/ITtscLoadPluginsOptions.ts +0 -9
- package/src/structures/ITtscLoadedNativePlugin.ts +0 -8
- package/src/structures/ITtscLoadedPlugins.ts +0 -12
- package/src/structures/ITtscNativeBackend.ts +0 -11
- package/src/structures/ITtscNativePluginContractVersion.ts +0 -1
- package/src/structures/ITtscNativePluginShape.ts +0 -9
- package/src/structures/ITtscNativeRewriteMode.ts +0 -1
- package/src/structures/ITtscNativeSource.ts +0 -4
- package/src/structures/ITtscParsedProjectConfig.ts +0 -10
- package/src/structures/ITtscPluginFactory.ts +0 -7
- package/src/structures/ITtscPluginModule.ts +0 -4
- package/src/structures/ITtscPreparedExecution.ts +0 -5
- package/src/structures/ITtscProjectLocatorOptions.ts +0 -5
- package/src/structures/ITtscRegisterOptions.ts +0 -7
- package/src/structures/ITtscResolveGoBinaryOptions.ts +0 -7
- package/src/structures/ITtscResolveOptions.ts +0 -20
- package/src/structures/ITtscResolvedTsgo.ts +0 -8
- package/src/structures/ITtscTransformOptions.ts +0 -13
- package/src/structures/ITtscTsgoResolveOptions.ts +0 -14
- package/test/native.test.ts +0 -103
- /package/lib/structures/{ITtscLoadedNativePlugin.js → internal/ITtscLoadedNativePlugin.js} +0 -0
- /package/lib/structures/{ITtscParsedProjectConfig.js → internal/ITtscParsedProjectConfig.js} +0 -0
- /package/lib/structures/{ITtscProjectLocatorOptions.js → internal/ITtscProjectLocatorOptions.js} +0 -0
package/src/api.ts
DELETED
|
@@ -1,872 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Programmatic API for ttsc.
|
|
3
|
-
*
|
|
4
|
-
* This module is the TypeScript surface bundler adapters (unplugin, vite,
|
|
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
|
-
*
|
|
9
|
-
* Contract:
|
|
10
|
-
*
|
|
11
|
-
* - `transform()` emits one file's rewritten JS, returning the text.
|
|
12
|
-
* - `build()` runs the whole project (tsgo + ttsc rewrite + --emit).
|
|
13
|
-
* - `check()` runs the analysis pass without emitting (CI gate use).
|
|
14
|
-
* - `version()` returns the wrapper and resolved `tsgo` version banner.
|
|
15
|
-
*
|
|
16
|
-
* All helpers accept a `binary` override so tests can point at a specific
|
|
17
|
-
* `tsgo` executable without touching PATH or node_modules.
|
|
18
|
-
*/
|
|
19
|
-
import { spawnSync } from "node:child_process";
|
|
20
|
-
import * as fs from "node:fs";
|
|
21
|
-
import * as os from "node:os";
|
|
22
|
-
import * as path from "node:path";
|
|
23
|
-
|
|
24
|
-
import type { ITtscBuildOptions } from "./structures/ITtscBuildOptions";
|
|
25
|
-
import type { ITtscBuildResult } from "./structures/ITtscBuildResult";
|
|
26
|
-
import type { ITtscCheckOptions } from "./structures/ITtscCheckOptions";
|
|
27
|
-
import type { ITtscCommonOptions } from "./structures/ITtscCommonOptions";
|
|
28
|
-
import type { ITtscLoadedNativePlugin } from "./structures/ITtscLoadedNativePlugin";
|
|
29
|
-
import type { ITtscResolvedTsgo } from "./structures/ITtscResolvedTsgo";
|
|
30
|
-
import type { ITtscTransformOptions } from "./structures/ITtscTransformOptions";
|
|
31
|
-
import { resolveBinary } from "./platform";
|
|
32
|
-
import { loadProjectPlugins } from "./plugin";
|
|
33
|
-
import { resolveProjectConfig, resolveProjectRoot } from "./project";
|
|
34
|
-
import { resolveTsgo } from "./tsgo";
|
|
35
|
-
|
|
36
|
-
export type { ITtscBuildOptions } from "./structures/ITtscBuildOptions";
|
|
37
|
-
export type { ITtscBuildResult } from "./structures/ITtscBuildResult";
|
|
38
|
-
export type { ITtscCheckOptions } from "./structures/ITtscCheckOptions";
|
|
39
|
-
export type { ITtscCommonOptions } from "./structures/ITtscCommonOptions";
|
|
40
|
-
export type { ITtscTransformOptions } from "./structures/ITtscTransformOptions";
|
|
41
|
-
|
|
42
|
-
/** Merge spawn env without clobbering unrelated vars. */
|
|
43
|
-
function mergeEnv(extra?: NodeJS.ProcessEnv): NodeJS.ProcessEnv {
|
|
44
|
-
const base = {
|
|
45
|
-
...process.env,
|
|
46
|
-
TTSC_NODE_BINARY: process.env.TTSC_NODE_BINARY ?? process.execPath,
|
|
47
|
-
};
|
|
48
|
-
if (!extra) return base;
|
|
49
|
-
return { ...base, ...extra };
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
function nativePluginEnv(
|
|
53
|
-
extra: NodeJS.ProcessEnv | undefined,
|
|
54
|
-
execution: ITtscExecutionContext,
|
|
55
|
-
): NodeJS.ProcessEnv {
|
|
56
|
-
return mergeEnv({
|
|
57
|
-
TTSC_TSGO_BINARY: process.env.TTSC_TSGO_BINARY ?? execution.tsgo.binary,
|
|
58
|
-
TTSC_TTSX_BINARY:
|
|
59
|
-
process.env.TTSC_TTSX_BINARY ?? path.join(__dirname, "launcher", "ttsx.js"),
|
|
60
|
-
...extra,
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
function spawnBinary(
|
|
65
|
-
binary: string,
|
|
66
|
-
args: readonly string[],
|
|
67
|
-
options: {
|
|
68
|
-
cwd?: string;
|
|
69
|
-
env?: NodeJS.ProcessEnv;
|
|
70
|
-
encoding?: BufferEncoding;
|
|
71
|
-
},
|
|
72
|
-
) {
|
|
73
|
-
const viaNode = shouldSpawnViaNode(binary);
|
|
74
|
-
if (!viaNode) {
|
|
75
|
-
ensureExecutable(binary);
|
|
76
|
-
}
|
|
77
|
-
return spawnSync(
|
|
78
|
-
viaNode ? process.execPath : binary,
|
|
79
|
-
viaNode ? [binary, ...args] : [...args],
|
|
80
|
-
{
|
|
81
|
-
cwd: options.cwd,
|
|
82
|
-
env: options.env,
|
|
83
|
-
encoding: options.encoding,
|
|
84
|
-
maxBuffer: 1024 * 1024 * 256,
|
|
85
|
-
windowsHide: true,
|
|
86
|
-
},
|
|
87
|
-
);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
function shouldSpawnViaNode(binary: string): boolean {
|
|
91
|
-
return /\.(?:[cm]?js|ts)$/i.test(binary);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
function ensureExecutable(binary: string): void {
|
|
95
|
-
if (process.platform === "win32") {
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
try {
|
|
99
|
-
const mode = fs.statSync(binary).mode & 0o777;
|
|
100
|
-
if ((mode & 0o111) !== 0) {
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
|
-
fs.chmodSync(binary, mode | 0o755);
|
|
104
|
-
} catch {
|
|
105
|
-
/* keep the original spawn error path */
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
function outputText(value: string | Buffer | null | undefined): string {
|
|
110
|
-
if (value == null) {
|
|
111
|
-
return "";
|
|
112
|
-
}
|
|
113
|
-
return typeof value === "string" ? value : value.toString("utf8");
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
function hasCapability(
|
|
117
|
-
plugin: ITtscLoadedNativePlugin,
|
|
118
|
-
capability: string,
|
|
119
|
-
): boolean {
|
|
120
|
-
return plugin.backend.capabilities?.includes(capability) === true;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
function isOutputPlugin(plugin: ITtscLoadedNativePlugin): boolean {
|
|
124
|
-
return hasCapability(plugin, "output");
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
function isCheckOnlyPlugin(plugin: ITtscLoadedNativePlugin): boolean {
|
|
128
|
-
const capabilities = plugin.backend.capabilities ?? [];
|
|
129
|
-
return (
|
|
130
|
-
capabilities.length > 0 &&
|
|
131
|
-
capabilities.every((capability) => capability === "check")
|
|
132
|
-
);
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
function isCompilerPlugin(plugin: ITtscLoadedNativePlugin): boolean {
|
|
136
|
-
return !isOutputPlugin(plugin) && !isCheckOnlyPlugin(plugin);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
function outputPlugins(
|
|
140
|
-
plugins: readonly ITtscLoadedNativePlugin[],
|
|
141
|
-
): ITtscLoadedNativePlugin[] {
|
|
142
|
-
return plugins.filter(isOutputPlugin);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
function checkOnlyPlugins(
|
|
146
|
-
plugins: readonly ITtscLoadedNativePlugin[],
|
|
147
|
-
): ITtscLoadedNativePlugin[] {
|
|
148
|
-
return plugins.filter(isCheckOnlyPlugin);
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
function compilerPlugins(
|
|
152
|
-
plugins: readonly ITtscLoadedNativePlugin[],
|
|
153
|
-
): ITtscLoadedNativePlugin[] {
|
|
154
|
-
return plugins.filter(isCompilerPlugin);
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
/**
|
|
158
|
-
* Transform a single .ts file and return the rewritten JS as a string.
|
|
159
|
-
*
|
|
160
|
-
* Intended for bundler per-file transforms (unplugin `transform()`). The caller
|
|
161
|
-
* passes the absolute path; ttsc loads the enclosing tsconfig, compiles with
|
|
162
|
-
* tsgo, and returns the rewritten JS.
|
|
163
|
-
*
|
|
164
|
-
* Throws when the binary exits non-zero — the error includes stderr so bundler
|
|
165
|
-
* error overlays surface the real cause.
|
|
166
|
-
*/
|
|
167
|
-
export function transform(options: ITtscTransformOptions): string {
|
|
168
|
-
const execution = resolveExecutionContext(options);
|
|
169
|
-
const sourceFile = realpathIfExists(
|
|
170
|
-
path.isAbsolute(options.file)
|
|
171
|
-
? options.file
|
|
172
|
-
: path.resolve(options.cwd ?? process.cwd(), options.file),
|
|
173
|
-
);
|
|
174
|
-
if (execution.nativePlugins.length > 0) {
|
|
175
|
-
return transformWithNativePlugins(options, execution, sourceFile);
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
const tempOutDir = fs.mkdtempSync(path.join(os.tmpdir(), "ttsc-transform-"));
|
|
179
|
-
try {
|
|
180
|
-
const result = build({
|
|
181
|
-
...options,
|
|
182
|
-
emit: true,
|
|
183
|
-
outDir: tempOutDir,
|
|
184
|
-
plugins: false,
|
|
185
|
-
tsconfig: execution.tsconfig,
|
|
186
|
-
});
|
|
187
|
-
if (result.status !== 0) {
|
|
188
|
-
throw new Error(
|
|
189
|
-
"ttsc.transform exited " +
|
|
190
|
-
result.status +
|
|
191
|
-
"\n" +
|
|
192
|
-
(result.stderr || result.stdout),
|
|
193
|
-
);
|
|
194
|
-
}
|
|
195
|
-
const emitted = findEmittedFile(tempOutDir, execution.projectRoot, sourceFile);
|
|
196
|
-
if (!emitted) {
|
|
197
|
-
throw new Error(`ttsc.transform: no output produced for ${sourceFile}`);
|
|
198
|
-
}
|
|
199
|
-
const transformed = fs.readFileSync(emitted, "utf8");
|
|
200
|
-
if (options.out) {
|
|
201
|
-
fs.mkdirSync(path.dirname(options.out), { recursive: true });
|
|
202
|
-
fs.writeFileSync(options.out, transformed, "utf8");
|
|
203
|
-
}
|
|
204
|
-
return transformed;
|
|
205
|
-
} finally {
|
|
206
|
-
fs.rmSync(tempOutDir, { recursive: true, force: true });
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
function transformWithNativePlugins(
|
|
211
|
-
options: ITtscTransformOptions,
|
|
212
|
-
execution: ITtscExecutionContext,
|
|
213
|
-
sourceFile: string,
|
|
214
|
-
): string {
|
|
215
|
-
const checked = runNativeCheckPlugins(options, execution);
|
|
216
|
-
if (checked.status !== 0) {
|
|
217
|
-
throw new Error(
|
|
218
|
-
"ttsc.transform exited " + checked.status + "\n" + checked.stderr,
|
|
219
|
-
);
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
const compilers = compilerPlugins(execution.nativePlugins);
|
|
223
|
-
const outputs = outputPlugins(execution.nativePlugins);
|
|
224
|
-
const tempOutDir = fs.mkdtempSync(path.join(os.tmpdir(), "ttsc-transform-"));
|
|
225
|
-
try {
|
|
226
|
-
let emitted: string | null = null;
|
|
227
|
-
if (compilers.length !== 0) {
|
|
228
|
-
assertSingleCompilerHost(compilers);
|
|
229
|
-
emitted = path.join(tempOutDir, "transform.js");
|
|
230
|
-
const transformed = runNativeCompilerTransform(
|
|
231
|
-
options,
|
|
232
|
-
execution,
|
|
233
|
-
sourceFile,
|
|
234
|
-
emitted,
|
|
235
|
-
compilers,
|
|
236
|
-
);
|
|
237
|
-
if (transformed.status !== 0) {
|
|
238
|
-
throw new Error(
|
|
239
|
-
"ttsc.transform exited " +
|
|
240
|
-
transformed.status +
|
|
241
|
-
"\n" +
|
|
242
|
-
transformed.stderr,
|
|
243
|
-
);
|
|
244
|
-
}
|
|
245
|
-
} else {
|
|
246
|
-
const result = build({
|
|
247
|
-
...options,
|
|
248
|
-
emit: true,
|
|
249
|
-
outDir: tempOutDir,
|
|
250
|
-
plugins: false,
|
|
251
|
-
skipDiagnosticsCheck: checkOnlyPlugins(execution.nativePlugins).length !== 0,
|
|
252
|
-
tsconfig: execution.tsconfig,
|
|
253
|
-
});
|
|
254
|
-
if (result.status !== 0) {
|
|
255
|
-
throw new Error(
|
|
256
|
-
"ttsc.transform exited " +
|
|
257
|
-
result.status +
|
|
258
|
-
"\n" +
|
|
259
|
-
(result.stderr || result.stdout),
|
|
260
|
-
);
|
|
261
|
-
}
|
|
262
|
-
emitted = findEmittedFile(tempOutDir, execution.projectRoot, sourceFile);
|
|
263
|
-
if (!emitted) {
|
|
264
|
-
throw new Error(`ttsc.transform: no output produced for ${sourceFile}`);
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
for (const plugin of outputs) {
|
|
269
|
-
const result = runNativeOutputPlugin(options, execution, plugin, emitted);
|
|
270
|
-
if (result.status !== 0) {
|
|
271
|
-
throw new Error(
|
|
272
|
-
"ttsc.transform exited " +
|
|
273
|
-
result.status +
|
|
274
|
-
"\n" +
|
|
275
|
-
(result.stderr || result.stdout),
|
|
276
|
-
);
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
const transformed = fs.readFileSync(emitted, "utf8");
|
|
281
|
-
if (options.out) {
|
|
282
|
-
fs.mkdirSync(path.dirname(options.out), { recursive: true });
|
|
283
|
-
fs.writeFileSync(options.out, transformed, "utf8");
|
|
284
|
-
}
|
|
285
|
-
return transformed;
|
|
286
|
-
} finally {
|
|
287
|
-
fs.rmSync(tempOutDir, { recursive: true, force: true });
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
function realpathIfExists(file: string): string {
|
|
292
|
-
try {
|
|
293
|
-
return fs.realpathSync(file);
|
|
294
|
-
} catch {
|
|
295
|
-
return file;
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
/**
|
|
300
|
-
* Run `ttsc` against a tsconfig. Returns once the binary exits so the caller
|
|
301
|
-
* can decide how to surface diagnostics. Does not throw on non-zero exit —
|
|
302
|
-
* bundler pipelines often want to continue and collect errors.
|
|
303
|
-
*/
|
|
304
|
-
export function build(options: ITtscBuildOptions = {}): ITtscBuildResult {
|
|
305
|
-
const execution = resolveExecutionContext(options);
|
|
306
|
-
if (execution.nativePlugins.length > 0) {
|
|
307
|
-
const compilers = compilerPlugins(execution.nativePlugins);
|
|
308
|
-
const outputs = outputPlugins(execution.nativePlugins);
|
|
309
|
-
const checked = runNativeCheckPlugins(options, execution);
|
|
310
|
-
if (checked.status !== 0) {
|
|
311
|
-
return checked;
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
if (options.emit === false) {
|
|
315
|
-
if (compilers.length !== 0) {
|
|
316
|
-
assertSingleCompilerHost(compilers);
|
|
317
|
-
return appendBuildOutput(
|
|
318
|
-
checked,
|
|
319
|
-
buildWithNativeCompilerPlugins(options, execution, compilers),
|
|
320
|
-
);
|
|
321
|
-
}
|
|
322
|
-
if (checked.stdout !== "" || checked.stderr !== "") {
|
|
323
|
-
return checked;
|
|
324
|
-
}
|
|
325
|
-
return runTsgo(execution, ["--noEmit"], options);
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
let result: ITtscBuildResult;
|
|
329
|
-
if (compilers.length !== 0) {
|
|
330
|
-
assertSingleCompilerHost(compilers);
|
|
331
|
-
result = appendBuildOutput(
|
|
332
|
-
checked,
|
|
333
|
-
buildWithNativeCompilerPlugins(options, execution, compilers),
|
|
334
|
-
);
|
|
335
|
-
} else {
|
|
336
|
-
if (
|
|
337
|
-
checked.stdout === "" &&
|
|
338
|
-
checked.stderr === "" &&
|
|
339
|
-
options.skipDiagnosticsCheck !== true
|
|
340
|
-
) {
|
|
341
|
-
const tsgoChecked = runTsgo(execution, ["--noEmit"], options);
|
|
342
|
-
if (tsgoChecked.status !== 0) {
|
|
343
|
-
return tsgoChecked;
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
const args = createTsgoBuildArgs(execution, options, {
|
|
347
|
-
listEmittedFiles:
|
|
348
|
-
outputs.length !== 0 || options.forceListEmittedFiles === true,
|
|
349
|
-
});
|
|
350
|
-
const emitted = runTsgoBuild(execution, options, args);
|
|
351
|
-
result = appendBuildOutput(checked, emitted);
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
if (result.status !== 0 || outputs.length === 0) {
|
|
355
|
-
return result;
|
|
356
|
-
}
|
|
357
|
-
return appendBuildOutput(
|
|
358
|
-
result,
|
|
359
|
-
applyOutputPlugins(options, execution, result.emittedFiles ?? [], outputs),
|
|
360
|
-
);
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
if (options.emit !== false && options.skipDiagnosticsCheck !== true) {
|
|
364
|
-
const checked = runTsgo(execution, ["--noEmit"], options);
|
|
365
|
-
if (checked.status !== 0) {
|
|
366
|
-
return checked;
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
const args = createTsgoBuildArgs(execution, options, {
|
|
371
|
-
listEmittedFiles:
|
|
372
|
-
options.emit !== false && options.forceListEmittedFiles === true,
|
|
373
|
-
});
|
|
374
|
-
return runTsgoBuild(execution, options, args);
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
function buildWithNativeCompilerPlugins(
|
|
378
|
-
options: ITtscBuildOptions,
|
|
379
|
-
execution: ITtscExecutionContext,
|
|
380
|
-
plugins: readonly ITtscLoadedNativePlugin[],
|
|
381
|
-
): ITtscBuildResult {
|
|
382
|
-
return runNativePluginCommand(
|
|
383
|
-
plugins[0]!,
|
|
384
|
-
createNativeBuildArgs(execution, options, plugins),
|
|
385
|
-
options,
|
|
386
|
-
execution,
|
|
387
|
-
"ttsc.build",
|
|
388
|
-
);
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
/**
|
|
392
|
-
* Run `ttsc check` (build without emit) — CI gate / pre-commit hook use.
|
|
393
|
-
* Resolves with an exit-code record; does not throw.
|
|
394
|
-
*/
|
|
395
|
-
export function check(options: ITtscCheckOptions = {}): ITtscBuildResult {
|
|
396
|
-
return build({ ...options, emit: false });
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
function runTsgo(
|
|
400
|
-
execution: ITtscExecutionContext,
|
|
401
|
-
extraArgs: readonly string[],
|
|
402
|
-
options: ITtscBuildOptions,
|
|
403
|
-
): ITtscBuildResult {
|
|
404
|
-
const res = spawnBinary(
|
|
405
|
-
execution.tsgo.binary,
|
|
406
|
-
["-p", execution.tsconfig, ...extraArgs],
|
|
407
|
-
{
|
|
408
|
-
cwd: execution.projectRoot,
|
|
409
|
-
env: mergeEnv(options.env),
|
|
410
|
-
encoding: "utf8",
|
|
411
|
-
},
|
|
412
|
-
);
|
|
413
|
-
if (res.error) {
|
|
414
|
-
throw new Error(
|
|
415
|
-
"ttsc: failed to spawn " + execution.tsgo.binary + ": " + res.error.message,
|
|
416
|
-
);
|
|
417
|
-
}
|
|
418
|
-
return normalizeFailedDiagnostics({
|
|
419
|
-
status: res.status ?? 1,
|
|
420
|
-
stdout: outputText(res.stdout),
|
|
421
|
-
stderr: outputText(res.stderr),
|
|
422
|
-
});
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
function runTsgoBuild(
|
|
426
|
-
execution: ITtscExecutionContext,
|
|
427
|
-
options: ITtscBuildOptions,
|
|
428
|
-
args: readonly string[],
|
|
429
|
-
): ITtscBuildResult {
|
|
430
|
-
const res = spawnBinary(execution.tsgo.binary, args, {
|
|
431
|
-
cwd: execution.projectRoot,
|
|
432
|
-
env: mergeEnv(options.env),
|
|
433
|
-
encoding: "utf8",
|
|
434
|
-
});
|
|
435
|
-
if (res.error) {
|
|
436
|
-
throw new Error(
|
|
437
|
-
"ttsc.build: failed to spawn " +
|
|
438
|
-
execution.tsgo.binary +
|
|
439
|
-
": " +
|
|
440
|
-
res.error.message,
|
|
441
|
-
);
|
|
442
|
-
}
|
|
443
|
-
const result = {
|
|
444
|
-
status: res.status ?? 1,
|
|
445
|
-
stdout: outputText(res.stdout),
|
|
446
|
-
stderr: outputText(res.stderr),
|
|
447
|
-
};
|
|
448
|
-
const emittedFiles = parseEmittedFiles(result.stdout);
|
|
449
|
-
if (emittedFiles.length !== 0) {
|
|
450
|
-
result.stdout = stripEmittedFileLines(result.stdout);
|
|
451
|
-
}
|
|
452
|
-
return normalizeFailedDiagnostics({ ...result, emittedFiles });
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
function createTsgoBuildArgs(
|
|
456
|
-
execution: ITtscExecutionContext,
|
|
457
|
-
options: ITtscBuildOptions,
|
|
458
|
-
flags: { listEmittedFiles: boolean },
|
|
459
|
-
): string[] {
|
|
460
|
-
const args = ["-p", execution.tsconfig];
|
|
461
|
-
if (options.emit === true) {
|
|
462
|
-
args.push("--noEmit", "false", "--emitDeclarationOnly", "false");
|
|
463
|
-
} else if (options.emit === false) {
|
|
464
|
-
args.push("--noEmit");
|
|
465
|
-
}
|
|
466
|
-
if (options.outDir) {
|
|
467
|
-
args.push("--outDir", path.resolve(execution.cwd, options.outDir));
|
|
468
|
-
}
|
|
469
|
-
if (flags.listEmittedFiles) {
|
|
470
|
-
args.push("--listEmittedFiles");
|
|
471
|
-
}
|
|
472
|
-
return args;
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
function createNativeBuildArgs(
|
|
476
|
-
execution: ITtscExecutionContext,
|
|
477
|
-
options: ITtscBuildOptions,
|
|
478
|
-
plugins: readonly ITtscLoadedNativePlugin[],
|
|
479
|
-
): string[] {
|
|
480
|
-
const args = [
|
|
481
|
-
options.emit === false ? "check" : "build",
|
|
482
|
-
"--tsconfig=" + execution.tsconfig,
|
|
483
|
-
"--rewrite-mode=" + (options.rewriteMode ?? plugins[0]?.backend.mode ?? "none"),
|
|
484
|
-
"--plugins-json=" + serializeNativePlugins(plugins),
|
|
485
|
-
"--cwd=" + execution.projectRoot,
|
|
486
|
-
];
|
|
487
|
-
if (options.emit === true) {
|
|
488
|
-
args.push("--emit");
|
|
489
|
-
} else if (options.emit === false) {
|
|
490
|
-
args.push("--noEmit");
|
|
491
|
-
}
|
|
492
|
-
if (options.outDir) {
|
|
493
|
-
args.push("--outDir=" + path.resolve(execution.cwd, options.outDir));
|
|
494
|
-
}
|
|
495
|
-
if (options.quiet === false) {
|
|
496
|
-
args.push("--verbose");
|
|
497
|
-
} else if (options.quiet === true) {
|
|
498
|
-
args.push("--quiet");
|
|
499
|
-
}
|
|
500
|
-
return args;
|
|
501
|
-
}
|
|
502
|
-
|
|
503
|
-
function createNativeCheckArgs(
|
|
504
|
-
execution: ITtscExecutionContext,
|
|
505
|
-
options: ITtscBuildOptions | ITtscTransformOptions,
|
|
506
|
-
plugin: ITtscLoadedNativePlugin,
|
|
507
|
-
): string[] {
|
|
508
|
-
const args = [
|
|
509
|
-
"check",
|
|
510
|
-
"--tsconfig=" + execution.tsconfig,
|
|
511
|
-
"--rewrite-mode=" + (options.rewriteMode ?? plugin.backend.mode),
|
|
512
|
-
"--plugins-json=" + serializeNativePlugins(execution.nativePlugins),
|
|
513
|
-
"--cwd=" + execution.projectRoot,
|
|
514
|
-
];
|
|
515
|
-
if ("outDir" in options && options.outDir) {
|
|
516
|
-
args.push("--outDir=" + path.resolve(execution.cwd, options.outDir));
|
|
517
|
-
}
|
|
518
|
-
if ("quiet" in options && options.quiet === false) {
|
|
519
|
-
args.push("--verbose");
|
|
520
|
-
} else if ("quiet" in options && options.quiet === true) {
|
|
521
|
-
args.push("--quiet");
|
|
522
|
-
}
|
|
523
|
-
return args;
|
|
524
|
-
}
|
|
525
|
-
|
|
526
|
-
function createNativeOutputArgs(
|
|
527
|
-
execution: ITtscExecutionContext,
|
|
528
|
-
options: ITtscBuildOptions | ITtscTransformOptions,
|
|
529
|
-
plugin: ITtscLoadedNativePlugin,
|
|
530
|
-
file: string,
|
|
531
|
-
): string[] {
|
|
532
|
-
const args = [
|
|
533
|
-
"output",
|
|
534
|
-
"--file=" + file,
|
|
535
|
-
"--tsconfig=" + execution.tsconfig,
|
|
536
|
-
"--rewrite-mode=" + (options.rewriteMode ?? plugin.backend.mode),
|
|
537
|
-
"--plugins-json=" + serializeNativePlugins(execution.nativePlugins),
|
|
538
|
-
"--cwd=" + execution.projectRoot,
|
|
539
|
-
];
|
|
540
|
-
if ("outDir" in options && options.outDir) {
|
|
541
|
-
args.push("--outDir=" + path.resolve(execution.cwd, options.outDir));
|
|
542
|
-
}
|
|
543
|
-
return args;
|
|
544
|
-
}
|
|
545
|
-
|
|
546
|
-
function createNativeTransformArgs(
|
|
547
|
-
execution: ITtscExecutionContext,
|
|
548
|
-
options: ITtscTransformOptions,
|
|
549
|
-
sourceFile: string,
|
|
550
|
-
out: string,
|
|
551
|
-
plugins: readonly ITtscLoadedNativePlugin[],
|
|
552
|
-
): string[] {
|
|
553
|
-
return [
|
|
554
|
-
"transform",
|
|
555
|
-
"--file=" + sourceFile,
|
|
556
|
-
"--out=" + out,
|
|
557
|
-
"--tsconfig=" + execution.tsconfig,
|
|
558
|
-
"--rewrite-mode=" + (options.rewriteMode ?? plugins[0]?.backend.mode ?? "none"),
|
|
559
|
-
"--plugins-json=" + serializeNativePlugins(plugins),
|
|
560
|
-
];
|
|
561
|
-
}
|
|
562
|
-
|
|
563
|
-
function serializeNativePlugins(plugins: readonly ITtscLoadedNativePlugin[]): string {
|
|
564
|
-
return JSON.stringify(
|
|
565
|
-
plugins.map((plugin) => ({
|
|
566
|
-
config: plugin.config,
|
|
567
|
-
contractVersion: plugin.backend.contractVersion,
|
|
568
|
-
mode: plugin.backend.mode,
|
|
569
|
-
name: plugin.name,
|
|
570
|
-
})),
|
|
571
|
-
);
|
|
572
|
-
}
|
|
573
|
-
|
|
574
|
-
function runNativeCheckPlugins(
|
|
575
|
-
options: ITtscBuildOptions | ITtscTransformOptions,
|
|
576
|
-
execution: ITtscExecutionContext,
|
|
577
|
-
): ITtscBuildResult {
|
|
578
|
-
let out: ITtscBuildResult = { status: 0, stdout: "", stderr: "" };
|
|
579
|
-
for (const plugin of checkOnlyPlugins(execution.nativePlugins)) {
|
|
580
|
-
const result = runNativePluginCommand(
|
|
581
|
-
plugin,
|
|
582
|
-
createNativeCheckArgs(execution, options, plugin),
|
|
583
|
-
options,
|
|
584
|
-
execution,
|
|
585
|
-
"ttsc.check",
|
|
586
|
-
);
|
|
587
|
-
out = appendBuildOutput(out, result);
|
|
588
|
-
if (result.status !== 0) {
|
|
589
|
-
return out;
|
|
590
|
-
}
|
|
591
|
-
}
|
|
592
|
-
return out;
|
|
593
|
-
}
|
|
594
|
-
|
|
595
|
-
function runNativeCompilerTransform(
|
|
596
|
-
options: ITtscTransformOptions,
|
|
597
|
-
execution: ITtscExecutionContext,
|
|
598
|
-
sourceFile: string,
|
|
599
|
-
out: string,
|
|
600
|
-
plugins: readonly ITtscLoadedNativePlugin[],
|
|
601
|
-
): ITtscBuildResult {
|
|
602
|
-
return runNativePluginCommand(
|
|
603
|
-
plugins[0]!,
|
|
604
|
-
createNativeTransformArgs(execution, options, sourceFile, out, plugins),
|
|
605
|
-
options,
|
|
606
|
-
execution,
|
|
607
|
-
"ttsc.transform",
|
|
608
|
-
);
|
|
609
|
-
}
|
|
610
|
-
|
|
611
|
-
function applyOutputPlugins(
|
|
612
|
-
options: ITtscBuildOptions,
|
|
613
|
-
execution: ITtscExecutionContext,
|
|
614
|
-
emittedFiles: readonly string[],
|
|
615
|
-
plugins: readonly ITtscLoadedNativePlugin[],
|
|
616
|
-
): ITtscBuildResult {
|
|
617
|
-
let out: ITtscBuildResult = { status: 0, stdout: "", stderr: "" };
|
|
618
|
-
for (const plugin of plugins) {
|
|
619
|
-
for (const file of emittedFiles) {
|
|
620
|
-
if (!fs.existsSync(file)) {
|
|
621
|
-
continue;
|
|
622
|
-
}
|
|
623
|
-
const result = runNativeOutputPlugin(options, execution, plugin, file);
|
|
624
|
-
out = appendBuildOutput(out, result);
|
|
625
|
-
if (result.status !== 0) {
|
|
626
|
-
return out;
|
|
627
|
-
}
|
|
628
|
-
}
|
|
629
|
-
}
|
|
630
|
-
return out;
|
|
631
|
-
}
|
|
632
|
-
|
|
633
|
-
function runNativeOutputPlugin(
|
|
634
|
-
options: ITtscBuildOptions | ITtscTransformOptions,
|
|
635
|
-
execution: ITtscExecutionContext,
|
|
636
|
-
plugin: ITtscLoadedNativePlugin,
|
|
637
|
-
file: string,
|
|
638
|
-
): ITtscBuildResult {
|
|
639
|
-
return runNativePluginCommand(
|
|
640
|
-
plugin,
|
|
641
|
-
createNativeOutputArgs(execution, options, plugin, file),
|
|
642
|
-
options,
|
|
643
|
-
execution,
|
|
644
|
-
"ttsc.output",
|
|
645
|
-
);
|
|
646
|
-
}
|
|
647
|
-
|
|
648
|
-
function runNativePluginCommand(
|
|
649
|
-
plugin: ITtscLoadedNativePlugin,
|
|
650
|
-
args: readonly string[],
|
|
651
|
-
options: ITtscBuildOptions | ITtscTransformOptions,
|
|
652
|
-
execution: ITtscExecutionContext,
|
|
653
|
-
label: string,
|
|
654
|
-
): ITtscBuildResult {
|
|
655
|
-
const binary = plugin.backend.binary;
|
|
656
|
-
if (!binary) {
|
|
657
|
-
return {
|
|
658
|
-
status: 2,
|
|
659
|
-
stdout: "",
|
|
660
|
-
stderr: `${label}: plugin "${plugin.name}" requires a version-matched binary\n`,
|
|
661
|
-
};
|
|
662
|
-
}
|
|
663
|
-
const res = spawnBinary(binary, args, {
|
|
664
|
-
cwd: execution.projectRoot,
|
|
665
|
-
env: nativePluginEnv(options.env, execution),
|
|
666
|
-
encoding: "utf8",
|
|
667
|
-
});
|
|
668
|
-
if (res.error) {
|
|
669
|
-
throw new Error(
|
|
670
|
-
`${label}: failed to spawn ${binary}: ${res.error.message}`,
|
|
671
|
-
);
|
|
672
|
-
}
|
|
673
|
-
return normalizeFailedDiagnostics({
|
|
674
|
-
status: res.status ?? 1,
|
|
675
|
-
stdout: outputText(res.stdout),
|
|
676
|
-
stderr: outputText(res.stderr),
|
|
677
|
-
});
|
|
678
|
-
}
|
|
679
|
-
|
|
680
|
-
function appendBuildOutput(left: ITtscBuildResult, right: ITtscBuildResult): ITtscBuildResult {
|
|
681
|
-
return normalizeFailedDiagnostics({
|
|
682
|
-
emittedFiles:
|
|
683
|
-
right.emittedFiles !== undefined ? right.emittedFiles : left.emittedFiles,
|
|
684
|
-
status: right.status !== 0 ? right.status : left.status,
|
|
685
|
-
stdout: left.stdout + right.stdout,
|
|
686
|
-
stderr: left.stderr + right.stderr,
|
|
687
|
-
});
|
|
688
|
-
}
|
|
689
|
-
|
|
690
|
-
function assertSingleCompilerHost(plugins: readonly ITtscLoadedNativePlugin[]): void {
|
|
691
|
-
const binaries = [
|
|
692
|
-
...new Set(
|
|
693
|
-
plugins
|
|
694
|
-
.map((plugin) => plugin.backend.binary)
|
|
695
|
-
.filter((binary): binary is string => typeof binary === "string"),
|
|
696
|
-
),
|
|
697
|
-
];
|
|
698
|
-
if (binaries.length > 1) {
|
|
699
|
-
throw new Error(
|
|
700
|
-
"ttsc: multiple compiler native backends cannot share one emit pass; " +
|
|
701
|
-
"use output-capability plugins for post-emit transforms",
|
|
702
|
-
);
|
|
703
|
-
}
|
|
704
|
-
}
|
|
705
|
-
|
|
706
|
-
/** Ask the binary for its version banner. Handy for user-agent strings. */
|
|
707
|
-
export function version(options: ITtscCommonOptions = {}): string {
|
|
708
|
-
const tsgo = resolveTsgo(options);
|
|
709
|
-
const res = spawnBinary(tsgo.binary, ["--version"], {
|
|
710
|
-
encoding: "utf8",
|
|
711
|
-
});
|
|
712
|
-
if (res.error || res.status !== 0) {
|
|
713
|
-
throw new Error(
|
|
714
|
-
"ttsc.version: failed: " + (outputText(res.stderr) || res.error?.message),
|
|
715
|
-
);
|
|
716
|
-
}
|
|
717
|
-
return `ttsc ${readOwnPackageVersion()} (${outputText(res.stdout).trim()})`;
|
|
718
|
-
}
|
|
719
|
-
|
|
720
|
-
/**
|
|
721
|
-
* Promise-facing variant of `transform()`. The host path stays synchronous so
|
|
722
|
-
* plugin descriptors can stay dependency-free, but many adapter surfaces still
|
|
723
|
-
* prefer a Promise-returning function.
|
|
724
|
-
*/
|
|
725
|
-
export function transformAsync(options: ITtscTransformOptions): Promise<string> {
|
|
726
|
-
return Promise.resolve().then(() => transform(options));
|
|
727
|
-
}
|
|
728
|
-
|
|
729
|
-
interface ITtscExecutionContext {
|
|
730
|
-
compilerOptions: Record<string, unknown>;
|
|
731
|
-
cwd: string;
|
|
732
|
-
nativePlugins: readonly ITtscLoadedNativePlugin[];
|
|
733
|
-
projectRoot: string;
|
|
734
|
-
tsgo: ITtscResolvedTsgo;
|
|
735
|
-
tsconfig: string;
|
|
736
|
-
}
|
|
737
|
-
|
|
738
|
-
function resolveExecutionContext(
|
|
739
|
-
options: ITtscCommonOptions & { tsconfig?: string },
|
|
740
|
-
): ITtscExecutionContext {
|
|
741
|
-
const cwd = path.resolve(options.cwd ?? process.cwd());
|
|
742
|
-
const tsconfig = resolveProjectConfig({
|
|
743
|
-
cwd,
|
|
744
|
-
tsconfig: options.tsconfig,
|
|
745
|
-
});
|
|
746
|
-
const projectRoot = resolveProjectRoot({ cwd, tsconfig });
|
|
747
|
-
const tsgo = resolveTsgo({ ...options, cwd: projectRoot });
|
|
748
|
-
const fallbackBinary = resolveBinary(options);
|
|
749
|
-
const loaded = loadProjectPlugins({
|
|
750
|
-
binary: fallbackBinary ?? "",
|
|
751
|
-
cwd,
|
|
752
|
-
entries: options.plugins,
|
|
753
|
-
tsconfig,
|
|
754
|
-
});
|
|
755
|
-
return {
|
|
756
|
-
compilerOptions: loaded.project.compilerOptions,
|
|
757
|
-
cwd,
|
|
758
|
-
nativePlugins: loaded.nativePlugins,
|
|
759
|
-
projectRoot,
|
|
760
|
-
tsgo,
|
|
761
|
-
tsconfig,
|
|
762
|
-
};
|
|
763
|
-
}
|
|
764
|
-
|
|
765
|
-
function isJavaScriptOutput(file: string): boolean {
|
|
766
|
-
return /\.(?:[cm]?js)$/i.test(file);
|
|
767
|
-
}
|
|
768
|
-
|
|
769
|
-
function parseEmittedFiles(stdout: string): string[] {
|
|
770
|
-
const out: string[] = [];
|
|
771
|
-
for (const line of stdout.split(/\r?\n/)) {
|
|
772
|
-
const match = line.match(/^TSFILE:\s*(.+)$/);
|
|
773
|
-
if (match?.[1]) {
|
|
774
|
-
out.push(path.resolve(match[1].trim()));
|
|
775
|
-
}
|
|
776
|
-
}
|
|
777
|
-
return out;
|
|
778
|
-
}
|
|
779
|
-
|
|
780
|
-
function stripEmittedFileLines(stdout: string): string {
|
|
781
|
-
return stdout
|
|
782
|
-
.split(/\r?\n/)
|
|
783
|
-
.filter((line) => !/^TSFILE:\s*/.test(line))
|
|
784
|
-
.join("\n")
|
|
785
|
-
.replace(/\n+$/, "");
|
|
786
|
-
}
|
|
787
|
-
|
|
788
|
-
function normalizeFailedDiagnostics(result: ITtscBuildResult): ITtscBuildResult {
|
|
789
|
-
if (result.status === 0 || result.stderr.trim().length !== 0) {
|
|
790
|
-
return result;
|
|
791
|
-
}
|
|
792
|
-
if (result.stdout.trim().length === 0) {
|
|
793
|
-
return result;
|
|
794
|
-
}
|
|
795
|
-
return {
|
|
796
|
-
emittedFiles: result.emittedFiles,
|
|
797
|
-
status: result.status,
|
|
798
|
-
stdout: "",
|
|
799
|
-
stderr: result.stdout,
|
|
800
|
-
};
|
|
801
|
-
}
|
|
802
|
-
|
|
803
|
-
function findEmittedFile(
|
|
804
|
-
outDir: string,
|
|
805
|
-
projectRoot: string,
|
|
806
|
-
sourceFile: string,
|
|
807
|
-
): string | null {
|
|
808
|
-
let best: string | null = null;
|
|
809
|
-
let bestScore = 0;
|
|
810
|
-
for (const file of listJavaScriptFiles(outDir)) {
|
|
811
|
-
const score = sharedSourceStemSegments(file, sourceFile);
|
|
812
|
-
if (score > bestScore) {
|
|
813
|
-
best = file;
|
|
814
|
-
bestScore = score;
|
|
815
|
-
}
|
|
816
|
-
}
|
|
817
|
-
if (best) {
|
|
818
|
-
return best;
|
|
819
|
-
}
|
|
820
|
-
const relative = path.relative(projectRoot, sourceFile);
|
|
821
|
-
if (relative && !relative.startsWith("..") && !path.isAbsolute(relative)) {
|
|
822
|
-
const exact = path.resolve(outDir, relative).replace(/\.[cm]?tsx?$/i, ".js");
|
|
823
|
-
if (fs.existsSync(exact)) {
|
|
824
|
-
return exact;
|
|
825
|
-
}
|
|
826
|
-
}
|
|
827
|
-
return null;
|
|
828
|
-
}
|
|
829
|
-
|
|
830
|
-
function listJavaScriptFiles(root: string): string[] {
|
|
831
|
-
const out: string[] = [];
|
|
832
|
-
const stack = [root];
|
|
833
|
-
while (stack.length !== 0) {
|
|
834
|
-
const current = stack.pop()!;
|
|
835
|
-
if (!fs.existsSync(current)) continue;
|
|
836
|
-
for (const entry of fs.readdirSync(current, { withFileTypes: true })) {
|
|
837
|
-
const next = path.join(current, entry.name);
|
|
838
|
-
if (entry.isDirectory()) {
|
|
839
|
-
stack.push(next);
|
|
840
|
-
} else if (entry.isFile() && isJavaScriptOutput(next)) {
|
|
841
|
-
out.push(next);
|
|
842
|
-
}
|
|
843
|
-
}
|
|
844
|
-
}
|
|
845
|
-
return out;
|
|
846
|
-
}
|
|
847
|
-
|
|
848
|
-
function sharedSourceStemSegments(outPath: string, srcPath: string): number {
|
|
849
|
-
const trim = (value: string): string[] => {
|
|
850
|
-
const normalized = value.replace(/\\/g, "/");
|
|
851
|
-
return normalized.replace(/\.[^.]+$/, "").split("/");
|
|
852
|
-
};
|
|
853
|
-
const a = trim(outPath);
|
|
854
|
-
const b = trim(srcPath);
|
|
855
|
-
const n = Math.min(a.length, b.length);
|
|
856
|
-
let shared = 0;
|
|
857
|
-
for (let i = 1; i <= n; i += 1) {
|
|
858
|
-
if (a[a.length - i] !== b[b.length - i]) break;
|
|
859
|
-
shared += 1;
|
|
860
|
-
}
|
|
861
|
-
return shared;
|
|
862
|
-
}
|
|
863
|
-
|
|
864
|
-
function readOwnPackageVersion(): string {
|
|
865
|
-
try {
|
|
866
|
-
const file = path.resolve(__dirname, "..", "package.json");
|
|
867
|
-
const pkg = JSON.parse(fs.readFileSync(file, "utf8")) as { version?: string };
|
|
868
|
-
return pkg.version ?? "0.0.0";
|
|
869
|
-
} catch {
|
|
870
|
-
return "0.0.0";
|
|
871
|
-
}
|
|
872
|
-
}
|