@amaster.ai/http-client 1.0.0-beta.2 → 1.0.0-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +2 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +28 -6
- package/dist/index.d.ts +28 -6
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/package.json +6 -1
package/dist/index.cjs
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
'use strict';function
|
|
1
|
+
'use strict';function f(t){if(!t)return "Request failed";if(typeof t=="string")return t;if(typeof t=="object"){let e=t;return e.message||e.error||e.msg||e.detail||"Request failed"}return "Request failed"}function l(t){if(!t||typeof t!="object"||!("data"in t))return false;if("status"in t){let e=t.status;return e===0||e===1||e==="0"||e==="1"}return false}function g(t){return l(t)?t.data:t}var y=/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/;function m(t){return y.test(t)}function R(t){return `${t.replace(" ","T")}.000Z`}function c(t){if(t==null)return t;if(Array.isArray(t))return t.map(e=>c(e));if(typeof t=="object"){let e={};for(let[n,i]of Object.entries(t))e[n]=c(i);return e}return typeof t=="string"&&m(t)?R(t):t}function q(t){return /^https?:\/\//i.test(t)}function w(t,e){let n=t.replace(/\/+$/,""),i=e.startsWith("/")?e:`/${e}`;return `${n}${i}`}function C(t){if(!t||typeof t!="object")return "";let e=Object.entries(t).filter(([,r])=>r!=null);if(e.length===0)return "";let n=globalThis?.URLSearchParams,i="";if(n){let r=new n;for(let[o,s]of e)if(Array.isArray(s))for(let u of s)r.append(o,String(u));else r.append(o,String(s));i=r.toString();}else i=e.flatMap(([r,o])=>Array.isArray(o)?o.map(s=>[r,s]):[[r,o]]).map(([r,o])=>`${encodeURIComponent(r)}=${encodeURIComponent(String(o))}`).join("&");return i?`?${i}`:""}function d(t,e){let n=C(e);return n?t.includes("?")?`${t}&${n.slice(1)}`:`${t}${n}`:t}function b(){let e=globalThis?.process?.env,n=e?.API_BASE_URL||e?.TARO_APP_API_BASE_URL||e?.VITE_API_BASE_URL||"";return String(n||"").trim()}function A(t,e){let n=String(t.url||"");if(q(n))return d(n,t.params);let i=String(t.baseURL||e?.baseURL||b()||"").trim(),r=i?w(i,n):n;return d(r,t.params)}function k(){let t=globalThis;return typeof t?.Taro?.request=="function"?t.Taro.request.bind(t.Taro):typeof t?.wx?.request=="function"?t.wx.request.bind(t.wx):typeof t?.tt?.request=="function"?t.tt.request.bind(t.tt):typeof t?.my?.request=="function"?t.my.request.bind(t.my):typeof t?.swan?.request=="function"?t.swan.request.bind(t.swan):typeof t?.qq?.request=="function"?t.qq.request.bind(t.qq):typeof t?.jd?.request=="function"?t.jd.request.bind(t.jd):null}async function T(t,e){try{let n=t(e);if(n&&typeof n.then=="function")return await n}catch{}return await new Promise((n,i)=>{t({...e,success:r=>n(r),fail:r=>i(r)});})}function h(t,e){let n={...t||{}};if(!e)return n;if(typeof e=="object")for(let[i,r]of Object.entries(e))r!=null&&(n[i]=String(r));return n}async function x(t,e){let n=k();if(!n)throw new Error("Mini-program request API not found (wx/tt/my/... or global Taro.request).");let i=A(t,e),r=String(t.method||"GET").toUpperCase(),o=h(e?.headers,t.headers),s=await T(n,{url:i,method:r,header:o,data:t.data});return {status:s?.statusCode??s?.status??0,data:s?.data,headers:s?.header}}function P(t){let e=t;return typeof e=="function"&&!!e?.defaults&&!!e?.interceptors}function S(t){let e,n;P(t)?e=t:n=t;let i=n?.adapter??"axios";return {async request(r){try{let o=0,s=null,u=typeof i=="function"?i:i==="taro"?"taro":"axios";if(typeof u=="function"){let a=await u(r);o=a.status??0,s=a.data??null;}else if(u==="taro"){let a=await x(r,n);o=a.status??0,s=a.data??null;}else {e||(e=(await import('axios')).default.create());let a=await e(r);o=a?.status??0,s=a?.data;}if(o>=200&&o<300){let a=g(s);return {data:c(a)??null,error:null,status:o}}return {data:null,error:{status:o,message:f(s)||`HTTP ${o}`,details:s},status:o}}catch(o){let s=o,u=s?.response?.status||s?.statusCode||0,a=s?.response?.data??s?.data;return {data:null,error:{status:u,message:f(a)||s?.message||"Network error",details:a},status:u}}}}}
|
|
2
|
+
exports.createHttpClient=S;//# sourceMappingURL=index.cjs.map
|
|
2
3
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/http.ts"],"names":["normalizeErrorMessage","payload","errorPayload","isBackendStandardFormat","data","status","unwrapBackendResponse","responseData","BACKEND_DATETIME_REGEX","isBackendDatetime","value","parseBackendDatetime","processResponseDates","item","processed","key","createHttpClient","axiosInstance","instance","config","resp","unwrappedData","error_","error"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { AxiosInstance, AxiosRequestConfig } from \"axios\";\n\nexport type ClientError = {\n message: string;\n status?: number;\n code?: string;\n details?: unknown;\n};\n\nexport type ClientResult<T> = {\n data: T | null;\n error: ClientError | null;\n status: number;\n};\n\nexport type HttpClient = {\n request<T>(\n config: AxiosRequestConfig & {\n url: string;\n method: NonNullable<AxiosRequestConfig[\"method\"]>;\n }\n ): Promise<ClientResult<T>>;\n};\n\ninterface ErrorPayload {\n message?: string;\n error?: string;\n msg?: string;\n detail?: string;\n}\n\nfunction normalizeErrorMessage(payload: unknown): string {\n if (!payload) {\n return \"Request failed\";\n }\n if (typeof payload === \"string\") {\n return payload;\n }\n if (typeof payload === \"object\") {\n const errorPayload = payload as ErrorPayload;\n return (\n errorPayload.message ||\n errorPayload.error ||\n errorPayload.msg ||\n errorPayload.detail ||\n \"Request failed\"\n );\n }\n return \"Request failed\";\n}\n\ninterface BackendStandardResponse {\n status: number | string;\n data: unknown;\n}\n\n/**\n * Check if response data matches backend standard format: { status: 0/1, data: {...} }\n * Handles both number and string status values\n */\nfunction isBackendStandardFormat(data: unknown): data is BackendStandardResponse {\n if (!data || typeof data !== \"object\" || !(\"data\" in data)) {\n return false;\n }\n\n // Check status field - handle both number and string values\n if (\"status\" in data) {\n const status = (data as BackendStandardResponse).status;\n // Accept 0, 1, \"0\", \"1\" as valid status values\n return status === 0 || status === 1 || status === \"0\" || status === \"1\";\n }\n\n return false;\n}\n\n/**\n * Unwrap backend standard format response\n * Backend returns: { status: 0, data: {...} }\n * We extract the inner 'data' field for cleaner client usage\n */\nfunction unwrapBackendResponse<T>(responseData: unknown): T {\n if (isBackendStandardFormat(responseData)) {\n // Extract inner data field\n return responseData.data as T;\n }\n // Return as-is if not standard format (e.g., BPM/Workflow APIs)\n return responseData as T;\n}\n\n/**\n * Backend datetime format regex: \"YYYY-MM-DD HH:MM:SS\"\n */\nconst BACKEND_DATETIME_REGEX = /^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}$/;\n\n/**\n * Check if a string matches backend datetime format\n */\nfunction isBackendDatetime(value: string): boolean {\n return BACKEND_DATETIME_REGEX.test(value);\n}\n\n/**\n * Convert backend datetime string to ISO 8601 format\n * \"2026-01-05 10:30:45\" → \"2026-01-05T10:30:45.000Z\"\n */\nfunction parseBackendDatetime(value: string): string {\n // Replace space with T and append Z for UTC\n return `${value.replace(\" \", \"T\")}.000Z`;\n}\n\n/**\n * Recursively process response data to convert backend datetime strings to ISO format\n * Handles nested objects and arrays\n */\nfunction processResponseDates(data: unknown): unknown {\n if (data === null || data === undefined) {\n return data;\n }\n\n // Handle arrays\n if (Array.isArray(data)) {\n return data.map((item) => processResponseDates(item));\n }\n\n // Handle objects\n if (typeof data === \"object\") {\n const processed: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(data)) {\n processed[key] = processResponseDates(value);\n }\n return processed;\n }\n\n // Handle backend datetime strings\n if (typeof data === \"string\" && isBackendDatetime(data)) {\n return parseBackendDatetime(data);\n }\n\n return data;\n}\n\n/**\n * Create an HTTP client instance\n * \n * @param axiosInstance - Optional axios instance to use (defaults to a basic axios instance)\n * @returns HttpClient with request method\n * \n * @example\n * ```typescript\n * import axios from \"axios\";\n * import { createHttpClient } from \"@amaster.ai/http-client\";\n * \n * const instance = axios.create({ baseURL: \"https://api.example.com\" });\n * const client = createHttpClient(instance);\n * \n * const result = await client.request({\n * url: \"/users\",\n * method: \"get\",\n * });\n * ```\n */\nexport function createHttpClient(axiosInstance?: AxiosInstance): HttpClient {\n // Import axios dynamically to avoid bundling it\n let instance = axiosInstance;\n \n return {\n async request<T>(\n config: AxiosRequestConfig & {\n url: string;\n method: NonNullable<AxiosRequestConfig[\"method\"]>;\n }\n ) {\n // Lazy load axios if not provided\n if (!instance) {\n const axios = await import(\"axios\");\n instance = axios.default.create();\n }\n\n try {\n const resp = await instance(config);\n const status = resp?.status ?? 0;\n\n if (status >= 200 && status < 300) {\n // Unwrap backend standard format: { status: 0, data: {...} } -> {...}\n const unwrappedData = unwrapBackendResponse<T>(resp?.data);\n // Convert backend datetime strings to ISO format\n const processedData = processResponseDates(unwrappedData);\n return { data: (processedData ?? null) as T | null, error: null, status };\n }\n\n return {\n data: null,\n error: {\n status,\n message: normalizeErrorMessage(resp?.data) || `HTTP ${status}`,\n details: resp?.data,\n },\n status,\n };\n } catch (error_: unknown) {\n // Catch network errors, timeouts, and other axios exceptions\n const error = error_ as {\n response?: { status?: number; data?: unknown };\n message?: string;\n };\n const status = error.response?.status || 0;\n return {\n data: null,\n error: {\n status,\n message:\n normalizeErrorMessage(error.response?.data) || error.message || \"Network error\",\n details: error.response?.data,\n },\n status,\n };\n }\n },\n };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/http.ts"],"names":["normalizeErrorMessage","payload","errorPayload","isBackendStandardFormat","data","status","unwrapBackendResponse","responseData","BACKEND_DATETIME_REGEX","isBackendDatetime","value","parseBackendDatetime","processResponseDates","item","processed","key","isAbsoluteUrl","url","joinBaseUrl","baseURL","b","u","encodeQuery","params","entries","v","URLSearchParamsCtor","q","sp","k","appendParamsToUrl","readEnvBaseUrl","env","resolveUrl","config","options","raw","withBase","getMiniProgramRequest","g","callMaybePromiseRequest","fn","ret","resolve","reject","res","err","mergeHeaders","base","extra","out","taroLikeAdapter","req","method","header","isAxiosInstance","createHttpClient","axiosInstanceOrOptions","instance","adapterChoice","adapter","r","resp","unwrappedData","error_","error","details"],"mappings":"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","file":"index.cjs","sourcesContent":["/* eslint-disable no-unused-vars */\nimport type { AxiosInstance, AxiosRequestConfig } from \"axios\";\n\nexport type ClientError = {\n message: string;\n status?: number;\n code?: string;\n details?: unknown;\n};\n\nexport type ClientResult<T> = {\n data: T | null;\n error: ClientError | null;\n status: number;\n};\n\nexport type RequestConfig = AxiosRequestConfig & {\n url: string;\n method: NonNullable<AxiosRequestConfig[\"method\"]> | string;\n};\n\nexport type AdapterResponse = {\n status: number;\n data: unknown;\n headers?: unknown;\n};\n\nexport type HttpAdapter = (_config: RequestConfig) => Promise<AdapterResponse>;\n\nexport type HttpClientOptions = {\n /**\n * - \"axios\": force axios (default, keeps backward compatible behavior)\n * - \"taro\": force mini-program request (wx/tt/my/...) or global Taro.request if present\n * - function: custom adapter\n */\n adapter?: \"taro\" | \"axios\" | HttpAdapter;\n /**\n * Base URL to prefix when `config.url` is relative (e.g. \"/api/...\").\n * For Taro/mini-program, relative URLs are usually invalid, so you should set this.\n */\n baseURL?: string;\n /** Default headers merged into each request */\n headers?: Record<string, string>;\n};\n\nexport type HttpClient = {\n request<T>(\n _config: RequestConfig\n ): Promise<ClientResult<T>>;\n};\n\ninterface ErrorPayload {\n message?: string;\n error?: string;\n msg?: string;\n detail?: string;\n}\n\nfunction normalizeErrorMessage(payload: unknown): string {\n if (!payload) {\n return \"Request failed\";\n }\n if (typeof payload === \"string\") {\n return payload;\n }\n if (typeof payload === \"object\") {\n const errorPayload = payload as ErrorPayload;\n return (\n errorPayload.message ||\n errorPayload.error ||\n errorPayload.msg ||\n errorPayload.detail ||\n \"Request failed\"\n );\n }\n return \"Request failed\";\n}\n\ninterface BackendStandardResponse {\n status: number | string;\n data: unknown;\n}\n\n/**\n * Check if response data matches backend standard format: { status: 0/1, data: {...} }\n * Handles both number and string status values\n */\nfunction isBackendStandardFormat(data: unknown): data is BackendStandardResponse {\n if (!data || typeof data !== \"object\" || !(\"data\" in data)) {\n return false;\n }\n\n // Check status field - handle both number and string values\n if (\"status\" in data) {\n const status = (data as BackendStandardResponse).status;\n // Accept 0, 1, \"0\", \"1\" as valid status values\n return status === 0 || status === 1 || status === \"0\" || status === \"1\";\n }\n\n return false;\n}\n\n/**\n * Unwrap backend standard format response\n * Backend returns: { status: 0, data: {...} }\n * We extract the inner 'data' field for cleaner client usage\n */\nfunction unwrapBackendResponse<T>(responseData: unknown): T {\n if (isBackendStandardFormat(responseData)) {\n // Extract inner data field\n return responseData.data as T;\n }\n // Return as-is if not standard format (e.g., BPM/Workflow APIs)\n return responseData as T;\n}\n\n/**\n * Backend datetime format regex: \"YYYY-MM-DD HH:MM:SS\"\n */\nconst BACKEND_DATETIME_REGEX = /^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}$/;\n\n/**\n * Check if a string matches backend datetime format\n */\nfunction isBackendDatetime(value: string): boolean {\n return BACKEND_DATETIME_REGEX.test(value);\n}\n\n/**\n * Convert backend datetime string to ISO 8601 format\n * \"2026-01-05 10:30:45\" → \"2026-01-05T10:30:45.000Z\"\n */\nfunction parseBackendDatetime(value: string): string {\n // Replace space with T and append Z for UTC\n return `${value.replace(\" \", \"T\")}.000Z`;\n}\n\n/**\n * Recursively process response data to convert backend datetime strings to ISO format\n * Handles nested objects and arrays\n */\nfunction processResponseDates(data: unknown): unknown {\n if (data === null || data === undefined) {\n return data;\n }\n\n // Handle arrays\n if (Array.isArray(data)) {\n return data.map((item) => processResponseDates(item));\n }\n\n // Handle objects\n if (typeof data === \"object\") {\n const processed: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(data)) {\n processed[key] = processResponseDates(value);\n }\n return processed;\n }\n\n // Handle backend datetime strings\n if (typeof data === \"string\" && isBackendDatetime(data)) {\n return parseBackendDatetime(data);\n }\n\n return data;\n}\n\nfunction isAbsoluteUrl(url: string): boolean {\n return /^https?:\\/\\//i.test(url);\n}\n\nfunction joinBaseUrl(baseURL: string, url: string): string {\n const b = baseURL.replace(/\\/+$/, \"\");\n const u = url.startsWith(\"/\") ? url : `/${url}`;\n return `${b}${u}`;\n}\n\nfunction encodeQuery(params: unknown): string {\n if (!params || typeof params !== \"object\") return \"\";\n const entries = Object.entries(params as Record<string, unknown>).filter(\n ([, v]) => v !== undefined && v !== null\n );\n if (entries.length === 0) return \"\";\n const URLSearchParamsCtor = (globalThis as any)?.URLSearchParams as\n | (new () => { append: (k: string, v: string) => void; toString: () => string })\n | undefined;\n\n let q = \"\";\n if (URLSearchParamsCtor) {\n const sp = new URLSearchParamsCtor();\n for (const [k, v] of entries) {\n if (Array.isArray(v)) {\n for (const item of v) sp.append(k, String(item));\n } else {\n sp.append(k, String(v));\n }\n }\n q = sp.toString();\n } else {\n // Minimal fallback (older runtimes): k=v&k=v...\n q = entries\n .flatMap(([k, v]) =>\n Array.isArray(v) ? v.map((item) => [k, item] as const) : ([[k, v]] as const)\n )\n .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(String(v))}`)\n .join(\"&\");\n }\n return q ? `?${q}` : \"\";\n}\n\nfunction appendParamsToUrl(url: string, params: unknown): string {\n const q = encodeQuery(params);\n if (!q) return url;\n if (url.includes(\"?\")) return `${url}&${q.slice(1)}`;\n return `${url}${q}`;\n}\n\nfunction readEnvBaseUrl(): string {\n const p = (globalThis as any)?.process;\n const env = p?.env;\n const value =\n (env?.API_BASE_URL as string | undefined) ||\n (env?.TARO_APP_API_BASE_URL as string | undefined) ||\n (env?.VITE_API_BASE_URL as string | undefined) ||\n \"\";\n return String(value || \"\").trim();\n}\n\nfunction resolveUrl(config: RequestConfig, options?: HttpClientOptions): string {\n const raw = String(config.url || \"\");\n if (isAbsoluteUrl(raw)) return appendParamsToUrl(raw, (config as any).params);\n\n const baseURL =\n String((config as any).baseURL || options?.baseURL || readEnvBaseUrl() || \"\").trim();\n const withBase = baseURL ? joinBaseUrl(baseURL, raw) : raw;\n return appendParamsToUrl(withBase, (config as any).params);\n}\n\nfunction getMiniProgramRequest():\n | ((_options: any) => any)\n | null {\n const g: any = globalThis as any;\n if (typeof g?.Taro?.request === \"function\") return g.Taro.request.bind(g.Taro);\n if (typeof g?.wx?.request === \"function\") return g.wx.request.bind(g.wx);\n if (typeof g?.tt?.request === \"function\") return g.tt.request.bind(g.tt);\n if (typeof g?.my?.request === \"function\") return g.my.request.bind(g.my);\n if (typeof g?.swan?.request === \"function\") return g.swan.request.bind(g.swan);\n if (typeof g?.qq?.request === \"function\") return g.qq.request.bind(g.qq);\n if (typeof g?.jd?.request === \"function\") return g.jd.request.bind(g.jd);\n return null;\n}\n\nasync function callMaybePromiseRequest(fn: (options: any) => any, options: any): Promise<any> {\n try {\n const ret = fn(options);\n if (ret && typeof ret.then === \"function\") {\n return await ret;\n }\n } catch {\n // fall through to callback-style below\n }\n\n return await new Promise((resolve, reject) => {\n fn({\n ...options,\n success: (res: any) => resolve(res),\n fail: (err: any) => reject(err),\n });\n });\n}\n\nfunction mergeHeaders(\n base: Record<string, string> | undefined,\n extra: unknown\n): Record<string, string> {\n const out: Record<string, string> = { ...(base || {}) };\n if (!extra) return out;\n if (typeof extra === \"object\") {\n for (const [k, v] of Object.entries(extra as Record<string, unknown>)) {\n if (v === undefined || v === null) continue;\n out[k] = String(v);\n }\n }\n return out;\n}\n\nasync function taroLikeAdapter(config: RequestConfig, options?: HttpClientOptions): Promise<AdapterResponse> {\n const req = getMiniProgramRequest();\n if (!req) {\n throw new Error(\"Mini-program request API not found (wx/tt/my/... or global Taro.request).\");\n }\n const url = resolveUrl(config, options);\n const method = String(config.method || \"GET\").toUpperCase();\n const header = mergeHeaders(options?.headers, (config as any).headers);\n\n const res = await callMaybePromiseRequest(req, {\n url,\n method,\n header,\n data: (config as any).data,\n });\n\n const status = (res?.statusCode ?? res?.status ?? 0) as number;\n return { status, data: res?.data, headers: res?.header };\n}\n\nfunction isAxiosInstance(value: unknown): value is AxiosInstance {\n const v: any = value as any;\n // axios instance is callable and has defaults + interceptors\n return typeof v === \"function\" && !!v?.defaults && !!v?.interceptors;\n}\n\n/**\n * Create an HTTP client instance\n * \n * @param axiosInstance - Optional axios instance to use (defaults to a basic axios instance)\n * @returns HttpClient with request method\n * \n * @example\n * ```typescript\n * import axios from \"axios\";\n * import { createHttpClient } from \"@amaster.ai/http-client\";\n * \n * const instance = axios.create({ baseURL: \"https://api.example.com\" });\n * const client = createHttpClient(instance);\n * \n * const result = await client.request({\n * url: \"/users\",\n * method: \"get\",\n * });\n * ```\n */\nexport function createHttpClient(axiosInstanceOrOptions?: AxiosInstance | HttpClientOptions): HttpClient {\n // Import axios dynamically to avoid bundling it\n let instance: AxiosInstance | undefined;\n let options: HttpClientOptions | undefined;\n\n if (isAxiosInstance(axiosInstanceOrOptions)) {\n instance = axiosInstanceOrOptions;\n } else {\n options = axiosInstanceOrOptions;\n }\n\n // Default to axios to preserve original behavior.\n // Taro/mini-program environments must explicitly opt-in via { adapter: \"taro\" }.\n const adapterChoice = options?.adapter ?? \"axios\";\n \n return {\n async request<T>(\n config: RequestConfig\n ) {\n try {\n let status = 0;\n let responseData: unknown = null;\n\n const adapter =\n typeof adapterChoice === \"function\" ? adapterChoice :\n adapterChoice === \"taro\" ? \"taro\" :\n \"axios\";\n\n if (typeof adapter === \"function\") {\n const r = await adapter(config);\n status = r.status ?? 0;\n responseData = r.data ?? null;\n } else if (adapter === \"taro\") {\n const r = await taroLikeAdapter(config, options);\n status = r.status ?? 0;\n responseData = r.data ?? null;\n } else {\n // axios path\n if (!instance) {\n const axios = await import(\"axios\");\n instance = axios.default.create();\n }\n const resp = await instance(config as any);\n status = resp?.status ?? 0;\n responseData = resp?.data;\n }\n\n if (status >= 200 && status < 300) {\n // Unwrap backend standard format: { status: 0, data: {...} } -> {...}\n const unwrappedData = unwrapBackendResponse<T>(responseData);\n // Convert backend datetime strings to ISO format\n const processedData = processResponseDates(unwrappedData);\n return { data: (processedData ?? null) as T | null, error: null, status };\n }\n\n return {\n data: null,\n error: {\n status,\n message: normalizeErrorMessage(responseData) || `HTTP ${status}`,\n details: responseData,\n },\n status,\n };\n } catch (error_: unknown) {\n // Catch network errors, timeouts, and other exceptions\n const error = error_ as any;\n const status = error?.response?.status || error?.statusCode || 0;\n const details = error?.response?.data ?? error?.data;\n return {\n data: null,\n error: {\n status,\n message:\n normalizeErrorMessage(details) || error?.message || \"Network error\",\n details,\n },\n status,\n };\n }\n },\n };\n}\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -11,11 +11,33 @@ type ClientResult<T> = {
|
|
|
11
11
|
error: ClientError | null;
|
|
12
12
|
status: number;
|
|
13
13
|
};
|
|
14
|
+
type RequestConfig = AxiosRequestConfig & {
|
|
15
|
+
url: string;
|
|
16
|
+
method: NonNullable<AxiosRequestConfig["method"]> | string;
|
|
17
|
+
};
|
|
18
|
+
type AdapterResponse = {
|
|
19
|
+
status: number;
|
|
20
|
+
data: unknown;
|
|
21
|
+
headers?: unknown;
|
|
22
|
+
};
|
|
23
|
+
type HttpAdapter = (_config: RequestConfig) => Promise<AdapterResponse>;
|
|
24
|
+
type HttpClientOptions = {
|
|
25
|
+
/**
|
|
26
|
+
* - "axios": force axios (default, keeps backward compatible behavior)
|
|
27
|
+
* - "taro": force mini-program request (wx/tt/my/...) or global Taro.request if present
|
|
28
|
+
* - function: custom adapter
|
|
29
|
+
*/
|
|
30
|
+
adapter?: "taro" | "axios" | HttpAdapter;
|
|
31
|
+
/**
|
|
32
|
+
* Base URL to prefix when `config.url` is relative (e.g. "/api/...").
|
|
33
|
+
* For Taro/mini-program, relative URLs are usually invalid, so you should set this.
|
|
34
|
+
*/
|
|
35
|
+
baseURL?: string;
|
|
36
|
+
/** Default headers merged into each request */
|
|
37
|
+
headers?: Record<string, string>;
|
|
38
|
+
};
|
|
14
39
|
type HttpClient = {
|
|
15
|
-
request<T>(
|
|
16
|
-
url: string;
|
|
17
|
-
method: NonNullable<AxiosRequestConfig["method"]>;
|
|
18
|
-
}): Promise<ClientResult<T>>;
|
|
40
|
+
request<T>(_config: RequestConfig): Promise<ClientResult<T>>;
|
|
19
41
|
};
|
|
20
42
|
/**
|
|
21
43
|
* Create an HTTP client instance
|
|
@@ -37,6 +59,6 @@ type HttpClient = {
|
|
|
37
59
|
* });
|
|
38
60
|
* ```
|
|
39
61
|
*/
|
|
40
|
-
declare function createHttpClient(
|
|
62
|
+
declare function createHttpClient(axiosInstanceOrOptions?: AxiosInstance | HttpClientOptions): HttpClient;
|
|
41
63
|
|
|
42
|
-
export { type ClientError, type ClientResult, type HttpClient, createHttpClient };
|
|
64
|
+
export { type AdapterResponse, type ClientError, type ClientResult, type HttpAdapter, type HttpClient, type HttpClientOptions, type RequestConfig, createHttpClient };
|
package/dist/index.d.ts
CHANGED
|
@@ -11,11 +11,33 @@ type ClientResult<T> = {
|
|
|
11
11
|
error: ClientError | null;
|
|
12
12
|
status: number;
|
|
13
13
|
};
|
|
14
|
+
type RequestConfig = AxiosRequestConfig & {
|
|
15
|
+
url: string;
|
|
16
|
+
method: NonNullable<AxiosRequestConfig["method"]> | string;
|
|
17
|
+
};
|
|
18
|
+
type AdapterResponse = {
|
|
19
|
+
status: number;
|
|
20
|
+
data: unknown;
|
|
21
|
+
headers?: unknown;
|
|
22
|
+
};
|
|
23
|
+
type HttpAdapter = (_config: RequestConfig) => Promise<AdapterResponse>;
|
|
24
|
+
type HttpClientOptions = {
|
|
25
|
+
/**
|
|
26
|
+
* - "axios": force axios (default, keeps backward compatible behavior)
|
|
27
|
+
* - "taro": force mini-program request (wx/tt/my/...) or global Taro.request if present
|
|
28
|
+
* - function: custom adapter
|
|
29
|
+
*/
|
|
30
|
+
adapter?: "taro" | "axios" | HttpAdapter;
|
|
31
|
+
/**
|
|
32
|
+
* Base URL to prefix when `config.url` is relative (e.g. "/api/...").
|
|
33
|
+
* For Taro/mini-program, relative URLs are usually invalid, so you should set this.
|
|
34
|
+
*/
|
|
35
|
+
baseURL?: string;
|
|
36
|
+
/** Default headers merged into each request */
|
|
37
|
+
headers?: Record<string, string>;
|
|
38
|
+
};
|
|
14
39
|
type HttpClient = {
|
|
15
|
-
request<T>(
|
|
16
|
-
url: string;
|
|
17
|
-
method: NonNullable<AxiosRequestConfig["method"]>;
|
|
18
|
-
}): Promise<ClientResult<T>>;
|
|
40
|
+
request<T>(_config: RequestConfig): Promise<ClientResult<T>>;
|
|
19
41
|
};
|
|
20
42
|
/**
|
|
21
43
|
* Create an HTTP client instance
|
|
@@ -37,6 +59,6 @@ type HttpClient = {
|
|
|
37
59
|
* });
|
|
38
60
|
* ```
|
|
39
61
|
*/
|
|
40
|
-
declare function createHttpClient(
|
|
62
|
+
declare function createHttpClient(axiosInstanceOrOptions?: AxiosInstance | HttpClientOptions): HttpClient;
|
|
41
63
|
|
|
42
|
-
export { type ClientError, type ClientResult, type HttpClient, createHttpClient };
|
|
64
|
+
export { type AdapterResponse, type ClientError, type ClientResult, type HttpAdapter, type HttpClient, type HttpClientOptions, type RequestConfig, createHttpClient };
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
function
|
|
1
|
+
function f(t){if(!t)return "Request failed";if(typeof t=="string")return t;if(typeof t=="object"){let e=t;return e.message||e.error||e.msg||e.detail||"Request failed"}return "Request failed"}function l(t){if(!t||typeof t!="object"||!("data"in t))return false;if("status"in t){let e=t.status;return e===0||e===1||e==="0"||e==="1"}return false}function g(t){return l(t)?t.data:t}var y=/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/;function m(t){return y.test(t)}function R(t){return `${t.replace(" ","T")}.000Z`}function c(t){if(t==null)return t;if(Array.isArray(t))return t.map(e=>c(e));if(typeof t=="object"){let e={};for(let[n,i]of Object.entries(t))e[n]=c(i);return e}return typeof t=="string"&&m(t)?R(t):t}function q(t){return /^https?:\/\//i.test(t)}function w(t,e){let n=t.replace(/\/+$/,""),i=e.startsWith("/")?e:`/${e}`;return `${n}${i}`}function C(t){if(!t||typeof t!="object")return "";let e=Object.entries(t).filter(([,r])=>r!=null);if(e.length===0)return "";let n=globalThis?.URLSearchParams,i="";if(n){let r=new n;for(let[o,s]of e)if(Array.isArray(s))for(let u of s)r.append(o,String(u));else r.append(o,String(s));i=r.toString();}else i=e.flatMap(([r,o])=>Array.isArray(o)?o.map(s=>[r,s]):[[r,o]]).map(([r,o])=>`${encodeURIComponent(r)}=${encodeURIComponent(String(o))}`).join("&");return i?`?${i}`:""}function d(t,e){let n=C(e);return n?t.includes("?")?`${t}&${n.slice(1)}`:`${t}${n}`:t}function b(){let e=globalThis?.process?.env,n=e?.API_BASE_URL||e?.TARO_APP_API_BASE_URL||e?.VITE_API_BASE_URL||"";return String(n||"").trim()}function A(t,e){let n=String(t.url||"");if(q(n))return d(n,t.params);let i=String(t.baseURL||e?.baseURL||b()||"").trim(),r=i?w(i,n):n;return d(r,t.params)}function k(){let t=globalThis;return typeof t?.Taro?.request=="function"?t.Taro.request.bind(t.Taro):typeof t?.wx?.request=="function"?t.wx.request.bind(t.wx):typeof t?.tt?.request=="function"?t.tt.request.bind(t.tt):typeof t?.my?.request=="function"?t.my.request.bind(t.my):typeof t?.swan?.request=="function"?t.swan.request.bind(t.swan):typeof t?.qq?.request=="function"?t.qq.request.bind(t.qq):typeof t?.jd?.request=="function"?t.jd.request.bind(t.jd):null}async function T(t,e){try{let n=t(e);if(n&&typeof n.then=="function")return await n}catch{}return await new Promise((n,i)=>{t({...e,success:r=>n(r),fail:r=>i(r)});})}function h(t,e){let n={...t||{}};if(!e)return n;if(typeof e=="object")for(let[i,r]of Object.entries(e))r!=null&&(n[i]=String(r));return n}async function x(t,e){let n=k();if(!n)throw new Error("Mini-program request API not found (wx/tt/my/... or global Taro.request).");let i=A(t,e),r=String(t.method||"GET").toUpperCase(),o=h(e?.headers,t.headers),s=await T(n,{url:i,method:r,header:o,data:t.data});return {status:s?.statusCode??s?.status??0,data:s?.data,headers:s?.header}}function P(t){let e=t;return typeof e=="function"&&!!e?.defaults&&!!e?.interceptors}function S(t){let e,n;P(t)?e=t:n=t;let i=n?.adapter??"axios";return {async request(r){try{let o=0,s=null,u=typeof i=="function"?i:i==="taro"?"taro":"axios";if(typeof u=="function"){let a=await u(r);o=a.status??0,s=a.data??null;}else if(u==="taro"){let a=await x(r,n);o=a.status??0,s=a.data??null;}else {e||(e=(await import('axios')).default.create());let a=await e(r);o=a?.status??0,s=a?.data;}if(o>=200&&o<300){let a=g(s);return {data:c(a)??null,error:null,status:o}}return {data:null,error:{status:o,message:f(s)||`HTTP ${o}`,details:s},status:o}}catch(o){let s=o,u=s?.response?.status||s?.statusCode||0,a=s?.response?.data??s?.data;return {data:null,error:{status:u,message:f(a)||s?.message||"Network error",details:a},status:u}}}}}
|
|
2
|
+
export{S as createHttpClient};//# sourceMappingURL=index.js.map
|
|
2
3
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/http.ts"],"names":["normalizeErrorMessage","payload","errorPayload","isBackendStandardFormat","data","status","unwrapBackendResponse","responseData","BACKEND_DATETIME_REGEX","isBackendDatetime","value","parseBackendDatetime","processResponseDates","item","processed","key","createHttpClient","axiosInstance","instance","config","resp","unwrappedData","error_","error"],"mappings":"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","file":"index.js","sourcesContent":["import type { AxiosInstance, AxiosRequestConfig } from \"axios\";\n\nexport type ClientError = {\n message: string;\n status?: number;\n code?: string;\n details?: unknown;\n};\n\nexport type ClientResult<T> = {\n data: T | null;\n error: ClientError | null;\n status: number;\n};\n\nexport type HttpClient = {\n request<T>(\n config: AxiosRequestConfig & {\n url: string;\n method: NonNullable<AxiosRequestConfig[\"method\"]>;\n }\n ): Promise<ClientResult<T>>;\n};\n\ninterface ErrorPayload {\n message?: string;\n error?: string;\n msg?: string;\n detail?: string;\n}\n\nfunction normalizeErrorMessage(payload: unknown): string {\n if (!payload) {\n return \"Request failed\";\n }\n if (typeof payload === \"string\") {\n return payload;\n }\n if (typeof payload === \"object\") {\n const errorPayload = payload as ErrorPayload;\n return (\n errorPayload.message ||\n errorPayload.error ||\n errorPayload.msg ||\n errorPayload.detail ||\n \"Request failed\"\n );\n }\n return \"Request failed\";\n}\n\ninterface BackendStandardResponse {\n status: number | string;\n data: unknown;\n}\n\n/**\n * Check if response data matches backend standard format: { status: 0/1, data: {...} }\n * Handles both number and string status values\n */\nfunction isBackendStandardFormat(data: unknown): data is BackendStandardResponse {\n if (!data || typeof data !== \"object\" || !(\"data\" in data)) {\n return false;\n }\n\n // Check status field - handle both number and string values\n if (\"status\" in data) {\n const status = (data as BackendStandardResponse).status;\n // Accept 0, 1, \"0\", \"1\" as valid status values\n return status === 0 || status === 1 || status === \"0\" || status === \"1\";\n }\n\n return false;\n}\n\n/**\n * Unwrap backend standard format response\n * Backend returns: { status: 0, data: {...} }\n * We extract the inner 'data' field for cleaner client usage\n */\nfunction unwrapBackendResponse<T>(responseData: unknown): T {\n if (isBackendStandardFormat(responseData)) {\n // Extract inner data field\n return responseData.data as T;\n }\n // Return as-is if not standard format (e.g., BPM/Workflow APIs)\n return responseData as T;\n}\n\n/**\n * Backend datetime format regex: \"YYYY-MM-DD HH:MM:SS\"\n */\nconst BACKEND_DATETIME_REGEX = /^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}$/;\n\n/**\n * Check if a string matches backend datetime format\n */\nfunction isBackendDatetime(value: string): boolean {\n return BACKEND_DATETIME_REGEX.test(value);\n}\n\n/**\n * Convert backend datetime string to ISO 8601 format\n * \"2026-01-05 10:30:45\" → \"2026-01-05T10:30:45.000Z\"\n */\nfunction parseBackendDatetime(value: string): string {\n // Replace space with T and append Z for UTC\n return `${value.replace(\" \", \"T\")}.000Z`;\n}\n\n/**\n * Recursively process response data to convert backend datetime strings to ISO format\n * Handles nested objects and arrays\n */\nfunction processResponseDates(data: unknown): unknown {\n if (data === null || data === undefined) {\n return data;\n }\n\n // Handle arrays\n if (Array.isArray(data)) {\n return data.map((item) => processResponseDates(item));\n }\n\n // Handle objects\n if (typeof data === \"object\") {\n const processed: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(data)) {\n processed[key] = processResponseDates(value);\n }\n return processed;\n }\n\n // Handle backend datetime strings\n if (typeof data === \"string\" && isBackendDatetime(data)) {\n return parseBackendDatetime(data);\n }\n\n return data;\n}\n\n/**\n * Create an HTTP client instance\n * \n * @param axiosInstance - Optional axios instance to use (defaults to a basic axios instance)\n * @returns HttpClient with request method\n * \n * @example\n * ```typescript\n * import axios from \"axios\";\n * import { createHttpClient } from \"@amaster.ai/http-client\";\n * \n * const instance = axios.create({ baseURL: \"https://api.example.com\" });\n * const client = createHttpClient(instance);\n * \n * const result = await client.request({\n * url: \"/users\",\n * method: \"get\",\n * });\n * ```\n */\nexport function createHttpClient(axiosInstance?: AxiosInstance): HttpClient {\n // Import axios dynamically to avoid bundling it\n let instance = axiosInstance;\n \n return {\n async request<T>(\n config: AxiosRequestConfig & {\n url: string;\n method: NonNullable<AxiosRequestConfig[\"method\"]>;\n }\n ) {\n // Lazy load axios if not provided\n if (!instance) {\n const axios = await import(\"axios\");\n instance = axios.default.create();\n }\n\n try {\n const resp = await instance(config);\n const status = resp?.status ?? 0;\n\n if (status >= 200 && status < 300) {\n // Unwrap backend standard format: { status: 0, data: {...} } -> {...}\n const unwrappedData = unwrapBackendResponse<T>(resp?.data);\n // Convert backend datetime strings to ISO format\n const processedData = processResponseDates(unwrappedData);\n return { data: (processedData ?? null) as T | null, error: null, status };\n }\n\n return {\n data: null,\n error: {\n status,\n message: normalizeErrorMessage(resp?.data) || `HTTP ${status}`,\n details: resp?.data,\n },\n status,\n };\n } catch (error_: unknown) {\n // Catch network errors, timeouts, and other axios exceptions\n const error = error_ as {\n response?: { status?: number; data?: unknown };\n message?: string;\n };\n const status = error.response?.status || 0;\n return {\n data: null,\n error: {\n status,\n message:\n normalizeErrorMessage(error.response?.data) || error.message || \"Network error\",\n details: error.response?.data,\n },\n status,\n };\n }\n },\n };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/http.ts"],"names":["normalizeErrorMessage","payload","errorPayload","isBackendStandardFormat","data","status","unwrapBackendResponse","responseData","BACKEND_DATETIME_REGEX","isBackendDatetime","value","parseBackendDatetime","processResponseDates","item","processed","key","isAbsoluteUrl","url","joinBaseUrl","baseURL","b","u","encodeQuery","params","entries","v","URLSearchParamsCtor","q","sp","k","appendParamsToUrl","readEnvBaseUrl","env","resolveUrl","config","options","raw","withBase","getMiniProgramRequest","g","callMaybePromiseRequest","fn","ret","resolve","reject","res","err","mergeHeaders","base","extra","out","taroLikeAdapter","req","method","header","isAxiosInstance","createHttpClient","axiosInstanceOrOptions","instance","adapterChoice","adapter","r","resp","unwrappedData","error_","error","details"],"mappings":"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","file":"index.js","sourcesContent":["/* eslint-disable no-unused-vars */\nimport type { AxiosInstance, AxiosRequestConfig } from \"axios\";\n\nexport type ClientError = {\n message: string;\n status?: number;\n code?: string;\n details?: unknown;\n};\n\nexport type ClientResult<T> = {\n data: T | null;\n error: ClientError | null;\n status: number;\n};\n\nexport type RequestConfig = AxiosRequestConfig & {\n url: string;\n method: NonNullable<AxiosRequestConfig[\"method\"]> | string;\n};\n\nexport type AdapterResponse = {\n status: number;\n data: unknown;\n headers?: unknown;\n};\n\nexport type HttpAdapter = (_config: RequestConfig) => Promise<AdapterResponse>;\n\nexport type HttpClientOptions = {\n /**\n * - \"axios\": force axios (default, keeps backward compatible behavior)\n * - \"taro\": force mini-program request (wx/tt/my/...) or global Taro.request if present\n * - function: custom adapter\n */\n adapter?: \"taro\" | \"axios\" | HttpAdapter;\n /**\n * Base URL to prefix when `config.url` is relative (e.g. \"/api/...\").\n * For Taro/mini-program, relative URLs are usually invalid, so you should set this.\n */\n baseURL?: string;\n /** Default headers merged into each request */\n headers?: Record<string, string>;\n};\n\nexport type HttpClient = {\n request<T>(\n _config: RequestConfig\n ): Promise<ClientResult<T>>;\n};\n\ninterface ErrorPayload {\n message?: string;\n error?: string;\n msg?: string;\n detail?: string;\n}\n\nfunction normalizeErrorMessage(payload: unknown): string {\n if (!payload) {\n return \"Request failed\";\n }\n if (typeof payload === \"string\") {\n return payload;\n }\n if (typeof payload === \"object\") {\n const errorPayload = payload as ErrorPayload;\n return (\n errorPayload.message ||\n errorPayload.error ||\n errorPayload.msg ||\n errorPayload.detail ||\n \"Request failed\"\n );\n }\n return \"Request failed\";\n}\n\ninterface BackendStandardResponse {\n status: number | string;\n data: unknown;\n}\n\n/**\n * Check if response data matches backend standard format: { status: 0/1, data: {...} }\n * Handles both number and string status values\n */\nfunction isBackendStandardFormat(data: unknown): data is BackendStandardResponse {\n if (!data || typeof data !== \"object\" || !(\"data\" in data)) {\n return false;\n }\n\n // Check status field - handle both number and string values\n if (\"status\" in data) {\n const status = (data as BackendStandardResponse).status;\n // Accept 0, 1, \"0\", \"1\" as valid status values\n return status === 0 || status === 1 || status === \"0\" || status === \"1\";\n }\n\n return false;\n}\n\n/**\n * Unwrap backend standard format response\n * Backend returns: { status: 0, data: {...} }\n * We extract the inner 'data' field for cleaner client usage\n */\nfunction unwrapBackendResponse<T>(responseData: unknown): T {\n if (isBackendStandardFormat(responseData)) {\n // Extract inner data field\n return responseData.data as T;\n }\n // Return as-is if not standard format (e.g., BPM/Workflow APIs)\n return responseData as T;\n}\n\n/**\n * Backend datetime format regex: \"YYYY-MM-DD HH:MM:SS\"\n */\nconst BACKEND_DATETIME_REGEX = /^\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}$/;\n\n/**\n * Check if a string matches backend datetime format\n */\nfunction isBackendDatetime(value: string): boolean {\n return BACKEND_DATETIME_REGEX.test(value);\n}\n\n/**\n * Convert backend datetime string to ISO 8601 format\n * \"2026-01-05 10:30:45\" → \"2026-01-05T10:30:45.000Z\"\n */\nfunction parseBackendDatetime(value: string): string {\n // Replace space with T and append Z for UTC\n return `${value.replace(\" \", \"T\")}.000Z`;\n}\n\n/**\n * Recursively process response data to convert backend datetime strings to ISO format\n * Handles nested objects and arrays\n */\nfunction processResponseDates(data: unknown): unknown {\n if (data === null || data === undefined) {\n return data;\n }\n\n // Handle arrays\n if (Array.isArray(data)) {\n return data.map((item) => processResponseDates(item));\n }\n\n // Handle objects\n if (typeof data === \"object\") {\n const processed: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(data)) {\n processed[key] = processResponseDates(value);\n }\n return processed;\n }\n\n // Handle backend datetime strings\n if (typeof data === \"string\" && isBackendDatetime(data)) {\n return parseBackendDatetime(data);\n }\n\n return data;\n}\n\nfunction isAbsoluteUrl(url: string): boolean {\n return /^https?:\\/\\//i.test(url);\n}\n\nfunction joinBaseUrl(baseURL: string, url: string): string {\n const b = baseURL.replace(/\\/+$/, \"\");\n const u = url.startsWith(\"/\") ? url : `/${url}`;\n return `${b}${u}`;\n}\n\nfunction encodeQuery(params: unknown): string {\n if (!params || typeof params !== \"object\") return \"\";\n const entries = Object.entries(params as Record<string, unknown>).filter(\n ([, v]) => v !== undefined && v !== null\n );\n if (entries.length === 0) return \"\";\n const URLSearchParamsCtor = (globalThis as any)?.URLSearchParams as\n | (new () => { append: (k: string, v: string) => void; toString: () => string })\n | undefined;\n\n let q = \"\";\n if (URLSearchParamsCtor) {\n const sp = new URLSearchParamsCtor();\n for (const [k, v] of entries) {\n if (Array.isArray(v)) {\n for (const item of v) sp.append(k, String(item));\n } else {\n sp.append(k, String(v));\n }\n }\n q = sp.toString();\n } else {\n // Minimal fallback (older runtimes): k=v&k=v...\n q = entries\n .flatMap(([k, v]) =>\n Array.isArray(v) ? v.map((item) => [k, item] as const) : ([[k, v]] as const)\n )\n .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(String(v))}`)\n .join(\"&\");\n }\n return q ? `?${q}` : \"\";\n}\n\nfunction appendParamsToUrl(url: string, params: unknown): string {\n const q = encodeQuery(params);\n if (!q) return url;\n if (url.includes(\"?\")) return `${url}&${q.slice(1)}`;\n return `${url}${q}`;\n}\n\nfunction readEnvBaseUrl(): string {\n const p = (globalThis as any)?.process;\n const env = p?.env;\n const value =\n (env?.API_BASE_URL as string | undefined) ||\n (env?.TARO_APP_API_BASE_URL as string | undefined) ||\n (env?.VITE_API_BASE_URL as string | undefined) ||\n \"\";\n return String(value || \"\").trim();\n}\n\nfunction resolveUrl(config: RequestConfig, options?: HttpClientOptions): string {\n const raw = String(config.url || \"\");\n if (isAbsoluteUrl(raw)) return appendParamsToUrl(raw, (config as any).params);\n\n const baseURL =\n String((config as any).baseURL || options?.baseURL || readEnvBaseUrl() || \"\").trim();\n const withBase = baseURL ? joinBaseUrl(baseURL, raw) : raw;\n return appendParamsToUrl(withBase, (config as any).params);\n}\n\nfunction getMiniProgramRequest():\n | ((_options: any) => any)\n | null {\n const g: any = globalThis as any;\n if (typeof g?.Taro?.request === \"function\") return g.Taro.request.bind(g.Taro);\n if (typeof g?.wx?.request === \"function\") return g.wx.request.bind(g.wx);\n if (typeof g?.tt?.request === \"function\") return g.tt.request.bind(g.tt);\n if (typeof g?.my?.request === \"function\") return g.my.request.bind(g.my);\n if (typeof g?.swan?.request === \"function\") return g.swan.request.bind(g.swan);\n if (typeof g?.qq?.request === \"function\") return g.qq.request.bind(g.qq);\n if (typeof g?.jd?.request === \"function\") return g.jd.request.bind(g.jd);\n return null;\n}\n\nasync function callMaybePromiseRequest(fn: (options: any) => any, options: any): Promise<any> {\n try {\n const ret = fn(options);\n if (ret && typeof ret.then === \"function\") {\n return await ret;\n }\n } catch {\n // fall through to callback-style below\n }\n\n return await new Promise((resolve, reject) => {\n fn({\n ...options,\n success: (res: any) => resolve(res),\n fail: (err: any) => reject(err),\n });\n });\n}\n\nfunction mergeHeaders(\n base: Record<string, string> | undefined,\n extra: unknown\n): Record<string, string> {\n const out: Record<string, string> = { ...(base || {}) };\n if (!extra) return out;\n if (typeof extra === \"object\") {\n for (const [k, v] of Object.entries(extra as Record<string, unknown>)) {\n if (v === undefined || v === null) continue;\n out[k] = String(v);\n }\n }\n return out;\n}\n\nasync function taroLikeAdapter(config: RequestConfig, options?: HttpClientOptions): Promise<AdapterResponse> {\n const req = getMiniProgramRequest();\n if (!req) {\n throw new Error(\"Mini-program request API not found (wx/tt/my/... or global Taro.request).\");\n }\n const url = resolveUrl(config, options);\n const method = String(config.method || \"GET\").toUpperCase();\n const header = mergeHeaders(options?.headers, (config as any).headers);\n\n const res = await callMaybePromiseRequest(req, {\n url,\n method,\n header,\n data: (config as any).data,\n });\n\n const status = (res?.statusCode ?? res?.status ?? 0) as number;\n return { status, data: res?.data, headers: res?.header };\n}\n\nfunction isAxiosInstance(value: unknown): value is AxiosInstance {\n const v: any = value as any;\n // axios instance is callable and has defaults + interceptors\n return typeof v === \"function\" && !!v?.defaults && !!v?.interceptors;\n}\n\n/**\n * Create an HTTP client instance\n * \n * @param axiosInstance - Optional axios instance to use (defaults to a basic axios instance)\n * @returns HttpClient with request method\n * \n * @example\n * ```typescript\n * import axios from \"axios\";\n * import { createHttpClient } from \"@amaster.ai/http-client\";\n * \n * const instance = axios.create({ baseURL: \"https://api.example.com\" });\n * const client = createHttpClient(instance);\n * \n * const result = await client.request({\n * url: \"/users\",\n * method: \"get\",\n * });\n * ```\n */\nexport function createHttpClient(axiosInstanceOrOptions?: AxiosInstance | HttpClientOptions): HttpClient {\n // Import axios dynamically to avoid bundling it\n let instance: AxiosInstance | undefined;\n let options: HttpClientOptions | undefined;\n\n if (isAxiosInstance(axiosInstanceOrOptions)) {\n instance = axiosInstanceOrOptions;\n } else {\n options = axiosInstanceOrOptions;\n }\n\n // Default to axios to preserve original behavior.\n // Taro/mini-program environments must explicitly opt-in via { adapter: \"taro\" }.\n const adapterChoice = options?.adapter ?? \"axios\";\n \n return {\n async request<T>(\n config: RequestConfig\n ) {\n try {\n let status = 0;\n let responseData: unknown = null;\n\n const adapter =\n typeof adapterChoice === \"function\" ? adapterChoice :\n adapterChoice === \"taro\" ? \"taro\" :\n \"axios\";\n\n if (typeof adapter === \"function\") {\n const r = await adapter(config);\n status = r.status ?? 0;\n responseData = r.data ?? null;\n } else if (adapter === \"taro\") {\n const r = await taroLikeAdapter(config, options);\n status = r.status ?? 0;\n responseData = r.data ?? null;\n } else {\n // axios path\n if (!instance) {\n const axios = await import(\"axios\");\n instance = axios.default.create();\n }\n const resp = await instance(config as any);\n status = resp?.status ?? 0;\n responseData = resp?.data;\n }\n\n if (status >= 200 && status < 300) {\n // Unwrap backend standard format: { status: 0, data: {...} } -> {...}\n const unwrappedData = unwrapBackendResponse<T>(responseData);\n // Convert backend datetime strings to ISO format\n const processedData = processResponseDates(unwrappedData);\n return { data: (processedData ?? null) as T | null, error: null, status };\n }\n\n return {\n data: null,\n error: {\n status,\n message: normalizeErrorMessage(responseData) || `HTTP ${status}`,\n details: responseData,\n },\n status,\n };\n } catch (error_: unknown) {\n // Catch network errors, timeouts, and other exceptions\n const error = error_ as any;\n const status = error?.response?.status || error?.statusCode || 0;\n const details = error?.response?.data ?? error?.data;\n return {\n data: null,\n error: {\n status,\n message:\n normalizeErrorMessage(details) || error?.message || \"Network error\",\n details,\n },\n status,\n };\n }\n },\n };\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@amaster.ai/http-client",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.4",
|
|
4
4
|
"description": "Base HTTP client with error handling and response unwrapping",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -33,6 +33,11 @@
|
|
|
33
33
|
"peerDependencies": {
|
|
34
34
|
"axios": "^1.11.0"
|
|
35
35
|
},
|
|
36
|
+
"peerDependenciesMeta": {
|
|
37
|
+
"axios": {
|
|
38
|
+
"optional": true
|
|
39
|
+
}
|
|
40
|
+
},
|
|
36
41
|
"devDependencies": {
|
|
37
42
|
"axios": "^1.11.0",
|
|
38
43
|
"tsup": "^8.3.5",
|