import type FilenSDK from "@filen/sdk"; /** * The exact dir-tree response shape the SDK's public `api(3).dir().tree()` returns, derived from the * SDK's own types so this reimplementation can never drift from what `remote.ts` consumes (the tuple * element types — uuid/metadata/parent, file encryption version, etc. — come along for free). */ export type DirTreeResponse = Awaited["dir"]>["tree"]>>; /** * The minimal slice of a FilenSDK instance the fetcher needs: its already-configured axios instance * (reused so we inherit the consumer's proxy/agent/interceptor setup and add no new HTTP surface) and * its config for the API key. The real `FilenSDK` satisfies this structurally. */ export type DirTreeSDK = Pick; export type DirTreeRequest = { uuid: string; deviceId: string; skipCache: boolean; }; /** * The swappable remote tree-fetch seam (lives on {@link SyncEnvironment}). Production wires * {@link fetchDirTreeMsgpack}; tests inject a fetcher that delegates to the fake cloud's * `api(3).dir().tree()` so every scenario keeps exercising the real engine logic without HTTP. */ export type SyncDirTreeFetcher = (sdk: DirTreeSDK, request: DirTreeRequest) => Promise; /** * The same gateway pool the SDK uses, mirrored here so this one reimplemented call does not reach into * SDK internals. Requests rotate through these on failure for deterministic failover. */ export declare const DIR_TREE_GATEWAY_URLS: readonly string[]; /** * A definitive API-level error: the response envelope reported `status: false` (e.g. `folder_not_found`). * Thrown WITHOUT retry — retrying a definitive rejection is pointless and would only mask the real cause. */ export declare class DirTreeAPIError extends Error { readonly code: string; constructor(code: string, message: string); } export type FetchDirTreeOptions = { maxTries?: number; baseRetryDelayMs?: number; maxRetryDelayMs?: number; timeoutMs?: number; gatewayURLs?: readonly string[]; abortSignal?: AbortSignal; /** Injectable for deterministic tests; defaults to `Math.random`. */ random?: () => number; /** Injectable for deterministic tests; defaults to a real timer. */ sleep?: (ms: number) => Promise; }; /** * Reimplements the single `/v3/dir/tree` API call the sync engine depends on, requesting a **msgpack** * response (decoded with msgpackr) instead of JSON — far cheaper to transfer and parse for very large * trees. The request BODY stays JSON; only the server's response is msgpack. * * Memory: this is the hottest allocation in a sync cycle (the entire remote tree lands here), so the * path is kept lean. msgpack decodes raw bytes straight to objects — unlike JSON, which must first * materialise the whole response as one giant UTF-8 string before parsing (peak = bytes + string + * objects vs bytes + objects). The arraybuffer Buffer is reused without copying ({@link toBuffer}), the * decoded `files`/`folders` arrays are returned by reference (never cloned), and axios response * transforms are disabled so it never tries to stringify/parse the binary body. Peak memory is then * just the response bytes plus the decoded tree — irreducible for a tree of that size. * * Behaviour mirrors the SDK's call 1:1 — identical body, identical `{ status, code, message, data }` * envelope, and the same deviceId-cache contract the engine relies on (an unchanged tree comes back * with empty `files`/`folders`, which `remote.ts` reads as "reuse my cache"). Transport is sturdier * than the SDK's: it rotates through every gateway on failure (the SDK picks a random one each try and * can hit the same dead host twice) and backs off with full-jitter exponential delay instead of a flat * interval. Definitive API errors and aborts short-circuit without retrying. */ export declare function fetchDirTreeMsgpack(sdk: DirTreeSDK, request: DirTreeRequest, options?: FetchDirTreeOptions): Promise;