Skip to content

feat(exe): add initial support for exe format#775

Closed
hyf0 wants to merge 2 commits intomainfrom
hyf_exe_support
Closed

feat(exe): add initial support for exe format#775
hyf0 wants to merge 2 commits intomainfrom
hyf_exe_support

Conversation

@hyf0
Copy link
Member

@hyf0 hyf0 commented Feb 20, 2026

  • This PR contains AI-generated code, but I have carefully reviewed it myself. Otherwise, my PR may be closed.

Description

Add a new exe format that compiles TypeScript into a standalone Node.js Single Executable Application (SEA) using the node --build-sea API.

CLI usage:

# Produces ./index executable (named after entry key)
tsdown ./src/index.ts --format exe

# Custom output name — produces ./hello (or hello.exe on Windows)
tsdown ./src/index.ts --format exe -o hello

Config file:

export default defineConfig({
  entry: ['src/cli.ts'],
  format: 'exe',
  outFile: 'myapp',
  exe: {
    useCodeCache: true,   // default: true
    useSnapshot: false,    // default: false
  },
})

Key behaviors:

  • Requires Node.js >= 25.5.0 (for node --build-sea support)
  • Single entry point only — multiple entries are rejected at config validation time
  • outDir is only used as a staging directory for intermediate JS output and is cleaned up after the build; the final binary is output to the project root (cwd)
  • Output name resolution: --out-file / outFile > first entry key > "app" fallback; .exe extension auto-appended on Windows
  • Several options are force-overridden for exe: dts: false, sourcemap: false, exports: false, publint: false, attw: false, unbundle: false, report: false, and all dependencies are force-bundled
  • Watch mode is disabled (logs a warning and builds once)
  • Code splitting is disabled (codeSplitting: false) — SEA only supports a single script as its entry, so dynamic import() calls must be inlined into the bundle rather than emitted as separate chunks
  • macOS: automatic ad-hoc codesigning via codesign --sign - (warns on failure)
  • CJS legacy warning is suppressed — since exe is internally mapped to cjs for Rolldown, the usual CJS deprecation warning would be misleading
  • formatBytes now auto-scales to MB for large outputs (exe binaries embed the Node.js runtime)
  • Experimental — emits a warning on every build

Linked Issues

Additional context

The exe format is internally normalized to cjs — Rolldown bundles everything into a single CJS file, then node --build-sea produces the final standalone binary as a post-build step.

@netlify
Copy link

netlify bot commented Feb 20, 2026

Deploy Preview for tsdown-main ready!

Name Link
🔨 Latest commit 8e619c2
🔍 Latest deploy log https://app.netlify.com/projects/tsdown-main/deploys/699874e12fe9b30008806039
😎 Deploy Preview https://deploy-preview-775--tsdown-main.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@pkg-pr-new
Copy link

pkg-pr-new bot commented Feb 20, 2026

Open in StackBlitz

tsdown

pnpm add https://pkg.pr.new/tsdown@775 -D
npm i https://pkg.pr.new/tsdown@775 -D
yarn add https://pkg.pr.new/[email protected] -D

create-tsdown

pnpm add https://pkg.pr.new/create-tsdown@775 -D
npm i https://pkg.pr.new/create-tsdown@775 -D
yarn add https://pkg.pr.new/[email protected] -D

tsdown-migrate

pnpm add https://pkg.pr.new/tsdown-migrate@775 -D
npm i https://pkg.pr.new/tsdown-migrate@775 -D
yarn add https://pkg.pr.new/[email protected] -D

commit: 8e619c2

@hyf0 hyf0 marked this pull request as ready for review February 20, 2026 14:51
Copilot AI review requested due to automatic review settings February 20, 2026 14:51
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds support for the exe format, which compiles TypeScript into standalone Node.js Single Executable Applications (SEA) using Node.js >= 25.5.0's --build-sea API. The feature is marked as experimental and emits warnings during builds.

Changes:

  • Adds exe format that internally normalizes to cjs for bundling, then post-processes the output into a standalone executable
  • Implements automatic format-specific overrides (disables DTS, sourcemap, exports checking, etc.) and forces all dependencies to be bundled
  • Includes Node version validation, macOS codesigning, and intelligent output name resolution from --out-file, entry keys, or fallback to "app"

Reviewed changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/features/exe.ts Core SEA build logic including Node version validation, executable generation via node --build-sea, macOS codesigning, and cleanup
src/features/exe.test.ts Unit tests for resolveExeName function covering various edge cases
tests/exe.test.ts E2E tests for exe format including multi-entry validation and executable runtime tests (conditionally run on Node >= 25.5.0)
src/config/types.ts Type definitions adding ExeOptions interface and 'exe' to Format union type
src/config/options.ts Config resolution with exe format validation (single entry check) and SEA-specific overrides
src/build.ts Integration of exe post-processing after rolldown build and watch mode disablement for exe
src/features/rolldown.ts Disables code splitting for exe format (SEA requires single script)
src/features/cjs.ts Suppresses legacy CJS warning for exe format
src/cli.ts Adds --out-file CLI option and updates format help text
src/utils/package.ts Adds normalizeFormat case for exe -> cjs and isExeFormat type guard
src/utils/format.ts Extends formatBytes to auto-scale to MB for values >= 1,000,000 (for large exe binaries)
tests/utils.ts Skips snapshot generation for exe format tests (binaries aren't suitable for snapshots)
.node-version Updates from lts/* to 25.6.1 to support SEA build API
dts.snapshot.json Type snapshot updates reflecting new ExeOptions export

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants