{"version":3,"file":"sync.mjs","names":[],"sources":["../src/sync/ops.ts"],"sourcesContent":["/**\n * Synchronous file system operations for main thread.\n * Uses SharedArrayBuffer to communicate with worker thread.\n *\n * @module\n */\n\nimport { Err, Ok, tryResult, type IOResult, type VoidIOResult } from 'happy-rusty';\nimport { decodeUtf8, toBytesView, validateAbsolutePath, validateExistsOptions, validateExpiredDate, validateWriteSyncFileContent } from '../shared/internal/mod.ts';\nimport { TIMEOUT_ERROR, type AppendOptions, type CopyOptions, type DirEntryLike, type ExistsOptions, type FileSystemHandleLike, type MoveOptions, type ReadDirSyncOptions, type ReadSyncFileContent, type ReadSyncOptions, type TempOptions, type WriteOptions, type WriteSyncFileContent, type ZipOptions } from '../shared/mod.ts';\nimport { getGlobalSyncOpTimeout, getMessenger, getSyncChannelState } from './channel/state.ts';\nimport type { ErrorLike, FileMetadata } from './defines.ts';\nimport { DATA_INDEX, decodePayload, encodePayload, MAIN_LOCK_INDEX, MAIN_LOCKED, MAIN_UNLOCKED, WORKER_LOCK_INDEX, WORKER_UNLOCKED, WorkerOp, type SyncMessenger } from './protocol.ts';\n\n/**\n * Synchronous version of `createFile`.\n * Creates a new empty file at the specified path.\n *\n * @param filePath - The absolute path of the file to create.\n * @returns A `VoidIOResult` indicating success or failure.\n * @see {@link createFile} for the async version.\n * @since 1.7.0\n * @example\n * ```typescript\n * createFileSync('/path/to/file.txt')\n *     .inspect(() => console.log('File created'));\n * ```\n */\nexport function createFileSync(filePath: string): VoidIOResult {\n    const filePathRes = validateAbsolutePath(filePath);\n    if (filePathRes.isErr()) return filePathRes.asErr();\n    filePath = filePathRes.unwrap();\n\n    return callWorkerOp(WorkerOp.createFile, filePath);\n}\n\n/**\n * Synchronous version of `mkdir`.\n * Creates a directory at the specified path, including any necessary parent directories.\n *\n * @param dirPath - The absolute path of the directory to create.\n * @returns A `VoidIOResult` indicating success or failure.\n * @see {@link mkdir} for the async version.\n * @since 1.1.0\n * @example\n * ```typescript\n * mkdirSync('/path/to/directory')\n *     .inspect(() => console.log('Directory created'));\n * ```\n */\nexport function mkdirSync(dirPath: string): VoidIOResult {\n    const dirPathRes = validateAbsolutePath(dirPath);\n    if (dirPathRes.isErr()) return dirPathRes.asErr();\n    dirPath = dirPathRes.unwrap();\n\n    return callWorkerOp(WorkerOp.mkdir, dirPath);\n}\n\n/**\n * Synchronous version of `move`.\n * Moves a file or directory from one location to another.\n *\n * @param srcPath - The source path.\n * @param destPath - The destination path.\n * @param options - Optional move options.\n * @returns A `VoidIOResult` indicating success or failure.\n * @see {@link move} for the async version.\n * @since 1.8.0\n * @example\n * ```typescript\n * moveSync('/old/path/file.txt', '/new/path/file.txt')\n *     .inspect(() => console.log('File moved'));\n * ```\n */\nexport function moveSync(srcPath: string, destPath: string, options?: MoveOptions): VoidIOResult {\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    return callWorkerOp(WorkerOp.move, srcPath, destPath, options);\n}\n\n/**\n * Synchronous version of `readDir`.\n * Reads the contents of a directory.\n *\n * **Note:** Returns `DirEntryLike[]` instead of `AsyncIterableIterator<DirEntry>` because:\n * 1. Sync API cannot return async iterators\n * 2. Native `FileSystemHandle` objects cannot be serialized across threads;\n *    `DirEntryLike` uses `FileSystemHandleLike` which is JSON-serializable\n *\n * @param dirPath - The absolute path of the directory to read.\n * @param options - Optional read options (e.g., recursive).\n * @returns An `IOResult` containing an array of directory entries.\n * @see {@link readDir} for the async version.\n * @since 1.1.0\n * @example\n * ```typescript\n * readDirSync('/documents')\n *     .inspect(entries => entries.forEach(e => console.log(e.path, e.handle.kind)));\n * ```\n */\nexport function readDirSync(dirPath: string, options?: ReadDirSyncOptions): IOResult<DirEntryLike[]> {\n    const dirPathRes = validateAbsolutePath(dirPath);\n    if (dirPathRes.isErr()) return dirPathRes.asErr();\n    dirPath = dirPathRes.unwrap();\n\n    return callWorkerOp(WorkerOp.readDir, dirPath, options);\n}\n\n/**\n * Synchronous version of `readFile`.\n * Reads the content of a file as a `File` object (blob encoding).\n *\n * @param filePath - The absolute path of the file to read.\n * @param options - Read options with 'blob' encoding.\n * @returns An `IOResult` containing a `File` object.\n * @since 1.1.0\n * @example\n * ```typescript\n * readFileSync('/path/to/file.txt', { encoding: 'blob' })\n *     .inspect(file => console.log(file.name, file.size));\n * ```\n */\nexport function readFileSync(filePath: string, options: ReadSyncOptions & {\n    encoding: 'blob';\n}): IOResult<File>;\n/**\n * Synchronous version of `readFile`.\n * Reads the content of a file as a string (utf8 encoding).\n *\n * @param filePath - The absolute path of the file to read.\n * @param options - Read options with 'utf8' encoding.\n * @returns An `IOResult` containing the file content as a string.\n * @since 1.1.0\n * @example\n * ```typescript\n * readFileSync('/path/to/file.txt', { encoding: 'utf8' })\n *     .inspect(content => console.log(content));\n * ```\n */\nexport function readFileSync(filePath: string, options: ReadSyncOptions & {\n    encoding: 'utf8';\n}): IOResult<string>;\n/**\n * Synchronous version of `readFile`.\n * Reads the content of a file as a Uint8Array (default).\n *\n * @param filePath - The absolute path of the file to read.\n * @param options - Optional read options. Defaults to 'bytes' encoding.\n * @returns An `IOResult` containing the file content as a Uint8Array.\n * @since 1.1.0\n * @example\n * ```typescript\n * readFileSync('/path/to/file.bin')\n *     .inspect(bytes => console.log('First byte:', bytes[0]));\n * ```\n */\nexport function readFileSync(filePath: string, options?: ReadSyncOptions & {\n    encoding?: 'bytes';\n}): IOResult<Uint8Array<ArrayBuffer>>;\n/**\n * Synchronous version of `readFile`.\n * Reads the content of a file 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 absolute path of the file to read.\n * @param options - Optional read options.\n * @returns An `IOResult` containing the file content.\n * @see {@link readFile} for the async version.\n * @since 1.1.0\n * @example\n * ```typescript\n * // When encoding is dynamic\n * const encoding = getUserPreference(); // 'utf8' | 'bytes' | ...\n * readFileSync('/path/to/file.txt', { encoding })\n *     .inspect(content => {\n *         // content type is ReadSyncFileContent (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 readFileSync(filePath: string, options?: ReadSyncOptions): IOResult<ReadSyncFileContent>;\n/**\n * Synchronous version of `readFile`.\n * Reads the content of a file with the specified encoding.\n *\n * @param filePath - The absolute path of the file to read.\n * @param options - Optional read options.\n * @returns An `IOResult` containing the file content.\n * @see {@link readFile} for the async version.\n */\nexport function readFileSync(filePath: string, options?: ReadSyncOptions): IOResult<ReadSyncFileContent> {\n    const filePathRes = validateAbsolutePath(filePath);\n    if (filePathRes.isErr()) return filePathRes.asErr();\n    filePath = filePathRes.unwrap();\n\n    const encoding = options?.encoding;\n\n    // blob encoding: use readBlobFile for File object with metadata\n    if (encoding === 'blob') {\n        // Response is [metadata, Uint8Array] from binary protocol\n        const readRes = callWorkerOp<[FileMetadata, Uint8Array<ArrayBuffer>]>(WorkerOp.readBlobFile, filePath);\n        return readRes.map(([metadata, data]) => deserializeFile(metadata, data));\n    }\n\n    // bytes/utf8: always request bytes encoding from worker\n    // This avoids double encoding/decoding for utf8 (string -> bytes -> string)\n    const readRes = callWorkerOp<Uint8Array<ArrayBuffer>>(WorkerOp.readFile, filePath);\n    return readRes.map(bytes => {\n        if (encoding === 'utf8') {\n            return decodeUtf8(bytes);\n        }\n        // 'bytes' or undefined (default)\n        return bytes;\n    });\n}\n\n/**\n * Synchronous version of `remove`.\n * Removes a file or directory at the specified path.\n *\n * @param path - The absolute path of the file or directory to remove.\n * @returns A `VoidIOResult` indicating success or failure.\n * @see {@link remove} for the async version.\n * @since 1.1.0\n * @example\n * ```typescript\n * removeSync('/path/to/file-or-directory')\n *     .inspect(() => console.log('Removed successfully'));\n * ```\n */\nexport function removeSync(path: string): VoidIOResult {\n    const pathRes = validateAbsolutePath(path);\n    if (pathRes.isErr()) return pathRes.asErr();\n    path = pathRes.unwrap();\n\n    return callWorkerOp(WorkerOp.remove, path);\n}\n\n/**\n * Synchronous version of `stat`.\n * Retrieves metadata about a file or directory.\n *\n * **Note:** Returns `FileSystemHandleLike` instead of `FileSystemHandle` because\n * native `FileSystemHandle` objects cannot be serialized across threads.\n * `FileSystemHandleLike` is a plain object with `name` and `kind` properties.\n * For file entries, it also includes `size`, `type`, and `lastModified` -\n * use `isFileHandleLike()` to check and narrow the type.\n *\n * @param path - The absolute path to get status for.\n * @returns An `IOResult` containing a `FileSystemHandleLike` object.\n * @see {@link stat} for the async version.\n * @since 1.1.0\n * @example\n * ```typescript\n * statSync('/path/to/entry')\n *     .inspect(handle => console.log(`Kind: ${ handle.kind }, Name: ${ handle.name }`));\n * ```\n */\nexport function statSync(path: string): IOResult<FileSystemHandleLike> {\n    const pathRes = validateAbsolutePath(path);\n    if (pathRes.isErr()) return pathRes.asErr();\n    path = pathRes.unwrap();\n\n    return callWorkerOp(WorkerOp.stat, path);\n}\n\n/**\n * Synchronous version of `truncate`.\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 * @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 `VoidIOResult` indicating success or failure.\n * @see {@link truncate} for the async version.\n * @since 2.2.0\n * @example\n * ```typescript\n * truncateSync('/log.txt', 5)\n *     .inspect(() => console.log('File truncated'));\n * ```\n */\nexport function truncateSync(filePath: string, len: number): VoidIOResult {\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    return callWorkerOp(WorkerOp.truncate, filePath, len);\n}\n\n/**\n * Synchronous version of `writeFile`.\n * Writes content to a file at the specified path.\n *\n * @param filePath - The absolute path of the file to write.\n * @param contents - The content to write (ArrayBuffer, TypedArray, or string).\n * @param options - Optional write options.\n * @returns A `VoidIOResult` indicating success or failure.\n * @see {@link writeFile} for the async version.\n * @since 1.1.0\n * @example\n * ```typescript\n * // Write string content\n * writeFileSync('/path/to/file.txt', 'Hello, World!');\n *\n * // Write binary content\n * writeFileSync('/path/to/file.bin', new Uint8Array([1, 2, 3]));\n * ```\n */\nexport function writeFileSync(filePath: string, contents: WriteSyncFileContent, options?: WriteOptions): VoidIOResult {\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 = validateWriteSyncFileContent(contents);\n    if (contentRes.isErr()) return contentRes.asErr();\n\n    // Put Uint8Array as the last argument for binary protocol\n    return callWorkerOp(WorkerOp.writeFile, filePath, options, toBytesView(contents));\n}\n\n/**\n * Synchronous version of `appendFile`.\n * Appends content to a file at the specified path.\n *\n * @param filePath - The absolute path of the file to append to.\n * @param contents - The content to append (ArrayBuffer, TypedArray, or string).\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 `VoidIOResult` indicating success or failure.\n * @see {@link appendFile} for the async version.\n * @since 1.1.0\n * @example\n * ```typescript\n * // Append to file, create if doesn't exist (default behavior)\n * appendFileSync('/path/to/log.txt', 'New log entry\\n');\n *\n * // Append only if file exists, fail if it doesn't\n * appendFileSync('/path/to/log.txt', 'New log entry\\n', { create: false });\n * ```\n */\nexport function appendFileSync(filePath: string, contents: WriteSyncFileContent, options?: AppendOptions): VoidIOResult {\n    return writeFileSync(filePath, contents, {\n        append: true,\n        create: options?.create,\n    });\n}\n\n/**\n * Synchronous version of `copy`.\n * Copies a file or directory from one location to another.\n *\n * @param srcPath - The source path.\n * @param destPath - The destination path.\n * @param options - Optional copy options.\n * @returns A `VoidIOResult` indicating success or failure.\n * @see {@link copy} for the async version.\n * @since 1.7.0\n * @example\n * ```typescript\n * // Copy a file\n * copySync('/src/file.txt', '/dest/file.txt');\n *\n * // Copy without overwriting\n * copySync('/src', '/dest', { overwrite: false });\n * ```\n */\nexport function copySync(srcPath: string, destPath: string, options?: CopyOptions): VoidIOResult {\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    return callWorkerOp(WorkerOp.copy, srcPath, destPath, options);\n}\n\n/**\n * Synchronous version of `emptyDir`.\n * Removes all contents of a directory.\n *\n * @param dirPath - The absolute path of the directory to empty.\n * @returns A `VoidIOResult` indicating success or failure.\n * @see {@link emptyDir} for the async version.\n * @since 1.1.0\n * @example\n * ```typescript\n * emptyDirSync('/path/to/directory');\n * ```\n */\nexport function emptyDirSync(dirPath: string): VoidIOResult {\n    const dirPathRes = validateAbsolutePath(dirPath);\n    if (dirPathRes.isErr()) return dirPathRes.asErr();\n    dirPath = dirPathRes.unwrap();\n\n    return callWorkerOp(WorkerOp.emptyDir, dirPath);\n}\n\n/**\n * Synchronous version of `exists`.\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 (e.g., isDirectory, isFile).\n * @returns An `IOResult` containing `true` if exists, `false` otherwise.\n * @see {@link exists} for the async version.\n * @since 1.1.0\n * @example\n * ```typescript\n * existsSync('/path/to/file')\n *     .inspect(exists => exists && console.log('File exists'));\n * ```\n */\nexport function existsSync(path: string, options?: ExistsOptions): IOResult<boolean> {\n    const pathRes = validateAbsolutePath(path);\n    if (pathRes.isErr()) return pathRes.asErr();\n    path = pathRes.unwrap();\n\n    const optionsRes = validateExistsOptions(options);\n    if (optionsRes.isErr()) return optionsRes.asErr();\n\n    return callWorkerOp(WorkerOp.exists, path, options);\n}\n\n/**\n * Synchronous version of `deleteTemp`.\n * Deletes the temporary directory and all its contents.\n *\n * @returns A `VoidIOResult` indicating success or failure.\n * @see {@link deleteTemp} for the async version.\n * @since 1.7.0\n * @example\n * ```typescript\n * deleteTempSync();\n * ```\n */\nexport function deleteTempSync(): VoidIOResult {\n    return callWorkerOp(WorkerOp.deleteTemp);\n}\n\n/**\n * Synchronous version of `mkTemp`.\n * Creates a temporary file or directory.\n *\n * @param options - Optional temp options (e.g., isDirectory, basename, extname).\n * @returns An `IOResult` containing the temporary path.\n * @see {@link mkTemp} for the async version.\n * @since 1.7.0\n * @example\n * ```typescript\n * mkTempSync({ extname: '.txt' })\n *     .inspect(path => console.log('Temp file:', path));\n * ```\n */\nexport function mkTempSync(options?: TempOptions): IOResult<string> {\n    return callWorkerOp(WorkerOp.mkTemp, options);\n}\n\n/**\n * Synchronous version of `pruneTemp`.\n * Removes expired files from the temporary directory.\n *\n * @param expired - Files with lastModified before this date will be removed.\n * @returns A `VoidIOResult` indicating success or failure.\n * @see {@link pruneTemp} for the async version.\n * @since 1.7.0\n * @example\n * ```typescript\n * // Remove files older than 24 hours\n * const yesterday = new Date(Date.now() - 24 * 60 * 60 * 1000);\n * pruneTempSync(yesterday);\n * ```\n */\nexport function pruneTempSync(expired: Date): VoidIOResult {\n    const expiredRes = validateExpiredDate(expired);\n    if (expiredRes.isErr()) return expiredRes;\n\n    return callWorkerOp(WorkerOp.pruneTemp, expired);\n}\n\n/**\n * Synchronous version of `readBlobFile`.\n * Reads a file as a `File` object.\n *\n * @param filePath - The absolute path of the file to read.\n * @returns An `IOResult` containing a `File` object.\n * @see {@link readBlobFile} for the async version.\n * @since 1.1.0\n * @example\n * ```typescript\n * readBlobFileSync('/path/to/file.txt')\n *     .inspect(file => console.log(file.name, file.size, file.type));\n * ```\n */\nexport function readBlobFileSync(filePath: string): IOResult<File> {\n    return readFileSync(filePath, {\n        encoding: 'blob',\n    });\n}\n\n/**\n * Synchronous version of `readJsonFile`.\n * Reads and parses a JSON file.\n *\n * @template T - The expected type of the parsed JSON.\n * @param filePath - The absolute path of the JSON file to read.\n * @returns An `IOResult` containing the parsed JSON object.\n * @see {@link readJsonFile} for the async version.\n * @since 1.8.4\n * @example\n * ```typescript\n * interface Config { name: string; version: number }\n * readJsonFileSync<Config>('/config.json')\n *     .inspect(config => console.log(config.name));\n * ```\n */\nexport function readJsonFileSync<T>(filePath: string): IOResult<T> {\n    return readTextFileSync(filePath).andThen(contents => {\n        return tryResult<T, Error, [string]>(JSON.parse, contents);\n    });\n}\n\n/**\n * Synchronous version of `readTextFile`.\n * Reads a file as a UTF-8 string.\n *\n * @param filePath - The absolute path of the file to read.\n * @returns An `IOResult` containing the file content as a string.\n * @see {@link readTextFile} for the async version.\n * @since 1.1.0\n * @example\n * ```typescript\n * readTextFileSync('/path/to/file.txt')\n *     .inspect(content => console.log(content));\n * ```\n */\nexport function readTextFileSync(filePath: string): IOResult<string> {\n    return readFileSync(filePath, {\n        encoding: 'utf8',\n    });\n}\n\n/**\n * Synchronous version of `writeJsonFile`.\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 `VoidIOResult` indicating success or failure.\n * @see {@link writeJsonFile} for the async version.\n * @since 1.1.0\n * @example\n * ```typescript\n * const config = { name: 'app', version: 1 };\n * writeJsonFileSync('/config.json', config);\n * ```\n */\nexport function writeJsonFileSync<T>(filePath: string, data: T): VoidIOResult {\n    return tryResult(JSON.stringify, data)\n        .andThen(text => writeFileSync(filePath, text));\n}\n\n/**\n * Synchronous version of `unzip`.\n * Extracts a zip file to a directory.\n *\n * @param zipFilePath - The path to the zip file.\n * @param destDir - The directory to unzip to.\n * @returns A `VoidIOResult` indicating success or failure.\n * @see {@link unzip} for the async version.\n * @since 1.6.0\n * @example\n * ```typescript\n * unzipSync('/downloads/archive.zip', '/extracted');\n * ```\n */\nexport function unzipSync(zipFilePath: string, destDir: string): VoidIOResult {\n    const zipFilePathRes = validateAbsolutePath(zipFilePath);\n    if (zipFilePathRes.isErr()) return zipFilePathRes.asErr();\n    zipFilePath = zipFilePathRes.unwrap();\n\n    const destDirRes = validateAbsolutePath(destDir);\n    if (destDirRes.isErr()) return destDirRes.asErr();\n    destDir = destDirRes.unwrap();\n\n    return callWorkerOp(WorkerOp.unzip, zipFilePath, destDir);\n}\n\n/**\n * Synchronous version of `zip`.\n * Zips a file or directory and writes to a zip file.\n *\n * @param sourcePath - The path to zip.\n * @param zipFilePath - The destination zip file path.\n * @param options - Optional zip options.\n * @returns A `VoidIOResult` indicating success or failure.\n * @see {@link zip} for the async version.\n * @since 1.6.0\n * @example\n * ```typescript\n * zipSync('/documents', '/backups/documents.zip');\n * ```\n */\nexport function zipSync(sourcePath: string, zipFilePath: string, options?: ZipOptions): VoidIOResult;\n/**\n * Synchronous version of `zip`.\n * Zips a file or directory and returns the zip data.\n *\n * @param sourcePath - The path to zip.\n * @param options - Optional zip options.\n * @returns An `IOResult` containing the zip data as `Uint8Array`.\n * @see {@link zip} for the async version.\n * @since 1.6.0\n * @example\n * ```typescript\n * zipSync('/documents')\n *     .inspect(data => console.log('Zip size:', data.byteLength));\n * ```\n */\nexport function zipSync(sourcePath: string, options?: ZipOptions): IOResult<Uint8Array<ArrayBuffer>>;\n/**\n * Synchronous version of `zip`.\n * Zips a file or directory.\n *\n * @param sourcePath - The path to zip.\n * @param zipFilePath - Optional destination zip file path or options.\n * @param options - Optional zip options.\n * @returns An `IOResult` containing the result.\n * @see {@link zip} for the async version.\n * @since 1.6.0\n */\nexport function zipSync(sourcePath: string, zipFilePath?: string | ZipOptions, options?: ZipOptions): IOResult<Uint8Array<ArrayBuffer> | void> {\n    const sourcePathRes = validateAbsolutePath(sourcePath);\n    if (sourcePathRes.isErr()) return sourcePathRes.asErr();\n    sourcePath = sourcePathRes.unwrap();\n\n    // If zipFilePath is a string path, validate it too\n    if (typeof zipFilePath === 'string') {\n        const zipFilePathRes = validateAbsolutePath(zipFilePath);\n        if (zipFilePathRes.isErr()) return zipFilePathRes.asErr();\n        zipFilePath = zipFilePathRes.unwrap();\n    }\n\n    // Result is Uint8Array directly as the last element from binary protocol, or undefined for void result\n    return callWorkerOp(WorkerOp.zip, sourcePath, zipFilePath, options);\n}\n\n// #region Internal Functions\n\n/**\n * Deserializes an `ErrorLike` object back to an `Error` instance.\n *\n * @param error - The `ErrorLike` object to deserialize.\n * @returns An `Error` instance with the same name and message.\n */\nfunction deserializeError(error: ErrorLike): Error {\n    const err = new Error(error.message);\n    err.name = error.name;\n\n    return err;\n}\n\n/**\n * Deserializes file metadata and binary data to a `File` instance.\n * Binary data is now received as the last element from the binary protocol.\n *\n * @param metadata - The file metadata (name, type, lastModified).\n * @param data - The binary data as Uint8Array.\n * @returns A `File` instance with the given properties.\n */\nfunction deserializeFile(metadata: FileMetadata, data: Uint8Array<ArrayBuffer>): File {\n    return new File([data], metadata.name, {\n        type: metadata.type,\n        lastModified: metadata.lastModified,\n    });\n}\n\n/**\n * Blocks execution until a condition is met or timeout occurs.\n * Uses busy-waiting, which is necessary for synchronous operations.\n *\n * @param condition - A function that returns `true` when the wait should end.\n * @returns A `VoidIOResult` - `Ok` if condition met, `Err` with TimeoutError if timed out.\n */\nfunction sleepUntil(condition: () => boolean): VoidIOResult {\n    const timeout = getGlobalSyncOpTimeout();\n    const start = performance.now();\n    while (!condition()) {\n        if (performance.now() - start > timeout) {\n            const error = new Error('Operation timed out');\n            error.name = TIMEOUT_ERROR;\n\n            return Err(error);\n        }\n    }\n\n    return Ok();\n}\n\n/**\n * Sends a synchronous request from main thread to worker and waits for response.\n * This function blocks the main thread until the worker responds.\n *\n * Communication Protocol:\n * 1. Lock main thread (set MAIN_LOCKED) to signal we're waiting\n * 2. Write request data and length to SharedArrayBuffer\n * 3. Wake worker by setting WORKER_UNLOCKED\n * 4. Busy-wait until worker signals completion (MAIN_UNLOCKED)\n * 5. Read response from SharedArrayBuffer\n *\n * @param messenger - The `SyncMessenger` instance for communication.\n * @param data - The request data as a `Uint8Array`.\n * @returns An `IOResult` containing the response data, or an error if the request is too large or times out.\n */\nfunction callWorkerFromMain(messenger: SyncMessenger, data: Uint8Array<ArrayBuffer>): IOResult<Uint8Array<SharedArrayBuffer>> {\n    const { i32a, maxDataLength } = messenger;\n    const requestLength = data.byteLength;\n\n    // check whether request is too large\n    if (requestLength > maxDataLength) {\n        return Err(new RangeError(`Request is too large: ${ requestLength } > ${ maxDataLength }. Consider increasing the size of SharedArrayBuffer`));\n    }\n\n    // Lock main thread - signal that we're waiting for a response\n    Atomics.store(i32a, MAIN_LOCK_INDEX, MAIN_LOCKED);\n\n    // Write payload: store length and data to SharedArrayBuffer\n    i32a[DATA_INDEX] = requestLength;\n    messenger.setPayload(data);\n\n    // Wake up worker by setting it to UNLOCKED\n    // Note: Atomics.notify() may not work reliably cross-thread, using store + busy-wait instead\n    // Atomics.notify(i32a, WORKER_LOCK_INDEX); // this may not work\n    Atomics.store(i32a, WORKER_LOCK_INDEX, WORKER_UNLOCKED);\n\n    // Busy-wait for worker to finish processing and unlock main thread\n    const waitResult = sleepUntil(() => Atomics.load(i32a, MAIN_LOCK_INDEX) === MAIN_UNLOCKED);\n    if (waitResult.isErr()) {\n        return waitResult.asErr();\n    }\n\n    // Worker has finished - read response data\n    const responseLength = i32a[DATA_INDEX];\n    const response = messenger.getPayload(responseLength);\n\n    return Ok(response);\n}\n\n/**\n * Calls a worker I/O operation synchronously.\n * Serializes the request, sends to worker, and deserializes the response.\n *\n * @template T - The expected return type.\n * @param op - The I/O operation enum value from `WorkerOp`.\n * @param args - Arguments to pass to the operation.\n * @returns The I/O operation result wrapped in `IOResult<T>`.\n */\nfunction callWorkerOp<T>(op: WorkerOp, ...args: unknown[]): IOResult<T> {\n    if (getSyncChannelState() !== 'ready') {\n        return Err(new Error('Sync channel not connected'));\n    }\n\n    const messenger = getMessenger() as SyncMessenger;\n\n    // Serialize request: [operation, ...arguments]\n    const request = [op, ...args];\n    const requestData = encodePayload(request);\n\n    return callWorkerFromMain(messenger, requestData)\n        .andThen(response => {\n            // Deserialize response: [error, result] or [error] if failed\n            // For binary protocol, if result contains Uint8Array, it's the last element\n            const decodedResponse = decodePayload<[ErrorLike | null, ...unknown[]]>(response);\n            const err = decodedResponse[0];\n            if (err) {\n                return Err(deserializeError(err));\n            }\n            // For single result, return decodedResponse[1]\n            // For multi-value result (like readBlobFile), return all elements after error\n            if (decodedResponse.length === 2) {\n                return Ok(decodedResponse[1] as T);\n            }\n            // Multi-value result: return slice from index 1\n            return Ok(decodedResponse.slice(1) as T);\n        });\n}\n\n// #endregion\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BA,SAAgB,eAAe,UAAgC;CAC3D,MAAM,cAAc,qBAAqB,QAAQ;CACjD,IAAI,YAAY,MAAM,GAAG,OAAO,YAAY,MAAM;CAClD,WAAW,YAAY,OAAO;CAE9B,OAAO,aAAa,SAAS,YAAY,QAAQ;AACrD;;;;;;;;;;;;;;;AAgBA,SAAgB,UAAU,SAA+B;CACrD,MAAM,aAAa,qBAAqB,OAAO;CAC/C,IAAI,WAAW,MAAM,GAAG,OAAO,WAAW,MAAM;CAChD,UAAU,WAAW,OAAO;CAE5B,OAAO,aAAa,SAAS,OAAO,OAAO;AAC/C;;;;;;;;;;;;;;;;;AAkBA,SAAgB,SAAS,SAAiB,UAAkB,SAAqC;CAC7F,MAAM,aAAa,qBAAqB,OAAO;CAC/C,IAAI,WAAW,MAAM,GAAG,OAAO,WAAW,MAAM;CAChD,UAAU,WAAW,OAAO;CAE5B,MAAM,cAAc,qBAAqB,QAAQ;CACjD,IAAI,YAAY,MAAM,GAAG,OAAO,YAAY,MAAM;CAClD,WAAW,YAAY,OAAO;CAE9B,OAAO,aAAa,SAAS,MAAM,SAAS,UAAU,OAAO;AACjE;;;;;;;;;;;;;;;;;;;;;AAsBA,SAAgB,YAAY,SAAiB,SAAwD;CACjG,MAAM,aAAa,qBAAqB,OAAO;CAC/C,IAAI,WAAW,MAAM,GAAG,OAAO,WAAW,MAAM;CAChD,UAAU,WAAW,OAAO;CAE5B,OAAO,aAAa,SAAS,SAAS,SAAS,OAAO;AAC1D;;;;;;;;;;AAyFA,SAAgB,aAAa,UAAkB,SAA0D;CACrG,MAAM,cAAc,qBAAqB,QAAQ;CACjD,IAAI,YAAY,MAAM,GAAG,OAAO,YAAY,MAAM;CAClD,WAAW,YAAY,OAAO;CAE9B,MAAM,WAAW,SAAS;CAG1B,IAAI,aAAa,QAGb,OADgB,aAAsD,SAAS,cAAc,QACtF,CAAA,CAAQ,KAAK,CAAC,UAAU,UAAU,gBAAgB,UAAU,IAAI,CAAC;CAM5E,OADgB,aAAsC,SAAS,UAAU,QAClE,CAAA,CAAQ,KAAI,UAAS;EACxB,IAAI,aAAa,QACb,OAAO,WAAW,KAAK;EAG3B,OAAO;CACX,CAAC;AACL;;;;;;;;;;;;;;;AAgBA,SAAgB,WAAW,MAA4B;CACnD,MAAM,UAAU,qBAAqB,IAAI;CACzC,IAAI,QAAQ,MAAM,GAAG,OAAO,QAAQ,MAAM;CAC1C,OAAO,QAAQ,OAAO;CAEtB,OAAO,aAAa,SAAS,QAAQ,IAAI;AAC7C;;;;;;;;;;;;;;;;;;;;;AAsBA,SAAgB,SAAS,MAA8C;CACnE,MAAM,UAAU,qBAAqB,IAAI;CACzC,IAAI,QAAQ,MAAM,GAAG,OAAO,QAAQ,MAAM;CAC1C,OAAO,QAAQ,OAAO;CAEtB,OAAO,aAAa,SAAS,MAAM,IAAI;AAC3C;;;;;;;;;;;;;;;;;;;;AAqBA,SAAgB,aAAa,UAAkB,KAA2B;CACtE,MAAM,cAAc,qBAAqB,QAAQ;CACjD,IAAI,YAAY,MAAM,GAAG,OAAO,YAAY,MAAM;CAClD,WAAW,YAAY,OAAO;CAE9B,IAAI,CAAC,OAAO,UAAU,GAAG,KAAK,MAAM,GAChC,OAAO,oBAAI,IAAI,UAAU,4CAA6C,KAAM,CAAC;CAGjF,OAAO,aAAa,SAAS,UAAU,UAAU,GAAG;AACxD;;;;;;;;;;;;;;;;;;;;AAqBA,SAAgB,cAAc,UAAkB,UAAgC,SAAsC;CAClH,MAAM,cAAc,qBAAqB,QAAQ;CACjD,IAAI,YAAY,MAAM,GAAG,OAAO,YAAY,MAAM;CAClD,WAAW,YAAY,OAAO;CAG9B,MAAM,aAAa,6BAA6B,QAAQ;CACxD,IAAI,WAAW,MAAM,GAAG,OAAO,WAAW,MAAM;CAGhD,OAAO,aAAa,SAAS,WAAW,UAAU,SAAS,YAAY,QAAQ,CAAC;AACpF;;;;;;;;;;;;;;;;;;;;;AAsBA,SAAgB,eAAe,UAAkB,UAAgC,SAAuC;CACpH,OAAO,cAAc,UAAU,UAAU;EACrC,QAAQ;EACR,QAAQ,SAAS;CACrB,CAAC;AACL;;;;;;;;;;;;;;;;;;;;AAqBA,SAAgB,SAAS,SAAiB,UAAkB,SAAqC;CAC7F,MAAM,aAAa,qBAAqB,OAAO;CAC/C,IAAI,WAAW,MAAM,GAAG,OAAO,WAAW,MAAM;CAChD,UAAU,WAAW,OAAO;CAE5B,MAAM,cAAc,qBAAqB,QAAQ;CACjD,IAAI,YAAY,MAAM,GAAG,OAAO,YAAY,MAAM;CAClD,WAAW,YAAY,OAAO;CAE9B,OAAO,aAAa,SAAS,MAAM,SAAS,UAAU,OAAO;AACjE;;;;;;;;;;;;;;AAeA,SAAgB,aAAa,SAA+B;CACxD,MAAM,aAAa,qBAAqB,OAAO;CAC/C,IAAI,WAAW,MAAM,GAAG,OAAO,WAAW,MAAM;CAChD,UAAU,WAAW,OAAO;CAE5B,OAAO,aAAa,SAAS,UAAU,OAAO;AAClD;;;;;;;;;;;;;;;;AAiBA,SAAgB,WAAW,MAAc,SAA4C;CACjF,MAAM,UAAU,qBAAqB,IAAI;CACzC,IAAI,QAAQ,MAAM,GAAG,OAAO,QAAQ,MAAM;CAC1C,OAAO,QAAQ,OAAO;CAEtB,MAAM,aAAa,sBAAsB,OAAO;CAChD,IAAI,WAAW,MAAM,GAAG,OAAO,WAAW,MAAM;CAEhD,OAAO,aAAa,SAAS,QAAQ,MAAM,OAAO;AACtD;;;;;;;;;;;;;AAcA,SAAgB,iBAA+B;CAC3C,OAAO,aAAa,SAAS,UAAU;AAC3C;;;;;;;;;;;;;;;AAgBA,SAAgB,WAAW,SAAyC;CAChE,OAAO,aAAa,SAAS,QAAQ,OAAO;AAChD;;;;;;;;;;;;;;;;AAiBA,SAAgB,cAAc,SAA6B;CACvD,MAAM,aAAa,oBAAoB,OAAO;CAC9C,IAAI,WAAW,MAAM,GAAG,OAAO;CAE/B,OAAO,aAAa,SAAS,WAAW,OAAO;AACnD;;;;;;;;;;;;;;;AAgBA,SAAgB,iBAAiB,UAAkC;CAC/D,OAAO,aAAa,UAAU,EAC1B,UAAU,OACd,CAAC;AACL;;;;;;;;;;;;;;;;;AAkBA,SAAgB,iBAAoB,UAA+B;CAC/D,OAAO,iBAAiB,QAAQ,CAAC,CAAC,SAAQ,aAAY;EAClD,OAAO,UAA8B,KAAK,OAAO,QAAQ;CAC7D,CAAC;AACL;;;;;;;;;;;;;;;AAgBA,SAAgB,iBAAiB,UAAoC;CACjE,OAAO,aAAa,UAAU,EAC1B,UAAU,OACd,CAAC;AACL;;;;;;;;;;;;;;;;;AAkBA,SAAgB,kBAAqB,UAAkB,MAAuB;CAC1E,OAAO,UAAU,KAAK,WAAW,IAAI,CAAC,CACjC,SAAQ,SAAQ,cAAc,UAAU,IAAI,CAAC;AACtD;;;;;;;;;;;;;;;AAgBA,SAAgB,UAAU,aAAqB,SAA+B;CAC1E,MAAM,iBAAiB,qBAAqB,WAAW;CACvD,IAAI,eAAe,MAAM,GAAG,OAAO,eAAe,MAAM;CACxD,cAAc,eAAe,OAAO;CAEpC,MAAM,aAAa,qBAAqB,OAAO;CAC/C,IAAI,WAAW,MAAM,GAAG,OAAO,WAAW,MAAM;CAChD,UAAU,WAAW,OAAO;CAE5B,OAAO,aAAa,SAAS,OAAO,aAAa,OAAO;AAC5D;;;;;;;;;;;;AA6CA,SAAgB,QAAQ,YAAoB,aAAmC,SAAgE;CAC3I,MAAM,gBAAgB,qBAAqB,UAAU;CACrD,IAAI,cAAc,MAAM,GAAG,OAAO,cAAc,MAAM;CACtD,aAAa,cAAc,OAAO;CAGlC,IAAI,OAAO,gBAAgB,UAAU;EACjC,MAAM,iBAAiB,qBAAqB,WAAW;EACvD,IAAI,eAAe,MAAM,GAAG,OAAO,eAAe,MAAM;EACxD,cAAc,eAAe,OAAO;CACxC;CAGA,OAAO,aAAa,SAAS,KAAK,YAAY,aAAa,OAAO;AACtE;;;;;;;AAUA,SAAS,iBAAiB,OAAyB;CAC/C,MAAM,MAAM,IAAI,MAAM,MAAM,OAAO;CACnC,IAAI,OAAO,MAAM;CAEjB,OAAO;AACX;;;;;;;;;AAUA,SAAS,gBAAgB,UAAwB,MAAqC;CAClF,OAAO,IAAI,KAAK,CAAC,IAAI,GAAG,SAAS,MAAM;EACnC,MAAM,SAAS;EACf,cAAc,SAAS;CAC3B,CAAC;AACL;;;;;;;;AASA,SAAS,WAAW,WAAwC;CACxD,MAAM,UAAU,uBAAuB;CACvC,MAAM,QAAQ,YAAY,IAAI;CAC9B,OAAO,CAAC,UAAU,GACd,IAAI,YAAY,IAAI,IAAI,QAAQ,SAAS;EACrC,MAAM,wBAAQ,IAAI,MAAM,qBAAqB;EAC7C,MAAM,OAAO;EAEb,OAAO,IAAI,KAAK;CACpB;CAGJ,OAAO,GAAG;AACd;;;;;;;;;;;;;;;;AAiBA,SAAS,mBAAmB,WAA0B,MAAwE;CAC1H,MAAM,EAAE,MAAM,kBAAkB;CAChC,MAAM,gBAAgB,KAAK;CAG3B,IAAI,gBAAgB,eAChB,OAAO,oBAAI,IAAI,WAAW,yBAA0B,cAAe,KAAM,cAAe,oDAAoD,CAAC;CAIjJ,QAAQ,MAAM,MAAM,iBAAiB,WAAW;CAGhD,KAAK,cAAc;CACnB,UAAU,WAAW,IAAI;CAKzB,QAAQ,MAAM,MAAM,mBAAmB,eAAe;CAGtD,MAAM,aAAa,iBAAiB,QAAQ,KAAK,MAAM,eAAe,MAAM,aAAa;CACzF,IAAI,WAAW,MAAM,GACjB,OAAO,WAAW,MAAM;CAO5B,OAAO,GAFU,UAAU,WADJ,KAAK,WAGlB,CAAQ;AACtB;;;;;;;;;;AAWA,SAAS,aAAgB,IAAc,GAAG,MAA8B;CACpE,IAAI,oBAAoB,MAAM,SAC1B,OAAO,oBAAI,IAAI,MAAM,4BAA4B,CAAC;CAStD,OAAO,mBANW,aAMQ,GAFN,cAAc,CADjB,IAAI,GAAG,IACU,CAEG,CAAW,CAAC,CAC5C,SAAQ,aAAY;EAGjB,MAAM,kBAAkB,cAAgD,QAAQ;EAChF,MAAM,MAAM,gBAAgB;EAC5B,IAAI,KACA,OAAO,IAAI,iBAAiB,GAAG,CAAC;EAIpC,IAAI,gBAAgB,WAAW,GAC3B,OAAO,GAAG,gBAAgB,EAAO;EAGrC,OAAO,GAAG,gBAAgB,MAAM,CAAC,CAAM;CAC3C,CAAC;AACT"}