import type lbug from '@ladybugdb/core'; export declare function cleanupNativePathJunctions(): void; export declare function toNativeSafePath(p: string): string; /** * Resolve the on-disk CSV staging dir for `/`, applying the * same ASCII-safe relocation `toNativeSafePath` enables: on Windows with a * non-ASCII storage path, LadybugDB's bulk COPY cannot open files under that * path, so the dir is relocated under `os.tmpdir()`. Shared by the structural * `csv/` dir and the streaming `pdg-csv/` dir (#2202) so the two can never * diverge on platform handling; the `gitnexus--` prefix keeps their tmp * locations distinct and recognizable. * * The relocated dir is created with `fs.mkdtempSync` (a unique, mode-0700, * guaranteed-not-pre-existing suffix) rather than a deterministic * `gitnexus--` name. A predictable name in the world-readable OS * temp dir is information-disclosure-prone and pre-plantable * (CWE-377/378 / CodeQL `js/insecure-temporary-file`); mkdtemp's random suffix * is the documented mitigation and is what reaches the streaming sink's * `fs.openSync`. The non-Windows / ASCII path stays a pure `path.join` (no dir * created) and is byte-identical to before. */ export declare function resolveNativeSafeStorageDir(storagePath: string, subdir: string): string; /** * Shared configuration for `@ladybugdb/core` `Database` construction. * * Two values changed meaningfully in `@ladybugdb/core` 0.16.0 and need to be * pinned explicitly by every caller, otherwise GitNexus regresses: * * 1. `maxDBSize` defaults to `0`, which the native runtime interprets as * "use the platform's full mmap address space" — typically 8 TB on * 64-bit Linux. Constrained environments (CI runners, containers, WSL) * cannot reserve that much address space and crash with * `Buffer manager exception: Mmap for size 8796093022208 failed.` * See LadybugDB upstream JSDoc: * > "introduced temporarily for now to get around with the default 8TB * > mmap address space limit some environment". * * 2. `enableCompression` flipped its default from `false` (0.15.x) to * `true` (0.16.0). Existing call sites that relied on the positional * default must now pass `false` explicitly to preserve behaviour. * * Putting both in one shared module guarantees every `new lbug.Database(...)` * call site agrees on the same ceiling and behaviour. */ /** * Upper bound for any single GitNexus LadybugDB file (graph index, group * bridge, install scratch, test fixture). 16 GiB is intentionally generous * for real-world code graphs (the GitNexus self-index uses < 50 MiB) while * remaining far below any 64-bit OS mmap ceiling. * * Override with the `GITNEXUS_LBUG_MAX_DB_SIZE` environment variable when * indexing genuinely huge monorepos. Values are coerced to a positive * integer; anything invalid falls back to the default. */ export declare const LBUG_MAX_DB_SIZE: number; export declare const parseWalCheckpointThreshold: (raw: string | undefined) => number | undefined; export declare const WAL_RECOVERY_SUGGESTION = "WAL corruption detected. Run `gitnexus analyze --force` to rebuild the index."; export declare function isWalCorruptionError(err: unknown): boolean; /** * True when `err` looks like a Ladybug WAL-checkpoint rotation/remove IO * failure. Tries strict matchers first (renames + removes), then falls * back to the permissive matcher. */ export declare const isLbugCheckpointIoError: (err: unknown) => boolean; type LbugModule = typeof lbug; export interface LbugDatabaseOptions { readOnly?: boolean; throwOnWalReplayFailure?: boolean; } export interface LbugConnectionHandle { db: lbug.Database; conn: lbug.Connection; } /** * Return true when the error message indicates that a LadybugDB write * transaction could not proceed due to lock contention — either a file * lock that could not be acquired (either at construction time, * `new lbug.Database(...)` raising from `local_file_system.cpp`, or during * a query, another writer holds the exclusive lock), or a same-process * write transaction rejected because another write transaction is already * active on the connection. * * Lives here (not in `lbug-adapter.ts`) so both the construction-time * retry (`openWithLockRetry` in this file) and the query-time retry * (`withLbugDb` in `lbug-adapter.ts`) consult the same matcher. Callers * import directly from this module — no re-export to keep in sync. */ export declare const isDbBusyError: (err: unknown) => boolean; /** See {@link classifyDeleteAllError}. */ export type DeleteAllErrorClass = 'benign-missing-table' | 'rethrow'; /** * Classify an error thrown while clearing all relationships of one type * before an incremental re-write (`deleteAllRelationshipsOfType` in * `lbug-adapter.ts` — the `deleteAllInjects` / `deleteAllCallSummaries` / * `deleteAllInterprocTaintPaths` family). * * - `'benign-missing-table'`: the CodeRelation table does not exist yet * (freshly-initialized DB) — the delete-all is a no-op, stay silent. * - `'rethrow'`: ANY other failure (lock, disk, closed connection, native * error) leaves stale rows that the subsequent re-extract then DUPLICATES * (CodeRelation has no PK), so the caller must abort the writeback * (#2084 review P2-5). * * Pure classification, extracted here (next to the other error matchers) so * the load-bearing regex/branch is unit-testable without a native DB — * driving a synthetic failure through the real singleton connection would * break every later test in the shared integration suite (#2200 review). */ export declare const classifyDeleteAllError: (err: unknown) => DeleteAllErrorClass; export declare function createLbugDatabase(lbugModule: LbugModule, databasePath: string, options?: LbugDatabaseOptions): lbug.Database; /** * Marker symbol attached to lock errors after `openWithLockRetry` exhausts * its budget. `withLbugDb`'s outer query-time retry consults this so it * does not re-retry a path that just spent up to ~1.5s in the open-time * loop — preventing 6s tail latencies (3× outer × 5× inner attempts). * * The symbol is internal to GitNexus; consumers should treat the underlying * error message as the user-visible signal. */ export declare const LBUG_OPEN_RETRY_EXHAUSTED: unique symbol; export declare const isOpenRetryExhausted: (err: unknown) => boolean; /** Exported only for direct unit testing — production callers use `openWithLockRetry`. */ export declare const _isTestFixturePathForTest: (dbPath: string) => boolean; export declare function openLbugConnection(lbugModule: LbugModule, databasePath: string, options?: LbugDatabaseOptions): Promise; export declare function closeLbugConnection(handle: LbugConnectionHandle): Promise; /** * Probe `dbPath` AND its `.wal` sidecar after `db.close()` so any * residual native file handle surfaces as EBUSY/EPERM/EACCES and the * bounded retry absorbs the release lag. Windows-only — Linux/macOS do * not exhibit this race. * * Both files matter. Empirically, on rapid open→close→reopen cycles the * main `dbPath` handle releases first; the `.wal` handle from the * previous Database lingers and the new Database's first write (CREATE * NODE TABLE during schema init) fails with "Could not set lock on * file". Probing both makes safeClose actually return when the kernel * is fully done with the path. * * Returns `true` when both probes succeeded (or skipped on non-lock * errors / missing files). Returns `false` when either probe exhausted * its budget with a lock code still in flight. * * Defensive shape: * - Opens read+write (`'r+'`) so the probe actually surfaces exclusive * locks held by the previous Database. A read-only probe (`'r'`) is * insufficient — Windows will grant read access while the previous * handle's exclusive write lock is still in flight, which lets * `safeClose` return before the next CREATE NODE TABLE can lock the * file. * - `try/finally` around `handle.close()` guarantees no fd leak even * if close itself throws. */ export declare const waitForWindowsHandleRelease: (dbPath: string) => Promise; export {};