Skip to content

Commit d49ef37

Browse files
committed
feat(exe)!: add exe.outDir for separate executable output dir, defaults to build
1 parent 8869180 commit d49ef37

4 files changed

Lines changed: 36 additions & 7 deletions

File tree

‎dts.snapshot.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@
127127
"DepPlugin": "declare function DepPlugin(_: ResolvedConfig, _: TsdownBundle): Plugin",
128128
"DepsConfig": "interface DepsConfig {\n neverBundle?: ExternalOption\n alwaysBundle?: Arrayable<string | RegExp> | NoExternalFn\n onlyAllowBundle?: Arrayable<string | RegExp> | false\n skipNodeModulesBundle?: boolean\n}",
129129
"DevtoolsOptions": "interface DevtoolsOptions extends NonNullable<InputOptions['devtools']> {\n ui?: boolean | Partial<StartOptions>\n clean?: boolean\n}",
130-
"ExeOptions": "interface ExeOptions extends ExeExtensionOptions {\n seaConfig?: Omit<SeaConfig, 'main' | 'output' | 'mainFormat'>\n fileName?: string | ((_: RolldownChunk) => string)\n}",
130+
"ExeOptions": "interface ExeOptions extends ExeExtensionOptions {\n seaConfig?: Omit<SeaConfig, 'main' | 'output' | 'mainFormat'>\n fileName?: string | ((_: RolldownChunk) => string)\n outDir?: string\n}",
131131
"ExportsOptions": "interface ExportsOptions {\n devExports?: boolean | string\n packageJson?: boolean\n all?: boolean\n exclude?: (RegExp | string)[]\n legacy?: boolean\n customExports?: Record<string, any> | ((_: Record<string, any>, _: { pkg: PackageJson; chunks: ChunksByFormat; isPublish: boolean }) => Awaitable<Record<string, any>>)\n inlinedDependencies?: boolean\n}",
132132
"Format": "type Format = ModuleFormat",
133133
"InlineConfig": "interface InlineConfig extends UserConfig {\n config?: boolean | string\n configLoader?: 'auto' | 'native' | 'unrun'\n filter?: RegExp | Arrayable<string>\n}",

‎src/features/clean.ts‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ export async function cleanOutDir(configs: ResolvedConfig[]): Promise<void> {
1919
config.clean.push('node_modules/.rolldown')
2020
}
2121

22+
if(config.exe){
23+
constexeOutDir=path.resolve(config.cwd,config.exe.outDir||'build')
24+
config.clean.push(exeOutDir)
25+
}
26+
2227
if(!config.clean.length)continue
2328
constfiles=awaitglob(config.clean,{
2429
cwd: config.cwd,

‎src/features/exe.ts‎

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import{mkdtemp,writeFile}from'node:fs/promises'
1+
import{mkdir,mkdtemp,writeFile}from'node:fs/promises'
22
import{tmpdir}from'node:os'
33
importpathfrom'node:path'
44
importprocessfrom'node:process'
@@ -9,7 +9,7 @@ import satisfies from 'semver/functions/satisfies.js'
99
import{x}from'tinyexec'
1010
import{formatBytes}from'../utils/format.ts'
1111
import{fsRemove,fsStat}from'../utils/fs.ts'
12-
import{importWithError}from'../utils/general.ts'
12+
import{importWithError,typeAssert}from'../utils/general.ts'
1313
importtype{ResolvedConfig,RolldownChunk}from'../config/types.ts'
1414
importtype{ExeExtensionOptions,ExeTarget}from'@tsdown/exe'
1515

@@ -20,6 +20,11 @@ export interface ExeOptions extends ExeExtensionOptions {
2020
* For example, do not include `.exe`, platform suffixes, or architecture suffixes.
2121
*/
2222
fileName?: string|((chunk: RolldownChunk)=>string)
23+
/**
24+
* Output directory for executables.
25+
* @default 'build'
26+
*/
27+
outDir?: string
2328
}
2429

2530
/**
@@ -176,8 +181,12 @@ async function buildSingleExe(
176181
executable?: string,
177182
target?: ExeTarget,
178183
): Promise<void>{
179-
constexe=config.exeasExeOptions
180-
constoutputPath=path.join(config.outDir,outputFile)
184+
typeAssert(config.exe)
185+
constexe=config.exe
186+
constexeOutDir=path.resolve(config.cwd,exe.outDir||'build')
187+
188+
awaitmkdir(exeOutDir,{recursive: true})
189+
constoutputPath=path.join(exeOutDir,outputFile)
181190
debug('Building SEA executable: %s -> %s',bundledFile,outputPath)
182191

183192
constt=performance.now()

‎tests/exe.test.ts‎

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,26 @@ describe.runIf(nodeSupportsBuiltinSea)('exe', () => {
3838
snapshot: false,
3939
})
4040

41-
constexePath=path.join(testDir,`dist/index${suffix}`)
41+
constexePath=path.join(testDir,`build/index${suffix}`)
4242
const{ stdout }=awaitx(exePath)
4343
expect(stdout.trim()).toBe('hello from sea')
4444
})
4545

46+
test('exe.outDir outputs executable to custom directory',async(context)=>{
47+
const{ testDir }=awaittestBuild({
48+
context,
49+
files: {
50+
'index.ts': 'console.log("hello from custom outdir")',
51+
},
52+
options: {exe: true},
53+
snapshot: false,
54+
})
55+
56+
constexePath=path.join(testDir,`build/index${suffix}`)
57+
const{ stdout }=awaitx(exePath)
58+
expect(stdout.trim()).toBe('hello from custom outdir')
59+
})
60+
4661
test('bundles dynamic import() and executes correctly',async(context)=>{
4762
const{ testDir }=awaittestBuild({
4863
context,
@@ -64,7 +79,7 @@ describe.runIf(nodeSupportsBuiltinSea)('exe', () => {
6479
snapshot: false,
6580
})
6681

67-
constexePath=path.join(testDir,`dist/index${suffix}`)
82+
constexePath=path.join(testDir,`build/index${suffix}`)
6883
const{ stdout }=awaitx(exePath)
6984
expect(stdout.trim()).toBe('hello from dynamic import')
7085
})

0 commit comments

Comments
 (0)