Pular para o conteúdo

File watching

Atualizado em Ver como Markdown

Monitor filesystem changes in real-time using Linux's native inotify system. The watch() method returns a Server-Sent Events (SSE) stream of file change events that you consume with parseSSEStream().

Methods

watch()

Watch a directory for filesystem changes. Returns an SSE stream of events.

const stream = await sandbox.watch(path: string, options?: WatchOptions): Promise<ReadableStream<Uint8Array>>

Parameters:

  • path - Absolute path or relative to /workspace (for example, /app/src or src)
  • options (optional):
    • recursive - Watch subdirectories recursively (default: true)
    • include - Glob patterns to include (for example, ['*.ts', '*.js']). Cannot be used together with exclude.
    • exclude - Glob patterns to exclude (default: ['.git', 'node_modules', '.DS_Store']). Cannot be used together with include.
    • sessionId - Session to run the watch in (if omittied, will use the default session unless enableDefaultSession is set to false)

Returns: Promise<ReadableStream<Uint8Array>> — an SSE stream of FileWatchSSEEvent objects

import { parseSSEStream } from "@cloudflare/sandbox";

const stream = await sandbox.watch("/workspace/src", {
	recursive: true,
	include: ["*.ts", "*.js"],
});

const controller = new AbortController();

for await (const event of parseSSEStream(stream, controller.signal)) {
	switch (event.type) {
		case "watching":
			console.log(`Watch established on ${event.path} (id: ${event.watchId})`);
			break;
		case "event":
			console.log(`${event.eventType}: ${event.path}`);
			break;
		case "error":
			console.error(`Watch error: ${event.error}`);
			break;
		case "stopped":
			console.log(`Watch stopped: ${event.reason}`);
			break;
	}
}

// Cancel the watch by aborting — cleans up the watcher server-side
controller.abort();
import { parseSSEStream } from "@cloudflare/sandbox";
import type { FileWatchSSEEvent } from "@cloudflare/sandbox";

const stream = await sandbox.watch("/workspace/src", {
	recursive: true,
	include: ["*.ts", "*.js"],
});

const controller = new AbortController();

for await (const event of parseSSEStream<FileWatchSSEEvent>(
	stream,
	controller.signal,
)) {
	switch (event.type) {
		case "watching":
			console.log(`Watch established on ${event.path} (id: ${event.watchId})`);
			break;
		case "event":
			console.log(`${event.eventType}: ${event.path}`);
			break;
		case "error":
			console.error(`Watch error: ${event.error}`);
			break;
		case "stopped":
			console.log(`Watch stopped: ${event.reason}`);
			break;
	}
}

// Cancel the watch by aborting — cleans up the watcher server-side
controller.abort();

Types

FileWatchSSEEvent

Union type of all SSE events emitted by the watch stream.

type FileWatchSSEEvent =
	| { type: "watching"; path: string; watchId: string }
	| {
			type: "event";
			eventType: FileWatchEventType;
			path: string;
			isDirectory: boolean;
			timestamp: string;
	  }
	| { type: "error"; error: string }
	| { type: "stopped"; reason: string };
  • watching — Emitted once when the watch is established. Contains the watchId and the path being watched.
  • event — Emitted for each filesystem change. Contains the eventType, the path that changed, and whether it isDirectory.
  • error — Emitted when the watch encounters an error.
  • stopped — Emitted when the watch is stopped, with a reason.

FileWatchEventType

Types of filesystem changes that can be detected.

type FileWatchEventType =
	| "create"
	| "modify"
	| "delete"
	| "move_from"
	| "move_to"
	| "attrib";
  • create — File or directory was created
  • modify — File content changed
  • delete — File or directory was deleted
  • move_from — File or directory was moved away (source of a rename/move)
  • move_to — File or directory was moved here (destination of a rename/move)
  • attrib — File or directory attributes changed (permissions, timestamps)

WatchOptions

Configuration options for watching directories.

interface WatchOptions {
	/** Watch subdirectories recursively (default: true) */
	recursive?: boolean;
	/** Glob patterns to include. Cannot be used together with `exclude`. */
	include?: string[];
	/** Glob patterns to exclude. Cannot be used together with `include`. Default: ['.git', 'node_modules', '.DS_Store'] */
	exclude?: string[];
	/** Session to run the watch in. If omitted, the sandbox's implicit execution mode is used. */
	sessionId?: string;
}

parseSSEStream()

Converts a ReadableStream<Uint8Array> into a typed AsyncGenerator of events. Accepts an optional AbortSignal to cancel the stream.

function parseSSEStream<T>(
	stream: ReadableStream<Uint8Array>,
	signal?: AbortSignal,
): AsyncGenerator<T>;

Parameters:

  • stream — The SSE stream returned by watch()
  • signal (optional) — An AbortSignal to cancel the stream. When aborted, the reader is cancelled which propagates cleanup to the server.

Aborting the signal is the recommended way to stop a watch from outside the consuming loop:

const controller = new AbortController();

// Cancel after 60 seconds
setTimeout(() => controller.abort(), 60_000);

for await (const event of parseSSEStream<FileWatchSSEEvent>(
	stream,
	controller.signal,
)) {
	// process events
}

Glob pattern support

The include and exclude options accept a limited set of glob tokens for predictable matching:

Token Meaning Example
* Match any characters within a path segment *.ts matches index.ts
** Match across directory boundaries **/*.test.ts
? Match a single character ?.js matches a.js

Character classes ([abc]), brace expansion ({a,b}), and backslash escapes are not supported. Patterns containing these tokens are rejected with a validation error.

Notes