import type { Drive } from "@suaveplan/drive"; import type { DriveTemplate } from "@suaveplan/drive-template"; import { SuaveplanError } from "@suaveplan/error"; /** * Real, hand-written `Drive`-shaped test double. NOT a mock — it is a real * class implementing every method consumed by `@suaveplan/drive-uri`. Used * for unit-tier tests where spinning up a full `Drive + storage-file + * chunksPlugin` would be excessive; integration tests use the real `Drive`. * * Per CLAUDE.md rule 2 this is acceptable because: * - the class is concrete, with deterministic behaviour * - no `vi.mock`/`jest.mock` is involved * - it implements the structural contract drive-uri consumes */ export class FakeDriveError extends SuaveplanError { public constructor( code: string, message: string, options?: { cause?: unknown } ) { super(code, message, options); this.name = "FakeDriveError"; } } export interface FakeDriveCalls { read: Array<{ path: string; options?: { signal?: AbortSignal } }>; write: Array<{ path: string; data: Uint8Array }>; delete: Array<{ path: string }>; stat: Array<{ path: string }>; list: Array<{ prefix?: string }>; createReadStream: Array<{ path: string; signal?: AbortSignal }>; hydrateFrom: Array<{ template: DriveTemplate; options?: { signal?: AbortSignal }; }>; } export interface FakeDriveOptions { readonly contents?: Map; readonly readError?: () => unknown; readonly hydrateError?: () => unknown; } export class FakeDrive { public readonly clock = undefined; public readonly rng = undefined; public readonly logger = undefined; public readonly events = undefined; public readonly calls: FakeDriveCalls = { read: [], write: [], delete: [], stat: [], list: [], createReadStream: [], hydrateFrom: [], }; readonly #contents: Map; readonly #options: FakeDriveOptions; public constructor(options: FakeDriveOptions = {}) { this.#contents = options.contents ?? new Map(); this.#options = options; } public async read( path: string, options?: { signal?: AbortSignal } ): Promise { const entry: { path: string; options?: { signal?: AbortSignal } } = { path, }; if (options !== undefined) entry.options = options; this.calls.read.push(entry); if (this.#options.readError !== undefined) { throw this.#options.readError(); } const bytes = this.#contents.get(path); if (bytes === undefined) { throw new FakeDriveError( "DRIVE.NOT_FOUND", `no entry for '${path}'` ); } return bytes; } public async write(path: string, data: Uint8Array): Promise { this.calls.write.push({ path, data }); this.#contents.set(path, data); } public async delete(path: string): Promise { this.calls.delete.push({ path }); return this.#contents.delete(path); } public async stat(path: string): Promise { this.calls.stat.push({ path }); const bytes = this.#contents.get(path); if (bytes === undefined) return null; return { path, size: bytes.byteLength }; } public async list(prefix?: string): Promise { this.calls.list.push({ ...(prefix !== undefined ? { prefix } : {}) }); const keys = Array.from(this.#contents.keys()).filter((k) => prefix === undefined || prefix === "" ? true : k.startsWith(prefix) ); return { keys, total: keys.length, hasMore: false }; } public createReadStream( path: string, signal?: AbortSignal ): ReadableStream { const entry: { path: string; signal?: AbortSignal } = { path }; if (signal !== undefined) entry.signal = signal; this.calls.createReadStream.push(entry); const bytes = this.#contents.get(path); return new ReadableStream({ start(ctrl) { if (bytes !== undefined) ctrl.enqueue(bytes); ctrl.close(); }, }); } public async hydrateFrom( template: DriveTemplate, options?: { signal?: AbortSignal } ): Promise<{ filesAdded: number }> { const entry: { template: DriveTemplate; options?: { signal?: AbortSignal }; } = { template }; if (options !== undefined) entry.options = options; this.calls.hydrateFrom.push(entry); if (this.#options.hydrateError !== undefined) { throw this.#options.hydrateError(); } return { filesAdded: 0 }; } } /** Returns a `Drive`-typed reference to the fake — narrows for ergonomic use. */ export function asDrive(fake: FakeDrive): Drive { return fake as unknown as Drive; }