Skip to content

Latest commit

 

History

History
295 lines (207 loc) · 4.97 KB

File metadata and controls

295 lines (207 loc) · 4.97 KB

runtime:fs API Reference

The runtime:fs module provides file system operations with capability-based access control.

Capabilities

File system access must be declared in manifest.app.toml:

[capabilities.fs]
read = ["~/.myapp/*", "./data/*"]
write = ["~/.myapp/*"]

Glob patterns supported:

  • * - matches any characters except /
  • ** - matches any characters including /
  • ~ - expands to user's home directory

Reading Files

readTextFile(path)

Read a file as UTF-8 text:

import { readTextFile } from "runtime:fs";

const content = await readTextFile("./config.json");
const config = JSON.parse(content);

readBytes(path)

Read a file as raw bytes:

import { readBytes } from "runtime:fs";

const data = await readBytes("./image.png");
// Returns: Uint8Array

Writing Files

writeTextFile(path, content)

Write UTF-8 text to a file:

import { writeTextFile } from "runtime:fs";

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

writeBytes(path, content)

Write raw bytes to a file:

import { writeBytes } from "runtime:fs";

const data = new Uint8Array([0x48, 0x65, 0x6c, 0x6c, 0x6f]);
await writeBytes("./binary.dat", data);

Directory Operations

readDir(path)

Read directory contents:

import { readDir } from "runtime:fs";

const entries = await readDir("./src");
for (const entry of entries) {
  console.log(entry.name, entry.is_file ? "file" : "dir");
}

Returns:

interface DirEntry {
  name: string;
  is_file: boolean;
  is_dir: boolean;
}

mkdir(path, options?)

Create a directory:

import { mkdir } from "runtime:fs";

// Create single directory
await mkdir("./output");

// Create nested directories
await mkdir("./path/to/nested", { recursive: true });

File Operations

stat(path)

Get file/directory information:

import { stat } from "runtime:fs";

const info = await stat("./file.txt");
console.log(info.size, info.is_file, info.readonly);

Returns:

interface FileStat {
  is_file: boolean;
  is_dir: boolean;
  size: number;
  readonly: boolean;
}

exists(path)

Check if a path exists:

import { exists } from "runtime:fs";

if (await exists("./config.json")) {
  // Load config
}

remove(path, options?)

Remove a file or directory:

import { remove } from "runtime:fs";

// Remove file
await remove("./temp.txt");

// Remove directory recursively
await remove("./cache", { recursive: true });

rename(from, to)

Rename or move a file/directory:

import { rename } from "runtime:fs";

await rename("./old-name.txt", "./new-name.txt");
await rename("./file.txt", "./archive/file.txt");

copy(from, to)

Copy a file:

import { copy } from "runtime:fs";

await copy("./source.txt", "./destination.txt");

File Watching

watch(path)

Watch a file or directory for changes:

import { watch } from "runtime:fs";

const watcher = await watch("./src");

// Using async iterator
for await (const event of watcher) {
  console.log(event.kind, event.paths);
}

// Using next() method
while (true) {
  const event = await watcher.next();
  if (!event) break;
  console.log(event);
}

// Clean up
await watcher.close();

Event shape:

interface FileEvent {
  kind: string;    // "create", "modify", "remove", etc.
  paths: string[]; // Affected paths
}

Watcher interface:

interface FileWatcher {
  id: string;
  next(): Promise<FileEvent | null>;
  [Symbol.asyncIterator](): AsyncIterableIterator<FileEvent>;
  close(): Promise<void>;
}

Error Handling

All operations throw on error:

import { readTextFile } from "runtime:fs";

try {
  const content = await readTextFile("./missing.txt");
} catch (error) {
  if (error.message.includes("not found")) {
    console.log("File does not exist");
  } else if (error.message.includes("permission")) {
    console.log("Access denied - check capabilities");
  }
}

Complete Example

import {
  readTextFile,
  writeTextFile,
  exists,
  mkdir,
  watch
} from "runtime:fs";
import { homeDir } from "runtime:sys";

// Config file path
const configPath = `${homeDir()}/.myapp/config.json`;

// Ensure directory exists
if (!await exists(`${homeDir()}/.myapp`)) {
  await mkdir(`${homeDir()}/.myapp`);
}

// Load or create config
let config;
if (await exists(configPath)) {
  const content = await readTextFile(configPath);
  config = JSON.parse(content);
} else {
  config = { theme: "dark", fontSize: 14 };
  await writeTextFile(configPath, JSON.stringify(config, null, 2));
}

// Watch for external changes
const watcher = await watch(configPath);
for await (const event of watcher) {
  if (event.kind === "modify") {
    const content = await readTextFile(configPath);
    config = JSON.parse(content);
    console.log("Config reloaded");
  }
}