# fs-async
**Repository Path**: nodets/fs-async
## Basic Information
- **Project Name**: fs-async
- **Description**: No description available
- **Primary Language**: Unknown
- **License**: MIT
- **Default Branch**: main
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2025-10-06
- **Last Updated**: 2025-10-06
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# fs-async
轻量级异步文件操作工具,基于 Node.js 原生 `fs/promises` 实现,**无第三方依赖**,支持文件读写、目录管理、路径匹配等核心场景,提供清晰的 TypeScript 类型提示,简化日常异步文件处理流程。
## 特性
- 🚀 **纯异步非阻塞**:基于 `fs/promises` 开发,避免阻塞事件循环,适配 Node.js 异步生态
- 📦 **零额外依赖**:移除 `glob` 等第三方库,仅依赖 Node.js 原生 API,减少项目体积
- 🔧 **核心功能全覆盖**:文件读写、JSON 处理、目录管理、路径匹配、哈希计算等常用操作
- ✅ **TypeScript 原生支持**:完整类型定义,支持 IDE 自动补全和类型校验,减少运行时错误
- 🖥️ **跨平台兼容**:统一处理 Windows/macOS/Linux 路径分隔符,避免跨平台路径问题
## 安装
```bash
# 安装核心包
npm install fs-async --save
# 低版本 Node.js(<16)如需 TypeScript 类型支持,需手动安装 @types/node
npm install @types/node --save-dev
```
## 快速开始
### 基础示例(ES Module)
```typescript
// 导入工具(默认导出为 fs 对象,与原生 fs 命名习惯一致)
import fs from 'fs-async';
async function fileOpsDemo() {
try {
// 1. 写入文件(自动创建不存在的父目录)
await fs.write('./data/log.txt', '2024-01-01: 系统启动成功');
// 2. 读取文件(默认编码 utf-8)
const logContent = await fs.read('./data/log.txt');
console.log('日志内容:', logContent); // 输出:2024-01-01: 系统启动成功
// 3. 写入 JSON 文件(自动格式化,缩进 2 空格)
await fs.writeJSON('./data/config.json', {
theme: 'dark',
timeout: 3000
});
// 4. 读取 JSON 文件(自动解析)
const config = await fs.readJSON('./data/config.json');
console.log('配置主题:', config.theme); // 输出:dark
// 5. 复制目录(强制覆盖已存在的目标目录)
await fs.copy('./data', './data-backup', { force: true });
// 6. 路径匹配(查找所有 .json 文件)
const jsonFiles = await fs.expand('**/*.json', { onlyFiles: true });
console.log('JSON 文件列表:', jsonFiles); // 输出:[ 'data/config.json', 'data-backup/config.json' ]
} catch (err: any) {
console.error('文件操作失败:', err.message);
}
}
fileOpsDemo();
```
### CommonJS 示例
```javascript
// 导入工具
const fs = require('fs-async');
async function dirOpsDemo() {
try {
// 创建嵌套目录
await fs.mkdir('./temp/docs');
// 检查路径是否为目录
const isDir = await fs.isDir('./temp/docs');
console.log('./temp/docs 是否为目录:', isDir); // 输出:true
// 清空目录(保留目录本身,删除内容)
await fs.emptyDir('./temp/docs');
// 删除目录(递归删除整个目录)
await fs.remove('./temp');
} catch (err) {
console.error('目录操作失败:', err.message);
}
}
dirOpsDemo();
```
## API 文档
所有方法均返回 `Promise`,支持 `async/await` 调用,以下是核心 API 说明:
### 1. 文件操作
| 方法 | 说明 | 参数 | 返回值 |
|------|------|------|--------|
| `fs.write(file, content, [options])` | 写入文件(自动创建父目录) | `file`: 目标文件路径
`content`: 写入内容(string/Buffer)
`options`: 可选,`fs.WriteFileOptions`(含 `encoding`/`flag` 等) | `Promise` |
| `fs.read(file, [options])` | 读取文件 | `file`: 文件路径
`options`: 可选,含 `encoding`(默认 `utf-8`)/`flag` | `Promise` |
| `fs.readJSON(file, [options])` | 读取 JSON 文件并解析 | `file`: JSON 文件路径
`options`: 可选,同 `fs.read` 的 `options` | `Promise`(解析后的 JSON 对象) |
| `fs.writeJSON(file, data, [spaces])` | 写入 JSON 文件(自动格式化) | `file`: 目标文件路径
`data`: 要序列化的 JSON 数据
`spaces`: 可选,缩进空格数(默认 2) | `Promise` |
| `fs.appendFile(file, content, [options])` | 向文件追加内容 | 参数同 `fs.write` | `Promise` |
| `fs.copy(from, to, [options])` | 复制文件/目录 | `from`: 源路径
`to`: 目标路径
`options`: 可选,`{ force?: boolean; preserveTimestamps?: boolean }`(`force` 强制覆盖,默认 false;`preserveTimestamps` 保留时间戳,默认 false) | `Promise` |
| `fs.move(from, to, [options])` | 移动/重命名文件/目录(跨设备自动降级为复制+删除) | `from`: 源路径
`to`: 目标路径
`options`: 可选,`{ force?: boolean }`(强制覆盖,默认 false) | `Promise` |
| `fs.remove(path)` | 删除文件/目录(递归删除,等同于 `rm -rf`) | `path`: 要删除的路径 | `Promise` |
| `fs.hashFile(file, [algorithm])` | 计算文件哈希值 | `file`: 文件路径
`algorithm`: 可选,哈希算法(默认 `sha256`,支持 `md5`/`sha1` 等) | `Promise`(十六进制哈希字符串) |
### 2. 目录操作
| 方法 | 说明 | 参数 | 返回值 |
|------|------|------|--------|
| `fs.mkdir(dirPath)` | 创建目录(递归创建,等同于 `mkdir -p`) | `dirPath`: 目标目录路径 | `Promise` |
| `fs.readDir(dir, [options])` | 读取目录内容 | `dir`: 目录路径
`options`: 可选,`{ withFileTypes?: boolean }`(`withFileTypes` 为 true 时返回 `fs.Dirent` 对象数组,否则返回文件名数组) | `Promise` |
| `fs.emptyDir(dir)` | 清空目录(保留目录本身,删除所有子内容) | `dir`: 目录路径 | `Promise` |
| `fs.isDir(path)` | 判断路径是否为目录 | `path`: 路径 | `Promise` |
| `fs.isFile(path)` | 判断路径是否为文件 | `path`: 路径 | `Promise` |
| `fs.exists(...paths)` | 判断路径是否存在(支持多参数拼接路径,如 `fs.exists('src', 'utils', 'file.ts')`) | `paths`: 路径片段(可多个) | `Promise` |
### 3. 路径工具
| 方法 | 说明 | 参数 | 返回值 |
|------|------|------|--------|
| `fs.expand(patterns, [options])` | 路径匹配(支持 `*`/`**` 模式,替代 `glob`) | `patterns`: 匹配模式(string 或 string 数组,如 `'**/*.ts'`)
`options`: 可选,`{ cwd?: string; dot?: boolean; onlyFiles?: boolean; onlyDirs?: boolean }`(`cwd` 工作目录,默认当前目录;`dot` 匹配隐藏文件,默认 false;`onlyFiles`/`onlyDirs` 仅匹配文件/目录) | `Promise`(匹配的路径数组) |
| `fs.isPathAbsolute(path)` | 判断路径是否为绝对路径 | `path`: 路径 | `Promise` |
| `fs.doesPathContain(ancestor, ...paths)` | 判断祖先路径是否包含所有子路径 | `ancestor`: 祖先路径
`paths`: 子路径(可多个) | `Promise` |
| `fs.createSymlink(target, linkPath, [options])` | 创建符号链接 | `target`: 链接指向的目标路径
`linkPath`: 链接文件路径
`options`: 可选,`{ type?: 'file' | 'dir' | 'junction' }`(链接类型,默认 `file`) | `Promise` |
| `fs.realpath(path)` | 获取符号链接指向的真实路径 | `path`: 符号链接路径 | `Promise` |
## 错误处理
所有方法抛出的错误均包含清晰的描述信息,可通过 `try/catch` 捕获并处理:
```typescript
try {
await fs.read('./nonexistent.txt');
} catch (err: any) {
console.error('错误类型:', err.name); // 输出:Error
console.error('错误信息:', err.message); // 输出:文件不存在:./nonexistent.txt
}
```
常见错误场景:
- 路径不存在:`文件不存在:xxx`/`目录不存在:xxx`
- 路径已存在:`目标已存在(设 force: true 覆盖):xxx`
- 类型不匹配:`路径是目录:xxx`/`路径是文件:xxx`
## 注意事项
1. **`fs.remove` 风险提示**:`fs.remove` 等同于 `rm -rf`,会递归删除目录所有内容,请谨慎使用,避免误删重要文件。
2. **跨设备移动**:`fs.move` 在跨设备(如 C 盘到 D 盘)时会自动降级为“复制+删除”,确保操作成功。
3. **路径匹配能力**:`fs.expand` 支持基础的 `*`(匹配单层任意字符)和 `**`(匹配多层目录)模式,复杂场景可自行扩展。
## 版本兼容
- 支持 Node.js 14+(推荐 Node.js 16+,原生支持完整的 `fs/promises` API)
- TypeScript 4.5+(如需类型校验)