Skip to content

Commit 1394d24

Browse files
ryoppippisxzz
andauthored
feat(tsgo): support custom tsgo binary path (#164)
Co-authored-by: Kevin Deng <sxzz@sxzz.moe>
1 parent 116c5d5 commit 1394d24

File tree

6 files changed

+109
-9
lines changed

6 files changed

+109
-9
lines changed

src/generate.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ export function createGeneratePlugin({
104104

105105
async buildStart(options) {
106106
if (tsgo) {
107-
tsgoDist = await runTsgo(rootDir, tsconfig, sourcemap)
107+
tsgoDist = await runTsgo(rootDir, tsconfig, sourcemap, tsgo.path)
108108
} else if (!oxc) {
109109
// tsc
110110
if (parallel) {

src/options.ts

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,21 +192,42 @@ export interface Options extends GeneralOptions, TscOptions {
192192
/**
193193
* **[Experimental]** Enables DTS generation using `tsgo`.
194194
*
195-
* To use this option, make sure `@typescript/native-preview` is installed as a dependency.
195+
* To use this option, make sure `@typescript/native-preview` is installed as a dependency,
196+
* or provide a custom path to the `tsgo` binary using the `path` option.
196197
*
197198
* **Note:** This option is not yet recommended for production environments.
198199
* `tsconfigRaw` and `isolatedDeclarations` options will be ignored when this option is enabled.
200+
*
201+
*
202+
* ```ts
203+
* // Use tsgo from `@typescript/native-preview` dependency
204+
* tsgo: true
205+
*
206+
* // Use custom tsgo path (e.g., managed by Nix)
207+
* tsgo: { path: '/path/to/tsgo' }
208+
* ```
199209
*/
200-
tsgo?: boolean
210+
tsgo?: boolean | TsgoOptions
211+
}
212+
213+
export interface TsgoOptions {
214+
enabled?: boolean
215+
216+
/**
217+
* Custom path to the `tsgo` binary.
218+
*/
219+
path?: string
201220
}
202221

203222
type Overwrite<T, U> = Pick<T, Exclude<keyof T, keyof U>> & U
223+
204224
export type OptionsResolved = Overwrite<
205225
Required<Omit<Options, 'compilerOptions'>>,
206226
{
207227
tsconfig?: string
208228
oxc: IsolatedDeclarationsOptions | false
209229
tsconfigRaw: TsConfigJson
230+
tsgo: Omit<TsgoOptions, 'enabled'> | false
210231
}
211232
>
212233

@@ -237,6 +258,13 @@ export function resolveOptions({
237258
oxc,
238259
tsgo = false,
239260
}: Options): OptionsResolved {
261+
// Resolve tsgo option
262+
if (tsgo === true) {
263+
tsgo = {}
264+
} else if (typeof tsgo === 'object' && tsgo.enabled === false) {
265+
tsgo = false
266+
}
267+
240268
let resolvedTsconfig: TsConfigJsonResolved | undefined
241269
if (tsconfig === true || tsconfig == null) {
242270
const { config, path } = getTsconfig(cwd) || {}

src/tsgo.ts

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,31 @@ const spawnAsync = (...args: Parameters<typeof spawn>) =>
1313
child.on('error', (error) => reject(error))
1414
})
1515

16+
export async function getTsgoPathFromNodeModules(): Promise<string> {
17+
const tsgoPkg = import.meta.resolve('@typescript/native-preview/package.json')
18+
const { default: getExePath } = await import(
19+
new URL('lib/getExePath.js', tsgoPkg).href
20+
)
21+
return getExePath()
22+
}
23+
1624
export async function runTsgo(
1725
rootDir: string,
1826
tsconfig?: string,
1927
sourcemap?: boolean,
20-
) {
28+
tsgoPath?: string,
29+
): Promise<string> {
2130
debug('[tsgo] rootDir', rootDir)
2231

23-
const tsgoPkg = import.meta.resolve('@typescript/native-preview/package.json')
24-
const { default: getExePath } = await import(
25-
new URL('lib/getExePath.js', tsgoPkg).href
26-
)
27-
const tsgo = getExePath()
32+
let tsgo: string
33+
if (tsgoPath) {
34+
tsgo = tsgoPath
35+
debug('[tsgo] using custom path', tsgo)
36+
} else {
37+
tsgo = await getTsgoPathFromNodeModules()
38+
debug('[tsgo] using tsgo from node_modules', tsgo)
39+
}
40+
2841
const tsgoDist = await mkdtemp(path.join(tmpdir(), 'rolldown-plugin-dts-'))
2942
debug('[tsgo] tsgoDist', tsgoDist)
3043

tests/__snapshots__/index.test.ts.snap

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,44 @@ export { type A };
391391
"
392392
`;
393393
394+
exports[`tsgo with custom path 1`] = `
395+
"// basic.d.ts
396+
//#region tests/fixtures/basic.d.ts
397+
declare const foo: number;
398+
type SomeType<T> = T;
399+
type FooType = string;
400+
interface Interface {}
401+
declare function fn(arg0: SomeType<FooType>, opt: Interface): void;
402+
declare enum Enum {
403+
A = 0,
404+
B = 1,
405+
C = 2,
406+
}
407+
declare class Cls {
408+
foo: string;
409+
fn(e: Enum): void;
410+
}
411+
//#endregion
412+
export { Cls, Enum, fn, foo };
413+
// basic.js
414+
//#region tests/fixtures/basic.ts
415+
const foo = 42;
416+
function fn(arg0, opt) {}
417+
let Enum = /* @__PURE__ */ function(Enum) {
418+
Enum[Enum["A"] = 0] = "A";
419+
Enum[Enum["B"] = 1] = "B";
420+
Enum[Enum["C"] = 2] = "C";
421+
return Enum;
422+
}({});
423+
var Cls = class {
424+
foo;
425+
fn(e) {}
426+
};
427+
428+
//#endregion
429+
export { Cls, Enum, fn, foo };"
430+
`;
431+
394432
exports[`tsx 1`] = `
395433
"// tsx.d.ts
396434
import { JSX } from "solid-js";

tests/fixtures/basic.tsconfig.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"compilerOptions": {
3+
"declaration": true
4+
},
5+
"include": ["basic.ts"]
6+
}

tests/index.test.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { fileURLToPath } from 'node:url'
33
import { rolldownBuild } from '@sxzz/test-utils'
44
import { describe, expect, test } from 'vitest'
55
import { dts } from '../src/index.ts'
6+
import { getTsgoPathFromNodeModules } from '../src/tsgo.ts'
67

78
const dirname = path.dirname(fileURLToPath(import.meta.url))
89

@@ -513,3 +514,17 @@ test('infer false branch', async () => {
513514
'T extends Array<infer U> ? (T extends Array<infer U2> ? U2 : U) : ',
514515
)
515516
})
517+
518+
test('tsgo with custom path', async () => {
519+
const tsgoPath = await getTsgoPathFromNodeModules()
520+
const { snapshot } = await rolldownBuild(
521+
path.resolve(dirname, 'fixtures/basic.ts'),
522+
[
523+
dts({
524+
tsgo: { path: tsgoPath },
525+
tsconfig: path.resolve(dirname, 'fixtures/basic.tsconfig.json'),
526+
}),
527+
],
528+
)
529+
expect(snapshot).toMatchSnapshot()
530+
})

0 commit comments

Comments
 (0)