UNPKG

@struktoai/mirage-core

Version:

A Unified Virtual Filesystem For AI Agents

68 lines • 4.29 kB
import { type RewriteWriteFn } from '../../cache/types.ts'; import { type PathSpec, type StatFn } from '../../types.ts'; import { ByteSpool } from '../../io/spool.ts'; import type { ByteSource } from '../../io/types.ts'; export type ReadFn = (path: PathSpec) => Promise<Uint8Array>; export type WriteFn<Written = unknown> = RewriteWriteFn<Written>; /** * Append by reading the file and writing it back whole. * * Not atomic against a concurrent writer. A zero-byte append is an open for * appending with nothing written after it (`cmd >> f` opens `f` before `cmd` * runs): it creates a missing file and leaves an existing one alone, so it * costs a stat rather than moving the whole object twice to add nothing, and * cannot put back bytes a concurrent writer had just replaced. The read takes * the caller's index, as every other read does: an id-addressed backend (Box, * Drive) turns a path into an id through it. Mirrors Python's * `append_by_rewrite`. */ export declare function appendByRewrite<Written>(read: ReadFn, write: RewriteWriteFn<Written>, stat: StatFn, path: PathSpec, data: Uint8Array): Promise<Written | undefined>; /** * Stage a read-modify-write with bounded RAM and the read's version. The new * bytes are spooled before the file is read: a streamed write lets its path * go while its source is pulled, so a write landing meanwhile is in the file * the replacement is made from. */ export declare function appendByStreamedRewrite<Written>(read: (path: PathSpec, onVersion: (version: string | null) => void) => AsyncIterable<Uint8Array>, write: RewriteWriteFn<Written>, stat: StatFn, path: PathSpec, data: ByteSource): Promise<Written | undefined>; /** * Write at an offset by spooling the file and writing it back whole, its * head, the new bytes and its tail streamed, so memory holds a chunk at a * time whatever the sizes. The new bytes are spooled before the file is * read: a streamed write lets its path go while its source is pulled, so a * write landing meanwhile is in the file the replacement is made from. * * A zero-length pwrite(2) on an existing file changes nothing and must not * read the file back: a concurrent writer's update between the stat and a * write would be clobbered by the stale contents. On a missing file it * creates an empty one. A key store answers a read of a directory's name as * a missing key, so a read that misses is checked against stat before * writing: writing there would put an object beside the directory. `read` * fills a spool with the whole file and answers the version the read * carried. Mirrors Python's `pwrite_by_streamed_rewrite`. */ export declare function pwriteByStreamedRewrite(read: (path: PathSpec, spool: ByteSpool) => Promise<string | null>, write: RewriteWriteFn<unknown>, stat: StatFn, path: PathSpec, data: ByteSource, offset: number): Promise<void>; /** * Resize by reading the file and writing it back padded or cut. * * For a store with no partial write. It cannot hold `noCreate` atomically, * so it refuses that before writing anything, as it does a negative length * (EINVAL). Emptying reads nothing, so its * write carries the version the agent read. Mirrors Python's * `truncate_by_rewrite`. */ export declare function truncateByRewrite(read: ReadFn, write: RewriteWriteFn<unknown>, path: PathSpec, length: number, noCreate: boolean): Promise<void>; /** A pwrite offset, refused with EINVAL when negative. Mirrors Python's `expect_offset`. */ export declare function expectOffset(offset: number, path: PathSpec): number; /** * Refuse a mkdir of a name that is taken, as mkdir(2) does. * * mkdir(2) refuses a name that exists, file or directory, and `mkdir -p` * passes only a directory. Not every backend's create says so (a Graph 409 * on a folder, Nextcloud's MKCOL 405, SFTP under `-p`), so both callers look * the name up before the create. A directory under `-p` still reaches the * create, which keeps it durable (an object store writes the marker of a * directory only a key implied), and a name that cannot be looked up is left * to it too, to answer ENOENT or ENOTDIR. Mirrors Python's `refuse_taken`. */ export declare function refuseTaken(stat: StatFn, path: PathSpec, parents: boolean): Promise<void>; //# sourceMappingURL=rewrite.d.ts.map