Skip to content

Commit 159ed8c

Browse files
committed
feat(migrate): add multi dirs support for tsup migration script
Resolves #452
1 parent 5741206 commit 159ed8c

File tree

14 files changed

+259
-17
lines changed

14 files changed

+259
-17
lines changed

docs/guide/migrate-from-tsup.md

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,29 @@ If you're currently using `tsup` and want to migrate to `tsdown`, the process is
1010
npx tsdown-migrate
1111
```
1212

13+
For monorepos, you can specify directories using glob patterns:
14+
15+
```bash
16+
npx tsdown-migrate packages/*
17+
```
18+
19+
Or specify multiple directories explicitly:
20+
21+
```bash
22+
npx tsdown-migrate packages/foo packages/bar
23+
```
24+
1325
> [!WARNING]
1426
> Please save your changes before migration. The migration process may modify your configuration files, so it's important to ensure all your changes are committed or backed up beforehand.
1527
28+
> [!TIP]
29+
> The migration tool will automatically install dependencies after migration. Make sure to run the command from within your project directory.
30+
1631
### Migration Options
1732

1833
The `migrate` command supports the following options to customize the migration process:
1934

20-
- `--cwd <dir>` (or `-c`): Specify the working directory for the migration.
35+
- `[...dirs]`: Specify directories to migrate. Supports glob patterns (e.g., `packages/*`). Defaults to the current directory if not specified.
2136
- `--dry-run` (or `-d`): Perform a dry run to preview the migration without making any changes.
2237

2338
With these options, you can easily tailor the migration process to fit your specific project setup.

packages/migrate/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
"ansis": "catalog:prod",
5252
"cac": "catalog:prod",
5353
"consola": "catalog:migrate",
54-
"diff": "catalog:migrate"
54+
"diff": "catalog:migrate",
55+
"tinyglobby": "catalog:prod"
5556
}
5657
}

packages/migrate/src/cli.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,11 @@ import { migrate, type MigrateOptions } from './index.ts'
77
const cli = cac(pkg.name).version(pkg.version).help()
88

99
cli
10-
.command('', 'Migrate a project to tsdown')
11-
.option(
12-
'-c, --cwd <path>',
13-
'Current working directory to run the migration in',
14-
)
10+
.command('[...dirs]', 'Migrate a project to tsdown')
1511
.option('-d, --dry-run', 'Perform a dry run without making changes')
16-
.action((options: MigrateOptions) => migrate(options))
12+
.action((dirs: string[], options: Omit<MigrateOptions, 'dirs'>) =>
13+
migrate({ ...options, dirs }),
14+
)
1715

1816
export async function runCLI(): Promise<void> {
1917
cli.parse(process.argv, { run: false })

packages/migrate/src/index.ts

Lines changed: 50 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
1+
import path from 'node:path'
12
import process from 'node:process'
23
import { getCliCommand, parseNi, run } from '@antfu/ni'
3-
import { green, underline } from 'ansis'
4+
import { green, greenBright, underline } from 'ansis'
45
import consola from 'consola'
6+
import { glob } from 'tinyglobby'
57
import { migratePackageJson } from './helpers/package-json.ts'
68
import { migrateTsupConfig } from './helpers/tsup-config.ts'
79

810
export interface MigrateOptions {
9-
cwd?: string
11+
dirs?: string[]
1012
dryRun?: boolean
1113
}
1214

13-
export async function migrate({ cwd, dryRun }: MigrateOptions): Promise<void> {
15+
export async function migrate({ dirs, dryRun }: MigrateOptions): Promise<void> {
1416
if (dryRun) {
1517
consola.info('Dry run enabled. No changes were made.')
1618
} else {
@@ -27,13 +29,52 @@ export async function migrate({ cwd, dryRun }: MigrateOptions): Promise<void> {
2729
}
2830
}
2931

30-
if (cwd) process.chdir(cwd)
32+
const baseCwd = process.cwd()
33+
let cwds: string[]
34+
if (!dirs || dirs.length === 0) {
35+
cwds = [baseCwd]
36+
} else {
37+
cwds = await glob(dirs, {
38+
cwd: baseCwd,
39+
onlyDirectories: true,
40+
absolute: true,
41+
expandDirectories: false,
42+
})
43+
if (cwds.length === 0) {
44+
consola.error(`No directories matched: ${dirs.join(', ')}`)
45+
process.exitCode = 1
46+
return
47+
}
48+
}
49+
50+
let migratedAny = false
3151

32-
let migrated = await migratePackageJson(dryRun)
33-
if (await migrateTsupConfig(dryRun)) {
34-
migrated = true
52+
try {
53+
for (const dir of cwds) {
54+
process.chdir(dir)
55+
56+
const relativeDirLabel = greenBright(
57+
path.relative(baseCwd, dir) || 'the current directory',
58+
)
59+
consola.info(`Processing ${relativeDirLabel}`)
60+
61+
let migrated = await migratePackageJson(dryRun)
62+
if (await migrateTsupConfig(dryRun)) {
63+
migrated = true
64+
}
65+
66+
if (!migrated) {
67+
consola.info(`No migrations to apply in ${relativeDirLabel}.`)
68+
continue
69+
}
70+
71+
migratedAny = true
72+
}
73+
} finally {
74+
process.chdir(baseCwd)
3575
}
36-
if (!migrated) {
76+
77+
if (!migratedAny) {
3778
consola.error('No migration performed.')
3879
process.exitCode = 1
3980
return
@@ -44,7 +85,7 @@ export async function migrate({ cwd, dryRun }: MigrateOptions): Promise<void> {
4485
if (dryRun) {
4586
consola.info('[dry-run] would run:', await getCliCommand(parseNi, []))
4687
} else {
47-
await run(parseNi, [], { cwd })
88+
await run(parseNi, [], { cwd: baseCwd })
4889
consola.success('Dependencies installed.')
4990
}
5091
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"name": "standalone-pkg",
3+
"version": "0.0.0",
4+
"type": "module",
5+
"packageManager": "[email protected]",
6+
"scripts": {
7+
"build": "tsup src/index.ts"
8+
},
9+
"dependencies": {
10+
"tsup": "^7.2.0"
11+
}
12+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"name": "issue-452",
3+
"version": "0.0.0",
4+
"private": true,
5+
"scripts": {
6+
"build": "pnpm --filter \"*\" build"
7+
}
8+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"name": "pkg-app",
3+
"version": "1.0.0",
4+
"private": true,
5+
"type": "module",
6+
"main": "./src/index.ts",
7+
"dependencies": {
8+
"pkg2": "workspace:*"
9+
},
10+
"devDependencies": {
11+
"tsup": "catalog:"
12+
},
13+
"scripts": {
14+
"build": "tsup"
15+
}
16+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { add } from 'pkg2'
2+
3+
export const answer: number = add(40, 2)
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { defineConfig } from 'tsup'
2+
3+
export default defineConfig({
4+
entry: ['src/index.ts'],
5+
format: ['esm'],
6+
dts: true,
7+
})
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"name": "pkg2",
3+
"version": "1.0.0",
4+
"private": true,
5+
"type": "module",
6+
"main": "./src/index.ts",
7+
"exports": {
8+
".": "./src/index.ts"
9+
},
10+
"devDependencies": {
11+
"tsup": "catalog:"
12+
},
13+
"scripts": {
14+
"build": "tsup"
15+
},
16+
"tsup": {
17+
"entry": [
18+
"src/index.ts"
19+
]
20+
}
21+
}

0 commit comments

Comments
 (0)