@struktoai/mirage-core
Version:
A Unified Virtual Filesystem For AI Agents
68 lines • 4.29 kB
TypeScript
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