{"version":3,"file":"sync.cjs","names":["validateAbsolutePath","WorkerOp","decodeUtf8","Err","validateWriteSyncFileContent","toBytesView","validateExistsOptions","validateExpiredDate","tryResult","getGlobalSyncOpTimeout","TIMEOUT_ERROR","Ok","MAIN_LOCK_INDEX","MAIN_UNLOCKED","MAIN_LOCKED","DATA_INDEX","WORKER_LOCK_INDEX","WORKER_UNLOCKED","getSyncChannelState","getMessenger","encodePayload","decodePayload"],"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 {\n    decodeUtf8,\n    toBytesView,\n    validateAbsolutePath,\n    validateExistsOptions,\n    validateExpiredDate,\n    validateWriteSyncFileContent,\n} from '../shared/internal/mod.ts';\nimport {\n    TIMEOUT_ERROR,\n    type AppendOptions,\n    type CopyOptions,\n    type DirEntryLike,\n    type DirEntrySlim,\n    type ExistsOptions,\n    type FileSystemHandleLike,\n    type MoveOptions,\n    type ReadDirSyncOptions,\n    type ReadSyncFileContent,\n    type ReadSyncOptions,\n    type TempOptions,\n    type WriteOptions,\n    type WriteSyncFileContent,\n    type ZipOptions,\n} from '../shared/mod.ts';\nimport { getGlobalSyncOpTimeout, getMessenger, getSyncChannelState } from './channel/state.ts';\nimport type { ErrorLike, FileMetadata } from './defines.ts';\nimport {\n    DATA_INDEX,\n    decodePayload,\n    encodePayload,\n    MAIN_LOCK_INDEX,\n    MAIN_LOCKED,\n    MAIN_UNLOCKED,\n    WORKER_LOCK_INDEX,\n    WORKER_UNLOCKED,\n    WorkerOp,\n    type SyncMessenger,\n} 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 without file metadata.\n *\n * Each entry carries only `path` and `kind`: no per-file `getFile()` lookup is performed\n * and the response stays small, which is what makes listing a large tree feasible.\n * Read metadata with {@link statSync} when it is actually needed.\n *\n * @param dirPath - The absolute path of the directory to read.\n * @param options - Read options with `withMetadata: false`.\n * @returns An `IOResult` containing an array of directory entries without metadata.\n * @see {@link readDirSync} for the metadata-carrying overload\n * @since 2.3.0\n * @example\n * ```typescript\n * readDirSync('/documents', { recursive: true, withMetadata: false })\n *     .inspect(entries => entries.forEach(entry => console.log(entry.path, entry.kind)));\n * ```\n */\nexport function readDirSync(\n    dirPath: string,\n    options: ReadDirSyncOptions & {\n        withMetadata: false;\n    },\n): IOResult<DirEntrySlim[]>;\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 * Pass `{ withMetadata: false }` to skip the per-file metadata lookup and get\n * `DirEntrySlim[]` instead, which keeps the response small when listing a large tree.\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(\n    dirPath: string,\n    options?: ReadDirSyncOptions,\n): IOResult<DirEntryLike[]>;\nexport function readDirSync(\n    dirPath: string,\n    options?: ReadDirSyncOptions,\n): IOResult<DirEntryLike[] | DirEntrySlim[]> {\n    const dirPathRes = validateAbsolutePath(dirPath);\n    if (dirPathRes.isErr()) return dirPathRes.asErr();\n    dirPath = dirPathRes.unwrap();\n\n    return callWorkerOp<DirEntryLike[] | DirEntrySlim[]>(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(\n    filePath: string,\n    options: ReadSyncOptions & {\n        encoding: 'blob';\n    },\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(\n    filePath: string,\n    options: ReadSyncOptions & {\n        encoding: 'utf8';\n    },\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(\n    filePath: string,\n    options?: ReadSyncOptions & {\n        encoding?: 'bytes';\n    },\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(\n    filePath: string,\n    options?: ReadSyncOptions,\n): 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(\n    filePath: string,\n    options?: ReadSyncOptions,\n): 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>]>(\n            WorkerOp.readBlobFile,\n            filePath,\n        );\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(\n    filePath: string,\n    contents: WriteSyncFileContent,\n    options?: WriteOptions,\n): 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(\n    filePath: string,\n    contents: WriteSyncFileContent,\n    options?: AppendOptions,\n): 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).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(\n    sourcePath: string,\n    zipFilePath: string,\n    options?: ZipOptions,\n): 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(\n    sourcePath: string,\n    options?: ZipOptions,\n): 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(\n    sourcePath: string,\n    zipFilePath?: string | ZipOptions,\n    options?: ZipOptions,\n): 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 * @param message - Error message used when the wait times out.\n * @returns A `VoidIOResult` - `Ok` if condition met, `Err` with TimeoutError if timed out.\n */\nfunction sleepUntil(condition: () => boolean, message = 'Operation timed out'): VoidIOResult {\n    const timeout = getGlobalSyncOpTimeout();\n    const start = performance.now();\n    while (!condition()) {\n        if (performance.now() - start > timeout) {\n            const error = new Error(message);\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. Drain a response that a timed-out earlier call left in flight, if any\n * 2. Lock main thread (set MAIN_LOCKED) to signal we're waiting\n * 3. Write request data and length to SharedArrayBuffer\n * 4. Wake worker by setting WORKER_UNLOCKED\n * 5. Busy-wait until worker signals completion (MAIN_UNLOCKED)\n * 6. 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(\n    messenger: SyncMessenger,\n    data: Uint8Array<ArrayBuffer>,\n): 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(\n            new RangeError(\n                `Request is too large: ${requestLength} > ${maxDataLength}. Consider increasing the size of SharedArrayBuffer`,\n            ),\n        );\n    }\n\n    // The slot must be free before it is reused. A timed-out call leaves MAIN_LOCK\n    // locked and only the worker unlocks it when it answers, so waiting for the\n    // unlock drains the pending response instead of letting it be decoded as the\n    // result of this call (its content is discarded, only the idle worker matters).\n    // Assumes a single caller per channel: contexts sharing one buffer via `attach`\n    // must not issue operations concurrently.\n    const drainRes = sleepUntil(\n        () => Atomics.load(i32a, MAIN_LOCK_INDEX) === MAIN_UNLOCKED,\n        'Sync channel is still waiting for the previous operation to finish',\n    );\n    if (drainRes.isErr()) {\n        return drainRes.asErr();\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: the store covers a worker that is between waits, the notify\n    // releases one that is already blocked in Atomics.wait (see listen.ts)\n    Atomics.store(i32a, WORKER_LOCK_INDEX, WORKER_UNLOCKED);\n    Atomics.notify(i32a, WORKER_LOCK_INDEX, 1);\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        // MAIN_LOCK is intentionally left locked: the worker will still write the\n        // response of this request, and the next call must drain it first.\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).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            // Void operations serialize to `null`; surface them as `undefined` so\n            // the runtime value matches the declared `void` result type\n            return Ok((decodedResponse[1] ?? undefined) 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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8DA,MAAA,eAAgB,GAAe,2BAAgC,qBAAA,CAAA,QAAA;CAC3D,IAAA,YAAM,MAAA,GAAcA,OAAAA,YAAAA,MAAAA;CACpB,WAAI,YAAkB,OAAG;CACzB,OAAA,aAAW,qBAAmB,SAAA,YAAA,QAAA;AAE9B;;;;;;;;;;;;;;;;CAiBJ,MAAA,cAA0B,GAAA,2BAA+B,qBAAA,CAAA,OAAA;CACrD,IAAA,WAAM,MAAA,GAAaA,OAAAA,WAAAA,MAAAA;CACnB,UAAI,WAAiB,OAAG;CACxB,OAAA,aAAU,qBAAkB,SAAA,OAAA,OAAA;AAE5B;;;;;;;;;;;;;;;;;;CAmBJ,MAAA,cAAyB,GAAA,2BAAwE,qBAAA,CAAA,OAAA;CAC7F,IAAA,WAAM,MAAA,GAAaA,OAAAA,WAAAA,MAAAA;CACnB,UAAI,WAAiB,OAAG;CACxB,MAAA,eAAqB,GAAA,2BAAO,qBAAA,CAAA,QAAA;CAE5B,IAAA,YAAM,MAAA,GAAcA,OAAAA,YAAAA,MAAAA;CACpB,WAAI,YAAkB,OAAG;CACzB,OAAA,aAAW,qBAAmB,SAAA,MAAA,SAAA,UAAA,OAAA;AAE9B;AACJ,SAAA,YAAA,SAAA,SAAA;CAsDA,MAAA,cACI,GAAA,2BAEyC,qBAAA,CAAA,OAAA;CACzC,IAAA,WAAM,MAAA,GAAaA,OAAAA,WAAAA,MAAAA;CACnB,UAAI,WAAiB,OAAG;CACxB,OAAA,aAAU,qBAAkB,SAAA,SAAA,SAAA,OAAA;AAE5B;;;;;;;;;;;CAsGJ,MAAA,eACI,GAAA,2BAE6B,qBAAA,CAAA,QAAA;CAC7B,IAAA,YAAM,MAAA,GAAcA,OAAAA,YAAAA,MAAAA;CACpB,WAAI,YAAkB,OAAG;CACzB,MAAA,WAAW,SAAY;CAEvB,IAAA,aAAiB,QAAA,OAAS,aAAA,qBAAA,SAAA,cAAA,QAAA,CAAA,CAAA,KAAA,CAAA,UAAA,UAAA,gBAAA,UAAA,IAAA,CAAA;CAG1B,OAAI,aAAa,qBAEG,SACZC,UAAAA,QAAAA,CAAAA,CAAAA,KAAS,UAAA;EASjB,IAAA,aADgB,QAAsCA,QAAAA,GAAAA,2BAAmB,WAC1D,CAAI,KAAA;EACf,OAAI;CAIJ,CAAA;AACJ;;;;;;;;;;;;;;;;CAiBJ,MAAA,WAAgB,GAAW,2BAA4B,qBAAA,CAAA,IAAA;CACnD,IAAA,QAAM,MAAA,GAAUD,OAAAA,QAAAA,MAAAA;CAChB,OAAI,QAAQ,OAAS;CACrB,OAAO,aAAQ,qBAAO,SAAA,QAAA,IAAA;AAEtB;;;;;;;;;;;;;;;;;;;;;;CAuBJ,MAAA,WAAyB,GAAA,2BAA8C,qBAAA,CAAA,IAAA;CACnE,IAAA,QAAM,MAAA,GAAUA,OAAAA,QAAAA,MAAAA;CAChB,OAAI,QAAQ,OAAS;CACrB,OAAO,aAAQ,qBAAO,SAAA,MAAA,IAAA;AAEtB;;;;;;;;;;;;;;;;;;;;;CAsBJ,MAAA,eAA6B,GAAA,2BAA6C,qBAAA,CAAA,QAAA;CACtE,IAAA,YAAM,MAAA,GAAcA,OAAAA,YAAAA,MAAAA;CACpB,WAAI,YAAkB,OAAG;CACzB,IAAA,CAAA,OAAW,UAAA,GAAY,KAAO,MAAA,GAAA,QAAA,GAAA,YAAA,IAAA,iBAAA,IAAA,UAAA,4CAAA,KAAA,CAAA;CAE9B,OAAK,aAAO,qBACR,SAAOG,UAAAA,UAAAA,GAAAA;AAGX;;;;;;;;;;;;;;;;;;;;;CAsBJ,MAAA,eAAgB,GACZ,2BAGY,qBAAA,CAAA,QAAA;CACZ,IAAA,YAAM,MAAA,GAAcH,OAAAA,YAAAA,MAAAA;CACpB,WAAI,YAAkB,OAAG;CACzB,MAAA,cAAW,GAAY,2BAAO,6BAAA,CAAA,QAAA;CAG9B,IAAA,WAAM,MAAA,GAAaI,OAAAA,WAAAA,MAAAA;CACnB,OAAI,aAAW,qBAAgB,SAAiB,WAAA,UAAA,UAAA,GAAA,2BAAA,YAAA,CAAA,QAAA,CAAA;AAGhD;;;;;;;;;;;;;;;;;;;;;;CAuBJ,OAAA,cAAgB,UACZ,UACA;EAGA,QAAO;EACH,QAAQ,SAAA;CACR,CAAA;AACJ;;;;;;;;;;;;;;;;;;;;;CAsBJ,MAAA,cAAyB,GAAA,2BAAwE,qBAAA,CAAA,OAAA;CAC7F,IAAA,WAAM,MAAA,GAAaJ,OAAAA,WAAAA,MAAAA;CACnB,UAAI,WAAiB,OAAG;CACxB,MAAA,eAAqB,GAAA,2BAAO,qBAAA,CAAA,QAAA;CAE5B,IAAA,YAAM,MAAA,GAAcA,OAAAA,YAAAA,MAAAA;CACpB,WAAI,YAAkB,OAAG;CACzB,OAAA,aAAW,qBAAmB,SAAA,MAAA,SAAA,UAAA,OAAA;AAE9B;;;;;;;;;;;;;;;CAgBJ,MAAA,cAAgB,GAAa,2BAA+B,qBAAA,CAAA,OAAA;CACxD,IAAA,WAAM,MAAA,GAAaA,OAAAA,WAAAA,MAAAA;CACnB,UAAI,WAAiB,OAAG;CACxB,OAAA,aAAU,qBAAkB,SAAA,UAAA,OAAA;AAE5B;;;;;;;;;;;;;;;;;CAkBJ,MAAA,WAAgB,GAAW,2BAA0D,qBAAA,CAAA,IAAA;CACjF,IAAA,QAAM,MAAA,GAAUA,OAAAA,QAAAA,MAAAA;CAChB,OAAI,QAAQ,OAAS;CACrB,MAAA,cAAe,GAAO,2BAAA,sBAAA,CAAA,OAAA;CAEtB,IAAA,WAAM,MAAA,GAAaM,OAAAA,WAAAA,MAAAA;CACnB,OAAI,aAAW,qBAAgB,SAAiB,QAAA,MAAA,OAAA;AAEhD;;;;;;;;;;;;;;CAeJ,OAAA,aAAgB,qBAA+B,SAAA,UAAA;AAC3C;;;;;;;;;;;;;;;;CAiBJ,OAAA,aAA2B,qBAAyC,SAAA,QAAA,OAAA;AAChE;;;;;;;;;;;;;;;;;CAkBJ,MAAA,cAAgB,GAAc,2BAA6B,oBAAA,CAAA,OAAA;CACvD,IAAA,WAAM,MAAA,GAAaC,OAAAA;CACnB,OAAI,aAAW,qBAAgB,SAAA,WAAA,OAAA;AAE/B;;;;;;;;;;;;;;;;CAiBJ,OAAA,aAAgB,UAAiB,EAAA,UAAkC,OAAA,CAAA;AAC/D;;;;;;;;;;;;;;;;;;CAqBJ,OAAA,iBAAgB,QAAoB,CAAA,CAAA,SAA+B,aAAA;EAC/D,QAAO,GAAA,YAAiB,UAAS,CAAC,KAAA,OAAQ,QAAA;CACtC,CAAA;AACJ;;;;;;;;;;;;;;;;CAiBJ,OAAA,aAAgB,UAAiB,EAAA,UAAoC,OAAA,CAAA;AACjE;;;;;;;;;;;;;;;;;;CAqBJ,QAAgB,GAAA,YAAA,UAAqB,CAAA,KAAkB,WAAuB,IAAA,CAAA,CAAA,SAAA,SAAA,cAAA,UAAA,IAAA,CAAA;AAC1E;;;;;;;;;;;;;;;;CAiBJ,MAAA,kBAA0B,GAAA,2BAAoD,qBAAA,CAAA,WAAA;CAC1E,IAAA,eAAM,MAAA,GAAiBP,OAAAA,eAAAA,MAAAA;CACvB,cAAI,eAAwB,OAAO;CACnC,MAAA,cAAc,GAAA,2BAAsB,qBAAA,CAAA,OAAA;CAEpC,IAAA,WAAM,MAAA,GAAaA,OAAAA,WAAAA,MAAAA;CACnB,UAAI,WAAiB,OAAG;CACxB,OAAA,aAAU,qBAAkB,SAAA,OAAA,aAAA,OAAA;AAE5B;;;;;;;;;;;;;CAqDJ,MAAA,iBACI,GAAA,2BAGwC,qBAAA,CAAA,UAAA;CACxC,IAAA,cAAM,MAAA,GAAgBA,OAAAA,cAAAA,MAAAA;CACtB,aAAI,cAAuB,OAAO;CAClC,IAAA,OAAA,gBAA2B,UAAO;EAGlC,MAAI,kBAAO,GAAgB,2BAAU,qBAAA,CAAA,WAAA;EACjC,IAAA,eAAM,MAAA,GAAiBA,OAAAA,eAAAA,MAAAA;EACvB,cAAI,eAAwB,OAAO;CACnC;CACJ,OAAA,aAAA,qBAAA,SAAA,KAAA,YAAA,aAAA,OAAA;AAGA;;;;;;;;CAWJ,MAAA,MAAS,IAAA,MAAA,MAAiB,OAAyB;CAC/C,IAAA,OAAM,MAAU;CAChB,OAAI;AAEJ;;;;;;;;;;CAWJ,OAAA,IAAS,KAAA,CAAA,IAAA,GAAgB,SAAA,MAAwB;EAC7C,MAAO,SAAS;EACZ,cAAM,SAAS;CACf,CAAA;AACJ;;;;;;;;;;CAWJ,MAAA,WAAS,GAAW,0BAAoC,uBAAqC,CAAA;CACzF,MAAM,QAAA,YAAUS,IAAAA;CAChB,OAAM,CAAA,UAAQ,GAAA,IAAA,YAAgB,IAAA,IAAA,QAAA,SAAA;EAC9B,MAAO,QAAC,IAAU,MACV,OAAA;EACA,MAAM,OAAA,kBAAyB;EAC/B,QAAM,GAAA,YAAOC,IAAAA,CAAAA,KAAAA;CAEb;CACJ,QAAA,GAAA,YAAA,GAAA,CAAA;AAGJ;;;;;;;;;;;;;;;;;;CAmBJ,MAAA,EAAS,MAAA,kBACL;CAGA,MAAM,gBAAQ,KAAA;CACd,IAAA,gBAAM,eAAqB,QAAA,GAAA,YAAA,IAAA,iBAAA,IAAA,WAAA,yBAAA,cAAA,KAAA,cAAA,oDAAA,CAAA;CAG3B,MAAI,WAAA,iBAAgB,QAChB,KAAOP,MAAAA,qBAAAA,eACC,MACA,qBAAA,eAAyB,oEAAiC;CAWtE,IAAA,SAAM,MAAW,GAAA,OAAA,SACP,MAAQ;CAGlB,QAAI,MAAS,MAAM,qBACC,iBAAM,qBAAA,WAAA;CAI1B,KAAA,qBAAoBS,cAAAA;CAGpB,UAAKG,WAAAA,IAAAA;CACL,QAAA,MAAU,MAAA,qBAAe,mBAAA,qBAAA,eAAA;CAIzB,QAAQ,OAAM,MAAMC,qBAAAA,mBAAmBC,CAAAA;CACvC,MAAA,aAAe,iBAAMD,QAAAA,KAAAA,MAAAA,qBAAoB,eAAA,MAAA,qBAAA,aAAA;CAGzC,IAAA,WAAM,MAAa,GAAA,OAAA,WAAiB,MAAQ;CAC5C,MAAI,WAAW,UAGX,WAAO,KAAW,qBAAM,WAAA;CAK5B,QAAM,GAAA,YAAW,GAAA,CAAU,QAAA;AAE3B;;;;;;;;;;;CAYJ,KAAA,GAAS,0BAA+D,oBAAA,CAAA,MAAA,SAAA,QAAA,GAAA,YAAA,IAAA,iBAAA,IAAA,MAAA,4BAAA,CAAA;CACpE,MAAA,aAAIE,GAAAA,0BAAAA,aAAoB,CAAM;CAI9B,MAAM,UAAA,CAAA,IAAA,GAAYC,IAAAA;CAGlB,OAAM,mBAAkB,YAAI,GAAA,qBAAA,cAAA,CAAA,OAAA,CAAA,CAAA,CAAA,SAAA,aAAA;EAG5B,MAAO,mBAAmB,GAAA,qBAFNC,cAAAA,CAAAA,QAAAA;EAKhB,MAAM,MAAA,gBAAkBC;EACxB,IAAA,KAAM,QAAM,GAAA,YAAgB,IAAA,CAAA,iBAAA,GAAA,CAAA;EAC5B,IAAI,gBACOlB,WAAAA,GAAAA,QAAI,GAAA,YAAoB,GAAC,CAAA,gBAAA,MAAA,KAAA,CAAA;EAIpC,QAAI,GAAA,YAAgB,GAAA,CAAA,gBAGhB,MAAOQ,CAAAA,CAAAA;CAGX,CAAA;AACJ"}