{"version":3,"file":"fetch.mjs","names":[],"sources":["../src/macros/env.ts","../src/std/fetch/mina_fetch.ts","../src/std/fetch/mod.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 * 小游戏平台的 HTTP 请求实现。\n */\n\nimport { ABORT_ERROR, FetchError, TIMEOUT_ERROR, type FetchResult, type FetchTask } from '@happy-ts/fetch-t';\nimport { Err, Ok, type IOResult } from 'happy-rusty';\nimport { Future } from 'tiny-future';\nimport { createFailedFetchTask, miniGameFailureToError, validateSafeUrl } from '../internal/mod.ts';\nimport type { MinaFetchInit } from './fetch_defines.ts';\n\n/**\n * 发起一个可中断的 ArrayBuffer 类型响应的网络请求。\n * @param url - 请求的 URL 地址。\n * @param init - 请求的初始化配置，指定响应类型为 ArrayBuffer 且请求可中断。\n * @returns 返回一个 ArrayBuffer 类型的 FetchTask。\n */\nexport function minaFetch(url: string, init: MinaFetchInit & {\n    responseType: 'arraybuffer';\n}): FetchTask<ArrayBuffer>;\n\n/**\n * 发起一个可中断的 JSON 类型响应的网络请求。\n * @typeParam T - 预期的 JSON 响应数据类型。\n * @param url - 请求的 URL 地址。\n * @param init - 请求的初始化配置，指定响应类型为 JSON 且请求可中断。\n * @returns 返回一个 JSON 类型的 FetchTask。\n */\nexport function minaFetch<T>(url: string, init: MinaFetchInit & {\n    responseType: 'json';\n}): FetchTask<T>;\n\n/**\n * 发起一个可中断的文本类型响应的网络请求。\n * @param url - 请求的 URL 地址。\n * @param init - 请求的初始化配置，指定响应类型为文本且请求可中断。\n * @returns 返回一个文本类型的 FetchTask。\n */\nexport function minaFetch(url: string, init?: MinaFetchInit & {\n    responseType: 'text';\n}): FetchTask<string>;\n\n/**\n * 发起一个可中断的网络请求，默认返回文本类型响应。\n * @param url - 请求的 URL 地址。\n * @param init - 请求的初始化配置，指定请求可中断。\n * @returns {FetchTask<string>} 返回一个文本类型的 FetchTask。\n */\nexport function minaFetch(url: string, init: MinaFetchInit): FetchTask<string>;\n\n/**\n * 发起一个网络请求，根据初始化配置返回对应类型的 FetchTask。\n * @typeParam T - 预期的响应数据类型。\n * @param url - 请求的 URL 地址。\n * @param init - 请求的初始化配置。\n * @returns 根据配置返回 FetchTask。\n */\nexport function minaFetch<T>(url: string, init?: MinaFetchInit): FetchTask<T> {\n    const urlRes = validateSafeUrl(url);\n    if (urlRes.isErr()) return createFailedFetchTask(urlRes);\n\n    const {\n        responseType,\n        onChunk,\n        ...rest\n    } = init ?? {};\n\n    let aborted = false;\n\n    const future = new Future<IOResult<T>>();\n\n    const options: WechatMinigame.RequestOption = {\n        ...rest,\n        url,\n        success(res) {\n            const { statusCode } = res;\n\n            if (statusCode >= 200 && statusCode < 300) {\n                future.resolve(Ok(res.data as T));\n            } else {\n                future.resolve(Err(new FetchError(res.errMsg, statusCode)));\n            }\n        },\n        fail(err) {\n            const error = miniGameFailureToError(err);\n            const { errMsg } = err;\n\n            if (errMsg.includes('abort')) {\n                error.name = ABORT_ERROR;\n            } else if (errMsg.includes('timeout')) {\n                error.name = TIMEOUT_ERROR;\n            }\n\n            future.resolve(Err(error));\n        },\n    };\n\n    if (responseType === 'arraybuffer') {\n        options.responseType = responseType;\n    } else if (responseType === 'json') {\n        options.dataType = responseType;\n    } else {\n        // 默认 responseType 是 text\n        options.responseType = responseType;\n        // responseType设置为text还不够，否则返回类型还是json\n        options.dataType = '其他';\n    }\n\n    const task = wx.request(options);\n\n    if (typeof onChunk === 'function') {\n        task.onChunkReceived(res => {\n            onChunk(new Uint8Array(res.data));\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 * 网络请求模块，提供可中断的 fetch 请求功能，支持 text、JSON、ArrayBuffer 等响应类型。\n * @module fetch\n */\nimport { fetchT as webFetch, type FetchInit, type FetchTask } from '@happy-ts/fetch-t';\nimport { IS_MINA } from '../../macros/env.ts';\nimport { bufferSourceToAb } from '../internal/mod.ts';\nimport type { MinaFetchInit, UnionFetchInit } from './fetch_defines.ts';\nimport { minaFetch } from './mina_fetch.ts';\n\nexport { ABORT_ERROR, FetchError, TIMEOUT_ERROR, type FetchTask } from '@happy-ts/fetch-t';\nexport type { UnionFetchInit } from './fetch_defines.ts';\n\n/**\n * 发起一个可中断的文本类型响应的网络请求。\n * @param url - 请求的 URL 地址。\n * @param init - 请求的初始化配置，指定响应类型为文本且请求可中断。\n * @returns 返回一个文本类型的 FetchTask。\n * @since 1.0.0\n * @example\n * ```ts\n * const task = fetchT('https://api.example.com/data', { responseType: 'text' });\n * const result = await task.result;\n * if (result.isOk()) {\n *     console.log(result.unwrap()); // 文本内容\n * }\n * // 如需中断请求\n * task.abort();\n * ```\n */\nexport function fetchT(url: string, init: UnionFetchInit & {\n    responseType: 'text';\n}): FetchTask<string>;\n\n/**\n * 发起一个可中断的 ArrayBuffer 类型响应的网络请求。\n * @param url - 请求的 URL 地址。\n * @param init - 请求的初始化配置，指定响应类型为 ArrayBuffer 且请求可中断。\n * @returns 返回一个 ArrayBuffer 类型的 FetchTask。\n * @since 1.0.0\n * @example\n * ```ts\n * const task = fetchT('https://api.example.com/file', { responseType: 'arraybuffer' });\n * const result = await task.result;\n * if (result.isOk()) {\n *     const buffer = result.unwrap();\n *     console.log('文件大小:', buffer.byteLength);\n * }\n * ```\n */\nexport function fetchT(url: string, init: UnionFetchInit & {\n    responseType: 'arraybuffer';\n}): FetchTask<ArrayBuffer>;\n\n/**\n * 发起一个可中断的 JSON 类型响应的网络请求。\n * @typeParam T - 预期的 JSON 响应数据类型。\n * @param url - 请求的 URL 地址。\n * @param init - 请求的初始化配置，指定响应类型为 JSON 且请求可中断。\n * @returns 返回一个 JSON 类型的 FetchTask。\n * @since 1.0.0\n * @example\n * ```ts\n * interface User {\n *     id: number;\n *     name: string;\n * }\n * const task = fetchT<User>('https://api.example.com/user/1', { responseType: 'json' });\n * const result = await task.result;\n * if (result.isOk()) {\n *     const user = result.unwrap();\n *     console.log(user.name);\n * }\n * ```\n */\nexport function fetchT<T>(url: string, init: UnionFetchInit & {\n    responseType: 'json';\n}): FetchTask<T>;\n\n/**\n * 发起一个可中断的网络请求，默认返回文本类型响应。\n * @typeParam T - 预期的响应数据类型。\n * @param url - 请求的 URL 地址。\n * @param init - 请求的初始化配置，指定请求可中断。\n * @returns FetchTask。\n * @since 1.0.0\n * @example\n * ```ts\n * const task = fetchT('https://api.example.com/data');\n * const result = await task.result;\n * if (result.isOk()) {\n *     console.log(result.unwrap());\n * }\n * ```\n */\nexport function fetchT(url: string, init?: UnionFetchInit): FetchTask<string | Response>;\n\n/**\n * 发起一个网络请求，根据初始化配置返回对应类型的 FetchTask。\n * @typeParam T - 预期的响应数据类型。\n * @param url - 请求的 URL 地址。\n * @param init - 请求的初始化配置。\n * @returns FetchTask。\n * @since 1.0.0\n * @example\n * ```ts\n * // 发起 POST 请求\n * const task = fetchT('https://api.example.com/submit', {\n *     method: 'POST',\n *     headers: { 'Content-Type': 'application/json' },\n *     body: JSON.stringify({ key: 'value' }),\n *     responseType: 'json',\n * });\n * const result = await task.result;\n * ```\n */\nexport function fetchT<T>(url: string, init?: UnionFetchInit): FetchTask<T> {\n    const defaultInit = init ?? {};\n    // 默认是 text 类型\n    defaultInit.responseType ??= 'text';\n\n    if (IS_MINA) {\n        // Map body → data, headers → header for mini-game\n        const { body, headers, ...rest } = defaultInit;\n        if (body != null) {\n            // wx.request data only accepts string | IAnyObject | ArrayBuffer\n            // BufferSource needs conversion to handle potential byteOffset\n            (rest as MinaFetchInit).data = typeof body === 'string' || isPlainObject(body)\n                ? body\n                : bufferSourceToAb(body as BufferSource);\n        }\n        if (headers !== undefined) {\n            (rest as MinaFetchInit).header = headers;\n        }\n        return minaFetch(url, rest) as FetchTask<T>;\n    }\n\n    // Auto-serialize object body for web\n    const { body, ...rest } = defaultInit;\n    const webInit: FetchInit & { abortable: true; } = { ...rest, body: body as BodyInit | null | undefined, abortable: true };\n\n    if (isPlainObject(body)) {\n        webInit.body = JSON.stringify(body);\n        // Object body is always serialized as JSON\n        const headers = new Headers(webInit.headers);\n        headers.set('Content-Type', 'application/json');\n        webInit.headers = headers;\n    }\n\n    return webFetch(url, webInit) as FetchTask<T>;\n}\n\n/**\n * 判断值是否为普通对象（非 string、非 BufferSource）。\n */\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n    return value != null\n        && typeof value === 'object'\n        && !ArrayBuffer.isView(value)\n        && !(value instanceof ArrayBuffer);\n}\n"],"mappings":";;;;;;;;AAeA,MAAa,UAAU;;;;;;;;;;;;;;AC0CvB,SAAgB,UAAa,KAAa,MAAoC;CAC1E,MAAM,SAAS,gBAAgB,GAAG;CAClC,IAAI,OAAO,MAAM,GAAG,OAAO,sBAAsB,MAAM;CAEvD,MAAM,EACF,cACA,SACA,GAAG,SACH,QAAQ,CAAC;CAEb,IAAI,UAAU;CAEd,MAAM,SAAS,IAAI,OAAoB;CAEvC,MAAM,UAAwC;EAC1C,GAAG;EACH;EACA,QAAQ,KAAK;GACT,MAAM,EAAE,eAAe;GAEvB,IAAI,cAAc,OAAO,aAAa,KAClC,OAAO,QAAQ,GAAG,IAAI,IAAS,CAAC;QAEhC,OAAO,QAAQ,IAAI,IAAI,aAAW,IAAI,QAAQ,UAAU,CAAC,CAAC;EAElE;EACA,KAAK,KAAK;GACN,MAAM,QAAQ,uBAAuB,GAAG;GACxC,MAAM,EAAE,WAAW;GAEnB,IAAI,OAAO,SAAS,OAAO,GACvB,MAAM,OAAO;QACV,IAAI,OAAO,SAAS,SAAS,GAChC,MAAM,OAAO;GAGjB,OAAO,QAAQ,IAAI,KAAK,CAAC;EAC7B;CACJ;CAEA,IAAI,iBAAiB,eACjB,QAAQ,eAAe;MACpB,IAAI,iBAAiB,QACxB,QAAQ,WAAW;MAChB;EAEH,QAAQ,eAAe;EAEvB,QAAQ,WAAW;CACvB;CAEA,MAAM,OAAO,GAAG,QAAQ,OAAO;CAE/B,IAAI,OAAO,YAAY,YACnB,KAAK,iBAAgB,QAAO;EACxB,QAAQ,IAAI,WAAW,IAAI,IAAI,CAAC;CACpC,CAAC;CAGL,OAAO;EACH,QAAc;GACV,UAAU;GACV,KAAK,MAAM;EACf;EAEA,IAAI,UAAmB;GACnB,OAAO;EACX;EAEA,IAAI,SAAyB;GACzB,OAAO,OAAO;EAClB;CACJ;AACJ;;;;;;;;;;;;;;;;;;;;;;;;;;ACdA,SAAgB,OAAU,KAAa,MAAqC;CACxE,MAAM,cAAc,QAAQ,CAAC;CAE7B,YAAY,iBAAiB;CAE7B,IAAI,SAAS;EAET,MAAM,EAAE,MAAM,SAAS,GAAG,SAAS;EACnC,IAAI,QAAQ,MAGR,KAAwB,OAAO,OAAO,SAAS,YAAY,cAAc,IAAI,IACvE,OACA,iBAAiB,IAAoB;EAE/C,IAAI,YAAY,KAAA,GACZ,KAAwB,SAAS;EAErC,OAAO,UAAU,KAAK,IAAI;CAC9B;CAGA,MAAM,EAAE,MAAM,GAAG,SAAS;CAC1B,MAAM,UAA4C;EAAE,GAAG;EAAY;EAAqC,WAAW;CAAK;CAExH,IAAI,cAAc,IAAI,GAAG;EACrB,QAAQ,OAAO,KAAK,UAAU,IAAI;EAElC,MAAM,UAAU,IAAI,QAAQ,QAAQ,OAAO;EAC3C,QAAQ,IAAI,gBAAgB,kBAAkB;EAC9C,QAAQ,UAAU;CACtB;CAEA,OAAO,SAAS,KAAK,OAAO;AAChC;;;;AAKA,SAAS,cAAc,OAAkD;CACrE,OAAO,SAAS,QACT,OAAO,UAAU,YACjB,CAAC,YAAY,OAAO,KAAK,KACzB,EAAE,iBAAiB;AAC9B"}