import type { ChunkingOptions } from "../../chunking.js"; import type { PgFileSystemOptions, SqlClient, SqlParam } from "../../types.js"; import { type CompiledExcludes } from "../../exclude.js"; import { type CompiledMounts } from "../../mounts.js"; export declare class FsStateBase { protected client: SqlClient; /** * The adapter's client before the read-only wrapper (tracing included). * Same as `client` on a writable instance. A read-only instance sends * plain reads here (see `getReadOnlyClient`) and everything else through * `client`, so writes still hit a READ ONLY transaction. */ private wireClient; /** * The value the adapter wants threaded back into its own constructor when the * core needs to reconstruct a sibling instance (fork, scope, tx facade). For * raw `CorePgFileSystem` consumers this is the same `SqlClient` as `client`; * for adapters (drizzle, node-postgres, postgres-js) it is the original * un-wrapped user db so the adapter constructor's `createXClient(options.db)` * runs exactly once per chain. Storing the wrapped `SqlClient` here would * make adapter forks wrap a `SqlClient` again, producing a client that * dispatches to a non-existent `db.execute` and crashes on first query. */ protected rawDb: unknown; readonly workspaceId: string; /** * Mutable backing for the public `version` getter. Internal code that needs * to change the instance's label after a successful commit (e.g. `renameVersion()`) * writes here. */ protected versionLabel: string; readonly permissions: { read: boolean; write: boolean; }; protected maxFileSize: number; protected maxReadSize: number | undefined; protected maxFiles: number; protected maxWorkspaceBytes: number | undefined; protected maxDepth: number; protected maxSymlinkDepth: number; protected maxCpNodes: number; protected statementTimeoutMs: number; protected embed?: (texts: string[]) => Promise; protected embeddingDimensions?: number; /** Chunk-level index options; null when the `chunking` option is off. */ protected chunking: ChunkingOptions | null; protected historyRetention: "retain" | "discard"; protected rootDir: string; protected versionRootPath: string; protected excludes: CompiledExcludes; protected mounts: CompiledMounts; protected readonly baseOptions: PgFileSystemOptions; protected requestedVersionId: number | null; protected cachedVersionId: number | null; protected cachedVersionRootId: number | null; /** * Optimistic visible-node count for `validateNodeCount`. Avoids running a * `COUNT(*)` over the COW-resolved view of the whole workspace on every * write while there's still comfortable headroom under `maxFiles`. May * drift upward when entries are removed (we never decrement); the drift * is self-correcting because as the cache approaches `maxFiles` we fall * back to the real `COUNT` and reset. */ protected cachedNodeCount: number | null; /** * When non-null, this instance is a transaction-bound facade. All `withWorkspace()` * calls on the facade run `fn(txClient)` directly instead of opening a new * transaction. The outer `transaction()` call has already wired up RLS * (`app.workspace_id`) and `statement_timeout` on this client. */ protected txClient: SqlClient | null; /** * Hooks queued by tx-bound facade methods (e.g. `renameVersion()`) to apply * instance-state mutations on the originating instance only after the outer * transaction commits. Set on the facade by `transaction()`; never mutated on * a top-level instance. */ protected postCommitHooks: Array<() => void> | null; /** * The instance that produced this facade via `createTxFacade()`. Used so that * post-commit hooks (such as label updates) can target the surviving outer * instance rather than the transient facade. */ protected originInstance: this | null; /** * Lazily-built `SqlClient` that auto-injects `set_config('app.workspace_id',...)` * and `set_config('statement_timeout',...)` as a CTE on every read query. * Lets single-statement reads bypass the BEGIN/SET/COMMIT triplet — the * `set_config(local=true)` calls take effect inside the implicit per-statement * transaction so RLS and the timeout are still honored. */ private cachedReadOnlyClient; constructor(options: PgFileSystemOptions); /** * The version label this instance is bound to. Backed by a mutable private field * so that operations like `renameVersion()` can update the label after commit. */ get version(): string; /** Absolute workspace path that owns this instance's version graph. */ get versionRoot(): string; /** * Open a transaction on `client`, install the per-tx workspace + timeout * settings, and run `fn`. Used by both `withWorkspace()` and `transaction()`. */ protected runInWorkspace(client: SqlClient, fn: (tx: SqlClient) => Promise): Promise; /** * Run `fn` inside a workspace-scoped transaction. If this instance is a * transaction-bound facade (i.e. `txClient` is set), reuse the open * transaction directly. Maps PostgreSQL "read-only transaction" violations * (SQLSTATE 25006) into the public `EPERM` `FsError`. */ protected withWorkspace(fn: (tx: SqlClient) => Promise): Promise; /** * Read-only variant of `withWorkspace`. When not inside an outer transaction, * runs `fn` against a wrapper client that injects `set_config` for RLS and * statement timeout as a CTE on every query — saving the BEGIN/SET/COMMIT * round-trips that a normal `withWorkspace` would incur. Each query inside * `fn` runs in its own implicit transaction; callers must not depend on * cross-query snapshot atomicity (real filesystem reads aren't atomic across * calls either). */ protected withReadOnlyWorkspace(fn: (tx: SqlClient) => Promise): Promise; private getReadOnlyClient; /** * Run `fn` inside a single database transaction. `fn` receives a * transaction-bound facade for the same workspace, version, permissions, * limits, and rootDir. Multiple operations on the facade share the same * transaction: if `fn` throws or rejects, every write rolls back; if `fn` * returns, the transaction commits and the return value is the * `transaction()` result. * * Re-entrant: calling `transaction()` on a facade that is already inside an * outer transaction reuses that outer transaction (no nested savepoints). * * Read-only instances still produce a read-only transaction; writes inside * `fn` raise `FsError(EPERM)`. * * The facade should not be retained after `fn` resolves — its underlying * SQL transaction has closed and further calls will fail. */ transaction(fn: (tx: this) => Promise): Promise; /** * Build a transaction-bound facade that shares this instance's configuration * and runs every operation against the supplied SQL transaction client. */ protected createTxFacade(sqlTx: SqlClient, postCommitHooks: Array<() => void>): this; protected toInternalPath(userPath: string): string; protected toUserPath(internalPath: string): string; protected guardRead(userPath: string): string; protected guardWrite(userPath: string): string; /** * Build the SQL fragment that filters out excluded paths from a result set. * Returns `{ sql: "TRUE", params: [] }` when no patterns are configured. * * `pathExpr` names the ltree path column in the surrounding query * (e.g. `e.path`, `path`, `src.path`). `nextParamIdx` is the next free `$N`. */ protected buildExcludeClause(pathExpr: string, nextParamIdx: number): { sql: string; params: SqlParam[]; }; /** * Build the SQL fragment that restricts a result set to mounted subtrees and * the ancestor paths leading to them. `{ sql: "TRUE", params: [] }` when this * instance has no mounts. Threaded into every directory-listing, walk, glob, * and search query alongside `buildExcludeClause`. */ protected buildMountClause(pathExpr: string, nextParamIdx: number): { sql: string; params: SqlParam[]; }; /** * Throw `ENOENT` if `internalPath` matches an exclude pattern. Used by every * public write method so that excluded paths are invisible to writers, not * merely shadowed at read time. */ protected guardExcludedWrite(internalPath: string, op: string, userPath: string): void; protected guardRootBoundary(internalPath: string): void; } //# sourceMappingURL=state.d.ts.map