Skip to content

fs

文件系统操作工具,提供文件复制、目录扫描、安全写入、变更检测、报告路径解析、文件映射和批量删除等功能。

导入方式

typescript
// 子模块独立导入(推荐)
import { checkSourceExists, copySourceToTarget, writeFileContent, scanDirectory, writeJsonReport, writeFileSyncSafely, shouldUpdateFileContent, resolveReportPath, scanAndMapFiles, deleteFiles } from '@meng-xi/vite-plugin/common/fs'
import type { CopyOptions, CopyResult, ScannedFile, ScanDirectoryOptions } from '@meng-xi/vite-plugin/common/fs'

// barrel 导入
import { checkSourceExists, copySourceToTarget, writeFileContent, scanDirectory, writeJsonReport, writeFileSyncSafely, shouldUpdateFileContent, resolveReportPath, scanAndMapFiles, deleteFiles } from '@meng-xi/vite-plugin/common'
import type { CopyOptions, CopyResult, ScannedFile, ScanDirectoryOptions } from '@meng-xi/vite-plugin/common'

类型导出

CopyOptions

复制操作选项接口。

typescript
interface CopyOptions {
	recursive: boolean // 是否递归复制子目录
	overwrite: boolean // 是否覆盖已存在文件
	incremental?: boolean // 是否仅复制修改过的文件(默认 false)
	parallelLimit?: number // 并发限制数(默认 10)
	skipEmptyDirs?: boolean // 是否跳过空目录
}

CopyResult

复制结果接口。

typescript
interface CopyResult {
	copiedFiles: number // 复制的文件数量
	skippedFiles: number // 跳过的文件数量
	copiedDirs: number // 复制的目录数量
	executionTime: number // 执行时间(毫秒)
}

checkSourceExists

检查源文件是否存在,不存在时抛出异常。

typescript
async function checkSourceExists(sourcePath: string): Promise<void>

参数

参数类型说明
sourcePathstring源文件路径

示例

typescript
await checkSourceExists('/path/to/file')
// 文件不存在时抛出: Error: 复制文件失败:源文件不存在 - /path/to/file

copySourceToTarget

复制文件或目录到目标位置。

typescript
async function copySourceToTarget(sourcePath: string, targetPath: string, options: CopyOptions): Promise<CopyResult>

参数

参数类型说明
sourcePathstring源路径
targetPathstring目标路径
optionsCopyOptions复制选项

CopyOptions

属性类型默认值说明
recursiveboolean-递归复制子目录
overwriteboolean-覆盖已存在文件
incrementalbooleanfalse仅复制修改过的文件
parallelLimitnumber10并发限制数

CopyResult

属性类型说明
copiedFilesnumber复制的文件数
skippedFilesnumber跳过的文件数
copiedDirsnumber复制的目录数
executionTimenumber执行时间(ms)

示例

typescript
const result = await copySourceToTarget('src/assets', 'dist/assets', {
	recursive: true,
	overwrite: true,
	incremental: true,
	parallelLimit: 10
})

console.log(result)
// { copiedFiles: 10, skippedFiles: 2, copiedDirs: 3, executionTime: 150 }

writeFileContent

写入文件内容。

typescript
async function writeFileContent(filePath: string, content: string): Promise<void>

参数

参数类型说明
filePathstring文件路径
contentstring文件内容

示例

typescript
await writeFileContent('/path/to/file.txt', 'Hello World')

scanDirectory

递归扫描目录,收集所有文件信息。

typescript
async function scanDirectory(dirPath: string, options?: ScanDirectoryOptions): Promise<ScannedFile[]>

参数

参数类型默认值说明
dirPathstring-目录路径
optionsScanDirectoryOptions{}扫描选项

ScanDirectoryOptions

属性类型默认值说明
includeExtensionsstring[][]包含的文件扩展名,为空则全部
excludePatternsstring[][]排除的路径模式列表
filter(filePath: string, extension: string, size: number) => boolean-自定义文件过滤函数

ScannedFile

属性类型说明
filePathstring文件绝对路径
sizenumber文件大小(字节)
extensionstring文件扩展名(小写,含点号)

返回值

Promise<ScannedFile[]> - 文件信息列表

示例

typescript
// 扫描所有 .js 文件
const jsFiles = await scanDirectory('dist', { includeExtensions: ['.js'] })

// 排除 node_modules
const files = await scanDirectory('dist', { excludePatterns: ['node_modules'] })

// 使用自定义过滤
const largeFiles = await scanDirectory('dist', {
	filter: (filePath, ext, size) => size > 1024
})

writeJsonReport

将数据写入 JSON 文件。

typescript
async function writeJsonReport(filePath: string, data: object, indent?: number): Promise<void>

参数

参数类型默认值说明
filePathstring-输出文件路径
dataobject-要序列化的数据对象
indentnumber2JSON 缩进空格数

示例

typescript
await writeJsonReport('dist/report.json', { timestamp: Date.now(), stats: [] })
await writeJsonReport('dist/report.json', data, 4)

writeFileSyncSafely

同步写入文件内容,自动创建不存在的目录。

typescript
function writeFileSyncSafely(filePath: string, content: string): void

参数

参数类型说明
filePathstring文件路径
contentstring文件内容

说明

  • 同步写入文件,如果目标目录不存在会自动递归创建
  • 适用于构建钩子中需要同步写入的场景(如 transform 钩子)
  • 当文件写入失败时(如权限不足),抛出 NodeJS.ErrnoException

示例

typescript
writeFileSyncSafely('/project/src/auto-imports.d.ts', 'declare global { ... }')

shouldUpdateFileContent

检查文件内容是否需要更新(同步版本)。

typescript
function shouldUpdateFileContent(filePath: string, newContent: string): boolean

参数

参数类型说明
filePathstring文件路径
newContentstring新生成的文件内容

返回值

boolean - 如果需要更新返回 true,否则返回 false

说明

  • 对比现有文件内容与新生成的内容,仅在内容发生变化时才需要写入
  • 减少不必要的文件 IO 操作
  • 文件不存在时返回 true

示例

typescript
if (shouldUpdateFileContent('/project/src/auto-imports.d.ts', newContent)) {
	writeFileSyncSafely('/project/src/auto-imports.d.ts', newContent)
}

resolveReportPath

解析报告输出路径。

typescript
function resolveReportPath(outDir: string, reportPath: string | false): string | null

参数

参数类型说明
outDirstring构建输出目录路径
reportPathstring | false报告文件路径,false 不生成报告

返回值

string | null - 解析后的绝对路径,reportPathfalse 时返回 null

说明

  • reportPath 为相对路径时,相对于 outDir 解析
  • reportPath 为绝对路径时直接使用
  • reportPathfalse 时返回 null

示例

typescript
resolveReportPath('dist', 'report.json')   // 'dist/report.json'
resolveReportPath('dist', '/tmp/r.json')    // '/tmp/r.json'
resolveReportPath('dist', false)            // null

scanAndMapFiles

扫描目录并构建文件路径映射表,用于快速查找文件。

typescript
async function scanAndMapFiles(
  dirPath: string,
  options?: ScanDirectoryOptions
): Promise<Map<string, ScannedFile>>

参数

参数类型默认值说明
dirPathstring-目录路径
optionsScanDirectoryOptions{}扫描选项(同 scanDirectory

返回值

Promise<Map<string, ScannedFile>> - 以文件相对路径为键、文件信息为值的映射表

说明

  • 基于 scanDirectory 实现,将扫描结果转换为 Map 结构便于 O(1) 查找
  • 键为相对于 dirPath 的规范化相对路径(使用正斜杠)
  • 适用于需要快速判断文件是否存在或获取文件信息的场景

示例

typescript
// 构建文件映射表
const fileMap = await scanAndMapFiles('dist')

// 检查文件是否存在
if (fileMap.has('assets/index.js')) {
	const file = fileMap.get('assets/index.js')!
	console.log(`文件大小: ${file.size} 字节`)
}

// 配合过滤条件使用
const jsFileMap = await scanAndMapFiles('dist', { includeExtensions: ['.js'] })

deleteFiles

批量删除文件列表,忽略不存在的文件。

typescript
async function deleteFiles(files: string[]): Promise<{ deleted: number; skipped: number }>

参数

参数类型说明
filesstring[]待删除的文件路径列表

返回值

Promise<{ deleted: number; skipped: number }> - 删除结果统计

属性类型说明
deletednumber成功删除的文件数
skippednumber跳过的文件数(不存在或删除失败)

说明

  • 并发删除文件,提高批量操作效率
  • 文件不存在时跳过,不抛出异常
  • 删除单个文件失败时跳过该文件,继续处理其他文件

示例

typescript
// 批量删除文件
const result = await deleteFiles([
	'dist/old-file.js',
	'dist/old-file.css',
	'dist/temp.txt'
])

console.log(`删除 ${result.deleted} 个,跳过 ${result.skipped} 个`)

Released under the MIT License.