npm package: @ldesign/dynamic-import
Description: 一个功能强大的Node.js动态包管理工具，支持运行时动态导入npm包、自动依赖安装、批量导入、版本控制等功能
Author: Dynamic Import Manager
Latest version: 0.0.5

# 🚀 Dynamic Import Manager

> 一个功能强大的Node.js动态包管理工具，让你在运行时轻松导入npm包！

[![npm version](https://badge.fury.io/js/@ldesign/dynamic-import.svg)](https://badge.fury.io/js/@ldesign/dynamic-import)
[![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue.svg)](https://www.typescriptlang.org/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Test Coverage](https://img.shields.io/badge/coverage-90%2B-brightgreen.svg)](https://github.com/your-username/dynamic-import-manager)

## ✨ 特性亮点

🎯 **动态加载** - 运行时动态导入任意npm包，无需预先安装⚡
**自动安装** - 智能检测并自动安装缺失的依赖包 🔄
**批量导入** - 支持同时导入多个包，提升效率 📦
**版本控制** - 精确控制包版本，避免版本冲突 🎨
**导出灵活** - 支持default、named、namespace多种导出方式🛡️
**类型安全** - 完整的TypeScript支持，开发更安心🚀
**高性能** - 智能缓存机制，避免重复导入 🔧
**易配置** - 支持多种包管理器（默认pnpm）🗂️
**临时安装** - 支持临时安装，自动清理package.json ⚙️
**灵活依赖** - 支持安装到devDependencies或dependencies

## 📦 安装

```bash
# 使用 npm
npm install @ldesign/dynamic-import

# 使用 yarn
yarn add @ldesign/dynamic-import

# 使用 pnpm (推荐)
pnpm add @ldesign/dynamic-import
```

## 🎯 快速开始

### 基础用法

```typescript
import { dynamicImport } from '@ldesign/dynamic-import'

// 动态导入lodash包（默认临时安装到devDependencies）
const { module: lodash } = await dynamicImport('lodash')
console.log(lodash.chunk([1, 2, 3, 4], 2)) // [[1, 2], [3, 4]]

// 指定版本导入，安装到dependencies
const { module: axios } = await dynamicImport('axios', {
  version: '1.6.0',
  exportType: 'default',
  isTemporary: false, // 保留在package.json中
  installType: 'prod', // 安装到dependencies
})
const response = await axios.get('https://api.github.com')

// 临时安装（不保留在package.json中）
const { module: chalk } = await dynamicImport('chalk', {
  isTemporary: true, // 默认值，安装后自动清理
  installType: 'dev', // 默认值，安装到devDependencies
})
console.log(chalk.blue('Hello World!'))
```

### 高级用法

```typescript
import { DynamicPackageManager } from '@ldesign/dynamic-import'

// 创建管理器实例
const manager = await DynamicPackageManager.create()

// 批量导入多个包
const result = await manager.importBatch({
  packages: [
    { packageName: 'lodash', exportType: 'default' },
    { packageName: 'dayjs', version: '1.11.0' },
    {
      packageName: 'chalk',
      exportType: 'named',
      namedExports: ['red', 'blue'],
    },
  ],
  parallel: true,
  maxConcurrency: 3,
})

console.log(`成功导入 ${result.successful.length} 个包`)
console.log(`失败 ${result.failed.length} 个包`)
```

## 📚 API 文档

### 便捷函数

#### `dynamicImport(packageName, options?)`

动态导入单个包的便捷函数。

```typescript
const result = await dynamicImport('package-name', {
  version: '1.0.0', // 指定版本
  exportType: 'default', // 导出类型: 'default' | 'named' | 'namespace'
  namedExports: ['func1'], // 具名导出列表（exportType为'named'时使用）
  forceReinstall: false, // 是否强制重新安装
  isTemporary: true, // 是否临时安装（默认true，安装后从package.json删除）
  installType: 'dev', // 安装类型: 'dev' | 'prod'（默认'dev'）
})
```

#### `importFromSpec(packageSpec, exportType?)`

从包规范字符串导入包。

```typescript
// 基础用法
const result = await importFromSpec('lodash@4.17.21')

// 作用域包
const result = await importFromSpec('@types/node@18.0.0', 'namespace')
```

#### `batchImport(packages, options?)`

批量导入多个包。

```typescript
const result = await batchImport(
  [
    { packageName: 'lodash', exportType: 'default' },
    { packageName: 'axios', version: '1.6.0' },
  ],
  {
    parallel: true, // 是否并行导入
    maxConcurrency: 3, // 最大并发数
    continueOnError: true, // 出错时是否继续
  }
)
```

### 核心类

#### `DynamicPackageManager`

主要的包管理器类，提供完整的动态导入功能。

```typescript
// 创建实例
const manager = await DynamicPackageManager.create()
const manager = new DynamicPackageManager('pnpm', '/custom/path')

// 导入包
const result = await manager.import({
  packageName: 'package-name',
  version: '1.0.0',
  exportType: 'default'
})

// 批量导入
const batchResult = await manager.importBatch({
  packages: [...],
  parallel: true
})

// 包管理
await manager.installPackage('package-name', '1.0.0')
await manager.uninstallPackage('package-name')

// 缓存管理
manager.clearAllCaches()
const cacheInfo = manager.getCacheInfo()
```

## 🎨 使用示例

### 示例1：动态加载工具库

```typescript
import { dynamicImport } from '@ldesign/dynamic-import'

async function processData(data: any[]) {
  // 动态加载lodash进行数据处理
  const { module: _ } = await dynamicImport('lodash')

  return _(data)
    .filter(item => item.active)
    .groupBy('category')
    .mapValues(group => group.length)
    .value()
}
```

### 示例2：条件导入不同的包

```typescript
import { dynamicImport } from '@ldesign/dynamic-import'

async function createLogger(type: 'simple' | 'advanced') {
  if (type === 'simple') {
    const { module: chalk } = await dynamicImport('chalk', {
      exportType: 'named',
      namedExports: ['red', 'green', 'blue'],
    })
    return {
      info: (msg: string) => console.log(chalk.blue(msg)),
      error: (msg: string) => console.log(chalk.red(msg)),
    }
  } else {
    const { module: winston } = await dynamicImport('winston')
    return winston.createLogger({
      level: 'info',
      format: winston.format.json(),
      transports: [new winston.transports.Console()],
    })
  }
}
```

### 示例3：插件系统

```typescript
import { DynamicPackageManager } from '@ldesign/dynamic-import'

class PluginSystem {
  private manager = await DynamicPackageManager.create()
  private plugins = new Map()

  async loadPlugin(pluginName: string, version?: string) {
    try {
      const result = await this.manager.import({
        packageName: pluginName,
        version,
        exportType: 'default',
      })

      this.plugins.set(pluginName, result.module)
      console.log(`✅ 插件 ${pluginName} 加载成功`)

      return result.module
    } catch (error) {
      console.error(`❌ 插件 ${pluginName} 加载失败:`, error.message)
      throw error
    }
  }

  async loadPlugins(pluginConfigs: Array<{ name: string; version?: string }>) {
    const packages = pluginConfigs.map(config => ({
      packageName: config.name,
      version: config.version,
      exportType: 'default' as const,
    }))

    const result = await this.manager.importBatch({
      packages,
      parallel: true,
      continueOnError: true,
    })

    result.successful.forEach(plugin => {
      this.plugins.set(plugin.packageName, plugin.module)
    })

    return {
      loaded: result.successful.length,
      failed: result.failed.length,
      plugins: this.plugins,
    }
  }
}
```

## ⚙️ 配置选项

### DynamicImportOptions

```typescript
interface DynamicImportOptions {
  packageName: string // 包名
  version?: string // 指定版本
  exportType?: ExportType // 导出类型
  namedExports?: string[] // 具名导出列表
  forceReinstall?: boolean // 强制重新安装
  installDir?: string // 自定义安装目录
  packageManager?: PackageManager // 包管理器类型
}
```

### BatchImportOptions

```typescript
interface BatchImportOptions {
  packages: DynamicImportOptions[] // 包配置列表
  parallel?: boolean // 是否并行安装
  maxConcurrency?: number // 最大并发数
  continueOnError?: boolean // 失败时是否继续
}
```

### 导出类型

- `'default'` - 默认导出（推荐）
- `'named'` - 具名导出，需要指定 `namedExports`
- `'namespace'` - 命名空间导出，导入整个模块

### 包管理器支持

- `'pnpm'` - 高性能的npm替代品（默认和推荐）
- `'yarn'` - Yarn Package Manager
- `'npm'` - Node Package Manager

## 🔧 高级用法

### 自定义包管理器

```typescript
import { DynamicPackageManager } from '@ldesign/dynamic-import'

// 使用特定的包管理器和目录
const manager = new DynamicPackageManager('yarn', '/custom/project/path')

// 或者自动检测（默认优先使用pnpm）
const autoManager = await DynamicPackageManager.create('/custom/path')
```

### 缓存管理

```typescript
// 获取缓存信息
const cacheInfo = manager.getCacheInfo()
console.log(`缓存大小: ${cacheInfo.size}`)
console.log(`缓存的包: ${cacheInfo.packages.join(', ')}`)

// 清除特定包的缓存
manager.clearCache('package-name')

// 清除所有缓存
manager.clearAllCaches()

// 预加载包（不导入）
await manager.preloadPackages([
  { name: 'lodash', version: '4.17.21' },
  { name: 'axios', version: '1.6.0' },
])
```

### 错误处理

```typescript
import {
  DynamicImportError,
  PackageInstallError,
  ModuleImportError,
} from '@ldesign/dynamic-import'

try {
  const result = await dynamicImport('non-existent-package')
} catch (error) {
  if (error instanceof PackageInstallError) {
    console.error('包安装失败:', error.message)
    console.error('包名:', error.packageName)
    console.error('退出码:', error.exitCode)
  } else if (error instanceof ModuleImportError) {
    console.error('模块导入失败:', error.message)
    console.error('包名:', error.packageName)
  } else if (error instanceof DynamicImportError) {
    console.error('动态导入错误:', error.message)
  }
}
```

### 版本控制

```typescript
// 精确版本
await dynamicImport('lodash', { version: '4.17.21' })

// 版本范围（使用semver）
await dynamicImport('lodash', { version: '^4.17.0' })
await dynamicImport('lodash', { version: '~4.17.20' })

// 最新版本（默认）
await dynamicImport('lodash')

// 强制重新安装特定版本
await dynamicImport('lodash', {
  version: '4.17.21',
  forceReinstall: true,
})
```

## 💡 最佳实践

### 1. 错误处理

始终使用try-catch包装动态导入操作：

```typescript
async function safeImport(packageName: string) {
  try {
    return await dynamicImport(packageName)
  } catch (error) {
    console.error(`导入 ${packageName} 失败:`, error.message)
    return null
  }
}
```

### 2. 性能优化

利用缓存机制避免重复导入：

```typescript
const manager = await DynamicPackageManager.create()

// 第一次导入会安装和缓存
const lodash1 = await manager.import({ packageName: 'lodash' })

// 第二次导入直接使用缓存，速度更快
const lodash2 = await manager.import({ packageName: 'lodash' })
```

### 3. 批量操作

对于多个包的导入，使用批量操作提升效率：

```typescript
// ✅ 推荐：批量导入
const result = await batchImport(
  [
    { packageName: 'lodash' },
    { packageName: 'axios' },
    { packageName: 'dayjs' },
  ],
  { parallel: true }
)

// ❌ 不推荐：逐个导入
const lodash = await dynamicImport('lodash')
const axios = await dynamicImport('axios')
const dayjs = await dynamicImport('dayjs')
```

### 4. 类型安全

充分利用TypeScript类型定义：

```typescript
import type { DynamicImportResult } from '@ldesign/dynamic-import'

// 指定返回类型
const result: DynamicImportResult<typeof import('lodash')> =
  await dynamicImport('lodash')

// 使用泛型
const { module } = await dynamicImport<typeof import('axios')>('axios')
```

## ❓ 常见问题

### Q: 支持哪些Node.js版本？

A: 支持Node.js 16.0.0及以上版本。

### Q: 可以在浏览器中使用吗？

A: 不可以，这是一个专为Node.js环境设计的工具，依赖于文件系统和包管理器。

### Q: 如何处理包的依赖冲突？

A: 工具会使用指定的包管理器来解决依赖冲突。建议使用pnpm以获得更好的依赖管理。

### Q: 导入的包会被永久安装吗？

A: 是的，包会被安装到项目的node_modules目录中。如需清理，可以手动删除或使用包管理器的清理命令。

### Q: 支持私有npm仓库吗？

A: 支持，工具会使用当前环境配置的npm registry设置。

### Q: 如何调试导入失败的问题？

A: 可以通过捕获错误对象来获取详细的错误信息，包括包名、错误类型和原始错误。

## 🤝 贡献指南

我们欢迎所有形式的贡献！

### 开发环境设置

```bash
# 克隆仓库
git clone https://github.com/your-username/dynamic-import-manager.git
cd dynamic-import-manager

# 安装依赖
pnpm install

# 运行测试
pnpm test

# 构建项目
pnpm build

# 检查代码质量
pnpm lint
```

### 提交规范

- 🐛 `fix:` 修复bug
- ✨ `feat:` 新功能
- 📝 `docs:` 文档更新
- 🎨 `style:` 代码格式化
- ♻️ `refactor:` 代码重构
- ⚡ `perf:` 性能优化
- ✅ `test:` 测试相关

## 📄 许可证

本项目采用 [MIT 许可证](LICENSE)。

## 🙏 致谢

感谢所有为这个项目做出贡献的开发者！

---

<div align="center">

**如果这个项目对你有帮助，请给它一个 ⭐️！**

[报告问题](https://github.com/your-username/dynamic-import-manager/issues) ·
[功能请求](https://github.com/your-username/dynamic-import-manager/issues) ·
[贡献代码](https://github.com/your-username/dynamic-import-manager/pulls)

</div>