/*********************** * Runtime identifier for platform-specific code paths ***********************/ import type { NodeWebSocketServerProvider } from "veryfront/extensions/websocket"; export type RuntimeId = "deno" | "node" | "bun" | "cloudflare" | "memory"; /** * Core runtime adapter interface * * Provides a unified abstraction over runtime-specific APIs (Deno, Node.js, Bun, Cloudflare Workers). * All platform-specific code should go through this adapter to ensure cross-platform compatibility. */ export interface RuntimeAdapter { /** Unique identifier for this runtime */ readonly id: RuntimeId; /** Human-readable name for logging */ readonly name: string; /** Runtime capabilities for feature detection */ readonly capabilities: RuntimeCapabilities; /** Filesystem operations */ fs: FileSystemAdapter; /** Environment variable access */ env: EnvironmentAdapter; /** HTTP server operations */ server: ServerAdapter; serve(handler: (request: Request) => Promise | Response, options: ServeOptions): Promise; /** Shell operations (sync fs for CLI) */ shell?: ShellAdapter; /** Key-value store (Cloudflare KV, Deno KV) */ kv?: KVStoreAdapter; /** File watcher (not available on Workers) */ watcher?: FileWatcherAdapter; /** Initialize the adapter (called once before first use) */ initialize?(): Promise; /** Clean shutdown (close connections, etc.) */ shutdown?(): Promise; } /** * Runtime capabilities for feature detection */ export interface RuntimeCapabilities { /** Native TypeScript support without compilation */ typescript: boolean; /** Native JSX/TSX support */ jsx: boolean; /** HTTP/2 server support */ http2: boolean; /** WebSocket support */ websocket: boolean; /** Web Workers / Worker threads support */ workers: boolean; /** File system watching */ fileWatching: boolean; /** Shell command execution */ shell: boolean; /** Key-value store available */ kvStore: boolean; /** Writable filesystem (false for Workers without KV) */ writableFs: boolean; } export interface WebSocketUpgradeOptions { protocol?: string; headers?: Headers | Record; idleTimeout?: number; } export interface ServerAdapter { upgradeWebSocket(request: Request, options?: WebSocketUpgradeOptions): WebSocketUpgrade; } export interface WebSocketConnection { readonly readyState: number; send(data: string | ArrayBuffer): void; close(code?: number, reason?: string): void; addEventListener(type: string, listener: EventListener, options?: AddEventListenerOptions): void; removeEventListener(type: string, listener: EventListener): void; } declare const WEBSOCKET_UPGRADE_RESPONSE_KIND = "websocket-upgrade"; /** * Explicit upgrade signal used when a runtime cannot construct a native * `Response` with status 101. */ export interface WebSocketUpgradeResponse { readonly kind: typeof WEBSOCKET_UPGRADE_RESPONSE_KIND; readonly status: 101; readonly statusText: string; readonly headers: Headers; readonly body: null; } export interface WebSocketUpgrade { socket: WebSocketConnection; response: Response | WebSocketUpgradeResponse; } export declare function createWebSocketUpgradeResponse(input?: { headers?: HeadersInit; statusText?: string; }): WebSocketUpgradeResponse; export declare function isWebSocketUpgradeResponse(value: unknown): value is WebSocketUpgradeResponse; export interface ServeOptions { port?: number; hostname?: string; signal?: AbortSignal; onListen?: (params: { hostname: string; port: number; }) => void; /** * Node.js only. Called synchronously for each raw HTTP listener `error` event * emitted after `onListen` returns. Returned promises are observed only for * rejection and are not awaited by the listener or shutdown. */ onRuntimeError?: (error: Error) => void | Promise; /** * Node.js only. Explicitly selected implementation for completing approved * WebSocket upgrades. When absent, HTTP serving remains available and every * Node WebSocket upgrade fails closed. */ nodeWebSocketServerProvider?: Readonly; } export interface Server { stop(): Promise; addr: { hostname: string; port: number; }; } export interface FileSystemAdapter { /** * Explicitly declares that paths in this adapter cannot traverse symbolic * links. The backing store may reject links or expose them only as inert * entries, but it must never resolve a path through one. Native/local * adapters must omit this marker and provide lstat and realPath instead. */ readonly symlinkSemantics?: "none"; /** Adapter is immutably bound to one project and needs no request scope. */ readonly projectContextSemantics?: "fixed"; readFile(path: string): Promise; /** Read raw bytes when binary-safe access is required */ readFileBytes?(path: string): Promise; /** * Fixed whole-object ceiling enforced by the backing store or transport * before a complete response can be materialized. * * This capability is distinct from `readFileBytesBounded`: the caller does * not choose the read size, and the implementation may materialize up to * this advertised ceiling even for a smaller file. It may be advertised * only alongside `readFileBytes` and only when the upstream boundary itself * rejects larger objects before returning them. */ readonly maxWholeFileReadBytes?: number; /** * Read a prefix without materializing more than `byteLimit` bytes. * * Implementations must enforce the limit while reading from their backing * store and continue until EOF or `byteLimit`; reading the complete object * and slicing afterward does not satisfy this capability. Callers can * request their accepted maximum plus one byte to distinguish an exact-size * file from an oversized file. Non-native adapters used for bounded Skill * discovery or strict Skill runtime reads must implement this capability. */ readFileBytesBounded?(path: string, byteLimit: number): Promise; /** * Read the complete file only when it is no larger than `byteLimit`. * * Implementations must enforce the limit while reading and reject when the * source has even one additional byte. They must not implement this by * materializing the whole object or by retaining a `byteLimit + 1` prefix. * Oversized sources reject with `RangeError`; other I/O failures propagate. */ readFileBytesWithinLimit?(path: string, byteLimit: number): Promise; /** * Read one stable file snapshot beneath `containmentRoot` without following * links and only when its complete contents fit within `byteLimit`. */ readFileSnapshotWithinLimit?(path: string, containmentRoot: string, byteLimit: number): Promise; writeFile(path: string, content: string): Promise; /** Write raw bytes when binary-safe output is required. */ writeFileBytes?(path: string, content: Uint8Array): Promise; /** Create a new byte file without replacing an existing path. */ createFileBytesExclusive?(path: string, content: Uint8Array): Promise; /** Atomically replace a path when the runtime supports same-filesystem rename. */ rename?(from: string, to: string): Promise; exists(path: string): Promise; readDir(path: string): AsyncIterable; stat(path: string): Promise; /** * Stat a path WITHOUT following a terminal symlink (lstat semantics). * Unlike stat(), which follows symlinks and therefore always reports * isSymlink:false for a link, this reports isSymlink:true for the link * itself. Used by path validation to detect symlink escapes. Optional: * virtual/remote filesystems that have no OS-level symlinks may omit it. */ lstat?(path: string): Promise; /** * Resolve a path to its canonical physical form, following all symlinks. * Used by path validation to check containment against the real target so a * symlink whose target escapes the base directory can be rejected. Throws if * the path does not exist. Optional: virtual/remote filesystems that have no * OS-level symlinks may omit it. */ realPath?(path: string): Promise; mkdir(path: string, options?: { recursive?: boolean; }): Promise; remove(path: string, options?: { recursive?: boolean; }): Promise; makeTempDir(prefix: string): Promise; watch(paths: string | string[], options?: WatchOptions): FileWatcher; /** Resolve a file path with extension fallback (e.g., pages/test → pages/test.mdx) */ resolveFile?(basePath: string, options?: ResolveFileOptions): Promise; /** Refresh remote source snapshots when a preview render detects stale cached content. */ refreshSourceSnapshot?(reason?: string): Promise; /** * Confirm that a mutable remote source snapshot is within its freshness * lease, coalescing the network check across concurrent requests. */ ensureSourceSnapshotFresh?(reason?: string): Promise; /** * Monotonic generation for the active source snapshot. Consumers can retain * derived state while this value is unchanged. */ getSourceSnapshotVersion?(): number | undefined | Promise; } /** A filesystem adapter that advertises genuine bounded byte reads. */ export type BoundedFileSystemAdapter = FileSystemAdapter & Required>; /** A filesystem adapter that can return only complete, size-admitted files. */ export type ExactBoundedFileSystemAdapter = FileSystemAdapter & Required>; export interface ResolveFileOptions { allowPagesPrefix?: boolean; } export interface DirEntry { name: string; isFile: boolean; isDirectory: boolean; isSymlink: boolean; } export interface FileInfo { size: number; isFile: boolean; isDirectory: boolean; isSymlink: boolean; mtime: Date | null; } export interface EnvironmentAdapter { get(key: string): string | undefined; set(key: string, value: string): void; toObject(): Record; } export interface WatchOptions { recursive?: boolean; signal?: AbortSignal; } export type FileChangeKind = "create" | "modify" | "delete" | "any"; export interface FileChangeEvent { kind: FileChangeKind; paths: string[]; } export interface FileWatcher extends AsyncIterable { close(): void; /** * Resolves once the underlying watcher has been installed and can observe * subsequent filesystem changes. Rejects when any requested watch root * cannot be acquired; callers must not advertise watching before it resolves. */ ready?: Promise; /** * Resolves once the watcher's internal loop has fully stopped, including * any in-flight filesystem operations. close() only signals shutdown; * await this to guarantee no pending async ops remain (e.g. before test * sanitizer checks or process exit). Rejects when the native watcher fails * or teardown cannot complete cleanly. */ done?: Promise; } export interface ShellAdapter { statSync(path: string): { isFile: boolean; isDirectory: boolean; }; readFileSync(path: string): string; } /** * Key-value store adapter for Cloudflare KV, Deno KV, etc. */ export interface KVStoreAdapter { get(key: string): Promise; set(key: string, value: string, options?: { expirationTtl?: number; }): Promise; delete(key: string): Promise; list(prefix?: string): AsyncIterable; } /** * File watcher adapter for development mode */ export interface FileWatcherAdapter { watch(paths: string | string[], options?: WatchOptions): FileWatcher; } export {}; //# sourceMappingURL=base.d.ts.map