/**
 * A WASI preview1 FILESYSTEM adapter over `RepackedSyncClient`.
 *
 * ## Why this file exists
 *
 * The broker gives a futex-parked thread synchronous access to ONE repacked store. A wasm engine does
 * not speak that API — it speaks `wasi_snapshot_preview1`, thirty-odd i32-returning imports over its
 * own linear memory. This module is the seam: every WASI file call a guest makes is translated into a
 * broker request, and the errno the broker already speaks (the protocol's numbers ARE WASI preview1
 * errnos) is handed straight back. Nothing here knows about pgwasm, OPFS, or any particular engine —
 * it needs a client, a way to reach the guest's memory, and nothing else.
 *
 * ## What it owns and what it refuses to touch
 *
 * The adapter owns fd `preopenFd` (3 by default — the "/" preopen) and every fd at or above `fdBase`
 * (4 by default). It NEVER touches fds 0–2: a host keeps its own stdin/stdout/stderr, and
 * {@link WasiPreview1Fs.compose} builds the merged import object that routes each call to whichever
 * side owns the fd. `owns()` is public so a host can make that decision itself.
 *
 * ## The fd table
 *
 * One entry per open descriptor, keyed by the WASI fd the guest sees:
 *
 *     { fd, path, isDir, clientFd, offset, fdflags, rightsBase, rightsInheriting, readable, writable }
 *
 * - `path` is the normalized absolute path the fd was opened with. It is kept for the whole life of
 *   the descriptor because the store resizes by PATH, not by descriptor: `fd_filestat_set_size` and
 *   `fd_allocate` resolve through it.
 * - `clientFd` is the broker's descriptor for a FILE. A DIRECTORY has none: the store cannot open a
 *   directory at all (its `open` answers `EISDIR`), so a directory fd is adapter-local — a remembered
 *   path plus a listing snapshot — and is still usable for `fd_readdir`, `fd_filestat_get`, `fd_sync`
 *   and as a dirfd for every path operation.
 * - `offset` is tracked HERE, not in the store. Every read and write the adapter issues carries an
 *   explicit position (the store's `pread`/`pwrite` form), so the store's own cursor is never used and
 *   `fd_seek`/`fd_tell` are exact even though several threads share one store.
 *
 * ## The mapping, decision by decision
 *
 * - **rights → access.** `RIGHTS_FD_READ` grants read, `RIGHTS_FD_WRITE` grants write; a request that
 *   asks for neither is read-only. That access is enforced by the BROKER (per its own fd) and again
 *   here, because a POSIX `open(O_RDONLY|O_CREAT)` has to open the store descriptor wider than the
 *   guest asked for — see below.
 * - **oflags → POSIX bits.** `CREAT`→`O_CREAT`, `EXCL`→`O_EXCL`, `TRUNC`→`O_TRUNC`, and the access
 *   mode from the rights. `planOpen` (server side) rejects `O_CREAT`/`O_TRUNC` without write access,
 *   so a create/truncate request always adds write to the POSIX access mode while the adapter keeps
 *   the NARROWER access the rights asked for and rejects a later `fd_write` with `ENOTCAPABLE`.
 * - **`O_DIRECTORY` and directories.** With `DIRECTORY` set the adapter never calls `open` (that would
 *   create a file); it stats and builds a directory fd. Without it, `open` is attempted and an
 *   `EISDIR` answer is recognised as "this is a directory" and turned into a directory fd too — which
 *   costs nothing on the common file path.
 * - **`O_APPEND` is emulated here, never passed to the broker.** An append write resolves end-of-file
 *   with `fstat` and then `pwrite`s there, so the adapter's own offset stays exact and
 *   `fd_fdstat_set_flags` can turn `APPEND` on and off on a descriptor that was not opened with it.
 * - **`fd_seek`.** `SET`/`CUR` are pure arithmetic on the adapter's offset; `END` resolves the size
 *   with `fstat` on the broker fd (never `size(path)`, which would race a rename).
 * - **`fd_readdir` cookies.** A cookie is an index into a listing SNAPSHOT taken on cookie 0, exactly
 *   as a POSIX `readdir` may. The snapshot is built out of `readdirPage` calls, and it exists for a
 *   protocol reason as much as a semantic one: the broker treats a cursor past the end of the listing
 *   as a protocol violation and DETACHES the client, so a stale cookie from a directory that shrank
 *   must never reach it. A cookie past the snapshot's end reports zero bytes used — end of directory.
 * - **truncate by path.** `fd_filestat_set_size` and `fd_allocate` call `truncate(path, size)` with
 *   the descriptor's remembered path. The store has no hard links, so nothing is lost.
 * - **`fd_sync`/`fd_datasync`.** Both map to the broker's `fsync`, whose durability is STORE-WIDE: on
 *   success every byte written through the broker by ANY client before the call returned is
 *   recoverable. That is stronger than `fd_sync` promises, never weaker.
 * - **symlinks.** The store HAS them, and `SYMLINK_FOLLOW` therefore means something everywhere it
 *   appears: `path_filestat_get` picks `stat` or `lstat`, and a `path_open` without it sends
 *   `O_NOFOLLOW` so a final component that IS a link answers `ELOOP` instead of opening its target.
 *   `path_unlink_file` removes the LINK, never the target — that is the core's `unlink`, not
 *   something added here. `path_symlink` writes a link and `path_readlink` reads one back, both
 *   verbatim: the store takes ABSOLUTE targets only (see `validateSymlinkTarget`), so a relative
 *   target is `EINVAL` rather than being silently reinterpreted, and an absolute one is a STORE
 *   path — which is the same thing as a guest path whenever the preopen is the store root, the
 *   default and the only arrangement a datadir uses. `path_link` remains `ENOTSUP`: the store has
 *   no hard links.
 * - **`fd_advise`** is a no-op success. **`fd_filestat_set_times`/`path_filestat_set_times`** answer
 *   `ENOTSUP`: the broker exposes no `utimes` opcode, and inventing an adapter-local timestamp would
 *   make two threads on ONE store disagree about a file's mtime, which is exactly what this whole
 *   arrangement exists to prevent.
 *
 * ## Failure discipline
 *
 * Every exported function is wrapped so that a JS exception can never leave it. A throw out of a WASI
 * import unwinds through the guest's nounwind frames and surfaces as a bare `RuntimeError:
 * unreachable` with no attribution at all; instead the wrapper reports `EIO` and hands the cause to
 * `onError` with the call name. A transport failure (the coordinator died, the client was detached) is
 * therefore an `EIO` the guest can act on rather than an abort it cannot.
 */
import type { RepackedSyncClient } from "../broker/client";
/**
 * WASI preview1 errno numbers. A superset of the store's own `FS_ERRNO` (whose values already ARE
 * these numbers); the extra codes are ones a filesystem ADAPTER has to answer and the store core
 * never produces, so they live here rather than widening the core's error vocabulary.
 */
export declare const WASI_ERRNO: {
    readonly SUCCESS: 0;
    readonly ACCES: 2;
    readonly BADF: 8;
    readonly EXIST: 20;
    readonly INVAL: 28;
    readonly IO: 29;
    readonly ISDIR: 31;
    readonly LOOP: 32;
    readonly NOENT: 44;
    readonly NOSYS: 52;
    readonly NOTDIR: 54;
    readonly NOTEMPTY: 55;
    readonly NOTSUP: 58;
    readonly OVERFLOW: 61;
    readonly PERM: 63;
    readonly SPIPE: 70;
    readonly NOTCAPABLE: 76;
};
/** WASI preview1 filetypes. */
export declare const WASI_FILETYPE: {
    readonly UNKNOWN: 0;
    readonly BLOCK_DEVICE: 1;
    readonly CHARACTER_DEVICE: 2;
    readonly DIRECTORY: 3;
    readonly REGULAR_FILE: 4;
    readonly SOCKET_DGRAM: 5;
    readonly SOCKET_STREAM: 6;
    readonly SYMBOLIC_LINK: 7;
};
/** `path_open` oflags. */
export declare const OFLAGS_CREAT = 1;
export declare const OFLAGS_DIRECTORY = 2;
export declare const OFLAGS_EXCL = 4;
export declare const OFLAGS_TRUNC = 8;
/** `fdflags`, on `path_open` and `fd_fdstat_set_flags`. */
export declare const FDFLAGS_APPEND = 1;
export declare const FDFLAGS_DSYNC = 2;
export declare const FDFLAGS_NONBLOCK = 4;
export declare const FDFLAGS_RSYNC = 8;
export declare const FDFLAGS_SYNC = 16;
/** `lookupflags`, on every path operation that could follow a symlink. */
export declare const LOOKUPFLAGS_SYMLINK_FOLLOW = 1;
/** The two rights the adapter reads; the rest are carried through untouched. */
export declare const RIGHTS_FD_READ: bigint;
export declare const RIGHTS_FD_WRITE: bigint;
/** What a preopen advertises when the host asked for nothing narrower. */
export declare const RIGHTS_ALL = 18446744073709551615n;
/** `fd_seek` whence values. */
export declare const WHENCE_SET = 0;
export declare const WHENCE_CUR = 1;
export declare const WHENCE_END = 2;
export interface WasiPreview1FsOptions {
    /** The synchronous broker client this adapter turns WASI calls into. */
    readonly client: RepackedSyncClient;
    /**
     * The guest's linear memory, resolved on EVERY call. A shared wasm memory grows underneath the host
     * and any cached `Uint8Array`/`DataView` goes stale (or detaches outright, for a non-shared one), so
     * nothing here holds a view across a call.
     */
    readonly memory: () => ArrayBuffer | SharedArrayBuffer;
    /** The fd the guest sees the preopened directory as. Defaults to 3, the WASI convention. */
    readonly preopenFd?: number;
    /** The directory that preopen names. Defaults to the store root. */
    readonly preopenPath?: string;
    /** The first fd the adapter hands out, and the bottom of the range it claims. Defaults to 4. */
    readonly fdBase?: number;
    /** The adapter's clock, in milliseconds. Defaults to the wall clock; used for diagnostics. */
    readonly now?: () => bigint;
    /** Where a JS exception that escaped a WASI call is reported. Defaults to `console.error`. */
    readonly onError?: (call: string, cause: unknown) => void;
}
/** The `wasi_snapshot_preview1` filesystem surface, with the ABI's exact signatures. */
export interface WasiPreview1FsFunctions {
    fd_prestat_get(fd: number, resultPtr: number): number;
    fd_prestat_dir_name(fd: number, pathPtr: number, pathLen: number): number;
    fd_close(fd: number): number;
    fd_read(fd: number, iovsPtr: number, iovsLen: number, nreadPtr: number): number;
    fd_pread(fd: number, iovsPtr: number, iovsLen: number, offset: bigint, nreadPtr: number): number;
    fd_write(fd: number, iovsPtr: number, iovsLen: number, nwrittenPtr: number): number;
    fd_pwrite(fd: number, iovsPtr: number, iovsLen: number, offset: bigint, nwrittenPtr: number): number;
    fd_seek(fd: number, offset: bigint, whence: number, resultPtr: number): number;
    fd_tell(fd: number, resultPtr: number): number;
    fd_fdstat_get(fd: number, resultPtr: number): number;
    fd_fdstat_set_flags(fd: number, fdflags: number): number;
    fd_fdstat_set_rights(fd: number, rightsBase: bigint, rightsInheriting: bigint): number;
    fd_filestat_get(fd: number, resultPtr: number): number;
    fd_filestat_set_size(fd: number, size: bigint): number;
    fd_filestat_set_times(fd: number, atim: bigint, mtim: bigint, fstflags: number): number;
    fd_readdir(fd: number, bufPtr: number, bufLen: number, cookie: bigint, bufusedPtr: number): number;
    fd_sync(fd: number): number;
    fd_datasync(fd: number): number;
    fd_allocate(fd: number, offset: bigint, length: bigint): number;
    fd_advise(fd: number, offset: bigint, length: bigint, advice: number): number;
    path_open(dirfd: number, dirflags: number, pathPtr: number, pathLen: number, oflags: number, rightsBase: bigint, rightsInheriting: bigint, fdflags: number, resultPtr: number): number;
    path_filestat_get(dirfd: number, flags: number, pathPtr: number, pathLen: number, resultPtr: number): number;
    path_filestat_set_times(dirfd: number, flags: number, pathPtr: number, pathLen: number, atim: bigint, mtim: bigint, fstflags: number): number;
    path_create_directory(dirfd: number, pathPtr: number, pathLen: number): number;
    path_remove_directory(dirfd: number, pathPtr: number, pathLen: number): number;
    path_unlink_file(dirfd: number, pathPtr: number, pathLen: number): number;
    path_rename(dirfd: number, oldPtr: number, oldLen: number, newDirfd: number, newPtr: number, newLen: number): number;
    path_readlink(dirfd: number, pathPtr: number, pathLen: number, bufPtr: number, bufLen: number, bufusedPtr: number): number;
    path_symlink(oldPtr: number, oldLen: number, dirfd: number, newPtr: number, newLen: number): number;
    path_link(oldDirfd: number, oldFlags: number, oldPtr: number, oldLen: number, newDirfd: number, newPtr: number, newLen: number): number;
}
/** The adapter: the WASI surface plus the three composition/lifecycle helpers a host needs. */
export interface WasiPreview1Fs extends WasiPreview1FsFunctions {
    /** Whether this adapter answers for `fd`: the preopen, or anything at or above `fdBase`. */
    owns(fd: number): boolean;
    /** How many descriptors the adapter currently holds, preopen excluded. */
    openFdCount(): number;
    /**
     * A merged `wasi_snapshot_preview1` object: every filesystem call goes to the adapter when the fd
     * (or the dirfd, for a path operation) is adapter-owned and to `base` otherwise. Everything in
     * `base` that is not a filesystem call — `args_get`, `clock_time_get`, `poll_oneoff`, `proc_exit`,
     * `random_get`, `sched_yield`, the socket stubs — is carried through untouched, as are `base`'s own
     * fd 0/1/2 handlers.
     */
    compose(base: Readonly<Record<string, unknown>>): Record<string, unknown>;
    /**
     * Close every descriptor, returning how many were released. The call a thread makes on its way out:
     * without it the coordinator holds the thread's store descriptors until the whole channel detaches.
     */
    closeAll(): number;
}
/**
 * Canonicalize a guest path the way the store demands: absolute, no `.`/`..`, no empty or repeated
 * separator, no trailing slash. Deliberately lenient in the same places a WASI host has to be —
 * wasi-libc hands preopen-RELATIVE paths, but an absolute one is accepted too, and a trailing NUL from
 * a fixed-size buffer is stripped rather than rejected.
 */
export declare function normalizeWasiPath(path: string): string;
export declare function createWasiPreview1Fs(options: WasiPreview1FsOptions): WasiPreview1Fs;
//# sourceMappingURL=preview1.d.ts.map