{"version":3,"file":"utils.cjs","names":[],"sources":["../src/std/utils/resultify.ts"],"sourcesContent":["import { Err, Ok, tryAsyncResult, type AsyncIOResult, type AsyncResult, type IOResult, type Result } from 'happy-rusty';\nimport { Future } from 'tiny-future';\nimport { miniGameFailureToError } from '../internal/helpers.js';\n\n/**\n * 将小游戏异步 API 转换为返回 `AsyncResult<T, E>` 的新函数，需要转换的 API 必须是接受可选 `success` 和 `fail` 回调的函数，并且其返回值必须是 `void` 或 `PromiseLike`。\n *\n * 其中 `T` 为 `success` 回调的参数类型，`E` 为 `fail` 回调的参数类型。\n *\n * @param api - 小游戏异步 API。\n * @returns 返回一个新的函数，该函数返回 `AsyncResult<T, E>`。\n * @since 2.0.0\n * @example\n * ```ts\n * // 将 wx.setStorage 转换为 AsyncResult 风格\n * const setStorageAsync = asyncResultify(wx.setStorage);\n * const result = await setStorageAsync({ key: 'test', data: 'value' });\n * if (result.isOk()) {\n *     console.log('存储成功');\n * } else {\n *     console.error('存储失败:', result.unwrapErr());\n * }\n * ```\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- 函数泛型约束需要 any 以兼容所有函数签名\nexport function asyncResultify<F extends (...args: any[]) => unknown, T = ResultifySuccessType<F>, E = ResultifyFailType<F>>(api: F): ResultifyValidAPI<F> extends true\n    ? (...args: Parameters<F>) => AsyncResult<T, E>\n    : never {\n    return ((...args: Parameters<F>): AsyncResult<T, E> => {\n        const future = new Future<Result<T, E>>();\n\n        const options = args[0] ?? {};\n        const { success, fail } = options;\n\n        // 强制使用callback的方式调用，即使支持Promise\n        options.success = (res: T) => {\n            // success 回调依旧执行\n            success?.(res);\n            future.resolve(Ok(res));\n        };\n        options.fail = (err: E) => {\n            // fail 回调依旧执行\n            fail?.(err);\n            future.resolve(Err(err));\n        };\n\n        const ret = api(options);\n\n        // 也支持其他返回 PromiseLike 的 API（鸭子类型检查）\n        if (ret != null && typeof ret === 'object' && typeof (ret as PromiseLike<T>).then === 'function') {\n            // Convert PromiseLike to AsyncResult\n            return tryAsyncResult(ret as PromiseLike<T>);\n        } else if (ret !== undefined) {\n            // 实测发现某些小游戏平台的 API 可能会返回非 void 非 PromiseLike 的值，虽然官方文档通常只描述了 void 或 PromiseLike 的返回类型。\n            // 为了兼容这些实际情况，我们暂时不抛出错误，而是允许这种情况存在。\n            // throw new TypeError('API must return void or PromiseLike. Otherwise the return value will be discarded');\n        }\n\n        return future.promise;\n    }) as ResultifyValidAPI<F> extends true ? (...args: Parameters<F>) => AsyncResult<T, E> : never;\n}\n\n/**\n * `asyncResultify` 的变体，将小游戏异步 API 转换为返回 `AsyncIOResult<T>` 的新函数。\n *\n * 与 `asyncResultify` 不同的是，此函数会将 `fail` 回调的 `WechatMinigame.GeneralCallbackResult` 转换为 `Error` 类型。\n *\n * @param api - 小游戏异步 API。\n * @returns 返回一个新的函数，该函数返回 `AsyncIOResult<T>`。\n * @since 2.0.0\n * @example\n * ```ts\n * // 将 wx.setStorage 转换为 AsyncIOResult 风格\n * const setStorageAsync = asyncIOResultify(wx.setStorage);\n * const result = await setStorageAsync({ key: 'test', data: 'value' });\n * if (result.isOk()) {\n *     console.log('存储成功');\n * } else {\n *     console.error('存储失败:', result.unwrapErr().message);\n * }\n * ```\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- 函数泛型约束需要 any 以兼容所有函数签名\nexport function asyncIOResultify<F extends (...args: any[]) => unknown, T = ResultifySuccessType<F>>(api: F): IOResultifyValidAPI<F> extends true\n    ? (...args: Parameters<F>) => AsyncIOResult<T>\n    : never {\n    const wrapped = asyncResultify<F, T, WechatMinigame.GeneralCallbackResult>(api);\n\n    return (async (...args: Parameters<F>): AsyncIOResult<T> => {\n        const result = await wrapped(...args);\n        return result.mapErr(miniGameFailureToError);\n    }) as IOResultifyValidAPI<F> extends true ? (...args: Parameters<F>) => AsyncIOResult<T> : never;\n}\n\n/**\n * 将小游戏同步 API 转换为返回 `IOResult<T>` 的新函数。\n *\n * 功能类似于 `tryGeneralSyncOp`，但以函数包装的方式使用，将可能抛出的异常捕获并转换为 `IOResult`。\n *\n * @param api - 小游戏同步 API。\n * @returns 返回一个新的函数，该函数返回 `IOResult<T>`。\n * @since 2.0.0\n * @example\n * ```ts\n * // 将 wx.getStorageSync 转换为 IOResult 风格\n * const getStorageSync = syncIOResultify(wx.getStorageSync);\n * const result = getStorageSync('test');\n * if (result.isOk()) {\n *     console.log('获取成功:', result.unwrap());\n * } else {\n *     console.error('获取失败:', result.unwrapErr().message);\n * }\n * ```\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- 函数泛型约束需要 any 以兼容所有函数签名\nexport function syncIOResultify<F extends (...args: any[]) => unknown>(api: F): (...args: Parameters<F>) => IOResult<ReturnType<F>> {\n    return (...args: Parameters<F>): IOResult<ReturnType<F>> => {\n        try {\n            return Ok(api(...args) as ReturnType<F>);\n        } catch (e) {\n            return Err(miniGameFailureToError(e as WechatMinigame.GeneralCallbackResult));\n        }\n    };\n}\n\n// #region Internal Types\n\n/**\n * 通用回调函数类型。\n */\ntype AnyCallback = (...args: never[]) => unknown;\n\n/**\n * 类型工具：判断 API 是否符合 resultify 条件。\n *\n * 要求 API 返回 `void` 或 `PromiseLike`，且参数包含 `success` 或 `fail` 回调。\n * @typeParam T - 待检查的 API 函数类型。\n */\ntype ResultifyValidAPI<T> = T extends (params: infer P) => infer R\n    ? R extends void | PromiseLike<unknown>\n    ? P extends { success?: AnyCallback; } | undefined\n    ? true\n    : P extends { fail?: AnyCallback; } | undefined\n    ? true\n    : false\n    : false\n    : false;\n\n/**\n * 类型工具：判断 API 是否符合 asyncIOResultify 条件。\n *\n * 在 `ResultifyValidAPI` 基础上，额外要求 `fail` 回调参数类型必须精确为 `GeneralCallbackResult`。\n * @typeParam T - 待检查的 API 函数类型。\n */\ntype IOResultifyValidAPI<T> = ResultifyValidAPI<T> extends true\n    ? ResultifyFailType<T> extends WechatMinigame.GeneralCallbackResult\n    ? WechatMinigame.GeneralCallbackResult extends ResultifyFailType<T>\n    ? true\n    : false\n    : false\n    : false;\n\n/**\n * 类型工具：提取成功回调参数类型。\n *\n * 从 API 函数的 `success` 回调中提取返回类型。\n * @typeParam T - API 函数类型。\n */\ntype ResultifySuccessType<T> = T extends (params: infer P) => unknown\n    ? P extends { success?: (res: infer S) => unknown; }\n    ? S\n    : never\n    : never;\n\n/**\n * 类型工具：提取失败回调参数类型。\n *\n * 从 API 函数的 `fail` 回调中提取错误类型。\n * @typeParam T - API 函数类型。\n */\ntype ResultifyFailType<T> = T extends (params: infer P) => unknown\n    ? P extends { fail?: (err: infer E) => unknown; }\n    ? E\n    : never\n    : never;\n\n// #endregion\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAyBA,SAAgB,eAA6G,KAEjH;CACR,SAAS,GAAG,SAA2C;EACnD,MAAM,SAAS,IAAI,YAAA,OAAqB;EAExC,MAAM,UAAU,KAAK,MAAM,CAAC;EAC5B,MAAM,EAAE,SAAS,SAAS;EAG1B,QAAQ,WAAW,QAAW;GAE1B,UAAU,GAAG;GACb,OAAO,SAAA,GAAA,YAAA,GAAA,CAAW,GAAG,CAAC;EAC1B;EACA,QAAQ,QAAQ,QAAW;GAEvB,OAAO,GAAG;GACV,OAAO,SAAA,GAAA,YAAA,IAAA,CAAY,GAAG,CAAC;EAC3B;EAEA,MAAM,MAAM,IAAI,OAAO;EAGvB,IAAI,OAAO,QAAQ,OAAO,QAAQ,YAAY,OAAQ,IAAuB,SAAS,YAElF,QAAA,GAAA,YAAA,eAAA,CAAsB,GAAqB;OACxC,IAAI,QAAQ,KAAA,GAAW,CAI9B;EAEA,OAAO,OAAO;CAClB;AACJ;;;;;;;;;;;;;;;;;;;;;AAuBA,SAAgB,iBAAqF,KAEzF;CACR,MAAM,UAAU,eAA2D,GAAG;CAE9E,QAAQ,OAAO,GAAG,SAA0C;EAExD,QAAO,MADc,QAAQ,GAAG,IAAI,EAAA,CACtB,OAAO,4BAAA,sBAAsB;CAC/C;AACJ;;;;;;;;;;;;;;;;;;;;;AAuBA,SAAgB,gBAAuD,KAA6D;CAChI,QAAQ,GAAG,SAAiD;EACxD,IAAI;GACA,QAAA,GAAA,YAAA,GAAA,CAAU,IAAI,GAAG,IAAI,CAAkB;EAC3C,SAAS,GAAG;GACR,QAAA,GAAA,YAAA,IAAA,EAAA,GAAA,4BAAA,uBAAA,CAAkC,CAAyC,CAAC;EAChF;CACJ;AACJ"}