@amaster.ai/http-client 1.1.0-beta.43 → 1.1.0-beta.44
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 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
'use strict';function
|
|
2
|
-
\u2192 Details:`,
|
|
1
|
+
'use strict';function w(e){if(!e)return "Request failed";if(typeof e=="string")return e;if(typeof e=="object"){let t=e;return t.message||t.error||t.msg||t.detail||"Request failed"}return "Request failed"}function E(e){if(!e||typeof e!="object"||!("data"in e))return false;if("status"in e){let t=e.status;return t===0||t===1||t==="0"||t==="1"}return false}function x(e){return E(e)?e.data:e}var P=/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/;function S(e){return P.test(e)}function U(e){return `${e.replace(" ","T")}.000Z`}function R(e){if(e==null)return e;if(Array.isArray(e))return e.map(t=>R(t));if(typeof e=="object"){let t={};for(let[n,s]of Object.entries(e))t[n]=R(s);return t}return typeof e=="string"&&S(e)?U(e):e}function _(e){return /^https?:\/\//i.test(e)}function H(e,t){let n=e.replace(/\/+$/,""),s=t.startsWith("/")?t:`/${t}`;return `${n}${s}`}function $(e){if(!e||typeof e!="object")return "";let t=Object.entries(e).filter(([,r])=>r!=null);if(t.length===0)return "";let n=globalThis?.URLSearchParams,s="";if(n){let r=new n;for(let[i,o]of t)if(Array.isArray(o))for(let a of o)r.append(i,String(a));else r.append(i,String(o));s=r.toString();}else s=t.flatMap(([r,i])=>Array.isArray(i)?i.map(o=>[r,o]):[[r,i]]).map(([r,i])=>`${encodeURIComponent(r)}=${encodeURIComponent(String(i))}`).join("&");return s?`?${s}`:""}function b(e,t){let n=$(t);return n?e.includes("?")?`${e}&${n.slice(1)}`:`${e}${n}`:e}function B(){let e="",t=undefined;if(t&&(e=t.TARO_APP_API_BASE_URL||t.VITE_API_BASE_URL||""),!e)try{e=process.env.TARO_APP_API_BASE_URL||process.env.VITE_API_BASE_URL||"";}catch{}return String(e||"").trim()}function I(e,t){let n=String(e.url||"");if(_(n))return b(n,e.params);let s=String(e.baseURL||t?.baseURL||B()||"").trim(),r=s?H(s,n):n;return b(r,e.params)}function A(){let e=globalThis;return typeof e?.Taro?.request=="function"?e.Taro.request.bind(e.Taro):typeof e?.wx?.request=="function"?e.wx.request.bind(e.wx):typeof e?.tt?.request=="function"?e.tt.request.bind(e.tt):typeof e?.my?.request=="function"?e.my.request.bind(e.my):typeof e?.swan?.request=="function"?e.swan.request.bind(e.swan):typeof e?.qq?.request=="function"?e.qq.request.bind(e.qq):typeof e?.jd?.request=="function"?e.jd.request.bind(e.jd):null}async function j(e,t){try{let n=e(t);if(n&&typeof n.then=="function")return await n}catch{}return await new Promise((n,s)=>{e({...t,success:r=>n(r),fail:r=>s(r)});})}function T(e,t){let n={...e||{}};if(!t)return n;if(typeof t=="object")for(let[s,r]of Object.entries(t))r!=null&&(n[s]=String(r));return n}async function v(e,t){let n=A();if(!n)throw new Error("Mini-program request API not found (wx/tt/my/... or global Taro.request).");let s=I(e,t),r=String(e.method||"GET").toUpperCase(),i=T(t?.headers,e.headers),o=await j(n,{url:s,method:r,header:i,data:e.data});return {status:o?.statusCode??o?.status??0,data:o?.data,headers:o?.header}}function C(e){let t=e;return typeof t=="function"&&!!t?.defaults&&!!t?.interceptors}function h(e,t,n,s,r=true){if(!r)return;let i=String(e.method||"GET").toUpperCase(),o=e.url;console.error(`[HTTP Error] ${i} ${o} - ${t} ${n}`,`
|
|
2
|
+
\u2192 Details:`,s);}function L(e){let t,n,s=false;C(e)?(t=e,s=true):(n=e,n?.adapter&&C(n.adapter)&&(t=n.adapter,s=true,n={...n,adapter:void 0}));let r=n?.adapter??(A()?"taro":"axios");return {async request(i){try{let o=i;if("body"in i&&i.body!==void 0){let{body:u,...l}=i;o={...l,data:u};}let a=0,c=null,f=typeof r=="function"?r:r==="taro"?"taro":"axios";if(typeof f=="function"){let u=await f(o);a=u.status??0,c=u.data??null;}else if(f==="taro"){let u=await v(o,n);a=u.status??0,c=u.data??null;}else {t||(t=(await import('axios')).default.create());let u=o;if(s){let y=t.defaults.headers||{},k=o.headers||{},q={};for(let[d,m]of Object.entries(y))d==="common"||d==="get"||d==="post"||d==="put"||d==="patch"||d==="delete"||d==="head"||d==="options"||m!=null&&(q[d]=String(m));u={...o,headers:{...q,...k}};}else n?.headers&&(u={...o,headers:T(n.headers,o.headers)});let l=await t(u);a=l?.status??0,c=l?.data;}if(a>=200&&a<300){let l=(n?.transformResponse??x)(c);return {data:R(l)??null,error:null,status:a}}let p=w(c)||`HTTP ${a}`,g=n?.logErrors!==!1;return h(i,a,p,c,g),{data:null,error:{status:a,message:p,details:c},status:a}}catch(o){let a=o,c=a?.response?.status||a?.statusCode||0,f=a?.response?.data??a?.data,p=w(f)||a?.message||"Network error",g=n?.logErrors!==false;return h(i,c,p,f||a,g),{data:null,error:{status:c,message:p,details:f},status:c}}}}}exports.createHttpClient=L;//# sourceMappingURL=index.cjs.map
|
|
3
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","defaultUnwrapBackendResponse","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","metaEnv","resolveUrl","config","options","raw","withBase","getMiniProgramRequest","g","callMaybePromiseRequest","fn","ret","resolve","reject","res","err","mergeHeaders","base","extra","out","taroLikeAdapter","req","method","header","isAxiosInstance","logErrorToConsole","message","details","shouldLog","createHttpClient","axiosInstanceOrOptions","instance","isUserProvidedInstance","adapterChoice","adapter","r","finalConfig","defaultHeaders","configHeaders","flattenedDefaults","resp","transformedData","errorMessage","error_","error"],"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 * HTTP adapter to use:\n * - undefined: auto-detect (taro if mini-program APIs exist, otherwise axios)\n * - \"taro\": force mini-program request (wx/tt/my/...) or global Taro.request\n * - \"axios\": force axios\n * - AxiosInstance: use provided axios instance\n * - function: custom adapter\n */\n adapter?: \"taro\" | \"axios\" | AxiosInstance | HttpAdapter;\n /**\n * Base URL to prefix when `config.url` is relative (e.g. \"/api/...\").\n * \n * If not provided:\n * - Taro/mini-program: auto-reads from process.env.TARO_APP_API_BASE_URL or process.env.VITE_API_BASE_URL\n * - H5/Browser: no baseURL (expects dev proxy or absolute URLs)\n */\n baseURL?: string;\n /** Default headers merged into each request */\n headers?: Record<string, string>;\n /**\n * Custom response transform function to extract/modify data from backend response\n * If not provided, uses default transform logic for { status: 0/1, data: {...} }\n * \n * Similar to axios's transformResponse option\n * \n * @example\n * ```typescript\n * // For backend that returns: { statusCode: 200, data: {...} }\n * const client = createHttpClient({\n * transformResponse: (response) => {\n * if (response && typeof response === 'object' && 'data' in response) {\n * return response.data;\n * }\n * return response;\n * }\n * });\n * ```\n */\n transformResponse?: <T>(responseData: unknown) => T;\n /**\n * Whether to log errors to console (default: true)\n * Set to false to disable automatic error logging\n */\n logErrors?: boolean;\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 * Default unwrap logic for backend standard format response\n * Backend returns: { status: 0, data: {...} }\n * We extract the inner 'data' field for cleaner client usage\n */\nfunction defaultUnwrapBackendResponse<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 let value = \"\";\n\n // Vite/H5:必须直接写 import.meta.env,Vite 才能正确处理\n const metaEnv = (import.meta as any)?.env;\n if (metaEnv) {\n value = metaEnv.TARO_APP_API_BASE_URL || metaEnv.VITE_API_BASE_URL || \"\";\n }\n\n // Taro 小程序 build:defineConstants 会把 process.env.xxx 替换为字面量\n // H5 环境:process 不存在会抛 ReferenceError,这里用 try/catch 吞掉\n if (!value) {\n try {\n value =\n process.env.TARO_APP_API_BASE_URL ||\n process.env.VITE_API_BASE_URL ||\n \"\";\n } catch {\n // process is not defined (browser) -> ignore\n }\n }\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 * Log error to console with detailed information\n * Only logs if logErrors option is not explicitly set to false\n */\nfunction logErrorToConsole(\n config: RequestConfig,\n status: number,\n message: string,\n details: unknown,\n shouldLog: boolean = true\n): void {\n if (!shouldLog) return;\n\n const method = String(config.method || \"GET\").toUpperCase();\n const url = config.url;\n\n // Format error message with request context\n console.error(\n `[HTTP Error] ${method} ${url} - ${status} ${message}`,\n \"\\n→ Details:\",\n details\n );\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 let isUserProvidedInstance = false;\n\n if (isAxiosInstance(axiosInstanceOrOptions)) {\n instance = axiosInstanceOrOptions;\n isUserProvidedInstance = true;\n } else {\n options = axiosInstanceOrOptions;\n // Check if adapter is an axios instance\n if (options?.adapter && isAxiosInstance(options.adapter)) {\n instance = options.adapter;\n isUserProvidedInstance = true;\n // Remove adapter from options to avoid confusion\n options = { ...options, adapter: undefined };\n }\n }\n\n // Smart default: auto-detect environment\n // - If mini-program APIs exist (wx/tt/my/Taro.request) → use taro adapter\n // - Otherwise → use axios (for H5/browser)\n // User can still explicitly override via { adapter: \"axios\" } or { adapter: \"taro\" }\n const adapterChoice = options?.adapter ?? (getMiniProgramRequest() ? \"taro\" : \"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 \n // Axios behavior: if config.headers is set, it REPLACES defaults.headers\n // We need to manually merge instance defaults with request headers\n let finalConfig: any = config;\n \n if (isUserProvidedInstance) {\n // For user-provided instances, merge defaults.headers with config.headers\n const defaultHeaders = instance.defaults.headers || {};\n const configHeaders = (config as any).headers || {};\n \n // Flatten axios headers structure (common, get, post, etc. + top-level)\n const flattenedDefaults: Record<string, string> = {};\n for (const [key, value] of Object.entries(defaultHeaders)) {\n if (key === 'common' || key === 'get' || key === 'post' || key === 'put' || \n key === 'patch' || key === 'delete' || key === 'head' || key === 'options') {\n // These are method-specific headers, skip for now\n continue;\n }\n if (value !== undefined && value !== null) {\n flattenedDefaults[key] = String(value);\n }\n }\n \n // Merge: defaults < config headers\n finalConfig = {\n ...config,\n headers: { ...flattenedDefaults, ...configHeaders },\n };\n } else if (options?.headers) {\n // For auto-created instances, merge options.headers\n finalConfig = {\n ...config,\n headers: mergeHeaders(options.headers, (config as any).headers),\n };\n }\n \n const resp = await instance(finalConfig);\n status = resp?.status ?? 0;\n responseData = resp?.data;\n }\n\n if (status >= 200 && status < 300) {\n // Transform backend response using custom or default logic\n const transformFn = options?.transformResponse ?? defaultUnwrapBackendResponse;\n const transformedData = transformFn<T>(responseData);\n // Convert backend datetime strings to ISO format\n const processedData = processResponseDates(transformedData);\n return { data: (processedData ?? null) as T | null, error: null, status };\n }\n\n // Non-2xx status code - log error before returning\n const errorMessage = normalizeErrorMessage(responseData) || `HTTP ${status}`;\n const shouldLog = options?.logErrors !== false; // Default to true\n logErrorToConsole(config, status, errorMessage, responseData, shouldLog);\n\n return {\n data: null,\n error: {\n status,\n message: errorMessage,\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 const errorMessage = normalizeErrorMessage(details) || error?.message || \"Network error\";\n \n // Log error to console\n const shouldLog = options?.logErrors !== false; // Default to true\n logErrorToConsole(config, status, errorMessage, details || error, shouldLog);\n \n return {\n data: null,\n error: {\n status,\n message: errorMessage,\n details,\n },\n status,\n };\n }\n },\n };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/http.ts"],"names":["normalizeErrorMessage","payload","errorPayload","isBackendStandardFormat","data","status","defaultUnwrapBackendResponse","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","metaEnv","resolveUrl","config","options","raw","withBase","getMiniProgramRequest","g","callMaybePromiseRequest","fn","ret","resolve","reject","res","err","mergeHeaders","base","extra","out","taroLikeAdapter","req","method","header","isAxiosInstance","logErrorToConsole","message","details","shouldLog","createHttpClient","axiosInstanceOrOptions","instance","isUserProvidedInstance","adapterChoice","processedConfig","body","rest","adapter","r","finalConfig","defaultHeaders","configHeaders","flattenedDefaults","resp","transformedData","errorMessage","error_","error"],"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 * HTTP adapter to use:\n * - undefined: auto-detect (taro if mini-program APIs exist, otherwise axios)\n * - \"taro\": force mini-program request (wx/tt/my/...) or global Taro.request\n * - \"axios\": force axios\n * - AxiosInstance: use provided axios instance\n * - function: custom adapter\n */\n adapter?: \"taro\" | \"axios\" | AxiosInstance | HttpAdapter;\n /**\n * Base URL to prefix when `config.url` is relative (e.g. \"/api/...\").\n * \n * If not provided:\n * - Taro/mini-program: auto-reads from process.env.TARO_APP_API_BASE_URL or process.env.VITE_API_BASE_URL\n * - H5/Browser: no baseURL (expects dev proxy or absolute URLs)\n */\n baseURL?: string;\n /** Default headers merged into each request */\n headers?: Record<string, string>;\n /**\n * Custom response transform function to extract/modify data from backend response\n * If not provided, uses default transform logic for { status: 0/1, data: {...} }\n * \n * Similar to axios's transformResponse option\n * \n * @example\n * ```typescript\n * // For backend that returns: { statusCode: 200, data: {...} }\n * const client = createHttpClient({\n * transformResponse: (response) => {\n * if (response && typeof response === 'object' && 'data' in response) {\n * return response.data;\n * }\n * return response;\n * }\n * });\n * ```\n */\n transformResponse?: <T>(responseData: unknown) => T;\n /**\n * Whether to log errors to console (default: true)\n * Set to false to disable automatic error logging\n */\n logErrors?: boolean;\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 * Default unwrap logic for backend standard format response\n * Backend returns: { status: 0, data: {...} }\n * We extract the inner 'data' field for cleaner client usage\n */\nfunction defaultUnwrapBackendResponse<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 let value = \"\";\n\n // Vite/H5:必须直接写 import.meta.env,Vite 才能正确处理\n const metaEnv = (import.meta as any)?.env;\n if (metaEnv) {\n value = metaEnv.TARO_APP_API_BASE_URL || metaEnv.VITE_API_BASE_URL || \"\";\n }\n\n // Taro 小程序 build:defineConstants 会把 process.env.xxx 替换为字面量\n // H5 环境:process 不存在会抛 ReferenceError,这里用 try/catch 吞掉\n if (!value) {\n try {\n value =\n process.env.TARO_APP_API_BASE_URL ||\n process.env.VITE_API_BASE_URL ||\n \"\";\n } catch {\n // process is not defined (browser) -> ignore\n }\n }\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 * Log error to console with detailed information\n * Only logs if logErrors option is not explicitly set to false\n */\nfunction logErrorToConsole(\n config: RequestConfig,\n status: number,\n message: string,\n details: unknown,\n shouldLog: boolean = true\n): void {\n if (!shouldLog) return;\n\n const method = String(config.method || \"GET\").toUpperCase();\n const url = config.url;\n\n // Format error message with request context\n console.error(\n `[HTTP Error] ${method} ${url} - ${status} ${message}`,\n \"\\n→ Details:\",\n details\n );\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 let isUserProvidedInstance = false;\n\n if (isAxiosInstance(axiosInstanceOrOptions)) {\n instance = axiosInstanceOrOptions;\n isUserProvidedInstance = true;\n } else {\n options = axiosInstanceOrOptions;\n // Check if adapter is an axios instance\n if (options?.adapter && isAxiosInstance(options.adapter)) {\n instance = options.adapter;\n isUserProvidedInstance = true;\n // Remove adapter from options to avoid confusion\n options = { ...options, adapter: undefined };\n }\n }\n\n // Smart default: auto-detect environment\n // - If mini-program APIs exist (wx/tt/my/Taro.request) → use taro adapter\n // - Otherwise → use axios (for H5/browser)\n // User can still explicitly override via { adapter: \"axios\" } or { adapter: \"taro\" }\n const adapterChoice = options?.adapter ?? (getMiniProgramRequest() ? \"taro\" : \"axios\");\n \n return {\n async request<T>(\n config: RequestConfig\n ) {\n try {\n // 兼容 body 参数,自动转换为 data(支持 Fetch API 习惯)\n let processedConfig = config;\n if ('body' in config && (config as any).body !== undefined) {\n const { body, ...rest } = config as any;\n processedConfig = { ...rest, data: body };\n }\n\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(processedConfig);\n status = r.status ?? 0;\n responseData = r.data ?? null;\n } else if (adapter === \"taro\") {\n const r = await taroLikeAdapter(processedConfig, 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 \n // Axios behavior: if config.headers is set, it REPLACES defaults.headers\n // We need to manually merge instance defaults with request headers\n let finalConfig: any = processedConfig;\n \n if (isUserProvidedInstance) {\n // For user-provided instances, merge defaults.headers with config.headers\n const defaultHeaders = instance.defaults.headers || {};\n const configHeaders = (processedConfig as any).headers || {};\n \n // Flatten axios headers structure (common, get, post, etc. + top-level)\n const flattenedDefaults: Record<string, string> = {};\n for (const [key, value] of Object.entries(defaultHeaders)) {\n if (key === 'common' || key === 'get' || key === 'post' || key === 'put' || \n key === 'patch' || key === 'delete' || key === 'head' || key === 'options') {\n // These are method-specific headers, skip for now\n continue;\n }\n if (value !== undefined && value !== null) {\n flattenedDefaults[key] = String(value);\n }\n }\n \n // Merge: defaults < config headers\n finalConfig = {\n ...processedConfig,\n headers: { ...flattenedDefaults, ...configHeaders },\n };\n } else if (options?.headers) {\n // For auto-created instances, merge options.headers\n finalConfig = {\n ...processedConfig,\n headers: mergeHeaders(options.headers, (processedConfig as any).headers),\n };\n }\n \n const resp = await instance(finalConfig);\n status = resp?.status ?? 0;\n responseData = resp?.data;\n }\n\n if (status >= 200 && status < 300) {\n // Transform backend response using custom or default logic\n const transformFn = options?.transformResponse ?? defaultUnwrapBackendResponse;\n const transformedData = transformFn<T>(responseData);\n // Convert backend datetime strings to ISO format\n const processedData = processResponseDates(transformedData);\n return { data: (processedData ?? null) as T | null, error: null, status };\n }\n\n // Non-2xx status code - log error before returning\n const errorMessage = normalizeErrorMessage(responseData) || `HTTP ${status}`;\n const shouldLog = options?.logErrors !== false; // Default to true\n logErrorToConsole(config, status, errorMessage, responseData, shouldLog);\n\n return {\n data: null,\n error: {\n status,\n message: errorMessage,\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 const errorMessage = normalizeErrorMessage(details) || error?.message || \"Network error\";\n \n // Log error to console\n const shouldLog = options?.logErrors !== false; // Default to true\n logErrorToConsole(config, status, errorMessage, details || error, shouldLog);\n \n return {\n data: null,\n error: {\n status,\n message: errorMessage,\n details,\n },\n status,\n };\n }\n },\n };\n}\n"]}
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
function
|
|
2
|
-
\u2192 Details:`,
|
|
1
|
+
function w(e){if(!e)return "Request failed";if(typeof e=="string")return e;if(typeof e=="object"){let t=e;return t.message||t.error||t.msg||t.detail||"Request failed"}return "Request failed"}function E(e){if(!e||typeof e!="object"||!("data"in e))return false;if("status"in e){let t=e.status;return t===0||t===1||t==="0"||t==="1"}return false}function x(e){return E(e)?e.data:e}var P=/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/;function S(e){return P.test(e)}function U(e){return `${e.replace(" ","T")}.000Z`}function R(e){if(e==null)return e;if(Array.isArray(e))return e.map(t=>R(t));if(typeof e=="object"){let t={};for(let[n,s]of Object.entries(e))t[n]=R(s);return t}return typeof e=="string"&&S(e)?U(e):e}function _(e){return /^https?:\/\//i.test(e)}function H(e,t){let n=e.replace(/\/+$/,""),s=t.startsWith("/")?t:`/${t}`;return `${n}${s}`}function $(e){if(!e||typeof e!="object")return "";let t=Object.entries(e).filter(([,r])=>r!=null);if(t.length===0)return "";let n=globalThis?.URLSearchParams,s="";if(n){let r=new n;for(let[i,o]of t)if(Array.isArray(o))for(let a of o)r.append(i,String(a));else r.append(i,String(o));s=r.toString();}else s=t.flatMap(([r,i])=>Array.isArray(i)?i.map(o=>[r,o]):[[r,i]]).map(([r,i])=>`${encodeURIComponent(r)}=${encodeURIComponent(String(i))}`).join("&");return s?`?${s}`:""}function b(e,t){let n=$(t);return n?e.includes("?")?`${e}&${n.slice(1)}`:`${e}${n}`:e}function B(){let e="",t=import.meta?.env;if(t&&(e=t.TARO_APP_API_BASE_URL||t.VITE_API_BASE_URL||""),!e)try{e=process.env.TARO_APP_API_BASE_URL||process.env.VITE_API_BASE_URL||"";}catch{}return String(e||"").trim()}function I(e,t){let n=String(e.url||"");if(_(n))return b(n,e.params);let s=String(e.baseURL||t?.baseURL||B()||"").trim(),r=s?H(s,n):n;return b(r,e.params)}function A(){let e=globalThis;return typeof e?.Taro?.request=="function"?e.Taro.request.bind(e.Taro):typeof e?.wx?.request=="function"?e.wx.request.bind(e.wx):typeof e?.tt?.request=="function"?e.tt.request.bind(e.tt):typeof e?.my?.request=="function"?e.my.request.bind(e.my):typeof e?.swan?.request=="function"?e.swan.request.bind(e.swan):typeof e?.qq?.request=="function"?e.qq.request.bind(e.qq):typeof e?.jd?.request=="function"?e.jd.request.bind(e.jd):null}async function j(e,t){try{let n=e(t);if(n&&typeof n.then=="function")return await n}catch{}return await new Promise((n,s)=>{e({...t,success:r=>n(r),fail:r=>s(r)});})}function T(e,t){let n={...e||{}};if(!t)return n;if(typeof t=="object")for(let[s,r]of Object.entries(t))r!=null&&(n[s]=String(r));return n}async function v(e,t){let n=A();if(!n)throw new Error("Mini-program request API not found (wx/tt/my/... or global Taro.request).");let s=I(e,t),r=String(e.method||"GET").toUpperCase(),i=T(t?.headers,e.headers),o=await j(n,{url:s,method:r,header:i,data:e.data});return {status:o?.statusCode??o?.status??0,data:o?.data,headers:o?.header}}function C(e){let t=e;return typeof t=="function"&&!!t?.defaults&&!!t?.interceptors}function h(e,t,n,s,r=true){if(!r)return;let i=String(e.method||"GET").toUpperCase(),o=e.url;console.error(`[HTTP Error] ${i} ${o} - ${t} ${n}`,`
|
|
2
|
+
\u2192 Details:`,s);}function L(e){let t,n,s=false;C(e)?(t=e,s=true):(n=e,n?.adapter&&C(n.adapter)&&(t=n.adapter,s=true,n={...n,adapter:void 0}));let r=n?.adapter??(A()?"taro":"axios");return {async request(i){try{let o=i;if("body"in i&&i.body!==void 0){let{body:u,...l}=i;o={...l,data:u};}let a=0,c=null,f=typeof r=="function"?r:r==="taro"?"taro":"axios";if(typeof f=="function"){let u=await f(o);a=u.status??0,c=u.data??null;}else if(f==="taro"){let u=await v(o,n);a=u.status??0,c=u.data??null;}else {t||(t=(await import('axios')).default.create());let u=o;if(s){let y=t.defaults.headers||{},k=o.headers||{},q={};for(let[d,m]of Object.entries(y))d==="common"||d==="get"||d==="post"||d==="put"||d==="patch"||d==="delete"||d==="head"||d==="options"||m!=null&&(q[d]=String(m));u={...o,headers:{...q,...k}};}else n?.headers&&(u={...o,headers:T(n.headers,o.headers)});let l=await t(u);a=l?.status??0,c=l?.data;}if(a>=200&&a<300){let l=(n?.transformResponse??x)(c);return {data:R(l)??null,error:null,status:a}}let p=w(c)||`HTTP ${a}`,g=n?.logErrors!==!1;return h(i,a,p,c,g),{data:null,error:{status:a,message:p,details:c},status:a}}catch(o){let a=o,c=a?.response?.status||a?.statusCode||0,f=a?.response?.data??a?.data,p=w(f)||a?.message||"Network error",g=n?.logErrors!==false;return h(i,c,p,f||a,g),{data:null,error:{status:c,message:p,details:f},status:c}}}}}export{L as createHttpClient};//# sourceMappingURL=index.js.map
|
|
3
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","defaultUnwrapBackendResponse","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","metaEnv","resolveUrl","config","options","raw","withBase","getMiniProgramRequest","g","callMaybePromiseRequest","fn","ret","resolve","reject","res","err","mergeHeaders","base","extra","out","taroLikeAdapter","req","method","header","isAxiosInstance","logErrorToConsole","message","details","shouldLog","createHttpClient","axiosInstanceOrOptions","instance","isUserProvidedInstance","adapterChoice","adapter","r","finalConfig","defaultHeaders","configHeaders","flattenedDefaults","resp","transformedData","errorMessage","error_","error"],"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 * HTTP adapter to use:\n * - undefined: auto-detect (taro if mini-program APIs exist, otherwise axios)\n * - \"taro\": force mini-program request (wx/tt/my/...) or global Taro.request\n * - \"axios\": force axios\n * - AxiosInstance: use provided axios instance\n * - function: custom adapter\n */\n adapter?: \"taro\" | \"axios\" | AxiosInstance | HttpAdapter;\n /**\n * Base URL to prefix when `config.url` is relative (e.g. \"/api/...\").\n * \n * If not provided:\n * - Taro/mini-program: auto-reads from process.env.TARO_APP_API_BASE_URL or process.env.VITE_API_BASE_URL\n * - H5/Browser: no baseURL (expects dev proxy or absolute URLs)\n */\n baseURL?: string;\n /** Default headers merged into each request */\n headers?: Record<string, string>;\n /**\n * Custom response transform function to extract/modify data from backend response\n * If not provided, uses default transform logic for { status: 0/1, data: {...} }\n * \n * Similar to axios's transformResponse option\n * \n * @example\n * ```typescript\n * // For backend that returns: { statusCode: 200, data: {...} }\n * const client = createHttpClient({\n * transformResponse: (response) => {\n * if (response && typeof response === 'object' && 'data' in response) {\n * return response.data;\n * }\n * return response;\n * }\n * });\n * ```\n */\n transformResponse?: <T>(responseData: unknown) => T;\n /**\n * Whether to log errors to console (default: true)\n * Set to false to disable automatic error logging\n */\n logErrors?: boolean;\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 * Default unwrap logic for backend standard format response\n * Backend returns: { status: 0, data: {...} }\n * We extract the inner 'data' field for cleaner client usage\n */\nfunction defaultUnwrapBackendResponse<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 let value = \"\";\n\n // Vite/H5:必须直接写 import.meta.env,Vite 才能正确处理\n const metaEnv = (import.meta as any)?.env;\n if (metaEnv) {\n value = metaEnv.TARO_APP_API_BASE_URL || metaEnv.VITE_API_BASE_URL || \"\";\n }\n\n // Taro 小程序 build:defineConstants 会把 process.env.xxx 替换为字面量\n // H5 环境:process 不存在会抛 ReferenceError,这里用 try/catch 吞掉\n if (!value) {\n try {\n value =\n process.env.TARO_APP_API_BASE_URL ||\n process.env.VITE_API_BASE_URL ||\n \"\";\n } catch {\n // process is not defined (browser) -> ignore\n }\n }\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 * Log error to console with detailed information\n * Only logs if logErrors option is not explicitly set to false\n */\nfunction logErrorToConsole(\n config: RequestConfig,\n status: number,\n message: string,\n details: unknown,\n shouldLog: boolean = true\n): void {\n if (!shouldLog) return;\n\n const method = String(config.method || \"GET\").toUpperCase();\n const url = config.url;\n\n // Format error message with request context\n console.error(\n `[HTTP Error] ${method} ${url} - ${status} ${message}`,\n \"\\n→ Details:\",\n details\n );\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 let isUserProvidedInstance = false;\n\n if (isAxiosInstance(axiosInstanceOrOptions)) {\n instance = axiosInstanceOrOptions;\n isUserProvidedInstance = true;\n } else {\n options = axiosInstanceOrOptions;\n // Check if adapter is an axios instance\n if (options?.adapter && isAxiosInstance(options.adapter)) {\n instance = options.adapter;\n isUserProvidedInstance = true;\n // Remove adapter from options to avoid confusion\n options = { ...options, adapter: undefined };\n }\n }\n\n // Smart default: auto-detect environment\n // - If mini-program APIs exist (wx/tt/my/Taro.request) → use taro adapter\n // - Otherwise → use axios (for H5/browser)\n // User can still explicitly override via { adapter: \"axios\" } or { adapter: \"taro\" }\n const adapterChoice = options?.adapter ?? (getMiniProgramRequest() ? \"taro\" : \"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 \n // Axios behavior: if config.headers is set, it REPLACES defaults.headers\n // We need to manually merge instance defaults with request headers\n let finalConfig: any = config;\n \n if (isUserProvidedInstance) {\n // For user-provided instances, merge defaults.headers with config.headers\n const defaultHeaders = instance.defaults.headers || {};\n const configHeaders = (config as any).headers || {};\n \n // Flatten axios headers structure (common, get, post, etc. + top-level)\n const flattenedDefaults: Record<string, string> = {};\n for (const [key, value] of Object.entries(defaultHeaders)) {\n if (key === 'common' || key === 'get' || key === 'post' || key === 'put' || \n key === 'patch' || key === 'delete' || key === 'head' || key === 'options') {\n // These are method-specific headers, skip for now\n continue;\n }\n if (value !== undefined && value !== null) {\n flattenedDefaults[key] = String(value);\n }\n }\n \n // Merge: defaults < config headers\n finalConfig = {\n ...config,\n headers: { ...flattenedDefaults, ...configHeaders },\n };\n } else if (options?.headers) {\n // For auto-created instances, merge options.headers\n finalConfig = {\n ...config,\n headers: mergeHeaders(options.headers, (config as any).headers),\n };\n }\n \n const resp = await instance(finalConfig);\n status = resp?.status ?? 0;\n responseData = resp?.data;\n }\n\n if (status >= 200 && status < 300) {\n // Transform backend response using custom or default logic\n const transformFn = options?.transformResponse ?? defaultUnwrapBackendResponse;\n const transformedData = transformFn<T>(responseData);\n // Convert backend datetime strings to ISO format\n const processedData = processResponseDates(transformedData);\n return { data: (processedData ?? null) as T | null, error: null, status };\n }\n\n // Non-2xx status code - log error before returning\n const errorMessage = normalizeErrorMessage(responseData) || `HTTP ${status}`;\n const shouldLog = options?.logErrors !== false; // Default to true\n logErrorToConsole(config, status, errorMessage, responseData, shouldLog);\n\n return {\n data: null,\n error: {\n status,\n message: errorMessage,\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 const errorMessage = normalizeErrorMessage(details) || error?.message || \"Network error\";\n \n // Log error to console\n const shouldLog = options?.logErrors !== false; // Default to true\n logErrorToConsole(config, status, errorMessage, details || error, shouldLog);\n \n return {\n data: null,\n error: {\n status,\n message: errorMessage,\n details,\n },\n status,\n };\n }\n },\n };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/http.ts"],"names":["normalizeErrorMessage","payload","errorPayload","isBackendStandardFormat","data","status","defaultUnwrapBackendResponse","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","metaEnv","resolveUrl","config","options","raw","withBase","getMiniProgramRequest","g","callMaybePromiseRequest","fn","ret","resolve","reject","res","err","mergeHeaders","base","extra","out","taroLikeAdapter","req","method","header","isAxiosInstance","logErrorToConsole","message","details","shouldLog","createHttpClient","axiosInstanceOrOptions","instance","isUserProvidedInstance","adapterChoice","processedConfig","body","rest","adapter","r","finalConfig","defaultHeaders","configHeaders","flattenedDefaults","resp","transformedData","errorMessage","error_","error"],"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 * HTTP adapter to use:\n * - undefined: auto-detect (taro if mini-program APIs exist, otherwise axios)\n * - \"taro\": force mini-program request (wx/tt/my/...) or global Taro.request\n * - \"axios\": force axios\n * - AxiosInstance: use provided axios instance\n * - function: custom adapter\n */\n adapter?: \"taro\" | \"axios\" | AxiosInstance | HttpAdapter;\n /**\n * Base URL to prefix when `config.url` is relative (e.g. \"/api/...\").\n * \n * If not provided:\n * - Taro/mini-program: auto-reads from process.env.TARO_APP_API_BASE_URL or process.env.VITE_API_BASE_URL\n * - H5/Browser: no baseURL (expects dev proxy or absolute URLs)\n */\n baseURL?: string;\n /** Default headers merged into each request */\n headers?: Record<string, string>;\n /**\n * Custom response transform function to extract/modify data from backend response\n * If not provided, uses default transform logic for { status: 0/1, data: {...} }\n * \n * Similar to axios's transformResponse option\n * \n * @example\n * ```typescript\n * // For backend that returns: { statusCode: 200, data: {...} }\n * const client = createHttpClient({\n * transformResponse: (response) => {\n * if (response && typeof response === 'object' && 'data' in response) {\n * return response.data;\n * }\n * return response;\n * }\n * });\n * ```\n */\n transformResponse?: <T>(responseData: unknown) => T;\n /**\n * Whether to log errors to console (default: true)\n * Set to false to disable automatic error logging\n */\n logErrors?: boolean;\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 * Default unwrap logic for backend standard format response\n * Backend returns: { status: 0, data: {...} }\n * We extract the inner 'data' field for cleaner client usage\n */\nfunction defaultUnwrapBackendResponse<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 let value = \"\";\n\n // Vite/H5:必须直接写 import.meta.env,Vite 才能正确处理\n const metaEnv = (import.meta as any)?.env;\n if (metaEnv) {\n value = metaEnv.TARO_APP_API_BASE_URL || metaEnv.VITE_API_BASE_URL || \"\";\n }\n\n // Taro 小程序 build:defineConstants 会把 process.env.xxx 替换为字面量\n // H5 环境:process 不存在会抛 ReferenceError,这里用 try/catch 吞掉\n if (!value) {\n try {\n value =\n process.env.TARO_APP_API_BASE_URL ||\n process.env.VITE_API_BASE_URL ||\n \"\";\n } catch {\n // process is not defined (browser) -> ignore\n }\n }\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 * Log error to console with detailed information\n * Only logs if logErrors option is not explicitly set to false\n */\nfunction logErrorToConsole(\n config: RequestConfig,\n status: number,\n message: string,\n details: unknown,\n shouldLog: boolean = true\n): void {\n if (!shouldLog) return;\n\n const method = String(config.method || \"GET\").toUpperCase();\n const url = config.url;\n\n // Format error message with request context\n console.error(\n `[HTTP Error] ${method} ${url} - ${status} ${message}`,\n \"\\n→ Details:\",\n details\n );\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 let isUserProvidedInstance = false;\n\n if (isAxiosInstance(axiosInstanceOrOptions)) {\n instance = axiosInstanceOrOptions;\n isUserProvidedInstance = true;\n } else {\n options = axiosInstanceOrOptions;\n // Check if adapter is an axios instance\n if (options?.adapter && isAxiosInstance(options.adapter)) {\n instance = options.adapter;\n isUserProvidedInstance = true;\n // Remove adapter from options to avoid confusion\n options = { ...options, adapter: undefined };\n }\n }\n\n // Smart default: auto-detect environment\n // - If mini-program APIs exist (wx/tt/my/Taro.request) → use taro adapter\n // - Otherwise → use axios (for H5/browser)\n // User can still explicitly override via { adapter: \"axios\" } or { adapter: \"taro\" }\n const adapterChoice = options?.adapter ?? (getMiniProgramRequest() ? \"taro\" : \"axios\");\n \n return {\n async request<T>(\n config: RequestConfig\n ) {\n try {\n // 兼容 body 参数,自动转换为 data(支持 Fetch API 习惯)\n let processedConfig = config;\n if ('body' in config && (config as any).body !== undefined) {\n const { body, ...rest } = config as any;\n processedConfig = { ...rest, data: body };\n }\n\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(processedConfig);\n status = r.status ?? 0;\n responseData = r.data ?? null;\n } else if (adapter === \"taro\") {\n const r = await taroLikeAdapter(processedConfig, 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 \n // Axios behavior: if config.headers is set, it REPLACES defaults.headers\n // We need to manually merge instance defaults with request headers\n let finalConfig: any = processedConfig;\n \n if (isUserProvidedInstance) {\n // For user-provided instances, merge defaults.headers with config.headers\n const defaultHeaders = instance.defaults.headers || {};\n const configHeaders = (processedConfig as any).headers || {};\n \n // Flatten axios headers structure (common, get, post, etc. + top-level)\n const flattenedDefaults: Record<string, string> = {};\n for (const [key, value] of Object.entries(defaultHeaders)) {\n if (key === 'common' || key === 'get' || key === 'post' || key === 'put' || \n key === 'patch' || key === 'delete' || key === 'head' || key === 'options') {\n // These are method-specific headers, skip for now\n continue;\n }\n if (value !== undefined && value !== null) {\n flattenedDefaults[key] = String(value);\n }\n }\n \n // Merge: defaults < config headers\n finalConfig = {\n ...processedConfig,\n headers: { ...flattenedDefaults, ...configHeaders },\n };\n } else if (options?.headers) {\n // For auto-created instances, merge options.headers\n finalConfig = {\n ...processedConfig,\n headers: mergeHeaders(options.headers, (processedConfig as any).headers),\n };\n }\n \n const resp = await instance(finalConfig);\n status = resp?.status ?? 0;\n responseData = resp?.data;\n }\n\n if (status >= 200 && status < 300) {\n // Transform backend response using custom or default logic\n const transformFn = options?.transformResponse ?? defaultUnwrapBackendResponse;\n const transformedData = transformFn<T>(responseData);\n // Convert backend datetime strings to ISO format\n const processedData = processResponseDates(transformedData);\n return { data: (processedData ?? null) as T | null, error: null, status };\n }\n\n // Non-2xx status code - log error before returning\n const errorMessage = normalizeErrorMessage(responseData) || `HTTP ${status}`;\n const shouldLog = options?.logErrors !== false; // Default to true\n logErrorToConsole(config, status, errorMessage, responseData, shouldLog);\n\n return {\n data: null,\n error: {\n status,\n message: errorMessage,\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 const errorMessage = normalizeErrorMessage(details) || error?.message || \"Network error\";\n \n // Log error to console\n const shouldLog = options?.logErrors !== false; // Default to true\n logErrorToConsole(config, status, errorMessage, details || error, shouldLog);\n \n return {\n data: null,\n error: {\n status,\n message: errorMessage,\n details,\n },\n status,\n };\n }\n },\n };\n}\n"]}
|