Skip to content

fs

File system utilities, providing file operations, directory scanning, safe writing, change detection, report path resolution, file mapping, and batch deletion.

Import

typescript
// Submodule import (recommended)
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
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'

Type Exports

CopyOptions

Copy operation options interface.

typescript
interface CopyOptions {
	recursive: boolean // Whether to recursively copy subdirectories
	overwrite: boolean // Whether to overwrite existing files
	incremental?: boolean // Whether to only copy modified files (default false)
	parallelLimit?: number // Concurrency limit (default 10)
	skipEmptyDirs?: boolean // Whether to skip empty directories
}

CopyResult

Copy result interface.

typescript
interface CopyResult {
	copiedFiles: number // Number of copied files
	skippedFiles: number // Number of skipped files
	copiedDirs: number // Number of copied directories
	executionTime: number // Execution time in milliseconds
}

checkSourceExists

Check if source file exists, throw an error if not found.

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

Parameters

ParameterTypeDescription
sourcePathstringSource path

Example

typescript
await checkSourceExists('/path/to/file')
// Throws if not found: Error: 复制文件失败:源文件不存在 - /path/to/file

copySourceToTarget

Copy files or directories to target location.

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

Parameters

ParameterTypeDescription
sourcePathstringSource path
targetPathstringTarget path
optionsCopyOptionsCopy options

CopyOptions

PropertyTypeDefaultDescription
recursiveboolean-Recursively copy subdirectories
overwriteboolean-Overwrite existing files
incrementalbooleanfalseOnly copy modified files
parallelLimitnumber10Concurrency limit

CopyResult

PropertyTypeDescription
copiedFilesnumberNumber of copied files
skippedFilesnumberNumber of skipped files
copiedDirsnumberNumber of copied dirs
executionTimenumberExecution time (ms)

Example

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

Write content to a file.

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

Parameters

ParameterTypeDescription
filePathstringFile path
contentstringFile content

Example

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

scanDirectory

Recursively scan a directory and collect file information.

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

Parameters

ParameterTypeDefaultDescription
dirPathstring-Directory path
optionsScanDirectoryOptions{}Scan options

ScanDirectoryOptions

PropertyTypeDefaultDescription
includeExtensionsstring[][]File extensions to include, empty for all
excludePatternsstring[][]Path patterns to exclude
filter(filePath: string, extension: string, size: number) => boolean-Custom file filter function

ScannedFile

PropertyTypeDescription
filePathstringAbsolute file path
sizenumberFile size in bytes
extensionstringFile extension (lowercase, with dot)

Returns

Promise<ScannedFile[]> - List of file information

Example

typescript
// Scan all .js files
const jsFiles = await scanDirectory('dist', { includeExtensions: ['.js'] })

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

// Custom filter
const largeFiles = await scanDirectory('dist', {
	filter: (filePath, ext, size) => size > 1024
})

writeJsonReport

Write data to a JSON file.

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

Parameters

ParameterTypeDefaultDescription
filePathstring-Output file path
dataobject-Data object to serialize
indentnumber2JSON indentation spaces

Example

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

writeFileSyncSafely

Synchronously write file content, automatically creating non-existent directories.

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

Parameters

ParameterTypeDescription
filePathstringFile path
contentstringFile content

Notes

  • Synchronously writes file, automatically creates target directories recursively if they don't exist
  • Suitable for scenarios requiring synchronous writes in build hooks (e.g., transform hook)
  • Throws NodeJS.ErrnoException when file write fails (e.g., insufficient permissions)

Example

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

shouldUpdateFileContent

Check if file content needs to be updated (synchronous version).

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

Parameters

ParameterTypeDescription
filePathstringFile path
newContentstringNewly generated file content

Returns

boolean - Returns true if update is needed, false otherwise

Notes

  • Compares existing file content with newly generated content, only needs to write when content has changed
  • Reduces unnecessary file IO operations
  • Returns true when file doesn't exist

Example

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

resolveReportPath

Resolve report output path.

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

Parameters

ParameterTypeDescription
outDirstringBuild output directory path
reportPathstring | falseReport file path, false to skip report generation

Returns

string | null - Resolved absolute path, returns null when reportPath is false

Notes

  • When reportPath is a relative path, it is resolved relative to outDir
  • When reportPath is an absolute path, it is used directly
  • When reportPath is false, returns null

Example

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

scanAndMapFiles

Scan a directory and map file information to custom structures.

typescript
async function scanAndMapFiles<T>(
  dirPath: string,
  params: {
    scanOptions?: ScanDirectoryOptions
    mapFn: (file: ScannedFile, dirPath: string) => T
  }
): Promise<T[]>

Parameters

ParameterTypeDefaultDescription
dirPathstring-Directory path
paramsobject-Scan and mapping parameters

params

PropertyTypeDefaultDescription
scanOptionsScanDirectoryOptions-Options passed to scanDirectory
mapFn(file: ScannedFile, dirPath: string) => T-Function to map ScannedFile to custom structure

Returns

Promise<T[]> - List of mapped entries

Notes

  • Recursively scans directory and applies mapFn to each file
  • Generic wrapper for the "scan + filter + map" pattern used by multiple plugins
  • mapFn receives the original ScannedFile and dirPath, allowing free computation of relativePath etc.

Example

typescript
// Scan and map to custom structure
const candidates = await scanAndMapFiles('dist', {
  scanOptions: { filter: (fp, ext, size) => size > 1024 },
  mapFn: (f, dir) => ({
    filePath: f.filePath,
    relativePath: normalizePath(path.relative(dir, f.filePath)),
    size: f.size,
    ext: f.extension
  })
})

deleteFiles

Batch delete a list of files.

typescript
async function deleteFiles(filePaths: string[]): Promise<void>

Parameters

ParameterTypeDescription
filePathsstring[]List of absolute file paths to delete (auto-deduplicated)

Notes

  • Deletes files by path list, auto-deduplicates then deletes one by one
  • Silently ignores deletion errors (e.g., file already deleted or insufficient permissions)

Example

typescript
await deleteFiles(['/dist/app.js', '/dist/app.js.gz'])

Released under the MIT License.