{"version":3,"file":"async.mjs","names":[],"sources":["../src/async/internal/helpers.ts","../src/async/core/create.ts","../src/async/core/read.ts","../src/async/core/remove.ts","../src/async/core/stat.ts","../src/async/core/truncate.ts","../src/async/core/write.ts","../src/async/ext.ts","../src/async/archive/helpers.ts","../src/async/archive/unzip-stream.ts","../src/async/archive/unzip.ts","../src/async/archive/zip-stream.ts","../src/async/archive/zip.ts","../src/async/tmp.ts","../src/async/transfer/download.ts","../src/async/transfer/upload.ts"],"sourcesContent":["/**\n * Internal helper utilities for async file operations.\n * These functions are not exported publicly.\n *\n * @internal\n * @module\n */\n\nimport type { FetchTask } from '@happy-ts/fetch-t';\nimport {\n    LazyAsync,\n    Ok,\n    RESULT_VOID,\n    tryAsyncResult,\n    type AsyncIOResult,\n    type AsyncVoidIOResult,\n    type IOResult,\n} from 'happy-rusty';\nimport { basename, dirname, SEPARATOR } from '../../shared/internal/mod.ts';\nimport {\n    ABORT_ERROR,\n    EMPTY_BODY_ERROR,\n    EMPTY_FILE_ERROR,\n    NOT_FOUND_ERROR,\n    NOTHING_TO_ZIP_ERROR,\n    ROOT_DIR,\n} from '../../shared/mod.ts';\n\n// #region Internal Variables\n\n/**\n * Lazily initialized root directory handle of the file system.\n * Created on first access via `force()`.\n */\nconst fsRoot = /*#__PURE__*/ LazyAsync(() => navigator.storage.getDirectory());\n\n// #endregion\n\n/**\n * Checks if the provided path is the root directory path.\n *\n * @param path - The path to check.\n * @returns `true` if the path equals `'/'`, otherwise `false`.\n */\nexport function isRootDir(path: string): boolean {\n    return path === ROOT_DIR;\n}\n\n/**\n * Retrieves a directory handle by traversing the path from root.\n *\n * Algorithm:\n * 1. Start from the OPFS root directory\n * 2. If path is `/`, return root immediately\n * 3. Split path by `/` separator and iterate through each segment\n * 4. For each segment, get or create the child directory handle\n * 5. Return error immediately if any segment fails\n *\n * @param dirPath - The absolute path of the directory to retrieve.\n * @param options - Optional parameters (e.g., `{ create: true }` to create intermediate directories).\n * @returns A promise that resolves to an `AsyncIOResult` containing the `FileSystemDirectoryHandle`.\n */\nexport async function getDirHandle(\n    dirPath: string,\n    options?: FileSystemGetDirectoryOptions,\n): AsyncIOResult<FileSystemDirectoryHandle> {\n    // Start from root\n    let dirHandle = fsRoot.isInitialized() ? fsRoot.get().unwrap() : await fsRoot.force();\n\n    if (isRootDir(dirPath)) {\n        // Root is already a handle, no traversal needed\n        return Ok(dirHandle);\n    } else {\n        // NOTE: Empty else branch is intentional to fix V8 coverage tracking.\n        // Without explicit else, V8 incorrectly marks code after early return as uncovered.\n    }\n\n    // Traverse path from root\n    // Iterate through each path segment\n    // Path is already normalized by validateAbsolutePath, no empty segments\n    // Remove leading '/' and start traversing\n    for (const childDirName of dirPath.slice(1).split(SEPARATOR)) {\n        // Get or create child directory\n        const dirHandleRes = await getChildDirHandle(dirHandle, childDirName, options);\n        if (dirHandleRes.isErr()) {\n            // Stop traversal on error\n            return dirHandleRes;\n        }\n\n        dirHandle = dirHandleRes.unwrap();\n    }\n\n    return Ok(dirHandle);\n}\n\n/**\n * Gets the directory handle for the parent directory of the given path.\n *\n * @param path - The absolute path whose parent directory handle is to be retrieved.\n * @param options - Optional parameters (e.g., `{ create: true }` to create intermediate directories).\n * @returns A promise that resolves to an `AsyncIOResult` containing the parent `FileSystemDirectoryHandle`.\n */\nexport function getParentDirHandle(\n    path: string,\n    options?: FileSystemGetDirectoryOptions,\n): AsyncIOResult<FileSystemDirectoryHandle> {\n    return getDirHandle(dirname(path), options);\n}\n\n/**\n * Retrieves a file handle given a file path.\n *\n * @param filePath - The absolute path of the file to retrieve.\n * @param options - Optional parameters (e.g., `{ create: true }` to create the file if not exists).\n * @returns A promise that resolves to an `AsyncIOResult` containing the `FileSystemFileHandle`.\n */\nexport async function getFileHandle(\n    filePath: string,\n    options?: FileSystemGetFileOptions,\n): AsyncIOResult<FileSystemFileHandle> {\n    const dirHandleRes = await getParentDirHandle(filePath, options);\n\n    return dirHandleRes.andThenAsync(dirHandle => {\n        const fileName = basename(filePath);\n        return getChildFileHandle(dirHandle, fileName, options);\n    });\n}\n\n/**\n * Checks whether the error is a `NotFoundError`.\n *\n * @param err - The error to check.\n * @returns `true` if the error's name is `'NotFoundError'`, otherwise `false`.\n */\nexport function isNotFoundError(err: Error): boolean {\n    return err.name === NOT_FOUND_ERROR;\n}\n\n/**\n * Aggregates multiple async void I/O results into a single result.\n * Waits for all tasks to complete, then returns the first error encountered,\n * or a void success result if all tasks succeed.\n *\n * @param tasks - The list of async void I/O result promises to aggregate.\n * @returns A promise that resolves to the first error result, or `RESULT_VOID` if all tasks succeed.\n */\nexport async function aggregateResults(tasks: AsyncVoidIOResult[]): AsyncVoidIOResult {\n    if (tasks.length === 0) {\n        return RESULT_VOID;\n    }\n\n    const allRes = await Promise.all(tasks);\n    return allRes.find(x => x.isErr()) ?? RESULT_VOID;\n}\n\n/**\n * Creates an `AbortError` instance.\n * Used to signal that an operation was aborted.\n *\n * @returns An `Error` object with the name set to `'AbortError'`.\n */\nexport function createAbortError(): Error {\n    const error = new Error('Operation was aborted');\n    error.name = ABORT_ERROR;\n\n    return error;\n}\n\n/**\n * Creates an `EmptyBodyError` instance.\n * Used to signal that a response body is empty (null).\n *\n * @returns An `Error` object with the name set to `'EmptyBodyError'`.\n */\nexport function createEmptyBodyError(): Error {\n    const error = new Error('Response body is empty');\n    error.name = EMPTY_BODY_ERROR;\n\n    return error;\n}\n\n/**\n * Creates an `EmptyFileError` instance.\n * Used to signal that a file content is empty (0 bytes).\n *\n * @returns An `Error` object with the name set to `'EmptyFileError'`.\n */\nexport function createEmptyFileError(): Error {\n    const error = new Error('File content is empty');\n    error.name = EMPTY_FILE_ERROR;\n\n    return error;\n}\n\n/**\n * Creates a `NothingToZipError` instance.\n * Used when attempting to zip an empty directory with preserveRoot=false.\n *\n * @returns An `Error` object with the name set to `'NothingToZipError'`.\n */\nexport function createNothingToZipError(): Error {\n    const error = new Error('Nothing to zip');\n    error.name = NOTHING_TO_ZIP_ERROR;\n\n    return error;\n}\n\n/**\n * Creates a failed FetchTask that immediately resolves with an error.\n * Used when validation fails before making the actual fetch request.\n *\n * @param errResult - The error result to return.\n * @returns A FetchTask that resolves with the error.\n */\nexport function createFailedFetchTask<T>(errResult: IOResult<unknown>): FetchTask<T> {\n    return {\n        abort(): void {\n            /* noop */\n        },\n        get aborted(): boolean {\n            return false;\n        },\n        get result() {\n            return Promise.resolve(errResult.asErr<T>());\n        },\n    };\n}\n\n/**\n * Marks all parent directories of a path as non-empty.\n * Used to optimize directory creation by skipping directories that will be\n * implicitly created when writing files.\n *\n * @param path - The relative file path.\n * @param nonEmptyDirs - Set to track non-empty directories.\n */\nexport function markParentDirsNonEmpty(path: string, nonEmptyDirs: Set<string>): void {\n    let slashIndex = path.lastIndexOf(SEPARATOR);\n    while (slashIndex > 0) {\n        const parent = path.slice(0, slashIndex);\n        if (nonEmptyDirs.has(parent)) break;\n        nonEmptyDirs.add(parent);\n        slashIndex = path.lastIndexOf(SEPARATOR, slashIndex - 1);\n    }\n}\n\n/**\n * Removes a file or directory with cross-browser compatibility.\n * Accepts either a handle or a name string. When a handle is provided and\n * `handle.remove()` is supported (Chrome/Edge), uses native removal.\n * Otherwise falls back to `parentDirHandle.removeEntry()`.\n *\n * For root directory removal on Firefox/Safari (where `handle.remove()` is not supported),\n * iterates through all children and removes them individually.\n *\n * @param handleOrName - The handle to remove, or the name of the entry.\n * @param parentDirHandle - The parent directory handle.\n * @param options - Optional remove options (e.g., `{ recursive: true }`).\n * @returns A promise that resolves when the entry is removed.\n */\nexport async function removeHandle(\n    handleOrName: FileSystemHandle | string,\n    parentDirHandle: FileSystemDirectoryHandle,\n    options?: FileSystemRemoveOptions,\n): Promise<void> {\n    if (typeof handleOrName === 'string') {\n        // Name string: use removeEntry directly\n        return parentDirHandle.removeEntry(handleOrName, options);\n    }\n\n    const removableHandle = handleOrName as RemovableHandle;\n\n    if (typeof removableHandle.remove === 'function') {\n        // Chrome/Edge: use native handle.remove()\n        return removableHandle.remove(options);\n    }\n\n    // Firefox/Safari: fallback to removeEntry()\n    // Special case: root directory has empty name, cannot use removeEntry\n    // Instead, iterate and remove all children\n    if (!handleOrName.name) {\n        const dirHandle = handleOrName as FileSystemDirectoryHandle;\n        const tasks: Promise<void>[] = [];\n\n        for await (const childName of dirHandle.keys()) {\n            tasks.push(dirHandle.removeEntry(childName, options));\n        }\n\n        if (tasks.length > 0) {\n            await Promise.all(tasks);\n        }\n    } else {\n        return parentDirHandle.removeEntry(handleOrName.name, options);\n    }\n}\n\n/**\n * Result of peeking a stream's first chunk.\n */\nexport interface PeekStreamResult<T> {\n    /** Whether the stream is empty (no data). */\n    isEmpty: boolean;\n    /** The reconstructed stream with first chunk prepended. Only valid if not empty. */\n    stream: ReadableStream<T>;\n}\n\n/**\n * Peeks the first chunk of a ReadableStream to check if it's empty.\n * Returns the original stream reconstructed with the peeked chunk prepended.\n *\n * This enables true streaming while detecting empty streams before processing.\n *\n * @param source - The source ReadableStream to peek.\n * @returns A promise resolving to an `AsyncIOResult` containing PeekStreamResult with isEmpty flag and reconstructed stream.\n */\nexport async function peekStream<T>(source: ReadableStream<T>): AsyncIOResult<PeekStreamResult<T>> {\n    const reader = source.getReader();\n\n    const firstRes = await tryAsyncResult(reader.read());\n    if (firstRes.isErr()) {\n        reader.releaseLock();\n        return firstRes.asErr();\n    }\n\n    const first = firstRes.unwrap();\n\n    if (first.done) {\n        reader.releaseLock();\n        // Return a new empty stream since the original is already consumed\n        return Ok({\n            isEmpty: true,\n            stream: new ReadableStream<T>({\n                start(controller) {\n                    controller.close();\n                },\n            }),\n        });\n    }\n\n    // Reconstruct stream: first chunk + remaining data\n    const stream = new ReadableStream<T>({\n        async start(controller) {\n            controller.enqueue(first.value);\n        },\n        async pull(controller) {\n            try {\n                const { done, value } = await reader.read();\n                if (done) {\n                    reader.releaseLock();\n                    controller.close();\n                } else {\n                    controller.enqueue(value);\n                }\n            } catch (err) {\n                reader.releaseLock();\n                controller.error(err);\n            }\n        },\n        async cancel(reason) {\n            try {\n                await reader.cancel(reason);\n            } finally {\n                reader.releaseLock();\n            }\n        },\n    });\n\n    return Ok({\n        isEmpty: false,\n        stream,\n    });\n}\n\n/**\n * Moves a file handle to a new path, creating parent directories if needed.\n *\n * Uses the native `move()` when available (instant rename; supported by all\n * modern browsers — Chrome 102+, Firefox 111+, Safari 15.2+ — though not on\n * the standards track). Falls back to copy semantics for older browsers without\n * `move()` — the caller is responsible for removing the source path after a\n * successful move.\n *\n * @param fileHandle - The file handle to move.\n * @param destFilePath - The destination absolute file path.\n * @returns A promise that resolves to an `AsyncVoidIOResult` indicating success or failure.\n */\nexport async function moveFileHandle(\n    fileHandle: FileSystemFileHandle,\n    destFilePath: string,\n): AsyncVoidIOResult {\n    const dirRes = await getParentDirHandle(destFilePath, {\n        create: true,\n    });\n\n    return dirRes.andTryAsync(async destDirHandle => {\n        const destName = basename(destFilePath);\n        const movable = fileHandle as unknown as MovableHandle;\n\n        // Native move (instant rename) when supported\n        if (typeof movable.move === 'function') {\n            return movable.move(destDirHandle, destName);\n        }\n\n        // Fallback: copy file content to dest (older browsers without handle.move())\n        // Inlined to avoid circular dep on write.ts (write.ts imports this module)\n        // getFile() and dest writable acquisition are independent — run in parallel\n        const [file, writable] = await Promise.all([\n            fileHandle.getFile(),\n            destDirHandle\n                .getFileHandle(destName, { create: true })\n                .then(handle => handle.createWritable()),\n        ]);\n        try {\n            await writable.write(file);\n        } finally {\n            await writable.close();\n        }\n    });\n}\n\n// #region Internal Types\n\n/**\n * Extended FileSystemHandle interface with optional remove method.\n * The remove() method is not supported in Firefox/iOS Safari.\n */\ninterface RemovableHandle extends FileSystemHandle {\n    remove?(options?: FileSystemRemoveOptions): Promise<void>;\n}\n\n/**\n * Extended FileSystemHandle interface with move method.\n * The move() method is not yet in TypeScript's lib.dom.d.ts.\n * @see https://github.com/mdn/browser-compat-data/issues/20341\n */\ninterface MovableHandle extends FileSystemHandle {\n    move(destination: FileSystemDirectoryHandle, name: string): Promise<void>;\n}\n\n// #endregion\n\n// #region Internal Functions\n\n/**\n * Asynchronously obtains a handle to a child directory from the given parent directory handle.\n *\n * @param dirHandle - The handle to the parent directory.\n * @param childDirName - The name of the child directory to retrieve.\n * @param options - Optional parameters (e.g., `{ create: true }` to create if not exists).\n * @returns A promise that resolves to an `AsyncIOResult` containing the `FileSystemDirectoryHandle`.\n */\nasync function getChildDirHandle(\n    dirHandle: FileSystemDirectoryHandle,\n    childDirName: string,\n    options?: FileSystemGetDirectoryOptions,\n): AsyncIOResult<FileSystemDirectoryHandle> {\n    const handleRes = await tryAsyncResult<FileSystemDirectoryHandle, DOMException>(\n        dirHandle.getDirectoryHandle(childDirName, options),\n    );\n    return handleRes.mapErr(err => {\n        const error = new Error(\n            `${err.name}: ${err.message} When get child directory '${childDirName}' from directory '${dirHandle.name || ROOT_DIR}'`,\n        );\n        error.name = err.name;\n        return error;\n    });\n}\n\n/**\n * Retrieves a file handle for a child file within a directory.\n *\n * @param dirHandle - The directory handle to search within.\n * @param childFileName - The name of the file to retrieve.\n * @param options - Optional parameters (e.g., `{ create: true }` to create if not exists).\n * @returns A promise that resolves to an `AsyncIOResult` containing the `FileSystemFileHandle`.\n */\nasync function getChildFileHandle(\n    dirHandle: FileSystemDirectoryHandle,\n    childFileName: string,\n    options?: FileSystemGetFileOptions,\n): AsyncIOResult<FileSystemFileHandle> {\n    const handleRes = await tryAsyncResult<FileSystemFileHandle, DOMException>(\n        dirHandle.getFileHandle(childFileName, options),\n    );\n    return handleRes.mapErr(err => {\n        const error = new Error(\n            `${err.name}: ${err.message} When get child file '${childFileName}' from directory '${dirHandle.name || ROOT_DIR}'`,\n        );\n        error.name = err.name;\n        return error;\n    });\n}\n\n// #endregion\n","import { RESULT_VOID, type AsyncVoidIOResult } from 'happy-rusty';\nimport { validateAbsolutePath } from '../../shared/internal/mod.ts';\nimport { getDirHandle, getFileHandle } from '../internal/mod.ts';\n\n/**\n * Creates a new empty file at the specified path, similar to the `touch` command.\n * If the file already exists, this operation succeeds without modifying it.\n * Parent directories are created automatically if they don't exist.\n *\n * **Note:** For temporary files, use {@link mkTemp} instead, which provides\n * automatic unique naming and integrates with {@link pruneTemp} for cleanup.\n *\n * @param filePath - The absolute path of the file to create.\n * @returns A promise that resolves to an `AsyncVoidIOResult` indicating success or failure.\n * @since 1.7.0\n * @see {@link createFileSync} for synchronous version\n * @see {@link mkTemp} for creating temporary files\n * @see {@link writeFile} for creating files with content\n * @example\n * ```typescript\n * (await createFile('/path/to/file.txt'))\n *     .inspect(() => console.log('File created'));\n * ```\n */\nexport async function createFile(filePath: string): AsyncVoidIOResult {\n    const filePathRes = validateAbsolutePath(filePath);\n    if (filePathRes.isErr()) return filePathRes.asErr();\n    filePath = filePathRes.unwrap();\n\n    const handleRes = await getFileHandle(filePath, {\n        create: true,\n    });\n\n    return handleRes.and(RESULT_VOID);\n}\n\n/**\n * Creates a new directory at the specified path, similar to `mkdir -p`.\n * Creates all necessary parent directories if they don't exist.\n *\n * **Note:** For temporary directories, use {@link mkTemp} with `{ isDirectory: true }` instead,\n * which provides automatic unique naming and integrates with temporary file management.\n *\n * @param dirPath - The absolute path where the directory will be created.\n * @returns A promise that resolves to an `AsyncVoidIOResult` indicating success or failure.\n * @since 1.0.0\n * @see {@link mkdirSync} for synchronous version\n * @see {@link emptyDir} for creating or emptying a directory\n * @see {@link mkTemp} for creating temporary directories\n * @example\n * ```typescript\n * (await mkdir('/path/to/new/directory'))\n *     .inspect(() => console.log('Directory created'));\n * ```\n */\nexport async function mkdir(dirPath: string): AsyncVoidIOResult {\n    const dirPathRes = validateAbsolutePath(dirPath);\n    if (dirPathRes.isErr()) return dirPathRes.asErr();\n    dirPath = dirPathRes.unwrap();\n\n    const handleRes = await getDirHandle(dirPath, {\n        create: true,\n    });\n\n    return handleRes.and(RESULT_VOID);\n}\n","import { Err, Ok, type AsyncIOResult } from 'happy-rusty';\nimport {\n    decodeUtf8,\n    join,\n    readBlobBytes,\n    validateAbsolutePath,\n} from '../../shared/internal/mod.ts';\nimport {\n    isDirectoryHandle,\n    type DirEntry,\n    type ReadDirOptions,\n    type ReadFileContent,\n    type ReadOptions,\n} from '../../shared/mod.ts';\nimport { createAbortError, getDirHandle, getFileHandle } from '../internal/mod.ts';\n/**\n * Reads the contents of a directory at the specified path.\n *\n * @param dirPath - The path of the directory to read.\n * @param options - Options of readdir.\n * @returns A promise that resolves to an `AsyncIOResult` containing an async iterable iterator over the entries of the directory.\n * @since 1.0.0\n * @see {@link readDirSync} for synchronous version\n * @example\n * ```typescript\n * // List directory contents\n * (await readDir('/documents'))\n *     .inspect(async entries => {\n *         for await (const entry of entries) {\n *             console.log(entry.path, entry.handle.kind);\n *         }\n *     });\n *\n * // List recursively\n * await readDir('/documents', { recursive: true });\n * ```\n */\nexport async function readDir(\n    dirPath: string,\n    options?: ReadDirOptions,\n): AsyncIOResult<AsyncIterableIterator<DirEntry>> {\n    const dirPathRes = validateAbsolutePath(dirPath);\n    if (dirPathRes.isErr()) return dirPathRes.asErr();\n    dirPath = dirPathRes.unwrap();\n\n    const dirHandleRes = await getDirHandle(dirPath);\n    if (dirHandleRes.isErr()) {\n        return dirHandleRes.asErr();\n    }\n\n    // Check if aborted after getting handle\n    if (options?.signal?.aborted) {\n        const { reason } = options.signal;\n        return Err(reason instanceof Error ? reason : createAbortError());\n    }\n\n    async function* read(\n        dirHandle: FileSystemDirectoryHandle,\n        relativePath?: string,\n    ): AsyncIterableIterator<DirEntry> {\n        if (options?.signal?.aborted) {\n            return;\n        }\n\n        for await (const [name, handle] of dirHandle.entries()) {\n            // Check if aborted before yielding each entry\n            if (options?.signal?.aborted) {\n                return;\n            }\n\n            const path = relativePath ? join(relativePath, name) : name;\n            yield {\n                path,\n                handle,\n            };\n\n            if (options?.recursive && isDirectoryHandle(handle)) {\n                yield* read(handle, path);\n            }\n        }\n    }\n\n    return Ok(read(dirHandleRes.unwrap()));\n}\n\n/**\n * Reads the content of a file at the specified path as a File.\n *\n * @param filePath - The path of the file to read.\n * @param options - Read options specifying the 'blob' encoding.\n * @returns A promise that resolves to an `AsyncIOResult` containing the file content as a File.\n * @since 1.0.0\n * @see {@link readFileSync} for synchronous version\n * @see {@link readBlobFile} convenience wrapper\n * @example\n * ```typescript\n * (await readFile('/path/to/file.txt', { encoding: 'blob' }))\n *     .inspect(file => console.log(file.name, file.size, file.type));\n * ```\n */\nexport function readFile(\n    filePath: string,\n    options: ReadOptions & {\n        encoding: 'blob';\n    },\n): AsyncIOResult<File>;\n\n/**\n * Reads the content of a file at the specified path as a string.\n *\n * @param filePath - The path of the file to read.\n * @param options - Read options specifying the 'utf8' encoding.\n * @returns A promise that resolves to an `AsyncIOResult` containing the file content as a string.\n * @since 1.0.0\n * @see {@link readFileSync} for synchronous version\n * @see {@link readTextFile} convenience wrapper\n * @example\n * ```typescript\n * (await readFile('/path/to/file.txt', { encoding: 'utf8' }))\n *     .inspect(content => console.log(content));\n * ```\n */\nexport function readFile(\n    filePath: string,\n    options: ReadOptions & {\n        encoding: 'utf8';\n    },\n): AsyncIOResult<string>;\n\n/**\n * Reads the content of a file at the specified path as a readable stream.\n * Useful for processing large files without loading them entirely into memory.\n *\n * @param filePath - The path of the file to read.\n * @param options - Read options specifying the 'stream' encoding.\n * @returns A promise that resolves to an `AsyncIOResult` containing a `ReadableStream<Uint8Array>`.\n * @since 1.0.0\n * @see {@link readFileSync} for synchronous version (bytes only)\n * @example\n * ```typescript\n * (await readFile('/path/to/large-file.bin', { encoding: 'stream' }))\n *     .inspect(async stream => {\n *         const reader = stream.getReader();\n *         while (true) {\n *             const { done, value } = await reader.read();\n *             if (done) break;\n *             console.log('Received chunk:', value.length, 'bytes');\n *         }\n *     });\n * ```\n */\nexport function readFile(\n    filePath: string,\n    options: ReadOptions & {\n        encoding: 'stream';\n    },\n): AsyncIOResult<ReadableStream<Uint8Array<ArrayBuffer>>>;\n\n/**\n * Reads the content of a file at the specified path as a Uint8Array (default).\n *\n * @param filePath - The path of the file to read.\n * @param options - Optional read options. Defaults to 'bytes' encoding.\n * @returns A promise that resolves to an `AsyncIOResult` containing the file content as a Uint8Array.\n * @since 1.0.0\n * @see {@link readFileSync} for synchronous version\n * @example\n * ```typescript\n * (await readFile('/path/to/file.bin'))\n *     .inspect(bytes => console.log('First byte:', bytes[0]));\n * ```\n */\nexport function readFile(\n    filePath: string,\n    options?: ReadOptions & {\n        encoding?: 'bytes';\n    },\n): AsyncIOResult<Uint8Array<ArrayBuffer>>;\n\n/**\n * Reads the content of a file at the specified path with the specified options.\n * This overload accepts any ReadOptions and returns the union of all possible content types.\n * Useful when the encoding is determined at runtime.\n *\n * @param filePath - The path of the file to read.\n * @param options - Optional read options.\n * @returns A promise that resolves to an `AsyncIOResult` containing the file content.\n * @since 1.0.0\n * @see {@link readFileSync} for synchronous version\n * @example\n * ```typescript\n * // When encoding is dynamic\n * const encoding = getUserPreference(); // 'utf8' | 'bytes' | ...\n * (await readFile('/path/to/file.txt', { encoding }))\n *     .inspect(content => {\n *         // content type is ReadFileContent (union type)\n *         if (typeof content === 'string') {\n *             console.log('Text:', content);\n *         } else if (content instanceof Uint8Array) {\n *             console.log('Bytes:', content.length);\n *         }\n *     });\n * ```\n */\nexport function readFile(filePath: string, options?: ReadOptions): AsyncIOResult<ReadFileContent>;\n\n/**\n * Reads the content of a file at the specified path with the specified options.\n *\n * @template T The type of the content to read from the file.\n * @param filePath - The path of the file to read.\n * @param options - Optional read options.\n * @returns A promise that resolves to an `AsyncIOResult` containing the file content.\n */\nexport async function readFile(\n    filePath: string,\n    options?: ReadOptions,\n): AsyncIOResult<ReadFileContent> {\n    const filePathRes = validateAbsolutePath(filePath);\n    if (filePathRes.isErr()) return filePathRes.asErr();\n    filePath = filePathRes.unwrap();\n\n    const fileHandleRes = await getFileHandle(filePath);\n\n    return fileHandleRes.andTryAsync(async fileHandle => {\n        const encoding = options?.encoding;\n\n        // Prefer sync access in Worker for better performance\n        // Only for encodings that don't require File object or streaming\n        return encoding !== 'blob' &&\n            encoding !== 'stream' &&\n            typeof fileHandle.createSyncAccessHandle === 'function'\n            ? readViaSyncAccess(fileHandle, encoding)\n            : // Main thread fallback or blob/stream encoding\n              readViaFile(fileHandle, encoding);\n    });\n}\n\n/**\n * Reads file content using the Worker's FileSystemSyncAccessHandle API.\n * More performant than File-based reading in Worker context.\n */\nasync function readViaSyncAccess(\n    fileHandle: FileSystemFileHandle,\n    encoding?: 'bytes' | 'utf8',\n): Promise<Uint8Array<ArrayBuffer> | string> {\n    const accessHandle = await fileHandle.createSyncAccessHandle();\n\n    try {\n        const size = accessHandle.getSize();\n        const bytes = new Uint8Array(size);\n        accessHandle.read(bytes, { at: 0 });\n\n        if (encoding === 'utf8') {\n            return decodeUtf8(bytes);\n        }\n        // 'bytes' or undefined (default)\n        return bytes;\n    } finally {\n        accessHandle.close();\n    }\n}\n\n/**\n * Reads file content using the File API (main thread strategy).\n */\nasync function readViaFile(\n    fileHandle: FileSystemFileHandle,\n    encoding?: 'bytes' | 'utf8' | 'blob' | 'stream',\n): Promise<ReadFileContent> {\n    const file = await fileHandle.getFile();\n\n    switch (encoding) {\n        case 'blob': {\n            return file;\n        }\n        case 'utf8': {\n            return file.text();\n        }\n        case 'stream': {\n            return file.stream();\n        }\n        default: {\n            // 'bytes' or undefined (default)\n            return readBlobBytes(file);\n        }\n    }\n}\n","import { Err, RESULT_VOID, type AsyncVoidIOResult } from 'happy-rusty';\nimport { basename, validateAbsolutePath } from '../../shared/internal/mod.ts';\nimport { getParentDirHandle, isNotFoundError, isRootDir, removeHandle } from '../internal/mod.ts';\n\n/**\n * Removes a file or directory at the specified path, similar to `rm -rf`.\n * If the path doesn't exist, the operation succeeds silently.\n *\n * @param path - The absolute path of the file or directory to remove.\n * @returns A promise that resolves to an `AsyncVoidIOResult` indicating success or failure.\n * @since 1.0.0\n * @see {@link removeSync} for synchronous version\n * @see {@link emptyDir} for emptying a directory without removing it\n * @see {@link deleteTemp} for removing the temporary directory\n * @example\n * ```typescript\n * (await remove('/path/to/file-or-directory'))\n *     .inspect(() => console.log('Removed successfully'));\n * ```\n */\nexport async function remove(path: string): AsyncVoidIOResult {\n    const pathRes = validateAbsolutePath(path);\n    if (pathRes.isErr()) return pathRes.asErr();\n    path = pathRes.unwrap();\n\n    const parentDirHandleRes = await getParentDirHandle(path);\n\n    const removeRes = await parentDirHandleRes.andTryAsync(parentDirHandle => {\n        // For root, parentDirHandle is the root itself\n        // For non-root, use basename as the entry name\n        const handleOrName = isRootDir(path) ? parentDirHandle : basename(path);\n        return removeHandle(handleOrName, parentDirHandle, {\n            recursive: true,\n        });\n    });\n\n    return removeRes.orElse(err => {\n        // not found as success\n        return isNotFoundError(err) ? RESULT_VOID : Err(err);\n    });\n}\n","import { tryAsyncResult, type AsyncIOResult } from 'happy-rusty';\nimport { basename, validateAbsolutePath } from '../../shared/internal/mod.ts';\nimport { getParentDirHandle, isRootDir } from '../internal/mod.ts';\n\n/**\n * Retrieves the `FileSystemHandle` for a file or directory at the specified path.\n * Can be used to check the type (file or directory) and access metadata.\n *\n * @param path - The absolute path of the file or directory.\n * @returns A promise that resolves to an `AsyncIOResult` containing the `FileSystemHandle`.\n * @since 1.0.0\n * @see {@link statSync} for synchronous version\n * @see {@link exists} for checking existence without getting the handle\n * @see {@link isFileHandle} for checking handle type\n * @see {@link isDirectoryHandle} for checking handle type\n * @example\n * ```typescript\n * (await stat('/path/to/entry'))\n *     .inspect(handle => console.log(`Kind: ${ handle.kind }, Name: ${ handle.name }`));\n * ```\n */\nexport async function stat(path: string): AsyncIOResult<FileSystemHandle> {\n    const pathRes = validateAbsolutePath(path);\n    if (pathRes.isErr()) return pathRes.asErr();\n    path = pathRes.unwrap();\n\n    const dirHandleRes = await getParentDirHandle(path);\n    if (isRootDir(path)) {\n        // root\n        return dirHandleRes;\n    }\n\n    return dirHandleRes.andThenAsync(async dirHandle => {\n        // Try to get the handle directly instead of iterating\n        // First try as file, then as directory\n        const childName = basename(path);\n        let findRes = await tryAsyncResult<FileSystemHandle, DOMException>(\n            dirHandle.getFileHandle(childName),\n        );\n        if (findRes.isOk()) {\n            return findRes;\n        }\n\n        // Not a file, try as directory\n        findRes = await tryAsyncResult<FileSystemHandle, DOMException>(\n            dirHandle.getDirectoryHandle(childName),\n        );\n\n        return findRes.mapErr(err => {\n            const error = new Error(\n                `${err.name}: '${childName}' does not exist. Full path is '${path}'`,\n            );\n            error.name = err.name;\n            return error;\n        });\n    });\n}\n","import { Err, type AsyncVoidIOResult } from 'happy-rusty';\nimport { validateAbsolutePath } from '../../shared/internal/mod.ts';\nimport { getFileHandle } from '../internal/mod.ts';\n\n/**\n * Truncates (resizes) a file to the specified size.\n *\n * If `len` is smaller than the current file size, the file is shortened and\n * the trailing data is discarded. If `len` is larger, the file is extended\n * with zero bytes (`\\x00`).\n *\n * The file must already exist; this operation never creates a new file.\n * Truncating a directory path returns a `TypeMismatchError`.\n *\n * @param filePath - The absolute path of the file to truncate.\n * @param len - The target size in bytes. Must be a non-negative integer.\n * @returns A promise that resolves to an `AsyncVoidIOResult` indicating success or failure.\n * @since 2.2.0\n * @see {@link truncateSync} for synchronous version\n * @example\n * ```typescript\n * await writeFile('/log.txt', 'Hello, World!');\n * await truncate('/log.txt', 5);   // file now contains \"Hello\"\n * await truncate('/log.txt', 8);   // file now contains \"Hello\\x00\\x00\\x00\"\n * ```\n */\nexport async function truncate(filePath: string, len: number): AsyncVoidIOResult {\n    const filePathRes = validateAbsolutePath(filePath);\n    if (filePathRes.isErr()) return filePathRes.asErr();\n    filePath = filePathRes.unwrap();\n\n    if (!Number.isInteger(len) || len < 0) {\n        return Err(new TypeError(`Size must be a non-negative integer, got ${len}`));\n    }\n\n    const fileHandleRes = await getFileHandle(filePath, { create: false });\n    return fileHandleRes.andTryAsync(async fileHandle => {\n        // Prefer sync access handle in Worker for better performance\n        if (typeof fileHandle.createSyncAccessHandle === 'function') {\n            const accessHandle = await fileHandle.createSyncAccessHandle();\n            try {\n                accessHandle.truncate(len);\n            } finally {\n                accessHandle.close();\n            }\n            return;\n        }\n\n        // Main thread fallback: keep existing data, then resize\n        const writable = await fileHandle.createWritable({ keepExistingData: true });\n        try {\n            await writable.truncate(len);\n        } finally {\n            await writable.close();\n        }\n    });\n}\n","import { tryAsyncResult, type AsyncIOResult, type AsyncVoidIOResult } from 'happy-rusty';\nimport {\n    readBlobBytesSync,\n    toBytesView,\n    validateAbsolutePath,\n    validateWriteFileContent,\n} from '../../shared/internal/mod.ts';\nimport type { WriteFileContent, WriteOptions } from '../../shared/mod.ts';\nimport { generateTempPath } from '../../shared/mod.ts';\nimport { getFileHandle, isNotFoundError, moveFileHandle } from '../internal/mod.ts';\nimport { remove } from './remove.ts';\n\n/**\n * Writes content to a file at the specified path.\n * Creates the file and parent directories if they don't exist (unless `create: false`).\n *\n * Overwriting inside a Worker is written to a temporary file in `/tmp` first and moved into\n * place on success, so an interrupted write leaves the previous content untouched. The main\n * thread's `createWritable` writes a swap file instead and needs no temp file. Appending\n * always writes in place.\n *\n * @param filePath - The absolute path of the file to write to.\n * @param contents - The content to write (string, ArrayBuffer, TypedArray, Blob, or ReadableStream<Uint8Array>).\n * @param options - Optional write options.\n * @param options.create - Whether to create the file if it doesn't exist. Default: `true`.\n * @param options.append - Whether to append to the file instead of overwriting. Default: `false`.\n * @returns A promise that resolves to an `AsyncVoidIOResult` indicating success or failure.\n * @since 1.0.0\n * @see {@link writeFileSync} for synchronous version\n * @see {@link appendFile} for appending to files\n * @see {@link writeJsonFile} for writing JSON data\n * @example\n * ```typescript\n * // Write string content\n * await writeFile('/path/to/file.txt', 'Hello, World!');\n *\n * // Write binary content\n * await writeFile('/path/to/file.bin', new Uint8Array([1, 2, 3]));\n *\n * // Append to existing file\n * await writeFile('/path/to/file.txt', '\\nMore content', { append: true });\n * ```\n */\nexport async function writeFile(\n    filePath: string,\n    contents: WriteFileContent,\n    options?: WriteOptions,\n): AsyncVoidIOResult {\n    const filePathRes = validateAbsolutePath(filePath);\n    if (filePathRes.isErr()) return filePathRes.asErr();\n    filePath = filePathRes.unwrap();\n\n    // Validate content type at entry point to prevent silent failures\n    const contentRes = validateWriteFileContent(contents);\n    if (contentRes.isErr()) return contentRes.asErr();\n\n    // For stream content, use temp file strategy when creating new files\n    if (isBinaryReadableStream(contents)) {\n        return writeStreamToFile(filePath, contents, options);\n    }\n\n    const fileHandleRes = await getWriteFileHandle(filePath, options);\n    if (fileHandleRes.isErr()) {\n        return fileHandleRes.asErr();\n    }\n\n    const fileHandle = fileHandleRes.unwrap();\n    const { append = false } = options ?? {};\n\n    if (isSyncAccessHandleSupported(fileHandle)) {\n        if (!append) {\n            // Sync access handles write in place, so an overwrite is routed through a\n            // temp file: a failed write then leaves the target untouched.\n            return writeViaTempFile(filePath, tempHandle =>\n                tryAsyncResult(() => writeDataViaSyncAccess(tempHandle, contents, false)),\n            );\n        }\n\n        // Appending has to keep the existing content and stays in place\n        return tryAsyncResult(() => writeDataViaSyncAccess(fileHandle, contents, true));\n    }\n\n    // Main thread fallback: createWritable already writes a swap file\n    return tryAsyncResult(() => writeDataViaWritable(fileHandle, contents, append));\n}\n\n/**\n * Opens a file and returns a writable stream for writing contents.\n * Useful for writing large files without loading them entirely into memory.\n * The caller is responsible for closing the stream when done.\n *\n * @param filePath - The absolute path of the file to write.\n * @param options - Optional write options.\n * @returns A promise that resolves to an `AsyncIOResult` containing a `FileSystemWritableFileStream`.\n * @since 1.0.0\n * @see {@link writeFile} for general file writing\n * @example\n * ```typescript\n * (await openWritableFileStream('/path/to/large-file.bin'))\n *     .inspect(async stream => {\n *         try {\n *             await stream.write(new Uint8Array([1, 2, 3]));\n *             await stream.write(new Uint8Array([4, 5, 6]));\n *         } finally {\n *             await stream.close();\n *         }\n *     });\n * ```\n */\nexport async function openWritableFileStream(\n    filePath: string,\n    options?: WriteOptions,\n): AsyncIOResult<FileSystemWritableFileStream> {\n    const filePathRes = validateAbsolutePath(filePath);\n    if (filePathRes.isErr()) return filePathRes.asErr();\n    filePath = filePathRes.unwrap();\n\n    const fileHandleRes = await getWriteFileHandle(filePath, options);\n\n    return fileHandleRes.andTryAsync(async fileHandle => {\n        const { append = false } = options ?? {};\n\n        const writable = await fileHandle.createWritable({\n            keepExistingData: append,\n        });\n\n        // If appending, seek to end\n        if (append) {\n            try {\n                const { size } = await fileHandle.getFile();\n                await writable.seek(size);\n            } catch (err) {\n                await writable.close();\n                throw err;\n            }\n        }\n\n        return writable;\n    });\n}\n\n/**\n * Gets a file handle for writing, with optional creation.\n */\nfunction getWriteFileHandle(\n    filePath: string,\n    options?: WriteOptions,\n): AsyncIOResult<FileSystemFileHandle> {\n    const { create = true } = options ?? {};\n    return getFileHandle(filePath, { create });\n}\n\n/**\n * Type guard for detecting binary ReadableStream input for file writing.\n */\nfunction isBinaryReadableStream(x: unknown): x is ReadableStream<Uint8Array<ArrayBuffer>> {\n    return typeof ReadableStream !== 'undefined' && x instanceof ReadableStream;\n}\n\n/**\n * Whether the handle supports the worker-only synchronous access API.\n * Only available inside a Worker, where it is also the preferred (in-place) writer.\n */\nfunction isSyncAccessHandleSupported(fileHandle: FileSystemFileHandle): boolean {\n    return typeof fileHandle.createSyncAccessHandle === 'function';\n}\n\n/**\n * Writes a ReadableStream to a file.\n *\n * Strategy:\n * - The worker's sync access handle writes in place, so an overwrite is routed through a\n *   temp file that is moved into place: an interrupted stream then leaves the target\n *   untouched instead of truncated. Appending keeps the existing content and writes in place.\n * - The main thread's `createWritable` already writes a swap file, so the target survives\n *   an interruption either way.\n *\n * Assumes filePath is already validated.\n */\nasync function writeStreamToFile(\n    filePath: string,\n    stream: ReadableStream<Uint8Array<ArrayBuffer>>,\n    options?: WriteOptions,\n): AsyncVoidIOResult {\n    const { create = true, append = false } = options ?? {};\n\n    // Check if target file already exists\n    const existHandleRes = await getFileHandle(filePath, { create: false });\n\n    if (existHandleRes.isErr()) {\n        // File doesn't exist or unexpected error - return error if not creating or not a NotFoundError\n        if (!create || !isNotFoundError(existHandleRes.unwrapErr())) {\n            return existHandleRes.asErr();\n        }\n\n        // New file: a failed stream must not leave a partial file behind\n        return writeViaTempFile(filePath, tempHandle =>\n            writeStreamToHandle(tempHandle, stream, false),\n        );\n    }\n\n    const fileHandle = existHandleRes.unwrap();\n\n    // In-place writers cannot roll back, so overwriting goes through a temp file\n    if (!append && isSyncAccessHandleSupported(fileHandle)) {\n        return writeViaTempFile(filePath, tempHandle =>\n            writeStreamToHandle(tempHandle, stream, false),\n        );\n    }\n\n    return writeStreamToHandle(fileHandle, stream, append);\n}\n\n/**\n * Writes through a temporary file in `/tmp` and moves it into place, so a failed write\n * cannot damage the target: the destination keeps its previous content until the move.\n *\n * The move is a rename (metadata only), so the extra cost does not grow with the content\n * size. Used by the in-place writers - sync access handles have no swap file to roll back.\n *\n * Assumes filePath is already validated.\n *\n * @param filePath - The destination absolute path.\n * @param writeToTemp - Writes the content to the provided temp file handle.\n * @returns A promise that resolves to an `AsyncVoidIOResult` indicating success or failure.\n */\nasync function writeViaTempFile(\n    filePath: string,\n    writeToTemp: (tempHandle: FileSystemFileHandle) => AsyncVoidIOResult,\n): AsyncVoidIOResult {\n    const tempPath = generateTempPath();\n    const tempHandleRes = await getFileHandle(tempPath, { create: true });\n    if (tempHandleRes.isErr()) {\n        return tempHandleRes.asErr();\n    }\n\n    const tempHandle = tempHandleRes.unwrap();\n    const writeRes = await writeToTemp(tempHandle);\n\n    if (writeRes.isErr()) {\n        // Clean up temp file on failure\n        await remove(tempPath);\n        return writeRes;\n    }\n\n    // Move temp file to target path (this creates parent directories if needed)\n    const moveRes = await moveFileHandle(tempHandle, filePath);\n    if (moveRes.isErr()) {\n        // Clean up temp file\n        await remove(tempPath);\n    }\n\n    return moveRes;\n}\n\n/**\n * Writes a stream to a file handle using the appropriate API.\n */\nasync function writeStreamToHandle(\n    fileHandle: FileSystemFileHandle,\n    stream: ReadableStream<Uint8Array<ArrayBuffer>>,\n    append: boolean,\n): AsyncVoidIOResult {\n    return tryAsyncResult(() => {\n        // Prefer sync access in Worker for better performance\n        if (isSyncAccessHandleSupported(fileHandle)) {\n            return writeStreamViaSyncAccess(fileHandle, stream, append);\n        }\n        // Main thread fallback\n        return writeStreamViaWritable(fileHandle, stream, append);\n    });\n}\n\n/**\n * Writes a ReadableStream to a file using the main thread's FileSystemWritableFileStream API.\n */\nasync function writeStreamViaWritable(\n    fileHandle: FileSystemFileHandle,\n    stream: ReadableStream<Uint8Array<ArrayBuffer>>,\n    append: boolean,\n): Promise<void> {\n    const writable = await fileHandle.createWritable({\n        keepExistingData: append,\n    });\n\n    if (append) {\n        const { size } = await fileHandle.getFile();\n        await writable.seek(size);\n    }\n\n    return stream.pipeTo(writable);\n}\n\n/**\n * Writes non-stream data to a file using the main thread's FileSystemWritableFileStream API.\n */\nasync function writeDataViaWritable(\n    fileHandle: FileSystemFileHandle,\n    contents: Exclude<WriteFileContent, ReadableStream>,\n    append: boolean,\n): Promise<void> {\n    const writable = await fileHandle.createWritable({\n        keepExistingData: append,\n    });\n\n    try {\n        const params: WriteParams = {\n            type: 'write',\n            data: contents,\n        };\n\n        if (append) {\n            const { size } = await fileHandle.getFile();\n            params.position = size;\n        }\n\n        return writable.write(params);\n    } finally {\n        await writable.close();\n    }\n}\n\n/**\n * Writes a ReadableStream to a file using the Worker's FileSystemSyncAccessHandle API.\n *\n * This writes in place (there is no swap file), so callers that must not leave a\n * truncated file behind route overwrites through {@link writeViaTempFile}; appending\n * is always in place.\n */\nasync function writeStreamViaSyncAccess(\n    fileHandle: FileSystemFileHandle,\n    stream: ReadableStream<Uint8Array<ArrayBuffer>>,\n    append: boolean,\n): Promise<void> {\n    const accessHandle = await fileHandle.createSyncAccessHandle();\n\n    try {\n        if (!append) {\n            accessHandle.truncate(0);\n        }\n\n        let position = append ? accessHandle.getSize() : 0;\n\n        for await (const chunk of stream) {\n            position = writeBytesWithRetry(accessHandle, chunk, position);\n        }\n    } finally {\n        accessHandle.close();\n    }\n}\n\n/**\n * Writes non-stream data to a file using the Worker's FileSystemSyncAccessHandle API.\n *\n * Like {@link writeStreamViaSyncAccess} this writes in place, so overwrites are routed\n * through {@link writeViaTempFile} by the caller.\n */\nasync function writeDataViaSyncAccess(\n    fileHandle: FileSystemFileHandle,\n    contents: Exclude<WriteFileContent, ReadableStream>,\n    append: boolean,\n): Promise<void> {\n    const accessHandle = await fileHandle.createSyncAccessHandle();\n\n    try {\n        // Always write as Uint8Array to avoid copying buffer.\n        // Blob must be handled separately (readBlobBytesSync) before toBytesView,\n        // since toBytesView does not accept Blob.\n        const bytes =\n            contents instanceof Blob ? readBlobBytesSync(contents) : toBytesView(contents);\n\n        if (!append) {\n            accessHandle.truncate(0);\n        }\n\n        const position = append ? accessHandle.getSize() : 0;\n        writeBytesWithRetry(accessHandle, bytes, position);\n    } finally {\n        accessHandle.close();\n    }\n}\n\n/**\n * Writes bytes to a FileSystemSyncAccessHandle with retry logic for partial writes.\n * Returns the final position after writing.\n */\nfunction writeBytesWithRetry(\n    accessHandle: FileSystemSyncAccessHandle,\n    bytes: Uint8Array<ArrayBuffer>,\n    position: number,\n): number {\n    let remaining = bytes;\n    let currentPosition = position;\n\n    while (remaining.byteLength > 0) {\n        const written = accessHandle.write(remaining, {\n            at: currentPosition,\n        });\n\n        currentPosition += written;\n\n        if (written >= remaining.byteLength) {\n            break;\n        }\n\n        // Create a new Uint8Array for the remaining part without copying buffer.\n        remaining = remaining.subarray(written);\n    }\n\n    return currentPosition;\n}\n","import {\n    Err,\n    Ok,\n    RESULT_FALSE,\n    RESULT_VOID,\n    tryAsyncResult,\n    tryResult,\n    type AsyncIOResult,\n    type AsyncVoidIOResult,\n} from 'happy-rusty';\nimport {\n    join,\n    SEPARATOR,\n    validateAbsolutePath,\n    validateExistsOptions,\n} from '../shared/internal/mod.ts';\nimport {\n    isDirectoryHandle,\n    isFileHandle,\n    type AppendOptions,\n    type CopyOptions,\n    type ExistsOptions,\n    type MoveOptions,\n    type WriteFileContent,\n} from '../shared/mod.ts';\nimport { mkdir, readDir, readFile, remove, stat, writeFile } from './core/mod.ts';\nimport {\n    aggregateResults,\n    isNotFoundError,\n    isRootDir,\n    markParentDirsNonEmpty,\n    moveFileHandle,\n} from './internal/mod.ts';\n\n/**\n * Appends content to a file at the specified path.\n * Creates the file if it doesn't exist (unless `create: false` is specified).\n *\n * @param filePath - The absolute path of the file to append to.\n * @param contents - The content to append (string, ArrayBuffer, TypedArray, or Blob).\n * @param options - Optional append options.\n * @param options.create - Whether to create the file if it doesn't exist. Default: `true`.\n * @returns A promise that resolves to an `AsyncVoidIOResult` indicating success or failure.\n * @since 1.0.0\n * @see {@link writeFile} with `append: true` option\n * @example\n * ```typescript\n * // Append to file, create if doesn't exist (default behavior)\n * await appendFile('/path/to/log.txt', 'New log entry\\n');\n *\n * // Append only if file exists, fail if it doesn't\n * await appendFile('/path/to/log.txt', 'New log entry\\n', { create: false });\n * ```\n */\nexport function appendFile(\n    filePath: string,\n    contents: WriteFileContent,\n    options?: AppendOptions,\n): AsyncVoidIOResult {\n    return writeFile(filePath, contents, {\n        append: true,\n        create: options?.create,\n    });\n}\n\n/**\n * Copies a file or directory from one location to another, similar to `cp -r`.\n * Both source and destination must be of the same type (both files or both directories).\n *\n * With `{ overwrite: false }` existing entries are skipped individually while the\n * rest of the source is still copied (similar to `cp -rn`).\n *\n * @param srcPath - The absolute source path.\n * @param destPath - The absolute destination path.\n * @param options - Optional copy options.\n * @param options.overwrite - Whether to overwrite existing files. Default: `true`.\n * @returns A promise that resolves to an `AsyncVoidIOResult` indicating success or failure.\n * @since 1.7.0\n * @see {@link move} for moving instead of copying\n * @example\n * ```typescript\n * // Copy a file\n * await copy('/src/file.txt', '/dest/file.txt');\n *\n * // Copy a directory\n * await copy('/src/folder', '/dest/folder');\n *\n * // Copy without overwriting existing files\n * await copy('/src', '/dest', { overwrite: false });\n * ```\n */\nexport async function copy(\n    srcPath: string,\n    destPath: string,\n    options?: CopyOptions,\n): AsyncVoidIOResult {\n    const copyRes = await mkDestFromSrc(\n        srcPath,\n        destPath,\n        copyFileHandle,\n        'copy',\n        options?.overwrite,\n    );\n    // Skipped entries are not an error for `copy` - it keeps merging the remaining ones\n    return copyRes.and(RESULT_VOID);\n}\n\n/**\n * Empties all contents of a directory at the specified path.\n * If the directory doesn't exist, it will be created.\n *\n * @param dirPath - The absolute path of the directory to empty.\n * @returns A promise that resolves to an `AsyncVoidIOResult` indicating success or failure.\n * @since 1.0.9\n * @see {@link mkdir} for creating directories\n * @see {@link remove} for removing directories\n * @example\n * ```typescript\n * await emptyDir('/path/to/directory');\n * ```\n */\nexport async function emptyDir(dirPath: string): AsyncVoidIOResult {\n    // For root directory, remove() clears all contents\n    if (isRootDir(dirPath)) {\n        return remove(dirPath);\n    }\n\n    // Check if path is a directory\n    const statRes = await stat(dirPath);\n    if (statRes.isErr()) {\n        // Create if not exist\n        return isNotFoundError(statRes.unwrapErr()) ? mkdir(dirPath) : statRes.asErr();\n    }\n\n    if (isFileHandle(statRes.unwrap())) {\n        return Err(new Error(`Path '${dirPath}' is not a directory`));\n    }\n\n    // Remove and recreate directory (OPFS has no metadata to preserve)\n    const removeRes = await remove(dirPath);\n    return removeRes.andThenAsync(() => mkdir(dirPath));\n}\n\n/**\n * Checks whether a file or directory exists at the specified path.\n *\n * @param path - The absolute path to check.\n * @param options - Optional existence options. Set `isDirectory: true` to check for directory,\n *                  or `isFile: true` to check for file. Cannot set both to `true`.\n * @returns A promise that resolves to an `AsyncIOResult<boolean>` indicating existence.\n * @since 1.0.0\n * @see {@link existsSync} for synchronous version\n * @see {@link stat} for getting the handle\n * @example\n * ```typescript\n * // Check if path exists (file or directory)\n * const exists = await exists('/path/to/entry');\n *\n * // Check if path exists and is a file\n * const isFile = await exists('/path/to/file', { isFile: true });\n *\n * // Check if path exists and is a directory\n * const isDir = await exists('/path/to/dir', { isDirectory: true });\n * ```\n */\nexport async function exists(path: string, options?: ExistsOptions): AsyncIOResult<boolean> {\n    const optionsRes = validateExistsOptions(options);\n    if (optionsRes.isErr()) return optionsRes.asErr();\n\n    const statRes = await stat(path);\n\n    return statRes\n        .map(handle => {\n            const { isDirectory = false, isFile = false } = options ?? {};\n            const notExist =\n                (isDirectory && isFileHandle(handle)) || (isFile && isDirectoryHandle(handle));\n            return !notExist;\n        })\n        .orElse(err => {\n            return isNotFoundError(err) ? RESULT_FALSE : statRes.asErr();\n        });\n}\n\n/**\n * Moves a file or directory from one location to another.\n * Both source and destination must be of the same type (both files or both directories).\n *\n * With `{ overwrite: false }` the move follows `mv -n` semantics: when the destination\n * already exists the operation is a no-op, leaving both the destination and the\n * source untouched. The source is only removed once the transfer has actually\n * happened, so a skipped move can never destroy data.\n *\n * @param srcPath - The absolute source path.\n * @param destPath - The absolute destination path.\n * @param options - Optional move options.\n * @param options.overwrite - Whether to overwrite existing files. Default: `true`.\n * @returns A promise that resolves to an `AsyncVoidIOResult` indicating success or failure.\n * @since 1.8.0\n * @see {@link copy} for copying instead of moving\n * @example\n * ```typescript\n * // Move/rename a file\n * await move('/old/path/file.txt', '/new/path/file.txt');\n *\n * // Move a directory\n * await move('/old/folder', '/new/folder');\n *\n * // Keep both files when the destination already exists\n * await move('/old/file.txt', '/new/file.txt', { overwrite: false });\n * ```\n */\nexport async function move(\n    srcPath: string,\n    destPath: string,\n    options?: MoveOptions,\n): AsyncVoidIOResult {\n    const mkRes = await mkDestFromSrc(\n        srcPath,\n        destPath,\n        moveFileHandle,\n        'move',\n        options?.overwrite,\n    );\n\n    // `remove` must only run when something was transferred: after a skipped\n    // move the source is still the only copy of the data. The caller cannot\n    // derive this from `overwrite` alone - `overwrite: false` still transfers\n    // when the destination does not exist, and only the helper knows that.\n    return mkRes.andThenAsync(outcome => {\n        return outcome === 'skipped' ? RESULT_VOID : remove(srcPath);\n    });\n}\n\n/**\n * Reads the content of a file as a `File` object (Blob with name).\n *\n * @param filePath - The absolute path of the file to read.\n * @returns A promise that resolves to an `AsyncIOResult` containing the `File` object.\n * @since 1.0.0\n * @see {@link readFile} with `encoding: 'blob'`\n * @see {@link uploadFile} for uploading files\n * @example\n * ```typescript\n * (await readBlobFile('/path/to/file.txt'))\n *     .inspect(file => console.log(file.name, file.size, file.type));\n * ```\n */\nexport function readBlobFile(filePath: string): AsyncIOResult<File> {\n    return readFile(filePath, {\n        encoding: 'blob',\n    });\n}\n\n/**\n * Reads a JSON file and parses its content.\n *\n * @template T - The expected type of the parsed JSON object.\n * @param filePath - The path of the JSON file to read.\n * @returns A promise that resolves to an `AsyncIOResult` containing the parsed JSON object.\n * @since 1.8.4\n * @see {@link writeJsonFile} for the reverse operation\n * @see {@link readTextFile} for reading raw text\n * @example\n * ```typescript\n * interface Config {\n *     name: string;\n *     version: number;\n * }\n * (await readJsonFile<Config>('/config.json'))\n *     .inspect(config => console.log(config.name));\n * ```\n */\nexport async function readJsonFile<T>(filePath: string): AsyncIOResult<T> {\n    const readRes = await readTextFile(filePath);\n    return readRes.andThen(text => tryResult<T, Error, [string]>(JSON.parse, text));\n}\n\n/**\n * Reads a file as a UTF-8 string.\n *\n * @param filePath - The absolute path of the file to read.\n * @returns A promise that resolves to an `AsyncIOResult` containing the file content as a string.\n * @since 1.0.0\n * @see {@link readFile} with `encoding: 'utf8'`\n * @see {@link readJsonFile} for reading JSON files\n * @example\n * ```typescript\n * (await readTextFile('/path/to/file.txt'))\n *     .inspect(content => console.log(content));\n * ```\n */\nexport function readTextFile(filePath: string): AsyncIOResult<string> {\n    return readFile(filePath, {\n        encoding: 'utf8',\n    });\n}\n\n/**\n * Writes an object to a file as JSON.\n *\n * @template T - The type of the object to write.\n * @param filePath - The absolute path of the file to write.\n * @param data - The object to serialize and write.\n * @returns A promise that resolves to an `AsyncVoidIOResult` indicating success or failure.\n * @since 1.0.0\n * @see {@link readJsonFile} for the reverse operation\n * @see {@link writeFile} for writing raw content\n * @example\n * ```typescript\n * const config = { name: 'app', version: 1 };\n * (await writeJsonFile('/config.json', config))\n *     .inspect(() => console.log('Config saved'));\n * ```\n */\nexport function writeJsonFile<T>(filePath: string, data: T): AsyncVoidIOResult {\n    const result = tryResult(JSON.stringify, data);\n    return result.andThenAsync(text => writeFile(filePath, text));\n}\n\n// #region Internal Types\n\n/**\n * Handler function type for processing source file to destination.\n *\n * @param srcFileHandle - The source file handle to process.\n * @param destFilePath - The destination file path.\n */\ntype HandleSrcFileToDest = (\n    srcFileHandle: FileSystemFileHandle,\n    destFilePath: string,\n) => AsyncVoidIOResult;\n\n/**\n * Outcome of {@link mkDestFromSrc}, needed by `move` to decide whether the source\n * may be removed: `'skipped'` means the destination was left untouched because\n * `overwrite` is `false`, so the source is still the only copy of the data.\n * A transfer that happened carries no value of its own.\n */\ntype TransferOutcome = 'skipped' | void;\n\n// #endregion\n\n// #region Internal Functions\n\n/**\n * Creates the error for a copy/move whose destination lies inside the source: a directory\n * would recurse forever, and the root directory contains every other path.\n *\n * @param opName - The operation name ('copy' or 'move').\n * @param srcPath - The source path.\n * @param destPath - The rejected destination path.\n * @returns The `Error` describing the rejected operation.\n */\nfunction createIntoItselfError(opName: 'copy' | 'move', srcPath: string, destPath: string): Error {\n    return new Error(`Cannot ${opName} '${srcPath}' into itself '${destPath}'`);\n}\n\n/**\n * Copies a file handle to a new path by reading and writing the file content.\n *\n * @param fileHandle - The file handle to copy.\n * @param destFilePath - The destination absolute path for the file.\n * @returns A promise that resolves to an `AsyncVoidIOResult` indicating success or failure.\n */\nasync function copyFileHandle(\n    fileHandle: FileSystemFileHandle,\n    destFilePath: string,\n): AsyncVoidIOResult {\n    const fileRes = await tryAsyncResult(fileHandle.getFile());\n    return fileRes.andThenAsync(file => writeFile(destFilePath, file));\n}\n\n/**\n * Internal helper that copies or moves a file/directory from source to destination.\n *\n * Algorithm:\n * 1. Verify source exists via stat()\n * 2. Check if destination exists and validate type compatibility (file-to-file or dir-to-dir)\n * 3. Respect overwrite flag:\n *    - `move` with `overwrite: false` is a no-op when the destination exists (`mv -n`),\n *      because a partially skipped tree could not be removed safely afterwards\n *    - `copy` with `overwrite: false` skips existing entries individually and keeps going\n * 4. For files: directly apply handler (copy or move)\n * 5. For directories: recursively process all entries in parallel\n *\n * @param srcPath - The source file/directory path.\n * @param destPath - The destination file/directory path.\n * @param handler - The function to handle file transfer (copy or move).\n * @param opName - The operation name for error messages ('copy' or 'move').\n * @param overwrite - Whether to overwrite existing files. Default: `true`.\n * @returns A promise that resolves to an `AsyncIOResult` which is `'skipped'` when the\n *          destination was left untouched, otherwise a plain success.\n */\nasync function mkDestFromSrc(\n    srcPath: string,\n    destPath: string,\n    handler: HandleSrcFileToDest,\n    opName: 'copy' | 'move',\n    overwrite = true,\n): AsyncIOResult<TransferOutcome> {\n    const srcPathRes = validateAbsolutePath(srcPath);\n    if (srcPathRes.isErr()) return srcPathRes.asErr();\n    srcPath = srcPathRes.unwrap();\n\n    const destPathRes = validateAbsolutePath(destPath);\n    if (destPathRes.isErr()) return destPathRes.asErr();\n    destPath = destPathRes.unwrap();\n\n    // Same path and a root source are pure path relations, so both are checked before\n    // touching the file system\n    if (destPath === srcPath) {\n        return Err(new Error(`Source and destination are the same: '${srcPath}'`));\n    }\n    if (isRootDir(srcPath)) {\n        return Err(createIntoItselfError(opName, srcPath, destPath));\n    }\n\n    const statRes = await stat(srcPath);\n    if (statRes.isErr()) {\n        return statRes.asErr();\n    }\n\n    const srcHandle = statRes.unwrap();\n\n    // A destination below a directory source would recurse forever. A destination below a\n    // *file* source cannot exist at all, so it falls through to the destination lookup\n    // below, which reports the real problem instead of claiming that the file would\n    // contain itself.\n    if (isDirectoryHandle(srcHandle) && destPath.startsWith(srcPath + SEPARATOR)) {\n        return Err(createIntoItselfError(opName, srcPath, destPath));\n    }\n\n    // Track whether destination already exists (needed for overwrite logic)\n    let destExists = false;\n\n    const destHandleRes = await stat(destPath);\n    if (destHandleRes.isErr()) {\n        // Destination doesn't exist - that's OK unless it's an unexpected error\n        if (!isNotFoundError(destHandleRes.unwrapErr())) {\n            return destHandleRes.asErr();\n        }\n    } else {\n        destExists = true;\n        // Validate type compatibility: both must be files OR both must be directories\n        const destHandle = destHandleRes.unwrap();\n        if (\n            !(isFileHandle(srcHandle) && isFileHandle(destHandle)) &&\n            !(isDirectoryHandle(srcHandle) && isDirectoryHandle(destHandle))\n        ) {\n            return Err(\n                new Error(\n                    `Source '${srcPath}' and destination '${destPath}' must both be files or both be directories`,\n                ),\n            );\n        }\n    }\n\n    // `mv -n`: a no-clobber move onto an existing destination is all-or-nothing,\n    // so the whole operation is skipped instead of leaving a half-moved tree behind\n    if (opName === 'move' && !overwrite && destExists) {\n        return Ok('skipped');\n    }\n\n    // Handle file source: apply handler directly\n    if (isFileHandle(srcHandle)) {\n        // `copy` no-clobber: skip this single entry, the caller keeps the rest of the operation\n        if (opName === 'copy' && !overwrite && destExists) {\n            return Ok('skipped');\n        }\n\n        return handler(srcHandle, destPath);\n    }\n\n    // Handle directory source: recursively process all entries\n    const readDirRes = await readDir(srcPath, {\n        recursive: true,\n    });\n    if (readDirRes.isErr()) {\n        return readDirRes.asErr();\n    }\n\n    // Collect all tasks for parallel execution\n    const tasks: AsyncVoidIOResult[] = [];\n    const dirs: string[] = [];\n    const nonEmptyDirs = new Set<string>();\n\n    try {\n        for await (const { path, handle } of readDirRes.unwrap()) {\n            if (isFileHandle(handle)) {\n                const newFilePath = join(destPath, path);\n\n                // Wrap file processing in an async IIFE for parallel execution\n                tasks.push(\n                    (async () => {\n                        let newPathExists = false;\n\n                        if (destExists) {\n                            // Destination dir exists, need to check each file individually\n                            const existsRes = await exists(newFilePath);\n                            if (existsRes.isErr()) {\n                                return existsRes.asErr();\n                            }\n\n                            newPathExists = existsRes.unwrap();\n                        }\n\n                        return overwrite || !newPathExists\n                            ? handler(handle, newFilePath)\n                            : RESULT_VOID;\n                    })(),\n                );\n\n                // Mark all parent directories as non-empty\n                markParentDirsNonEmpty(path, nonEmptyDirs);\n            } else {\n                dirs.push(path);\n            }\n        }\n    } catch (e) {\n        return Err(e as Error);\n    }\n\n    // Only create truly empty directories\n    for (const dir of dirs) {\n        if (!nonEmptyDirs.has(dir)) {\n            tasks.push(mkdir(join(destPath, dir)));\n        }\n    }\n\n    // Handle empty source directory case\n    if (tasks.length === 0 && !destExists) {\n        return mkdir(destPath);\n    }\n\n    // Wait for all tasks and return first error if any\n    return aggregateResults(tasks);\n}\n\n// #endregion\n","/**\n * Internal helper utilities for archive operations.\n *\n * @internal\n * @module\n */\n\nimport { Err, RESULT_VOID, type AsyncIOResult, type VoidIOResult } from 'happy-rusty';\nimport { join, normalize, SEPARATOR, validateAbsolutePath } from '../../shared/internal/mod.ts';\nimport { ROOT_DIR } from '../../shared/mod.ts';\nimport { exists } from '../ext.ts';\n\n/**\n * Empty bytes constant, used for directory entries in zip or empty file content.\n */\nexport const EMPTY_BYTES: Uint8Array<ArrayBuffer> = /*#__PURE__*/ new Uint8Array(0);\n\n/**\n * Validates that an archive entry name stays inside the destination directory.\n *\n * Entry names come from the archive and are therefore untrusted: a name like\n * `../evil.txt` resolves outside of `destDir` and would overwrite unrelated\n * files in the origin private file system (zip-slip). Names that resolve to\n * `destDir` itself are accepted, because archives created by tools such as\n * `zip -r archive.zip .` legitimately contain such a root entry.\n *\n * @param entryName - The entry name as stored in the archive.\n * @param destDir - The normalized destination directory path.\n * @returns A `VoidIOResult` indicating whether the entry may be extracted.\n */\nexport function validateArchiveEntry(entryName: string, destDir: string): VoidIOResult {\n    // `join` keeps absolute names inside destDir, but `..` segments can escape it\n    const target = normalize(join(destDir, entryName));\n    const isInside =\n        target === destDir ||\n        target.startsWith(destDir === ROOT_DIR ? ROOT_DIR : destDir + SEPARATOR);\n\n    return isInside\n        ? RESULT_VOID\n        : Err(\n              new Error(\n                  `Archive entry '${entryName}' would escape the destination directory '${destDir}'`,\n              ),\n          );\n}\n\n/**\n * Validates that destDir is an absolute path and is not an existing file.\n * If destDir doesn't exist, that's fine (it will be created).\n * If destDir exists and is a directory, that's fine.\n * If destDir exists and is a file, return an error.\n *\n * @param destDir - The destination directory path to validate.\n * @returns An `AsyncIOResult` containing the normalized path, or an error.\n */\nexport async function validateDestDir(destDir: string): AsyncIOResult<string> {\n    const pathRes = validateAbsolutePath(destDir);\n    if (pathRes.isErr()) return pathRes;\n    destDir = pathRes.unwrap();\n\n    const existsRes = await exists(destDir, { isFile: true });\n\n    return existsRes.andThen(isFile => {\n        return isFile ? Err(new Error(`Path '${destDir}' is not a directory`)) : pathRes;\n    });\n}\n","import { fetchT } from '@happy-ts/fetch-t';\nimport { AsyncUnzipInflate, Unzip, UnzipPassThrough, type UnzipFile } from 'fflate/browser';\nimport { Err, type AsyncIOResult, type AsyncVoidIOResult } from 'happy-rusty';\nimport { join, SEPARATOR, validateUrl } from '../../shared/internal/mod.ts';\nimport type { UnzipFromUrlRequestInit } from '../../shared/mod.ts';\nimport { mkdir, readFile, writeFile } from '../core/mod.ts';\nimport {\n    aggregateResults,\n    createEmptyBodyError,\n    createEmptyFileError,\n    markParentDirsNonEmpty,\n} from '../internal/mod.ts';\nimport { EMPTY_BYTES, validateArchiveEntry, validateDestDir } from './helpers.ts';\n\n/**\n * Unzip a zip file to a directory using streaming decompression.\n * Equivalent to `unzip -o <zipFilePath> -d <destDir>`\n *\n * This function processes the zip file incrementally, minimizing memory usage.\n * Recommended for large files (>10MB). For small files, consider using {@link unzip} instead.\n *\n * Entries that would be written outside of `destDir` (zip-slip) fail the whole\n * operation instead of being extracted.\n *\n * Use [fflate](https://github.com/101arrowz/fflate) as the unzip backend.\n *\n * @param zipFilePath - Zip file path.\n * @param destDir - The directory to unzip to.\n * @returns A promise that resolves to an `AsyncIOResult` indicating whether the zip file was successfully unzipped.\n * @since 2.0.0\n * @see {@link unzip} for batch version (faster for small files)\n * @see {@link zipStream} for the reverse operation\n * @example\n * ```typescript\n * (await unzipStream('/downloads/large-archive.zip', '/extracted'))\n *     .inspect(() => console.log('Unzipped successfully'));\n * ```\n */\nexport async function unzipStream(zipFilePath: string, destDir: string): AsyncVoidIOResult {\n    return unzipStreamWith(\n        () => readFile(zipFilePath, { encoding: 'stream' }),\n        destDir,\n        createEmptyFileError,\n    );\n}\n\n/**\n * Unzip a remote zip file to a directory using streaming decompression.\n * Equivalent to `unzip -o <zipFilePath> -d <destDir>`\n *\n * This function processes the zip file incrementally, minimizing memory usage.\n * Recommended for large files (>10MB). For small files, consider using {@link unzipFromUrl} instead.\n *\n * Use [fflate](https://github.com/101arrowz/fflate) as the unzip backend.\n *\n * This API is built on `@happy-ts/fetch-t` for downloading the zip file.\n * `options` supports `timeout` and `onProgress` options.\n *\n * @param zipFileUrl - Zip file url.\n * @param destDir - The directory to unzip to.\n * @param requestInit - Optional request options.\n * @returns A promise that resolves to an `AsyncIOResult` indicating whether the zip file was successfully unzipped.\n * @since 2.0.0\n * @see {@link unzipFromUrl} for batch version (faster for small files)\n * @see {@link zipStreamFromUrl} for the reverse operation\n * @example\n * ```typescript\n * (await unzipStreamFromUrl('https://example.com/large-archive.zip', '/extracted'))\n *     .inspect(() => console.log('Remote zip file unzipped successfully'));\n *\n * // With timeout\n * (await unzipStreamFromUrl('https://example.com/archive.zip', '/extracted', { timeout: 30000 }))\n *     .inspect(() => console.log('Remote zip file unzipped successfully'));\n * ```\n */\nexport async function unzipStreamFromUrl(\n    zipFileUrl: string | URL,\n    destDir: string,\n    requestInit?: UnzipFromUrlRequestInit,\n): AsyncVoidIOResult {\n    const zipFileUrlRes = validateUrl(zipFileUrl);\n    if (zipFileUrlRes.isErr()) return zipFileUrlRes.asErr();\n    zipFileUrl = zipFileUrlRes.unwrap();\n\n    return unzipStreamWith(\n        () =>\n            fetchT(zipFileUrl, {\n                redirect: 'follow',\n                ...requestInit,\n                responseType: 'stream',\n                abortable: false,\n            }),\n        destDir,\n        createEmptyBodyError,\n    );\n}\n\n// #region Internal Functions\n\n/**\n * Common streaming unzip implementation for both local and remote sources.\n * @param getStream - Function to get the readable stream.\n * @param destDir - Destination directory path.\n * @param createEmptyError - Function to create error for empty data.\n */\nasync function unzipStreamWith(\n    getStream: () => AsyncIOResult<ReadableStream<Uint8Array<ArrayBuffer>> | null>,\n    destDir: string,\n    createEmptyError: () => Error,\n): AsyncVoidIOResult {\n    const destDirRes = await validateDestDir(destDir);\n    if (destDirRes.isErr()) return destDirRes.asErr();\n    destDir = destDirRes.unwrap();\n\n    const streamRes = await getStream();\n    if (streamRes.isErr()) return streamRes.asErr();\n    const stream = streamRes.unwrap();\n\n    // stream can be null for 204/304 responses\n    if (!stream) {\n        return Err(createEmptyError());\n    }\n\n    return streamUnzipTo(stream, destDir, createEmptyError);\n}\n\n/**\n * Stream unzip from a ReadableStream to destination directory.\n * Uses fflate's streaming Unzip API to minimize memory usage.\n *\n * @param stream - The readable stream containing zip data.\n * @param destDir - Destination directory path.\n * @param createEmptyError - Function to create error for empty data.\n */\nasync function streamUnzipTo(\n    stream: ReadableStream<Uint8Array<ArrayBuffer>>,\n    destDir: string,\n    createEmptyError: () => Error,\n): AsyncVoidIOResult {\n    // Track directories and files for proper handling\n    const tasks: AsyncVoidIOResult[] = [];\n    const dirs: string[] = [];\n    const nonEmptyDirs = new Set<string>();\n    let hasData = false;\n    let entryError: Error | null = null;\n\n    const unzipper = new Unzip();\n    // Register decompression handlers\n    unzipper.register(UnzipPassThrough); // For stored (uncompressed) files\n    unzipper.register(AsyncUnzipInflate); // For deflated files\n\n    unzipper.onfile = file => {\n        if (entryError) {\n            // Stop scheduling work after the first unsafe entry\n            return;\n        }\n\n        const path = file.name;\n\n        // Entry names are untrusted: reject anything resolving outside destDir\n        const entryRes = validateArchiveEntry(path, destDir);\n        if (entryRes.isErr()) {\n            entryError = entryRes.unwrapErr();\n            return;\n        }\n\n        if (path.at(-1) === SEPARATOR) {\n            // Directory entry - collect for later creation\n            dirs.push(path.slice(0, -1));\n        } else {\n            // Create a promise for this file's extraction\n            tasks.push(extractFile(file, join(destDir, path)));\n            // File entry - mark parent directories as non-empty\n            markParentDirsNonEmpty(path, nonEmptyDirs);\n        }\n    };\n\n    try {\n        for await (const chunk of stream) {\n            hasData = true;\n            unzipper.push(chunk, false);\n\n            if (entryError) {\n                // Abandoning the loop cancels the stream - no point decompressing\n                // the rest of an archive that will be rejected\n                break;\n            }\n        }\n\n        if (!entryError) {\n            // Signal end of stream\n            unzipper.push(EMPTY_BYTES, true);\n        }\n    } catch (err) {\n        return Err(err as Error);\n    }\n\n    if (entryError) {\n        return Err(entryError);\n    }\n\n    // Empty stream check\n    if (!hasData) {\n        return Err(createEmptyError());\n    }\n\n    // Add empty directory creation tasks\n    for (const dir of dirs) {\n        if (!nonEmptyDirs.has(dir)) {\n            tasks.push(mkdir(join(destDir, dir)));\n        }\n    }\n\n    return aggregateResults(tasks);\n}\n\n/**\n * Extract a single file from the unzip stream using streaming write.\n *\n * @param file - The UnzipFile object from fflate.\n * @param destPath - The destination path for this file.\n */\nfunction extractFile(file: UnzipFile, destPath: string): AsyncVoidIOResult {\n    // Convert UnzipFile to ReadableStream\n    const stream = new ReadableStream<Uint8Array<ArrayBuffer>>({\n        start(controller) {\n            file.ondata = (err, data, final) => {\n                if (err) {\n                    controller.error(err);\n                    return;\n                }\n\n                controller.enqueue(data);\n\n                if (final) {\n                    controller.close();\n                }\n            };\n\n            file.start();\n        },\n    });\n\n    return writeFile(destPath, stream);\n}\n\n// #endregion\n","import { fetchT } from '@happy-ts/fetch-t';\nimport { unzip as decompress } from 'fflate/browser';\nimport { Err, type AsyncIOResult, type AsyncVoidIOResult, type VoidIOResult } from 'happy-rusty';\nimport { Future } from 'tiny-future';\nimport { join, SEPARATOR, validateUrl } from '../../shared/internal/mod.ts';\nimport type { UnzipFromUrlRequestInit } from '../../shared/mod.ts';\nimport { mkdir, readFile, writeFile } from '../core/mod.ts';\nimport {\n    aggregateResults,\n    createEmptyBodyError,\n    createEmptyFileError,\n    markParentDirsNonEmpty,\n} from '../internal/mod.ts';\nimport { validateArchiveEntry, validateDestDir } from './helpers.ts';\n\n/**\n * Unzip a zip file to a directory using batch decompression.\n * Equivalent to `unzip -o <zipFilePath> -d <destDir>`\n *\n * This function loads the entire zip file into memory before decompression.\n * Faster for small files (<5MB). For large files, consider using {@link unzipStream} instead.\n *\n * Entries that would be written outside of `destDir` (zip-slip) fail the whole\n * operation instead of being extracted.\n *\n * Use [fflate](https://github.com/101arrowz/fflate) as the unzip backend.\n *\n * @param zipFilePath - Zip file path.\n * @param destDir - The directory to unzip to.\n * @returns A promise that resolves to an `AsyncIOResult` indicating whether the zip file was successfully unzipped.\n * @since 1.6.0\n * @see {@link unzipSync} for synchronous version\n * @see {@link unzipStream} for streaming version (better for large files)\n * @see {@link zip} for the reverse operation\n * @example\n * ```typescript\n * (await unzip('/downloads/archive.zip', '/extracted'))\n *     .inspect(() => console.log('Unzipped successfully'));\n * ```\n */\nexport async function unzip(zipFilePath: string, destDir: string): AsyncVoidIOResult {\n    return unzipWith(() => readFile(zipFilePath), destDir, createEmptyFileError);\n}\n\n/**\n * Unzip a remote zip file to a directory using batch decompression.\n * Equivalent to `unzip -o <zipFilePath> -d <destDir>`\n *\n * This function loads the entire zip file into memory before decompression.\n * Faster for small files (<5MB). For large files, consider using {@link unzipStreamFromUrl} instead.\n *\n * Use [fflate](https://github.com/101arrowz/fflate) as the unzip backend.\n *\n * This API is built on `@happy-ts/fetch-t` for downloading the zip file.\n * `options` supports `timeout` and `onProgress` options.\n *\n * @param zipFileUrl - Zip file url.\n * @param destDir - The directory to unzip to.\n * @param requestInit - Optional request options.\n * @returns A promise that resolves to an `AsyncIOResult` indicating whether the zip file was successfully unzipped.\n * @since 1.7.0\n * @see {@link unzipStreamFromUrl} for streaming version (better for large files)\n * @see {@link zipFromUrl} for the reverse operation\n * @example\n * ```typescript\n * (await unzipFromUrl('https://example.com/archive.zip', '/extracted'))\n *     .inspect(() => console.log('Remote zip file unzipped successfully'));\n *\n * // With timeout\n * (await unzipFromUrl('https://example.com/archive.zip', '/extracted', { timeout: 5000 }))\n *     .inspect(() => console.log('Remote zip file unzipped successfully'));\n * ```\n */\nexport async function unzipFromUrl(\n    zipFileUrl: string | URL,\n    destDir: string,\n    requestInit?: UnzipFromUrlRequestInit,\n): AsyncVoidIOResult {\n    const zipFileUrlRes = validateUrl(zipFileUrl);\n    if (zipFileUrlRes.isErr()) return zipFileUrlRes.asErr();\n    zipFileUrl = zipFileUrlRes.unwrap();\n\n    return unzipWith(\n        () =>\n            fetchT(zipFileUrl, {\n                redirect: 'follow',\n                ...requestInit,\n                responseType: 'bytes',\n                abortable: false,\n            }),\n        destDir,\n        createEmptyBodyError,\n    );\n}\n\n// #region Internal Functions\n\n/**\n * Common unzip implementation for both local and remote sources.\n * @param getBytes - Function to get zip data.\n * @param destDir - Destination directory path.\n * @param createEmptyError - Function to create error for empty data.\n */\nasync function unzipWith(\n    getBytes: () => AsyncIOResult<Uint8Array<ArrayBuffer>>,\n    destDir: string,\n    createEmptyError: () => Error,\n): AsyncVoidIOResult {\n    const destDirRes = await validateDestDir(destDir);\n    if (destDirRes.isErr()) return destDirRes.asErr();\n    destDir = destDirRes.unwrap();\n\n    const bytesRes = await getBytes();\n\n    return bytesRes.andThenAsync(bytes => {\n        return bytes.byteLength === 0 ? Err(createEmptyError()) : batchUnzipTo(bytes, destDir);\n    });\n}\n\n/**\n * Unzip a buffer then write to the destination directory.\n * @param bytes - Zipped Uint8Array.\n * @param destDir - Destination directory path.\n */\nfunction batchUnzipTo(bytes: Uint8Array<ArrayBuffer>, destDir: string): AsyncVoidIOResult {\n    const future = new Future<VoidIOResult>();\n\n    decompress(bytes, async (err, unzipped) => {\n        if (err) {\n            future.resolve(Err(err));\n            return;\n        }\n\n        // Collect all tasks for parallel execution\n        const tasks: AsyncVoidIOResult[] = [];\n        const dirs: string[] = [];\n        const nonEmptyDirs = new Set<string>();\n\n        for (const path in unzipped) {\n            // Entry names are untrusted: reject anything resolving outside destDir\n            const entryRes = validateArchiveEntry(path, destDir);\n            if (entryRes.isErr()) {\n                future.resolve(entryRes.asErr());\n                return;\n            }\n\n            if (path.at(-1) === SEPARATOR) {\n                // Collect directory entries without trailing slash\n                dirs.push(path.slice(0, -1));\n            } else {\n                // File entry - writeFile will create parent directories automatically\n                tasks.push(writeFile(join(destDir, path), unzipped[path]));\n                // Mark all parent directories as non-empty\n                markParentDirsNonEmpty(path, nonEmptyDirs);\n            }\n        }\n\n        // Only create truly empty directories\n        for (const dir of dirs) {\n            if (!nonEmptyDirs.has(dir)) {\n                tasks.push(mkdir(join(destDir, dir)));\n            }\n        }\n\n        future.resolve(aggregateResults(tasks));\n    });\n\n    return future.promise;\n}\n\n// #endregion\n","import { fetchT } from '@happy-ts/fetch-t';\nimport { Zip, ZipDeflate, ZipPassThrough, zipSync } from 'fflate/browser';\nimport { Err, tryAsyncResult, type AsyncVoidIOResult } from 'happy-rusty';\nimport {\n    basename,\n    join,\n    SEPARATOR,\n    validateAbsolutePath,\n    validateUrl,\n} from '../../shared/internal/mod.ts';\nimport {\n    isFileHandle,\n    type DirEntry,\n    type ZipFromUrlRequestInit,\n    type ZipLevel,\n    type ZipOptions,\n} from '../../shared/mod.ts';\nimport { readDir, stat, writeFile } from '../core/mod.ts';\nimport { createEmptyBodyError, createNothingToZipError, peekStream } from '../internal/mod.ts';\nimport { EMPTY_BYTES } from './helpers.ts';\n\n/**\n * Zip a file or directory using streaming compression.\n * Equivalent to `zip -r <zipFilePath> <sourcePath>`.\n *\n * This function processes files sequentially with streaming read/write,\n * minimizing memory usage. Recommended for large directories or files.\n * For better speed with small files, consider using {@link zip} instead.\n *\n * Use [fflate](https://github.com/101arrowz/fflate) as the zip backend.\n *\n * @param sourcePath - The path to be zipped.\n * @param zipFilePath - The path to the zip file.\n * @param options - Options of zip.\n * @returns A promise that resolves to an `AsyncIOResult` indicating whether the source was successfully zipped.\n * @since 2.0.0\n * @see {@link zip} for batch version (faster for small files)\n * @see {@link unzipStream} for the reverse operation\n * @example\n * ```typescript\n * // Stream zip a large directory\n * (await zipStream('/large-documents', '/backups/documents.zip'))\n *     .inspect(() => console.log('Directory zipped successfully'));\n * ```\n */\nexport async function zipStream(\n    sourcePath: string,\n    zipFilePath: string,\n    options?: ZipOptions,\n): AsyncVoidIOResult {\n    // Normalize before deriving entry names, otherwise `basename` would come from\n    // the raw path while the entry content is read from the normalized one\n    const sourcePathRes = validateAbsolutePath(sourcePath);\n    if (sourcePathRes.isErr()) return sourcePathRes.asErr();\n    sourcePath = sourcePathRes.unwrap();\n\n    const zipFilePathRes = validateAbsolutePath(zipFilePath);\n    if (zipFilePathRes.isErr()) return zipFilePathRes.asErr();\n    zipFilePath = zipFilePathRes.unwrap();\n\n    const statRes = await stat(sourcePath);\n    if (statRes.isErr()) return statRes.asErr();\n\n    const sourceHandle = statRes.unwrap();\n    const sourceName = basename(sourcePath);\n    const { level } = options ?? {};\n\n    if (isFileHandle(sourceHandle)) {\n        // Single file - stream read and compress\n        return streamZipFile(sourceHandle, sourceName, zipFilePath, level);\n    }\n\n    // Directory - stream compress entries directly\n    const readDirRes = await readDir(sourcePath, { recursive: true });\n    if (readDirRes.isErr()) return readDirRes.asErr();\n\n    const { preserveRoot = true } = options ?? {};\n    const entries = readDirRes.unwrap();\n\n    // Peek first entry to check if directory is empty\n    const firstRes = await tryAsyncResult(entries.next());\n    if (firstRes.isErr()) return firstRes.asErr();\n\n    const first = firstRes.unwrap();\n    if (first.done && !preserveRoot) {\n        // Empty directory with preserveRoot=false - nothing to zip\n        // Matches zip command: `zip -r archive.zip .` in empty dir returns \"Nothing to do!\"\n        return Err(createNothingToZipError());\n    }\n\n    return streamZipEntries(first, entries, sourceName, zipFilePath, preserveRoot, level);\n}\n\n/**\n * Zip a remote file using streaming compression.\n *\n * This function downloads and compresses the file in a streaming manner,\n * minimizing memory usage. Recommended for large remote files.\n * For small files, consider using {@link zipFromUrl} instead.\n *\n * Use [fflate](https://github.com/101arrowz/fflate) as the zip backend.\n *\n * This API is built on `@happy-ts/fetch-t` for downloading the source.\n * `requestInit` supports `timeout`, `onProgress`, and `filename` via {@link ZipFromUrlRequestInit}.\n *\n * @param sourceUrl - The url to be zipped.\n * @param zipFilePath - The path to the zip file.\n * @param requestInit - Optional request initialization parameters.\n * @returns A promise that resolves to an `AsyncIOResult` indicating whether the source was successfully zipped.\n * @since 2.0.0\n * @see {@link zipFromUrl} for batch version (faster for small files)\n * @see {@link unzipStreamFromUrl} for the reverse operation\n * @example\n * ```typescript\n * // Stream zip a large remote file\n * (await zipStreamFromUrl('https://example.com/large-file.bin', '/backups/file.zip'))\n *     .inspect(() => console.log('Remote file zipped successfully'));\n * ```\n */\nexport async function zipStreamFromUrl(\n    sourceUrl: string | URL,\n    zipFilePath: string,\n    requestInit?: ZipFromUrlRequestInit,\n): AsyncVoidIOResult {\n    const sourceUrlRes = validateUrl(sourceUrl);\n    if (sourceUrlRes.isErr()) return sourceUrlRes.asErr();\n    sourceUrl = sourceUrlRes.unwrap();\n\n    const zipFilePathRes = validateAbsolutePath(zipFilePath);\n    if (zipFilePathRes.isErr()) return zipFilePathRes.asErr();\n    zipFilePath = zipFilePathRes.unwrap();\n\n    // Fetch as stream for true streaming\n    const fetchRes = await fetchT(sourceUrl, {\n        redirect: 'follow',\n        ...requestInit,\n        responseType: 'stream',\n        abortable: false,\n    });\n\n    if (fetchRes.isErr()) return fetchRes.asErr();\n\n    const stream = fetchRes.unwrap();\n    const { filename, keepEmptyBody = false, level } = requestInit ?? {};\n    // Use provided filename, or basename of pathname, or 'file' as fallback\n    const sourceName =\n        filename ?? (sourceUrl.pathname !== SEPARATOR ? basename(sourceUrl.pathname) : 'file');\n\n    // Handle null stream (204/304 responses or HEAD requests)\n    if (!stream) {\n        return keepEmptyBody ? zipEmptyFile(sourceName, zipFilePath) : Err(createEmptyBodyError());\n    }\n\n    // Peek first chunk to check for empty body\n    const peekRes = await peekStream(stream);\n    if (peekRes.isErr()) return peekRes.asErr();\n\n    const peek = peekRes.unwrap();\n\n    if (peek.isEmpty) {\n        return keepEmptyBody ? zipEmptyFile(sourceName, zipFilePath) : Err(createEmptyBodyError());\n    }\n\n    return streamZipFromStream(peek.stream, sourceName, zipFilePath, level);\n}\n\n// #region Internal Functions\n\n/**\n * Create a Zip instance with callback that pipes to controller.\n */\nfunction createZip(controller: ReadableStreamDefaultController<Uint8Array<ArrayBuffer>>): Zip {\n    return new Zip((err, chunk, final) => {\n        if (err) {\n            controller.error(err);\n            return;\n        }\n\n        controller.enqueue(chunk);\n\n        if (final) {\n            controller.close();\n        }\n    });\n}\n\n/**\n * Add an empty entry (directory or empty file) to zip.\n */\nfunction addEmptyEntry(zip: Zip, entryName: string): void {\n    const entry = new ZipPassThrough(entryName);\n    zip.add(entry);\n    entry.push(EMPTY_BYTES, true);\n}\n\n/**\n * Create a zip entry for a file, choosing the strategy based on compression level.\n *\n * - `level === 0`: use `ZipPassThrough` (store, no compression) — avoids DEFLATE overhead\n *   for already-compressed data.\n * - `level === 1..9`: use `ZipDeflate` with the given level.\n * - `level === undefined`: use `ZipDeflate` with fflate's default (6).\n *\n * Both `ZipPassThrough` and `ZipDeflate` implement `ZipInputFile`, so they share the\n * `push(chunk, final)` interface consumed by the caller.\n */\nfunction createZipEntry(entryName: string, level?: ZipLevel): ZipDeflate | ZipPassThrough {\n    if (level === 0) {\n        return new ZipPassThrough(entryName);\n    }\n    return level != null ? new ZipDeflate(entryName, { level }) : new ZipDeflate(entryName);\n}\n\n/**\n * Stream zip a single file handle.\n */\nasync function streamZipFile(\n    fileHandle: FileSystemFileHandle,\n    entryName: string,\n    zipFilePath: string,\n    level?: ZipLevel,\n): AsyncVoidIOResult {\n    const fileRes = await tryAsyncResult(fileHandle.getFile());\n\n    return fileRes.andThenAsync(file => {\n        return file.size === 0\n            ? zipEmptyFile(entryName, zipFilePath)\n            : streamZipFromStream(file.stream(), entryName, zipFilePath, level);\n    });\n}\n\n/**\n * Stream zip from a ReadableStream source.\n */\nfunction streamZipFromStream(\n    sourceStream: ReadableStream<Uint8Array<ArrayBuffer>>,\n    entryName: string,\n    zipFilePath: string,\n    level?: ZipLevel,\n): AsyncVoidIOResult {\n    const zipStream = new ReadableStream<Uint8Array<ArrayBuffer>>({\n        async start(controller) {\n            const zip = createZip(controller);\n            const entry = createZipEntry(entryName, level);\n            zip.add(entry);\n\n            try {\n                for await (const chunk of sourceStream) {\n                    entry.push(chunk, false);\n                }\n                entry.push(EMPTY_BYTES, true);\n                zip.end();\n            } catch (err) {\n                controller.error(err);\n            }\n        },\n    });\n\n    return writeFile(zipFilePath, zipStream);\n}\n\n/**\n * Create a zip with an empty file entry.\n *\n * This is preferred over streaming for empty files/bodies to avoid creating\n * unnecessary ReadableStream, Zip, and ZipDeflate instances.\n */\nfunction zipEmptyFile(entryName: string, zipFilePath: string): AsyncVoidIOResult {\n    const data = zipSync({\n        [entryName]: EMPTY_BYTES,\n    });\n    return writeFile(zipFilePath, data);\n}\n\n/**\n * Stream zip multiple directory entries sequentially.\n */\nfunction streamZipEntries(\n    first: IteratorResult<DirEntry>,\n    rest: AsyncIterableIterator<DirEntry>,\n    sourceName: string,\n    zipFilePath: string,\n    preserveRoot: boolean,\n    level?: ZipLevel,\n): AsyncVoidIOResult {\n    const zipStream = new ReadableStream<Uint8Array<ArrayBuffer>>({\n        async start(controller) {\n            const zip = createZip(controller);\n\n            // Add root directory entry first\n            if (preserveRoot) {\n                addEmptyEntry(zip, sourceName + SEPARATOR);\n            }\n\n            // Helper to process a single entry\n            const processEntry = async ({ path, handle }: DirEntry): Promise<void> => {\n                const entryName = preserveRoot ? join(sourceName, path) : path;\n\n                // Directory entry\n                if (!isFileHandle(handle)) {\n                    addEmptyEntry(zip, entryName + SEPARATOR);\n                    return;\n                }\n\n                // File entry - stream read and compress\n                const file = await handle.getFile();\n                const entry = createZipEntry(entryName, level);\n                zip.add(entry);\n\n                for await (const chunk of file.stream()) {\n                    entry.push(chunk, false);\n                }\n                entry.push(EMPTY_BYTES, true);\n            };\n\n            try {\n                // Process peeked first entry\n                if (!first.done) {\n                    await processEntry(first.value);\n                }\n\n                // Process remaining entries\n                for await (const dirEntry of rest) {\n                    await processEntry(dirEntry);\n                }\n\n                zip.end();\n            } catch (err) {\n                controller.error(err);\n            }\n        },\n    });\n\n    return writeFile(zipFilePath, zipStream);\n}\n\n// #endregion\n","import { fetchT } from '@happy-ts/fetch-t';\nimport { zip as compress, type AsyncZippable, type FlateError } from 'fflate/browser';\nimport {\n    Err,\n    Ok,\n    tryAsyncResult,\n    type AsyncIOResult,\n    type AsyncVoidIOResult,\n    type IOResult,\n    type VoidIOResult,\n} from 'happy-rusty';\nimport { Future } from 'tiny-future';\nimport {\n    basename,\n    join,\n    readBlobBytes,\n    readBlobBytesSync,\n    SEPARATOR,\n    validateAbsolutePath,\n    validateUrl,\n} from '../../shared/internal/mod.ts';\nimport {\n    isFileHandle,\n    type ZipFromUrlRequestInit,\n    type ZipLevel,\n    type ZipOptions,\n} from '../../shared/mod.ts';\nimport { readDir, stat, writeFile } from '../core/mod.ts';\nimport { createEmptyBodyError, createNothingToZipError } from '../internal/mod.ts';\nimport { EMPTY_BYTES } from './helpers.ts';\n\n/**\n * Zip a file or directory and write to a zip file.\n * Equivalent to `zip -r <zipFilePath> <sourcePath>`.\n *\n * Use [fflate](https://github.com/101arrowz/fflate) as the zip backend.\n * @param sourcePath - The path to be zipped.\n * @param zipFilePath - The path to the zip file.\n * @param options - Options of zip.\n * @returns A promise that resolves to an `AsyncIOResult` indicating whether the source was successfully zipped.\n * @since 1.6.0\n * @see {@link zipSync} for synchronous version\n * @see {@link zipStream} for streaming version (better for large files)\n * @see {@link unzip} for the reverse operation\n * @example\n * ```typescript\n * // Zip a directory to a file\n * (await zip('/documents', '/backups/documents.zip'))\n *     .inspect(() => console.log('Directory zipped successfully'));\n * ```\n */\nexport function zip(\n    sourcePath: string,\n    zipFilePath: string,\n    options?: ZipOptions,\n): AsyncVoidIOResult;\n\n/**\n * Zip a file or directory and return the zip file data.\n * Equivalent to `zip -r <zipFilePath> <sourcePath>`.\n *\n * Use [fflate](https://github.com/101arrowz/fflate) as the zip backend.\n * @param sourcePath - The path to be zipped.\n * @param options - Options of zip.\n * @returns A promise that resolves to an `AsyncIOResult` indicating whether the source was successfully zipped.\n * @since 1.6.0\n * @see {@link zipSync} for synchronous version\n * @see {@link zipStream} for streaming version (better for large files)\n * @see {@link unzip} for the reverse operation\n * @example\n * ```typescript\n * // Zip a directory and get the data\n * (await zip('/documents'))\n *     .inspect(zipData => console.log(`Zip size: ${ zipData.byteLength } bytes`));\n * ```\n */\nexport function zip(\n    sourcePath: string,\n    options?: ZipOptions,\n): AsyncIOResult<Uint8Array<ArrayBuffer>>;\nexport async function zip(\n    sourcePath: string,\n    zipFilePath?: string | ZipOptions,\n    options?: ZipOptions,\n): Promise<ZipIOResult> {\n    // Normalize before deriving entry names, otherwise `basename` would come from\n    // the raw path while the entry content is read from the normalized one\n    const sourcePathRes = validateAbsolutePath(sourcePath);\n    if (sourcePathRes.isErr()) return sourcePathRes.asErr() as ZipIOResult;\n    sourcePath = sourcePathRes.unwrap();\n\n    if (typeof zipFilePath === 'string') {\n        const zipFilePathRes = validateAbsolutePath(zipFilePath);\n        if (zipFilePathRes.isErr()) return zipFilePathRes.asErr() as ZipIOResult;\n        zipFilePath = zipFilePathRes.unwrap();\n    } else {\n        options = zipFilePath;\n        zipFilePath = undefined;\n    }\n\n    const statRes = await stat(sourcePath);\n    if (statRes.isErr()) {\n        return statRes.asErr() as ZipIOResult;\n    }\n\n    const handle = statRes.unwrap();\n    const sourceName = basename(sourcePath);\n    const zippable: AsyncZippable = {};\n\n    if (isFileHandle(handle)) {\n        // file\n        const dataRes = await getFileDataByHandle(handle);\n        if (dataRes.isErr()) {\n            return dataRes.asErr() as ZipIOResult;\n        }\n        zippable[sourceName] = dataRes.unwrap();\n    } else {\n        // directory\n        const readDirRes = await readDir(sourcePath, {\n            recursive: true,\n        });\n        if (readDirRes.isErr()) {\n            return readDirRes.asErr() as ZipIOResult;\n        }\n\n        // default to preserve root\n        const { preserveRoot = true } = options ?? {};\n        const tasks: AsyncIOResult<{\n            entryName: string;\n            data: Uint8Array<ArrayBuffer>;\n        }>[] = [];\n\n        // Add root directory entry\n        if (preserveRoot) {\n            zippable[sourceName + SEPARATOR] = EMPTY_BYTES;\n        }\n\n        try {\n            for await (const { path, handle } of readDirRes.unwrap()) {\n                const entryName = preserveRoot ? join(sourceName, path) : path;\n\n                if (isFileHandle(handle)) {\n                    // file\n                    tasks.push(\n                        (async () => {\n                            const dataRes = await getFileDataByHandle(handle);\n                            return dataRes.map(data => ({\n                                entryName,\n                                data,\n                            }));\n                        })(),\n                    );\n                } else {\n                    // directory - add entry with trailing slash and empty content\n                    zippable[entryName + SEPARATOR] = EMPTY_BYTES;\n                }\n            }\n        } catch (e) {\n            return Err<never, Error>(e as Error);\n        }\n\n        if (tasks.length > 0) {\n            const results = await Promise.all(tasks);\n            for (const res of results) {\n                if (res.isErr()) {\n                    return res.asErr() as ZipIOResult;\n                }\n                const { entryName, data } = res.unwrap();\n                zippable[entryName] = data;\n            }\n        }\n    }\n\n    // Nothing to zip - matches standard zip command behavior\n    if (Object.keys(zippable).length === 0) {\n        return Err<never, Error>(createNothingToZipError());\n    }\n\n    return zipTo(zippable, zipFilePath, options?.level);\n}\n\n/**\n * Zip a remote file and write to a zip file.\n *\n * Use [fflate](https://github.com/101arrowz/fflate) as the zip backend.\n *\n * This API is built on `@happy-ts/fetch-t` for downloading the source.\n * `requestInit` supports `timeout`, `onProgress`, and `filename` via {@link ZipFromUrlRequestInit}.\n *\n * @param sourceUrl - The url to be zipped.\n * @param zipFilePath - The path to the zip file.\n * @param requestInit - Optional request initialization parameters.\n * @returns A promise that resolves to an `AsyncIOResult` indicating whether the source was successfully zipped.\n * @since 1.7.0\n * @see {@link zipStreamFromUrl} for streaming version (better for large files)\n * @see {@link unzipFromUrl} for the reverse operation\n * @example\n * ```typescript\n * // Zip a remote file to a local zip file\n * (await zipFromUrl('https://example.com/file.txt', '/backups/file.zip'))\n *     .inspect(() => console.log('Remote file zipped successfully'));\n * ```\n */\nexport function zipFromUrl(\n    sourceUrl: string | URL,\n    zipFilePath: string,\n    requestInit?: ZipFromUrlRequestInit,\n): AsyncVoidIOResult;\n\n/**\n * Zip a remote file and return the zip file data.\n *\n * Use [fflate](https://github.com/101arrowz/fflate) as the zip backend.\n *\n * This API is built on `@happy-ts/fetch-t` for downloading the source.\n * `requestInit` supports `timeout`, `onProgress`, and `filename` via {@link ZipFromUrlRequestInit}.\n *\n * @param sourceUrl - The url to be zipped.\n * @param requestInit - Optional request initialization parameters.\n * @returns A promise that resolves to an `AsyncIOResult` indicating whether the source was successfully zipped.\n * @since 1.7.0\n * @see {@link zipStreamFromUrl} for streaming version (better for large files)\n * @see {@link unzipFromUrl} for the reverse operation\n * @example\n * ```typescript\n * // Zip a remote file and get the data\n * (await zipFromUrl('https://example.com/file.txt'))\n *     .inspect(zipData => console.log(`Zip size: ${ zipData.byteLength } bytes`));\n * ```\n */\nexport function zipFromUrl(\n    sourceUrl: string | URL,\n    requestInit?: ZipFromUrlRequestInit,\n): AsyncIOResult<Uint8Array<ArrayBuffer>>;\nexport async function zipFromUrl(\n    sourceUrl: string | URL,\n    zipFilePath?: string | ZipFromUrlRequestInit,\n    requestInit?: ZipFromUrlRequestInit,\n): Promise<ZipIOResult> {\n    const sourceUrlRes = validateUrl(sourceUrl);\n    if (sourceUrlRes.isErr()) return sourceUrlRes.asErr() as ZipIOResult;\n    sourceUrl = sourceUrlRes.unwrap();\n\n    if (typeof zipFilePath === 'string') {\n        const zipFilePathRes = validateAbsolutePath(zipFilePath);\n        if (zipFilePathRes.isErr()) return zipFilePathRes.asErr() as ZipIOResult;\n        zipFilePath = zipFilePathRes.unwrap();\n    } else {\n        requestInit = zipFilePath;\n        zipFilePath = undefined;\n    }\n\n    const fetchRes = await fetchT(sourceUrl, {\n        redirect: 'follow',\n        ...requestInit,\n        responseType: 'bytes',\n        abortable: false,\n    });\n\n    if (fetchRes.isErr()) {\n        return fetchRes.asErr() as ZipIOResult;\n    }\n\n    const bytes = fetchRes.unwrap();\n\n    const { filename, keepEmptyBody = false, level } = requestInit ?? {};\n\n    // body can be null for 204/304 responses or HEAD requests\n    if (!keepEmptyBody && bytes.byteLength === 0) {\n        return Err<never, Error>(createEmptyBodyError());\n    }\n\n    // Use provided filename, or basename of pathname, or 'file' as fallback\n    const sourceName =\n        filename ?? (sourceUrl.pathname !== SEPARATOR ? basename(sourceUrl.pathname) : 'file');\n\n    return zipTo(\n        {\n            [sourceName]: bytes,\n        },\n        zipFilePath,\n        level,\n    );\n}\n\n// #region Internal Types\n\n/**\n * Result type for zip operation.\n */\ntype ZipIOResult = IOResult<Uint8Array<ArrayBuffer>> | VoidIOResult;\n\n// #endregion\n\n// #region Internal Functions\n\n/**\n * Zip data and optionally write to the target path.\n * @param zippable - Zippable data.\n * @param zipFilePath - Target zip file path. If provided, writes to file; otherwise returns bytes.\n * @param level - Compression level (0-9). `undefined` uses fflate's default (6).\n */\nfunction zipTo(\n    zippable: AsyncZippable,\n    zipFilePath?: string,\n    level?: ZipLevel,\n): Promise<ZipIOResult> {\n    const future = new Future<ZipIOResult>();\n\n    compress(\n        zippable,\n        {\n            consume: true,\n            level,\n        },\n        async (err, bytesLike) => {\n            if (err) {\n                future.resolve(Err<never, FlateError>(err));\n                return;\n            }\n\n            const bytes = bytesLike;\n            // whether to write to file\n            if (zipFilePath) {\n                future.resolve(writeFile(zipFilePath, bytes));\n            } else {\n                future.resolve(Ok(bytes));\n            }\n        },\n    );\n\n    return future.promise;\n}\n\n/**\n * Reads the binary data from a file handle.\n * Uses FileReaderSync in Worker context for better performance,\n * falls back to async readBlobBytes in main thread.\n *\n * @param fileHandle - The `FileSystemFileHandle` to read from.\n * @returns A promise that resolves to an `AsyncIOResult` containing the file content as a `Uint8Array`.\n */\nfunction getFileDataByHandle(\n    fileHandle: FileSystemFileHandle,\n): AsyncIOResult<Uint8Array<ArrayBuffer>> {\n    return tryAsyncResult(async () => {\n        const file = await fileHandle.getFile();\n        // Use sync read in Worker context, async in main thread\n        return typeof FileReaderSync === 'function' ? readBlobBytesSync(file) : readBlobBytes(file);\n    });\n}\n\n// #endregion\n","import { Ok, type AsyncIOResult, type AsyncVoidIOResult } from 'happy-rusty';\nimport { validateExpiredDate } from '../shared/internal/mod.ts';\nimport { generateTempPath, isFileHandle, TMP_DIR, type TempOptions } from '../shared/mod.ts';\nimport { createFile, mkdir, remove } from './core/mod.ts';\nimport { getDirHandle, removeHandle } from './internal/mod.ts';\n\n/**\n * Creates a temporary file or directory in the `/tmp` directory.\n * Uses `crypto.randomUUID()` to generate a unique name.\n *\n * @param options - Options for creating the temporary path.\n * @returns A promise that resolves to an `AsyncIOResult` containing the created path.\n * @since 1.7.0\n * @see {@link generateTempPath} for generating paths without creating\n * @see {@link deleteTemp} for removing the entire temp directory\n * @see {@link pruneTemp} for removing expired temp files\n * @example\n * ```typescript\n * // Create a temporary file\n * (await mkTemp())\n *     .inspect(path => console.log(path)); // '/tmp/tmp-550e8400-e29b-41d4-a716-446655440000'\n *\n * // Create a temporary directory\n * await mkTemp({ isDirectory: true });\n *\n * // Create with custom basename and extension\n * await mkTemp({ basename: 'cache', extname: '.json' });\n * ```\n */\nexport async function mkTemp(options?: TempOptions): AsyncIOResult<string> {\n    const path = generateTempPath(options);\n    const { isDirectory = false } = options ?? {};\n\n    const res = await (isDirectory ? mkdir : createFile)(path);\n\n    return res.and(Ok(path));\n}\n\n/**\n * Deletes the entire temporary directory (`/tmp`) and all its contents.\n *\n * **Warning:** When writing a `ReadableStream` to a new file, `writeFile` uses a temporary file\n * in `/tmp` before moving it to the target path. Calling `deleteTemp()` during such operations\n * may cause the write to fail. Ensure no stream writes are in progress before calling this function.\n *\n * @returns A promise that resolves to an `AsyncVoidIOResult` indicating success or failure.\n * @since 1.7.0\n * @see {@link pruneTemp} for selective cleanup\n * @see {@link remove} for general file/directory removal\n * @example\n * ```typescript\n * (await deleteTemp())\n *     .inspect(() => console.log('Temporary directory deleted'));\n * ```\n */\nexport function deleteTemp(): AsyncVoidIOResult {\n    return remove(TMP_DIR);\n}\n\n/**\n * Removes expired files from the temporary directory.\n * Only removes direct children files whose `lastModified` time is before the specified date.\n *\n * **Note:** This function only removes files directly under `/tmp`, not subdirectories or their contents.\n * Use `deleteTemp()` to remove the entire temporary directory including all nested content.\n *\n * @param expired - Files modified before this date will be deleted.\n * @returns A promise that resolves to an `AsyncVoidIOResult` indicating success or failure.\n * @since 1.7.0\n * @see {@link deleteTemp} for removing all temp files\n * @see {@link mkTemp} for creating temp files\n * @example\n * ```typescript\n * // Remove files older than 24 hours\n * const yesterday = new Date(Date.now() - 24 * 60 * 60 * 1000);\n * const result = await pruneTemp(yesterday);\n * ```\n */\nexport async function pruneTemp(expired: Date): AsyncVoidIOResult {\n    const expiredRes = validateExpiredDate(expired);\n    if (expiredRes.isErr()) return expiredRes;\n\n    // Get TMP_DIR handle to iterate and reuse for removal\n    const tmpDirHandleRes = await getDirHandle(TMP_DIR);\n\n    return tmpDirHandleRes.andTryAsync(async tmpDirHandle => {\n        const expiredTime = expired.getTime();\n        const tasks: Promise<void>[] = [];\n\n        // Only process direct children (no recursive), since mkTemp only creates top-level items\n        for await (const handle of tmpDirHandle.values()) {\n            if (!isFileHandle(handle)) {\n                continue;\n            }\n\n            tasks.push(\n                (async () => {\n                    const file = await handle.getFile();\n                    if (file.lastModified <= expiredTime) {\n                        return removeHandle(handle, tmpDirHandle);\n                    }\n                })(),\n            );\n        }\n\n        if (tasks.length > 0) {\n            await Promise.all(tasks);\n        }\n    });\n}\n","import { fetchT, type FetchResult, type FetchTask } from '@happy-ts/fetch-t';\nimport { Err, Ok } from 'happy-rusty';\nimport { extname, validateAbsolutePath, validateUrl } from '../../shared/internal/mod.ts';\nimport type { DownloadFileTempResponse, DownloadRequestInit } from '../../shared/mod.ts';\nimport { generateTempPath } from '../../shared/mod.ts';\nimport { createFile, writeFile } from '../core/mod.ts';\nimport { createEmptyBodyError, createFailedFetchTask, peekStream } from '../internal/mod.ts';\n\n/**\n * Downloads a file from a URL and saves it to a temporary file.\n * The returned response will contain the temporary file path.\n *\n * This API is built on `@happy-ts/fetch-t`.\n * - Supports `timeout` and `onProgress` via {@link DownloadRequestInit}\n * - Supports `keepEmptyBody` to allow saving empty responses\n * - Returns an abortable {@link FetchTask}\n *\n * @param fileUrl - The URL of the file to download.\n * @param requestInit - Optional request initialization parameters.\n * @returns A task that can be aborted and contains the result of the download.\n * @since 1.0.4\n * @see {@link uploadFile} for the reverse operation\n * @see {@link unzipFromUrl} for downloading and extracting zip files\n * @example\n * ```typescript\n * // Download to a temporary file\n * const task = downloadFile('https://example.com/file.pdf');\n * (await task.result)\n *     .inspect(({ tempFilePath }) => console.log(`File downloaded to: ${ tempFilePath }`));\n * ```\n */\nexport function downloadFile(\n    fileUrl: string | URL,\n    requestInit?: DownloadRequestInit,\n): FetchTask<DownloadFileTempResponse>;\n\n/**\n * Downloads a file from a URL and saves it to the specified path.\n *\n * @param fileUrl - The URL of the file to download.\n * @param filePath - The path where the downloaded file will be saved.\n * @param requestInit - Optional request initialization parameters.\n * @returns A task that can be aborted and contains the result of the download.\n * @since 1.0.4\n * @see {@link uploadFile} for the reverse operation\n * @see {@link unzipFromUrl} for downloading and extracting zip files\n * @example\n * ```typescript\n * // Download to a specific path\n * const task = downloadFile('https://example.com/file.pdf', '/downloads/file.pdf');\n * (await task.result)\n *     .inspect(() => console.log('File downloaded successfully'));\n *\n * // Abort the download\n * task.abort();\n * ```\n */\nexport function downloadFile(\n    fileUrl: string | URL,\n    filePath: string,\n    requestInit?: DownloadRequestInit,\n): FetchTask<Response>;\nexport function downloadFile(\n    fileUrl: string | URL,\n    filePath?: string | DownloadRequestInit,\n    requestInit?: DownloadRequestInit,\n): FetchTask<Response | DownloadFileTempResponse> {\n    type T = FetchResult<Response | DownloadFileTempResponse>;\n\n    const fileUrlRes = validateUrl(fileUrl);\n    if (fileUrlRes.isErr()) return createFailedFetchTask(fileUrlRes);\n    fileUrl = fileUrlRes.unwrap();\n\n    let saveToTemp = false;\n\n    if (typeof filePath === 'string') {\n        const filePathRes = validateAbsolutePath(filePath);\n        if (filePathRes.isErr()) return createFailedFetchTask(filePathRes);\n        filePath = filePathRes.unwrap();\n    } else {\n        requestInit = filePath;\n        // save to a temporary file, preserve the extension from URL\n        filePath = generateTempPath({\n            extname: extname(fileUrl.pathname),\n        });\n        saveToTemp = true;\n    }\n\n    const fetchTask = fetchT(fileUrl, {\n        redirect: 'follow',\n        ...requestInit,\n        abortable: true,\n    });\n\n    const result = (async (): T => {\n        const responseRes = await fetchTask.result;\n\n        return responseRes.andThenAsync(async rawResponse => {\n            function okResult() {\n                return Ok(\n                    saveToTemp\n                        ? ({\n                              tempFilePath: filePath as string,\n                              rawResponse,\n                          } satisfies DownloadFileTempResponse)\n                        : rawResponse,\n                );\n            }\n\n            // Handle empty body: return error or create empty file\n            async function handleEmptyBody() {\n                const { keepEmptyBody = false } = requestInit ?? {};\n\n                if (!keepEmptyBody) {\n                    return Err(createEmptyBodyError());\n                }\n\n                const createRes = await createFile(filePath as string);\n                return createRes.and(okResult());\n            }\n\n            // Use peek approach for true streaming while detecting empty body\n            // Note: browsers don't conform to spec (body should be null for 204/HEAD responses)\n            // See: https://developer.mozilla.org/en-US/docs/Web/API/Response/body\n            const { body } = rawResponse;\n\n            // body is null - treat as empty\n            if (!body) {\n                return handleEmptyBody();\n            }\n\n            // Peek first chunk to detect empty stream\n            const peekRes = await peekStream(body);\n            if (peekRes.isErr()) return peekRes.asErr();\n\n            const peek = peekRes.unwrap();\n            if (peek.isEmpty) {\n                return handleEmptyBody();\n            }\n\n            // True streaming write with reconstructed stream\n            const writeRes = await writeFile(filePath, peek.stream);\n\n            return writeRes.and(okResult());\n        });\n    })();\n\n    return {\n        // FetchTask.abort() accepts `any` for the reason parameter to match\n        // the native AbortController.abort(reason?: any) signature\n        // eslint-disable-next-line @typescript-eslint/no-explicit-any\n        abort(reason?: any): void {\n            fetchTask.abort(reason);\n        },\n\n        get aborted(): boolean {\n            return fetchTask.aborted;\n        },\n\n        get result(): T {\n            return result;\n        },\n    };\n}\n","import { fetchT, type FetchResult, type FetchTask } from '@happy-ts/fetch-t';\nimport { Err } from 'happy-rusty';\nimport { basename, validateAbsolutePath, validateUrl } from '../../shared/internal/mod.ts';\nimport type { UploadRequestInit } from '../../shared/mod.ts';\nimport { readBlobFile } from '../ext.ts';\nimport { createAbortError, createFailedFetchTask } from '../internal/mod.ts';\n\n/**\n * Uploads a file from the specified path to a URL.\n *\n * This API is built on `@happy-ts/fetch-t`.\n * - Supports `timeout` and `onProgress` via {@link UploadRequestInit}\n * - Returns an abortable {@link FetchTask}\n *\n * @param filePath - The path of the file to upload.\n * @param uploadUrl - The URL where the file will be uploaded.\n * @param requestInit - Optional request initialization parameters.\n * @returns A task that can be aborted and contains the result of the upload.\n * @since 1.0.6\n * @see {@link downloadFile} for the reverse operation\n * @see {@link readBlobFile} for reading file as Blob before upload\n * @example\n * ```typescript\n * const task = uploadFile('/documents/report.pdf', 'https://example.com/upload');\n * (await task.result)\n *     .inspect(() => console.log('File uploaded successfully'));\n *\n * // Abort the upload\n * task.abort();\n * ```\n */\nexport function uploadFile(\n    filePath: string,\n    uploadUrl: string | URL,\n    requestInit?: UploadRequestInit,\n): FetchTask<Response> {\n    const filePathRes = validateAbsolutePath(filePath);\n    if (filePathRes.isErr()) return createFailedFetchTask(filePathRes);\n    filePath = filePathRes.unwrap();\n\n    const uploadUrlRes = validateUrl(uploadUrl);\n    if (uploadUrlRes.isErr()) return createFailedFetchTask(uploadUrlRes);\n    uploadUrl = uploadUrlRes.unwrap();\n\n    let aborted = false;\n    let fetchTask: FetchTask<Response>;\n\n    const result = (async (): FetchResult<Response> => {\n        const fileRes = await readBlobFile(filePath);\n\n        return fileRes.andThenAsync(async file => {\n            // maybe aborted\n            if (aborted) {\n                return Err(createAbortError());\n            }\n\n            const {\n                // default file name\n                filename = basename(filePath),\n                ...rest\n            } = requestInit ?? {};\n\n            const formData = new FormData();\n            formData.append(filename, file, filename);\n\n            fetchTask = fetchT(uploadUrl, {\n                method: 'POST',\n                ...rest,\n                abortable: true,\n                body: formData,\n            });\n\n            return fetchTask.result;\n        });\n    })();\n\n    return {\n        // FetchTask.abort() accepts `any` for the reason parameter to match\n        // the native AbortController.abort(reason?: any) signature\n        // eslint-disable-next-line @typescript-eslint/no-explicit-any\n        abort(reason?: any): void {\n            aborted = true;\n            fetchTask?.abort(reason);\n        },\n\n        get aborted(): boolean {\n            return aborted;\n        },\n\n        get result(): FetchResult<Response> {\n            return result;\n        },\n    };\n}\n"],"mappings":"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"}