import type { Accessor } from '../../../accessor/base.ts'; import type { IndexCacheStore } from '../../../cache/index/store.ts'; import type { StatOverlay } from '../../../ops/types.ts'; import type { FindOptions } from '../../../resource/base.ts'; import { PathSpec, type CopyFn, type FindFn, type FileStat, type MoveFn, type ReadBytesFn, type ReadStreamFn, type ReaddirFn, type StatFn } from '../../../types.ts'; import type { ChildMounts } from '../../../ops/types.ts'; import type { DuEntries } from '../generic/du.ts'; import type { AggregateFn, CommandFnResult, CommandOpts, ProvisionFn } from '../../config.ts'; export type ReaddirOp = ReaddirFn<[ accessor: A, path: PathSpec, index?: IndexCacheStore ]>; type ReadBytesOp = ReadBytesFn<[ accessor: A, path: PathSpec, index?: IndexCacheStore ]>; type ReadStreamOp = ReadStreamFn<[ accessor: A, path: PathSpec, index?: IndexCacheStore ]>; export type StatOp = StatFn<[ accessor: A, path: PathSpec, index?: IndexCacheStore ]>; type WriteOp = (accessor: A, path: PathSpec, data: Uint8Array) => Promise; type ExistsOp = (accessor: A, path: PathSpec) => Promise; type PathOp = (accessor: A, path: PathSpec) => Promise; type RmdirOp = (accessor: A, path: PathSpec, index?: IndexCacheStore) => Promise; type MkdirOp = (accessor: A, path: PathSpec, parents?: boolean) => Promise; type RenameOp = MoveFn<[accessor: A, src: PathSpec, dst: PathSpec]>; type CopyOp = CopyFn<[accessor: A, src: PathSpec, dst: PathSpec]>; type FindOp = FindFn<[ accessor: A, path: PathSpec, options: FindOptions ]>; type DuSizeOp = (accessor: A, path: PathSpec, index?: IndexCacheStore) => Promise; type DuEntriesOp = (accessor: A, path: PathSpec, index?: IndexCacheStore) => Promise; export type ResolveGlobOp = (accessor: A, paths: readonly PathSpec[], index?: IndexCacheStore) => Promise; export declare function makeResolveGlob(readdir: ReaddirOp, maxGlobMatches?: number, children?: ChildMounts): ResolveGlobOp; export interface DuOps { size: DuSizeOp; entries: DuEntriesOp; } export interface CommandIO { readdir: ReaddirOp; readBytes: ReadBytesOp; readRange?: (accessor: A, path: PathSpec, index: IndexCacheStore | undefined, offset: number, size: number | null) => Promise; readStream: ReadStreamOp; stat: StatOp; isMounted: (accessor: A) => boolean; local?: boolean; maxGlobMatches?: number; write?: WriteOp; exists?: ExistsOp; mkdir?: MkdirOp; unlink?: PathOp; rmdir?: RmdirOp; rmR?: PathOp; rename?: RenameOp; copy?: CopyOp; dirCopy?: CopyOp; create?: PathOp; truncate?: (accessor: A, path: PathSpec, length: number) => Promise; find?: FindOp; du?: DuOps; maxDuEntries?: number; append?: (accessor: A, path: PathSpec, data: Uint8Array) => Promise; setAttrs?: (...args: any[]) => unknown; globChildren?: ChildMounts; } export declare function resolveGlobOf(ops: CommandIO): ResolveGlobOp; /** Refuse a relocation that would surface a hidden path. * * A rename or a native directory copy re-anchors everything below its * source, and a hide's coverage does not move with the content, so * hidden bytes would land at paths the session can see. EACCES on the * source, which mv and cp render in GNU's permission-denied voice. * Only a directory has anything below it to re-anchor, so callers * check this for a source they know is a directory and skip it for a * file. */ export declare function refuseReveal(src: PathSpec, dst: PathSpec): void; /** * Return `ops` whose slots refuse hidden paths like missing ones. * * The commands factory hands this copy to every generic command, the * same shape as `withReadCache`, so hidden-path enforcement lands once * for the whole command tier (resolveGlobOf derives from the wrapped * readdir). The backends' own IO constants stay raw: the ops tables * built from them serve the dispatcher, which enforces hiding itself * at the door. The guards read the current session at call time, so * one wrapped copy is shared across sessions. */ export declare function withHiddenGuard(ops: CommandIO): CommandIO; /** * Return `ops` whose content and mutation slots ask the admitted * command's gate before touching a path. * * The rule arms' counterpart of `withHiddenGuard`, wrapped inside it so * a hidden path still answers ENOENT before any rule can name it. The * gate judged the line's operands; this is how a walk (`grep -r`, `find`, * `du`, `cp -r`, `tar`) is held to the same rules on the entries it * reaches below them. `stat` and `exists` stay unguarded, because deny * means present and refused, not absent: a listing shows a refused * entry's name and size, and the read of it is what fails, as GNU reports * an unreadable file. `readdir` asks about the directory being listed, * never filters its names. A backend's native `find`/`du` are not * wrapped: the builders route to the readdir walk while a path rule * scopes the command (`pathRulesActive`), so every entry passes through * here. */ export declare function withRuleGuard(ops: CommandIO): CommandIO; /** * Return `ops` whose mutation slots hold each written path to its * region's effective mode. * * The per-path half of the mount's write gate, innermost of the three * guards: hides answer ENOENT first, rules refuse next, and only a path * both leave standing is judged for its mode, the same order the op * door applies. Reads are never wrapped, because `READ` allows them * everywhere the other guards do; a copy's source is a read too, so * only its destination answers, while a rename mutates both endpoints. */ export declare function withModeGuard(ops: CommandIO): CommandIO; /** * Return `ops` under the whole path axis: hides answer ENOENT first, * rules refuse next, the mode speaks last. * * The one spelling of the guard chain, used by the commands factory * for every generic command and by a bespoke command family that * consumes a `CommandIO` directly (the object-store overrides), so an * override enforces the session's path axis exactly like the generic * it replaces. */ export declare function withPathGuards(ops: CommandIO): CommandIO; /** * Return `ops` whose content and mutation slots admit each PathSpec * through the workspace's coded preOps hooks. * * The coded-policy arm of the guard chain, applied outside the cache * wraps so admission fires before a warm serve, the dispatcher's own * order. The surface is the rule guard's plus readdir: content reads * (readBytes, readStream, readRange), every mutation slot, and the * directory a readdir lists. stat/exists and the native find/du slots * stay unguarded as presence facts, the mode-000 shape the rule guard * already states, so a denied entry still lists and stats while the * read of it is what fails. Inert unless a dispatched command bound * policies overriding preOps (`opPolicyScope`, with the mount prefix * and session identity captured at wrap time so a lazily drained * reader still answers as the command that bound it, see * `livePolicyScope`; `prefix` arrives from the wrap site because the * fallback mount-gate storage resolves by path, which a drained * reader no longer has a live gate for). */ export declare function withPolicyGuard(ops: CommandIO, prefix?: string): CommandIO; /** * Guard one bare backend write the way the adapter guards a slot. * * For a bespoke command wired from loose functions rather than a * `CommandIO` (the google `rm` family binds an index-threaded unlink): * the same chain in the same order, judging the written path. A hidden * path answers ENOENT, the flavor of the flat mutation slots. The * policy arm rides outermost, as it does on the slot chain, and reads * the live context (this wrap happens at registration, its handlers * are eager). */ export declare function withWriteGuards(fn: (accessor: A, path: PathSpec, index?: IndexCacheStore) => Promise | R): (accessor: A, path: PathSpec, index?: IndexCacheStore) => Promise; /** * A `readRange` slot built from a backend read that already takes a byte * window as its options argument. * * Without the slot the ops factory reads the whole object and slices, so * `head -c 100` on a 2 GiB S3 key downloads 2 GiB. Python has pushed the * window down on every one of these backends since the slot existed by * pointing `read_range` at its own `read_bytes`; this is the same move, * spelled for a read whose window arrives in an options object. * * Args: * read: the backend's whole-file read, whose fourth argument is an * `{offset?, size?}` window. */ export declare function rangeOf(read: (accessor: A, path: PathSpec, index: IndexCacheStore | undefined, options: { offset?: number; size?: number; }) => Promise): NonNullable['readRange']>; export declare function dirAwareStat(ops: CommandIO, accessor: A, opts: CommandOpts): (p: PathSpec) => Promise; export declare function overlaidStat(stat: (p: PathSpec) => Promise, overlay: StatOverlay | undefined): (p: PathSpec) => Promise; export declare function requireOp(op: T | undefined, name: string): T; /** * Return `ops` whose reads refuse a directory with GNU's EISDIR. * * The read family's counterpart of `withHiddenGuard` and * `withSlashGuard`: reading a directory is never a legitimate call, so * the refusal belongs to the slot rather than to each builder's wiring. * It used to belong to the wiring, and 23 of the read builders passed the * raw `ops.readStream` instead, so a directory on a keyed backend * reported ENOENT. * * Refined after the failure, never before it, so a read that succeeds * costs exactly what it did. The refusal is built from the operand's own * PathSpec, so it carries the virtual path: a raw disk error names the * host path, which is the mount's own business and must not reach a * user-facing line. * * Mirrors the Python `with_dir_guard`. */ export declare function withDirGuard(ops: CommandIO): CommandIO; export declare function dirAwareStream(ops: CommandIO, accessor: A, opts: CommandOpts): (p: PathSpec) => AsyncIterable; export type BuilderFn = (ops: CommandIO, accessor: A, paths: PathSpec[], texts: string[], opts: CommandOpts) => Promise | CommandFnResult; export type Operation = 'write' | 'exists' | 'mkdir' | 'unlink' | 'rmdir' | 'rename' | 'copy' | 'truncate'; export declare function supports(ops: CommandIO, requirements: readonly Operation[]): boolean; export interface Builder { name: string; fn: BuilderFn; provision?: (stat: StatOp) => ProvisionFn; write?: boolean; aggregate?: AggregateFn; read?: boolean; /** * Backend ops the command cannot run without. A backend missing any of * them does not get the command registered at all, rather than getting a * command that throws on every invocation. `write: true` is not enough on * its own: rmdir needs `rmdir`, truncate needs `truncate`, and a backend * can have `write` without either. */ requirements?: readonly Operation[]; } export {}; //# sourceMappingURL=adapter.d.ts.map