import { - copyFile,
- emptyDir,
- ensureDir,
- ensureFile,
- exists,
- expandGlob,
- globToRegExp,
- lstat,
- readdir,
- readTextFile,
- rm,
- stat,
- toPath,
- walk,
- type WalkEntry,
- type WalkOptions,
- writeTextFile
} from "@effectionx/fs"FS
File system operations for Effection programs. This package wraps Node.js
fs/promises APIs as Effection Operations with structured concurrency support.
Installation
npm install @effectionx/fs
Basic Usage
import { main } from "effection";
import { exists, readTextFile, writeTextFile } from "@effectionx/fs";
await main(function* () {
if (yield* exists("./config.json")) {
const config = yield* readTextFile("./config.json");
console.log(JSON.parse(config));
} else {
yield* writeTextFile("./config.json", JSON.stringify({ version: 1 }));
}
});
File Operations
stat()
Get file or directory stats.
import { stat } from "@effectionx/fs";
const stats = yield* stat("./file.txt");
console.log(stats.isFile()); // true
console.log(stats.size); // file size in bytes
lstat()
Get file or directory stats without following symlinks.
import { lstat } from "@effectionx/fs";
const stats = yield* lstat("./symlink");
console.log(stats.isSymbolicLink()); // true
exists()
Check if a file or directory exists.
import { exists } from "@effectionx/fs";
if (yield* exists("./config.json")) {
console.log("Config file found");
}
readTextFile()
Read a file as text.
import { readTextFile } from "@effectionx/fs";
const content = yield* readTextFile("./README.md");
writeTextFile()
Write text to a file.
import { writeTextFile } from "@effectionx/fs";
yield* writeTextFile("./output.txt", "Hello, World!");
ensureFile()
Ensure a file exists, creating parent directories and the file if needed.
import { ensureFile } from "@effectionx/fs";
yield* ensureFile("./data/logs/app.log");
copyFile()
Copy a file.
import { copyFile } from "@effectionx/fs";
yield* copyFile("./source.txt", "./backup.txt");
rm()
Remove a file or directory.
import { rm } from "@effectionx/fs";
// Remove a file
yield* rm("./temp.txt");
// Remove a directory recursively
yield* rm("./temp", { recursive: true });
// Force remove (no error if doesn't exist)
yield* rm("./maybe-exists", { force: true });
Directory Operations
ensureDir()
Ensure a directory exists, creating it recursively if needed.
import { ensureDir } from "@effectionx/fs";
yield* ensureDir("./data/cache/images");
readdir()
Read the contents of a directory.
import { readdir } from "@effectionx/fs";
const entries = yield* readdir("./src");
console.log(entries); // ["index.ts", "utils.ts", ...]
emptyDir()
Empty a directory by removing all its contents. Creates the directory if it doesn't exist.
import { emptyDir } from "@effectionx/fs";
yield* emptyDir("./dist");
walk()
Walk a directory tree and yield entries as a Stream.
import { walk } from "@effectionx/fs";
import { each } from "effection";
for (const entry of yield* each(walk("./src"))) {
if (entry.isFile && entry.name.endsWith(".ts")) {
console.log(entry.path);
}
yield* each.next();
}
Each entry includes:
path- Full path to the entryname- Basename of the entryisFile- Whether it's a fileisDirectory- Whether it's a directoryisSymlink- Whether it's a symbolic link
Walk Options
walk("./src", {
includeDirs: true, // Include directories (default: true)
includeFiles: true, // Include files (default: true)
includeSymlinks: true, // Include symlinks (default: true)
match: [/\.ts$/], // Only include matching paths
skip: [/node_modules/], // Exclude matching paths
maxDepth: 3, // Maximum traversal depth
followSymlinks: false, // Follow symbolic links (default: false)
});
expandGlob()
Expand glob patterns and yield matching paths as a Stream.
import { expandGlob } from "@effectionx/fs";
import { each } from "effection";
for (const entry of yield* each(expandGlob("./src/**/*.ts"))) {
console.log(entry.path);
yield* each.next();
}
Glob Options
expandGlob("**/*.ts", {
root: "./src", // Root directory (default: ".")
exclude: ["**/*.test.ts"], // Patterns to exclude
includeDirs: false, // Include directories (default: true)
followSymlinks: false, // Follow symbolic links (default: false)
});
Utilities
toPath()
Convert a path or URL to a file path string.
import { toPath } from "@effectionx/fs";
toPath("./file.txt"); // "./file.txt"
toPath(new URL("file:///tmp")); // "/tmp"
globToRegExp()
Convert a glob pattern to a RegExp.
import { globToRegExp } from "@effectionx/fs";
const regex = globToRegExp("*.ts");
regex.test("file.ts"); // true
regex.test("file.js"); // false
// Supports extended glob syntax
globToRegExp("**/*.{ts,js}"); // Match .ts or .js files recursively
globToRegExp("file[0-9].txt"); // Character classes
globToRegExp("src/**/test?.ts"); // ? matches single character
URL Conversion
Re-exported from node:url for convenience:
import { fromFileUrl, toFileUrl } from "@effectionx/fs";
fromFileUrl(new URL("file:///tmp/file.txt")); // "/tmp/file.txt"
toFileUrl("/tmp/file.txt"); // URL { href: "file:///tmp/file.txt" }
Path and URL Support
All file operations accept either a string path or a URL object:
import { readTextFile } from "@effectionx/fs";
// String path
yield* readTextFile("./config.json");
// URL object
yield* readTextFile(new URL("file:///etc/config.json"));
// import.meta.url based paths
yield* readTextFile(new URL("./data.json", import.meta.url));
API Reference
Options for walk()
Properties
- includeDirsoptional: boolean
Include directories in results (default: true)
- includeFilesoptional: boolean
Include files in results (default: true)
- includeSymlinksoptional: boolean
Include symbolic links in results (default: true)
- matchoptional: RegExp[]
Only include entries matching these patterns
- skipoptional: RegExp[]
Exclude entries matching these patterns
- maxDepthoptional: number
Maximum depth to traverse (default: Infinity)
- followSymlinksoptional: boolean
Follow symbolic links (default: false)
Walk a directory tree and yield entries as a Stream
Examples
Example 1
import { walk } from "@effectionx/fs";
import { each } from "effection";
for (const entry of yield* each(walk("./src"))) {
if (entry.isFile && entry.name.endsWith(".ts")) {
console.log(entry.path);
}
yield* each.next();
}
Parameters
root: string | URL
Return Type
Stream<WalkEntry, void>
Expand glob patterns and yield matching paths as a Stream
Examples
Example 1
import { expandGlob } from "@effectionx/fs";
import { each } from "effection";
for (const entry of yield* each(expandGlob("./src/*.ts"))) {
console.log(entry.path);
yield* each.next();
}
Parameters
glob: string
Return Type
Stream<WalkEntry, void>