minigame-std
Version:
Cross-platform standard library for WeChat minigame and web browsers with unified APIs for crypto, fs, fetch, storage, and more.
125 lines (124 loc) • 3.93 kB
JavaScript
import { ABORT_ERROR, ABORT_ERROR as ABORT_ERROR$1, FetchError, FetchError as FetchError$1, TIMEOUT_ERROR, TIMEOUT_ERROR as TIMEOUT_ERROR$1, fetchT as fetchT$1 } from "@happy-ts/fetch-t";
import { bufferSourceToAb, createFailedFetchTask, miniGameFailureToError, validateSafeUrl } from "./_internal.mjs";
import { Err, Ok } from "happy-rusty";
import { Future } from "tiny-future";
//#region src/macros/env.ts
/**
* 如果在小游戏环境中返回 true,否则返回 false。
*/
const IS_MINA = __MINIGAME_STD_MINA__;
//#endregion
//#region src/std/fetch/mina_fetch.ts
/**
* @internal
* 小游戏平台的 HTTP 请求实现。
*/
/**
* 发起一个网络请求,根据初始化配置返回对应类型的 FetchTask。
* @typeParam T - 预期的响应数据类型。
* @param url - 请求的 URL 地址。
* @param init - 请求的初始化配置。
* @returns 根据配置返回 FetchTask。
*/
function minaFetch(url, init) {
const urlRes = validateSafeUrl(url);
if (urlRes.isErr()) return createFailedFetchTask(urlRes);
const { responseType, onChunk, ...rest } = init ?? {};
let aborted = false;
const future = new Future();
const options = {
...rest,
url,
success(res) {
const { statusCode } = res;
if (statusCode >= 200 && statusCode < 300) future.resolve(Ok(res.data));
else future.resolve(Err(new FetchError$1(res.errMsg, statusCode)));
},
fail(err) {
const error = miniGameFailureToError(err);
const { errMsg } = err;
if (errMsg.includes("abort")) error.name = ABORT_ERROR$1;
else if (errMsg.includes("timeout")) error.name = TIMEOUT_ERROR$1;
future.resolve(Err(error));
}
};
if (responseType === "arraybuffer") options.responseType = responseType;
else if (responseType === "json") options.dataType = responseType;
else {
options.responseType = responseType;
options.dataType = "其他";
}
const task = wx.request(options);
if (typeof onChunk === "function") task.onChunkReceived((res) => {
onChunk(new Uint8Array(res.data));
});
return {
abort() {
aborted = true;
task.abort();
},
get aborted() {
return aborted;
},
get result() {
return future.promise;
}
};
}
//#endregion
//#region src/std/fetch/mod.ts
/**
* 网络请求模块,提供可中断的 fetch 请求功能,支持 text、JSON、ArrayBuffer 等响应类型。
* @module fetch
*/
/**
* 发起一个网络请求,根据初始化配置返回对应类型的 FetchTask。
* @typeParam T - 预期的响应数据类型。
* @param url - 请求的 URL 地址。
* @param init - 请求的初始化配置。
* @returns FetchTask。
* @since 1.0.0
* @example
* ```ts
* // 发起 POST 请求
* const task = fetchT('https://api.example.com/submit', {
* method: 'POST',
* headers: { 'Content-Type': 'application/json' },
* body: JSON.stringify({ key: 'value' }),
* responseType: 'json',
* });
* const result = await task.result;
* ```
*/
function fetchT(url, init) {
const defaultInit = init ?? {};
defaultInit.responseType ??= "text";
if (IS_MINA) {
const { body, headers, ...rest } = defaultInit;
if (body != null) rest.data = typeof body === "string" || isPlainObject(body) ? body : bufferSourceToAb(body);
if (headers !== void 0) rest.header = headers;
return minaFetch(url, rest);
}
const { body, ...rest } = defaultInit;
const webInit = {
...rest,
body,
abortable: true
};
if (isPlainObject(body)) {
webInit.body = JSON.stringify(body);
const headers = new Headers(webInit.headers);
headers.set("Content-Type", "application/json");
webInit.headers = headers;
}
return fetchT$1(url, webInit);
}
/**
* 判断值是否为普通对象(非 string、非 BufferSource)。
*/
function isPlainObject(value) {
return value != null && typeof value === "object" && !ArrayBuffer.isView(value) && !(value instanceof ArrayBuffer);
}
//#endregion
export { ABORT_ERROR, FetchError, TIMEOUT_ERROR, fetchT };
//# sourceMappingURL=fetch.mjs.map