@h-ai/api-client 0.1.0-alpha5
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/LICENSE +202 -0
- package/README.md +340 -0
- package/dist/index.d.ts +348 -0
- package/dist/index.js +748 -0
- package/dist/index.js.map +1 -0
- package/package.json +43 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/api-client-auth.ts","../messages/en-US.json","../messages/zh-CN.json","../src/api-client-i18n.ts","../src/api-client-types.ts","../src/api-client-contract.ts","../src/api-client-error.ts","../src/api-client-fetch.ts","../src/api-client-token-manager.ts","../src/api-client-main.ts"],"names":["core","err","ok","logger"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * @h-ai/api-client — Token 存储适配器\n *\n * 提供 localStorage 和内存两种内置 Token 存储实现。\n * @module api-client-auth\n */\n\nimport type { TokenStorage } from './api-client-types.js'\n\n// ─── localStorage 存储 ───\n\nconst LS_ACCESS_KEY = 'hai_access_token'\nconst LS_REFRESH_KEY = 'hai_refresh_token'\n\n/**\n * 创建基于 localStorage 的 Token 存储\n *\n * 适用于浏览器端 SPA / PWA。Capacitor 环境建议使用\n * `@h-ai/capacitor` 提供的 `CapacitorTokenStorage`。\n *\n * @returns TokenStorage 实例\n *\n * @example\n * ```ts\n * import { api, createLocalStorageTokenStorage } from '@h-ai/api-client'\n *\n * await api.init({\n * baseUrl: 'https://api.example.com',\n * auth: {\n * storage: createLocalStorageTokenStorage(),\n * refreshUrl: '/auth/refresh',\n * },\n * })\n * ```\n */\nexport function createLocalStorageTokenStorage(): TokenStorage {\n return {\n async getAccessToken() {\n return globalThis.localStorage?.getItem(LS_ACCESS_KEY) ?? null\n },\n async setAccessToken(token: string) {\n globalThis.localStorage?.setItem(LS_ACCESS_KEY, token)\n },\n async getRefreshToken() {\n return globalThis.localStorage?.getItem(LS_REFRESH_KEY) ?? null\n },\n async setRefreshToken(token: string) {\n globalThis.localStorage?.setItem(LS_REFRESH_KEY, token)\n },\n async clear() {\n globalThis.localStorage?.removeItem(LS_ACCESS_KEY)\n globalThis.localStorage?.removeItem(LS_REFRESH_KEY)\n },\n }\n}\n\n// ─── 内存存储 ───\n\n/**\n * 创建内存 Token 存储\n *\n * 适用于 Node.js 测试、SSR 或短生命周期场景。\n * 页面刷新后 Token 丢失。\n *\n * @returns TokenStorage 实例\n *\n * @example\n * ```ts\n * import { api, createMemoryTokenStorage } from '@h-ai/api-client'\n *\n * await api.init({\n * baseUrl: 'https://api.example.com',\n * auth: {\n * storage: createMemoryTokenStorage(),\n * refreshUrl: '/auth/refresh',\n * },\n * })\n * ```\n */\nexport function createMemoryTokenStorage(): TokenStorage {\n let accessToken: string | null = null\n let refreshToken: string | null = null\n\n return {\n async getAccessToken() {\n return accessToken\n },\n async setAccessToken(token: string) {\n accessToken = token\n },\n async getRefreshToken() {\n return refreshToken\n },\n async setRefreshToken(token: string) {\n refreshToken = token\n },\n async clear() {\n accessToken = null\n refreshToken = null\n },\n }\n}\n","{\n \"apiClient_networkError\": \"Network request failed\",\n \"apiClient_timeout\": \"Request timeout\",\n \"apiClient_serverError\": \"Server error ({status})\",\n \"apiClient_unauthorized\": \"Unauthorized, please log in again\",\n \"apiClient_forbidden\": \"Access forbidden\",\n \"apiClient_notFound\": \"Resource not found\",\n \"apiClient_validationFailed\": \"Request validation failed\",\n \"apiClient_tokenRefreshFailed\": \"Token refresh failed, please log in again\",\n \"apiClient_notInitialized\": \"API client not initialized, please call api.init() first\",\n \"apiClient_configError\": \"API client config error: {error}\",\n \"apiClient_responseValidationFailed\": \"Response validation failed\",\n \"apiClient_unknown\": \"Unknown error\"\n}\n","{\n \"apiClient_networkError\": \"网络请求失败\",\n \"apiClient_timeout\": \"请求超时\",\n \"apiClient_serverError\": \"服务器错误({status})\",\n \"apiClient_unauthorized\": \"未授权,请重新登录\",\n \"apiClient_forbidden\": \"无权限访问\",\n \"apiClient_notFound\": \"请求的资源不存在\",\n \"apiClient_validationFailed\": \"请求参数校验失败\",\n \"apiClient_tokenRefreshFailed\": \"Token刷新失败,请重新登录\",\n \"apiClient_notInitialized\": \"API 客户端未初始化,请先调用 api.init()\",\n \"apiClient_configError\": \"API 客户端配置错误:{error}\",\n \"apiClient_responseValidationFailed\": \"响应数据校验失败\",\n \"apiClient_unknown\": \"未知错误\"\n}\n","/**\n * @h-ai/api-client — i18n\n *\n * 模块 i18n 文案访问入口。\n * @module api-client-i18n\n */\n\nimport { core } from '@h-ai/core'\nimport messagesEnUS from '../messages/en-US.json'\nimport messagesZhCN from '../messages/zh-CN.json'\n\ntype ApiClientMessageKey = keyof typeof messagesZhCN\n\n/**\n * api-client 模块 i18n 文案获取器\n *\n * @param key - 文案 Key\n * @param options - 插值参数\n * @returns 本地化后的文案字符串\n */\nexport const apiClientM = core.i18n.createMessageGetter<ApiClientMessageKey>({\n 'zh-CN': messagesZhCN,\n 'en-US': messagesEnUS,\n})\n","/**\n * @h-ai/api-client — 类型定义\n *\n * 通用 HTTP 客户端的公共类型、EndpointDef 契约接口、\n * TokenStorage 适配器接口等。\n * @module api-client-types\n */\n\nimport type { ErrorInfo, HaiResult } from '@h-ai/core'\nimport type { z } from 'zod'\nimport { core } from '@h-ai/core'\n\n// ─── 错误定义(照 @h-ai/core 范式) ───\n\nconst ApiClientErrorInfo = {\n NETWORK_ERROR: '001:502',\n TIMEOUT: '002:504',\n SERVER_ERROR: '003:502',\n UNAUTHORIZED: '004:401',\n FORBIDDEN: '005:403',\n NOT_FOUND: '006:404',\n VALIDATION_FAILED: '007:400',\n TOKEN_REFRESH_FAILED: '008:401',\n NOT_INITIALIZED: '010:500',\n CONFIG_ERROR: '011:500',\n UNKNOWN: '099:500',\n} as const satisfies ErrorInfo\n\nexport const HaiApiClientError = core.error.buildHaiErrorsDef('api-client', ApiClientErrorInfo)\n\n// ─── API 契约 ───\n\n/**\n * API 端点契约定义\n *\n * 描述单个 API 端点的 HTTP 方法、路径、入参/出参 Schema 与元数据。\n * 客户端通过 `api.call(endpoint, input)` 调用,服务端通过\n * `kit.fromContract(endpoint, handler)` 响应,两端共享同一份契约。\n *\n * @typeParam TInput - 入参类型(由 Zod Schema 推导)\n * @typeParam TOutput - 出参类型(由 Zod Schema 推导)\n *\n * @example\n * ```ts\n * const loginEndpoint: EndpointDef<LoginInput, LoginOutput> = {\n * method: 'POST',\n * path: '/auth/login',\n * input: LoginInputSchema,\n * output: LoginOutputSchema,\n * requireAuth: false,\n * }\n * ```\n */\nexport interface EndpointDef<\n TInput = unknown,\n TOutput = unknown,\n> {\n /** HTTP 方法 */\n method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH'\n /** 相对路径(相对于 API 前缀,如 '/auth/login') */\n path: string\n /** 入参 Zod Schema(GET 请求为 query params,其他为 body) */\n input: z.ZodType<TInput>\n /** 出参 Zod Schema */\n output: z.ZodType<TOutput>\n /** 是否需要认证(默认 true) */\n requireAuth?: boolean\n /** OpenAPI 描述元数据 */\n meta?: {\n summary?: string\n tags?: string[]\n }\n}\n\n// ─── Token ───\n\n/**\n * Token 对(与 @h-ai/iam 的 TokenPair 对齐)\n */\nexport interface TokenPair {\n /** Access Token */\n accessToken: string\n /** Refresh Token */\n refreshToken: string\n /** 过期时间(秒) */\n expiresIn: number\n /** Token 类型 */\n tokenType: 'Bearer'\n}\n\n/**\n * Token 存储适配器\n *\n * 可插拔存储后端(localStorage / memory / Capacitor Preferences / 自定义)。\n */\nexport interface TokenStorage {\n /** 获取 Access Token */\n getAccessToken: () => Promise<string | null>\n /** 设置 Access Token */\n setAccessToken: (token: string) => Promise<void>\n /** 获取 Refresh Token */\n getRefreshToken: () => Promise<string | null>\n /** 设置 Refresh Token */\n setRefreshToken: (token: string) => Promise<void>\n /** 清空所有 Token */\n clear: () => Promise<void>\n}\n\n// ─── 拦截器 ───\n\n/**\n * 请求配置(传递给拦截器)\n */\nexport interface RequestConfig {\n /** 完整 URL */\n url: string\n /** HTTP 方法 */\n method: string\n /** 请求头 */\n headers: Record<string, string>\n /** 请求体(已序列化) */\n body?: string | FormData\n /** 信号(abort) */\n signal?: AbortSignal\n}\n\n/** 请求拦截器 */\nexport type RequestInterceptor = (config: RequestConfig) => RequestConfig | Promise<RequestConfig>\n\n/** 响应拦截器 */\nexport type ResponseInterceptor = (response: Response) => Response | Promise<Response>\n\n// ─── 配置 ───\n\n/**\n * Token 刷新配置\n */\nexport interface AuthConfig {\n /** Token 存储适配器(默认 createLocalStorageTokenStorage) */\n storage?: TokenStorage\n /** Refresh Token 接口路径(相对于 baseUrl) */\n refreshUrl: string\n /** Token 刷新回调 */\n onTokenRefreshed?: (tokens: TokenPair) => void\n /** Token 刷新失败回调(通常用于跳转登录页) */\n onRefreshFailed?: () => void\n}\n\n/**\n * ApiClient 配置\n */\nexport interface ApiClientConfig {\n /** API 基础 URL(如 https://api.example.com/api/v1) */\n baseUrl: string\n /** Token 认证配置(省略则不启用自动 Token 管理) */\n auth?: AuthConfig\n /** 请求超时(毫秒,默认 30000) */\n timeout?: number\n /** 拦截器 */\n interceptors?: {\n request?: RequestInterceptor[]\n response?: ResponseInterceptor[]\n }\n /** 自定义 fetch 实现(用于测试或特殊环境) */\n fetch?: typeof globalThis.fetch\n}\n\n// ─── 上传选项 ───\n\n/**\n * 文件上传选项\n */\nexport interface UploadOptions {\n /** 文件字段名(默认 'file') */\n fieldName?: string\n /** 附加表单字段 */\n extraFields?: Record<string, string>\n}\n\n/**\n * 流式请求选项\n */\nexport interface StreamOptions {\n /** 外部取消信号(例如 AbortController.signal) */\n signal?: AbortSignal\n}\n\n// ─── ApiClient 接口 ───\n\n/**\n * Api Client 实例接口\n *\n * 提供通用 HTTP 方法和契约调用能力。\n */\nexport interface ApiClient {\n /** GET 请求 */\n get: <T>(path: string, params?: Record<string, unknown>) => Promise<HaiResult<T>>\n /** POST 请求 */\n post: <T>(path: string, body?: unknown) => Promise<HaiResult<T>>\n /** PUT 请求 */\n put: <T>(path: string, body?: unknown) => Promise<HaiResult<T>>\n /** PATCH 请求 */\n patch: <T>(path: string, body?: unknown) => Promise<HaiResult<T>>\n /** DELETE 请求 */\n delete: <T>(path: string, params?: Record<string, unknown>) => Promise<HaiResult<T>>\n\n /** 文件上传 */\n upload: (path: string, file: File | Blob, options?: UploadOptions) => Promise<HaiResult<unknown>>\n\n /** 流式请求(返回 AsyncIterable) */\n stream: (path: string, body?: unknown, options?: StreamOptions) => AsyncIterable<string>\n\n /**\n * 契约调用(推荐)\n *\n * 基于 EndpointDef 发起请求,路径、方法、入参、出参类型全由契约保证。\n */\n call: <TInput, TOutput>(\n endpoint: EndpointDef<TInput, TOutput>,\n input: TInput,\n ) => Promise<HaiResult<TOutput>>\n\n /** Token 管理 */\n auth: {\n /** 设置 Token */\n setTokens: (tokens: TokenPair) => Promise<void>\n /** 清空 Token */\n clear: () => Promise<void>\n /** Token 刷新回调,返回取消订阅函数 */\n onTokenRefreshed: (callback: (tokens: TokenPair) => void) => () => void\n }\n}\n\n/**\n * 辅助函数:创建端点定义(获得类型推导)\n *\n * @example\n * ```ts\n * const login = defineEndpoint({\n * method: 'POST',\n * path: '/auth/login',\n * input: LoginInputSchema,\n * output: LoginOutputSchema,\n * requireAuth: false,\n * })\n * ```\n */\nexport function defineEndpoint<TInput, TOutput>(\n def: EndpointDef<TInput, TOutput>,\n): EndpointDef<TInput, TOutput> {\n return def\n}\n\n// ─── ApiClientFunctions ───\n\n/**\n * API 客户端函数接口(单例模式)\n *\n * 统一的 API 客户端访问入口:\n * - `api.init(config)` — 初始化客户端\n * - `api.close()` — 关闭客户端并释放资源\n * - `api.get / post / put / patch / delete` — 通用 HTTP 方法\n * - `api.call(endpoint, input)` — 契约调用\n * - `api.upload(path, file)` — 文件上传\n * - `api.stream(path, body)` — 流式请求\n * - `api.auth` — Token 管理\n * - `api.config` — 当前配置(未初始化时为 null)\n * - `api.isInitialized` — 初始化状态\n */\nexport interface ApiClientFunctions {\n /**\n * 初始化 API 客户端\n *\n * 已有实例时会先 close 再重新初始化。\n *\n * @param config - 客户端配置\n * @returns 成功 ok(undefined);失败返回 err(含 ApiClientError)\n */\n init: (config: ApiClientConfig) => Promise<HaiResult<void>>\n\n /**\n * 关闭 API 客户端并释放资源\n *\n * 重复调用不会报错。\n */\n close: () => Promise<void>\n\n /** 当前客户端配置;未初始化或已关闭时为 null */\n readonly config: ApiClientConfig | null\n\n /** 是否已完成初始化 */\n readonly isInitialized: boolean\n\n /** GET 请求 */\n readonly get: ApiClient['get']\n /** POST 请求 */\n readonly post: ApiClient['post']\n /** PUT 请求 */\n readonly put: ApiClient['put']\n /** PATCH 请求 */\n readonly patch: ApiClient['patch']\n /** DELETE 请求 */\n readonly delete: ApiClient['delete']\n /** 文件上传 */\n readonly upload: ApiClient['upload']\n\n /**\n * 流式请求(返回 AsyncIterable)\n *\n * @throws 未初始化时抛出异常(async generator 无法返回 HaiResult)\n */\n readonly stream: ApiClient['stream']\n\n /** 契约调用(推荐) */\n readonly call: ApiClient['call']\n\n /** Token 管理 */\n readonly auth: ApiClient['auth']\n}\n","/**\n * @h-ai/api-client — 契约调用\n *\n * 基于 EndpointDef 发起类型安全的 API 请求。\n * @module api-client-contract\n */\n\nimport type { HaiResult } from '@h-ai/core'\nimport type { FetchClient } from './api-client-fetch.js'\nimport type { EndpointDef } from './api-client-types.js'\nimport { err, ok } from '@h-ai/core'\nimport { apiClientM } from './api-client-i18n.js'\nimport { HaiApiClientError } from './api-client-types.js'\n\n/**\n * 创建契约调用函数\n *\n * @param fetchClient - Fetch Client 实例\n * @returns call 函数\n */\nexport function createContractCaller(fetchClient: FetchClient) {\n /**\n * 基于端点契约发起请求\n *\n * 路径、方法、入参、出参类型全由契约保证。\n *\n * @typeParam TInput - 入参类型\n * @typeParam TOutput - 出参类型\n * @param endpoint - 端点契约定义\n * @param input - 入参数据\n * @returns 出参 HaiResult\n *\n * @example\n * ```ts\n * const result = await api.call(iamEndpoints.login, { identifier: 'alice', password: 'xxx' })\n * ```\n */\n async function call<TInput, TOutput>(\n endpoint: EndpointDef<TInput, TOutput>,\n input: TInput,\n ): Promise<HaiResult<TOutput>> {\n // 客户端入参校验(避免无效请求发送到服务端)\n const parsed = endpoint.input.safeParse(input)\n if (!parsed.success) {\n return err(\n HaiApiClientError.VALIDATION_FAILED,\n apiClientM('apiClient_validationFailed'),\n parsed.error.issues,\n )\n }\n\n const validInput = parsed.data\n\n let result: HaiResult<unknown>\n\n switch (endpoint.method) {\n case 'GET':\n result = await fetchClient.get(endpoint.path, validInput as Record<string, unknown>)\n break\n\n case 'POST':\n result = await fetchClient.post(endpoint.path, validInput)\n break\n\n case 'PUT':\n result = await fetchClient.put(endpoint.path, validInput)\n break\n\n case 'PATCH':\n result = await fetchClient.patch(endpoint.path, validInput)\n break\n\n case 'DELETE':\n result = await fetchClient.delete(endpoint.path, validInput as Record<string, unknown>)\n break\n\n default:\n return err(\n HaiApiClientError.UNKNOWN,\n apiClientM('apiClient_unknown'),\n )\n }\n\n if (!result.success) {\n return result\n }\n\n // 响应数据校验(确保服务端返回的数据符合契约)\n const outputParsed = endpoint.output.safeParse(result.data)\n if (!outputParsed.success) {\n return err(\n HaiApiClientError.VALIDATION_FAILED,\n apiClientM('apiClient_responseValidationFailed'),\n outputParsed.error.issues,\n )\n }\n\n return ok(outputParsed.data)\n }\n\n return call\n}\n","/**\n * @h-ai/api-client — 错误处理\n *\n * HTTP 状态码到 HaiResult 错误的统一转换。\n * @module api-client-error\n */\n\nimport type { HaiResult } from '@h-ai/core'\nimport { err } from '@h-ai/core'\nimport { apiClientM } from './api-client-i18n.js'\nimport { HaiApiClientError } from './api-client-types.js'\n\n/**\n * 将 HTTP 响应转为 HaiResult<never>\n *\n * @param response - HTTP 响应\n * @returns HaiResult<never>\n */\nexport async function responseToError(response: Response): Promise<HaiResult<never>> {\n let details: unknown\n\n try {\n const body = await response.json()\n details = body\n }\n catch {\n // 响应体不是 JSON,忽略\n }\n\n const status = response.status\n\n if (status === 401) {\n return err(\n HaiApiClientError.UNAUTHORIZED,\n apiClientM('apiClient_unauthorized'),\n details,\n )\n }\n\n if (status === 403) {\n return err(\n HaiApiClientError.FORBIDDEN,\n apiClientM('apiClient_forbidden'),\n details,\n )\n }\n\n if (status === 404) {\n return err(\n HaiApiClientError.NOT_FOUND,\n apiClientM('apiClient_notFound'),\n details,\n )\n }\n\n if (status === 400 || status === 422) {\n return err(\n HaiApiClientError.VALIDATION_FAILED,\n apiClientM('apiClient_validationFailed'),\n details,\n )\n }\n\n if (status >= 500) {\n return err(\n HaiApiClientError.SERVER_ERROR,\n apiClientM('apiClient_serverError', { params: { status: String(status) } }),\n details,\n )\n }\n\n return err(\n HaiApiClientError.UNKNOWN,\n apiClientM('apiClient_unknown'),\n details,\n )\n}\n\n/**\n * 将网络异常转为 HaiResult<never>\n *\n * @param cause - 原始异常\n * @returns HaiResult<never>\n */\nexport function networkErrorToResult(cause: unknown): HaiResult<never> {\n // AbortError = 超时\n if (cause instanceof DOMException && cause.name === 'AbortError') {\n return err(\n HaiApiClientError.TIMEOUT,\n apiClientM('apiClient_timeout'),\n cause,\n )\n }\n\n return err(\n HaiApiClientError.NETWORK_ERROR,\n apiClientM('apiClient_networkError'),\n cause,\n )\n}\n","/**\n * @h-ai/api-client — 核心 fetch 封装\n *\n * 请求/响应拦截器链、超时控制、Token 自动附加、401 自动刷新重试。\n * @module api-client-fetch\n */\n\nimport type { HaiResult } from '@h-ai/core'\nimport type { TokenManager } from './api-client-token-manager.js'\nimport type {\n ApiClientConfig,\n RequestConfig,\n RequestInterceptor,\n ResponseInterceptor,\n StreamOptions,\n UploadOptions,\n} from './api-client-types.js'\nimport { core, ok } from '@h-ai/core'\nimport { networkErrorToResult, responseToError } from './api-client-error.js'\nimport { apiClientM } from './api-client-i18n.js'\n\nconst logger = core.logger.child({ module: 'api-client', scope: 'fetch' })\n\n/** 默认超时 30s */\nconst DEFAULT_TIMEOUT = 30_000\n\n/**\n * 创建核心请求函数\n *\n * 封装 fetch 请求,集成:\n * - 请求/响应拦截器链\n * - 超时控制(AbortController)\n * - Token 自动附加(Authorization: Bearer)\n * - 401 自动刷新 + 重试(一次)\n *\n * @param config - ApiClient 配置\n * @param tokenManager - Token 管理器(可选)\n * @returns 请求函数集合\n */\nexport function createFetchClient(\n config: ApiClientConfig,\n tokenManager?: TokenManager,\n) {\n const fetchFn = config.fetch ?? globalThis.fetch.bind(globalThis)\n const timeout = config.timeout ?? DEFAULT_TIMEOUT\n const requestInterceptors: RequestInterceptor[] = config.interceptors?.request ?? []\n const responseInterceptors: ResponseInterceptor[] = config.interceptors?.response ?? []\n\n /**\n * 构建完整 URL\n */\n function buildUrl(path: string, params?: Record<string, unknown>): string {\n const base = config.baseUrl.replace(/\\/+$/, '')\n const normalizedPath = path.startsWith('/') ? path : `/${path}`\n const url = new URL(`${base}${normalizedPath}`)\n\n if (params) {\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined && value !== null) {\n url.searchParams.set(key, String(value))\n }\n }\n }\n\n return url.toString()\n }\n\n /**\n * 执行请求(含拦截器、超时、Token、401 重试)\n */\n async function execute<T>(\n requestConfig: RequestConfig,\n retryOnUnauthorized = true,\n ): Promise<HaiResult<T>> {\n logger.trace('Executing request', { method: requestConfig.method, url: requestConfig.url })\n\n // 1. Token 注入\n if (tokenManager) {\n const accessToken = await tokenManager.storage.getAccessToken()\n if (accessToken) {\n requestConfig.headers.Authorization = `Bearer ${accessToken}`\n }\n }\n\n // 2. 请求拦截器\n let finalConfig = requestConfig\n for (const interceptor of requestInterceptors) {\n finalConfig = await interceptor(finalConfig)\n }\n\n // 3. 超时控制\n const controller = new AbortController()\n const timeoutId = setTimeout(() => controller.abort(), timeout)\n finalConfig.signal = controller.signal\n\n try {\n let response = await fetchFn(finalConfig.url, {\n method: finalConfig.method,\n headers: finalConfig.headers,\n body: finalConfig.body,\n signal: finalConfig.signal,\n })\n\n clearTimeout(timeoutId)\n\n // 4. 响应拦截器\n for (const interceptor of responseInterceptors) {\n response = await interceptor(response)\n }\n\n // 5. 401 自动刷新 + 重试\n if (response.status === 401 && retryOnUnauthorized && tokenManager) {\n logger.trace('Received 401, attempting token refresh', { url: requestConfig.url })\n const tokens = await tokenManager.refresh()\n if (tokens) {\n logger.trace('Token refreshed, retrying request', { url: requestConfig.url })\n requestConfig.headers.Authorization = `Bearer ${tokens.accessToken}`\n return execute<T>(requestConfig, false)\n }\n logger.warn('Token refresh failed, returning 401 error', { url: requestConfig.url })\n }\n\n // 6. 错误处理\n if (!response.ok) {\n return responseToError(response)\n }\n\n // 7. 解析成功响应\n const contentType = response.headers.get('content-type') ?? ''\n if (contentType.includes('application/json')) {\n const body = await response.json() as { data?: T, success?: boolean }\n // 兼容标准 HaiResult 响应格式 { success, data }\n if (body && typeof body === 'object' && 'data' in body) {\n return ok(body.data as T)\n }\n return ok(body as T)\n }\n\n // 非 JSON 响应(204 No Content 等)\n return ok(undefined as T)\n }\n catch (cause) {\n clearTimeout(timeoutId)\n logger.warn('Request failed', { url: requestConfig.url, error: cause })\n return networkErrorToResult(cause)\n }\n }\n\n // ─── 通用 HTTP 方法 ───\n\n async function get<T>(path: string, params?: Record<string, unknown>): Promise<HaiResult<T>> {\n return execute<T>({\n url: buildUrl(path, params),\n method: 'GET',\n headers: { Accept: 'application/json' },\n })\n }\n\n async function post<T>(path: string, body?: unknown): Promise<HaiResult<T>> {\n return execute<T>({\n url: buildUrl(path),\n method: 'POST',\n headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' },\n body: body !== undefined ? JSON.stringify(body) : undefined,\n })\n }\n\n async function put<T>(path: string, body?: unknown): Promise<HaiResult<T>> {\n return execute<T>({\n url: buildUrl(path),\n method: 'PUT',\n headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' },\n body: body !== undefined ? JSON.stringify(body) : undefined,\n })\n }\n\n async function patch<T>(path: string, body?: unknown): Promise<HaiResult<T>> {\n return execute<T>({\n url: buildUrl(path),\n method: 'PATCH',\n headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' },\n body: body !== undefined ? JSON.stringify(body) : undefined,\n })\n }\n\n async function del<T>(path: string, params?: Record<string, unknown>): Promise<HaiResult<T>> {\n return execute<T>({\n url: buildUrl(path, params),\n method: 'DELETE',\n headers: { Accept: 'application/json' },\n })\n }\n\n // ─── 文件上传 ───\n\n async function upload(\n path: string,\n file: File | Blob,\n options?: UploadOptions,\n ): Promise<HaiResult<unknown>> {\n const formData = new FormData()\n formData.append(options?.fieldName ?? 'file', file)\n\n if (options?.extraFields) {\n for (const [key, value] of Object.entries(options.extraFields)) {\n formData.append(key, value)\n }\n }\n\n return execute({\n url: buildUrl(path),\n method: 'POST',\n headers: { Accept: 'application/json' },\n body: formData,\n })\n }\n\n // ─── 流式请求 ───\n\n async function* stream(path: string, body?: unknown, options?: StreamOptions): AsyncIterable<string> {\n const requestConfig: RequestConfig = {\n url: buildUrl(path),\n method: 'POST',\n headers: { 'Content-Type': 'application/json', 'Accept': 'text/event-stream' },\n body: body !== undefined ? JSON.stringify(body) : undefined,\n }\n\n // Token 注入\n if (tokenManager) {\n const accessToken = await tokenManager.storage.getAccessToken()\n if (accessToken) {\n requestConfig.headers.Authorization = `Bearer ${accessToken}`\n }\n }\n\n // 请求拦截器\n let finalConfig = requestConfig\n for (const interceptor of requestInterceptors) {\n finalConfig = await interceptor(finalConfig)\n }\n\n // 超时控制 + 外部 abort\n const controller = new AbortController()\n let timeoutId: ReturnType<typeof setTimeout> | null = null\n let timeoutTriggered = false\n\n const clearStreamTimeout = () => {\n if (timeoutId) {\n clearTimeout(timeoutId)\n timeoutId = null\n }\n }\n\n const armStreamTimeout = () => {\n clearStreamTimeout()\n timeoutTriggered = false\n timeoutId = setTimeout(() => {\n timeoutTriggered = true\n controller.abort()\n }, timeout)\n }\n\n const externalSignal = options?.signal\n const onExternalAbort = () => {\n controller.abort()\n }\n\n if (externalSignal) {\n if (externalSignal.aborted) {\n controller.abort()\n }\n else {\n externalSignal.addEventListener('abort', onExternalAbort, { once: true })\n }\n }\n\n async function doStreamFetch(): Promise<Response> {\n armStreamTimeout()\n try {\n return await fetchFn(finalConfig.url, {\n method: finalConfig.method,\n headers: finalConfig.headers,\n body: finalConfig.body,\n signal: controller.signal,\n })\n }\n catch (cause) {\n clearStreamTimeout()\n throw cause\n }\n }\n\n // 统一资源清理:无论 doStreamFetch / 401 重试 / 读取阶段在哪抛出异常,\n // 都确保清理超时定时器、外部信号监听器和 reader 锁。\n let reader: ReadableStreamDefaultReader<Uint8Array> | null = null\n\n try {\n let response = await doStreamFetch()\n\n // 401 自动刷新 + 重试(一次)\n if (response.status === 401 && tokenManager) {\n logger.info('Stream received 401, attempting token refresh', { url: requestConfig.url })\n const tokens = await tokenManager.refresh()\n if (tokens) {\n finalConfig.headers.Authorization = `Bearer ${tokens.accessToken}`\n response = await doStreamFetch()\n }\n }\n\n if (!response.ok) {\n const errorResult = await responseToError(response)\n if (!errorResult.success) {\n throw new Error(errorResult.error.message, { cause: errorResult.error })\n }\n }\n\n if (!response.body) {\n throw new Error(apiClientM('apiClient_networkError'))\n }\n\n reader = response.body.getReader()\n const decoder = new TextDecoder()\n let lineBuffer = ''\n\n while (true) {\n armStreamTimeout()\n const { done, value } = await reader.read()\n clearStreamTimeout()\n if (done)\n break\n\n lineBuffer += decoder.decode(value, { stream: true })\n // 按换行分割,保留最后一段(可能是不完整行)\n const parts = lineBuffer.split('\\n')\n lineBuffer = parts.pop() ?? ''\n\n for (const line of parts) {\n if (line.startsWith('data: ')) {\n const data = line.slice(6)\n if (data !== '[DONE]') {\n yield data\n }\n }\n }\n }\n\n // 处理缓冲区剩余内容\n if (lineBuffer.startsWith('data: ')) {\n const data = lineBuffer.slice(6)\n if (data !== '[DONE]') {\n yield data\n }\n }\n }\n catch (cause) {\n if (cause instanceof DOMException && cause.name === 'AbortError') {\n if (externalSignal?.aborted && !timeoutTriggered) {\n throw cause\n }\n throw new Error(apiClientM('apiClient_timeout'), { cause })\n }\n throw cause\n }\n finally {\n clearStreamTimeout()\n if (externalSignal) {\n externalSignal.removeEventListener('abort', onExternalAbort)\n }\n if (reader) {\n reader.releaseLock()\n }\n }\n }\n\n return { get, post, put, patch, delete: del, upload, stream, execute, buildUrl }\n}\n\n/** Fetch Client 类型 */\nexport type FetchClient = ReturnType<typeof createFetchClient>\n","/**\n * @h-ai/api-client — Token 管理器(内部)\n *\n * 管理 Token 存储和自动刷新逻辑,仅供模块内部使用,不对外导出。\n * @module api-client-token-manager\n * @internal\n */\n\nimport type { TokenPair, TokenStorage } from './api-client-types.js'\nimport { core } from '@h-ai/core'\nimport { z } from 'zod'\n\nconst logger = core.logger.child({ module: 'api-client', scope: 'auth' })\n\n/**\n * Token 刷新响应校验 Schema\n */\nconst TokenPairSchema = z.object({\n accessToken: z.string().min(1),\n refreshToken: z.string().min(1),\n expiresIn: z.number().optional(),\n tokenType: z.string().optional(),\n})\n\n/**\n * Token 刷新回调\n */\ntype RefreshCallback = (tokens: TokenPair) => void\n\n/**\n * 创建 Token 管理器\n *\n * 内部使用,管理 Token 存储和刷新逻辑。\n *\n * @param storage - Token 存储适配器\n * @param refreshUrl - Refresh Token 接口完整 URL\n * @param fetchFn - fetch 实现\n * @param onRefreshFailed - 刷新失败回调\n * @returns Token 管理器\n */\nexport function createTokenManager(\n storage: TokenStorage,\n refreshUrl: string,\n fetchFn: typeof globalThis.fetch,\n onRefreshFailed?: () => void,\n) {\n const callbacks: RefreshCallback[] = []\n let refreshPromise: Promise<TokenPair | null> | null = null\n\n /**\n * 刷新 Token(带并发去重)\n *\n * 多个并发 401 只发一次 refresh 请求。\n */\n async function refresh(): Promise<TokenPair | null> {\n // 去重:已有刷新请求进行中,复用\n if (refreshPromise) {\n return refreshPromise\n }\n\n refreshPromise = doRefresh()\n try {\n return await refreshPromise\n }\n finally {\n refreshPromise = null\n }\n }\n\n async function doRefresh(): Promise<TokenPair | null> {\n const refreshToken = await storage.getRefreshToken()\n if (!refreshToken) {\n logger.warn('Token refresh skipped, no refresh token available')\n onRefreshFailed?.()\n return null\n }\n\n logger.debug('Refreshing token', { url: refreshUrl })\n\n try {\n const response = await fetchFn(refreshUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ refreshToken }),\n })\n\n if (!response.ok) {\n await storage.clear()\n onRefreshFailed?.()\n return null\n }\n\n const body = await response.json() as { data?: unknown }\n const parsed = TokenPairSchema.safeParse(body.data)\n if (!parsed.success) {\n logger.warn('Token refresh returned invalid data', { issues: parsed.error.issues })\n await storage.clear()\n onRefreshFailed?.()\n return null\n }\n\n // 提供默认值,避免 as TokenPair 不安全强转\n const tokens: TokenPair = {\n accessToken: parsed.data.accessToken,\n refreshToken: parsed.data.refreshToken,\n expiresIn: parsed.data.expiresIn ?? 3600,\n tokenType: 'Bearer',\n }\n await storage.setAccessToken(tokens.accessToken)\n await storage.setRefreshToken(tokens.refreshToken)\n logger.info('Token refreshed successfully')\n\n // 通知回调\n for (const cb of callbacks) {\n cb(tokens)\n }\n\n return tokens\n }\n catch (error) {\n logger.error('Token refresh failed', { error })\n await storage.clear()\n onRefreshFailed?.()\n return null\n }\n }\n\n return {\n storage,\n refresh,\n\n async setTokens(tokens: TokenPair) {\n await storage.setAccessToken(tokens.accessToken)\n await storage.setRefreshToken(tokens.refreshToken)\n },\n\n async clear() {\n await storage.clear()\n },\n\n onTokenRefreshed(callback: RefreshCallback): () => void {\n callbacks.push(callback)\n return () => {\n const idx = callbacks.indexOf(callback)\n if (idx >= 0)\n callbacks.splice(idx, 1)\n }\n },\n }\n}\n\n/** Token 管理器类型 */\nexport type TokenManager = ReturnType<typeof createTokenManager>\n","/**\n * @h-ai/api-client — 模块入口\n *\n * 提供统一的 `api` 对象,管理 HTTP 客户端运行时状态与生命周期。\n * @module api-client-main\n */\n\nimport type { HaiResult } from '@h-ai/core'\nimport type { ApiClient, ApiClientConfig, ApiClientFunctions, TokenPair } from './api-client-types.js'\n\nimport { core, err, ok } from '@h-ai/core'\nimport { createLocalStorageTokenStorage } from './api-client-auth.js'\nimport { createContractCaller } from './api-client-contract.js'\nimport { createFetchClient } from './api-client-fetch.js'\nimport { apiClientM } from './api-client-i18n.js'\nimport { createTokenManager } from './api-client-token-manager.js'\nimport { HaiApiClientError } from './api-client-types.js'\n\nconst logger = core.logger.child({ module: 'api-client', scope: 'main' })\n\n// ─── 内部状态 ───\n\n/** 当前 ApiClient 实例(init 后非空,close 后置空) */\nlet currentClient: ApiClient | null = null\n\n/** 当前客户端配置(init 后非空,close 后置空) */\nlet currentConfig: ApiClientConfig | null = null\n\n/** 并发初始化防护标志 */\nlet initInProgress = false\n\n// ─── 内部工厂 ───\n\n/**\n * 根据配置创建 ApiClient 实例\n *\n * 仅供 init() 内部使用,不对外暴露。\n */\nfunction createClient(config: ApiClientConfig): ApiClient {\n // 优先使用外部传入的 fetch(便于测试/跨平台注入);未传入时回退到全局 fetch\n const fetchFn = config.fetch ?? globalThis.fetch.bind(globalThis)\n // auth 开启时,默认使用 localStorage 作为 Token 存储\n const tokenStorage = config.auth?.storage ?? createLocalStorageTokenStorage()\n\n // Token 管理器(可选)\n const tokenManager = config.auth\n ? createTokenManager(\n tokenStorage,\n `${config.baseUrl.replace(/\\/+$/, '')}${config.auth.refreshUrl}`,\n fetchFn,\n config.auth.onRefreshFailed,\n )\n : undefined\n\n // 注册外部回调\n if (config.auth?.onTokenRefreshed && tokenManager) {\n tokenManager.onTokenRefreshed(config.auth.onTokenRefreshed)\n }\n\n // Fetch Client\n const fetchClient = createFetchClient(config, tokenManager)\n\n // 契约调用\n const call = createContractCaller(fetchClient)\n\n // Auth 管理接口\n const auth: ApiClient['auth'] = {\n async setTokens(tokens: TokenPair) {\n if (tokenManager) {\n await tokenManager.setTokens(tokens)\n }\n },\n async clear() {\n if (tokenManager) {\n await tokenManager.clear()\n }\n },\n onTokenRefreshed(callback: (tokens: TokenPair) => void): () => void {\n if (tokenManager) {\n return tokenManager.onTokenRefreshed(callback)\n }\n return () => { }\n },\n }\n\n return {\n get: fetchClient.get,\n post: fetchClient.post,\n put: fetchClient.put,\n patch: fetchClient.patch,\n delete: fetchClient.delete,\n upload: fetchClient.upload,\n stream: fetchClient.stream,\n call,\n auth,\n }\n}\n\n// ─── 未初始化占位 ───\n\n/**\n * 未初始化状态的错误工具包\n *\n * 当 api 未调用 init() 就直接使用 HTTP 方法时,\n * 所有方法调用都会返回 NOT_INITIALIZED 错误。\n */\nconst notInitialized = core.module.createNotInitializedKit(\n HaiApiClientError.NOT_INITIALIZED,\n () => apiClientM('apiClient_notInitialized'),\n)\n\n/** 未初始化时的 HTTP 操作占位代理(get/post/put/patch/delete/upload/call) */\nconst notInitializedOps = notInitialized.proxy<Pick<ApiClient, 'get' | 'post' | 'put' | 'patch' | 'delete' | 'upload' | 'call'>>()\n\n/** 未初始化时的 Token 管理占位 */\nconst notInitializedAuth: ApiClient['auth'] = {\n async setTokens() {\n logger.warn('api.auth.setTokens called before initialization, ignored')\n },\n async clear() {\n logger.warn('api.auth.clear called before initialization, ignored')\n },\n onTokenRefreshed() {\n logger.warn('api.auth.onTokenRefreshed called before initialization, ignored')\n return () => { }\n },\n}\n\n/**\n * 未初始化时的流式请求占位\n *\n * async generator 无法返回 HaiResult,迭代时抛出异常。\n */\nfunction notInitializedStreamFn(_path: string, _body?: unknown, _options?: { signal?: AbortSignal }): AsyncIterable<string> {\n return {\n [Symbol.asyncIterator]() {\n return {\n async next(): Promise<IteratorResult<string>> {\n throw new Error(apiClientM('apiClient_notInitialized'))\n },\n }\n },\n }\n}\n\n// ─── API 客户端单例 ───\n\n/**\n * API 客户端单例\n *\n * 使用前必须先调用 `api.init()` 初始化,传入 baseUrl 等配置信息。\n * 初始化后通过 `api.get`、`api.post`、`api.call` 等方法发起请求。\n *\n * @example\n * ```ts\n * import { api } from '@h-ai/api-client'\n *\n * // 初始化\n * await api.init({\n * baseUrl: 'https://api.example.com/api/v1',\n * auth: { refreshUrl: '/auth/refresh' },\n * })\n *\n * // 契约调用\n * const result = await api.call(loginEndpoint, { identifier: 'alice', password: 'xxx' })\n *\n * // 通用 HTTP\n * const users = await api.get<User[]>('/users', { page: 1 })\n *\n * // 关闭\n * await api.close()\n * ```\n */\nexport const api: ApiClientFunctions = {\n /**\n * 初始化 API 客户端\n *\n * 如果当前已有活跃实例,会先自动 close 再重新初始化。\n * 创建异常时返回 CONFIG_ERROR 错误。\n *\n * @param config 客户端配置(baseUrl、auth 等)\n * @returns 成功时返回 ok(undefined);失败时返回包含错误码和消息的 err。\n */\n async init(config: ApiClientConfig): Promise<HaiResult<void>> {\n if (initInProgress) {\n return err(\n HaiApiClientError.CONFIG_ERROR,\n apiClientM('apiClient_configError', { params: { error: 'initialization already in progress' } }),\n )\n }\n\n initInProgress = true\n try {\n if (currentClient) {\n logger.warn('Api-client module is already initialized, reinitializing')\n await api.close()\n }\n\n logger.info('Initializing api-client module')\n\n currentClient = createClient(config)\n currentConfig = config\n logger.info('Api-client module initialized')\n return ok(undefined)\n }\n catch (error) {\n logger.error('Api-client module initialization failed', { error })\n return err(\n HaiApiClientError.CONFIG_ERROR,\n apiClientM('apiClient_configError', { params: { error: error instanceof Error ? error.message : String(error) } }),\n error,\n )\n }\n finally {\n initInProgress = false\n }\n },\n\n /** GET 请求。未初始化时返回 NOT_INITIALIZED 错误 */\n get get() { return currentClient?.get ?? notInitializedOps.get },\n /** POST 请求。未初始化时返回 NOT_INITIALIZED 错误 */\n get post() { return currentClient?.post ?? notInitializedOps.post },\n /** PUT 请求。未初始化时返回 NOT_INITIALIZED 错误 */\n get put() { return currentClient?.put ?? notInitializedOps.put },\n /** PATCH 请求。未初始化时返回 NOT_INITIALIZED 错误 */\n get patch() { return currentClient?.patch ?? notInitializedOps.patch },\n /** DELETE 请求。未初始化时返回 NOT_INITIALIZED 错误 */\n get delete() { return currentClient?.delete ?? notInitializedOps.delete },\n /** 文件上传。未初始化时返回 NOT_INITIALIZED 错误 */\n get upload() { return currentClient?.upload ?? notInitializedOps.upload },\n /** 契约调用。未初始化时返回 NOT_INITIALIZED 错误 */\n get call() { return currentClient?.call ?? notInitializedOps.call },\n\n /**\n * 流式请求。未初始化时迭代抛出异常。\n *\n * @throws 未初始化时抛出 Error\n */\n get stream() { return currentClient?.stream ?? notInitializedStreamFn },\n\n /** Token 管理接口。未初始化时为空操作 */\n get auth() { return currentClient?.auth ?? notInitializedAuth },\n\n /** 当前客户端配置;未初始化或已关闭时为 null */\n get config() { return currentConfig },\n\n /** 是否已完成初始化 */\n get isInitialized() { return currentClient !== null },\n\n /**\n * 关闭 API 客户端并释放资源\n *\n * 关闭后所有 HTTP 操作将返回 NOT_INITIALIZED 错误。\n * 重复调用不会报错。\n */\n async close() {\n if (!currentClient) {\n currentConfig = null\n return\n }\n\n logger.info('Closing api-client module')\n\n currentClient = null\n currentConfig = null\n\n logger.info('Api-client module closed')\n },\n}\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@h-ai/api-client",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "0.1.0-alpha5",
|
|
5
|
+
"description": "Hai Framework universal HTTP client with Bearer token and API contract support.",
|
|
6
|
+
"license": "Apache-2.0",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"import": "./dist/index.js",
|
|
11
|
+
"default": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"main": "./dist/index.js",
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"files": [
|
|
17
|
+
"dist"
|
|
18
|
+
],
|
|
19
|
+
"publishConfig": {
|
|
20
|
+
"access": "public"
|
|
21
|
+
},
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"zod": "^4.3.6",
|
|
24
|
+
"@h-ai/core": "0.1.0-alpha5"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"@types/node": "^25.1.0",
|
|
28
|
+
"rimraf": "^6.0.1",
|
|
29
|
+
"tsup": "^8.3.5",
|
|
30
|
+
"typescript": "^5.7.2",
|
|
31
|
+
"vitest": "^4.0.18"
|
|
32
|
+
},
|
|
33
|
+
"scripts": {
|
|
34
|
+
"build": "tsup",
|
|
35
|
+
"dev": "tsup --watch",
|
|
36
|
+
"test": "vitest run",
|
|
37
|
+
"test:watch": "vitest",
|
|
38
|
+
"typecheck": "tsc --noEmit",
|
|
39
|
+
"lint": "eslint .",
|
|
40
|
+
"lint:fix": "eslint . --fix",
|
|
41
|
+
"clean": "rimraf dist .turbo"
|
|
42
|
+
}
|
|
43
|
+
}
|