Agent Role: You are tasked with migrating any TypeScript library from its current build system to the high-performance Void Zero toolchain. Follow these instructions systematically.
Transform any TypeScript library (regardless of current setup) to use:
- TSDown for both JavaScript bundling AND TypeScript declarations (primary approach)
- Oxlint for linting (optional, can keep existing)
- Vitest for testing (optional, can keep existing)
- Rolldown as advanced fallback for complex bundling needs (optional)
- Vite as legacy fallback build option (optional)
Expected Performance: 5-10x faster builds (guaranteed), 100x faster linting (if migrating to Oxlint), framework-compatible output.
Key Insight: For TypeScript libraries, TSDown can handle both bundling and declarations in one tool, eliminating the need for separate bundler configurations!
Agent Instructions: First analyze the project structure to infer answers, then confirm with the user:
Agent Task: Analyze the project before asking questions. Infer these automatically:
# Detect entry points
find . -name "index.ts" -o -name "index.js" | head -5
ls -la src/ lib/ 2>/dev/null || echo "No src/lib found"
# Detect source structure
[ -d "src" ] && echo "Source: src/" || [ -d "lib" ] && echo "Source: lib/" || echo "Source: root level"
# Detect current tools
grep -E "(webpack|rollup|esbuild|jest|eslint|babel)" package.json | head -10
# Detect framework
grep -E "(react|vue|svelte)" package.json | head -5
# Detect test files
find . -name "*.test.*" -o -name "*.spec.*" | head -3
# Check for multiple exports
grep -E "(exports|main|module)" package.json
Format: "I detected [INFERENCE], is this correct? If not, please clarify:"
-
Entry Point: "I found these potential entry points:
[detected files]
. Main entry appears to be[best guess]
- correct?" -
Source Directory: "Source code appears to be in
[detected directory]
- is this right?" -
Current Tools: "I detected you're using
[found tools]
for building/testing/linting - accurate?" -
Framework Type: "Based on dependencies, this appears to be a
[React/Vue/vanilla/other]
library - correct?" -
Multiple Exports: "Package.json suggests
[single/multiple]
export structure - is this right?"
-
External Dependencies: "Should these dependencies stay external (not bundled)?
[list from peerDependencies + common libs]
" -
Migration Scope: "Do you want to migrate just the build system, or also linting/testing to Void Zero tools?"
-
Output Formats: "I see you currently output
[detected formats]
- keep both ESM and CJS?" -
Special Build Steps: "I noticed
[custom scripts/configs]
- any special build requirements I should preserve?" -
Breaking Changes: "This migration may change your build scripts - are you okay with that?"
Agent Decision Matrix Based on Analysis + Answers:
- Always migrate: TSDown (build + types) - single tool for everything!
- Auto-configure: Entry points (Q1), source paths (Q2), externals (Q6), output formats (Q8)
- Conditionally migrate: Oxlint (based on Q7), Vitest (based on Q7)
- Advanced needs only: Rolldown (complex bundling), Vite (legacy fallback)
- Preserve existing: Custom build steps (Q9), existing tools (if user prefers in Q7)
Task: Examine the existing project structure and identify what needs to be replaced (this should build on your STEP 0 auto-analysis).
Actions:
-
Verify auto-analysis findings with the user using smart questions above
-
Document current setup based on analysis + user confirmation:
- Entry point:
[confirmed path]
- Source directory:
[confirmed directory]
- Current bundler:
[detected tool]
- Current linter:
[detected tool or none]
- Current test framework:
[detected tool or none]
- Framework type:
[React/Vue/vanilla/other]
- External dependencies:
[from peerDependencies + user input]
- Entry point:
-
Plan replacement strategy:
webpack.config.js
β Replace with Rolldownrollup.config.js
β Replace with Rolldownesbuild.config.js
β Replace with Rolldown.eslintrc.*
β Replace with Oxlint (if user agrees)jest.config.*
β Replace with Vitest (if user agrees)babel.config.*
β Remove (Rolldown handles transpilation)- Multiple
tsconfig.*.json
β Simplify to one - Build scripts in
/scripts/
β Replace with simple npm scripts
Expected Output: Clear migration plan based on actual project structure rather than assumptions.
Task: Replace old dependencies with Void Zero ecosystem (install only what you need).
Actions:
- Remove old dependencies (only uninstall what exists in the current project):
# Check package.json first, then remove only existing bundlers
npm uninstall -D webpack webpack-cli webpack-dev-server || true
npm uninstall -D rollup @rollup/plugin-* || true
npm uninstall -D esbuild || true
npm uninstall -D parcel || true
# Remove existing linters only if found
npm uninstall -D eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin || true
npm uninstall -D eslint-plugin-* || true
# Remove existing test runners only if found
npm uninstall -D jest @types/jest ts-jest || true
npm uninstall -D mocha @types/mocha || true
# Remove transpilation tools only if found
npm uninstall -D babel-core @babel/core @babel/preset-* || true
npm uninstall -D swc @swc/core || true
- Install Void Zero tools (TSDown-first approach):
# Core essentials (always install - TSDown handles both JS and types!)
npm install -D tsdown@^0.14.1
npm install -D typescript@^5.8.3
# Choose linting approach:
npm install -D oxlint@^1.11.2 # OR keep existing ESLint setup
# Choose testing approach:
npm install -D vitest@^3.2.4 # OR keep existing test framework
# Advanced bundling (only if TSDown isn't sufficient):
npm install -D rolldown@^1.0.0-beta.32
# Legacy fallback build (install if complex build needs):
npm install -D vite@^6.0.0 vite-plugin-dts@^4.3.0
# Utilities (install if needed):
npm install -D rimraf@^6.0.1 @types/node@^24.0.10
Task: Create the essential configuration (TSDown-first approach for libraries).
Action 3A: Create tsdown.config.js
(Primary build - handles both JS and types!)
// TSDown can handle both bundling and declarations for libraries
export default {
entry: "src/index.ts", // Adjust based on your project structure
outDir: "dist",
format: ["esm", "cjs"], // Outputs both ES modules and CommonJS
dts: true, // Generate TypeScript declarations
sourcemap: true,
external: [], // Add external dependencies here (will be updated in Step 8)
clean: true,
};
Action 3B: Create rolldown.config.js
(Only if you need advanced bundling features)
// Only create this if TSDown doesn't meet your complex bundling needs
export default {
input: "src/index.ts", // Common alternatives: "lib/index.ts", "index.ts"
output: [
{
file: "dist/esm/index.js",
format: "esm",
sourcemap: true,
},
{
file: "dist/cjs/index.cjs",
format: "cjs",
sourcemap: true,
},
],
external: [], // Add external dependencies here
};
Action 3C: Create oxlint.json
(only if migrating from ESLint)
{
"rules": {}
}
Action 3D: Create vite.config.ts
(only if you need legacy fallback build)
import { defineConfig } from "vite";
import dts from "vite-plugin-dts";
export default defineConfig({
plugins: [
dts({
outDir: "dist/types",
include: ["src/**/*"], // Adjust path if needed: ["lib/**/*"], etc.
exclude: ["**/*.test.ts", "**/*.spec.ts"],
}),
],
build: {
lib: {
entry: "src/index.ts", // Adjust to match your entry point
formats: ["es", "cjs"],
fileName: (format) =>
format === "es" ? "esm/index.js" : "cjs/index.cjs",
},
minify: false, // Libraries should not be minified
target: "esnext",
rollupOptions: {
output: {
compact: false, // Clean output for frameworks
},
},
},
});
Task: Simplify TypeScript setup to one modern config.
Actions:
- Remove old tsconfig files:
tsconfig.*.json
(except main one) - Replace
tsconfig.json
content with:
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "bundler",
"declaration": true,
"declarationMap": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"isolatedModules": true,
"noEmit": true
},
"include": ["src/**/*", "vite.config.ts"],
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.spec.ts"]
}
Task: Update package.json to use Void Zero toolchain.
Action 5A: Replace scripts section (TSDown-first approach):
{
"scripts": {
"clean": "rimraf dist", // OR "rm -rf dist" if rimraf not installed
"build": "tsdown", // Single command builds both JS and types!
"build:rolldown": "rolldown -c rolldown.config.js", // Only if using Rolldown
"build:vite": "npm run clean && vite build", // Legacy fallback
"lint": "oxlint", // OR keep your existing linter: "eslint src"
"lint:fix": "oxlint --fix", // OR "eslint src --fix"
"test": "vitest run", // OR keep existing: "jest", "mocha", etc.
"test:watch": "vitest", // OR existing watch command
"prepublishOnly": "npm run build"
}
}
Action 5B: Update/add package configuration fields (TSDown output structure):
{
"type": "module",
"main": "./dist/index.cjs", // TSDown output structure
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"sideEffects": false,
"exports": {
".": {
"import": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
},
"require": {
"types": "./dist/index.d.ts",
"default": "./dist/index.cjs"
}
}
},
"files": ["dist"]
}
Task: Migrate tests to Vitest (optional - you can keep existing test setup).
Actions (only if migrating to Vitest):
- Find test files: Look for
*.test.*
,*.spec.*
,/test/
,/__tests__/
- Update imports (if migrating from Jest):
- Change
import { describe, it, expect } from 'jest'
- To
import { describe, it, expect } from 'vitest'
- Change
- Remove old test configs:
jest.config.*
,.mocharc.*
(if migrating) - Create
vitest.config.ts
only if you have complex testing needs:
import { defineConfig } from "vitest/config";
export default defineConfig({
test: {
globals: true,
environment: "node", // or "jsdom" for browser-like tests
},
});
Note: You can keep your existing test setup (Jest, Mocha, etc.) and only migrate the build system.
Task: Remove obsolete configuration and build files (only remove what exists).
Actions - Check and remove these files if they exist:
# Remove old bundler configs (check first)
[ -f webpack.config.js ] && rm webpack.config.js
[ -f rollup.config.js ] && rm rollup.config.js
[ -f esbuild.config.js ] && rm esbuild.config.js
[ -f parcel.config.js ] && rm parcel.config.js
# Remove old linter configs (only if migrating to Oxlint)
[ -f .eslintrc.js ] && rm .eslintrc.js
[ -f .eslintrc.json ] && rm .eslintrc.json
[ -f .eslintrc.yml ] && rm .eslintrc.yml
# Remove old test configs (only if migrating to Vitest)
[ -f jest.config.js ] && rm jest.config.js
[ -f jest.config.json ] && rm jest.config.json
[ -f .mocharc.json ] && rm .mocharc.json
# Remove transpilation configs (check first)
[ -f babel.config.js ] && rm babel.config.js
[ -f .babelrc ] && rm .babelrc
[ -f .swcrc ] && rm .swcrc
# Remove multiple tsconfig files (keep main tsconfig.json)
[ -f tsconfig.cjs.json ] && rm tsconfig.cjs.json
[ -f tsconfig.esm.json ] && rm tsconfig.esm.json
[ -f tsconfig.types.json ] && rm tsconfig.types.json
# Remove build scripts directory (only if it contains build scripts)
[ -d scripts ] && [ "$(ls -A scripts)" ] && echo "Check scripts/ directory manually"
# Remove old package files
rm -f *.tgz
Task: Configure external dependencies for the bundler.
Actions:
- Read
package.json
dependencies
andpeerDependencies
- Add them to
rolldown.config.js
external array:
external: ["react", "react-dom", "lodash"]; // Example
- Rule: Never bundle dependencies that consumers should provide
Task: Verify everything works correctly.
Actions:
# Test build (core requirement)
npm run build
# Test linting (if migrated to Oxlint)
npm run lint
# Test tests (with existing or new test framework)
npm test
# Create test package
npm pack
Expected Results:
- Build completes in <1 second (major improvement)
- Single
tsdown
command handles everything! - Linting completes in <50ms (if using Oxlint)
- All tests pass (with existing or migrated test framework)
- Package creates successfully
- Output structure (TSDown approach):
dist/
βββ index.js (ESM)
βββ index.cjs (CommonJS)
βββ index.d.ts (TypeScript declarations)
βββ *.map files (sourcemaps)
Task: Ensure the package works across different frameworks.
Actions:
- Check that
dist/
contains both.d.ts
AND.js/.cjs
files - Verify package.json has proper
exports
field - Test import in a simple test file:
// Test ESM
import { yourFunction } from "./package-name";
// Test CJS
const { yourFunction } = require("./package-name");
// Test CJS const { yourFunction } = require("./package-name");
## π¨ Common Edge Cases to Handle
### Multiple Entry Points
If the library has multiple exports, update configs:
```javascript
// rolldown.config.js
export default [
{ input: 'src/index.ts', output: [...] },
{ input: 'src/utils.ts', output: [...] }
]
Add JSX/Vue support:
// rolldown.config.js
export default {
// ... other config
plugins: [
// Add react() or vue() plugin if needed
],
};
If src files are not in /src/
, adjust all config file paths accordingly.
Apply this migration to each package individually, not at the root level.
The migration is complete when:
- β Build time reduced by 5-10x (core requirement)
- β TSDown successfully handles both bundling AND declarations (primary goal)
- β Package exports both ESM and CJS
- β
Single
npm run build
command works - β No old bundler tools remain
- β All tests pass (regardless of test framework)
- β Package size optimized
- β Framework compatibility verified
Optional completions (depending on what you migrated):
- β Linting time reduced by 100x (if migrated to Oxlint)
- β Test performance improved (if migrated to Vitest)
- β Rolldown available for advanced bundling needs (if installed)
Agent Reference: Use the auto-detected information + user confirmations to customize the migration:
// tsdown.config.js - use confirmed paths (primary approach)
export default {
entry: "[detected/confirmed entry point]", // e.g., "src/index.ts"
outDir: "dist",
format: ["esm", "cjs"],
dts: true,
// For multiple exports (detected in analysis), specify multiple entries
// entry: ["src/index.ts", "src/utils.ts"]
};
// rolldown.config.js - only if TSDown isn't sufficient
export default {
input: "[detected/confirmed entry point]", // e.g., "src/index.ts"
// For multiple exports (detected in analysis), create array of configs
// input: ["src/index.ts", "src/utils.ts"]
};
// If React/Vue library detected, add to tsdown.config.js:
export default {
entry: "src/index.ts",
outDir: "dist",
format: ["esm", "cjs"],
dts: true,
esbuildOptions: {
jsx: "automatic", // For React
// or configure for Vue/Svelte
},
};
// OR for complex cases, use rolldown.config.js:
import react from "@rolldown/plugin-react";
import vue from "@rolldown/plugin-vue";
export default {
plugins: [react()], // Add appropriate plugin based on detection
// ...
};
// tsdown.config.js - use detected peerDependencies + user confirmation
export default {
entry: "src/index.ts",
outDir: "dist",
format: ["esm", "cjs"],
dts: true,
external: ["react", "react-dom", "vue"], // From peerDeps + user input
};
// package.json scripts - TSDown-first approach
{
"scripts": {
"build": "tsdown", // Primary: single command for everything!
"build:rolldown": "rolldown -c", // Only if using Rolldown for complex needs
"lint": "oxlint", // If user chose to migrate linting
"test": "vitest run" // If user chose to migrate testing
// Otherwise keep existing: "eslint src", "jest", etc.
}
}
Every migrated library should have (TSDown-first approach):
βββ src/ # Source code (unchanged location may vary)
βββ dist/ # Generated by TSDown
β βββ index.js # ES modules
β βββ index.cjs # CommonJS
β βββ index.d.ts # TypeScript declarations
β βββ *.map # Sourcemaps
βββ package.json # Updated configuration
βββ tsconfig.json # Simplified TypeScript config
βββ tsdown.config.js # Primary build config (TSDown)
βββ rolldown.config.js # Advanced build config (optional)
βββ vite.config.ts # Legacy fallback build config (optional)
βββ oxlint.json # Linting config (optional)
βββ README.md # Updated documentation
Agent Note: This migration should work for ANY TypeScript library regardless of its current setup. The key principle is:
- Always install: TSDown + TypeScript (TSDown handles both bundling AND declarations!)
- Optionally install: Oxlint (linting), Vitest (testing), Rolldown (complex bundling), Vite (legacy fallback)
- Adapt paths: Check actual entry points (src/, lib/, index.ts, etc.)
- Preserve choices: Keep existing test/lint setups if preferred
- Remove safely: Only delete files that actually exist
Focus on the TSDown-first transformation for libraries - it's simpler and handles both JS bundling and TypeScript declarations in one tool!