{"version":3,"file":"fs.cjs","names":[],"sources":["../src/macros/env.ts","../src/std/fs/mina_fs_shared.ts","../src/std/fs/mina_fs_async.ts","../src/std/fs/web_fs_helpers.ts","../src/std/fs/fs_async.ts","../src/std/fs/mina_fs_sync.ts","../src/std/fs/fs_sync.ts"],"sourcesContent":["/**\n * @internal\n * 小游戏环境宏模块。\n */\n\n/**\n * 小游戏环境宏。\n *\n * 可通过打包工具在 build 时修改，如 esbuild webpack vite 等。\n */\ndeclare const __MINIGAME_STD_MINA__: boolean;\n\n/**\n * 如果在小游戏环境中返回 true，否则返回 false。\n */\nexport const IS_MINA = __MINIGAME_STD_MINA__;\n","/**\n * @internal\n * 同步/异步的公共代码。\n */\n\nimport { NOT_FOUND_ERROR, NOTHING_TO_ZIP_ERROR, ROOT_DIR, type ExistsOptions } from 'happy-opfs';\nimport { Err, Lazy, Ok, RESULT_FALSE, RESULT_VOID, tryResult, type AsyncIOResult, type IOResult, type Result, type VoidIOResult } from 'happy-rusty';\nimport { bufferSourceToAb, miniGameFailureToError } from '../internal/mod.ts';\nimport { normalize } from '../path/mod.ts';\nimport { asyncResultify } from '../utils/mod.ts';\nimport type { ReadOptions, WriteFileContent } from './fs_define.ts';\n\n// #region Internal Variables\n\n/**\n * 小游戏文件系统管理器实例。\n *\n */\nconst fs = /*#__PURE__*/ Lazy(() => wx.getFileSystemManager());\n\n/**\n * 用户数据根目录，`wxfile://usr` 或 `http://usr`。\n *\n */\nconst usrPath = /*#__PURE__*/ Lazy(() => wx.env.USER_DATA_PATH);\n\n/**\n * 根路径，`wxfile://` 或 `http://`。\n *\n */\nconst rootPath = /*#__PURE__*/ Lazy(() => {\n    const path = usrPath.force();\n    // 剥离 `usr`\n    return `${path.split('://')[0]}://`;\n});\n\n// #endregion\n\n/**\n * zip 操作的结果。\n */\nexport type ZipIOResult = IOResult<Uint8Array<ArrayBuffer> | void>;\n\nexport const EMPTY_BYTES: Uint8Array<ArrayBuffer> = /*#__PURE__*/ new Uint8Array(0);\n\n/**\n * 获取小游戏文件系统管理器实例。\n * @returns 文件系统管理器实例。\n */\nexport function getFs(): WechatMinigame.FileSystemManager {\n    return fs.force();\n}\n\n/**\n * 获取文件系统的根路径。\n * @returns 文件系统的根路径。\n */\nexport function getUsrPath(): string {\n    return usrPath.force();\n}\n\n/**\n * 验证并标准化路径，返回绝对路径。\n *\n * 支持两种输入格式：\n * 1. 完整路径：以 `wxfile://` 或 `http://` 开头（如 `wxfile://usr/test`）\n * 2. 相对路径：以 `/` 开头（如 `/test`），会自动拼接 `wx.env.USER_DATA_PATH`\n *\n * @param path - 待验证的路径。\n * @returns 验证成功返回标准化后的绝对路径，失败返回错误信息。\n */\nexport function validateAbsolutePath(path: string): IOResult<string> {\n    const typeError = validatePathType(path);\n    if (typeError) return typeError;\n\n    // 是否已经是完整路径\n    let isFullPath = false;\n    // 检查是否为完整路径（以 `wxfile://` 或 `http://` 开头）\n    if (path.startsWith(rootPath.force())) {\n        isFullPath = true;\n        // 先剥离协议前缀，避免 normalize 将 `://` 转换为 `:/`\n        path = path.slice(rootPath.force().length);\n        // 传根路径没意义\n        if (!path) {\n            return Err(new Error('Path must not be root directory'));\n        }\n    }\n\n    // 标准化路径（处理 `.`、`..` 等）并去除末尾的 `/`\n    const normalized = normalize(path);\n    path = normalized.length > 1 && normalized[normalized.length - 1] === ROOT_DIR\n        ? normalized.slice(0, -1)\n        : normalized;\n\n    // 完整路径：重新拼接协议前缀\n    if (isFullPath) {\n        // 还是根路径\n        if (path === ROOT_DIR) {\n            return Err(new Error('Path must not be root directory'));\n        }\n        // 确保路径不是以 `/` 开头，避免 `wxfile:///usr` 这样的多斜杠情况\n        if (path[0] === ROOT_DIR) {\n            path = path.slice(1);\n        }\n        return Ok(rootPath.force() + path);\n    }\n\n    // 相对路径：必须以 `/` 开头\n    if (path[0] !== ROOT_DIR) {\n        return Err(new Error(`Path must be absolute (start with '/'): '${path}'`));\n    }\n\n    // 拼接用户数据根目录\n    return Ok(usrPath.force() + path);\n}\n\n/**\n * 验证可读路径（用于只读操作：readFile、stat、readDir）。\n *\n * 支持三种输入格式：\n * 1. 完整路径：以 `wxfile://` 或 `http://` 开头（如 `wxfile://usr/test`）\n * 2. 用户数据相对路径：以 `/` 开头（如 `/test`），会自动拼接 `wx.env.USER_DATA_PATH`\n * 3. 代码包路径：不以 `./`、`../` 开头的相对路径（如 `images/logo.png`），直接返回原路径\n *\n * @param path - 待验证的路径。\n * @returns 验证成功返回标准化后的路径，失败返回错误信息。\n */\nexport function validateReadablePath(path: string): IOResult<string> {\n    const typeError = validatePathType(path);\n    if (typeError) return typeError;\n\n    // 对于完整路径和以 / 开头的路径，使用现有的绝对路径验证\n    if (path.startsWith(rootPath.force()) || path.startsWith(ROOT_DIR)) {\n        return validateAbsolutePath(path);\n    }\n\n    // 既不是完整路径，也不以 / 开头，检查是否为代码包路径（不以 ./、../ 开头）\n    if (path.startsWith('./') || path.startsWith('../')) {\n        return Err(new Error(`Invalid path: '${path}'. Code package paths must not start with './' or '../'`));\n    }\n\n    // 代码包路径返回标准化后的结果\n    const normalized = normalize(path);\n    return Ok(normalized);\n}\n\n/**\n * 验证提供的 ExistsOptions 是否有效。\n * `isDirectory` 和 `isFile` 不能同时为 `true`。\n *\n * @param options - 要验证的 ExistsOptions。\n * @returns 表示成功或错误的 VoidIOResult。\n */\nexport function validateExistsOptions(options?: ExistsOptions): VoidIOResult {\n    const { isDirectory = false, isFile = false } = options ?? {};\n\n    return isDirectory && isFile\n        ? Err(new Error('isDirectory and isFile cannot both be true'))\n        : RESULT_VOID;\n}\n\n/**\n * 判断错误是否为 `NotFoundError`。\n * @param error - 要检查的错误。\n * @returns 如果是 `NotFoundError` 返回 `true`，否则返回 `false`。\n */\nexport function isNotFoundError(error: Error): boolean {\n    return error.name === NOT_FOUND_ERROR;\n}\n\n/**\n * 将错误对象转换为 IOResult 类型。\n * @typeParam T - Result 的 Ok 类型。\n * @param error - IO 操作的错误对象, 可以是同步(Error)或者异步(WechatMinigame.FileError)的。\n * @returns 转换后的 IOResult 对象。\n */\nexport function fileErrorToResult<T>(error: FileError): IOResult<T> {\n    const err = miniGameFailureToError(error);\n\n    if (isNotFoundFileError(err)) {\n        err.name = NOT_FOUND_ERROR;\n    }\n\n    return Err(err);\n}\n\n/**\n * 处理 `mkdir` 的错误。\n */\nexport function fileErrorToMkdirResult(error: FileError): VoidIOResult {\n    // 已存在当做成功\n    return isAlreadyExistsFileError(error) ? RESULT_VOID : fileErrorToResult(error);\n}\n\n/**\n * 处理 `remove` 的错误。\n */\nexport function fileErrorToRemoveResult(error: FileError): VoidIOResult {\n    // 目标 path 本就不存在，当做成功\n    return isNotFoundFileError(error) ? RESULT_VOID : fileErrorToResult(error);\n}\n\n/*\n * 创建 `NothingToZipError` 错误。\n */\nexport function createNothingToZipError(): IOResult<never> {\n    const error = new Error('Nothing to zip');\n    error.name = NOTHING_TO_ZIP_ERROR;\n\n    return Err(error);\n}\n\n/*\n * 创建\"文件不存在且 create 为 false\"的错误。\n * @param filePath - 文件路径。\n * @returns 错误结果。\n */\nexport function createFileNotExistsError(filePath: string): IOResult<never> {\n    return Err(new Error(`Cannot append to non-existent file: ${filePath}`));\n}\n\n/*\n * 创建\"目录已存在但是文件\"的错误。\n * @param dirPath - 目录路径。\n * @returns 错误结果。\n */\nexport function createDirIsFileError(dirPath: string): IOResult<never> {\n    return Err(new Error(`Path already exists but is a file: ${dirPath}`));\n}\n\n/**\n * 获取读取文件的编码。\n * @returns 返回 `'utf8'` 或 `undefined`（读取二进制时不传 encoding）。\n */\nexport function getReadFileEncoding(options?: ReadOptions): 'utf8' | undefined {\n    // NOTE: 想要读取 ArrayBuffer 就不能传 encoding\n    // 如果传了 'bytes' 或不传，返回 undefined\n    return options?.encoding === 'utf8' ? 'utf8' : undefined;\n}\n\n/**\n * 获取写入文件的参数。\n */\nexport function getWriteFileContents(contents: WriteFileContent): IOResult<GetWriteFileContents> {\n    const isBin = typeof contents !== 'string';\n\n    let data: string | ArrayBuffer;\n\n    if (isBin) {\n        const result = tryResult(() => bufferSourceToAb(contents));\n        if (result.isErr()) return result.asErr();\n\n        data = result.unwrap();\n    } else {\n        data = contents;\n    }\n\n    const encoding = isBin ? undefined : 'utf8';\n\n    return Ok({\n        data,\n        encoding,\n    });\n}\n\n/**\n * 获取 `exists` 的结果。\n *\n * 注意：Windows 和 Mac 平台 `stat` 代码包内不存在的文件时, 平台会误报成功并返回 `stats.size = -1`。\n * 此处通过 `stats.size < 0` 判断并视为不存在, 以兼容该平台 bug。\n *\n * TODO(platform-wx): 待微信 Windows/Mac 平台修复该 stat 误报 bug 后, 移除 `stats.size < 0` 判断。\n * 跟踪点: `mina_fs_shared.ts` getExistsResult。\n */\nexport function getExistsResult(statResult: IOResult<WechatMinigame.Stats>, options?: ExistsOptions): IOResult<boolean> {\n    return statResult.map(stats => {\n        const { isDirectory = false, isFile = false } = options ?? {};\n\n        const notExist =\n            stats.size < 0 // TODO(platform-wx): Windows/Mac 平台 stat 代码包不存在文件时的误报, 待平台修复后移除\n            || (isDirectory && stats.isFile())\n            || (isFile && stats.isDirectory());\n\n        return !notExist;\n    }).orElse(err => {\n        return isNotFoundError(err) ? RESULT_FALSE : statResult.asErr();\n    });\n}\n\n/**\n * 判断文件/目录是否存在（不区分类型）。\n *\n * 相比 `stat` + `getExistsResult`，使用底层 `access` 接口开销更小，不会构造 `Stats` 对象。\n * 当 `ExistsOptions` 不需要检查 `isDirectory`/`isFile` 时使用此实现。\n *\n * @param path - 文件或目录路径。\n * @returns 存在返回 `true`，不存在返回 `false`，其他错误透传。\n */\nexport async function accessExists(path: string): AsyncIOResult<boolean> {\n    const pathRes = validateReadablePath(path);\n    if (pathRes.isErr()) return pathRes.asErr();\n    path = pathRes.unwrap();\n\n    const accessRes = await asyncResultify(getFs().access)({ path });\n    return accessResultToExists(accessRes);\n}\n\n/**\n * `accessExists` 的同步版本。\n *\n * @param path - 文件或目录路径。\n * @returns 存在返回 `true`，不存在返回 `false`，其他错误透传。\n */\nexport function accessExistsSync(path: string): IOResult<boolean> {\n    const pathRes = validateReadablePath(path);\n    if (pathRes.isErr()) return pathRes.asErr();\n    path = pathRes.unwrap();\n\n    const accessRes = tryResult(() => getFs().accessSync(path));\n    return accessResultToExists(accessRes);\n}\n\n\n/**\n * 根据 `recursive` 不同标准化 `stat` 的结果(recursive=true 的时候开发者工具对于文件和空文件夹会返回单个 Stats)。\n * - `recursive=false`: 返回单个 `Stats` 或 `FileStats[]`\n * - `recursive=true`: 始终返回 `FileStats[]`，即使是单个文件或空目录\n *   - 如果是单个 `Stats`，包装成数组，path 设为 '' 表示当前项目\n */\nexport function normalizeStats(statsOrFileStats: WechatMinigame.Stats | WechatMinigame.FileStats[], recursive: boolean): WechatMinigame.Stats | WechatMinigame.FileStats[] {\n    if (Array.isArray(statsOrFileStats)) {\n        return statsOrFileStats.map(({ path, stats }) => ({\n            path: path.replace(/^\\/+/, ''), // 返回相对路径, 去掉开头的 `/`(安卓子项目 path 不以 `/` 开头)\n            stats,\n        })).sort((a, b) => a.path.localeCompare(b.path)); // 按 path 排序\n    }\n\n    // 只要是 recursive 就返回数组(即使是文件或者空目录))\n    return recursive\n        ? [{\n            path: '', // 当前文件夹本身的相对路径\n            stats: statsOrFileStats,\n        }]\n        : statsOrFileStats;\n}\n\n// #region Internal Types\n\ntype FileError = WechatMinigame.FileError | (Error & {\n    errno?: number;\n});\n\ninterface GetWriteFileContents {\n    data: string | ArrayBuffer;\n    encoding?: 'utf8';\n}\n\n// #endregion\n\n// #region Internal Functions\n\n/**\n * 标准化同步或异步的文件错误对象。\n * @param error - IO 操作的错误对象, 可以是同步(Error)或者异步(WechatMinigame.FileError)的。\n */\nfunction normalizeFileError(error: FileError): WechatMinigame.FileError {\n    return error instanceof Error\n        ? {\n            errCode: error.errno ?? 0,\n            errMsg: error.message,\n        }\n        : error;\n}\n\n/**\n * 判断是否文件或者文件夹不存在。\n * @param error - IO 操作的错误对象, 可以是同步(Error)或者异步(WechatMinigame.FileError)的。\n */\nfunction isNotFoundFileError(error: FileError): boolean {\n    // 1300002\tno such file or directory ${path}\n    const { errCode, errMsg } = normalizeFileError(error);\n    // 可能没有errCode\n    return errCode === 1300002\n        || errMsg.includes('no such file or directory');\n}\n\n/**\n * 判断是否文件或者文件夹已存在。\n * @param error - IO 操作的错误对象, 可以是同步(Error)或者异步(WechatMinigame.FileError)的。\n */\nfunction isAlreadyExistsFileError(error: FileError): boolean {\n    // 1301005\tfile already exists ${dirPath}\t已有同名文件或目录\n    const { errCode, errMsg } = normalizeFileError(error);\n    // 可能没有errCode\n    return errCode === 1301005\n        || errMsg.includes('already exists');\n}\n\n/**\n * 验证 path 是否为字符串类型。\n * @param path - 待验证的路径。\n * @returns 如果不是字符串返回错误，否则返回 undefined。\n */\nfunction validatePathType(path: unknown): IOResult<never> | undefined {\n    if (typeof path !== 'string') {\n        return Err(new TypeError(`Path must be a string but received ${typeof path}`));\n    }\n}\n\n/**\n * 将 `access`/`accessSync` 调用的结果转换为存在性结果。\n * - 成功 → `true`\n * - NotFound → `false`\n * - 其他错误 → 透传\n */\nfunction accessResultToExists<T, E>(accessRes: Result<T, E>): IOResult<boolean> {\n    return accessRes\n        .map(() => true)\n        .orElse(err => {\n            // 归一化错误（识别 not found 并设置 name），再判断是否为不存在\n            const normalized = fileErrorToResult<boolean>(err as FileError).unwrapErr();\n            return isNotFoundError(normalized) ? RESULT_FALSE : Err(normalized);\n        });\n}\n\n// #endregion\n","/**\n * @internal\n * 小游戏平台的异步文件系统操作实现。\n */\n\nimport { ABORT_ERROR, FetchError, type FetchResult, type FetchTask } from '@happy-ts/fetch-t';\nimport { zipSync as compressSync, type AsyncZippable } from 'fflate/browser';\nimport { type AppendOptions, type ExistsOptions, type WriteOptions, type ZipOptions } from 'happy-opfs';\nimport { Err, Ok, RESULT_VOID, tryResult, type AsyncIOResult, type AsyncVoidIOResult, type IOResult, type VoidIOResult } from 'happy-rusty';\nimport { Future } from 'tiny-future';\nimport { createFailedFetchTask, miniGameFailureToError, validateSafeUrl } from '../internal/mod.ts';\nimport { basename, dirname, SEPARATOR } from '../path/mod.ts';\nimport { asyncResultify } from '../utils/mod.ts';\nimport type { ReadFileContent, ReadOptions, StatOptions, WriteFileContent } from './fs_define.ts';\nimport type { DownloadFileOptions, UploadFileOptions } from './mina_fs_define.ts';\nimport { accessExists, createDirIsFileError, createFileNotExistsError, createNothingToZipError, EMPTY_BYTES, fileErrorToMkdirResult, fileErrorToRemoveResult, fileErrorToResult, getExistsResult, getFs, getReadFileEncoding, getUsrPath, getWriteFileContents, isNotFoundError, normalizeStats, validateAbsolutePath, validateExistsOptions, validateReadablePath, type ZipIOResult } from './mina_fs_shared.ts';\n\n/**\n * 递归创建文件夹，相当于`mkdir -p`。\n * @param dirPath - 需要创建的目录路径。\n * @returns 创建操作的异步结果。\n */\nexport async function mkdir(dirPath: string): AsyncVoidIOResult {\n    // 为了检查根路径, 提前 validateAbsolutePath\n    const dirPathRes = validateAbsolutePath(dirPath);\n    if (dirPathRes.isErr()) return dirPathRes.asErr();\n    dirPath = dirPathRes.unwrap();\n\n    // 根目录无需创建\n    if (dirPath === getUsrPath()) {\n        return RESULT_VOID;\n    }\n\n    const statRes = await stat(dirPath);\n    if (statRes.isOk()) {\n        // 已存在并且是文件\n        if (statRes.unwrap().isFile()) {\n            return createDirIsFileError(dirPath);\n        }\n\n        // 存在文件夹则不创建\n        return RESULT_VOID;\n    }\n\n    // 递归创建\n    const mkdirRes = await asyncResultify(getFs().mkdir)({\n        dirPath,\n        recursive: true,\n    });\n\n    return mkdirRes\n        .and(RESULT_VOID)\n        .orElse(fileErrorToMkdirResult);\n}\n\n/**\n * 移动或重命名文件或目录。\n * @param srcPath - 原路径。\n * @param destPath - 新路径。\n * @returns 移动操作的异步结果。\n */\nexport async function move(srcPath: string, destPath: string): AsyncVoidIOResult {\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    const moveRes = await asyncResultify(getFs().rename)({\n        oldPath: srcPath,\n        newPath: destPath,\n    });\n\n    return moveRes\n        .and(RESULT_VOID)\n        .orElse(fileErrorToResult);\n}\n\n/**\n * 读取目录下的所有文件和子目录。\n * @param dirPath - 目录路径。\n * @returns 包含目录内容的字符串数组的异步结果。\n */\nexport async function readDir(dirPath: string): AsyncIOResult<string[]> {\n    const dirPathRes = validateReadablePath(dirPath);\n    if (dirPathRes.isErr()) return dirPathRes.asErr();\n    dirPath = dirPathRes.unwrap();\n\n    const readDirRes = await asyncResultify(getFs().readdir)({\n        dirPath,\n    });\n\n    return readDirRes\n        .map(x => x.files)\n        .orElse(fileErrorToResult);\n}\n\n/**\n * 以 UTF-8 格式读取文件。\n * @param filePath - 文件路径。\n * @param options - 读取选项，指定编码为 'utf8'。\n * @returns 包含文件内容的字符串的异步结果。\n */\nexport function readFile(filePath: string, options: ReadOptions & {\n    encoding: 'utf8';\n}): AsyncIOResult<string>;\n\n/**\n * 以二进制格式读取文件。\n * @param filePath - 文件路径。\n * @param options - 读取选项，指定编码为 'bytes'。\n * @returns 包含文件内容的 Uint8Array<ArrayBuffer> 的异步结果。\n */\nexport function readFile(filePath: string, options?: ReadOptions & {\n    encoding: 'bytes';\n}): AsyncIOResult<Uint8Array<ArrayBuffer>>;\n\n/**\n * 读取文件内容。\n * @param filePath - 文件路径。\n * @param options - 读取选项。\n * @returns 包含文件内容的异步结果。\n */\nexport function readFile(filePath: string, options?: ReadOptions): AsyncIOResult<ReadFileContent>;\n\n/**\n * 读取文件内容，可选地指定编码和返回类型。\n * @template T - 返回内容的类型。\n * @param filePath - 文件路径。\n * @param options - 可选的读取选项。\n * @returns 包含文件内容的异步结果。\n */\nexport async function readFile(filePath: string, options?: ReadOptions): AsyncIOResult<ReadFileContent> {\n    const filePathRes = validateReadablePath(filePath);\n    if (filePathRes.isErr()) return filePathRes.asErr();\n    filePath = filePathRes.unwrap();\n\n    const encoding = getReadFileEncoding(options);\n    const readFileRes = await asyncResultify(getFs().readFile)({\n        filePath,\n        encoding,\n    });\n\n    return readFileRes\n        .map(x => {\n            const { data } = x;\n            // 小游戏返回的是 ArrayBuffer，需要转换为 Uint8Array\n            return typeof data === 'string' ? data : new Uint8Array(data);\n        })\n        .orElse(fileErrorToResult);\n}\n\n/**\n * 删除指定路径的文件或目录。\n * @param path - 需要删除的文件或目录的路径。\n * @returns 删除操作的异步结果。\n */\nexport async function remove(path: string): AsyncVoidIOResult {\n    const statRes = await stat(path);\n    if (statRes.isErr()) {\n        // 不存在当做成功\n        return isNotFoundError(statRes.unwrapErr()) ? RESULT_VOID : statRes.asErr();\n    }\n\n    // stat 已经校验通过了\n    path = validateAbsolutePath(path).unwrap();\n\n    // 文件夹还是文件\n    const removeRes = await (statRes.unwrap().isDirectory()\n        ? asyncResultify(getFs().rmdir)({\n            dirPath: path,\n            recursive: true,\n        })\n        : asyncResultify(getFs().unlink)({\n            filePath: path,\n        }));\n\n    return removeRes\n        .and(RESULT_VOID)\n        .orElse(fileErrorToRemoveResult);\n}\n\n/**\n * 获取文件或目录的状态信息。\n * @param path - 文件或目录的路径。\n * @param options - 可选选项。\n * @returns 包含状态信息的异步结果。\n */\nexport function stat(path: string, options?: StatOptions & {\n    recursive: false;\n}): AsyncIOResult<WechatMinigame.Stats>;\nexport function stat(path: string, options: StatOptions & {\n    recursive: true;\n}): AsyncIOResult<WechatMinigame.FileStats[]>;\nexport function stat(path: string, options?: StatOptions): AsyncIOResult<WechatMinigame.Stats | WechatMinigame.FileStats[]>;\nexport async function stat(path: string, options?: StatOptions): AsyncIOResult<WechatMinigame.Stats | WechatMinigame.FileStats[]> {\n    const pathRes = validateReadablePath(path);\n    if (pathRes.isErr()) return pathRes.asErr();\n    path = pathRes.unwrap();\n\n    const { recursive = false } = options ?? {};\n    const statRes = await asyncResultify(getFs().stat)({\n        path,\n        recursive,\n    });\n\n    return statRes\n        .map(x => normalizeStats(x.stats, recursive))\n        .orElse(fileErrorToResult);\n}\n\n/**\n * 将内容写入文件。\n * @param filePath - 文件路径。\n * @param contents - 要写入的内容。\n * @param options - 可选的写入选项。\n * @returns 写入操作的异步结果。\n */\nexport async function writeFile(filePath: string, contents: WriteFileContent, options?: WriteOptions): AsyncVoidIOResult {\n    // 默认创建\n    const { append = false, create = true } = options ?? {};\n\n    const fs = getFs();\n    let writeMethod: typeof fs.appendFile | typeof fs.writeFile = fs.writeFile;\n\n    if (append) {\n        // append 先判断文件是否存在\n        const existsRes = await exists(filePath);\n        if (existsRes.isErr()) return existsRes.asErr();\n\n        if (existsRes.unwrap()) {\n            // 文件存在才使用 appendFile\n            writeMethod = fs.appendFile;\n        } else {\n            // 文件不存在，根据 create 参数决定\n            if (!create) {\n                return createFileNotExistsError(filePath);\n            }\n            // create=true 时使用 writeFile 创建文件\n            writeMethod = fs.writeFile;\n        }\n    }\n\n    // 减少可能的重复校验\n    const filePathRes = validateAbsolutePath(filePath);\n    if (filePathRes.isErr()) return filePathRes.asErr();\n    filePath = filePathRes.unwrap();\n\n    // 使用 writeFile 时（文件不存在或非 append 模式）需要创建目录\n    if (create && writeMethod === fs.writeFile) {\n        const mkdirRes = await mkdir(dirname(filePath));\n        if (mkdirRes.isErr()) return mkdirRes;\n    }\n\n    const contentsRes = getWriteFileContents(contents);\n    if (contentsRes.isErr()) return contentsRes.asErr();\n    const { data, encoding } = contentsRes.unwrap();\n\n    const writeRes = await asyncResultify(writeMethod)({\n        filePath,\n        data,\n        encoding,\n    });\n\n    return writeRes\n        .and(RESULT_VOID)\n        .orElse(fileErrorToResult);\n}\n\n/**\n * 向文件追加内容。\n * @param filePath - 文件路径。\n * @param contents - 要追加的内容。\n * @param options - 可选的追加选项。\n * @returns 追加操作的异步结果。\n */\nexport function appendFile(filePath: string, contents: WriteFileContent, options?: AppendOptions): AsyncVoidIOResult {\n    return writeFile(filePath, contents, {\n        append: true,\n        create: options?.create ?? true,\n    });\n}\n\n/**\n * 复制文件或文件夹。\n *\n * @param srcPath - 源文件或文件夹路径。\n * @param destPath - 目标文件或文件夹路径。\n * @returns 操作的异步结果。\n */\nexport async function copy(srcPath: string, destPath: string): AsyncVoidIOResult {\n    const destPathRes = validateAbsolutePath(destPath);\n    if (destPathRes.isErr()) return destPathRes.asErr();\n    destPath = destPathRes.unwrap();\n\n    const statRes = await stat(srcPath, {\n        recursive: true,\n    });\n    if (statRes.isErr()) return statRes.asErr();\n\n    // stat 已经校验通过了\n    srcPath = validateAbsolutePath(srcPath).unwrap();\n\n    for (const { path, stats } of statRes.unwrap()) {\n        let copyRes: VoidIOResult;\n\n        if (!path) {\n            // 根目录或者文件\n            if (stats.isDirectory()) {\n                copyRes = await mkdir(destPath);\n            } else {\n                const mkdirRes = await mkdir(dirname(destPath));\n                copyRes = await mkdirRes.andThenAsync(() => {\n                    return copyFile(srcPath, destPath);\n                });\n            }\n        } else {\n            // 不能用join\n            const srcEntryPath = srcPath + SEPARATOR + path;\n            const destEntryPath = destPath + SEPARATOR + path;\n\n            copyRes = await (stats.isDirectory()\n                ? mkdir(destEntryPath)\n                // 由于串行执行, 文件的父目录一定先于文件创建, 所以不需要额外 mkdir\n                : copyFile(srcEntryPath, destEntryPath));\n        }\n\n        if (copyRes.isErr()) return copyRes;\n    }\n\n    return RESULT_VOID;\n}\n\n/**\n * 检查指定路径的文件或目录是否存在。\n * @param path - 文件或目录的路径。\n * @param options - 可选的检查选项。\n * @returns 检查存在性的异步结果，存在时返回 true。\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 { isDirectory = false, isFile = false } = options ?? {};\n\n    // 不需要区分类型时，使用 access 比 stat 更轻量（不构造 Stats 对象）\n    if (!isDirectory && !isFile) {\n        return accessExists(path);\n    }\n\n    const statRes = await stat(path);\n    return getExistsResult(statRes, options);\n}\n\n/**\n * 清空目录中的所有文件和子目录。\n * @param dirPath - 目录路径。\n * @returns 清空操作的异步结果。\n */\nexport async function emptyDir(dirPath: string): AsyncVoidIOResult {\n    const readDirRes = await readDir(dirPath);\n    if (readDirRes.isErr()) {\n        // 不存在则创建\n        return isNotFoundError(readDirRes.unwrapErr())\n            ? mkdir(dirPath)\n            : readDirRes.asErr();\n    }\n\n    // readDir 已经校验通过了\n    dirPath = validateAbsolutePath(dirPath).unwrap();\n\n    const tasks = readDirRes.unwrap().map(name => remove(dirPath + SEPARATOR + name));\n    const taskResults = await Promise.all(tasks);\n    // 是否有失败？\n    const failed = taskResults.find(x => x.isErr());\n\n    return failed ?? RESULT_VOID;\n}\n\n/**\n * 读取文本文件的内容。\n * @param filePath - 文件路径。\n * @returns 包含文件文本内容的异步结果。\n */\nexport function readTextFile(filePath: string): AsyncIOResult<string> {\n    return readFile(filePath, {\n        encoding: 'utf8',\n    });\n}\n\n/**\n * 读取文件并解析为 JSON。\n * @param filePath - 文件路径。\n * @returns 读取结果。\n */\nexport async function readJsonFile<T>(filePath: string): AsyncIOResult<T> {\n    const readFileRes = await readTextFile(filePath);\n\n    return readFileRes.andThen(contents => {\n        return tryResult(JSON.parse, contents);\n    });\n}\n\n/**\n * 将数据序列化为 JSON 并写入文件。\n * @param filePath - 文件路径。\n * @param data - 要写入的数据。\n * @returns 写入结果。\n */\nexport async function writeJsonFile<T>(filePath: string, data: T): AsyncVoidIOResult {\n    const result = tryResult(JSON.stringify, data);\n\n    return result.andThenAsync(text => writeFile(filePath, text));\n}\n\n/**\n * 下载文件并保存到临时文件。\n * @param fileUrl - 文件的网络 URL。\n * @param options - 可选参数。\n * @returns 下载操作的异步结果。\n */\nexport function downloadFile(fileUrl: string, options?: DownloadFileOptions): FetchTask<WechatMinigame.DownloadFileSuccessCallbackResult>;\n/**\n * 下载文件。\n * @param fileUrl - 文件的网络 URL。\n * @param filePath - 可选的下载后文件存储的路径，没传则存到临时文件。\n * @param options - 可选参数。\n * @returns 下载操作的异步结果。\n */\nexport function downloadFile(fileUrl: string, filePath: string, options?: DownloadFileOptions): FetchTask<WechatMinigame.DownloadFileSuccessCallbackResult>;\nexport function downloadFile(fileUrl: string, filePath?: string | DownloadFileOptions, options?: DownloadFileOptions): FetchTask<WechatMinigame.DownloadFileSuccessCallbackResult> {\n    type T = WechatMinigame.DownloadFileSuccessCallbackResult;\n\n    const fileUrlRes = validateSafeUrl(fileUrl);\n    if (fileUrlRes.isErr()) return createFailedFetchTask(fileUrlRes);\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        options = filePath;\n        filePath = undefined;\n    }\n\n    const {\n        onProgress,\n        headers,\n        ...rest\n    } = options ?? {};\n\n    let aborted = false;\n\n    const future = new Future<IOResult<T>>();\n\n    let task: WechatMinigame.DownloadTask;\n\n    const download = () => {\n        task = wx.downloadFile({\n            ...rest,\n            url: fileUrl,\n            filePath: filePath as string,\n            header: headers,\n            async success(response): Promise<void> {\n                if (aborted) {\n                    future.resolve(Err(createAbortError()));\n                    return;\n                }\n\n                const { statusCode } = response;\n\n                if (statusCode >= 200 && statusCode < 300) {\n                    future.resolve(Ok(response));\n                    return;\n                }\n\n                // 删除不符合预期的文件，但无需主动删除临时文件\n                if (response.filePath) {\n                    await remove(response.filePath);\n                }\n\n                future.resolve(Err(new FetchError(response.errMsg, statusCode)));\n            },\n            fail(err): void {\n                future.resolve(aborted ? Err(createAbortError()) : miniGameFailureToResult(err));\n            },\n        });\n\n        if (typeof onProgress === 'function') {\n            task.onProgressUpdate(progress => {\n                const { totalBytesExpectedToWrite, totalBytesWritten } = progress;\n                onProgress(typeof totalBytesExpectedToWrite === 'number' && typeof totalBytesWritten === 'number' ? Ok({\n                    totalByteLength: totalBytesExpectedToWrite,\n                    completedByteLength: totalBytesWritten,\n                }) : Err(new Error(`Unknown download progress ${totalBytesWritten}/${totalBytesExpectedToWrite}`)));\n            });\n        }\n    };\n\n    if (typeof filePath === 'string') {\n        // 如果目录不存在则创建\n        mkdir(dirname(filePath)).then(mkdirRes => {\n            if (aborted) {\n                future.resolve(Err(createAbortError()));\n                return;\n            }\n\n            if (mkdirRes.isErr()) {\n                future.resolve(mkdirRes.asErr());\n                return;\n            }\n\n            download();\n        });\n    } else {\n        // 可能下载到临时文件\n        download();\n    }\n\n    return {\n        abort(): void {\n            aborted = true;\n            task?.abort();\n        },\n\n        get aborted(): boolean {\n            return aborted;\n        },\n\n        get result(): FetchResult<T> {\n            return future.promise;\n        },\n    };\n}\n\n/**\n * 文件上传。\n * @param filePath - 需要上传的文件路径。\n * @param fileUrl - 目标网络 URL。\n * @param options - 可选参数。\n * @returns 上传操作的异步结果。\n */\nexport function uploadFile(filePath: string, fileUrl: string, options?: UploadFileOptions): FetchTask<WechatMinigame.UploadFileSuccessCallbackResult> {\n    type T = WechatMinigame.UploadFileSuccessCallbackResult;\n\n    const fileUrlRes = validateSafeUrl(fileUrl);\n    if (fileUrlRes.isErr()) return createFailedFetchTask(fileUrlRes);\n\n    const filePathRes = validateAbsolutePath(filePath);\n    if (filePathRes.isErr()) return createFailedFetchTask(filePathRes);\n    filePath = filePathRes.unwrap();\n\n    const { headers, ...rest } = options ?? {};\n\n    let aborted = false;\n\n    const future = new Future<IOResult<T>>();\n\n    const task = wx.uploadFile({\n        name: basename(filePath),\n        ...rest,\n        url: fileUrl,\n        filePath,\n        header: headers,\n        success(res): void {\n            future.resolve(Ok(res));\n        },\n        fail(err): void {\n            future.resolve(miniGameFailureToResult(err));\n        },\n    });\n\n    return {\n        abort(): void {\n            aborted = true;\n            task?.abort();\n        },\n\n        get aborted(): boolean {\n            return aborted;\n        },\n\n        get result(): FetchResult<T> {\n            return future.promise;\n        },\n    };\n}\n\n/**\n * 解压 zip 文件。\n * @param zipFilePath - 要解压的 zip 文件路径。\n * @param destDir - 要解压到的目标文件夹路径。\n * @returns 解压操作的异步结果。\n */\nexport async function unzip(zipFilePath: string, destDir: string): AsyncVoidIOResult {\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    const unzipRes = await asyncResultify(getFs().unzip)({\n        zipFilePath,\n        targetPath: destDir,\n    });\n\n    return unzipRes\n        .and(RESULT_VOID)\n        .orElse(fileErrorToResult);\n}\n\n/**\n * 从网络下载 zip 文件并解压。\n * @param zipFileUrl - Zip 文件的网络地址。\n * @param destDir - 要解压到的目标文件夹路径。\n * @param options - 可选的下载参数。\n * @returns 下载并解压操作的异步结果。\n */\nexport async function unzipFromUrl(zipFileUrl: string, destDir: string, options?: DownloadFileOptions): AsyncVoidIOResult {\n    const destDirRes = validateAbsolutePath(destDir);\n    if (destDirRes.isErr()) return destDirRes.asErr();\n    destDir = destDirRes.unwrap();\n\n    const downloadRes = await downloadFile(zipFileUrl, options).result;\n\n    return downloadRes.andThenAsync(({ tempFilePath }) => {\n        return unzip(tempFilePath, destDir);\n    });\n}\n\n/**\n * 压缩文件到内存。\n * @param sourcePath - 需要压缩的文件（夹）路径。\n * @param options - 可选的压缩参数。\n * @returns 压缩成功的异步结果。\n */\nexport async function zip(sourcePath: string, options?: ZipOptions): AsyncIOResult<Uint8Array<ArrayBuffer>>;\n/**\n * 压缩文件。\n * @param sourcePath - 需要压缩的文件（夹）路径。\n * @param zipFilePath - 压缩后的 zip 文件路径。\n * @param options - 可选的压缩参数。\n * @returns 压缩成功的异步结果。\n */\nexport async function zip(sourcePath: string, zipFilePath: string, options?: ZipOptions): AsyncVoidIOResult;\nexport async function zip(sourcePath: string, zipFilePath?: string | ZipOptions, options?: ZipOptions): AsyncZipIOResult {\n    if (typeof zipFilePath === 'string') {\n        const zipFilePathRes = validateAbsolutePath(zipFilePath);\n        if (zipFilePathRes.isErr()) return zipFilePathRes.asErr();\n        zipFilePath = zipFilePathRes.unwrap();\n    } else {\n        options = zipFilePath;\n        zipFilePath = undefined;\n    }\n\n    const statRes = await stat(sourcePath, {\n        recursive: true,\n    });\n    if (statRes.isErr()) return statRes.asErr();\n    const statsArray = statRes.unwrap();\n\n    // stat 已经校验通过了\n    sourcePath = validateAbsolutePath(sourcePath).unwrap();\n    const sourceName = basename(sourcePath);\n\n    const zippable: AsyncZippable = {};\n\n    if (statsArray.length === 1 && statsArray[0].stats.isFile()) {\n        // sourcePath 是文件\n        const readFileRes = await readFile(sourcePath);\n        if (readFileRes.isErr()) return readFileRes;\n\n        zippable[sourceName] = readFileRes.unwrap();\n    } else {\n        // sourcePath 是目录\n        // 默认保留根目录\n        const preserveRoot = options?.preserveRoot ?? true;\n        if (preserveRoot) {\n            // 添加根目录条目\n            zippable[sourceName + SEPARATOR] = EMPTY_BYTES;\n        }\n\n        const tasks: AsyncIOResult<{\n            entryName: string;\n            data: Uint8Array<ArrayBuffer>;\n        }>[] = [];\n\n        for (const { path, stats } of statRes.unwrap()) {\n            // 这里就跳过根目录了\n            if (!path) continue;\n\n            const entryName = preserveRoot ? sourceName + SEPARATOR + path : path;\n\n            if (stats.isFile()) {\n                // 不能用 join，否则 http://usr 会变成 http:/usr\n                tasks.push((async () => {\n                    const readFileRes = await readFile(sourcePath + SEPARATOR + path);\n                    return readFileRes.map(data => ({\n                        entryName,\n                        data,\n                    }));\n                })());\n            } else {\n                // 文件夹 - 添加带有尾部斜杠和空内容的条目\n                zippable[entryName + SEPARATOR] = EMPTY_BYTES;\n            }\n        }\n\n        if (tasks.length > 0) {\n            const results = await Promise.all(tasks);\n            for (const result of results) {\n                if (result.isErr()) return result.asErr();\n\n                const { entryName, data } = result.unwrap();\n                zippable[entryName] = data;\n            }\n        }\n    }\n\n    // Nothing to zip - 和标准 zip 命令的行为一致\n    if (Object.keys(zippable).length === 0) {\n        return createNothingToZipError();\n    }\n\n    return zipTo(zippable, zipFilePath);\n}\n\n/**\n * 下载文件并压缩到内存。\n * @param sourceUrl - 要下载的文件 URL。\n * @param options - 下载选项。\n */\nexport async function zipFromUrl(sourceUrl: string, options?: DownloadFileOptions): AsyncIOResult<Uint8Array<ArrayBuffer>>;\n/**\n * 下载文件并压缩为 zip 文件。\n * @param sourceUrl - 要下载的文件 URL。\n * @param zipFilePath - 要输出的 zip 文件路径。\n * @param options - 下载选项。\n */\nexport async function zipFromUrl(sourceUrl: string, zipFilePath: string, options?: DownloadFileOptions): AsyncVoidIOResult;\nexport async function zipFromUrl(sourceUrl: string, zipFilePath?: string | DownloadFileOptions, options?: DownloadFileOptions): AsyncZipIOResult {\n    if (typeof zipFilePath === 'string') {\n        const zipFilePathRes = validateAbsolutePath(zipFilePath);\n        if (zipFilePathRes.isErr()) return zipFilePathRes.asErr();\n        zipFilePath = zipFilePathRes.unwrap();\n    } else {\n        options = zipFilePath;\n        zipFilePath = undefined;\n    }\n\n    const downloadRes = await downloadFile(sourceUrl, options).result;\n\n    return downloadRes.andThenAsync(async ({ tempFilePath }) => {\n        const readFileRes = await readFile(tempFilePath);\n        if (readFileRes.isErr()) return readFileRes;\n\n        const sourceName = basename(tempFilePath);\n        const zippable = {\n            [sourceName]: readFileRes.unwrap(),\n        };\n\n        return zipTo(zippable, zipFilePath);\n    });\n}\n\n// #region Internal Types\n\n/**\n * 异步的 zip 操作的结果。\n */\ntype AsyncZipIOResult = Promise<ZipIOResult>;\n\n// #endregion\n\n// #region Internal Functions\n\n/**\n * 将错误对象转换为 IOResult 类型。\n */\nfunction miniGameFailureToResult<T>(error: WechatMinigame.GeneralCallbackResult): IOResult<T> {\n    return Err(miniGameFailureToError(error));\n}\n\n/**\n * 创建一个 `AbortError` 错误。\n */\nfunction createAbortError(): Error {\n    const error = new Error();\n    error.name = ABORT_ERROR;\n\n    return error;\n}\n\n/**\n * 复制文件。\n */\nasync function copyFile(srcPath: string, destPath: string): AsyncVoidIOResult {\n    const copyRes = await asyncResultify(getFs().copyFile)({\n        srcPath,\n        destPath,\n    });\n\n    return copyRes\n        .and(RESULT_VOID)\n        .orElse(fileErrorToResult);\n}\n\n/**\n * 将 zippable 对象压缩为 zip 文件。\n */\nfunction zipTo(zippable: AsyncZippable, zipFilePath?: string): AsyncZipIOResult {\n    // 小游戏不支持 Web Worker(fflate 异步接口内部使用了), 退化到同步接口\n    return tryResult(() => compressSync(zippable))\n        .andThenAsync(bytesLike => {\n            const bytes = bytesLike as Uint8Array<ArrayBuffer>;\n            // 有文件路径则写入文件\n            return zipFilePath\n                ? writeFile(zipFilePath, bytes)\n                : Promise.resolve(Ok(bytes)) as AsyncZipIOResult;\n        });\n}\n\n// #endregion\n","/**\n * @internal\n * 文件系统辅助函数。\n */\n\nimport { isFileHandle, isFileHandleLike, readDir, readDirSync, stat, statSync, type FileSystemHandleLike } from 'happy-opfs';\nimport { Ok, tryAsyncResult, type AsyncIOResult, type IOResult } from 'happy-rusty';\nimport type { StatOptions } from './fs_define.ts';\n\n/**\n * 将 `FileSystemHandleLike` 转换为小游戏 `Stats`。\n * @param handleLike - 要转换的 `FileSystemHandleLike` 对象。\n * @returns 小游戏的 `Stats` 对象。\n */\nexport function convertFileSystemHandleLikeToStats(handleLike: FileSystemHandleLike): WechatMinigame.Stats {\n    const isFile = isFileHandleLike(handleLike);\n\n    return {\n        isFile: (): boolean => isFile,\n        isDirectory: (): boolean => !isFile,\n        size: isFile ? handleLike.size : 0,\n        lastModifiedTime: isFile ? handleLike.lastModified : 0,\n        lastAccessedTime: 0,\n        mode: 0,\n    };\n}\n\n/**\n * 将 `FileSystemHandle` 转换为小游戏 `Stats`。\n * @param handle - 要转换的 `FileSystemHandle` 对象。\n * @returns 小游戏的 `Stats` 对象。\n */\nexport async function convertFileSystemHandleToStats(handle: FileSystemHandle): Promise<WechatMinigame.Stats> {\n    const isFile = isFileHandle(handle);\n    let size = 0;\n    let lastModified = 0;\n\n    if (isFile) {\n        const file = await handle.getFile();\n        ({ size, lastModified } = file);\n    }\n\n    return {\n        isFile: (): boolean => isFile,\n        isDirectory: (): boolean => !isFile,\n        size,\n        lastModifiedTime: lastModified,\n        lastAccessedTime: 0,\n        mode: 0,\n    };\n}\n\n/**\n * 将 Web 端的读取目录结果转换为小游戏端的读取目录结果。\n * @param dirPath - 要读取的目录路径。\n * @returns 目录内容路径数组。\n */\nexport async function webToMinaReadDir(dirPath: string): AsyncIOResult<string[]> {\n    // 小游戏不支持 recursive 选项\n    const readDirRes = await readDir(dirPath);\n    return readDirRes.andTryAsync(async entries => {\n        if (typeof Array.fromAsync === 'function') {\n            return Array.fromAsync(entries, ({ path }) => path);\n        }\n\n        const items: string[] = [];\n        for await (const { path } of entries) {\n            items.push(path);\n        }\n        return items;\n    });\n}\n\n/**\n * 将 Web 端的 stat 结果转换为小游戏端的 stat 结果。\n * @param path - 要获取状态的路径。\n * @param options - 可选的 stat 选项。\n * @returns 文件或目录的状态信息。\n */\nexport async function webToMinaStat(path: string, options?: StatOptions): AsyncIOResult<WechatMinigame.Stats | WechatMinigame.FileStats[]> {\n    const statRes = await stat(path);\n    if (statRes.isErr()) return statRes.asErr();\n\n    const handle = statRes.unwrap();\n\n    const entryStatsRes = await tryAsyncResult(convertFileSystemHandleToStats(handle));\n    if (entryStatsRes.isErr()) return entryStatsRes;\n\n    // 非递归模式直接返回\n    if (!options?.recursive) {\n        return entryStatsRes;\n    }\n\n    const entryStats = entryStatsRes.unwrap();\n    if (entryStats.isFile()) {\n        return Ok([{\n            path: '', // 当前文件本身的相对路径\n            stats: entryStats,\n        }]);\n    }\n\n    // 递归读取目录\n    const readDirRes = await readDir(path);\n    return readDirRes.andTryAsync(async entries => {\n        // 只要是 recursive 模式下的目录, 就返回数组(即使空目录)\n        const tasks = [Promise.resolve({\n            path: '', // 当前文件夹本身的相对路径\n            stats: entryStats,\n        })];\n\n        for await (const { path, handle } of entries) {\n            tasks.push((async () => {\n                const stats = await convertFileSystemHandleToStats(handle);\n                return {\n                    path,\n                    stats,\n                };\n            })());\n        }\n\n        return Promise.all(tasks);\n    });\n}\n\n/**\n * 将 Web 端的读取目录结果转换为小游戏端的读取目录结果。\n * @param dirPath - 要读取的目录路径。\n * @returns 目录内容路径数组。\n */\nexport function webToMinaReadDirSync(dirPath: string): IOResult<string[]> {\n    // 小游戏不支持 recursive 选项\n    const readDirRes = readDirSync(dirPath);\n    return readDirRes.map(entries => {\n        return entries.map(({ path }) => path);\n    });\n}\n\n/**\n * 将 Web 端的 stat 结果转换为小游戏端的 stat 结果。\n * @param path - 要获取状态的路径。\n * @param options - 可选的 stat 选项。\n * @returns 文件或目录的状态信息。\n */\nexport function webToMinaStatSync(path: string, options?: StatOptions): IOResult<WechatMinigame.Stats | WechatMinigame.FileStats[]> {\n    const statRes = statSync(path);\n    if (statRes.isErr()) return statRes.asErr();\n\n    const handleLike = statRes.unwrap();\n\n    const entryStats = convertFileSystemHandleLikeToStats(handleLike);\n\n    // 非递归模式直接返回\n    if (!options?.recursive) {\n        return Ok(entryStats);\n    }\n\n    if (entryStats.isFile()) {\n        return Ok([{\n            path: '', // 当前文件本身的相对路径\n            stats: entryStats,\n        }]);\n    }\n\n    // 递归读取目录\n    const readDirRes = readDirSync(path);\n    return readDirRes.map(entries => {\n        const statsArr = entries.map(({ path, handle }) => ({\n            path,\n            stats: convertFileSystemHandleLikeToStats(handle),\n        }));\n\n        // 只要是 recursive 模式下的目录, 就返回数组(即使是空目录)\n        statsArr.unshift({\n            path: '', // 当前文件夹本身的相对路径\n            stats: entryStats,\n        });\n\n        return statsArr;\n    });\n}\n","import type { FetchTask } from '@happy-ts/fetch-t';\nimport {\n    appendFile as webAppendFile,\n    copy as webCopy,\n    downloadFile as webDownloadFile,\n    emptyDir as webEmptyDir,\n    exists as webExists,\n    mkdir as webMkdir,\n    move as webMove,\n    readFile as webReadFile,\n    readJsonFile as webReadJsonFile,\n    readTextFile as webReadTextFile,\n    remove as webRemove,\n    unzip as webUnzip,\n    unzipFromUrl as webUnzipFromUrl,\n    uploadFile as webUploadFile,\n    writeFile as webWriteFile,\n    writeJsonFile as webWriteJsonFile,\n    zip as webZip,\n    zipFromUrl as webZipFromUrl,\n    type AppendOptions,\n    type DownloadFileTempResponse,\n    type ExistsOptions,\n    type WriteOptions,\n    type ZipOptions,\n} from 'happy-opfs';\nimport { type AsyncIOResult, type AsyncVoidIOResult } from 'happy-rusty';\nimport { IS_MINA } from '../../macros/env.ts';\nimport type { ReadFileContent, ReadOptions, StatOptions, UnionDownloadFileOptions, UnionUploadFileOptions, WriteFileContent, ZipFromUrlOptions } from './fs_define.ts';\nimport {\n    appendFile as minaAppendFile,\n    copy as minaCopy,\n    downloadFile as minaDownloadFile,\n    emptyDir as minaEmptyDir,\n    exists as minaExists,\n    mkdir as minaMkdir,\n    move as minaMove,\n    readDir as minaReadDir,\n    readFile as minaReadFile,\n    readJsonFile as minaReadJsonFile,\n    readTextFile as minaReadTextFile,\n    remove as minaRemove,\n    stat as minaStat,\n    unzip as minaUnzip,\n    unzipFromUrl as minaUnzipFromUrl,\n    uploadFile as minaUploadFile,\n    writeFile as minaWriteFile,\n    writeJsonFile as minaWriteJsonFile,\n    zip as minaZip,\n    zipFromUrl as minaZipFromUrl,\n} from './mina_fs_async.ts';\nimport { webToMinaReadDir, webToMinaStat } from './web_fs_helpers.ts';\n\n/**\n * 递归创建文件夹，相当于 `mkdir -p`。\n * @param dirPath - 将要创建的目录的路径。\n * @returns 创建成功返回的异步操作结果。\n * @since 1.0.0\n * @example\n * ```ts\n * const result = await mkdir('/path/to/dir');\n * if (result.isOk()) {\n *     console.log('目录创建成功');\n * }\n * ```\n */\nexport function mkdir(dirPath: string): AsyncVoidIOResult {\n    return (IS_MINA ? minaMkdir : webMkdir)(dirPath);\n}\n\n/**\n * 移动或重命名文件或目录。\n * @param srcPath - 原始路径。\n * @param destPath - 新路径。\n * @returns 操作成功返回的异步操作结果。\n * @since 1.0.0\n * @example\n * ```ts\n * const result = await move('/old/path', '/new/path');\n * if (result.isOk()) {\n *     console.log('移动成功');\n * }\n * ```\n */\nexport function move(srcPath: string, destPath: string): AsyncVoidIOResult {\n    return (IS_MINA ? minaMove : webMove)(srcPath, destPath);\n}\n\n/**\n * 异步读取指定目录下的所有文件和子目录。\n * @param dirPath - 需要读取的目录路径。\n * @returns 包含目录内容的字符串数组的异步操作结果。\n * @since 1.0.0\n * @example\n * ```ts\n * const result = await readDir('/path/to/dir');\n * if (result.isOk()) {\n *     console.log(result.unwrap()); // ['file1.txt', 'file2.txt', 'subdir']\n * }\n * ```\n */\nexport async function readDir(dirPath: string): AsyncIOResult<string[]> {\n    return (IS_MINA ? minaReadDir : webToMinaReadDir)(dirPath);\n}\n\n/**\n * 以 UTF-8 格式读取文件。\n * @param filePath - 文件路径。\n * @param options - 读取选项，指定编码为 'utf8'。\n * @returns 包含文件内容的字符串的异步操作结果。\n * @since 1.0.0\n * @example\n * ```ts\n * const result = await readFile('/path/to/file.txt', { encoding: 'utf8' });\n * if (result.isOk()) {\n *     console.log(result.unwrap());\n * }\n * ```\n */\nexport function readFile(filePath: string, options: ReadOptions & {\n    encoding: 'utf8';\n}): AsyncIOResult<string>;\n\n/**\n * 以二进制格式读取文件。\n * @param filePath - 文件路径。\n * @param options - 读取选项，指定编码为 'bytes'。\n * @returns 包含文件内容的 Uint8Array<ArrayBuffer> 的异步操作结果。\n * @since 1.0.0\n * @example\n * ```ts\n * const result = await readFile('/path/to/file.txt', { encoding: 'bytes' });\n * if (result.isOk()) {\n *     const bytes = result.unwrap();\n *     console.log(decodeUtf8(bytes));\n * }\n * ```\n */\nexport function readFile(filePath: string, options?: ReadOptions & {\n    encoding: 'bytes';\n}): AsyncIOResult<Uint8Array<ArrayBuffer>>;\n\n/**\n * 读取文件内容。\n * @param filePath - 文件的路径。\n * @param options - 可选的读取选项。\n * @returns 包含文件内容的异步操作结果。\n * @since 1.0.0\n * @example\n * ```ts\n * const result = await readFile('/path/to/file.txt');\n * if (result.isOk()) {\n *     const bytes = result.unwrap();\n *     console.log(decodeUtf8(bytes));\n * }\n * ```\n */\nexport function readFile(filePath: string, options?: ReadOptions): AsyncIOResult<ReadFileContent>;\n/**\n * 读取文件内容，可选地指定编码和返回类型。\n * @template T - 返回内容的类型。\n * @param filePath - 文件路径。\n * @param options - 可选的读取选项。\n * @returns 包含文件内容的异步操作结果。\n */\nexport function readFile(filePath: string, options?: ReadOptions): AsyncIOResult<ReadFileContent> {\n    return IS_MINA\n        ? minaReadFile(filePath, options)\n        : webReadFile(filePath, options) as AsyncIOResult<ReadFileContent>;\n}\n\n/**\n * 删除文件或目录。\n * @param path - 要删除的文件或目录的路径。\n * @returns 删除成功返回的异步操作结果。\n * @since 1.0.0\n * @example\n * ```ts\n * const result = await remove('/path/to/file.txt');\n * if (result.isOk()) {\n *     console.log('删除成功');\n * }\n * ```\n */\nexport function remove(path: string): AsyncVoidIOResult {\n    return (IS_MINA ? minaRemove : webRemove)(path);\n}\n\n/**\n * 获取单个文件或目录的状态信息。\n * @param path - 文件或目录的路径。\n * @param options - 可选选项，recursive 设置为 false（默认）获取单个文件状态。\n * @returns 包含状态信息的异步操作结果。\n * @since 1.0.0\n * @example\n * ```ts\n * const result = await stat('/path/to/file.txt');\n * if (result.isOk()) {\n *     const stats = result.unwrap();\n *     console.log(stats.isFile()); // true\n * }\n * ```\n */\nexport function stat(path: string, options?: StatOptions & {\n    recursive: false;\n}): AsyncIOResult<WechatMinigame.Stats>;\n/**\n * 递归获取目录下所有文件和子目录的状态信息。\n * @param path - 目录的路径。\n * @param options - 选项，recursive 设置为 true 以递归获取。\n * @returns 包含所有文件状态信息数组的异步操作结果。\n * @since 1.0.0\n * @example\n * ```ts\n * const result = await stat('/path/to/dir', { recursive: true });\n * if (result.isOk()) {\n *     const fileStats = result.unwrap();\n *     fileStats.forEach(file => console.log(file.path));\n * }\n * ```\n */\nexport function stat(path: string, options: StatOptions & {\n    recursive: true;\n}): AsyncIOResult<WechatMinigame.FileStats[]>;\nexport function stat(path: string, options?: StatOptions): AsyncIOResult<WechatMinigame.Stats | WechatMinigame.FileStats[]>;\n/**\n * 获取文件或目录的状态信息。\n * @param path - 文件或目录的路径。\n * @param options - 可选选项，包含 recursive 可递归获取目录下所有文件状态。\n * @returns 包含状态信息的异步操作结果。\n * @since 1.0.0\n * @example\n * ```ts\n * const result = await stat('/path/to/file.txt');\n * if (result.isOk()) {\n *     const stats = result.unwrap();\n *     console.log(stats.isFile()); // true\n * }\n * ```\n */\nexport async function stat(path: string, options?: StatOptions): AsyncIOResult<WechatMinigame.Stats | WechatMinigame.FileStats[]> {\n    return (IS_MINA ? minaStat : webToMinaStat)(path, options);\n}\n\n/**\n * 写入文件，文件不存在则创建，同时创建对应目录。\n * @param filePath - 文件路径。\n * @param contents - 要写入的内容，支持 ArrayBuffer 和 string（需确保是 UTF-8 编码）。\n * @param options - 可选写入选项。\n * @returns 写入成功返回的异步操作结果。\n * @since 1.0.0\n * @example\n * ```ts\n * const result = await writeFile('/path/to/file.txt', 'Hello, World!');\n * if (result.isOk()) {\n *     console.log('写入成功');\n * }\n * ```\n */\nexport function writeFile(filePath: string, contents: WriteFileContent, options?: WriteOptions): AsyncVoidIOResult {\n    return (IS_MINA ? minaWriteFile : webWriteFile)(filePath, contents, options);\n}\n\n/**\n * 向文件追加内容。\n * @param filePath - 文件路径。\n * @param contents - 要追加的内容。\n * @param options - 可选的追加选项。\n * @returns 追加成功返回的异步操作结果。\n * @since 1.0.0\n * @example\n * ```ts\n * const result = await appendFile('/path/to/file.txt', '\\nNew content');\n * if (result.isOk()) {\n *     console.log('追加成功');\n * }\n * ```\n */\nexport function appendFile(filePath: string, contents: WriteFileContent, options?: AppendOptions): AsyncVoidIOResult {\n    return (IS_MINA ? minaAppendFile : webAppendFile)(filePath, contents, options);\n}\n\n/**\n * 复制文件或文件夹。\n * @param srcPath - 源文件或文件夹路径。\n * @param destPath - 目标文件或文件夹路径。\n * @returns 操作的异步结果。\n * @since 1.0.0\n * @example\n * ```ts\n * const result = await copy('/src/file.txt', '/dest/file.txt');\n * if (result.isOk()) {\n *     console.log('复制成功');\n * }\n * ```\n */\nexport function copy(srcPath: string, destPath: string): AsyncVoidIOResult {\n    return (IS_MINA ? minaCopy : webCopy)(srcPath, destPath);\n}\n\n/**\n * 检查指定路径的文件或目录是否存在。\n * @param path - 文件或目录的路径。\n * @param options - 可选的检查选项。\n * @returns 存在返回 true 的异步操作结果。\n * @since 1.0.0\n * @example\n * ```ts\n * const result = await exists('/path/to/file.txt');\n * if (result.isOk() && result.unwrap()) {\n *     console.log('文件存在');\n * }\n * ```\n */\nexport function exists(path: string, options?: ExistsOptions): AsyncIOResult<boolean> {\n    return (IS_MINA ? minaExists : webExists)(path, options);\n}\n\n/**\n * 清空指定目录下的所有文件和子目录。\n * @param dirPath - 目录路径。\n * @returns 清空成功返回的异步操作结果。\n * @since 1.0.1\n * @example\n * ```ts\n * const result = await emptyDir('/path/to/dir');\n * if (result.isOk()) {\n *     console.log('目录已清空');\n * }\n * ```\n */\nexport function emptyDir(dirPath: string): AsyncVoidIOResult {\n    return (IS_MINA ? minaEmptyDir : webEmptyDir)(dirPath);\n}\n\n/**\n * 读取 JSON 文件并解析为对象。\n * @typeParam T - JSON 解析后的类型。\n * @param filePath - 文件路径。\n * @returns 解析后的对象。\n * @since 1.6.0\n * @example\n * ```ts\n * const result = await readJsonFile<{ name: string }>('/path/to/config.json');\n * if (result.isOk()) {\n *     console.log(result.unwrap().name);\n * }\n * ```\n */\nexport function readJsonFile<T>(filePath: string): AsyncIOResult<T> {\n    return (IS_MINA ? minaReadJsonFile : webReadJsonFile)(filePath);\n}\n\n/**\n * 读取文本文件的内容。\n * @param filePath - 文件路径。\n * @returns 包含文件文本内容的异步操作结果。\n * @since 1.0.0\n * @example\n * ```ts\n * const result = await readTextFile('/path/to/file.txt');\n * if (result.isOk()) {\n *     console.log(result.unwrap());\n * }\n * ```\n */\nexport function readTextFile(filePath: string): AsyncIOResult<string> {\n    return (IS_MINA ? minaReadTextFile : webReadTextFile)(filePath);\n}\n\n/**\n * 将数据序列化为 JSON 并写入文件。\n * @typeParam T - 要写入数据的类型。\n * @param filePath - 文件路径。\n * @param data - 要写入的数据。\n * @returns 写入操作的异步结果。\n * @since 2.0.0\n * @example\n * ```ts\n * const result = await writeJsonFile('/path/to/config.json', { name: 'test' });\n * if (result.isOk()) {\n *     console.log('写入成功');\n * }\n * ```\n */\nexport function writeJsonFile<T>(filePath: string, data: T): AsyncVoidIOResult {\n    return (IS_MINA ? minaWriteJsonFile : webWriteJsonFile)(filePath, data);\n}\n\n/**\n * 下载文件并保存到临时文件。\n * @param fileUrl - 文件的网络 URL。\n * @param options - 可选的下载参数。\n * @returns 下载操作的 FetchTask，可用于取消或监听进度。\n * @since 1.0.0\n * @example\n * ```ts\n * const task = downloadFile('https://example.com/file.zip');\n * const result = await task.result;\n * if (result.isOk()) {\n *     console.log('下载完成:', result.unwrap().tempFilePath);\n * }\n * ```\n */\nexport function downloadFile(fileUrl: string, options?: UnionDownloadFileOptions): FetchTask<WechatMinigame.DownloadFileSuccessCallbackResult | DownloadFileTempResponse>;\n/**\n * 下载文件并保存到指定路径。\n * @param fileUrl - 文件的网络 URL。\n * @param filePath - 下载后文件存储的路径。\n * @param options - 可选的请求初始化参数。\n * @returns 下载操作的 FetchTask。\n * @since 1.0.0\n * @example\n * ```ts\n * const task = downloadFile('https://example.com/file.zip', '/path/to/save.zip');\n * const result = await task.result;\n * if (result.isOk()) {\n *     console.log('下载完成');\n * }\n * ```\n */\nexport function downloadFile(fileUrl: string, filePath: string, options?: UnionDownloadFileOptions): FetchTask<WechatMinigame.DownloadFileSuccessCallbackResult | Response>;\nexport function downloadFile(fileUrl: string, filePath?: string | UnionDownloadFileOptions, options?: UnionDownloadFileOptions): FetchTask<WechatMinigame.DownloadFileSuccessCallbackResult | DownloadFileTempResponse | Response> {\n    if (typeof filePath === 'string') {\n        return IS_MINA\n            ? minaDownloadFile(fileUrl, filePath, options)\n            : webDownloadFile(fileUrl, filePath, options);\n    } else {\n        return IS_MINA\n            ? minaDownloadFile(fileUrl, filePath)\n            : webDownloadFile(fileUrl, filePath);\n    }\n}\n\n/**\n * 上传本地文件到服务器。\n * @param filePath - 需要上传的文件路径。\n * @param fileUrl - 目标服务器的 URL。\n * @param options - 可选的请求初始化参数。\n * @returns 上传操作的 FetchTask。\n * @since 1.0.0\n * @example\n * ```ts\n * const task = uploadFile('/path/to/file.txt', 'https://example.com/upload');\n * const result = await task.result;\n * if (result.isOk()) {\n *     console.log('上传成功');\n * }\n * ```\n */\nexport function uploadFile(filePath: string, fileUrl: string, options?: UnionUploadFileOptions): FetchTask<WechatMinigame.UploadFileSuccessCallbackResult | Response> {\n    return IS_MINA\n        ? minaUploadFile(filePath, fileUrl, options)\n        : webUploadFile(filePath, fileUrl, options);\n}\n\n/**\n * 解压 zip 文件。\n * @param zipFilePath - 要解压的 zip 文件路径。\n * @param targetPath - 要解压到的目标文件夹路径。\n * @returns 解压操作的异步结果。\n * @since 1.3.0\n * @example\n * ```ts\n * const result = await unzip('/path/to/archive.zip', '/path/to/output');\n * if (result.isOk()) {\n *     console.log('解压成功');\n * }\n * ```\n */\nexport function unzip(zipFilePath: string, targetPath: string): AsyncVoidIOResult {\n    return (IS_MINA ? minaUnzip : webUnzip)(zipFilePath, targetPath);\n}\n\n/**\n * 从网络下载 zip 文件并解压。\n * @param zipFileUrl - Zip 文件的网络地址。\n * @param targetPath - 要解压到的目标文件夹路径。\n * @param options - 可选的下载参数。\n * @returns 下载并解压操作的异步结果。\n * @since 1.4.0\n * @example\n * ```ts\n * const result = await unzipFromUrl('https://example.com/archive.zip', '/path/to/output');\n * if (result.isOk()) {\n *     console.log('下载并解压成功');\n * }\n * ```\n */\nexport function unzipFromUrl(zipFileUrl: string, targetPath: string, options?: UnionDownloadFileOptions): AsyncVoidIOResult {\n    return (IS_MINA ? minaUnzipFromUrl : webUnzipFromUrl)(zipFileUrl, targetPath, options);\n}\n\n/**\n * 压缩文件或文件夹到内存。\n * @param sourcePath - 需要压缩的文件（夹）路径。\n * @param options - 可选的压缩参数。\n * @returns 压缩后的 Uint8Array。\n * @since 1.3.0\n * @example\n * ```ts\n * const result = await zip('/path/to/source');\n * if (result.isOk()) {\n *     console.log('压缩成功:', result.unwrap().length, 'bytes');\n * }\n * ```\n */\nexport function zip(sourcePath: string, options?: ZipOptions): AsyncIOResult<Uint8Array<ArrayBuffer>>;\n/**\n * 压缩文件或文件夹并保存到指定路径。\n * @param sourcePath - 需要压缩的文件（夹）路径。\n * @param zipFilePath - 压缩后的 zip 文件路径。\n * @param options - 可选的压缩参数。\n * @returns 压缩操作的异步结果。\n * @since 1.3.0\n * @example\n * ```ts\n * const result = await zip('/path/to/source', '/path/to/archive.zip');\n * if (result.isOk()) {\n *     console.log('压缩成功');\n * }\n * ```\n */\nexport function zip(sourcePath: string, zipFilePath: string, options?: ZipOptions): AsyncVoidIOResult;\nexport function zip(sourcePath: string, zipFilePath?: string | ZipOptions, options?: ZipOptions): AsyncIOResult<Uint8Array<ArrayBuffer> | void> {\n    if (typeof zipFilePath === 'string') {\n        return (IS_MINA ? minaZip : webZip)(sourcePath, zipFilePath, options);\n    } else {\n        return (IS_MINA ? minaZip : webZip)(sourcePath, zipFilePath);\n    }\n}\n\n/**\n * 下载文件并压缩到内存。\n * @param sourceUrl - 要下载的文件 URL。\n * @param options - 合并的下载和压缩选项。\n * @returns 压缩后的 Uint8Array。\n * @since 1.4.0\n * @example\n * ```ts\n * const result = await zipFromUrl('https://example.com/file.txt');\n * if (result.isOk()) {\n *     console.log('下载并压缩成功');\n * }\n * ```\n */\nexport function zipFromUrl(sourceUrl: string, options?: ZipFromUrlOptions): AsyncIOResult<Uint8Array<ArrayBuffer>>;\n/**\n * 下载文件并压缩为 zip 文件。\n * @param sourceUrl - 要下载的文件 URL。\n * @param zipFilePath - 要输出的 zip 文件路径。\n * @param options - 合并的下载和压缩选项。\n * @returns 操作的异步结果。\n * @since 1.4.0\n * @example\n * ```ts\n * const result = await zipFromUrl('https://example.com/file.txt', '/path/to/archive.zip');\n * if (result.isOk()) {\n *     console.log('下载并压缩成功');\n * }\n * ```\n */\nexport function zipFromUrl(sourceUrl: string, zipFilePath: string, options?: ZipFromUrlOptions): AsyncVoidIOResult;\nexport function zipFromUrl(sourceUrl: string, zipFilePath?: string | ZipFromUrlOptions, options?: ZipFromUrlOptions): AsyncIOResult<Uint8Array<ArrayBuffer> | void> {\n    if (typeof zipFilePath === 'string') {\n        return IS_MINA\n            ? minaZipFromUrl(sourceUrl, zipFilePath, options)\n            : webZipFromUrl(sourceUrl, zipFilePath, options);\n    } else {\n        return IS_MINA\n            ? minaZipFromUrl(sourceUrl, zipFilePath)\n            : webZipFromUrl(sourceUrl, zipFilePath);\n    }\n}\n","/**\n * @internal\n * 小游戏平台的同步文件系统操作实现。\n */\n\nimport { zipSync as compressSync, unzipSync as decompressSync, type AsyncZippable } from 'fflate/browser';\nimport { type AppendOptions, type ExistsOptions, type WriteOptions, type ZipOptions } from 'happy-opfs';\nimport { Ok, RESULT_VOID, tryResult, type IOResult, type VoidIOResult } from 'happy-rusty';\nimport { basename, dirname, SEPARATOR } from '../path/mod.ts';\nimport type { ReadFileContent, ReadOptions, StatOptions, WriteFileContent } from './fs_define.ts';\nimport { accessExistsSync, createDirIsFileError, createFileNotExistsError, createNothingToZipError, EMPTY_BYTES, fileErrorToMkdirResult, fileErrorToRemoveResult, fileErrorToResult, getExistsResult, getFs, getReadFileEncoding, getUsrPath, getWriteFileContents, isNotFoundError, normalizeStats, validateAbsolutePath, validateExistsOptions, validateReadablePath, type ZipIOResult } from './mina_fs_shared.ts';\n\n/**\n * `mkdir` 的同步版本。\n * @param dirPath - 要创建的目录路径。\n * @returns 操作结果。\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    // 根目录无需创建\n    if (dirPath === getUsrPath()) {\n        return RESULT_VOID;\n    }\n\n    const statRes = statSync(dirPath);\n    if (statRes.isOk()) {\n        // 已存在并且是文件\n        if (statRes.unwrap().isFile()) {\n            return createDirIsFileError(dirPath);\n        }\n\n        // 存在文件夹则不创建\n        return RESULT_VOID;\n    }\n\n    // 递归创建\n    return trySyncOp(() => getFs().mkdirSync(dirPath, true), fileErrorToMkdirResult);\n}\n\n/**\n * `move` 的同步版本。\n * @param srcPath - 源路径。\n * @param destPath - 目标路径。\n * @returns 操作结果。\n */\nexport function moveSync(srcPath: string, destPath: string): 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 trySyncOp(() => getFs().renameSync(srcPath, destPath));\n}\n\n/**\n * `readDir` 的同步版本。\n * @param dirPath - 要读取的目录路径。\n * @returns 目录中的文件和子目录名称数组。\n */\nexport function readDirSync(dirPath: string): IOResult<string[]> {\n    const dirPathRes = validateReadablePath(dirPath);\n    if (dirPathRes.isErr()) return dirPathRes.asErr();\n    dirPath = dirPathRes.unwrap();\n\n    return trySyncOp(() => getFs().readdirSync(dirPath));\n}\n\n/**\n * `readFile` 的同步版本。\n * @param filePath - 要读取的文件路径。\n * @param options - 读取选项。\n * @returns 文件内容。\n */\nexport function readFileSync(filePath: string, options: ReadOptions & {\n    encoding: 'utf8';\n}): IOResult<string>;\nexport function readFileSync(filePath: string, options?: ReadOptions & {\n    encoding: 'bytes';\n}): IOResult<Uint8Array<ArrayBuffer>>;\nexport function readFileSync(filePath: string, options?: ReadOptions): IOResult<ReadFileContent>;\nexport function readFileSync(filePath: string, options?: ReadOptions): IOResult<ReadFileContent> {\n    const filePathRes = validateReadablePath(filePath);\n    if (filePathRes.isErr()) return filePathRes.asErr();\n    filePath = filePathRes.unwrap();\n\n    const encoding = getReadFileEncoding(options);\n\n    return trySyncOp(() => {\n        const data = getFs().readFileSync(filePath, encoding);\n        // 小游戏返回的是 ArrayBuffer，需要转换为 Uint8Array\n        return typeof data === 'string' ? data : new Uint8Array(data);\n    });\n}\n\n/**\n * `remove` 的同步版本。\n * @param path - 要删除的文件或目录路径。\n * @returns 操作结果。\n */\nexport function removeSync(path: string): VoidIOResult {\n    const statRes = statSync(path);\n\n    if (statRes.isErr()) {\n        // 不存在当做成功\n        return isNotFoundError(statRes.unwrapErr()) ? RESULT_VOID : statRes.asErr();\n    }\n\n    // statSync 已经校验通过了\n    path = validateAbsolutePath(path).unwrap();\n\n    return trySyncOp(() => {\n        // 文件夹还是文件\n        if (statRes.unwrap().isDirectory()) {\n            getFs().rmdirSync(path, true);\n        } else {\n            getFs().unlinkSync(path);\n        }\n    }, fileErrorToRemoveResult);\n}\n\n/**\n * `stat` 的同步版本。\n * @param path - 文件或目录路径。\n * @param options - 统计选项。\n * @returns 文件或目录的统计信息。\n */\nexport function statSync(path: string, options?: StatOptions & {\n    recursive: false;\n}): IOResult<WechatMinigame.Stats>;\nexport function statSync(path: string, options: StatOptions & {\n    recursive: true;\n}): IOResult<WechatMinigame.FileStats[]>;\nexport function statSync(path: string, options?: StatOptions): IOResult<WechatMinigame.Stats | WechatMinigame.FileStats[]>;\nexport function statSync(path: string, options?: StatOptions): IOResult<WechatMinigame.Stats | WechatMinigame.FileStats[]> {\n    const pathRes = validateReadablePath(path);\n    if (pathRes.isErr()) return pathRes.asErr();\n    path = pathRes.unwrap();\n\n    const { recursive = false } = options ?? {};\n\n    return trySyncOp(() => getFs().statSync(path, recursive))\n        .map(x => normalizeStats(x, recursive));\n}\n\n/**\n * `writeFile` 的同步版本。\n * @param filePath - 要写入的文件路径。\n * @param contents - 要写入的内容。\n * @param options - 写入选项。\n * @returns 操作结果。\n */\nexport function writeFileSync(filePath: string, contents: WriteFileContent, options?: WriteOptions): VoidIOResult {\n    // 默认创建\n    const { append = false, create = true } = options ?? {};\n\n    const fs = getFs();\n    let writeMethod: typeof fs.appendFileSync | typeof fs.writeFileSync = fs.writeFileSync;\n\n    if (append) {\n        // append 模式，先检查文件是否存在\n        const existsRes = existsSync(filePath);\n        if (existsRes.isErr()) return existsRes.asErr();\n\n        if (existsRes.unwrap()) {\n            // 文件存在，使用 appendFileSync\n            writeMethod = fs.appendFileSync;\n        } else {\n            // 文件不存在，根据 create 参数决定\n            if (!create) {\n                return createFileNotExistsError(filePath);\n            }\n            // create=true 时使用 writeFileSync 创建文件\n            writeMethod = fs.writeFileSync;\n        }\n    }\n\n    // 减少可能的重复校验\n    const filePathRes = validateAbsolutePath(filePath);\n    if (filePathRes.isErr()) return filePathRes.asErr();\n    filePath = filePathRes.unwrap();\n\n    // 使用 writeFileSync 时（文件不存在或非 append 模式）需要创建目录\n    if (create && writeMethod === fs.writeFileSync) {\n        const result = mkdirSync(dirname(filePath));\n        if (result.isErr()) return result;\n    }\n\n    const contentsRes = getWriteFileContents(contents);\n    if (contentsRes.isErr()) return contentsRes.asErr();\n\n    const { data, encoding } = contentsRes.unwrap();\n\n    return trySyncOp(() => writeMethod(filePath, data, encoding));\n}\n\n/**\n * `appendFile` 的同步版本。\n * @param filePath - 文件路径。\n * @param contents - 要追加的内容。\n * @param options - 可选的追加选项。\n * @returns 操作结果。\n */\nexport function appendFileSync(filePath: string, contents: WriteFileContent, options?: AppendOptions): VoidIOResult {\n    return writeFileSync(filePath, contents, {\n        append: true,\n        create: options?.create ?? true,\n    });\n}\n\n/**\n * `copy` 的同步版本。\n * @param srcPath - 源路径。\n * @param destPath - 目标路径。\n * @returns 操作结果。\n */\nexport function copySync(srcPath: string, destPath: string): VoidIOResult {\n    const destPathRes = validateAbsolutePath(destPath);\n    if (destPathRes.isErr()) return destPathRes.asErr();\n    destPath = destPathRes.unwrap();\n\n    const statRes = statSync(srcPath, {\n        recursive: true,\n    });\n    if (statRes.isErr()) return statRes.asErr();\n\n    // statSync 已经校验通过了\n    srcPath = validateAbsolutePath(srcPath).unwrap();\n\n    for (const { path, stats } of statRes.unwrap()) {\n        let copyRes: VoidIOResult;\n\n        if (!path) {\n            // 根目录或者文件\n            if (stats.isDirectory()) {\n                copyRes = mkdirSync(destPath);\n            } else {\n                const mkdirRes = mkdirSync(dirname(destPath));\n                copyRes = mkdirRes.andThen(() => {\n                    return copyFileSync(srcPath, destPath);\n                });\n            }\n        } else {\n            // 不能用join\n            const srcEntryPath = srcPath + SEPARATOR + path;\n            const destEntryPath = destPath + SEPARATOR + path;\n\n            copyRes = (stats.isDirectory()\n                ? mkdirSync(destEntryPath)\n                // 由于串行执行, 文件的父目录一定先于文件创建, 所以不需要额外 mkdir\n                : copyFileSync(srcEntryPath, destEntryPath));\n        }\n\n        if (copyRes.isErr()) return copyRes;\n    }\n\n    return RESULT_VOID;\n}\n\n/**\n * `exists` 的同步版本。\n * @param path - 文件或目录路径。\n * @param options - 检查选项。\n * @returns 是否存在。\n */\nexport function existsSync(path: string, options?: ExistsOptions): IOResult<boolean> {\n    const optionsRes = validateExistsOptions(options);\n    if (optionsRes.isErr()) return optionsRes.asErr();\n\n    const { isDirectory = false, isFile = false } = options ?? {};\n\n    // 不需要区分类型时，使用 access 比 stat 更轻量（不构造 Stats 对象）\n    if (!isDirectory && !isFile) {\n        return accessExistsSync(path);\n    }\n\n    const statRes = statSync(path);\n    return getExistsResult(statRes, options);\n}\n\n/**\n * `emptyDir` 的同步版本。\n * @param dirPath - 要清空的目录路径。\n * @returns 操作结果。\n */\nexport function emptyDirSync(dirPath: string): VoidIOResult {\n    const readDirRes = readDirSync(dirPath);\n    if (readDirRes.isErr()) {\n        // 不存在则创建\n        return isNotFoundError(readDirRes.unwrapErr())\n            ? mkdirSync(dirPath)\n            : readDirRes.asErr();\n    }\n\n    // readDirSync 已经校验通过了\n    dirPath = validateAbsolutePath(dirPath).unwrap();\n\n    for (const name of readDirRes.unwrap()) {\n        const removeRes = removeSync(dirPath + SEPARATOR + name);\n        if (removeRes.isErr()) return removeRes.asErr();\n    }\n\n    return RESULT_VOID;\n}\n\n/**\n * `readTextFile` 的同步版本。\n * @param filePath - 要读取的文件路径。\n * @returns 文件的文本内容。\n */\nexport function readTextFileSync(filePath: string): IOResult<string> {\n    return readFileSync(filePath, {\n        encoding: 'utf8',\n    });\n}\n\n/**\n * `readJsonFile` 的同步版本。\n * @param filePath - 要读取的 JSON 文件路径。\n * @returns 解析后的 JSON 对象。\n */\nexport function readJsonFileSync<T>(filePath: string): IOResult<T> {\n    const readFileRes = readTextFileSync(filePath);\n\n    return readFileRes.andThen(contents => {\n        return tryResult(JSON.parse, contents);\n    });\n}\n\n/**\n * `writeJsonFile` 的同步版本。\n * @param filePath - 要写入的文件路径。\n * @param data - 要序列化并写入的数据。\n * @returns 操作结果。\n */\nexport function writeJsonFileSync<T>(filePath: string, data: T): VoidIOResult {\n    const result = tryResult(JSON.stringify, data);\n\n    return result.andThen(text => writeFileSync(filePath, text));\n}\n\n/**\n * `unzip` 的同步版本。\n * @param zipFilePath - 要解压的 ZIP 文件路径。\n * @param destDir - 解压目标目录。\n * @returns 操作结果。\n */\nexport function unzipSync(zipFilePath: string, destDir: string): VoidIOResult {\n    const destDirRes = validateAbsolutePath(destDir);\n    if (destDirRes.isErr()) return destDirRes.asErr();\n    destDir = destDirRes.unwrap();\n\n    const readFileRes = readFileSync(zipFilePath);\n    if (readFileRes.isErr()) return readFileRes.asErr();\n    const bytes = readFileRes.unwrap();\n\n    const unzippedRes = tryResult(() => decompressSync(bytes));\n    if (unzippedRes.isErr()) return unzippedRes.asErr();\n    const unzipped = unzippedRes.unwrap();\n\n    for (const path in unzipped) {\n        if (path.at(-1) === SEPARATOR) {\n            // 文件夹\n            const mkdirRes = mkdirSync(destDir + SEPARATOR + path.slice(1));\n            if (mkdirRes.isErr()) return mkdirRes.asErr();\n        } else {\n            const writeFileRes = writeFileSync(destDir + SEPARATOR + path, unzipped[path] as Uint8Array<ArrayBuffer>);\n            if (writeFileRes.isErr()) return writeFileRes.asErr();\n        }\n    }\n\n    return RESULT_VOID;\n}\n\n/**\n * `zip` 的同步版本，返回压缩后的字节数组。\n * @param sourcePath - 要压缩的源路径。\n * @param options - 压缩选项。\n * @returns 压缩后的字节数组。\n */\nexport function zipSync(sourcePath: string, options?: ZipOptions): IOResult<Uint8Array<ArrayBuffer>>;\n/**\n * `zip` 的同步版本，将压缩结果写入指定文件。\n * @param sourcePath - 要压缩的源路径。\n * @param zipFilePath - ZIP 文件输出路径。\n * @param options - 压缩选项。\n * @returns 操作结果。\n */\nexport function zipSync(sourcePath: string, zipFilePath: string, options?: ZipOptions): VoidIOResult;\nexport function zipSync(sourcePath: string, zipFilePath?: string | ZipOptions, options?: ZipOptions): ZipIOResult {\n    if (typeof zipFilePath === 'string') {\n        const zipFilePathRes = validateAbsolutePath(zipFilePath);\n        if (zipFilePathRes.isErr()) return zipFilePathRes.asErr();\n        zipFilePath = zipFilePathRes.unwrap();\n    } else {\n        options = zipFilePath;\n        zipFilePath = undefined;\n    }\n\n    const statRes = statSync(sourcePath, {\n        recursive: true,\n    });\n    if (statRes.isErr()) return statRes.asErr();\n    const statsArray = statRes.unwrap();\n\n    // statSync 已经校验通过了\n    sourcePath = validateAbsolutePath(sourcePath).unwrap();\n    const sourceName = basename(sourcePath);\n\n    const zippable: AsyncZippable = {};\n\n    if (statsArray.length === 1 && statsArray[0].stats.isFile()) {\n        // sourcePath 是文件\n        const readFileRes = readFileSync(sourcePath);\n        if (readFileRes.isErr()) return readFileRes;\n\n        zippable[sourceName] = readFileRes.unwrap();\n    } else {\n        // sourcePath 是目录\n        // 默认保留根目录\n        const preserveRoot = options?.preserveRoot ?? true;\n        if (preserveRoot) {\n            // 添加根目录条目\n            zippable[sourceName + SEPARATOR] = EMPTY_BYTES;\n        }\n\n        for (const { path, stats } of statsArray) {\n            // 这里就跳过根目录了\n            if (!path) continue;\n\n            const entryName = preserveRoot ? sourceName + SEPARATOR + path : path;\n\n            if (stats.isFile()) {\n                // 不能用 join，否则 http://usr 会变成 http:/usr\n                const readFileRes = readFileSync(sourcePath + SEPARATOR + path);\n                if (readFileRes.isErr()) return readFileRes;\n\n                zippable[entryName] = readFileRes.unwrap();\n            } else {\n                // 文件夹 - 添加带有尾部斜杠和空内容的条目\n                zippable[entryName + SEPARATOR] = EMPTY_BYTES;\n            }\n        }\n    }\n\n    // Nothing to zip - 和标准 zip 命令的行为一致\n    if (Object.keys(zippable).length === 0) {\n        return createNothingToZipError();\n    }\n\n    return tryResult(() => compressSync(zippable))\n        .andThen<Uint8Array<ArrayBuffer> | void>(bytesLike => {\n            const bytes = bytesLike as Uint8Array<ArrayBuffer>;\n            // 有文件路径则写入文件\n            return zipFilePath\n                ? writeFileSync(zipFilePath, bytes)\n                : Ok(bytes);\n        });\n}\n\n// #region Internal Functions\n\n/**\n * 安全地调用同步接口。\n */\nfunction trySyncOp<T>(op: () => T, errToResult: (err: Error) => IOResult<T> = fileErrorToResult): IOResult<T> {\n    return tryResult<T, Error>(op).orElse(errToResult);\n}\n\n/**\n * 复制单个文件。\n */\nfunction copyFileSync(srcPath: string, destPath: string): VoidIOResult {\n    return trySyncOp(() => getFs().copyFileSync(srcPath, destPath));\n}\n\n// #endregion\n","import {\n    appendFileSync as webAppendFileSync,\n    copySync as webCopySync,\n    emptyDirSync as webEmptyDirSync,\n    existsSync as webExistsSync,\n    mkdirSync as webMkdirSync,\n    moveSync as webMoveSync,\n    readFileSync as webReadFileSync,\n    readJsonFileSync as webReadJsonFileSync,\n    readTextFileSync as webReadTextFileSync,\n    removeSync as webRemoveSync,\n    unzipSync as webUnzipSync,\n    writeFileSync as webWriteFileSync,\n    writeJsonFileSync as webWriteJsonFileSync,\n    zipSync as webZipSync,\n    type AppendOptions,\n    type ExistsOptions,\n    type ZipOptions,\n} from 'happy-opfs';\nimport { type IOResult, type VoidIOResult } from 'happy-rusty';\nimport { IS_MINA } from '../../macros/env.ts';\nimport type { ReadFileContent, ReadOptions, StatOptions, WriteFileContent } from './fs_define.ts';\nimport {\n    appendFileSync as minaAppendFileSync,\n    copySync as minaCopySync,\n    emptyDirSync as minaEmptyDirSync,\n    existsSync as minaExistsSync,\n    mkdirSync as minaMkdirSync,\n    moveSync as minaMoveSync,\n    readDirSync as minaReadDirSync,\n    readFileSync as minaReadFileSync,\n    readJsonFileSync as minaReadJsonFileSync,\n    readTextFileSync as minaReadTextFileSync,\n    removeSync as minaRemoveSync,\n    statSync as minaStatSync,\n    unzipSync as minaUnzipSync,\n    writeFileSync as minaWriteFileSync,\n    writeJsonFileSync as minaWriteJsonFileSync,\n    zipSync as minaZipSync,\n} from './mina_fs_sync.ts';\nimport { webToMinaReadDirSync, webToMinaStatSync } from './web_fs_helpers.ts';\n\n/**\n * `mkdir` 的同步版本，递归创建文件夹。\n * @param dirPath - 将要创建的目录的路径。\n * @returns 创建成功返回的操作结果。\n * @since 1.1.0\n * @example\n * ```ts\n * const result = mkdirSync('/path/to/dir');\n * if (result.isOk()) {\n *     console.log('目录创建成功');\n * }\n * ```\n */\nexport function mkdirSync(dirPath: string): VoidIOResult {\n    return (IS_MINA ? minaMkdirSync : webMkdirSync)(dirPath);\n}\n\n/**\n * `move` 的同步版本，移动或重命名文件或目录。\n * @param srcPath - 原始路径。\n * @param destPath - 新路径。\n * @returns 操作成功返回的操作结果。\n * @since 1.1.0\n * @example\n * ```ts\n * const result = moveSync('/old/path', '/new/path');\n * if (result.isOk()) {\n *     console.log('移动成功');\n * }\n * ```\n */\nexport function moveSync(srcPath: string, destPath: string): VoidIOResult {\n    return (IS_MINA ? minaMoveSync : webMoveSync)(srcPath, destPath);\n}\n\n/**\n * `readDir` 的同步版本，读取指定目录下的所有文件和子目录。\n * @param dirPath - 需要读取的目录路径。\n * @returns 包含目录内容的字符串数组的操作结果。\n * @since 1.1.0\n * @example\n * ```ts\n * const result = readDirSync('/path/to/dir');\n * if (result.isOk()) {\n *     console.log(result.unwrap()); // ['file1.txt', 'file2.txt']\n * }\n * ```\n */\nexport function readDirSync(dirPath: string): IOResult<string[]> {\n    return (IS_MINA ? minaReadDirSync : webToMinaReadDirSync)(dirPath);\n}\n\n/**\n * 以 UTF-8 格式读取文件。\n * @param filePath - 文件路径。\n * @param options - 读取选项，指定编码为 'utf8'。\n * @returns 包含文件内容的字符串的操作结果。\n * @since 1.1.0\n * @example\n * ```ts\n * const result = readFileSync('/path/to/file.txt', { encoding: 'utf8' });\n * if (result.isOk()) {\n *     console.log(result.unwrap());\n * }\n * ```\n */\nexport function readFileSync(filePath: string, options: ReadOptions & {\n    encoding: 'utf8';\n}): IOResult<string>;\n\n/**\n * 以二进制格式读取文件。\n * @param filePath - 文件路径。\n * @param options - 读取选项，指定编码为 'bytes'。\n * @returns 包含文件内容的 Uint8Array<ArrayBuffer> 的操作结果。\n * @since 1.1.0\n * @example\n * ```ts\n * const result = readFileSync('/path/to/file.txt', { encoding: 'bytes' });\n * if (result.isOk()) {\n *     const bytes = result.unwrap();\n *     console.log(decodeUtf8(bytes));\n * }\n * ```\n */\nexport function readFileSync(filePath: string, options?: ReadOptions & {\n    encoding: 'bytes';\n}): IOResult<Uint8Array<ArrayBuffer>>;\n\n/**\n * `readFile` 的同步版本，读取文件内容。\n * @param filePath - 文件的路径。\n * @param options - 可选的读取选项。\n * @returns 包含文件内容的操作结果。\n * @since 1.1.0\n * @example\n * ```ts\n * const result = readFileSync('/path/to/file.txt');\n * if (result.isOk()) {\n *     const bytes = result.unwrap();\n *     console.log(decodeUtf8(bytes));\n * }\n * ```\n */\nexport function readFileSync(filePath: string, options?: ReadOptions): IOResult<ReadFileContent>;\nexport function readFileSync(filePath: string, options?: ReadOptions): IOResult<ReadFileContent> {\n    return IS_MINA\n        ? minaReadFileSync(filePath, options)\n        : webReadFileSync(filePath, options) as IOResult<ReadFileContent>;\n}\n\n/**\n * `remove` 的同步版本，删除文件或目录。\n * @param path - 要删除的文件或目录的路径。\n * @returns 删除成功返回的操作结果。\n * @since 1.1.0\n * @example\n * ```ts\n * const result = removeSync('/path/to/file.txt');\n * if (result.isOk()) {\n *     console.log('删除成功');\n * }\n * ```\n */\nexport function removeSync(path: string): VoidIOResult {\n    return (IS_MINA ? minaRemoveSync : webRemoveSync)(path);\n}\n\n/**\n * `stat` 的同步版本，获取文件或目录的状态信息。\n * @param path - 文件或目录的路径。\n * @returns 包含状态信息的操作结果。\n * @since 1.1.0\n * @example\n * ```ts\n * const result = statSync('/path/to/file.txt');\n * if (result.isOk()) {\n *     console.log(result.unwrap().isFile()); // true\n * }\n * ```\n */\nexport function statSync(path: string, options?: StatOptions & {\n    recursive: false;\n}): IOResult<WechatMinigame.Stats>;\n/**\n * `stat` 的同步版本，递归获取目录下所有文件和子目录的状态信息。\n * @param path - 目录的路径。\n * @param options - 选项，recursive 设置为 true 时递归获取。\n * @returns 包含目录下所有文件状态信息数组的操作结果。\n * @since 1.1.0\n * @example\n * ```ts\n * const result = statSync('/path/to/dir', { recursive: true });\n * if (result.isOk()) {\n *     result.unwrap().forEach(item => {\n *         console.log(item.path, item.stats.isDirectory());\n *     });\n * }\n * ```\n */\nexport function statSync(path: string, options: StatOptions & {\n    recursive: true;\n}): IOResult<WechatMinigame.FileStats[]>;\n/**\n * `stat` 的同步版本，获取文件或目录的状态信息。\n * @param path - 文件或目录的路径。\n * @param options - 可选选项，包含 recursive 可递归获取目录下所有文件状态。\n * @returns 包含状态信息的操作结果，根据 options.recursive 返回单个 Stats 或 FileStats 数组。\n * @since 1.1.0\n */\nexport function statSync(path: string, options?: StatOptions): IOResult<WechatMinigame.Stats | WechatMinigame.FileStats[]>;\nexport function statSync(path: string, options?: StatOptions): IOResult<WechatMinigame.Stats | WechatMinigame.FileStats[]> {\n    return (IS_MINA ? minaStatSync : webToMinaStatSync)(path, options);\n}\n\n/**\n * `writeFile` 的同步版本，写入文件。\n * @param filePath - 文件路径。\n * @param contents - 要写入的内容。\n * @returns 写入成功返回的操作结果。\n * @since 1.1.0\n * @example\n * ```ts\n * const result = writeFileSync('/path/to/file.txt', 'Hello, World!');\n * if (result.isOk()) {\n *     console.log('写入成功');\n * }\n * ```\n */\nexport function writeFileSync(filePath: string, contents: WriteFileContent): VoidIOResult {\n    return (IS_MINA ? minaWriteFileSync : webWriteFileSync)(filePath, contents);\n}\n\n/**\n * `appendFile` 的同步版本，向文件追加内容。\n * @param filePath - 文件路径。\n * @param contents - 要追加的内容。\n * @param options - 可选的追加选项。\n * @returns 追加成功返回的操作结果。\n * @since 1.1.0\n * @example\n * ```ts\n * const result = appendFileSync('/path/to/file.txt', '\\nNew content');\n * if (result.isOk()) {\n *     console.log('追加成功');\n * }\n * ```\n */\nexport function appendFileSync(filePath: string, contents: WriteFileContent, options?: AppendOptions): VoidIOResult {\n    return (IS_MINA ? minaAppendFileSync : webAppendFileSync)(filePath, contents, options);\n}\n\n/**\n * `copy` 的同步版本，复制文件或文件夹。\n * @param srcPath - 源文件或文件夹路径。\n * @param destPath - 目标文件或文件夹路径。\n * @returns 操作的结果。\n * @since 1.1.0\n * @example\n * ```ts\n * const result = copySync('/src/file.txt', '/dest/file.txt');\n * if (result.isOk()) {\n *     console.log('复制成功');\n * }\n * ```\n */\nexport function copySync(srcPath: string, destPath: string): VoidIOResult {\n    return (IS_MINA ? minaCopySync : webCopySync)(srcPath, destPath);\n}\n\n/**\n * `exists` 的同步版本，检查指定路径的文件或目录是否存在。\n * @param path - 文件或目录的路径。\n * @param options - 可选的检查选项。\n * @returns 存在返回 true 的操作结果。\n * @since 1.1.0\n * @example\n * ```ts\n * const result = existsSync('/path/to/file.txt');\n * if (result.isOk() && result.unwrap()) {\n *     console.log('文件存在');\n * }\n * ```\n */\nexport function existsSync(path: string, options?: ExistsOptions): IOResult<boolean> {\n    return (IS_MINA ? minaExistsSync : webExistsSync)(path, options);\n}\n\n/**\n * `emptyDir` 的同步版本，清空指定目录下的所有文件和子目录。\n * @param dirPath - 目录路径。\n * @returns 清空成功返回的操作结果。\n * @since 1.1.0\n * @example\n * ```ts\n * const result = emptyDirSync('/path/to/dir');\n * if (result.isOk()) {\n *     console.log('目录已清空');\n * }\n * ```\n */\nexport function emptyDirSync(dirPath: string): VoidIOResult {\n    return (IS_MINA ? minaEmptyDirSync : webEmptyDirSync)(dirPath);\n}\n\n/**\n * `readJsonFile` 的同步版本，读取 JSON 文件并解析为对象。\n * @typeParam T - JSON 解析后的类型。\n * @param filePath - 文件路径。\n * @returns 解析后的对象。\n * @since 1.6.0\n * @example\n * ```ts\n * const result = readJsonFileSync<{ name: string }>('/path/to/config.json');\n * if (result.isOk()) {\n *     console.log(result.unwrap().name);\n * }\n * ```\n */\nexport function readJsonFileSync<T>(filePath: string): IOResult<T> {\n    return (IS_MINA ? minaReadJsonFileSync : webReadJsonFileSync)(filePath);\n}\n\n/**\n * `readTextFile` 的同步版本，读取文本文件的内容。\n * @param filePath - 文件路径。\n * @returns 包含文件文本内容的操作结果。\n * @since 1.1.0\n * @example\n * ```ts\n * const result = readTextFileSync('/path/to/file.txt');\n * if (result.isOk()) {\n *     console.log(result.unwrap());\n * }\n * ```\n */\nexport function readTextFileSync(filePath: string): IOResult<string> {\n    return (IS_MINA ? minaReadTextFileSync : webReadTextFileSync)(filePath);\n}\n\n/**\n * `writeJsonFile` 的同步版本，将数据序列化为 JSON 并写入文件。\n * @typeParam T - 要写入数据的类型。\n * @param filePath - 文件路径。\n * @param data - 要写入的数据。\n * @returns 写入操作的结果。\n * @since 2.0.0\n * @example\n * ```ts\n * const result = writeJsonFileSync('/path/to/config.json', { name: 'test' });\n * if (result.isOk()) {\n *     console.log('写入成功');\n * }\n * ```\n */\nexport function writeJsonFileSync<T>(filePath: string, data: T): VoidIOResult {\n    return (IS_MINA ? minaWriteJsonFileSync : webWriteJsonFileSync)(filePath, data);\n}\n\n/**\n * `unzip` 的同步版本，解压 zip 文件。\n * @param zipFilePath - 要解压的 zip 文件路径。\n * @param targetPath - 要解压到的目标文件夹路径。\n * @returns 解压操作的结果。\n * @since 1.3.0\n * @example\n * ```ts\n * const result = unzipSync('/path/to/archive.zip', '/path/to/output');\n * if (result.isOk()) {\n *     console.log('解压成功');\n * }\n * ```\n */\nexport function unzipSync(zipFilePath: string, targetPath: string): VoidIOResult {\n    return (IS_MINA ? minaUnzipSync : webUnzipSync)(zipFilePath, targetPath);\n}\n\n/**\n * 压缩文件或文件夹到内存。\n * @param sourcePath - 需要压缩的文件（夹）路径。\n * @param options - 可选的压缩参数。\n * @returns 压缩后的 Uint8Array。\n * @since 1.3.0\n * @example\n * ```ts\n * const result = zipSync('/path/to/source');\n * if (result.isOk()) {\n *     console.log('压缩成功:', result.unwrap().length, 'bytes');\n * }\n * ```\n */\nexport function zipSync(sourcePath: string, options?: ZipOptions): IOResult<Uint8Array<ArrayBuffer>>;\n/**\n * `zip` 的同步版本，压缩文件或文件夹。\n * @param sourcePath - 需要压缩的文件（夹）路径。\n * @param zipFilePath - 压缩后的 zip 文件路径。\n * @param options - 可选的压缩参数。\n * @returns 压缩操作的结果。\n * @since 1.3.0\n * @example\n * ```ts\n * const result = zipSync('/path/to/source', '/path/to/archive.zip');\n * if (result.isOk()) {\n *     console.log('压缩成功');\n * }\n * ```\n */\nexport function zipSync(sourcePath: string, zipFilePath: string, options?: ZipOptions): VoidIOResult;\nexport function zipSync(sourcePath: string, zipFilePath?: string | ZipOptions, options?: ZipOptions): IOResult<Uint8Array<ArrayBuffer> | void> {\n    if (typeof zipFilePath === 'string') {\n        return (IS_MINA ? minaZipSync : webZipSync)(sourcePath, zipFilePath, options);\n    } else {\n        return (IS_MINA ? minaZipSync : webZipSync)(sourcePath, zipFilePath);\n    }\n}\n"],"mappings":"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"}