npm package: @iswangh/script
Description: 工具脚本集合，提供依赖更新等开发工具
Author: iswangh
Latest version: 0.0.2

# @iswangh/script

工具脚本集合，提供依赖更新等开发工具。

## 项目介绍

`@iswangh/script` 是一个工具脚本集合 npm 包，提供多个实用的开发工具脚本，包括依赖更新、Git 分支检查等功能。该包既可作为 CLI 工具直接使用，也可作为库被其他脚本导入使用。

### 核心功能

- **多脚本支持**：支持多个独立的脚本工具
- **CLI 接口**：提供命令行工具，可直接使用
- **编程接口**：可作为库被其他脚本导入使用
- **配置灵活**：支持配置文件、环境变量、命令行参数
- **多包管理器支持**：支持 bun、npm、pnpm、yarn、deno

### 与 @antfu/ni 的关系

`@iswangh/script` 的 `update-deps` 命令默认行为与 `@antfu/ni` 的 `nup` 命令一致（遵循版本范围限制），但提供了更丰富的功能：

- **`nup`**：简单快速的依赖更新，遵循版本范围限制，适合日常使用
- **`update-deps`**：默认行为与 `nup` 一致，但提供更细粒度的控制，包括：
  - **默认遵循版本范围限制**（类似 `nup` 的行为）
  - **支持多种更新策略**（通过 `--strategy` 选项）：
    - `range`：遵循版本范围限制（默认）
    - `latest`：更新到绝对最新版本
    - `patch-only`：只更新补丁版本（最保守）
    - `minor-only`：只更新次要版本和补丁版本（中等保守）
  - 批量更新控制（避免一次性更新过多包导致的问题）
  - 排除特定包（exclude）
  - 只更新 dependencies 或 devDependencies
  - 预览模式（dry-run）
  - 详细的版本变化报告和错误追踪
  - 支持配置文件统一管理

两者可以配合使用：日常快速更新使用 `nup`，需要精细控制时使用 `update-deps`。

### 应用场景

- 需要批量更新项目依赖的场景
- 需要在发布前检查 Git 分支的场景
- 需要自动化开发工具脚本的场景

## 技术栈

### 运行时依赖

- **commander**: `^12.1.0` - CLI 命令行工具
- **js-yaml**: `^4.1.1` - YAML 配置文件解析库

### 开发依赖

- **TypeScript**: `^5.9.3` - TypeScript 编译器
- **tsup**: `^8.5.1` - 基于 esbuild 的 TypeScript 构建工具
- **@iswangh/eslint-config**: `^0.1.7` - ESLint 配置
- **@iswangh/commitlint-config**: `^0.1.3` - Commitlint 配置
- **tsx**: `^4.19.2` - TypeScript 执行器

## 目录结构

```
@iswangh/script/
├── bin/
│   └── script.js                    # CLI 统一入口
├── src/
│   ├── index.ts                     # 库入口（导出所有功能）
│   ├── cli.ts                       # CLI 主入口
│   ├── commands/                    # 命令模块
│   │   ├── update-deps/             # update-deps 命令
│   │   │   ├── index.ts             # 命令入口
│   │   │   ├── config.ts            # 配置管理
│   │   │   ├── types.ts             # 类型定义
│   │   │   └── updater/             # 更新逻辑
│   │   │       ├── index.ts         # 聚合导出
│   │   │       ├── updater.ts       # 主更新逻辑
│   │   │       ├── batch.ts         # 批量更新逻辑
│   │   │       └── version.ts       # 版本对比逻辑
│   │   ├── check-branch/            # check-branch 命令
│   │   │   ├── index.ts             # 命令入口
│   │   │   ├── types.ts             # 类型定义
│   │   │   └── checker.ts           # 检查逻辑（包含 Git 操作）
│   │   └── index.ts                 # 命令导出
│   ├── core/                        # 核心功能
│   │   ├── index.ts                 # 聚合导出
│   │   ├── logger/                  # 日志工具
│   │   │   ├── index.ts             # 聚合导出
│   │   │   └── logger.ts            # 日志实现
│   │   ├── package-manager/         # 包管理器检测
│   │   │   ├── index.ts             # 聚合导出
│   │   │   ├── detector.ts          # 检测逻辑
│   │   │   └── types.ts             # 类型定义
│   │   └── config-loader/           # 配置加载器
│   │       ├── index.ts             # 聚合导出
│   │       ├── loader.ts            # 配置加载逻辑
│   │       ├── file-loader.ts       # 文件配置加载
│   │       ├── env-loader.ts        # 环境变量加载
│   │       └── types.ts             # 类型定义
│   └── utils/                       # 工具函数
│       ├── index.ts                 # 聚合导出
│       ├── cli.ts                   # CLI 工具实现
│       └── fs.ts                    # 文件系统工具实现
├── tsconfig.json                     # TypeScript 配置（Project References）
├── tsconfig.app.json                 # 应用代码配置
├── tsconfig.node.json                # Node.js 工具配置
├── package.json
└── README.md
```

## 快速开始

### 环境要求

- Node.js >= 20.19.0 或 >= 22.12.0
- 支持 ESM 的包管理器（pnpm、npm、yarn、bun）

### 安装

推荐使用 `ni`（需要全局安装 `@antfu/ni`）：

```bash
ni -g @iswangh/script
```

或使用其他包管理器：

```bash
# pnpm
pnpm add -g @iswangh/script

# npm
npm install -g @iswangh/script

# yarn
yarn global add @iswangh/script
```

### CLI 使用

#### update-deps 命令（别名：ud）

更新项目依赖到最新版本。

**更新策略**：
- **`range`**（默认）：遵循版本范围限制，只更新到符合 `package.json` 中版本范围限制的最新版本（类似 `nup` 的行为）
  - 例如：`"vue": "^3.0.0"` → 更新到 `^3.5.0`（仍在 `^3.0.0` 范围内），不会更新到 `^4.0.0`
- **`latest`**：更新到绝对最新版本（忽略版本范围限制）
  - 例如：`"vue": "^3.0.0"` → 更新到 `^4.0.0`（可能包含破坏性变更）
- **`patch-only`**：只更新补丁版本（最保守，只更新 PATCH，不更新 MINOR 和 MAJOR）
  - 例如：`"vue": "^3.0.0"` → 更新到 `~3.0.5`（只允许 `3.0.x`）
- **`minor-only`**：只更新次要版本和补丁版本（中等保守，更新 MINOR 和 PATCH，不更新 MAJOR）
  - 例如：`"vue": "^3.0.0"` → 更新到 `^3.5.0`（允许 `3.x.x`，但不允许 `4.x.x`）

**与 `nup` 的区别**：
- `nup`（来自 `@antfu/ni`）：简单快速，适合日常快速更新所有依赖
- `update-deps`：提供更细粒度的控制，适合需要精确控制更新过程的场景

**使用示例**：

```bash
# 基本使用（遵循版本范围限制，类似 nup，默认策略）
ws update-deps
# 或
ws ud

# 更新到绝对最新版本（忽略版本范围限制）
ws ud --strategy latest
# 或
ws ud -s latest

# 只更新补丁版本（最保守）
ws ud --strategy patch-only
# 或
ws ud -s patch-only

# 只更新次要版本和补丁版本（中等保守）
ws ud --strategy minor-only
# 或
ws ud -s minor-only

# 排除指定包
ws ud --exclude vue,typescript
# 或
ws ud -e vue,typescript

# 指定批量更新大小
ws ud --batch-size 20
# 或
ws ud -b 20

# 只更新 dependencies
ws ud --only dependencies
# 或
ws ud -o dependencies

# 预览模式（不实际更新）
ws ud --dry-run
# 或
ws ud -d

# 详细输出
ws ud --verbose
# 或
ws ud -v

# 组合使用多个选项
ws ud -e vue,typescript -b 15 -d -v

# 更新到绝对最新版本并排除指定包
ws ud --strategy latest -e vue,typescript

# 只更新补丁版本并排除指定包
ws ud --strategy patch-only -e vue,typescript
```

#### check-branch 命令（别名：cb）

检查当前 Git 分支是否允许发布：

```bash
# 基本使用（完整命令名，默认允许 main、master）
ws check-branch

# 使用简化别名（推荐）
ws cb

# 自定义允许的分支
ws cb --allowed-branches main,develop
# 或
ws cb -a main,develop
```

#### 使用 npx（无需安装）

无需全局安装，直接使用 `npx` 运行：

```bash
# 使用 update-deps 命令（完整名或别名）
npx @iswangh/script update-deps
npx @iswangh/script ud

# 使用 check-branch 命令（完整名或别名）
npx @iswangh/script check-branch
npx @iswangh/script cb

# 带参数使用
npx @iswangh/script ud --strategy latest -e vue,typescript
npx @iswangh/script cb -a main,develop
```

**注意**：首次使用 `npx` 时会自动下载包，可能需要一些时间。

#### 常见使用场景

**场景 1：日常依赖更新（推荐）**

使用默认策略（遵循版本范围限制，类似 `nup`），安全且快速：

```bash
# 基本更新
ws ud

# 排除特定包（如 Vue、TypeScript 等核心依赖）
ws ud -e vue,typescript

# 预览模式，先查看会更新哪些包
ws ud -d -v
```

**场景 2：更新到绝对最新版本**

需要获取所有依赖的最新版本（可能包含破坏性变更）：

```bash
# 更新到绝对最新版本
ws ud --strategy latest

# 更新到最新版本并排除特定包
ws ud --strategy latest -e vue,typescript
```

**场景 3：保守更新（只更新补丁版本）**

只更新补丁版本，避免引入破坏性变更：

```bash
# 只更新补丁版本
ws ud --strategy patch-only

# 只更新补丁版本并排除特定包
ws ud --strategy patch-only -e vue,typescript
```

**场景 4：中等保守更新（更新次要版本和补丁版本）**

更新次要版本和补丁版本，但不更新主版本：

```bash
# 更新次要版本和补丁版本
ws ud --strategy minor-only

# 更新次要版本和补丁版本并排除特定包
ws ud --strategy minor-only -e vue,typescript
```

**场景 5：发布前检查**

在发布前检查分支和更新依赖：

```bash
# 检查分支（默认允许 main、master）
ws cb

# 检查分支并自定义允许的分支
ws cb -a main,develop

# 检查分支并更新依赖
ws cb && ws ud
```

**场景 6：CI/CD 集成**

在 CI/CD 流程中使用：

```bash
# 检查分支
ws cb -a main

# 预览依赖更新（不实际更新）
ws ud -d -v

# 实际更新依赖
ws ud -v
```

### 编程接口使用

#### 基本示例

```typescript
import { updateDependencies, checkBranch, logger } from '@iswangh/script'

// 更新依赖
const result = await updateDependencies({
  exclude: ['vue', 'typescript'],
  batchSize: 15,
  dryRun: false,
})

logger.info(`更新了 ${result.count} 个包`)

// 检查分支
const branchResult = checkBranch({
  allowedBranches: ['main', 'master'],
})

if (!branchResult.allowed) {
  throw new Error(`当前分支 ${branchResult.currentBranch} 不允许发布`)
}
```

#### 完整示例：在发布脚本中使用

```typescript
// scripts/publish.ts
import { checkBranch, updateDependencies, logger } from '@iswangh/script'
import process from 'node:process'

async function main() {
  try {
    // 1. 检查分支
    logger.info('检查 Git 分支...')
    const branchResult = checkBranch({
      allowedBranches: ['main', 'master'],
    })

    if (!branchResult.allowed) {
      logger.error(`当前分支 ${branchResult.currentBranch} 不允许发布`)
      logger.error(`允许的分支：${branchResult.allowedBranches.join(', ')}`)
      process.exit(1)
    }

    logger.success(`✅ 当前分支：${branchResult.currentBranch}`)

    // 2. 更新依赖（可选）
    logger.info('更新项目依赖...')
    const updateResult = await updateDependencies({
      exclude: ['vue', 'typescript'],
      batchSize: 10,
      dryRun: false,
      verbose: true,
    })

    if (updateResult.count > 0) {
      logger.success(`✅ 成功更新 ${updateResult.count} 个包`)
      for (const change of updateResult.changes) {
        if (change.updated) {
          logger.info(`  ${change.name}: ${change.oldVersion} → ${change.newVersion}`)
        }
      }
    }
    else {
      logger.info('所有依赖已是最新版本')
    }

    // 3. 继续发布流程...
    logger.info('开始发布流程...')
  }
  catch (error) {
    logger.error(`发布失败: ${error instanceof Error ? error.message : String(error)}`)
    process.exit(1)
  }
}

main()
```

#### 在 package.json 脚本中使用

```json
{
  "scripts": {
    "prepublishOnly": "ws cb && ws ud",
    "prepublishOnly:verbose": "ws cb -a main && ws ud -v",
    "update:deps": "ws ud",
    "update:deps:dry": "ws ud -d -v"
  }
}
```

## 配置系统

### 配置文件优先级

配置加载遵循以下优先级（从高到低）：

1. **命令行参数**（最高优先级）
2. **环境变量**
3. **配置文件**（按顺序查找，支持多种格式）：
   - **命令特定配置文件**（优先级更高，按顺序尝试）：
     1. `{command-name}.config.js/ts/json/yaml/yml`
     2. `.{command-name}rc.js/ts/json/yaml/yml`
     3. `{command-name}rc.json/yaml/yml`
     4. `.{command-name}rc`（无扩展名，作为 JSON）
     5. `config/{command-name}.js/ts`
   - **统一配置文件**（包含所有命令的配置，按顺序尝试）：
     1. `iswangh-script.config.js/ts/json/yaml/yml`
     2. `.iswangh-scriptrc.js/ts/json/yaml/yml`
     3. `iswangh-scriptrc.json/yaml/yml`
     4. `.iswangh-scriptrc`（无扩展名，作为 JSON）
     5. `config/iswangh-script.js/ts`
4. **package.json 配置**（`package.json` 中的对应字段）
5. **默认值**（最低优先级）

### 配置文件命名规范

配置文件支持多种格式，按照优先级顺序尝试加载（参考 ESLint、Prettier 等工具的最佳实践）：

**命令特定配置文件**（按优先级顺序）：
1. `{command-name}.config.js/ts/json/yaml/yml`（如 `update-deps.config.js`）
2. `.{command-name}rc.js/ts/json/yaml/yml`（如 `.update-depsrc.json`）
3. `{command-name}rc.json/yaml/yml`（如 `update-depsrc.json`）
4. `.{command-name}rc`（无扩展名，作为 JSON，如 `.update-depsrc`）
5. `config/{command-name}.js/ts`（如 `config/update-deps.js`）

**统一配置文件**（按优先级顺序）：
1. `iswangh-script.config.js/ts/json/yaml/yml`
2. `.iswangh-scriptrc.js/ts/json/yaml/yml`
3. `iswangh-scriptrc.json/yaml/yml`
4. `.iswangh-scriptrc`（无扩展名，作为 JSON）
5. `config/iswangh-script.js/ts`

**说明**：
- 配置文件按上述顺序依次尝试加载，找到第一个存在的文件即使用
- JavaScript/TypeScript 配置文件支持动态逻辑（ES Module 或 CommonJS）
- JSON/YAML 配置文件为静态配置
- 无扩展名的 `rc` 文件会被作为 JSON 解析

**多配置文件处理**：
- 如果项目中同时存在多个格式的配置文件（如同时有 `update-deps.config.js` 和 `update-depsrc.json`），系统会按照优先级顺序加载第一个存在的文件
- 其他配置文件将被忽略，不会合并
- 在 `verbose` 模式下，如果检测到多个配置文件存在，会输出警告信息，提示用户删除或重命名其他配置文件以避免混淆
- **建议**：每个命令只保留一个配置文件，避免多个配置文件导致的混淆

### 统一配置文件

统一配置文件包含所有命令的配置，适合在单个文件中管理多个命令的配置。

#### `iswangh-script.config.js`（推荐，支持动态逻辑）

```javascript
// iswangh-script.config.js
// 统一配置文件，包含所有命令的配置
export default {
  // update-deps 命令配置
  updateDeps: {
    exclude: ['vue', 'typescript'],
    batchSize: 15,
    only: null,
    dryRun: false,
    verbose: true,
  },
  // check-branch 命令配置
  checkBranch: {
    allowedBranches: ['main', 'master', 'develop'],
  },
}

// 或使用 CommonJS 格式
module.exports = {
  updateDeps: {
    exclude: ['vue', 'typescript'],
    batchSize: 15,
  },
  checkBranch: {
    allowedBranches: ['main', 'master'],
  },
}
```

#### `iswangh-script.config.ts`（TypeScript 配置文件）

```typescript
// iswangh-script.config.ts
// 统一配置文件，包含所有命令的配置
import type { UpdateDepsConfig, CheckBranchConfig } from '@iswangh/script'

const config = {
  // update-deps 命令配置
  updateDeps: {
    exclude: ['vue', 'typescript'],
    batchSize: 15,
    only: null,
    dryRun: false,
    verbose: true,
  } as UpdateDepsConfig,
  // check-branch 命令配置
  checkBranch: {
    allowedBranches: ['main', 'master', 'develop'],
  } as CheckBranchConfig,
}

export default config
```

**注意**：TypeScript 配置文件需要先编译为 `.config.js`，或使用 `tsx` 等工具运行。

#### `iswangh-scriptrc.json`（JSON 配置文件）

```json
{
  "updateDeps": {
    "exclude": ["vue", "typescript"],
    "batchSize": 15,
    "only": null,
    "dryRun": false,
    "verbose": true
  },
  "checkBranch": {
    "allowedBranches": ["main", "master", "develop"]
  }
}
```

### 命令特定配置文件

如果只需要配置单个命令，可以使用命令特定的配置文件。

#### `update-deps.config.js`（推荐，支持动态逻辑）

```javascript
// update-deps.config.js
// 仅包含 update-deps 命令的配置
export default {
  exclude: ['vue', 'typescript'],
  batchSize: 15,
  only: null,
  dryRun: false,
  verbose: true,
  strategy: 'range', // 更新策略：'range'（默认）、'latest'、'patch-only'、'minor-only'
}

// 或使用 CommonJS 格式
module.exports = {
  exclude: ['vue', 'typescript'],
  batchSize: 15,
}
```

#### `update-deps.config.ts`（TypeScript 配置文件）

```typescript
// update-deps.config.ts
// 仅包含 update-deps 命令的配置
import type { UpdateDepsConfig } from '@iswangh/script'

const config: UpdateDepsConfig = {
  exclude: ['vue', 'typescript'],
  batchSize: 15,
  only: null,
  dryRun: false,
  verbose: true,
  strategy: 'range', // 更新策略：'range'（默认）、'latest'、'patch-only'、'minor-only'
}

export default config
```

**注意**：TypeScript 配置文件需要先编译为 `.config.js`，或使用 `tsx` 等工具运行。

#### `update-depsrc.json`（JSON 配置文件）

```json
{
  "exclude": ["vue", "typescript"],
  "batchSize": 15,
  "only": null,
  "dryRun": false,
  "verbose": true,
  "strategy": "range"
}
```

### package.json 配置

```json
{
  "name": "my-project",
  "updateDeps": {
    "exclude": ["vue"],
    "batchSize": 20
  },
  "checkBranch": {
    "allowedBranches": ["main", "master"]
  }
}
```

### 环境变量

环境变量命名规则：`{COMMAND_NAME}_{CONFIG_KEY}`，其中命令名使用大写字母，横线替换为下划线。

**update-deps 命令环境变量**：

```bash
# 在命令行中设置（PowerShell）
$env:UPDATE_DEPS_EXCLUDE="vue,typescript"
$env:UPDATE_DEPS_BATCH_SIZE="20"
$env:UPDATE_DEPS_ONLY="dependencies"
$env:UPDATE_DEPS_DRY_RUN="false"
$env:UPDATE_DEPS_VERBOSE="true"
$env:UPDATE_DEPS_STRATEGY="range"

# 在命令行中设置（Bash/Zsh）
export UPDATE_DEPS_EXCLUDE=vue,typescript
export UPDATE_DEPS_BATCH_SIZE=20
export UPDATE_DEPS_ONLY=dependencies
export UPDATE_DEPS_DRY_RUN=false
export UPDATE_DEPS_VERBOSE=true
export UPDATE_DEPS_STRATEGY=range

# 或在 .env 文件中设置（需要工具支持）
UPDATE_DEPS_EXCLUDE=vue,typescript
UPDATE_DEPS_BATCH_SIZE=20
UPDATE_DEPS_ONLY=dependencies
UPDATE_DEPS_DRY_RUN=false
UPDATE_DEPS_VERBOSE=true
UPDATE_DEPS_STRATEGY=range
```

**check-branch 命令环境变量**：

```bash
# PowerShell
$env:CHECK_BRANCH_ALLOWED_BRANCHES="main,master,develop"

# Bash/Zsh
export CHECK_BRANCH_ALLOWED_BRANCHES=main,master,develop
```

**环境变量值类型说明**：
- 字符串：直接使用字符串值
- 数字：使用数字字符串（如 `"20"`）
- 布尔值：使用 `"true"` 或 `"false"` 字符串
- 数组：使用逗号分隔的字符串（如 `"vue,typescript"`）
- JSON：可以使用 JSON 格式的字符串，系统会自动解析

## API 文档

### updateDependencies

更新项目依赖到最新版本。

```typescript
function updateDependencies(
  config: UpdateDepsConfig,
  rootDir?: string
): Promise<UpdateResult>
```

**参数：**

- `config: UpdateDepsConfig` - 更新配置
  - `exclude?: string[] | string` - 排除更新的包名列表
  - `batchSize?: number` - 批量更新大小（默认：10）
  - `only?: 'dependencies' | 'devDependencies' | null` - 只更新指定字段
  - `dryRun?: boolean` - 预览模式，不实际更新
  - `verbose?: boolean` - 详细输出
  - `strategy?: 'range' | 'latest' | 'patch-only' | 'minor-only'` - 更新策略（默认：'range'，遵循版本范围限制，类似 nup 的行为）
- `rootDir?: string` - 项目根目录，默认为当前工作目录

**返回值：**

- `Promise<UpdateResult>` - 更新结果
  - `count: number` - 实际更新的包数量
  - `changes: PackageVersionChange[]` - 版本变化信息列表
  - `failedBatches?: FailedBatch[]` - 失败的批次列表

**示例：**

```typescript
import { updateDependencies, logger } from '@iswangh/script'

// 遵循版本范围限制（默认行为，类似 nup）
const result = await updateDependencies({
  exclude: ['vue', 'typescript'],
  batchSize: 15,
  strategy: 'range', // 默认策略
})

// 更新到绝对最新版本（忽略版本范围限制）
const result2 = await updateDependencies({
  exclude: ['vue', 'typescript'],
  batchSize: 15,
  strategy: 'latest', // 更新到绝对最新版本
})

// 只更新补丁版本（最保守）
const result3 = await updateDependencies({
  exclude: ['vue', 'typescript'],
  batchSize: 15,
  strategy: 'patch-only', // 只更新补丁版本
})

// 只更新次要版本和补丁版本（中等保守）
const result4 = await updateDependencies({
  exclude: ['vue', 'typescript'],
  batchSize: 15,
  strategy: 'minor-only', // 只更新次要版本和补丁版本
})

logger.info(`更新了 ${result.count} 个包`)
for (const change of result.changes) {
  if (change.updated) {
    logger.success(`${change.name}: ${change.oldVersion} → ${change.newVersion}`)
  }
}
```

### checkBranch

检查当前 Git 分支是否允许发布。

```typescript
function checkBranch(
  config?: CheckBranchConfig,
  cwd?: string
): CheckBranchResult
```

**参数：**

- `config?: CheckBranchConfig` - 检查配置
  - `allowedBranches?: string[]` - 允许发布的分支列表（默认：['main', 'master']）
- `cwd?: string` - 工作目录，默认为当前工作目录

**返回值：**

- `CheckBranchResult` - 检查结果
  - `currentBranch: string` - 当前分支名称
  - `allowed: boolean` - 是否允许发布
  - `allowedBranches: string[]` - 允许的分支列表

**示例：**

```typescript
import { checkBranch, logger } from '@iswangh/script'

// 基本使用（使用默认允许的分支）
const result = checkBranch()

if (!result.allowed) {
  logger.error(`当前分支 ${result.currentBranch} 不允许发布`)
  logger.error(`允许的分支：${result.allowedBranches.join(', ')}`)
  throw new Error('分支检查失败')
}

// 自定义允许的分支
const result2 = checkBranch({
  allowedBranches: ['main', 'develop', 'release'],
})

// 指定工作目录
const result3 = checkBranch(
  {
    allowedBranches: ['main'],
  },
  '/path/to/project',
)
```

### detectPackageManager

检测项目使用的包管理器。

```typescript
function detectPackageManager(rootDir?: string): PackageManager | null
```

**参数：**

- `rootDir?: string` - 项目根目录，默认为当前工作目录

**返回值：**

- `PackageManager | null` - 检测到的包管理器类型（'bun' | 'npm' | 'pnpm' | 'yarn' | 'deno'），如果未检测到则返回 null

**示例：**

```typescript
import { detectPackageManager, logger, type PackageManager } from '@iswangh/script'

// 基本使用
const pm = detectPackageManager()
if (pm) {
  logger.info(`检测到包管理器: ${pm}`)
}
else {
  logger.warn('未检测到包管理器')
}

// 根据包管理器执行不同操作
const pm2: PackageManager | null = detectPackageManager()
if (pm2 === 'pnpm') {
  logger.info('使用 pnpm 作为包管理器')
}
else if (pm2 === 'npm') {
  logger.info('使用 npm 作为包管理器')
}

// 指定项目根目录
const pm3 = detectPackageManager('/path/to/project')
```

### logger

日志工具，提供统一的日志输出接口。

```typescript
// 默认日志工具实例
import { logger } from '@iswangh/script'

// 或创建自定义日志工具实例
import { createLogger, Logger } from '@iswangh/script'
```

**默认实例方法：**

- `logger.info(message: string, ...args: unknown[]): void` - 输出信息日志
- `logger.success(message: string, ...args: unknown[]): void` - 输出成功日志（带 ✅ 图标）
- `logger.warn(message: string, ...args: unknown[]): void` - 输出警告日志（带 ⚠️ 图标）
- `logger.error(message: string, ...args: unknown[]): void` - 输出错误日志（带 ❌ 图标）
- `logger.verboseLog(message: string, ...args: unknown[]): void` - 输出详细日志（仅在 verbose 模式下输出，带 🔍 图标）
- `logger.setVerbose(enabled: boolean): void` - 设置详细输出模式

**示例：**

```typescript
import { logger } from '@iswangh/script'

// 基本使用
logger.info('开始处理...')
logger.success('处理完成')
logger.warn('警告信息')
logger.error('错误信息')

// 启用详细模式
logger.setVerbose(true)
logger.verboseLog('这是详细日志，只在 verbose 模式下显示')

// 创建自定义日志工具实例
import { createLogger } from '@iswangh/script'

const customLogger = createLogger({ verbose: true })
customLogger.info('使用自定义日志工具')
```

## 开发指南

### 环境要求

- Node.js >= 20.19.0 或 >= 22.12.0
- 推荐使用 Volta 管理 Node.js 版本
- 推荐全局安装 `@antfu/ni` 用于智能命令

### 开发环境启动

```bash
# 安装依赖
ni

# 开发模式（监听文件变化）
nr dev

# 类型检查
nr type-check

# 代码检查
nr lint

# 自动修复代码问题
nr lint:fix

# 构建项目
nr build

# 监听模式构建
nr build:watch
```

### 项目结构说明

- **`bin/`**：CLI 可执行文件
- **`src/`**：源代码目录
  - **`src/commands/`**：命令模块，每个命令一个目录
  - **`src/core/`**：核心功能，可被多个命令共享
  - **`src/utils/`**：工具函数
- **`dist/`**：构建输出目录（由 tsup 生成）
- **`tsup.config.ts`**：tsup 构建配置，支持省略索引文件的导入

### 添加新命令

1. 在 `src/commands/` 下创建新命令目录
2. 实现命令逻辑（模块化设计，使用索引文件聚合导出）
3. 在 `src/cli.ts` 中注册命令
4. 在 `src/commands/index.ts` 中导出命令
5. 在 `src/index.ts` 中导出命令相关功能（如需要）

示例：

```typescript
// src/commands/new-command/index.ts
import { Command } from 'commander'
import { logger } from '../../core'

export const newCommand = new Command('new-command')
  .description('新命令描述')
  .action(async () => {
    logger.info('执行新命令')
  })

// src/cli.ts
import { newCommand } from './commands'
program.addCommand(newCommand)
```

### 代码规范

- 遵循 `@iswangh/eslint-config` 规范
- 使用 TypeScript 严格模式
- 所有公共函数必须有 JSDoc 注释
- 遵循语义化版本规范
- 所有模块使用索引文件聚合导出
- 所有导入使用聚合文件，不直接导入模块内部文件

### 提交规范

- 遵循 `@iswangh/commitlint-config` 规范
- 使用约定式提交格式（Conventional Commits）

## 常见问题

### Q: 更新策略有什么区别？

**A:** 更新策略的区别如下：

- **`range`**（默认）：遵循版本范围限制，只更新到符合 `package.json` 中版本范围限制的最新版本
  - 例如：`"vue": "^3.0.0"` → 更新到 `^3.5.0`（仍在 `^3.0.0` 范围内），不会更新到 `^4.0.0`
  - **适用场景**：日常依赖更新，保持向后兼容
  - **推荐度**：⭐⭐⭐⭐⭐（最推荐）

- **`latest`**：更新到绝对最新版本（忽略版本范围限制）
  - 例如：`"vue": "^3.0.0"` → 更新到 `^4.0.0`（可能包含破坏性变更）
  - **适用场景**：需要获取所有依赖的最新版本，愿意处理可能的破坏性变更
  - **推荐度**：⭐⭐（谨慎使用）

- **`patch-only`**：只更新补丁版本（最保守）
  - 例如：`"vue": "^3.0.0"` → 更新到 `~3.0.5`（只允许 `3.0.x`）
  - **适用场景**：只接受安全补丁和 bug 修复，不接受新功能
  - **推荐度**：⭐⭐⭐⭐（保守场景推荐）

- **`minor-only`**：只更新次要版本和补丁版本（中等保守）
  - 例如：`"vue": "^3.0.0"` → 更新到 `^3.5.0`（允许 `3.x.x`，但不允许 `4.x.x`）
  - **适用场景**：接受新功能和 bug 修复，但不接受破坏性变更
  - **推荐度**：⭐⭐⭐⭐（平衡场景推荐）

### Q: 与 `nup` 命令有什么区别？

**A:** `update-deps` 默认行为与 `nup` 一致（遵循版本范围限制），但提供了更丰富的功能：

| 功能 | `nup` | `update-deps` |
|------|-------|---------------|
| 默认行为 | 遵循版本范围限制 | 遵循版本范围限制（一致） |
| 更新策略 | 仅支持范围限制 | 支持 4 种策略（range、latest、patch-only、minor-only） |
| 批量更新控制 | 不支持 | 支持（可配置批量大小） |
| 排除特定包 | 不支持 | 支持 |
| 只更新指定字段 | 不支持 | 支持（dependencies 或 devDependencies） |
| 预览模式 | 不支持 | 支持（dry-run） |
| 详细输出 | 不支持 | 支持（verbose） |
| 配置文件支持 | 不支持 | 支持（多种格式） |

**建议**：
- 日常快速更新：使用 `nup`
- 需要精细控制：使用 `update-deps`

### Q: 如何选择批量更新大小？

**A:** 批量更新大小（`--batch-size`）影响更新速度和稳定性：

- **小批量（5-10）**：更稳定，但速度较慢
  - 适用场景：依赖较多、网络不稳定、首次使用
  - 推荐值：`10`（默认值）

- **中批量（15-20）**：平衡速度和稳定性
  - 适用场景：依赖中等、网络稳定、熟悉工具
  - 推荐值：`15-20`

- **大批量（30+）**：速度快，但可能不稳定
  - 适用场景：依赖较少、网络非常稳定、有经验
  - 推荐值：`30-50`

**建议**：从默认值 `10` 开始，根据实际情况调整。

### Q: 配置文件优先级是什么？

**A:** 配置加载优先级（从高到低）：

1. **命令行参数**（最高优先级）
2. **环境变量**
3. **配置文件**（命令特定 > 统一配置）
4. **package.json 配置**
5. **默认值**（最低优先级）

**示例**：如果同时设置了命令行参数和配置文件，命令行参数会覆盖配置文件。

### Q: 支持哪些包管理器？

**A:** 支持以下包管理器：

- **bun**：检测 `bun.lock` 文件
- **npm**：检测 `package-lock.json` 文件
- **pnpm**：检测 `pnpm-lock.yaml` 文件
- **yarn**：检测 `yarn.lock` 文件
- **deno**：检测 `deno.json` 或 `deno.jsonc` 文件

**注意**：Deno 项目需要手动更新依赖，工具会提示相关信息。

### Q: 如何排除特定包？

**A:** 有多种方式排除特定包：

**方式 1：命令行参数**
```bash
ws ud -e vue,typescript
```

**方式 2：配置文件**
```json
{
  "updateDeps": {
    "exclude": ["vue", "typescript"]
  }
}
```

**方式 3：环境变量**
```bash
export UPDATE_DEPS_EXCLUDE=vue,typescript
```

### Q: 预览模式（dry-run）有什么用？

**A:** 预览模式可以查看会更新哪些包，而不实际更新：

```bash
# 预览更新
ws ud -d -v

# 查看详细输出
ws ud --dry-run --verbose
```

**适用场景**：
- 首次使用，想了解工具行为
- 更新前检查，确认要更新的包
- CI/CD 流程中，检查更新计划

### Q: 如何查看详细输出？

**A:** 使用 `--verbose` 或 `-v` 选项：

```bash
# 基本详细输出
ws ud -v

# 组合使用
ws ud -d -v
```

**详细输出包含**：
- 检测到的包管理器
- 排除的包列表
- 每个批次的更新进度
- 版本变化详情
- 失败的批次信息（如果有）
- 多配置文件警告（如果有）

### Q: 更新失败怎么办？

**A:** 如果更新失败，可以：

1. **查看详细输出**：使用 `-v` 选项查看详细错误信息
2. **检查失败批次**：工具会显示失败的批次和错误信息
3. **减小批量大小**：使用 `-b 5` 减小批量大小，提高稳定性
4. **排除问题包**：使用 `-e` 排除有问题的包
5. **使用预览模式**：先使用 `-d` 预览，确认更新计划

**常见失败原因**：
- 网络问题：检查网络连接
- 包版本冲突：检查依赖兼容性
- 包管理器问题：检查包管理器是否正确安装
- 权限问题：检查文件权限

## 项目信息

- **许可证**：MIT
- **仓库**：[Gitee](https://gitee.com/iswangh/script.git)
- **版本**：0.0.0（初始开发版本）