> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ooneex.com/llms.txt
> Use this file to discover all available pages before exploring further.

# File System

> Async, type-safe utilities for reading, writing, copying, streaming, and watching files and directories on Bun.

`@ooneex/fs` wraps Bun's optimized file I/O behind two ergonomic classes, `File` and `Directory`. Every operation is async, returns rich objects instead of raw paths, and throws typed exceptions (`FileException`, `DirectoryException`) carrying a status code and contextual data when something goes wrong.

## Installation

Add the package with Bun:

```bash theme={null}
bun add @ooneex/fs
```

## Usage

Create a `File` from a path or URL, then read, write, or inspect it.

```typescript theme={null}
import { File } from "@ooneex/fs";

const file = new File("/path/to/config.json");

if (await file.exists()) {
  // Read in different shapes
  const raw = await file.text();
  const config = await file.json<{ name: string; version: number }>();
  const bytes = await file.bytes();

  // Metadata
  console.log(file.getName());      // "config.json"
  console.log(file.getExtension()); // "json"
  console.log(file.getSize());      // size in bytes
}

// Write, append, copy, delete
await file.write("Hello, World!");
await file.append("\nmore content");
const backup = await file.copy("/path/to/config.backup.json");
await backup.delete();
```

### Streaming large files

Iterate over a file incrementally instead of loading it all into memory. `streamAsJson` reads a JSON array file and yields each element one at a time.

```typescript theme={null}
import { File } from "@ooneex/fs";

const file = new File("/path/to/large-data.json");

for await (const item of file.streamAsJson<{ id: number }>()) {
  console.log(item.id);
}

// Or stream raw chunks / decoded text
const log = new File("/path/to/app.log");
for await (const line of log.streamAsText()) {
  process.stdout.write(line);
}
```

### Downloading and buffered writing

```typescript theme={null}
import { File } from "@ooneex/fs";

// Download a remote file to disk
const downloaded = await File.download("https://example.com/data.zip", "/tmp/data.zip");

// Buffered (incremental) writes via a FileSink
const out = new File("/tmp/output.txt");
const writer = out.writer();
writer.write("Line 1\n");
writer.write("Line 2\n");
writer.end(); // flush and close
```

### Working with directories

`Directory` mirrors common shell operations and exposes async generators for traversal.

```typescript theme={null}
import { Directory } from "@ooneex/fs";

const dir = new Directory("/path/to/project");

await dir.mkdir();                       // recursive by default
const names = await dir.ls({ recursive: true });
const totalBytes = await dir.getSize();

// Navigate fluently
const srcDir = dir.cd("src", "components");

// Iterate only files matching a pattern
for await (const file of srcDir.getFiles({ recursive: true, pattern: /\.ts$/ })) {
  console.log(file.getPath());
}

// Copy, move, clean up
await dir.cp("/path/to/copy", { overwrite: true });
if (await dir.isEmpty()) {
  await dir.rm({ force: true });
}

// Watch for changes
const watcher = dir.watch((event, filename) => {
  console.log(`${event}: ${filename}`);
}, { recursive: true });
// watcher.close();
```

## When to use it

* You are building on Bun and want a clean, object-oriented wrapper around its file APIs.
* You need typed, descriptive errors (`FileException` / `DirectoryException`) with status codes and context instead of raw `errno` failures.
* You process large files and want generator-based streaming (`stream`, `streamAsText`, `streamAsJson`).
* You traverse, filter, copy, move, or watch directory trees and want `File`/`Directory` objects rather than bare strings.
* Skip it for trivial one-off reads where `Bun.file(...).text()` is enough, or in non-Bun runtimes (the package targets Bun's I/O).
