ttsc 0.3.1 → 0.4.0-dev.20260424
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/LICENSE +1 -1
- package/README.md +216 -302
- package/cmd/ttsc/build.go +128 -0
- package/cmd/ttsc/main.go +222 -0
- package/cmd/ttsc/main_test.go +288 -0
- package/cmd/ttsc/transform.go +166 -0
- package/driver/host.go +31 -0
- package/driver/program.go +298 -0
- package/driver/rewrite.go +315 -0
- package/go.mod +48 -0
- package/go.sum +22 -0
- package/lib/api.d.ts +91 -0
- package/lib/api.js +325 -0
- package/lib/api.js.map +1 -0
- package/lib/cli.d.ts +1 -0
- package/lib/cli.js +481 -0
- package/lib/cli.js.map +1 -0
- package/lib/index.d.ts +17 -0
- package/lib/index.js +34 -0
- package/lib/index.js.map +1 -0
- package/lib/native.d.ts +15 -0
- package/lib/native.js +34 -0
- package/lib/native.js.map +1 -0
- package/lib/platform.d.ts +66 -0
- package/lib/platform.js +170 -0
- package/lib/platform.js.map +1 -0
- package/lib/plugin.d.ts +47 -0
- package/lib/plugin.js +150 -0
- package/lib/plugin.js.map +1 -0
- package/lib/project.d.ts +32 -0
- package/lib/project.js +303 -0
- package/lib/project.js.map +1 -0
- package/package.json +70 -63
- package/shim/ast/extra-shim.json +4 -0
- package/shim/ast/go.mod +5 -0
- package/shim/ast/shim.go +117 -0
- package/shim/bundled/extra-shim.json +1 -0
- package/shim/bundled/go.mod +5 -0
- package/shim/bundled/shim.go +19 -0
- package/shim/checker/extra-shim.json +31 -0
- package/shim/checker/go.mod +5 -0
- package/shim/checker/shim.go +146 -0
- package/shim/compiler/extra-shim.json +4 -0
- package/shim/compiler/go.mod +5 -0
- package/shim/compiler/shim.go +50 -0
- package/shim/core/extra-shim.json +4 -0
- package/shim/core/go.mod +5 -0
- package/shim/core/shim.go +11 -0
- package/shim/diagnosticwriter/go.mod +5 -0
- package/shim/diagnosticwriter/shim.go +29 -0
- package/shim/parser/extra-shim.json +4 -0
- package/shim/parser/go.mod +5 -0
- package/shim/parser/shim.go +55 -0
- package/shim/scanner/extra-shim.json +4 -0
- package/shim/scanner/go.mod +5 -0
- package/shim/scanner/shim.go +96 -0
- package/shim/tsoptions/extra-shim.json +4 -0
- package/shim/tsoptions/go.mod +5 -0
- package/shim/tsoptions/shim.go +123 -0
- package/shim/tspath/extra-shim.json +4 -0
- package/shim/tspath/go.mod +5 -0
- package/shim/tspath/shim.go +165 -0
- package/shim/vfs/cachedvfs/extra-shim.json +4 -0
- package/shim/vfs/cachedvfs/go.mod +5 -0
- package/shim/vfs/cachedvfs/shim.go +12 -0
- package/shim/vfs/extra-shim.json +4 -0
- package/shim/vfs/go.mod +5 -0
- package/shim/vfs/osvfs/extra-shim.json +4 -0
- package/shim/vfs/osvfs/go.mod +5 -0
- package/shim/vfs/osvfs/shim.go +13 -0
- package/shim/vfs/shim.go +19 -0
- package/src/api.ts +416 -0
- package/src/cli.ts +492 -0
- package/src/index.ts +18 -0
- package/src/launcher/ttsc-dev.js +42 -0
- package/src/launcher/ttsc.js +19 -0
- package/src/native.ts +60 -0
- package/src/platform.ts +163 -0
- package/src/plugin.ts +241 -0
- package/src/project.ts +330 -0
- package/test/native.test.ts +60 -0
- package/test/package.test.ts +123 -0
- package/test/platform.test.ts +58 -0
- package/test/project.test.ts +195 -0
- package/tools/gen_shims/go.mod +14 -0
- package/tools/gen_shims/go.sum +12 -0
- package/tools/gen_shims/main.go +446 -0
- package/CHANGELOG.md +0 -2
- package/bin/tsc +0 -2
- package/bin/tsserver +0 -2
- package/lib/PluginCreator.d.ts +0 -67
- package/lib/PluginCreator.js +0 -190
- package/lib/cancelationToken.d.ts +0 -0
- package/lib/cancelationToken.js +0 -2
- package/lib/loadTypescript.d.ts +0 -7
- package/lib/loadTypescript.js +0 -56
- package/lib/patchCreateProgram.d.ts +0 -21
- package/lib/patchCreateProgram.js +0 -190
- package/lib/tsc.d.ts +0 -1
- package/lib/tsc.js +0 -24
- package/lib/tsserver.d.ts +0 -0
- package/lib/tsserver.js +0 -2
- package/lib/tsserverlibrary.d.ts +0 -3
- package/lib/tsserverlibrary.js +0 -4
- package/lib/typescript.d.ts +0 -3
- package/lib/typescript.js +0 -4
- package/lib/typescriptServices.d.ts +0 -3
- package/lib/typescriptServices.js +0 -4
- package/lib/typingsInstaller.d.ts +0 -0
- package/lib/typingsInstaller.js +0 -2
- package/lib/watchGuard.d.ts +0 -0
- package/lib/watchGuard.js +0 -2
package/src/platform.ts
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Platform detection and binary resolution for ttsc.
|
|
3
|
+
*
|
|
4
|
+
* This is the tested implementation used by the ttsc launcher after build.
|
|
5
|
+
* Keep it pure and dependency-free so it can be unit-tested without spawning
|
|
6
|
+
* any child process.
|
|
7
|
+
*
|
|
8
|
+
* Resolution order:
|
|
9
|
+
*
|
|
10
|
+
* 1. `TTSC_BINARY` environment variable (absolute path). Highest priority —
|
|
11
|
+
* lets local devs or CI point at an ad-hoc build without touching
|
|
12
|
+
* node_modules.
|
|
13
|
+
* 2. `@ttsc/{platform}-{arch}/bin/ttsc{.exe}` optional dependency.
|
|
14
|
+
* Standard distribution path.
|
|
15
|
+
* 3. A package-local `native/ttsc-native` binary. Used by this
|
|
16
|
+
* repository's local `pnpm run build` output before the
|
|
17
|
+
* platform packages exist on npm.
|
|
18
|
+
*
|
|
19
|
+
* If every strategy fails, `resolveBinary` returns `null` so the caller can print a
|
|
20
|
+
* detailed install hint.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import * as fs from "node:fs";
|
|
24
|
+
import * as path from "node:path";
|
|
25
|
+
|
|
26
|
+
export interface ResolveOptions {
|
|
27
|
+
/**
|
|
28
|
+
* Override `require.resolve` for testing. Takes a module request string and
|
|
29
|
+
* returns an absolute path (or throws).
|
|
30
|
+
*/
|
|
31
|
+
resolver?: (request: string) => string;
|
|
32
|
+
/** Override `process.platform` for testing. */
|
|
33
|
+
platform?: NodeJS.Platform;
|
|
34
|
+
/** Override `process.arch` for testing. */
|
|
35
|
+
arch?: string;
|
|
36
|
+
/** Override `process.env` for testing. */
|
|
37
|
+
env?: NodeJS.ProcessEnv;
|
|
38
|
+
/**
|
|
39
|
+
* Override the package-local scan used for the local `native/ttsc-native`
|
|
40
|
+
* fallback. Returns an absolute path if present, else null.
|
|
41
|
+
*/
|
|
42
|
+
localBinaryLookup?: () => string | null;
|
|
43
|
+
/** Override the module directory used to resolve the package-local binary. */
|
|
44
|
+
moduleDir?: string;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** Canonical key `{platform}-{arch}` used in the binary package name. */
|
|
48
|
+
export function platformKey(opts: ResolveOptions = {}): string {
|
|
49
|
+
const platform = opts.platform ?? process.platform;
|
|
50
|
+
const arch = opts.arch ?? process.arch;
|
|
51
|
+
return `${platform}-${arch}`;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** Binary filename for the current platform (`.exe` on Windows, else none). */
|
|
55
|
+
export function binaryName(opts: ResolveOptions = {}): string {
|
|
56
|
+
const platform = opts.platform ?? process.platform;
|
|
57
|
+
return platform === "win32" ? "ttsc.exe" : "ttsc";
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Resolve the optional-dependency module request string for the current
|
|
62
|
+
* platform. Separated from actual resolution so we can log the request when
|
|
63
|
+
* the dependency is missing.
|
|
64
|
+
*/
|
|
65
|
+
export function platformPackageRequest(opts: ResolveOptions = {}): string {
|
|
66
|
+
const key = platformKey(opts);
|
|
67
|
+
const bin = binaryName(opts);
|
|
68
|
+
return `@ttsc/${key}/bin/${bin}`;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** The list of platform keys the package currently ships. */
|
|
72
|
+
export const SUPPORTED_PLATFORMS: readonly string[] = Object.freeze([
|
|
73
|
+
"linux-x64",
|
|
74
|
+
"linux-arm64",
|
|
75
|
+
"darwin-x64",
|
|
76
|
+
"darwin-arm64",
|
|
77
|
+
"win32-x64",
|
|
78
|
+
"win32-arm64",
|
|
79
|
+
]);
|
|
80
|
+
|
|
81
|
+
/** True if the given platform key is in the supported list. */
|
|
82
|
+
export function isSupported(key: string): boolean {
|
|
83
|
+
return SUPPORTED_PLATFORMS.includes(key);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Resolve an absolute path to the ttsc binary using the documented priority
|
|
88
|
+
* order. Returns `null` when every strategy fails — the launcher then prints
|
|
89
|
+
* the install hint and exits non-zero.
|
|
90
|
+
*/
|
|
91
|
+
export function resolveBinary(opts: ResolveOptions = {}): string | null {
|
|
92
|
+
const env = opts.env ?? process.env;
|
|
93
|
+
|
|
94
|
+
// 1. Env override. Absolute path is required; a relative value is ignored so
|
|
95
|
+
// tests can't accidentally resolve something outside the intended tree.
|
|
96
|
+
if (env.TTSC_BINARY && path.isAbsolute(env.TTSC_BINARY)) {
|
|
97
|
+
return env.TTSC_BINARY;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// 2. Platform-specific optional dependency (the published distribution path).
|
|
101
|
+
const resolver = opts.resolver ?? ((req: string) => require.resolve(req));
|
|
102
|
+
try {
|
|
103
|
+
return resolver(platformPackageRequest(opts));
|
|
104
|
+
} catch {
|
|
105
|
+
/* fall through */
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// 3. Package-local fallback: <package>/native/ttsc-native.
|
|
109
|
+
if (opts.localBinaryLookup) {
|
|
110
|
+
const local = opts.localBinaryLookup();
|
|
111
|
+
if (local) return local;
|
|
112
|
+
} else {
|
|
113
|
+
const local = defaultLocalBinaryPath(opts);
|
|
114
|
+
if (local) return local;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Human-readable message shown when no binary can be located. Pure string —
|
|
122
|
+
* the launcher writes it to stderr.
|
|
123
|
+
*/
|
|
124
|
+
export function installHint(opts: ResolveOptions = {}): string {
|
|
125
|
+
const key = platformKey(opts);
|
|
126
|
+
const pkg = `@ttsc/${key}`;
|
|
127
|
+
const supported = SUPPORTED_PLATFORMS.join(", ");
|
|
128
|
+
return [
|
|
129
|
+
`ttsc: platform-specific binary not found (${pkg}).`,
|
|
130
|
+
`Platform: ${opts.platform ?? process.platform}/${opts.arch ?? process.arch}.`,
|
|
131
|
+
``,
|
|
132
|
+
`Resolution order:`,
|
|
133
|
+
` 1. TTSC_BINARY env var (absolute path)`,
|
|
134
|
+
` 2. ${pkg} optional dependency`,
|
|
135
|
+
` 3. ./native/ttsc-native (local workspace build)`,
|
|
136
|
+
``,
|
|
137
|
+
`Try:`,
|
|
138
|
+
` npm install --include=optional ${pkg}`,
|
|
139
|
+
` pnpm install --shamefully-hoist`,
|
|
140
|
+
``,
|
|
141
|
+
`Supported platforms: ${supported}.`,
|
|
142
|
+
`If your platform is not in that list, open an issue at`,
|
|
143
|
+
`https://github.com/samchon/ttsc/issues.`,
|
|
144
|
+
].join("\n");
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function defaultLocalBinaryPath(opts: ResolveOptions): string | null {
|
|
148
|
+
const root = packageRootDir(opts);
|
|
149
|
+
const candidate = path.resolve(
|
|
150
|
+
root,
|
|
151
|
+
"..",
|
|
152
|
+
"native",
|
|
153
|
+
(opts.platform ?? process.platform) === "win32" ? "ttsc-native.exe" : "ttsc-native",
|
|
154
|
+
);
|
|
155
|
+
return fs.existsSync(candidate) ? candidate : null;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function packageRootDir(opts: ResolveOptions = {}): string {
|
|
159
|
+
if (opts.moduleDir) {
|
|
160
|
+
return fs.realpathSync.native?.(opts.moduleDir) ?? fs.realpathSync(opts.moduleDir);
|
|
161
|
+
}
|
|
162
|
+
return fs.realpathSync.native?.(__dirname) ?? fs.realpathSync(__dirname);
|
|
163
|
+
}
|
package/src/plugin.ts
ADDED
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
type NativeRewriteMode,
|
|
6
|
+
type TtscNativeBackend,
|
|
7
|
+
resolveNativeBackend,
|
|
8
|
+
} from "./native";
|
|
9
|
+
import {
|
|
10
|
+
type ParsedProjectConfig,
|
|
11
|
+
type ProjectPluginConfig,
|
|
12
|
+
readProjectConfig,
|
|
13
|
+
} from "./project";
|
|
14
|
+
|
|
15
|
+
export type {
|
|
16
|
+
NativePluginContractVersion,
|
|
17
|
+
NativeRewriteMode,
|
|
18
|
+
TtscNativeBackend,
|
|
19
|
+
} from "./native";
|
|
20
|
+
|
|
21
|
+
export interface TtscPluginFactoryContext {
|
|
22
|
+
binary: string;
|
|
23
|
+
cwd: string;
|
|
24
|
+
projectRoot: string;
|
|
25
|
+
tsconfig: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface TtscTransformContext {
|
|
29
|
+
code: string;
|
|
30
|
+
command: "build" | "transform";
|
|
31
|
+
cwd: string;
|
|
32
|
+
outputFile?: string;
|
|
33
|
+
projectRoot: string;
|
|
34
|
+
sourceFile?: string;
|
|
35
|
+
tsconfig: string;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface TtscPlugin {
|
|
39
|
+
name: string;
|
|
40
|
+
native?: TtscNativeBackend;
|
|
41
|
+
/** @deprecated Use `native.mode` instead. */
|
|
42
|
+
nativeMode?: NativeRewriteMode;
|
|
43
|
+
/** @deprecated Use `native.binary` instead. */
|
|
44
|
+
nativeBinary?: string;
|
|
45
|
+
transformOutput?(context: TtscTransformContext): string;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export type TtscPluginFactory = (
|
|
49
|
+
config: ProjectPluginConfig,
|
|
50
|
+
context: TtscPluginFactoryContext,
|
|
51
|
+
) => TtscPlugin;
|
|
52
|
+
|
|
53
|
+
export type TtscPluginModule = TtscPlugin | TtscPluginFactory;
|
|
54
|
+
|
|
55
|
+
export interface LoadedPlugins {
|
|
56
|
+
compatibilityFallback: boolean;
|
|
57
|
+
nativeBackend: TtscNativeBackend | null;
|
|
58
|
+
nativeBinary: string | null;
|
|
59
|
+
nativeMode: NativeRewriteMode;
|
|
60
|
+
plugins: TtscPlugin[];
|
|
61
|
+
project: ParsedProjectConfig;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export interface LoadPluginsOptions {
|
|
65
|
+
binary: string;
|
|
66
|
+
cwd?: string;
|
|
67
|
+
entries?: readonly ProjectPluginConfig[] | false;
|
|
68
|
+
file?: string;
|
|
69
|
+
tsconfig?: string;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export function definePlugin<T extends TtscPluginModule>(plugin: T): T {
|
|
73
|
+
return plugin;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export function loadProjectPlugins(options: LoadPluginsOptions): LoadedPlugins {
|
|
77
|
+
const project = readProjectConfig({
|
|
78
|
+
cwd: options.cwd,
|
|
79
|
+
file: options.file,
|
|
80
|
+
tsconfig: options.tsconfig,
|
|
81
|
+
});
|
|
82
|
+
const entries =
|
|
83
|
+
options.entries === false
|
|
84
|
+
? []
|
|
85
|
+
: [...(options.entries ?? project.compilerOptions.plugins)].filter(
|
|
86
|
+
(entry) => entry.enabled !== false,
|
|
87
|
+
);
|
|
88
|
+
if (entries.length === 0) {
|
|
89
|
+
return {
|
|
90
|
+
compatibilityFallback: false,
|
|
91
|
+
nativeBackend: null,
|
|
92
|
+
nativeBinary: null,
|
|
93
|
+
nativeMode: "none",
|
|
94
|
+
plugins: [],
|
|
95
|
+
project,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const context: TtscPluginFactoryContext = {
|
|
100
|
+
binary: options.binary,
|
|
101
|
+
cwd: path.resolve(options.cwd ?? process.cwd()),
|
|
102
|
+
projectRoot: project.root,
|
|
103
|
+
tsconfig: project.path,
|
|
104
|
+
};
|
|
105
|
+
const plugins = entries.map((entry) => loadPluginEntry(entry, context));
|
|
106
|
+
|
|
107
|
+
let nativeBinary: string | null = null;
|
|
108
|
+
let nativeBackend: TtscNativeBackend | null = null;
|
|
109
|
+
let nativeMode: NativeRewriteMode = "none";
|
|
110
|
+
for (const plugin of plugins) {
|
|
111
|
+
const backend = resolveNativeBackend(plugin);
|
|
112
|
+
if (!backend) {
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
if (nativeMode !== "none" && nativeMode !== backend.mode) {
|
|
116
|
+
throw new Error(
|
|
117
|
+
`ttsc: multiple native plugin modes requested (${nativeMode}, ${backend.mode})`,
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
nativeMode = backend.mode;
|
|
121
|
+
nativeBackend = backend;
|
|
122
|
+
if (backend.binary) {
|
|
123
|
+
if (nativeBinary !== null && nativeBinary !== backend.binary) {
|
|
124
|
+
throw new Error(
|
|
125
|
+
`ttsc: multiple native plugin binaries requested (${nativeBinary}, ${backend.binary})`,
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
nativeBinary = backend.binary;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return {
|
|
132
|
+
compatibilityFallback: false,
|
|
133
|
+
nativeBackend,
|
|
134
|
+
nativeBinary,
|
|
135
|
+
nativeMode,
|
|
136
|
+
plugins,
|
|
137
|
+
project,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export function applyPluginTransforms(
|
|
142
|
+
plugins: readonly TtscPlugin[],
|
|
143
|
+
context: TtscTransformContext,
|
|
144
|
+
): string {
|
|
145
|
+
let code = context.code;
|
|
146
|
+
for (const plugin of plugins) {
|
|
147
|
+
if (!plugin.transformOutput) {
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
code = plugin.transformOutput({ ...context, code });
|
|
151
|
+
}
|
|
152
|
+
return code;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function loadPluginEntry(
|
|
156
|
+
entry: ProjectPluginConfig,
|
|
157
|
+
context: TtscPluginFactoryContext,
|
|
158
|
+
): TtscPlugin {
|
|
159
|
+
const specifier = entry.transform;
|
|
160
|
+
if (typeof specifier !== "string" || specifier.length === 0) {
|
|
161
|
+
throw new Error(`ttsc: plugin entry is missing a string "transform" field`);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const request = resolvePluginRequest(specifier, context.projectRoot);
|
|
165
|
+
const mod = require(request) as {
|
|
166
|
+
createTtscPlugin?: TtscPluginFactory;
|
|
167
|
+
default?: TtscPluginModule;
|
|
168
|
+
} & Partial<Record<"plugin", TtscPluginModule>>;
|
|
169
|
+
const candidate =
|
|
170
|
+
mod.createTtscPlugin ??
|
|
171
|
+
mod.default ??
|
|
172
|
+
mod.plugin ??
|
|
173
|
+
(mod as unknown as TtscPluginModule);
|
|
174
|
+
if (typeof candidate === "function") {
|
|
175
|
+
return candidate(entry, context);
|
|
176
|
+
}
|
|
177
|
+
if (
|
|
178
|
+
candidate &&
|
|
179
|
+
typeof candidate === "object" &&
|
|
180
|
+
typeof candidate.name === "string"
|
|
181
|
+
) {
|
|
182
|
+
return candidate;
|
|
183
|
+
}
|
|
184
|
+
throw new Error(
|
|
185
|
+
`ttsc: plugin "${specifier}" does not export a valid ttsc plugin`,
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function resolvePluginRequest(specifier: string, projectRoot: string): string {
|
|
190
|
+
if (path.isAbsolute(specifier)) {
|
|
191
|
+
return specifier;
|
|
192
|
+
}
|
|
193
|
+
if (isRelativePluginSpecifier(specifier)) {
|
|
194
|
+
return path.resolve(projectRoot, specifier);
|
|
195
|
+
}
|
|
196
|
+
try {
|
|
197
|
+
return require.resolve(specifier, { paths: [projectRoot] });
|
|
198
|
+
} catch (error) {
|
|
199
|
+
const sourceFallback = resolveSourceCheckoutPlugin(specifier, projectRoot);
|
|
200
|
+
if (sourceFallback) {
|
|
201
|
+
return sourceFallback;
|
|
202
|
+
}
|
|
203
|
+
throw error;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function isRelativePluginSpecifier(specifier: string): boolean {
|
|
208
|
+
return (
|
|
209
|
+
specifier === "." ||
|
|
210
|
+
specifier === ".." ||
|
|
211
|
+
specifier.startsWith("./") ||
|
|
212
|
+
specifier.startsWith("../") ||
|
|
213
|
+
specifier.startsWith(".\\") ||
|
|
214
|
+
specifier.startsWith("..\\")
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
function resolveSourceCheckoutPlugin(
|
|
219
|
+
specifier: string,
|
|
220
|
+
projectRoot: string,
|
|
221
|
+
): string | null {
|
|
222
|
+
const normalized = specifier.replace(/\\/g, "/");
|
|
223
|
+
const match = normalized.match(/^(.*)\/lib\/transform$/);
|
|
224
|
+
if (!match) {
|
|
225
|
+
return null;
|
|
226
|
+
}
|
|
227
|
+
try {
|
|
228
|
+
const packageJson = require.resolve(`${match[1]}/package.json`, {
|
|
229
|
+
paths: [projectRoot],
|
|
230
|
+
});
|
|
231
|
+
const packageRoot = path.dirname(packageJson);
|
|
232
|
+
const candidates = [
|
|
233
|
+
path.join(packageRoot, "lib", "transform.js"),
|
|
234
|
+
path.join(packageRoot, "src", "transform.ts"),
|
|
235
|
+
path.join(packageRoot, "bin", "ttsc-plugin.cjs"),
|
|
236
|
+
];
|
|
237
|
+
return candidates.find((candidate) => fs.existsSync(candidate)) ?? null;
|
|
238
|
+
} catch {
|
|
239
|
+
return null;
|
|
240
|
+
}
|
|
241
|
+
}
|