import type { BaseVFS } from '../../../vfs/base.ts';
import { FileStat, type Limit, type MountMode, type PathSpec, type Visibility } from '../../../types.ts';
import type { MountEntry } from '../mount.ts';
import type { NamespaceStore, NodeFields } from './store.ts';
import type { RecordFields } from '../../record/types.ts';
import type { MountRegistry } from '../registry.ts';
import { type Clock } from '../../../utils/clock.ts';
import { NamespaceReader } from '../../dispatcher/reader.ts';
import type { SessionState } from '../../session/session.ts';
import type { MemoryBudget } from '../../../io/memory.ts';
import type { NetworkRule } from '../../../io/network.ts';
export type ResolveFn = (path: string) => Promise<[BaseVFS, PathSpec, MountMode]>;
export interface NodeMeta {
    target?: string;
    mtime?: number;
    mode?: number;
    uid?: number | string;
    gid?: number | string;
    atime?: string;
    observedMtime?: number;
    xattrs?: Map<string, Uint8Array>;
}
export interface SetAttrsFields {
    mode?: number;
    uid?: number | string;
    gid?: number | string;
    atime?: string;
    mtime?: number;
}
export declare function metaToFields(meta: NodeMeta): NodeFields;
export declare function metaFromFields(fields: RecordFields): NodeMeta;
export declare class Namespace {
    private readonly registry;
    private readonly resolveFn;
    private readonly store;
    private nodeTable;
    private links;
    private loaded;
    private loading;
    constructor(registry: MountRegistry, resolveFn: ResolveFn, store?: NamespaceStore);
    get nodes(): Map<string, NodeMeta>;
    /** The workspace clock, which the dispatcher records a call outside a line on. */
    get clock(): Clock;
    ensureLoaded(): Promise<void>;
    replaceNodes(entries: Map<string, NodeMeta>): Promise<void>;
    close(): Promise<void>;
    symlinkTargets(): ReadonlyMap<string, string>;
    isLink(path: string): boolean;
    readlink(path: string): string | null;
    symlink(link: string, target: string, mtime: number): Promise<void>;
    metaFor(path: string): NodeMeta | null;
    setAttrs(path: string, fields: SetAttrsFields): Promise<void>;
    xattrs(path: string): Map<string, Uint8Array>;
    setXattr(path: string, name: string, value: Uint8Array): Promise<void>;
    removeXattr(path: string, name: string): Promise<void>;
    dropAttrs(path: string, fields: readonly string[]): Promise<void>;
    dropOverlay(path: string): Promise<boolean>;
    dropOverlaysUnder(paths: readonly string[], excluded?: readonly string[]): Promise<number>;
    clearTimes(path: string, observed?: number | null): Promise<void>;
    unlink(path: string): Promise<boolean>;
    unlinkGlob(pattern: string, keep?: ReadonlySet<string>): Promise<number>;
    rename(src: string, dst: string): Promise<boolean>;
    follow(path: string): string;
    followParent(path: string): string;
    linkStatAt(path: string): FileStat | null;
    linkStatsBelow(directory: string): [string, FileStat][];
    linkNamesUnder(directory: string): Set<string>;
    private linksUnder;
    /**
     * Re-anchor every node below one directory onto another.
     *
     * A rename moves a whole subtree, and the node table addresses its entries by
     * absolute path, so a link or an attr overlay below the source names a path
     * that no longer exists once the backend has moved the bytes. No backend can
     * report those entries, which is why nothing below the dispatcher can do this.
     * Entries in a mount below stay, as purgeUnder keeps them: the mount stays
     * where it is, so its links and overlays are still its own, whenever it was
     * mounted. Mirrors Python's `rename_under`.
     */
    renameUnder(src: string, dst: string): Promise<number>;
    purgeUnder(directory: string, keep?: ReadonlySet<string>): Promise<number>;
    resolve(path: string, follow?: boolean): Promise<[BaseVFS, PathSpec, MountMode]>;
    mountFor(path: string): MountEntry;
    tryMountFor(path: string): MountEntry | null;
    mountPrefixes(): string[];
    /** The workspace's command limits, the layer under each mount's. */
    get commandLimits(): Readonly<Record<string, Limit>>;
    /** The workspace's max_memory, null for no cap. */
    get memory(): MemoryBudget | null;
    /** The rule the workspace's connections are judged by, null for no limit. */
    get network(): NetworkRule | null;
    /** The workspace's system clock, null for the host's time. */
    get systemClock(): Clock | null;
    /**
     * How a session's files read this namespace: the reader for whichever
     * session an op runs as (`NamespaceReader`), over the link table and the
     * mount registry this owns, read live. Mirrors Python's `Namespace.readers`.
     *
     * @param visibility the visibility of a session, by id; null names the
     *   session bound when the question is asked.
     */
    readers(visibility: (sessionId: string | null) => Visibility | null): (sessionId: string | null) => NamespaceReader;
    /**
     * The link table as one session sees it (`NamespaceReader`), the one every
     * reader above the dispatcher follows a link through: a link the session
     * cannot see is no link to any command, so none resolves, copies or reports
     * a hidden one. Mirrors Python's `Namespace.session_links`.
     *
     * @param session the session; omitted for the one the current context
     *   runs as.
     */
    sessionLinks(session?: SessionState | null): NamespaceReader;
}
//# sourceMappingURL=namespace.d.ts.map