Effection Logo
@effectionx/fsv0.2.0thefrontside/effectionx
NPM Badge with published version

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 entry
  • name - Basename of the entry
  • isFile - Whether it's a file
  • isDirectory - Whether it's a directory
  • isSymlink - 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

function toPath(pathOrUrl: string | URL): string

Convert a path or URL to a file path string

Parameters

pathOrUrl: string | URL

Return Type

string

function stat(pathOrUrl: string | URL): Operation<Stats>

Get file or directory stats

Examples

Example 1
import { stat } from "@effectionx/fs";

const stats = yield* stat("./file.txt");
console.log(stats.isFile());

Parameters

pathOrUrl: string | URL

Return Type

Operation<Stats>

function lstat(pathOrUrl: string | URL): Operation<Stats>

Get file or directory stats without following symlinks

Examples

Example 1
import { lstat } from "@effectionx/fs";

const stats = yield* lstat("./symlink");
console.log(stats.isSymbolicLink());

Parameters

pathOrUrl: string | URL

Return Type

Operation<Stats>

function* exists(pathOrUrl: string | URL): Operation<boolean>

Check if a file or directory exists

Examples

Example 1
import { exists } from "@effectionx/fs";

if (yield* exists("./config.json")) {
  console.log("Config file found");
}

Parameters

pathOrUrl: string | URL

Return Type

Operation<boolean>

function* ensureDir(pathOrUrl: string | URL): Operation<void>

Ensure a directory exists, creating it recursively if needed

Examples

Example 1
import { ensureDir } from "@effectionx/fs";

yield* ensureDir("./data/cache");

Parameters

pathOrUrl: string | URL

Return Type

Operation<void>

function* ensureFile(pathOrUrl: string | URL): Operation<void>

Ensure a file exists, creating parent directories and the file if needed

Examples

Example 1
import { ensureFile } from "@effectionx/fs";

yield* ensureFile("./data/config.json");

Parameters

pathOrUrl: string | URL

Return Type

Operation<void>

function readdir(pathOrUrl: string | URL): Operation<string[]>

Read the contents of a directory

Examples

Example 1
import { readdir } from "@effectionx/fs";

const entries = yield* readdir("./src");

Parameters

pathOrUrl: string | URL

Return Type

Operation<string[]>

function* emptyDir(pathOrUrl: string | URL): Operation<void>

Empty a directory by removing all its contents. Creates the directory if it doesn't exist.

Examples

Example 1
import { emptyDir } from "@effectionx/fs";

yield* emptyDir("./dist");

Parameters

pathOrUrl: string | URL

Return Type

Operation<void>

function rm(pathOrUrl: string | URL, options?: {}): Operation<void>

Remove a file or directory

Examples

Example 1
import { rm } from "@effectionx/fs";

yield* rm("./temp", { recursive: true });

Parameters

pathOrUrl: string | URL

optionsoptional: {}

Return Type

Operation<void>

function copyFile(src: string | URL, dest: string | URL): Operation<void>

Copy a file

Examples

Example 1
import { copyFile } from "@effectionx/fs";

yield* copyFile("./source.txt", "./dest.txt");

Parameters

src: string | URL

dest: string | URL

Return Type

Operation<void>

function readTextFile(pathOrUrl: string | URL): Operation<string>

Read a file as text

Examples

Example 1
import { readTextFile } from "@effectionx/fs";

const content = yield* readTextFile("./config.json");

Parameters

pathOrUrl: string | URL

Return Type

Operation<string>

function writeTextFile(pathOrUrl: string | URL, content: string): Operation<void>

Write text to a file

Examples

Example 1
import { writeTextFile } from "@effectionx/fs";

yield* writeTextFile("./output.txt", "Hello, World!");

Parameters

pathOrUrl: string | URL

content: string

Return Type

Operation<void>

interface WalkEntry

Entry returned by walk()

Properties

path: string

Full path to the entry

name: string

Name of the entry (basename)

isFile: boolean

Whether the entry is a file

isDirectory: boolean

Whether the entry is a directory

isSymlink: boolean

Whether the entry is a symbolic link

interface WalkOptions

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)

function walk(root: string | URL, options: WalkOptions = {}): Stream<WalkEntry, void>

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>

function expandGlob(glob: string, options: {} = {}): 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>

function globToRegExp(glob: string, options?: {}): RegExp

Convert a glob pattern to a RegExp

Examples

Example 1
import { globToRegExp } from "@effectionx/fs";

const regex = globToRegExp("*.ts");
console.log(regex.test("file.ts")); // true

Parameters

glob: string

optionsoptional: {}

Return Type

RegExp