Skip to content

Commit efba2cc

Browse files
lauigisxzz
andauthored
feat(migrate): add monorepo support (#659)
Co-authored-by: Kevin Deng <sxzz@sxzz.moe>
1 parent 590156f commit efba2cc

File tree

15 files changed

+280
-28
lines changed

15 files changed

+280
-28
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.

docs/zh-CN/guide/migrate-from-tsup.md

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,41 @@
11
# 从 tsup 迁移
22

3-
[tsup](https://tsup.egoist.dev/) 是一个功能强大且广泛使用的打包器,与 `tsdown` 有许多相似之处。`tsup` 基于 [esbuild](https://esbuild.github.io/) 构建,`tsdown` 则利用了 [Rolldown](https://rolldown.rs/) 的强大能力,带来更**快速**、更**强大**的打包体验。
3+
[tsup](https://tsup.egoist.dev/) 是一个功能强大且广泛使用的打包器,与 `tsdown` 有许多相似之处。虽然 `tsup` 基于 [esbuild](https://esbuild.github.io/) 构建,`tsdown` 则利用了 [Rolldown](https://rolldown.rs/) 的强大能力,带来更**快速**、更**强大**的打包体验。
44

55
## 迁移指南
66

7-
如果您当前正在使用 `tsup` 并希望迁移到 `tsdown`,迁移过程非常简单,因为 `tsdown` 提供了专门的 `migrate` 命令:
7+
如果您当前正在使用 `tsup` 并希望迁移到 `tsdown`,迁移过程非常简单,只需使用专门的 `migrate` 命令:
88

99
```bash
1010
npx tsdown-migrate
1111
```
1212

13+
对于 monorepo 项目,您可以通过通配符模式指定目录:
14+
15+
```bash
16+
npx tsdown-migrate packages/*
17+
```
18+
19+
或者显式指定多个目录:
20+
21+
```bash
22+
npx tsdown-migrate packages/foo packages/bar
23+
```
24+
1325
> [!WARNING]
1426
> 在迁移之前,请保存您的更改。迁移过程可能会修改您的配置文件,因此请确保所有更改已提交或备份。
1527
28+
> [!TIP]
29+
> 迁移工具会在迁移后自动安装依赖。请确保在项目目录下运行该命令。
30+
1631
### 迁移选项
1732

1833
`migrate` 命令支持以下选项,用于自定义迁移过程:
1934

20-
- `--cwd <dir>`(或 `-c`):指定迁移的工作目录
35+
- `[...dirs]`:指定要迁移的目录。支持通配符模式(如 `packages/*`)。如果未指定,默认为当前目录
2136
- `--dry-run`(或 `-d`):执行预览迁移(dry run),不会进行任何实际更改。
2237

23-
通过这些选项,您可以轻松调整迁移过程以适应您的特定项目设置
38+
通过这些选项,您可以轻松调整迁移过程以适应您的特定项目结构
2439

2540
## 与 tsup 的区别
2641

@@ -31,22 +46,22 @@ npx tsdown-migrate
3146
- **`format`**:默认值为 `esm`
3247
- **`clean`**:默认启用,每次构建前会清理 `outDir`
3348
- **`dts`**:如果您的 `package.json` 中包含 `typings``types` 字段,则会自动启用。
34-
- **`target`**默认情况下,如果 `package.json` 中存在 `engines.node` 字段,则会读取该字段的值
49+
- **`target`**默认会读取 `package.json` 中的 `engines.node` 字段(如有)
3550

3651
### 功能差距
3752

38-
`tsdown` 尚未实现 `tsup` 中的某些功能。如果您发现缺少某些您需要的选项,请 [提交问题](https://github.com/rolldown/tsdown/issues) 告诉我们您的需求。
53+
`tsdown` 尚未实现 `tsup` 中的某些功能。如果您发现缺少某些您需要的选项,请[提交 issue](https://github.com/rolldown/tsdown/issues) 告诉我们您的需求。
3954

40-
### tsdown 的新功能
55+
### tsdown 新增特性
4156

42-
`tsdown` 还引入了一些 `tsup` 中没有的新功能
57+
`tsdown` 还引入了一些 `tsup` 不具备的新特性
4358

4459
- **`nodeProtocol`**:控制 Node.js 内置模块导入的处理方式:
45-
- `true`:为内置模块添加 `node:` 前缀(例如,`fs``node:fs`
46-
- `'strip'`从导入中移除 `node:` 前缀(例如,`node:fs``fs`
60+
- `true`:为内置模块添加 `node:` 前缀(`fs``node:fs`
61+
- `'strip'`移除导入中的 `node:` 前缀(`node:fs``fs`
4762
- `false`:保持导入不变(默认)
4863

49-
迁移后,请仔细检查您的配置以确保其符合您的预期
64+
迁移后,请仔细检查您的配置,确保其符合您的预期
5065

5166
## 致谢
5267

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: 47 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
import process from 'node:process'
22
import { getCliCommand, parseNi, run } from '@antfu/ni'
3-
import { green, underline } from 'ansis'
3+
import { green, greenBright, underline } from 'ansis'
44
import consola from 'consola'
5+
import { glob } from 'tinyglobby'
56
import { migratePackageJson } from './helpers/package-json.ts'
67
import { migrateTsupConfig } from './helpers/tsup-config.ts'
78

89
export interface MigrateOptions {
9-
cwd?: string
10+
dirs?: string[]
1011
dryRun?: boolean
1112
}
1213

13-
export async function migrate({ cwd, dryRun }: MigrateOptions): Promise<void> {
14+
export async function migrate({ dirs, dryRun }: MigrateOptions): Promise<void> {
1415
if (dryRun) {
1516
consola.info('Dry run enabled. No changes were made.')
1617
} else {
@@ -27,13 +28,50 @@ export async function migrate({ cwd, dryRun }: MigrateOptions): Promise<void> {
2728
}
2829
}
2930

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

32-
let migrated = await migratePackageJson(dryRun)
33-
if (await migrateTsupConfig(dryRun)) {
34-
migrated = true
51+
try {
52+
for (const dir of cwds) {
53+
process.chdir(dir)
54+
55+
const dirLabel = greenBright(dir)
56+
consola.info(`Processing ${dirLabel}`)
57+
58+
let migrated = await migratePackageJson(dryRun)
59+
if (await migrateTsupConfig(dryRun)) {
60+
migrated = true
61+
}
62+
63+
if (!migrated) {
64+
consola.warn(`No migrations to apply in ${dirLabel}.`)
65+
continue
66+
}
67+
68+
migratedAny = true
69+
}
70+
} finally {
71+
process.chdir(baseCwd)
3572
}
36-
if (!migrated) {
73+
74+
if (!migratedAny) {
3775
consola.error('No migration performed.')
3876
process.exitCode = 1
3977
return
@@ -44,7 +82,7 @@ export async function migrate({ cwd, dryRun }: MigrateOptions): Promise<void> {
4482
if (dryRun) {
4583
consola.info('[dry-run] would run:', await getCliCommand(parseNi, []))
4684
} else {
47-
await run(parseNi, [], { cwd })
85+
await run(parseNi, [], { cwd: baseCwd })
4886
consola.success('Dependencies installed.')
4987
}
5088
}
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": "pnpm@10.26.0",
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+
})

0 commit comments

Comments
 (0)