@goplus123/core-api 1.1.7 → 1.1.8
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/chunk-23EAHSO4.cjs.map +1 -1
- package/dist/index.cjs +26 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +26 -1
- package/dist/index.js.map +1 -1
- package/dist/legacy-LOUPMLZX.cjs.map +1 -1
- package/dist/spec-WKJMH322.cjs.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/tjg/Desktop/gamepluspackage/packages/api/dist/index.cjs","../src/client/grpcClient.ts","../src/client/invokers/builtinGrpcWebInvoker.ts","../src/client/httpClient.ts","../src/client/wsClient.ts","../src/client/requestApi.ts","../src/client/wsRpcClient.ts","../src/client/unifiedApiClient.ts","../src/client/interceptors.ts","../src/utils/adapters/web.ts","../src/utils/fetchGuid.ts","../src/utils/uniqueKey.ts","../src/routing/router.ts","../src/index.ts"],"names":["apiError","method","i","serviceInstance","serviceInstances"],"mappings":"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AAA;AACT,EAAA;AACF;AAES;AACH,EAAA;AACM,IAAA;AACF,EAAA;AACN,IAAA;AACF,EAAA;AACF;AAES;AACD,EAAA;AACF,EAAA;AACK,IAAA;AAA+C,MAAA;AAAW,MAAA;AAEjE,IAAA;AACF,EAAA;AACO,EAAA;AACC,IAAA;AACA,IAAA;AACC,IAAA;AACR,EAAA;AACH;AAES;AACD,EAAA;AACA,EAAA;AACG,EAAA;AACA,IAAA;AACT,EAAA;AACO,EAAA;AACT;AAES;AACD,EAAA;AAEF,EAAA;AACA,EAAA;AACK,IAAA;AACT,EAAA;AAEM,EAAA;AACD,EAAA;AAEC,EAAA;AAIE,EAAA;AACD,EAAA;AACT;AAES;AACD,EAAA;AACA,EAAA;AAEF,EAAA;AAEE,EAAA;AACF,EAAA;AAEE,EAAA;AACG,EAAA;AACA,IAAA;AACT,EAAA;AACO,EAAA;AACT;AAES;AACD,EAAA;AACF,EAAA;AACE,IAAA;AACJ,IAAA;AACO,IAAA;AACT,EAAA;AACM,EAAA;AACF,EAAA;AACE,EAAA;AACI,EAAA;AACF,EAAA;AACD,EAAA;AACC,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AAEJ,IAAA;AAIJ,EAAA;AACO,EAAA;AACT;AAES;AACD,EAAA;AACF,EAAA;AACE,IAAA;AACI,MAAA;AACA,MAAA;AACN,MAAA;AACA,MAAA;AACM,IAAA;AACN,MAAA;AACF,IAAA;AACF,EAAA;AACM,EAAA;AACF,EAAA;AACE,IAAA;AACI,MAAA;AACN,MAAA;AACM,IAAA;AACN,MAAA;AACF,IAAA;AACF,EAAA;AACM,EAAA;AACA,EAAA;AACGC,EAAAA;AACH,EAAA;AACD,EAAA;AACC,EAAA;AACE,EAAA;AACD,EAAA;AACC,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACD,IAAA;AACC,IAAA;AACA,IAAA;AACF,IAAA;AACE,IAAA;AACA,IAAA;AACF,IAAA;AACE,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACF,IAAA;AACA,IAAA;AACN,EAAA;AACO,EAAA;AACT;AVkwEY;AACA;AW/6EN;AAEA;AACK,EAAA;AACA,IAAA;AACT,EAAA;AACS,EAAA;AACP,IAAA;AACF,EAAA;AACF;AAEM;AACK,EAAA;AACA,IAAA;AACT,EAAA;AACS,EAAA;AACP,IAAA;AACA,IAAA;AACF,EAAA;AACF;AAEI;AACA;AAES;AACX,EAAA;AACA,EAAA;AACF;AAEa;AX46ED;AACA;AY97EH;AACH,EAAA;AACA,EAAA;AACE,EAAA;AACJ,IAAA;AACA,IAAA;AACD,EAAA;AACQ,EAAA;AACX;AAES;AACA,EAAA;AACT;AAEI;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,EAAA;AACF,EAAA;AACE,EAAA;AACX;AAEI;AACA;AAEY;AACV,EAAA;AACJ,EAAA;AACF;AAES;AACH,EAAA;AACA,EAAA;AACK,IAAA;AACT,EAAA;AACO,EAAA;AACL,IAAA;AACO,IAAA;AACC,MAAA;AACJ,QAAA;AACF,MAAA;AACD,IAAA;AACF,EAAA;AACH;AAEgB;AACR,EAAA;AACN,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACF;AAEgB;AACd,EAAA;AACF;AAEgB;AACd,EAAA;AACF;AAEgB;AACd,EAAA;AACI,EAAA;AACF,IAAA;AACF,EAAA;AACF;AAEgB;AACd,EAAA;AACF;AAEgB;AACd,EAAA;AACF;AAES;AACG,EAAA;AACZ;AAES;AACE,EAAA;AACX;AAES;AACE,EAAA;AACX;AAES;AAKD,EAAA;AACF,EAAA;AACC,EAAA;AACH,IAAA;AACA,IAAA;AACF,EAAA;AACA,EAAA;AACF;AAES;AACP,EAAA;AACA,EAAA;AACA,EAAA;AACE,IAAA;AACM,MAAA;AACF,QAAA;AACA,QAAA;AACF,MAAA;AACI,MAAA;AACE,QAAA;AACF,UAAA;AACE,YAAA;AACA,YAAA;AACF,UAAA;AACF,QAAA;AACA,QAAA;AACE,UAAA;AACA,UAAA;AACE,YAAA;AAAmD,cAAA;AACpC,c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QAAA;AACI,QAAA;AACJ,QAAA;AACI,QAAA;AACA,QAAA;AACN,MAAA;AACF,IAAA;AACA,IAAA;AACQ,MAAA;AACA,MAAA;AACN,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACI,QAAA;AACJ,QAAA;AACI,QAAA;AACA,QAAA;AACN,MAAA;AACF,IAAA;AACK,IAAA;AACE,MAAA;AACH,QAAA;AACA,QAAA;AACF,MAAA;AACA,MAAA;AACF,IAAA;AACA,IAAA;AACQ,MAAA;AACF,MAAA;AACF,QAAA;AACE,UAAA;AACF,QAAA;AACA,QAAA;AACF,MAAA;AACA,sBAAA;AACF,IAAA;AACF,EAAA;AACO,EAAA;AACT;AAQI;AACE;AACF;AACA;AAEK;AACF,EAAA;AACG,EAAA;AACE,EAAA;AACZ;AAES;AACC,EAAA;AACE,EAAA;AACZ;AAES;AACH,EAAA;AACJ,EAAA;AACE,IAAA;AACF,EAAA;AACA,EAAA;AACK,EAAA;AACL,EAAA;AACA,EAAA;AACA,EAAA;AACE,IAAA;AACF,EAAA;AACF;AAEa;AACP,EAAA;AACE,IAAA;AACI,MAAA;AACA,MAAA;AACN,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACI,QAAA;AACJ,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,sBAAA;AACF,IAAA;AACQ,IAAA;AACN,MAAA;AACE,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACA,sBAAA;AACA,sBAAA;AACF,IAAA;AACF,EAAA;AACM,EAAA;AACA,IAAA;AACI,MAAA;AACA,MAAA;AACN,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACI,QAAA;AACJ,QAAA;AACA,QAAA;AACF,MAAA;AACF,IAAA;AACA,IAAA;AACE,MAAA;AACA,sBAAA;AACF,IAAA;AACQ,IAAA;AACN,MAAA;AACE,QAAA;AACF,MAAA;AACA,MAAA;AACA,MAAA;AACA,sBAAA;AACA,sBAAA;AACF,IAAA;AACF,EAAA;AACF;AAQI;AACE;AACF;AACA;AAEK;AACF,EAA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","file":"/Users/tjg/Desktop/gamepluspackage/packages/api/dist/index.cjs","sourcesContent":[null,"// src/client/grpcClient.ts\nimport { createClient, Client, Transport, Interceptor } from '@connectrpc/connect'\nimport type { CallOptions } from '@connectrpc/connect'\nimport { createConnectTransport, createGrpcWebTransport } from '@connectrpc/connect-web'\nimport { create } from '@bufbuild/protobuf'\nimport type { DescMessage, DescService, MessageInitShape, MessageShape } from '@bufbuild/protobuf'\nimport type { ApiLogger } from './interceptors'\nimport { createBuiltinGrpcWebInvoker } from './invokers/builtinGrpcWebInvoker'\n\nexport class GrpcApiError extends Error {\n name = 'GrpcApiError'\n service: string\n method: unknown\n code?: unknown\n baseUrl?: string\n\n constructor(options: {\n service: string\n method: unknown\n code?: unknown\n baseUrl?: string\n message?: string\n cause?: unknown\n }) {\n super(options.message ?? 'gRPC request failed', { cause: options.cause })\n this.service = options.service\n this.method = options.method\n this.code = options.code\n this.baseUrl = options.baseUrl\n ;(this as any).cause = options.cause\n }\n}\n\nexport type MessageInit<Req extends DescMessage> = Exclude<MessageInitShape<Req>, MessageShape<Req>>\n\nexport type GrpcInvokerUnaryArgs = {\n baseUrl: string\n service: DescService\n methodName: string\n method?: unknown\n request: unknown\n headers: Record<string, string>\n callOptions?: CallOptions\n}\n\nexport interface GrpcInvoker {\n unary(args: GrpcInvokerUnaryArgs): Promise<unknown>\n}\n\n/**\n * gRPC 客户端配置\n */\nexport interface GrpcClientConfig {\n /** 默认 gRPC 服务基础地址(未命中下面任何路由规则时的兜底) (e.g. https://demo.connect.build) */\n baseUrl: string\n /** 按 serviceTypeName 或 namespace 映射 baseUrl(优先级低于 resolveBaseUrl,高于 autoBaseUrlByNamespace) */\n baseUrlByService?: Record<string, string>\n /** 动态解析 baseUrl(最高优先级;用于真实路由与 typeName 不一致的场景) */\n resolveBaseUrl?: (serviceTypeName: string) => string | undefined\n /** 自动按 namespace 拼接路径:baseUrl + '/{namespace}'(仅在未命中上述规则时生效) */\n autoBaseUrlByNamespace?: boolean\n /**\n * 传输协议类型\n * - 'connect': 使用 Connect 协议 (推荐,更轻量,支持 HTTP/1.1 和 HTTP/2)\n * - 'grpc-web': 使用 gRPC-Web 协议 (兼容旧版 gRPC-Web 服务)\n * 默认 'grpc-web'\n */\n protocol?: 'connect' | 'grpc-web' | 'auto'\n /** 是否开启调试日志 */\n debug?: boolean\n /**\n * 自定义 fetch 实现 (用于 React Native 或 Node.js 环境)\n * 如果在 React Native 中,通常不需要传,全局 fetch 可用\n */\n fetch?: typeof globalThis.fetch\n getToken?: () => string | null | Promise<string | null>\n headers?: Record<string, string>\n getHeaders?: () =>\n | Record<string, string>\n | null\n | undefined\n | Promise<Record<string, string> | null | undefined>\n logger?: ApiLogger\n logPayload?:\n | boolean\n | {\n request?: boolean\n response?: boolean\n maxLength?: number\n }\n invoker?: GrpcInvoker | 'builtin'\n}\n\n/**\n * 通用 gRPC 客户端封装 (基于 ConnectRPC)\n */\nexport class GrpcClient {\n private transport: Transport\n private baseUrl: string\n private baseUrlByService?: Record<string, string>\n private resolveBaseUrl?: (serviceTypeName: string) => string | undefined\n private autoBaseUrlByNamespace: boolean\n private protocol: Exclude<GrpcClientConfig['protocol'], 'auto'>\n private fetchImpl?: typeof globalThis.fetch\n private interceptors: Interceptor[]\n private transportByBaseUrl: Map<string, Transport>\n private getToken?: () => string | null | Promise<string | null>\n private headers?: Record<string, string>\n private getHeaders?: () =>\n | Record<string, string>\n | null\n | undefined\n | Promise<Record<string, string> | null | undefined>\n private logger?: ApiLogger\n private logPayload:\n | {\n request: boolean\n response: boolean\n maxLength: number\n }\n | undefined\n private invoker?: GrpcInvoker\n private invokerMode: 'none' | 'builtin' | 'custom'\n private invokerClientByKey: Map<string, unknown>\n\n constructor(config: GrpcClientConfig) {\n this.baseUrl = config.baseUrl\n this.baseUrlByService = config.baseUrlByService\n this.resolveBaseUrl = config.resolveBaseUrl\n this.autoBaseUrlByNamespace = config.autoBaseUrlByNamespace ?? false\n this.fetchImpl = config.fetch\n this.getToken = config.getToken\n this.headers = config.headers\n this.getHeaders = config.getHeaders\n this.logger =\n config.logger ??\n (config.debug\n ? { debug: console.log, info: console.log, warn: console.warn, error: console.error }\n : undefined)\n this.logPayload = this.normalizeLogPayload(config.logPayload)\n\n this.interceptors = [\n this.createRpcFromInterceptor(),\n this.createAuthInterceptor(),\n this.createLogInterceptor(),\n ]\n this.protocol = (config.protocol ?? 'grpc-web') === 'connect' ? 'connect' : 'grpc-web'\n this.transportByBaseUrl = new Map()\n this.transport = this.createTransport(this.baseUrl)\n this.invokerClientByKey = new Map()\n this.invokerMode = config.invoker === 'builtin' ? 'builtin' : config.invoker ? 'custom' : 'none'\n this.invoker =\n config.invoker === 'builtin'\n ? createBuiltinGrpcWebInvoker({ fetch: this.fetchImpl, logger: this.logger })\n : config.invoker\n }\n\n private createTransport(baseUrl: string): Transport {\n const cached = this.transportByBaseUrl.get(baseUrl)\n if (cached) return cached\n\n const transportOptions = {\n baseUrl,\n interceptors: this.interceptors,\n fetch: this.fetchImpl,\n }\n const t =\n this.protocol === 'grpc-web'\n ? createGrpcWebTransport(transportOptions)\n : createConnectTransport(transportOptions)\n this.transportByBaseUrl.set(baseUrl, t)\n return t\n }\n\n private pickBaseUrl(serviceTypeName: string): string {\n const resolved = this.resolveBaseUrl?.(serviceTypeName)\n if (resolved) return resolved\n\n const map = this.baseUrlByService ?? {}\n\n const direct = map[serviceTypeName]\n if (direct) return direct\n\n const ns = serviceTypeName.split('.')[0]\n const byNs = map[ns]\n if (byNs) return byNs\n\n if (this.autoBaseUrlByNamespace && ns) {\n try {\n const u = new URL(this.baseUrl)\n u.pathname = `/${ns.toLowerCase()}`\n u.search = ''\n u.hash = ''\n return u.toString().replace(/\\/$/, '')\n } catch {\n return this.baseUrl\n }\n }\n\n return this.baseUrl\n }\n\n private normalizeHeaders(input: unknown): Record<string, string> {\n if (!input) return {}\n if (typeof Headers !== 'undefined' && input instanceof Headers) {\n const out: Record<string, string> = {}\n input.forEach((value, key) => {\n out[key] = value\n })\n return out\n }\n if (Array.isArray(input)) {\n const out: Record<string, string> = {}\n for (const pair of input) {\n if (!pair) continue\n const [k, v] = pair as any\n if (k == null || v == null) continue\n out[String(k)] = String(v)\n }\n return out\n }\n if (typeof input === 'object') return { ...(input as any) }\n return {}\n }\n\n private hasHeader(headers: Record<string, string>, key: string): boolean {\n const lower = key.toLowerCase()\n for (const k of Object.keys(headers)) {\n if (k.toLowerCase() === lower) return true\n }\n return false\n }\n\n private async attachInvokerHeaders(\n headers: Record<string, string>,\n methodName: string,\n ): Promise<Record<string, string>> {\n const next = { ...headers }\n\n if (methodName) {\n const rpcFromKey = Object.keys(next).find((k) => k.toLowerCase() === 'rpc_from')\n const existing = rpcFromKey ? String((next as any)[rpcFromKey] ?? '') : ''\n if (!rpcFromKey || existing.trim().length === 0) {\n next['rpc_from'] = methodName\n }\n }\n\n if (this.headers) {\n for (const [key, value] of Object.entries(this.headers)) {\n if (!this.hasHeader(next, key)) next[key] = value\n }\n }\n if (this.getHeaders) {\n const extra = await this.getHeaders()\n if (extra) {\n for (const [key, value] of Object.entries(extra)) {\n if (!this.hasHeader(next, key)) next[key] = value\n }\n }\n }\n if (this.getToken && !this.hasHeader(next, 'Authorization')) {\n const token = await this.getToken()\n if (token) next['Authorization'] = `Bearer ${token}`\n }\n\n return next\n }\n\n private getInvokerClientKey(service: DescService, baseUrl: string): string {\n return `${String((service as any)?.typeName ?? '')}@@${baseUrl}`\n }\n\n private getServiceMethodMap(service: DescService): Record<string, unknown> | undefined {\n const out: Record<string, unknown> = {}\n const addMethod = (m: any) => {\n if (!m) return\n const localName = m.localName != null ? String(m.localName) : ''\n const name = m.name != null ? String(m.name) : ''\n if (localName) out[localName] = m\n if (name && !(name in out)) out[name] = m\n }\n\n const direct = (service as any)?.method\n if (direct && typeof direct === 'object') {\n for (const [k, v] of Object.entries(direct as any)) {\n if (v) out[k] = v\n addMethod(v)\n }\n }\n\n const methods = (service as any)?.methods\n if (Array.isArray(methods)) {\n for (const m of methods) addMethod(m)\n } else if (methods && typeof methods === 'object') {\n for (const [k, v] of Object.entries(methods as any)) {\n if (v) out[k] = v\n addMethod(v)\n }\n }\n\n return Object.keys(out).length > 0 ? out : undefined\n }\n\n private getServiceMethodDesc(service: DescService, methodName: string): unknown | undefined {\n const methodMap = this.getServiceMethodMap(service)\n if (!methodMap) return undefined\n\n const direct = (methodMap as any)[methodName]\n if (direct) return direct\n\n for (const m of Object.values(methodMap)) {\n if (!m) continue\n const localName = (m as any).localName != null ? String((m as any).localName) : ''\n const name = (m as any).name != null ? String((m as any).name) : ''\n if (localName === methodName || name === methodName) return m\n }\n\n return undefined\n }\n\n private getServiceViaInvoker<TService extends DescService>(service: TService): Client<TService> {\n const baseUrl = this.pickBaseUrl((service as any).typeName ?? '')\n const key = this.getInvokerClientKey(service, baseUrl)\n const cached = this.invokerClientByKey.get(key)\n if (cached) return cached as any\n\n const methodMap = this.getServiceMethodMap(service)\n const typeName = String((service as any)?.typeName ?? '')\n const client = new Proxy(\n {},\n {\n get: (_target, prop) => {\n if (prop === 'then') return undefined\n if (typeof prop !== 'string') return undefined\n if (methodMap && !(prop in methodMap)) {\n return async () => {\n throw new Error(`gRPC method not found: ${typeName}.${prop}`)\n }\n }\n return async (request: unknown, options?: CallOptions) => {\n return await this.invokeUnary(service, prop, request, options)\n }\n },\n },\n )\n\n this.invokerClientByKey.set(key, client)\n return client as any\n }\n\n private async invokeUnary(\n service: DescService,\n methodName: string,\n request: unknown,\n options?: CallOptions,\n ): Promise<unknown> {\n const typeName = String((service as any)?.typeName ?? '')\n const baseUrl = this.pickBaseUrl(typeName)\n\n try {\n if (this.invoker) {\n this.logger?.debug?.('[Grpc:Invoker]', {\n mode: this.invokerMode,\n service: typeName,\n methodName,\n baseUrl,\n })\n const method = this.getServiceMethodDesc(service, methodName)\n const headers = await this.attachInvokerHeaders(\n this.normalizeHeaders((options as any)?.headers),\n methodName,\n )\n this.logger?.debug?.('[Grpc]', {\n service: typeName,\n methodName,\n baseUrl,\n messageType: (request as any)?.constructor?.name,\n payload: this.formatPayloadForLog(request),\n })\n const res = await this.invoker.unary({\n baseUrl,\n service,\n methodName,\n method,\n request,\n headers,\n callOptions: options,\n })\n this.logger?.debug?.('[Grpc:Response]', {\n service: typeName,\n methodName,\n baseUrl,\n messageType: (res as any)?.constructor?.name,\n payload: this.formatPayloadForLog(res, 'response'),\n })\n return res\n }\n\n const transport = baseUrl === this.baseUrl ? this.transport : this.createTransport(baseUrl)\n const client = createClient(service as any, transport) as any\n const method = client?.[methodName]\n if (typeof method !== 'function') {\n throw new Error(`gRPC method not found: ${typeName}.${methodName}`)\n }\n return await method(request as any, options as any)\n } catch (err) {\n this.logger?.error?.('[Grpc:Error]', { service: typeName, methodName, baseUrl, error: err })\n if (err instanceof GrpcApiError) throw err\n throw new GrpcApiError({\n service: typeName || baseUrl,\n method: methodName,\n code: (err as any)?.code,\n baseUrl,\n message: (err as any)?.message,\n cause: err,\n })\n }\n }\n\n /**\n * 创建特定服务的客户端实例\n * @param service Service Definition (从生成的 _connect.ts 导入)\n */\n getService<TService extends DescService>(service: TService): Client<TService> {\n if (this.invoker) {\n return this.getServiceViaInvoker(service)\n }\n const baseUrl = this.pickBaseUrl((service as any).typeName ?? '')\n const transport = baseUrl === this.baseUrl ? this.transport : this.createTransport(baseUrl)\n return createClient(service, transport)\n }\n\n unary<Req extends DescMessage, Res>(\n schema: Req,\n payload: MessageInit<Req> | undefined,\n call: (req: MessageInitShape<Req>, options?: CallOptions) => Promise<Res>,\n options?: CallOptions,\n ): Promise<Res> {\n const req = create(schema, payload)\n return call(req, options)\n }\n\n /**\n * rpc_from 拦截器\n */\n private createRpcFromInterceptor(): Interceptor {\n return (next) => async (req) => {\n const existing = (req.header as any).get?.('rpc_from')\n if (existing == null) {\n const raw =\n (req as any)?.method?.name ??\n (req as any)?.method?.localName ??\n (typeof (req as any)?.url === 'string'\n ? String((req as any).url)\n .split('?')[0]\n .split('/')\n .pop()\n : undefined)\n\n if (raw) {\n const normalized = raw.length > 0 ? raw[0]!.toLowerCase() + raw.slice(1) : raw\n req.header.set('rpc_from', normalized)\n }\n }\n return next(req)\n }\n }\n\n /**\n * 认证拦截器\n */\n private createAuthInterceptor(): Interceptor {\n return (next) => async (req) => {\n if (this.headers) {\n for (const [key, value] of Object.entries(this.headers)) {\n const existing = (req.header as any).get?.(key)\n if (existing == null) req.header.set(key, value)\n }\n }\n if (this.getHeaders) {\n const extra = await this.getHeaders()\n if (extra) {\n for (const [key, value] of Object.entries(extra)) {\n const existing = (req.header as any).get?.(key)\n if (existing == null) req.header.set(key, value)\n }\n }\n }\n if (this.getToken) {\n const token = await this.getToken()\n if (token) req.header.set('Authorization', `Bearer ${token}`)\n }\n return next(req)\n }\n }\n\n /**\n * 日志拦截器\n */\n private createLogInterceptor(): Interceptor {\n return (next) => async (req) => {\n const debug = this.logger?.debug\n const error = this.logger?.error\n\n debug?.('[Grpc]', {\n method: (req as any).method,\n url: req.url,\n messageType: (req as any)?.message?.constructor?.name,\n payload: this.formatPayloadForLog((req as any)?.message),\n })\n try {\n const res = await next(req)\n debug?.('[Grpc:Response]', {\n url: req.url,\n messageType: (res as any)?.message?.constructor?.name,\n payload: this.formatPayloadForLog((res as any)?.message, 'response'),\n })\n return res\n } catch (err) {\n error?.('[Grpc:Error]', { url: req.url, error: err })\n if (err instanceof GrpcApiError) throw err\n throw new GrpcApiError({\n service: req.url,\n method: (req as any).method,\n code: (err as any)?.code,\n baseUrl: (() => {\n try {\n return new URL(req.url).origin\n } catch {\n return undefined\n }\n })(),\n message: (err as any)?.message,\n cause: err,\n })\n }\n }\n }\n\n private normalizeLogPayload(input: GrpcClientConfig['logPayload']):\n | {\n request: boolean\n response: boolean\n maxLength: number\n }\n | undefined {\n if (!input) return undefined\n if (input === true) return { request: true, response: true, maxLength: 10_000 }\n return {\n request: input.request ?? true,\n response: input.response ?? true,\n maxLength: typeof input.maxLength === 'number' ? input.maxLength : 10_000,\n }\n }\n\n private formatPayloadForLog(value: unknown, kind: 'request' | 'response' = 'request') {\n if (!this.logPayload) return undefined\n if (kind === 'request' && !this.logPayload.request) return undefined\n if (kind === 'response' && !this.logPayload.response) return undefined\n return this.safeSerialize(value, this.logPayload.maxLength)\n }\n\n private safeSerialize(value: unknown, maxLength: number): string | undefined {\n if (value == null) return value == null ? String(value) : undefined\n if (typeof value === 'string')\n return value.length > maxLength ? value.slice(0, maxLength) + '...' : value\n try {\n const seen = new WeakSet<object>()\n const json = JSON.stringify(value, (_key, v) => {\n if (typeof v === 'bigint') return v.toString()\n if (typeof v === 'function') return `[Function${v.name ? ` ${v.name}` : ''}]`\n if (typeof v === 'symbol') return v.toString()\n if (v instanceof Uint8Array) return { __type: 'Uint8Array', byteLength: v.byteLength }\n if (v && typeof v === 'object') {\n if (seen.has(v)) return '[Circular]'\n seen.add(v)\n }\n return v\n })\n return json.length > maxLength ? json.slice(0, maxLength) + '...' : json\n } catch {\n try {\n const s = String(value)\n return s.length > maxLength ? s.slice(0, maxLength) + '...' : s\n } catch {\n return undefined\n }\n }\n }\n}\n","import { fromBinary, toBinary } from '@bufbuild/protobuf'\nimport type { GrpcInvoker } from '../grpcClient'\nimport type { ApiLogger } from '../interceptors'\n\nexport function createBuiltinGrpcWebInvoker(options: {\n fetch?: typeof globalThis.fetch\n logger?: ApiLogger\n}): GrpcInvoker {\n const fetchImpl = options.fetch ?? globalThis.fetch\n const logger = options.logger\n if (!fetchImpl) {\n return {\n unary: async () => {\n throw new Error('fetch is not available in current environment')\n },\n }\n }\n\n const grpcWebEncodeUnary = (messageBytes: Uint8Array): Uint8Array => {\n const out = new Uint8Array(5 + messageBytes.byteLength)\n out[0] = 0\n const view = new DataView(out.buffer, out.byteOffset, out.byteLength)\n view.setUint32(1, messageBytes.byteLength, false)\n out.set(messageBytes, 5)\n return out\n }\n\n const bytesToAscii = (bytes: Uint8Array): string => {\n let s = ''\n for (let i = 0; i < bytes.length; i++) s += String.fromCharCode(bytes[i]!)\n return s\n }\n\n const parseGrpcWebTrailers = (bytes: Uint8Array): Record<string, string> => {\n const text = bytesToAscii(bytes)\n const out: Record<string, string> = {}\n for (const line of text.split('\\r\\n')) {\n if (!line) continue\n const idx = line.indexOf(':')\n if (idx < 0) continue\n const k = line.slice(0, idx).trim().toLowerCase()\n const v = line.slice(idx + 1).trim()\n out[k] = v\n }\n return out\n }\n\n const grpcWebDecodeUnary = (\n body: Uint8Array,\n ): {\n message?: Uint8Array\n trailers: Record<string, string>\n } => {\n let offset = 0\n let message: Uint8Array | undefined\n let trailers: Record<string, string> = {}\n while (offset + 5 <= body.byteLength) {\n const flags = body[offset]!\n const length = new DataView(body.buffer, body.byteOffset + offset + 1, 4).getUint32(0, false)\n offset += 5\n if (offset + length > body.byteLength) break\n const frame = body.subarray(offset, offset + length)\n offset += length\n const isTrailer = (flags & 0x80) === 0x80\n if (isTrailer) {\n trailers = { ...trailers, ...parseGrpcWebTrailers(frame) }\n } else if (message == null) {\n message = frame\n }\n }\n return { message, trailers }\n }\n\n const joinUrl = (baseUrl: string, path: string): string => {\n return baseUrl.replace(/\\/+$/, '') + '/' + path.replace(/^\\/+/, '')\n }\n\n const capitalizeRpcName = (methodName: string): string => {\n if (!methodName) return methodName\n return methodName[0]!.toUpperCase() + methodName.slice(1)\n }\n\n const getGrpcWebPath = (service: any, methodName: string, method: any): string => {\n const typeName = String(service?.typeName ?? '')\n const rpcName = String(method?.name ?? '') || capitalizeRpcName(methodName)\n return `${typeName}/${rpcName}`\n }\n\n const safeDecodeGrpcMessage = (value: string | undefined): string | undefined => {\n if (!value) return value\n try {\n return decodeURIComponent(value)\n } catch {\n return value\n }\n }\n\n return {\n unary: async (args) => {\n const service = String((args.service as any)?.typeName ?? '')\n const startedAt = Date.now()\n let url: string | undefined\n\n const contentType = 'application/grpc-web+proto'\n\n const controller = typeof AbortController !== 'undefined' ? new AbortController() : undefined\n const timeoutMs = (args.callOptions as any)?.timeoutMs\n const timeoutId =\n controller && typeof timeoutMs === 'number'\n ? setTimeout(() => controller.abort(), timeoutMs)\n : undefined\n\n try {\n const method = (args as any).method\n if (!method) {\n throw new Error(`gRPC method not found: ${service}.${args.methodName}`)\n }\n\n url = joinUrl(args.baseUrl, getGrpcWebPath(args.service as any, args.methodName, method))\n const requestBytes = toBinary((method as any).input, args.request as any)\n const body = grpcWebEncodeUnary(requestBytes)\n\n logger?.debug?.('[Grpc:Invoker:Builtin:Start]', {\n service,\n methodName: args.methodName,\n baseUrl: args.baseUrl,\n url,\n timeoutMs,\n requestBytes: requestBytes.byteLength,\n })\n\n const res = await fetchImpl(url, {\n method: 'POST',\n headers: {\n ...args.headers,\n 'content-type': contentType,\n accept: contentType,\n 'x-grpc-web': '1',\n },\n body: body.buffer as ArrayBuffer,\n signal: controller?.signal,\n } as any)\n\n logger?.debug?.('[Grpc:Invoker:Builtin:Http]', {\n service,\n methodName: args.methodName,\n url,\n ok: res.ok,\n status: res.status,\n statusText: res.statusText,\n durationMs: Date.now() - startedAt,\n })\n\n if (!res.ok) {\n throw new Error(`gRPC fetch failed: ${res.status} ${res.statusText}`)\n }\n const raw = new Uint8Array(await res.arrayBuffer())\n const decoded = grpcWebDecodeUnary(raw)\n const statusFromHeaders =\n typeof (res as any).headers?.get === 'function'\n ? (res as any).headers.get('grpc-status')\n : undefined\n const msgFromHeaders =\n typeof (res as any).headers?.get === 'function'\n ? (res as any).headers.get('grpc-message')\n : undefined\n\n const grpcStatus = decoded.trailers['grpc-status'] ?? statusFromHeaders ?? '0'\n const grpcMessage = safeDecodeGrpcMessage(\n decoded.trailers['grpc-message'] ?? msgFromHeaders,\n )\n\n logger?.debug?.('[Grpc:Invoker:Builtin:End]', {\n service,\n methodName: args.methodName,\n url,\n grpcStatus,\n grpcMessage,\n durationMs: Date.now() - startedAt,\n })\n\n if (grpcStatus !== '0') {\n const msg = grpcMessage ?? 'gRPC request failed'\n throw new Error(`gRPC status=${grpcStatus} message=${msg}`)\n }\n if (!decoded.message) throw new Error('gRPC response message missing')\n return fromBinary((method as any).output, decoded.message)\n } catch (error) {\n logger?.error?.('[Grpc:Invoker:Builtin:Error]', {\n service,\n methodName: args.methodName,\n baseUrl: args.baseUrl,\n url,\n durationMs: Date.now() - startedAt,\n error,\n })\n throw error\n } finally {\n if (timeoutId) clearTimeout(timeoutId)\n }\n },\n }\n}\n","// src/client/httpClient.ts\nimport type { ApiLogger } from './interceptors'\n\n/**\n * 统一的 API 响应结构(根据实际后端接口调整)\n */\nexport interface ApiResponse<T = any> {\n code: number\n message: string\n data: T\n}\n\nexport class HttpApiError extends Error {\n name = 'HttpApiError'\n url: string\n method: string\n status?: number\n body?: unknown\n\n constructor(options: {\n url: string\n method: string\n status?: number\n message?: string\n body?: unknown\n cause?: unknown\n }) {\n super(options.message ?? 'HTTP request failed', { cause: options.cause })\n this.url = options.url\n this.method = options.method\n this.status = options.status\n this.body = options.body\n ;(this as any).cause = options.cause\n }\n}\n\nexport interface HttpClientConfig {\n method?: string\n url?: string\n params?: Record<string, any>\n data?: any\n headers?: Record<string, string>\n getHeaders?: () =>\n | Record<string, string>\n | null\n | undefined\n | Promise<Record<string, string> | null | undefined>\n timeout?: number\n returnRaw?: boolean\n getToken?: () => string | null | Promise<string | null>\n logger?: ApiLogger\n}\n\nexport class HttpClient {\n /**\n * HTTP transport 的最小封装:\n * - 统一 baseURL 拼接与 query 序列化\n * - 统一鉴权 token / 额外 headers 挂载\n * - 统一超时与错误结构化(HttpApiError)\n *\n * 该层不做业务 envelope 解包,保持通用。\n */\n private baseURL: string\n private timeout: number\n private getToken?: () => string | null | Promise<string | null>\n private getHeaders?: () =>\n | Record<string, string>\n | null\n | undefined\n | Promise<Record<string, string> | null | undefined>\n private logger?: ApiLogger\n private defaultHeaders: Record<string, string>\n\n constructor(baseURL: string, config?: HttpClientConfig) {\n this.baseURL = baseURL\n this.timeout = config?.timeout ?? 10000\n this.getToken = config?.getToken\n this.getHeaders = config?.getHeaders\n this.logger = config?.logger\n this.defaultHeaders = {\n 'Content-Type': 'application/json',\n ...(config?.headers ?? {}),\n }\n }\n\n private buildURL(path: string, params?: Record<string, any>): string {\n /**\n * 业务意图:\n * - 兼容绝对地址与相对地址(相对地址拼到 baseURL 上)\n * - params 支持数组(同 key 多值),用于常见的筛选/批量参数\n */\n const isAbsolute = /^https?:\\/\\//i.test(path)\n const base = isAbsolute ? path : `${this.baseURL.replace(/\\/$/, '')}/${path.replace(/^\\//, '')}`\n if (!params || Object.keys(params).length === 0) return base\n const url = new URL(base)\n Object.entries(params).forEach(([key, value]) => {\n if (value === undefined || value === null) return\n if (Array.isArray(value)) {\n value.forEach((v) => url.searchParams.append(key, String(v)))\n } else {\n url.searchParams.append(key, String(value))\n }\n })\n return url.toString()\n }\n\n private async attachToken(headers: Record<string, string>) {\n /**\n * 业务意图:如果调用方未显式设置 Authorization,则自动补 token。\n * 这样既能默认走统一鉴权,也允许特定接口覆盖/不带 token。\n */\n if (this.getToken && !headers.Authorization) {\n const token = await this.getToken()\n if (token) {\n headers.Authorization = `Bearer ${token}`\n }\n }\n }\n\n private async attachExtraHeaders(headers: Record<string, string>) {\n /**\n * 业务意图:附加平台公共头(如渠道、语言、设备信息等)。\n * 与 attachToken 一样,只在调用方未设置同名 header 时才注入,避免互相覆盖。\n */\n if (!this.getHeaders) return\n const extra = await this.getHeaders()\n if (!extra) return\n for (const [key, value] of Object.entries(extra)) {\n if (value === undefined || value === null) continue\n if (headers[key] === undefined) {\n headers[key] = String(value)\n }\n }\n }\n\n private async fetchWithTimeout(\n url: string,\n init: RequestInit,\n timeout?: number,\n ): Promise<Response> {\n /**\n * 业务意图:对 fetch 统一增加超时控制。\n * 超时通过 AbortController 实现,调用侧将收到 AbortError。\n */\n const timeoutMs = timeout ?? this.timeout\n if (!timeoutMs || timeoutMs <= 0) {\n return fetch(url, init)\n }\n const controller = new AbortController()\n const id = setTimeout(() => controller.abort(), timeoutMs)\n try {\n return await fetch(url, { ...init, signal: controller.signal })\n } finally {\n clearTimeout(id)\n }\n }\n\n private async handleErrorResponse(options: {\n res: Response\n url: string\n method: string\n }): Promise<never> {\n /**\n * 业务意图:把非 2xx 的 HTTP 响应统一转换为 HttpApiError,\n * 并尽可能把响应体(json/text)带出来,方便上层做错误提示与排查。\n */\n const errorLog = this.logger?.error ?? console.error\n const warnLog = this.logger?.warn ?? console.warn\n let body: any\n const contentType = options.res.headers.get('content-type') || ''\n try {\n if (contentType.includes('application/json')) {\n body = await options.res.json()\n } else {\n body = await options.res.text()\n }\n } catch {\n body = undefined\n }\n errorLog('HTTP Error', { status: options.res.status, url: options.url, method: options.method })\n switch (options.res.status) {\n case 401:\n warnLog('Unauthorized, please login.')\n break\n case 403:\n warnLog('Forbidden.')\n break\n case 404:\n warnLog('Resource not found.')\n break\n case 500:\n errorLog('Internal Server Error.')\n break\n default:\n errorLog('Unknown Error.')\n break\n }\n throw new HttpApiError({\n url: options.url,\n method: options.method,\n status: options.res.status,\n message: `HTTP error ${options.res.status}`,\n body,\n })\n }\n\n private handleNetworkError(error: any) {\n const errorLog = this.logger?.error ?? console.error\n if (error && error.name === 'AbortError') {\n errorLog('HTTP request aborted due to timeout.')\n return\n }\n errorLog('HTTP network error:', error)\n }\n\n async request<T>(config: HttpClientConfig): Promise<T> {\n const startedAt = Date.now()\n const method = (config.method ?? 'GET').toUpperCase()\n const url = this.buildURL(config.url ?? '', config.params)\n const headers: Record<string, string> = {\n ...this.defaultHeaders,\n ...(config.headers ?? {}),\n }\n await this.attachExtraHeaders(headers)\n await this.attachToken(headers)\n\n const init: RequestInit = {\n method,\n headers,\n }\n\n if (method !== 'GET' && method !== 'HEAD' && config.data !== undefined) {\n init.body = typeof config.data === 'string' ? config.data : JSON.stringify(config.data)\n }\n\n let res: Response\n try {\n this.logger?.debug?.('http.request', { method, url })\n res = await this.fetchWithTimeout(url, init, config.timeout)\n } catch (err) {\n this.handleNetworkError(err)\n throw new HttpApiError({\n url,\n method,\n message:\n (err as any)?.name === 'AbortError' ? 'HTTP request timeout' : (err as any)?.message,\n cause: err,\n })\n }\n\n if (!res.ok) {\n await this.handleErrorResponse({ res, url, method })\n }\n\n this.logger?.debug?.('http.response', {\n method,\n url,\n status: res.status,\n durationMs: Date.now() - startedAt,\n })\n\n if (config.returnRaw) {\n return res as unknown as T\n }\n\n const contentType = res.headers.get('content-type') || ''\n if (contentType.includes('application/json')) {\n return (await res.json()) as T\n }\n const text = await res.text()\n return text as unknown as T\n }\n\n get<T>(url: string, params?: any, config?: HttpClientConfig): Promise<T> {\n return this.request<T>({ ...config, method: 'GET', url, params })\n }\n\n post<T>(url: string, data?: any, config?: HttpClientConfig): Promise<T> {\n return this.request<T>({ ...config, method: 'POST', url, data })\n }\n\n put<T>(url: string, data?: any, config?: HttpClientConfig): Promise<T> {\n return this.request<T>({ ...config, method: 'PUT', url, data })\n }\n\n delete<T>(url: string, params?: any, config?: HttpClientConfig): Promise<T> {\n return this.request<T>({ ...config, method: 'DELETE', url, params })\n }\n\n patch<T>(url: string, data?: any, config?: HttpClientConfig): Promise<T> {\n return this.request<T>({ ...config, method: 'PATCH', url, data })\n }\n}\n","/**\n * WebSocket 事件枚举\n */\nimport type { ApiLogger } from './interceptors'\n\nexport enum WsEvent {\n OPEN = '__open__',\n CLOSE = '__close__',\n ERROR = '__error__',\n RECONNECTING = '__reconnecting__',\n RECONNECT_FAILED = '__reconnect_failed__',\n RAW_MESSAGE = '__raw__',\n}\n\nexport type WsTransportErrorType =\n | 'connection_timeout'\n | 'reconnect_failed'\n | 'request_timeout'\n | 'disconnected'\n\nexport class WsTransportError extends Error {\n name = 'WsTransportError'\n type: WsTransportErrorType\n requestId?: string\n functionName?: string\n\n constructor(options: {\n type: WsTransportErrorType\n requestId?: string\n functionName?: string\n message?: string\n cause?: unknown\n }) {\n const message =\n options.message ??\n (options.type === 'connection_timeout'\n ? 'WebSocket connection timeout'\n : options.type === 'reconnect_failed'\n ? 'WebSocket reconnect failed'\n : options.type === 'request_timeout'\n ? 'WebSocket request timeout'\n : 'WebSocket disconnected')\n super(message, { cause: options.cause })\n this.type = options.type\n this.requestId = options.requestId\n this.functionName = options.functionName\n ;(this as any).cause = options.cause\n }\n}\n\nexport interface HeaderConfig {\n version: string\n platformId: string\n isReload: boolean\n deviceType: number | string\n deviceId?: string\n childPlatformId: string\n // clientType: string\n}\n\n/**\n * WebSocket 消息处理函数类型\n */\ntype MessageHandler = (data: any) => void\n\nexport type WsNotifyHandler<T = any> = (payload: T) => void\n\nexport class WsNotifyCenter {\n private listeners = new Map<string, Set<WsNotifyHandler<any>>>()\n\n on<T = any>(type: string, handler: WsNotifyHandler<T>) {\n if (!this.listeners.has(type)) {\n this.listeners.set(type, new Set())\n }\n this.listeners.get(type)!.add(handler as any)\n return () => this.off(type, handler as any)\n }\n\n off<T = any>(type: string, handler: WsNotifyHandler<T>) {\n this.listeners.get(type)?.delete(handler as any)\n }\n\n offAll(type?: string) {\n if (type) {\n this.listeners.delete(type)\n } else {\n this.listeners.clear()\n }\n }\n\n emit(type: string, payload: any) {\n this.listeners.get(type)?.forEach((fn) => {\n fn(payload)\n })\n }\n}\n\nexport interface WsRequestOptions<T = any> {\n /**\n * 业务意图:为单次请求提供“等待连接 + 等待响应”的约束:\n * - timeout:超时失败\n * - responseFunctionName:某些后端会用不同的 functionName 作为响应事件名\n * - matchRequestId:是否用 requestId 严格匹配响应(默认 true)\n * - filter:对响应数据二次过滤(例如只接收特定状态的推送)\n */\n timeout?: number\n filter?: (data: T) => boolean\n responseFunctionName?: string\n matchRequestId?: boolean\n}\n\n/**\n * WebSocket 客户端配置选项\n */\nexport interface WsClientOptions {\n /** WebSocket 服务地址 */\n url: string\n /** 子协议 */\n protocols?: string | string[]\n /** 心跳配置 */\n heartbeat?: {\n /** 心跳间隔 (ms) */\n interval: number\n /** 响应超时时间 (ms) */\n timeout: number\n /** 发送的心跳包类型 (默认为 'ping') */\n pingType?: string\n /** 期望的响应包类型 (默认为 'pong') */\n pongType?: string\n }\n /** 重连配置 */\n reconnect?: {\n /** 是否启用自动重连 */\n enabled: boolean\n /** 最大重试次数 */\n maxRetries: number\n /** 重连间隔 (ms) */\n interval: number\n }\n /** 是否开启调试日志 */\n debug?: boolean\n /** 获取 Token 的函数 */\n getToken?: () => string | null | Promise<string | null>\n logger?: ApiLogger\n}\n\n/**\n * WebSocket 客户端封装\n * 提供自动重连、心跳检测、消息订阅、消息队列等功能\n *\n * Public stable APIs:\n * - connect / disconnect / destroy\n * - request\n * - notify.on\n * - on(WsEvent)\n */\nexport class WsClient {\n /**\n * WS transport 的底层实现:\n * - 连接:connect/waitConnected + 自动重连 + 心跳保活\n * - 通信:send/request,基于 requestId 的请求-响应匹配\n * - 事件:on/off/emit,用 functionName/type 作为事件名分发消息\n *\n * 约定:业务消息体会合并 headerConfig(平台/设备信息等),用于服务端识别来源。\n */\n private ws: WebSocket | null = null\n private connectPromise: Promise<void> | null = null\n private options: WsClientOptions\n private headerConfig: HeaderConfig\n private logger?: ApiLogger\n\n /** 请求 ID 计数器 */\n private requestIndex = 0\n /** 当前重连尝试次数 */\n private retryCount = 0\n /** 重连定时器 */\n private reconnectTimer: number | null = null\n /** 标记是否为手动关闭,手动关闭不触发重连 */\n private manuallyClosed = false\n\n /** 事件监听器集合 (transport / debug / internal) */\n private listeners = new Map<string, Set<MessageHandler>>()\n /** 业务消息通知中心 (notify / business) */\n readonly notify = new WsNotifyCenter()\n private pendingRequests = new Map<\n string,\n {\n responseFunctionName?: string\n filter?: (data: any) => boolean\n resolve: (data: any) => void\n reject: (error: any) => void\n timer: number | null\n }\n >()\n\n /* 心跳相关 */\n private heartbeatTimer: number | null = null\n private lastPongTime = 0\n private lastPingTime = 0\n\n /* 消息队列 (用于在连接未建立时缓存消息) */\n private messageQueue: string[] = []\n\n constructor(options: WsClientOptions, headerConfig?: HeaderConfig) {\n // 合并默认配置\n this.options = {\n ...options,\n reconnect: {\n enabled: true,\n maxRetries: 5,\n interval: 3000,\n ...options.reconnect,\n },\n heartbeat: {\n interval: 30000,\n timeout: 30000,\n pingType: 'ping',\n pongType: 'pong',\n ...options.heartbeat,\n },\n }\n\n this.headerConfig = headerConfig ?? {\n version: '',\n platformId: '',\n isReload: false,\n deviceType: '',\n childPlatformId: '',\n // clientType: 2\n }\n this.logger = options.logger\n }\n\n /* ======================\n * 认证\n * ====================== */\n\n /* ======================\n * 状态 / 连接控制\n * ====================== */\n\n /**\n * 获取当前 WebSocket 状态\n * 0: CONNECTING, 1: OPEN, 2: CLOSING, 3: CLOSED\n */\n get state(): number {\n return this.ws ? this.ws.readyState : WebSocket.CLOSED\n }\n\n /**\n * 是否已连接\n */\n get isConnected(): boolean {\n return this.state === WebSocket.OPEN\n }\n\n /**\n * 获取当前请求 ID\n */\n get requestId(): string {\n this.requestIndex = (this.requestIndex + 1) % 1_000_000\n return `RQ${this.requestIndex}`\n }\n\n /**\n * 等待连接建立\n * @param timeout 超时时间 (ms),默认 10000ms\n */\n async waitConnected(timeout: number = 10000): Promise<void> {\n /**\n * 业务意图:对上层屏蔽“连接尚未建立”的状态差异,\n * request 会先 waitConnected,再发送消息,避免调用方自己管理连接时序。\n */\n if (this.isConnected) {\n return Promise.resolve()\n }\n\n return new Promise((resolve, reject) => {\n let timer: number | null = null\n\n const cleanup = () => {\n if (timer) clearTimeout(timer)\n this.off(WsEvent.OPEN, onOpen)\n this.off(WsEvent.ERROR, onError)\n this.off(WsEvent.RECONNECT_FAILED, onFail)\n }\n\n const onOpen = () => {\n cleanup()\n resolve()\n }\n\n const onError = (_err: any) => {\n // 连接错误不一定代表最终失败(可能会重连),但在 waitConnected 语境下,\n // 如果是首次连接失败,可能希望抛出。\n // 这里我们选择不立即 reject,除非超时或重连失败,因为有重连机制。\n }\n\n const onFail = () => {\n cleanup()\n reject(new WsTransportError({ type: 'reconnect_failed' }))\n }\n\n this.on(WsEvent.OPEN, onOpen)\n this.on(WsEvent.ERROR, onError)\n this.on(WsEvent.RECONNECT_FAILED, onFail)\n\n timer = window.setTimeout(() => {\n cleanup()\n reject(new WsTransportError({ type: 'connection_timeout' }))\n }, timeout)\n\n // 如果当前没有在连接中,尝试连接\n if (!this.ws || this.ws.readyState === WebSocket.CLOSED) {\n this.connect().catch((err) => {\n // connect 本身抛错通常是因为 buildURL 失败\n cleanup()\n reject(err)\n })\n }\n })\n }\n\n /**\n * 建立 WebSocket 连接\n * @param extraParams 可选的 URL 查询参数\n */\n async connect(extraParams?: Record<string, string>) {\n /**\n * 业务意图:连接只允许“同一时间一条 connect 流程”,避免并发调用导致重复建连。\n * connectPromise 用来复用同一次连接过程。\n */\n if (this.connectPromise) {\n return await this.connectPromise\n }\n\n if (\n this.ws &&\n (this.ws.readyState === WebSocket.CONNECTING || this.ws.readyState === WebSocket.OPEN)\n ) {\n this.log('WebSocket is already connected or connecting.')\n return\n }\n\n this.connectPromise = (async () => {\n this.manuallyClosed = false\n let url: string\n try {\n url = await this.buildURL(extraParams)\n } catch (e) {\n this.log('Failed to build URL:', e)\n this.emit(WsEvent.ERROR, e)\n return\n }\n\n this.log(`Connecting to ${url}...`)\n this.ws = new WebSocket(url, this.options.protocols)\n\n this.ws.onopen = () => {\n /**\n * 连接建立后:\n * - 重置重连次数\n * - 启动心跳\n * - 把连接期间缓存的消息队列 flush 出去\n */\n this.log('WebSocket connected.')\n this.retryCount = 0\n this.emit(WsEvent.OPEN, null)\n this.startHeartbeat()\n this.flushMessageQueue()\n }\n\n this.ws.onclose = (event) => {\n this.log(`WebSocket closed. Code: ${event.code}, Reason: ${event.reason}`)\n this.cleanup()\n this.emit(WsEvent.CLOSE, { code: event.code, reason: event.reason })\n if (!this.manuallyClosed) {\n this.tryReconnect()\n }\n }\n\n this.ws.onerror = (err) => {\n this.log('WebSocket error:', err)\n this.emit(WsEvent.ERROR, err)\n }\n\n this.ws.onmessage = (e) => {\n this.handleMessage(e.data)\n }\n })().finally(() => {\n this.connectPromise = null\n })\n\n return await this.connectPromise\n }\n\n /**\n * 主动断开连接\n */\n disconnect() {\n this.manuallyClosed = true\n this.clearReconnect()\n this.cleanup()\n if (this.ws) {\n this.ws.close()\n this.ws = null\n }\n this.log('WebSocket disconnected manually.')\n }\n\n /**\n * 销毁 WsClient 实例\n * - 断开连接\n * - 清除所有定时器\n * - 拒绝所有挂起请求\n * - 移除所有事件监听\n */\n destroy() {\n this.manuallyClosed = true\n this.clearReconnect()\n this.cleanup()\n if (this.ws) {\n this.ws.close()\n this.ws = null\n }\n this.offAll()\n this.notify.offAll()\n this.messageQueue = []\n this.log('WsClient destroyed.')\n }\n\n /* ======================\n * 发送 / 接收\n * ====================== */\n\n private shouldLogIo() {\n return Boolean(this.options.debug || this.logger?.debug)\n }\n\n private maskLogValue(value: any) {\n if (!this.shouldLogIo()) return undefined\n const sensitiveKey = /token|authorization|password|passwd|secret|session/i\n const seen = new WeakSet<object>()\n const replacer = (key: string, val: any) => {\n if (key && sensitiveKey.test(key)) return '[REDACTED]'\n if (!val || typeof val !== 'object') return val\n if (seen.has(val)) return '[Circular]'\n seen.add(val)\n return val\n }\n try {\n const json = JSON.stringify(value, replacer)\n if (!json) return value\n if (json.length > 4000) return json.slice(0, 4000) + '…'\n return JSON.parse(json)\n } catch {\n return value\n }\n }\n\n private createWireMessage(functionName: string, service?: string, payload?: any): {\n requestId: string\n message: string\n } {\n const requestId = payload?.requestId ?? this.requestId\n const message = JSON.stringify({\n functionName,\n data: {\n ...(payload && typeof payload === 'object' ? payload : {}),\n ...this.headerConfig,\n uuid: this.options.protocols,\n requestId,\n },\n service,\n })\n return { requestId, message }\n }\n\n private sendNow(functionName: string, service?: string, payload?: any) {\n const { requestId, message } = this.createWireMessage(functionName, service, payload)\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {\n this.log('[ws:send][blocked]', {\n service,\n functionName,\n requestId,\n data: this.maskLogValue(payload),\n })\n throw new WsTransportError({ type: 'disconnected', requestId, functionName })\n }\n\n this.log('[ws:send]', {\n service,\n functionName,\n requestId,\n data: this.maskLogValue(payload),\n })\n this.ws.send(message)\n }\n\n /**\n * 发送消息\n * @param functionName 业务方法名\n * @param service 服务名\n * @param payload 业务参数\n */\n send(functionName: string, service?: string, payload?: any) {\n const { requestId, message } = this.createWireMessage(functionName, service, payload)\n\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {\n this.log('[ws:send][queued]', {\n service,\n functionName,\n requestId,\n data: this.maskLogValue(payload),\n })\n this.messageQueue.push(message)\n return\n }\n\n this.log('[ws:send]', {\n service,\n functionName,\n requestId,\n data: this.maskLogValue(payload),\n })\n this.ws.send(message)\n }\n\n request<T = any>(functionName: string, payload?: any, options?: WsRequestOptions<T>): Promise<T>\n request<T = any>(\n functionName: string,\n service: string,\n payload?: any,\n options?: WsRequestOptions<T>,\n ): Promise<T>\n async request<T = any>(\n functionName: string,\n payloadOrService?: any,\n payloadOrOptions?: any,\n maybeOptions?: WsRequestOptions<T>,\n ): Promise<T> {\n const hasService = typeof payloadOrService === 'string'\n const service = hasService ? (payloadOrService as string) : undefined\n const payload = hasService ? payloadOrOptions : payloadOrService\n const options: WsRequestOptions<T> | undefined = hasService\n ? (maybeOptions as WsRequestOptions<T> | undefined)\n : (payloadOrOptions as WsRequestOptions<T> | undefined)\n\n const requestId = (payload as any)?.requestId ?? this.requestId\n const responseFunctionName = options?.responseFunctionName ?? functionName\n const matchRequestId = options?.matchRequestId ?? true\n\n await this.waitConnected(options?.timeout)\n\n if (matchRequestId) {\n /**\n * 严格模式:默认启用 requestId 匹配,防止并发调用同一个 functionName 时串包。\n * pendingRequests 用于等待指定 requestId 的响应,并可按 responseFunctionName/filter 做二次约束。\n */\n return new Promise<T>((resolve, reject) => {\n let timer: number | null = null\n\n if (options?.timeout && options.timeout > 0) {\n timer = window.setTimeout(() => {\n this.pendingRequests.delete(requestId)\n this.log('[ws:timeout]', {\n service,\n functionName,\n requestId,\n responseFunctionName,\n timeout: options.timeout,\n })\n reject(\n new WsTransportError({\n type: 'request_timeout',\n requestId,\n functionName: responseFunctionName,\n }),\n )\n }, options.timeout)\n }\n\n this.pendingRequests.set(requestId, {\n responseFunctionName,\n filter: options?.filter ? (options.filter as any) : undefined,\n resolve,\n reject,\n timer,\n })\n\n try {\n this.sendNow(functionName, service as any, { ...(payload ?? {}), requestId })\n } catch (e) {\n this.pendingRequests.delete(requestId)\n if (timer) clearTimeout(timer)\n reject(e)\n }\n })\n }\n\n return new Promise<T>((resolve, reject) => {\n /**\n * 非严格模式:按事件名订阅响应(可选再检查 requestId/filter)。\n * 适合服务端不回传 requestId 或者响应是广播/推送的场景。\n */\n let timer: number | null = null\n\n const off = this.on(responseFunctionName, (data: T) => {\n if (matchRequestId) {\n const dataRequestId = (data as any)?.requestId ?? (data as any)?.data?.requestId\n if (dataRequestId && dataRequestId !== requestId) {\n return\n }\n }\n if (options?.filter && !options.filter(data)) {\n return\n }\n if (timer) clearTimeout(timer)\n off()\n resolve(data)\n })\n\n if (options?.timeout && options.timeout > 0) {\n timer = window.setTimeout(() => {\n off()\n this.log('[ws:timeout]', {\n service,\n functionName,\n requestId,\n responseFunctionName,\n timeout: options.timeout,\n })\n reject(\n new WsTransportError({\n type: 'request_timeout',\n requestId,\n functionName: responseFunctionName,\n }),\n )\n }, options.timeout)\n }\n\n try {\n this.sendNow(functionName, service as any, { ...(payload ?? {}), requestId })\n } catch (e) {\n if (timer) clearTimeout(timer)\n off()\n reject(e)\n }\n })\n }\n\n /**\n * 处理接收到的原始消息\n * @param raw 原始字符串数据\n */\n private handleMessage(raw: string) {\n /**\n * 业务意图:兼容两种常见服务端消息结构:\n * 1) { type, payload, requestId? }\n * 2) { functionName, data/payload, requestId? }\n *\n * 同时支持把心跳 pong 拦截掉,不进入业务分发。\n */\n try {\n const msg = JSON.parse(raw)\n\n const deriveNotifyAlias = (name: string): string | undefined => {\n if (!name.startsWith('notify')) return\n const rest = name.slice('notify'.length)\n if (!rest) return\n return rest[0]!.toLowerCase() + rest.slice(1)\n }\n\n if (msg && typeof msg === 'object' && typeof msg.type === 'string') {\n const { type, payload } = msg\n if (this.isPong(type)) {\n this.lastPongTime = Date.now()\n return\n }\n if (this.isAliveAck(msg, payload)) {\n this.lastPongTime = Date.now()\n return\n }\n const requestId =\n msg.requestId ??\n (payload && typeof payload === 'object'\n ? ((payload as any).requestId ?? (payload as any)?.data?.requestId)\n : undefined)\n this.log('[ws:recv]', {\n service: (msg as any).service,\n functionName: type,\n requestId,\n data: this.maskLogValue(payload),\n })\n const resolved = requestId ? this.tryResolvePending(requestId, type, payload) : false\n const alias = deriveNotifyAlias(type)\n if (!resolved) {\n this.notify.emit(type, payload)\n if (alias && alias !== type) {\n this.notify.emit(alias, payload)\n }\n }\n this.emit(type, payload)\n if (alias && alias !== type) {\n this.emit(alias, payload)\n }\n return\n }\n\n if (msg && typeof msg === 'object' && typeof msg.functionName === 'string') {\n const functionName = msg.functionName\n const payload = msg.data ?? msg.payload\n if (this.isPong(functionName)) {\n this.lastPongTime = Date.now()\n return\n }\n if (this.isAliveAck(msg, payload)) {\n this.lastPongTime = Date.now()\n return\n }\n const requestId =\n msg.requestId ??\n (payload && typeof payload === 'object'\n ? ((payload as any).requestId ?? (payload as any)?.data?.requestId)\n : undefined)\n this.log('[ws:recv]', {\n service: (msg as any).service,\n functionName,\n requestId,\n data: this.maskLogValue(payload),\n })\n const resolved = requestId\n ? this.tryResolvePending(requestId, functionName, payload)\n : false\n const alias = deriveNotifyAlias(functionName)\n if (!resolved) {\n this.notify.emit(functionName, payload)\n if (alias && alias !== functionName) {\n this.notify.emit(alias, payload)\n }\n }\n this.emit(functionName, payload)\n if (alias && alias !== functionName) {\n this.emit(alias, payload)\n }\n return\n }\n\n this.emit(WsEvent.RAW_MESSAGE, msg)\n } catch (e) {\n // 非 JSON 格式或其他解析错误,作为原始消息发出\n this.emit(WsEvent.RAW_MESSAGE, raw)\n this.log('Failed to parse message:', raw, e)\n }\n }\n\n private tryResolvePending(requestId: string, functionName: string, payload: any): boolean {\n const pending = this.pendingRequests.get(requestId)\n if (!pending) return false\n if (pending.responseFunctionName && pending.responseFunctionName !== functionName) return false\n if (pending.filter && !pending.filter(payload)) return false\n this.pendingRequests.delete(requestId)\n if (pending.timer) clearTimeout(pending.timer)\n this.log('[ws:resp]', {\n functionName,\n requestId,\n data: this.maskLogValue(payload),\n })\n pending.resolve(payload)\n return true\n }\n\n /**\n * 发送队列中缓存的消息\n */\n private flushMessageQueue() {\n if (this.messageQueue.length === 0) return\n\n this.log(`Flushing ${this.messageQueue.length} queued messages.`)\n while (this.messageQueue.length > 0 && this.ws?.readyState === WebSocket.OPEN) {\n const message = this.messageQueue.shift()\n if (message) {\n this.ws.send(message)\n }\n }\n }\n\n /* ======================\n * 心跳 + 断线判定\n * ====================== */\n\n private startHeartbeat() {\n /**\n * 业务意图:通过 ping/pong 做连接保活和断线判定。\n * 当超过 timeout 未收到 pong,会触发 forceReconnect,交给 tryReconnect 流程处理。\n */\n const hb = this.options.heartbeat\n if (!hb) return\n\n this.lastPongTime = Date.now()\n this.lastPingTime = 0\n // 清除旧的定时器(如果有)\n this.stopHeartbeat()\n\n const ping = () => {\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) return\n this.lastPingTime = Date.now()\n const requestId = this.requestId\n const deviceType =\n this.headerConfig.deviceType === '' || this.headerConfig.deviceType === undefined\n ? 1\n : this.headerConfig.deviceType\n const message = JSON.stringify({\n service: 'connection',\n functionName: 'isAlive',\n data: {\n _heartBeat: true,\n deviceType,\n deviceId: this.headerConfig.deviceId ?? '',\n platformId: this.headerConfig.platformId ?? '',\n version: this.headerConfig.version ?? '',\n uuid: this.options.protocols,\n requestId,\n childPlatformId: this.headerConfig.childPlatformId ?? '',\n },\n })\n this.ws.send(message)\n }\n\n ping()\n\n this.heartbeatTimer = window.setInterval(() => {\n const now = Date.now()\n\n if (\n this.lastPingTime > 0 &&\n now - this.lastPongTime > hb.timeout &&\n now - this.lastPingTime > hb.timeout\n ) {\n this.log('Heartbeat timeout, forcing reconnect...')\n this.forceReconnect()\n return\n }\n\n ping()\n }, hb.interval)\n }\n\n private stopHeartbeat() {\n if (this.heartbeatTimer) {\n clearInterval(this.heartbeatTimer)\n this.heartbeatTimer = null\n }\n }\n\n private forceReconnect() {\n this.cleanup()\n if (this.ws) {\n this.ws.close() // 这会触发 onclose,进而触发 tryReconnect\n this.ws = null\n }\n }\n\n /* ======================\n * 重连机制\n * ====================== */\n\n private tryReconnect() {\n /**\n * 业务意图:断线后按配置重连,超出最大次数则发出 RECONNECT_FAILED 事件。\n * 上层可监听该事件做降级提示或切换为 HTTP。\n */\n const cfg = this.options.reconnect\n if (!cfg?.enabled) return\n\n // 如果重试次数超过限制,停止重连并触发失败事件\n if (this.retryCount >= cfg.maxRetries) {\n this.log(`Max retry attempts (${cfg.maxRetries}) reached. Giving up.`)\n this.emit(WsEvent.RECONNECT_FAILED, null)\n return\n }\n\n this.retryCount++\n const delay = cfg.interval\n this.log(`Attempting reconnect (${this.retryCount}/${cfg.maxRetries}) in ${delay}ms...`)\n this.emit(WsEvent.RECONNECTING, {\n attempt: this.retryCount,\n maxRetries: cfg.maxRetries,\n interval: delay,\n })\n\n this.reconnectTimer = window.setTimeout(() => {\n this.connect()\n }, delay)\n }\n\n private clearReconnect() {\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer)\n this.reconnectTimer = null\n }\n }\n\n /* ======================\n * 事件系统\n * ====================== */\n\n /**\n * 注册事件监听器\n * @param type 事件类型\n * @param handler 处理函数\n * @returns 取消监听的函数\n */\n on(type: string, handler: MessageHandler) {\n if (!this.listeners.has(type)) {\n this.listeners.set(type, new Set())\n }\n this.listeners.get(type)!.add(handler)\n return () => this.off(type, handler)\n }\n\n /**\n * 移除事件监听器\n * @param type 事件类型\n * @param handler 处理函数\n */\n off(type: string, handler: MessageHandler) {\n this.listeners.get(type)?.delete(handler)\n }\n\n /**\n * 移除某类事件的所有监听器,或移除所有监听器\n * @param type 事件类型,不传则移除所有\n */\n offAll(type?: string) {\n if (type) {\n this.listeners.delete(type)\n } else {\n this.listeners.clear()\n }\n }\n\n private emit(type: string, data: any) {\n this.listeners.get(type)?.forEach((fn) => {\n try {\n fn(data)\n } catch (e) {\n this.log(`Error in listener for event '${type}':`, e)\n }\n })\n }\n\n /* ======================\n * 工具方法\n * ====================== */\n\n private cleanup() {\n this.stopHeartbeat()\n\n // 清理所有挂起的请求,防止连接断开后请求一直处于 pending 状态\n for (const [requestId, pending] of this.pendingRequests) {\n pending.reject(\n new WsTransportError({\n type: 'disconnected',\n requestId,\n functionName: pending.responseFunctionName,\n }),\n )\n if (pending.timer) clearTimeout(pending.timer)\n }\n this.pendingRequests.clear()\n\n // 注意:这里不应该清除 messageQueue,因为重连后可能需要发送\n }\n\n private isPong(type: string) {\n return type === (this.options.heartbeat?.pongType ?? 'pong')\n }\n\n private isAliveAck(msg: any, payload: any) {\n if (!msg || typeof msg !== 'object') return false\n if (msg.service !== 'connection') return false\n if (msg.functionName !== 'isAlive' && msg.type !== 'isAlive') return false\n return payload && typeof payload === 'object' && (payload as any).status === 200\n }\n\n private async buildURL(params?: Record<string, string>) {\n /**\n * 业务意图:构造最终 WS 连接地址:\n * - 允许用户只传 host/path(自动补 wss://)\n * - 浏览器 WebSocket 不支持自定义 headers,因此 token 通过 query 参数携带\n * - extraParams 用于按需追加查询参数(如 env、灰度标记等)\n */\n let urlStr = this.options.url\n if (!/^\\w+:\\/\\//.test(urlStr)) {\n urlStr = `wss://${urlStr}`\n }\n const url = new URL(urlStr)\n\n // 合并 Token\n if (this.options.getToken) {\n const token = await this.options.getToken()\n if (token) {\n url.searchParams.append('token', token)\n }\n }\n\n // 合并传入的参数\n if (params) {\n Object.entries(params).forEach(([key, value]) => {\n url.searchParams.append(key, value)\n })\n }\n\n return url.toString()\n }\n\n private log(...args: any[]) {\n if (this.logger?.debug) {\n this.logger.debug('[WsClient]', args)\n return\n }\n if (this.options.debug) {\n console.log('[WsClient]', ...args)\n }\n }\n}\n","import { GrpcClient, GrpcClientConfig } from './grpcClient'\nimport { HttpClient, HttpClientConfig } from './httpClient'\nimport { WsClient, WsClientOptions, HeaderConfig } from './wsClient'\nimport type { ApiLogger } from './interceptors'\nimport type { ApiErrorHandler } from './unifiedApiClient'\nimport type { KeyValueStorage } from '../utils/storage'\n\nexport interface RequestApiConfig {\n http?: {\n baseUrl: string\n config?: HttpClientConfig\n }\n ws?: WsClientOptions\n grpc?: GrpcClientConfig\n headerConfig: HeaderConfig\n defaultTransport?: 'http' | 'ws' | 'grpc' | 'auto'\n requestApiInitWaitMs?: number\n auth?: {\n /**\n * 提供给三种 transport 复用的鉴权能力:\n * - HTTP:注入 Authorization header\n * - gRPC:注入 Authorization header\n * - WS:受浏览器限制无法自定义 header,因此在 URL query 中附带 token\n */\n getToken?: () => string | null | Promise<string | null>\n /**\n * 获取额外公共头(平台信息、灰度、语言等)。\n * HTTP/gRPC 会以 header 形式携带;WS 侧由 HeaderConfig 写入消息体。\n */\n getHeaders?: () =>\n | Record<string, string>\n | null\n | undefined\n | Promise<Record<string, string> | null | undefined>\n }\n logger?: ApiLogger\n onApiError?: ApiErrorHandler\n uniqueKeyStorage?: KeyValueStorage | null\n}\n\n/**\n * 统一请求 API 封装\n * 集合了 HttpClient, WsClient, GrpcClient\n * 提供统一的 Token 管理和访问入口\n */\nexport class RequestApi {\n /**\n * 统一的 transport 容器:\n * - 负责把全局 auth/logger/headerConfig 注入到各 transport\n * - 上层(SDK / UnifiedApiClient)不需要关心具体如何拼接 token/header\n */\n public http: HttpClient\n public ws: WsClient\n public grpc: GrpcClient\n\n constructor(config: RequestApiConfig) {\n const getToken = config.auth?.getToken\n const getHeaders = config.auth?.getHeaders\n // 初始化 HttpClient\n const httpBaseUrl = config.http?.baseUrl || ''\n const httpConfig = config.http?.config\n this.http = new HttpClient(httpBaseUrl, {\n ...httpConfig,\n getToken: httpConfig?.getToken ?? getToken,\n getHeaders: httpConfig?.getHeaders ?? getHeaders,\n logger: httpConfig?.logger ?? config.logger,\n })\n\n // 初始化 WsClient\n this.ws = new WsClient(\n {\n ...(config.ws || { url: '' }),\n getToken: config.ws?.getToken ?? getToken,\n logger: config.ws?.logger ?? config.logger,\n },\n config.headerConfig,\n )\n\n // 初始化 GrpcClient\n this.grpc = new GrpcClient({\n ...(config.grpc || { baseUrl: '' }),\n getToken: config.grpc?.getToken ?? getToken,\n headers: config.grpc?.headers,\n getHeaders: config.grpc?.getHeaders ?? getHeaders,\n logger: config.grpc?.logger ?? config.logger,\n })\n }\n}\n","import { WsClient, WsRequestOptions } from './wsClient'\n\nexport type WsBusinessEnvelope<T = any> =\n | {\n success?: boolean\n status?: number\n code?: number\n message?: string\n data?: T\n requestId?: string\n }\n | T\n\nexport type WsAdapterMatch =\n | {\n service?: string | RegExp\n functionName?: string | RegExp\n }\n | ((ctx: { service: string; functionName: string }) => boolean)\n\nexport type WsResponseAdapter<TRes = any, TData = any> = {\n match: WsAdapterMatch\n isSuccess?: (res: TRes) => boolean\n unwrap?: (res: TRes) => TData\n getBizCode?: (res: TRes) => number | undefined\n getCode?: (res: TRes) => number | undefined\n getStatus?: (res: TRes) => number | undefined\n getMessage?: (res: TRes) => string | undefined\n getRequestId?: (res: TRes) => string | undefined\n}\n\nexport type WsApiErrorKind = 'transport_error' | 'biz_error' | 'unknown_error'\n\nexport class WsApiError extends Error {\n name = 'WsApiError'\n kind: WsApiErrorKind\n service: string\n functionName: string\n requestId?: string\n code?: number\n status?: number\n\n constructor(options: {\n kind?: WsApiErrorKind\n service: string\n functionName: string\n requestId?: string\n code?: number\n status?: number\n message?: string\n cause?: unknown\n }) {\n super(options.message ?? 'WS request failed', { cause: options.cause })\n this.kind = options.kind ?? 'unknown_error'\n this.service = options.service\n this.functionName = options.functionName\n this.requestId = options.requestId\n this.code = options.code\n this.status = options.status\n ;(this as any).cause = options.cause\n }\n}\n\nexport interface WsRpcClientOptions {\n /**\n * 业务意图:WS 接口通常没有统一的 HTTP status,\n * 这里通过约定的 envelope(success/code/status/message/data)做标准化处理。\n */\n defaultTimeout?: number\n /**\n * 是否自动把 { data } 解包返回给调用方。\n * - true:更贴近业务使用习惯(拿到就是 TData)\n * - false:保留原始 envelope,便于上层自定义处理\n */\n unwrapData?: boolean\n /**\n * 自定义成功判断逻辑(用于不同后端约定)。\n */\n isSuccess?: (value: any) => boolean\n /**\n * 自定义错误文案提取逻辑(用于不同后端约定)。\n */\n getMessage?: (value: any) => string | undefined\n getRequestId?: (value: any) => string | undefined\n getCode?: (value: any) => number | undefined\n getStatus?: (value: any) => number | undefined\n onError?: (\n error: WsApiError,\n source: { service: string; functionName: string; requestId?: string },\n ) => void\n}\n\nexport class WsRpcClient {\n readonly ws: WsClient\n private options: WsRpcClientOptions\n private adapters: WsResponseAdapter[] = []\n private defaultAdapter: WsResponseAdapter | undefined\n\n constructor(ws: WsClient, options: WsRpcClientOptions = {}) {\n this.ws = ws\n this.options = {\n defaultTimeout: options.defaultTimeout ?? 10000,\n unwrapData: options.unwrapData ?? true,\n isSuccess: options.isSuccess,\n getMessage: options.getMessage,\n getRequestId: options.getRequestId,\n getCode: options.getCode,\n getStatus: options.getStatus,\n onError: options.onError,\n }\n }\n\n addAdapter(adapter: WsResponseAdapter, options?: { prepend?: boolean }) {\n const prepend = options?.prepend ?? true\n if (prepend) {\n this.adapters.unshift(adapter)\n } else {\n this.adapters.push(adapter)\n }\n return () => {\n this.adapters = this.adapters.filter((a) => a !== adapter)\n }\n }\n\n clearAdapters() {\n this.adapters = []\n }\n\n setDefaultAdapter(adapter?: WsResponseAdapter) {\n this.defaultAdapter = adapter\n }\n\n private matchAdapter(match: WsAdapterMatch, service: string, functionName: string): boolean {\n if (typeof match === 'function') return match({ service, functionName })\n if (match.service !== undefined) {\n if (typeof match.service === 'string') {\n if (match.service !== service) return false\n } else if (!match.service.test(service)) {\n return false\n }\n }\n if (match.functionName !== undefined) {\n if (typeof match.functionName === 'string') {\n if (match.functionName !== functionName) return false\n } else if (!match.functionName.test(functionName)) {\n return false\n }\n }\n return true\n }\n\n private resolveAdapter(service: string, functionName: string): WsResponseAdapter | undefined {\n for (const adapter of this.adapters) {\n if (this.matchAdapter(adapter.match, service, functionName)) return adapter\n }\n if (\n this.defaultAdapter &&\n this.matchAdapter(this.defaultAdapter.match, service, functionName)\n ) {\n return this.defaultAdapter\n }\n return undefined\n }\n\n private isOkWithAdapter(value: any, adapter: WsResponseAdapter | undefined): boolean {\n if (adapter?.isSuccess) return adapter.isSuccess(value)\n return this.isOk(value)\n }\n\n private extractRequestIdWithAdapter(\n value: unknown,\n adapter: WsResponseAdapter | undefined,\n ): string | undefined {\n const mapped = adapter?.getRequestId?.(value as any)\n const normalized = this.normalizeString(mapped)\n if (normalized) return normalized\n return this.extractRequestId(value)\n }\n\n private extractCodeWithAdapter(\n value: unknown,\n adapter: WsResponseAdapter | undefined,\n ): number | undefined {\n const mapped = adapter?.getBizCode?.(value as any) ?? adapter?.getCode?.(value as any)\n const normalized = this.normalizeNumber(mapped)\n if (normalized !== undefined) return normalized\n return this.extractCode(value)\n }\n\n private extractStatusWithAdapter(\n value: unknown,\n adapter: WsResponseAdapter | undefined,\n ): number | undefined {\n const mapped = adapter?.getStatus?.(value as any)\n const normalized = this.normalizeNumber(mapped)\n if (normalized !== undefined) return normalized\n return this.extractStatus(value)\n }\n\n private getErrorMessageWithAdapter(\n value: any,\n adapter: WsResponseAdapter | undefined,\n ): string | undefined {\n const mapped = adapter?.getMessage?.(value)\n const normalized = this.normalizeString(mapped)\n if (normalized) return normalized\n return this.getErrorMessage(value)\n }\n\n private normalizeNumber(value: unknown): number | undefined {\n if (typeof value === 'number' && Number.isFinite(value)) return value\n if (typeof value === 'string') {\n const trimmed = value.trim()\n if (!trimmed) return undefined\n const asNumber = Number(trimmed)\n return Number.isFinite(asNumber) ? asNumber : undefined\n }\n return undefined\n }\n\n private normalizeString(value: unknown): string | undefined {\n if (typeof value === 'string') {\n const trimmed = value.trim()\n return trimmed.length > 0 ? trimmed : undefined\n }\n if (typeof value === 'number' && Number.isFinite(value)) return String(value)\n return undefined\n }\n\n private pickField(value: unknown, keys: string[]): unknown {\n if (!value || typeof value !== 'object') return undefined\n const anyValue = value as any\n for (const key of keys) {\n if (anyValue[key] !== undefined) return anyValue[key]\n }\n const data = anyValue.data\n if (data && typeof data === 'object') {\n for (const key of keys) {\n if ((data as any)[key] !== undefined) return (data as any)[key]\n }\n }\n return undefined\n }\n\n private extractRequestId(value: unknown): string | undefined {\n if (this.options.getRequestId) {\n const mapped = this.options.getRequestId(value as any)\n const normalized = this.normalizeString(mapped)\n if (normalized) return normalized\n }\n if (!value || typeof value !== 'object') return undefined\n const anyValue = value as any\n const id = anyValue.requestId ?? anyValue?.data?.requestId\n return this.normalizeString(id)\n }\n\n private extractCode(value: unknown): number | undefined {\n if (this.options.getCode) {\n const mapped = this.options.getCode(value as any)\n const normalized = this.normalizeNumber(mapped)\n if (normalized !== undefined) return normalized\n }\n const raw = this.pickField(value, ['code', 'errCode', 'errorCode', 'resultCode'])\n return this.normalizeNumber(raw)\n }\n\n private extractStatus(value: unknown): number | undefined {\n if (this.options.getStatus) {\n const mapped = this.options.getStatus(value as any)\n const normalized = this.normalizeNumber(mapped)\n if (normalized !== undefined) return normalized\n }\n const raw = this.pickField(value, ['status', 'statusCode', 'httpStatus', 'http_code'])\n return this.normalizeNumber(raw)\n }\n\n call<TPayload = any, TData = any>(\n functionName: string,\n service: string,\n payload?: TPayload,\n options?: WsRequestOptions<WsBusinessEnvelope<TData>>,\n ): Promise<TData>\n call<TPayload = any, TData = any>(params: {\n functionName: string\n service: string\n payload?: TPayload\n options?: WsRequestOptions<WsBusinessEnvelope<TData>>\n }): Promise<TData>\n async call<TPayload = any, TData = any>(\n functionNameOrParams:\n | string\n | {\n functionName: string\n service: string\n payload?: TPayload\n options?: WsRequestOptions<WsBusinessEnvelope<TData>>\n },\n service?: string,\n payload?: TPayload,\n options?: WsRequestOptions<WsBusinessEnvelope<TData>>,\n ): Promise<TData> {\n if (typeof functionNameOrParams === 'string') {\n return await this.request(functionNameOrParams, service as string, payload, options)\n }\n\n return await this.request(\n functionNameOrParams.functionName,\n functionNameOrParams.service,\n functionNameOrParams.payload,\n functionNameOrParams.options,\n )\n }\n\n callRaw<TPayload = any, TRes = any>(\n functionName: string,\n service: string,\n payload?: TPayload,\n options?: WsRequestOptions<TRes>,\n ): Promise<TRes>\n callRaw<TPayload = any, TRes = any>(params: {\n functionName: string\n service: string\n payload?: TPayload\n options?: WsRequestOptions<TRes>\n }): Promise<TRes>\n async callRaw<TPayload = any, TRes = any>(\n functionNameOrParams:\n | string\n | {\n functionName: string\n service: string\n payload?: TPayload\n options?: WsRequestOptions<TRes>\n },\n service?: string,\n payload?: TPayload,\n options?: WsRequestOptions<TRes>,\n ): Promise<TRes> {\n if (typeof functionNameOrParams === 'string') {\n return await this.requestRaw(functionNameOrParams, service as string, payload, options)\n }\n\n return await this.requestRaw(\n functionNameOrParams.functionName,\n functionNameOrParams.service,\n functionNameOrParams.payload,\n functionNameOrParams.options,\n )\n }\n\n async request<TPayload = any, TData = any>(\n functionName: string,\n service: string,\n payload?: TPayload,\n options?: WsRequestOptions<WsBusinessEnvelope<TData>>,\n ): Promise<TData> {\n /**\n * 业务意图:\n * - 统一包一层,把底层 WsClient.request 的连接/超时/订阅细节隐藏起来\n * - 把 transport 级异常转换为 WsApiError(kind 属于 transport_error)\n * - 把业务失败(code/status/success)也转换为 WsApiError(kind 属于 biz_error)\n */\n const requestId = this.extractRequestId(payload) ?? this.ws.requestId\n const finalPayload =\n payload && typeof payload === 'object' ? { ...payload, requestId } : payload\n\n let res: WsBusinessEnvelope<TData>\n try {\n res = await this.ws.request<WsBusinessEnvelope<TData>>(functionName, service, finalPayload, {\n timeout: options?.timeout ?? this.options.defaultTimeout,\n responseFunctionName: options?.responseFunctionName,\n matchRequestId: options?.matchRequestId,\n filter: options?.filter,\n })\n } catch (err) {\n const wrapped = new WsApiError({\n kind: 'transport_error',\n service,\n functionName,\n requestId,\n message: (err as any)?.message,\n cause: err,\n })\n try {\n this.options.onError?.(wrapped, { service, functionName, requestId })\n } catch {\n void 0\n }\n throw wrapped\n }\n\n const adapter = this.resolveAdapter(service, functionName)\n\n if (!this.isOkWithAdapter(res, adapter)) {\n const responseRequestId = this.extractRequestIdWithAdapter(res, adapter) ?? requestId\n const wrapped = new WsApiError({\n kind: 'biz_error',\n service,\n functionName,\n requestId: responseRequestId,\n code: this.extractCodeWithAdapter(res, adapter),\n status: this.extractStatusWithAdapter(res, adapter),\n message: this.getErrorMessageWithAdapter(res, adapter) ?? 'Request failed',\n })\n try {\n this.options.onError?.(wrapped, { service, functionName, requestId: responseRequestId })\n } catch {\n void 0\n }\n throw wrapped\n }\n\n if (adapter?.unwrap) {\n return adapter.unwrap(res as any) as TData\n }\n\n if (this.options.unwrapData && res && typeof res === 'object' && 'data' in (res as any)) {\n return (res as any).data as TData\n }\n\n return res as TData\n }\n\n async requestRaw<TPayload = any, TRes = any>(\n functionName: string,\n service: string,\n payload?: TPayload,\n options?: WsRequestOptions<TRes>,\n ): Promise<TRes> {\n const requestId = this.extractRequestId(payload) ?? this.ws.requestId\n const finalPayload =\n payload && typeof payload === 'object' ? { ...payload, requestId } : payload\n\n let res: TRes\n try {\n res = await this.ws.request<TRes>(functionName, service, finalPayload, {\n timeout: options?.timeout ?? this.options.defaultTimeout,\n responseFunctionName: options?.responseFunctionName,\n matchRequestId: options?.matchRequestId,\n filter: options?.filter,\n })\n } catch (err) {\n const wrapped = new WsApiError({\n kind: 'transport_error',\n service,\n functionName,\n requestId,\n message: (err as any)?.message,\n cause: err,\n })\n try {\n this.options.onError?.(wrapped, { service, functionName, requestId })\n } catch {\n void 0\n }\n throw wrapped\n }\n\n const adapter = this.resolveAdapter(service, functionName)\n\n if (!this.isOkWithAdapter(res, adapter)) {\n const responseRequestId = this.extractRequestIdWithAdapter(res, adapter) ?? requestId\n const wrapped = new WsApiError({\n kind: 'biz_error',\n service,\n functionName,\n requestId: responseRequestId,\n code: this.extractCodeWithAdapter(res, adapter),\n status: this.extractStatusWithAdapter(res, adapter),\n message: this.getErrorMessageWithAdapter(res, adapter) ?? 'Request failed',\n })\n try {\n this.options.onError?.(wrapped, { service, functionName, requestId: responseRequestId })\n } catch {\n void 0\n }\n throw wrapped\n }\n\n return res\n }\n\n private isOk(value: any): boolean {\n /**\n * 默认成功判定:\n * - success 为 boolean:直接使用\n * - status 为 number:认为 200 表示成功(优先级高于 code)\n * - code 为 number:认为 0 或 200 表示成功(仅在缺少 status 时生效)\n * - 非对象:认为成功(兼容服务端直接返回数据的情况)\n */\n if (this.options.isSuccess) return this.options.isSuccess(value)\n if (!value || typeof value !== 'object') return true\n\n const rawSuccess = this.pickField(value, ['success'])\n if (rawSuccess !== undefined) {\n if (typeof rawSuccess === 'boolean') return rawSuccess\n if (typeof rawSuccess === 'string') {\n const lowered = rawSuccess.trim().toLowerCase()\n if (lowered === 'true') return true\n if (lowered === 'false') return false\n }\n }\n\n const rawStatus = this.pickField(value, ['status', 'statusCode', 'httpStatus', 'http_code'])\n if (rawStatus !== undefined) {\n const status = this.normalizeNumber(rawStatus)\n return typeof status === 'number' ? status === 200 : false\n }\n\n const rawCode = this.pickField(value, ['code', 'errCode', 'errorCode', 'resultCode'])\n if (rawCode !== undefined) {\n const code = this.normalizeNumber(rawCode)\n return typeof code === 'number' ? code === 0 || code === 200 : false\n }\n\n if (this.options.unwrapData && 'data' in (value as any)) return true\n\n return true\n }\n\n private getErrorMessage(value: any): string | undefined {\n if (this.options.getMessage) return this.options.getMessage(value)\n if (!value || typeof value !== 'object') return undefined\n const msg = this.pickField(value, [\n 'message',\n 'msg',\n 'error',\n 'errMsg',\n 'errmsg',\n 'errorMessage',\n ])\n return this.normalizeString(msg)\n }\n}\n","import type { EndpointSpec } from '../spec/endpoint'\nimport type { GenService } from '@bufbuild/protobuf/codegenv2'\nimport { create } from '@bufbuild/protobuf'\nimport { GrpcApiError, GrpcClient } from './grpcClient'\nimport { HttpApiError, HttpClient } from './httpClient'\nimport { WsApiError, WsRpcClient } from './wsRpcClient'\nimport {\n ApiCallContext,\n ApiInterceptor,\n composeInterceptors,\n isBizError,\n isTransportError,\n} from './interceptors'\n\nexport type ApiErrorCategory = 'biz' | 'transport' | 'unknown'\n\nexport type ApiError = {\n category: ApiErrorCategory\n endpointId: string\n transport: EndpointSpec<any, any>['transport']\n service?: string\n functionName?: string\n code?: unknown\n status?: number\n message: string\n raw: unknown\n}\n\nexport type ApiErrorHandler = (error: ApiError) => void\n\nexport type GrpcAdapterMatch =\n | {\n endpointId?: string | RegExp\n serviceTypeName?: string | RegExp\n methodName?: string | RegExp\n }\n | ((ctx: { endpointId: string; serviceTypeName: string; methodName: string }) => boolean)\n\nexport type GrpcResponseAdapter<TRes = any, TData = any> = {\n match: GrpcAdapterMatch\n isSuccess?: (res: TRes) => boolean\n unwrap?: (res: TRes) => TData\n getBizCode?: (res: TRes) => number | undefined\n getCode?: (res: TRes) => number | undefined\n getStatus?: (res: TRes) => number | undefined\n getMessage?: (res: TRes) => string | undefined\n}\n\nexport class GrpcBizError extends Error {\n name = 'GrpcBizError'\n kind = 'biz'\n endpointId: string\n serviceTypeName: string\n methodName: string\n code?: number\n status?: number\n raw: unknown\n\n constructor(options: {\n endpointId: string\n serviceTypeName: string\n methodName: string\n code?: number\n status?: number\n message?: string\n raw: unknown\n }) {\n super(options.message ?? 'gRPC request failed')\n this.endpointId = options.endpointId\n this.serviceTypeName = options.serviceTypeName\n this.methodName = options.methodName\n this.code = options.code\n this.status = options.status\n this.raw = options.raw\n }\n}\n\nexport function normalizeApiError(\n err: unknown,\n source:\n | { endpoint: EndpointSpec<any, any> }\n | {\n transport: EndpointSpec<any, any>['transport']\n endpointId: string\n service?: string\n functionName?: string\n },\n): ApiError {\n let endpoint: EndpointSpec<any, any> | undefined\n let transport: EndpointSpec<any, any>['transport']\n let endpointId: string\n let sourceService: string | undefined\n let sourceFunctionName: string | undefined\n\n if ('endpoint' in source) {\n endpoint = source.endpoint\n transport = source.endpoint.transport\n endpointId = source.endpoint.id\n } else {\n endpoint = undefined\n transport = source.transport\n endpointId = source.endpointId\n sourceService = source.service\n sourceFunctionName = source.functionName\n }\n\n const category: ApiErrorCategory = isBizError(err)\n ? 'biz'\n : isTransportError(err)\n ? 'transport'\n : 'unknown'\n\n const fallbackServiceFunction = (): { service?: string; functionName?: string } => {\n if (endpoint) {\n if (endpoint.transport === 'ws') {\n return { service: endpoint.ws.service, functionName: endpoint.ws.functionName }\n }\n if (endpoint.transport === 'grpc') {\n return {\n service: (endpoint.grpc.service as any)?.typeName,\n functionName: endpoint.grpc.methodName,\n }\n }\n const [service, functionName] = endpoint.id.split('.', 2)\n return { service, functionName }\n }\n return { service: sourceService, functionName: sourceFunctionName }\n }\n\n const fallback = fallbackServiceFunction()\n\n if (err instanceof WsApiError) {\n return {\n category,\n endpointId,\n transport: 'ws',\n service: err.service ?? fallback.service,\n functionName: err.functionName ?? fallback.functionName,\n code: err.code,\n status: err.status,\n message: err.message ?? 'WS request failed',\n raw: err,\n }\n }\n\n if (err instanceof HttpApiError) {\n return {\n category,\n endpointId,\n transport: 'http',\n service: fallback.service,\n functionName: fallback.functionName,\n code: err.status,\n status: err.status,\n message: err.message ?? 'HTTP request failed',\n raw: err,\n }\n }\n\n if (err instanceof GrpcApiError) {\n return {\n category,\n endpointId,\n transport: 'grpc',\n service: fallback.service,\n functionName: fallback.functionName,\n code: err.code,\n message: err.message ?? 'gRPC request failed',\n raw: err,\n }\n }\n\n if (err instanceof GrpcBizError) {\n return {\n category,\n endpointId,\n transport: 'grpc',\n service: err.serviceTypeName ?? fallback.service,\n functionName: err.methodName ?? fallback.functionName,\n code: err.code,\n status: err.status,\n message: err.message ?? 'gRPC request failed',\n raw: err.raw,\n }\n }\n\n const anyErr = err as any\n return {\n category,\n endpointId,\n transport,\n service: fallback.service,\n functionName: fallback.functionName,\n code: anyErr?.code,\n status: typeof anyErr?.status === 'number' ? anyErr.status : undefined,\n message: anyErr?.message ?? (typeof err === 'string' ? err : 'Request failed'),\n raw: err,\n }\n}\n\nexport class UnifiedApiClient {\n /**\n * 统一调用入口:\n * - 输入:EndpointSpec(来自 spec 层)+ request + meta\n * - 输出:Promise<TRes>\n *\n * 业务意图是把“调用哪个服务/方法”从具体 transport 细节中剥离出来,\n * 调用侧只需要认 EndpointSpec,不需要知道走 HTTP/WS/gRPC。\n */\n readonly http: HttpClient\n readonly rpc: WsRpcClient\n readonly grpc: GrpcClient\n private callChain: (ctx: ApiCallContext<any, any>) => Promise<any>\n private onError?: ApiErrorHandler\n private grpcAdapters: GrpcResponseAdapter[] = []\n private grpcDefaultAdapter: GrpcResponseAdapter | undefined\n\n constructor(\n deps: { http: HttpClient; rpc: WsRpcClient; grpc: GrpcClient },\n options?: { interceptors?: ApiInterceptor[]; onError?: ApiErrorHandler },\n ) {\n this.http = deps.http\n this.rpc = deps.rpc\n this.grpc = deps.grpc\n /**\n * 业务意图:把横切能力(鉴权、日志、重试、灰度等)做成拦截器链,\n * 统一包裹 dispatch,避免每个 transport 重复实现。\n */\n this.callChain = composeInterceptors(options?.interceptors ?? [], (ctx) => this.dispatch(ctx))\n this.onError = options?.onError\n }\n\n addGrpcAdapter(adapter: GrpcResponseAdapter, options?: { prepend?: boolean }) {\n const prepend = options?.prepend ?? true\n if (prepend) {\n this.grpcAdapters.unshift(adapter)\n } else {\n this.grpcAdapters.push(adapter)\n }\n return () => {\n this.grpcAdapters = this.grpcAdapters.filter((a) => a !== adapter)\n }\n }\n\n clearGrpcAdapters() {\n this.grpcAdapters = []\n }\n\n setGrpcDefaultAdapter(adapter?: GrpcResponseAdapter) {\n this.grpcDefaultAdapter = adapter\n }\n\n setErrorHandler(handler?: ApiErrorHandler) {\n this.onError = handler\n }\n\n async call<TReq = any, TRes = any>(\n endpoint: EndpointSpec<TReq, TRes>,\n request?: TReq,\n meta?: ApiCallContext<TReq, TRes>['meta'],\n ): Promise<TRes> {\n /**\n * ctx.headers 初始为空,由拦截器注入;dispatch 会把 headers 合并进具体请求实现。\n * meta 用于承载 callOptions/wsOptions 等 transport 级选项,以及业务侧的扩展字段。\n */\n const ctx: ApiCallContext<TReq, TRes> = { endpoint, request, headers: {}, meta }\n try {\n return await this.callChain(ctx)\n } catch (err) {\n const apiError = normalizeApiError(err, { endpoint: endpoint as any })\n if (this.onError) {\n try {\n this.onError(apiError)\n } catch {\n // ignore\n }\n }\n if (err instanceof Error) {\n ;(err as any).apiError = apiError\n throw err\n }\n\n const wrapped = new Error(apiError.message, { cause: err as any })\n ;(wrapped as any).apiError = apiError\n throw wrapped\n }\n }\n\n private async dispatch(ctx: ApiCallContext<any, any>): Promise<any> {\n const endpoint = ctx.endpoint as EndpointSpec<any, any>\n\n if (endpoint.transport === 'http') {\n /**\n * HTTP 分发策略:\n * - GET/DELETE:把 request 放到 query params\n * - 其他方法:把 request 放到 body\n */\n const method = endpoint.http.method\n const url = endpoint.http.url\n const config =\n method === 'GET' || method === 'DELETE'\n ? { method, url, params: ctx.request }\n : { method, url, data: ctx.request }\n return await this.http.request<any>({\n ...(config as any),\n headers: { ...(ctx.headers ?? {}) },\n })\n }\n\n if (endpoint.transport === 'ws') {\n /**\n * WS 分发策略:\n * - endpoint.ws 内含 service/functionName/默认 timeout 等信息\n * - meta.wsOptions 允许调用侧覆盖 timeout/responseFunctionName 等细节\n */\n const wsOptions = (ctx.meta as any)?.wsOptions as\n | {\n timeout?: number\n responseFunctionName?: string\n matchRequestId?: boolean\n filter?: (data: any) => boolean\n }\n | undefined\n return await this.rpc.request<any, any>(\n endpoint.ws.functionName,\n endpoint.ws.service,\n ctx.request,\n {\n timeout: wsOptions?.timeout ?? endpoint.ws.timeout,\n responseFunctionName: wsOptions?.responseFunctionName ?? endpoint.ws.responseFunctionName,\n matchRequestId: wsOptions?.matchRequestId,\n filter: wsOptions?.filter,\n },\n )\n }\n\n /**\n * gRPC 分发策略:\n * - service/methodName 来自 endpoint.grpc\n * - 若存在 requestSchema,则把 plain object 转成 protobuf message\n * - 合并 callOptions.headers 与 ctx.headers,确保拦截器注入的 header 生效\n */\n const service = endpoint.grpc.service as GenService<any>\n const methodName = endpoint.grpc.methodName\n const client = this.grpc.getService(service) as any\n const method = client[methodName]\n if (typeof method !== 'function') {\n throw new Error(`gRPC method not found: ${service.typeName}.${methodName}`)\n }\n const callOptions = (ctx.meta as any)?.callOptions\n const req = endpoint.grpc.requestSchema\n ? create(endpoint.grpc.requestSchema as any, ctx.request ?? {})\n : ctx.request\n const headers = { ...(callOptions?.headers ?? {}), ...(ctx.headers ?? {}) }\n const res = await method(req, { ...(callOptions ?? {}), headers } as any)\n\n const adapter = this.resolveGrpcAdapter({\n endpointId: endpoint.id,\n serviceTypeName: service.typeName,\n methodName,\n })\n\n if (!adapter) return res\n\n if (!this.isGrpcOkWithAdapter(res, adapter)) {\n throw new GrpcBizError({\n endpointId: endpoint.id,\n serviceTypeName: service.typeName,\n methodName,\n code: this.extractGrpcCodeWithAdapter(res, adapter),\n status: this.extractGrpcStatusWithAdapter(res, adapter),\n message: this.getGrpcErrorMessageWithAdapter(res, adapter) ?? 'Request failed',\n raw: res,\n })\n }\n\n if (adapter.unwrap) return adapter.unwrap(res)\n return res\n }\n\n private matchGrpcAdapter(\n match: GrpcAdapterMatch,\n ctx: { endpointId: string; serviceTypeName: string; methodName: string },\n ): boolean {\n if (typeof match === 'function') return match(ctx)\n\n if (match.endpointId !== undefined) {\n if (typeof match.endpointId === 'string') {\n if (match.endpointId !== ctx.endpointId) return false\n } else if (!match.endpointId.test(ctx.endpointId)) {\n return false\n }\n }\n\n if (match.serviceTypeName !== undefined) {\n if (typeof match.serviceTypeName === 'string') {\n if (match.serviceTypeName !== ctx.serviceTypeName) return false\n } else if (!match.serviceTypeName.test(ctx.serviceTypeName)) {\n return false\n }\n }\n\n if (match.methodName !== undefined) {\n if (typeof match.methodName === 'string') {\n if (match.methodName !== ctx.methodName) return false\n } else if (!match.methodName.test(ctx.methodName)) {\n return false\n }\n }\n\n return true\n }\n\n private resolveGrpcAdapter(ctx: {\n endpointId: string\n serviceTypeName: string\n methodName: string\n }): GrpcResponseAdapter | undefined {\n for (const adapter of this.grpcAdapters) {\n if (this.matchGrpcAdapter(adapter.match, ctx)) return adapter\n }\n if (this.grpcDefaultAdapter && this.matchGrpcAdapter(this.grpcDefaultAdapter.match, ctx)) {\n return this.grpcDefaultAdapter\n }\n return undefined\n }\n\n private normalizeNumber(value: unknown): number | undefined {\n if (typeof value === 'number' && Number.isFinite(value)) return value\n if (typeof value === 'string') {\n const trimmed = value.trim()\n if (!trimmed) return undefined\n const asNumber = Number(trimmed)\n return Number.isFinite(asNumber) ? asNumber : undefined\n }\n return undefined\n }\n\n private normalizeString(value: unknown): string | undefined {\n if (typeof value === 'string') {\n const trimmed = value.trim()\n return trimmed.length > 0 ? trimmed : undefined\n }\n if (typeof value === 'number' && Number.isFinite(value)) return String(value)\n return undefined\n }\n\n private pickField(value: unknown, keys: string[]): unknown {\n if (!value || typeof value !== 'object') return undefined\n const anyValue = value as any\n for (const key of keys) {\n if (anyValue[key] !== undefined) return anyValue[key]\n }\n return undefined\n }\n\n private isGrpcOk(value: any): boolean {\n if (!value || typeof value !== 'object') return true\n\n const rawSuccess = this.pickField(value, ['success', 'ok'])\n if (rawSuccess !== undefined) {\n if (typeof rawSuccess === 'boolean') return rawSuccess\n if (typeof rawSuccess === 'string') {\n const lowered = rawSuccess.trim().toLowerCase()\n if (lowered === 'true') return true\n if (lowered === 'false') return false\n }\n }\n\n const rawCode = this.pickField(value, ['code', 'errCode', 'errorCode', 'resultCode'])\n if (rawCode !== undefined) {\n const code = this.normalizeNumber(rawCode)\n return typeof code === 'number' ? code === 0 || code === 200 : false\n }\n\n const rawStatus = this.pickField(value, ['status', 'statusCode', 'httpStatus', 'http_code'])\n if (rawStatus !== undefined) {\n const status = this.normalizeNumber(rawStatus)\n return typeof status === 'number' ? status === 0 || status === 200 : false\n }\n\n return true\n }\n\n private isGrpcOkWithAdapter(value: any, adapter: GrpcResponseAdapter): boolean {\n if (adapter.isSuccess) return adapter.isSuccess(value)\n return this.isGrpcOk(value)\n }\n\n private extractGrpcCodeWithAdapter(value: any, adapter: GrpcResponseAdapter): number | undefined {\n const mapped = adapter.getBizCode?.(value) ?? adapter.getCode?.(value)\n const normalized = this.normalizeNumber(mapped)\n if (normalized !== undefined) return normalized\n return this.normalizeNumber(\n this.pickField(value, ['code', 'errCode', 'errorCode', 'resultCode']),\n )\n }\n\n private extractGrpcStatusWithAdapter(\n value: any,\n adapter: GrpcResponseAdapter,\n ): number | undefined {\n const mapped = adapter.getStatus?.(value)\n const normalized = this.normalizeNumber(mapped)\n if (normalized !== undefined) return normalized\n return this.normalizeNumber(\n this.pickField(value, ['status', 'statusCode', 'httpStatus', 'http_code']),\n )\n }\n\n private getGrpcErrorMessageWithAdapter(\n value: any,\n adapter: GrpcResponseAdapter,\n ): string | undefined {\n const mapped = adapter.getMessage?.(value)\n const normalized = this.normalizeString(mapped)\n if (normalized) return normalized\n return this.normalizeString(\n this.pickField(value, ['message', 'msg', 'error', 'errMsg', 'errmsg', 'errorMessage']),\n )\n }\n}\n","import type { EndpointSpec } from '../spec/endpoint'\n\nexport type ApiHeaders = Record<string, string>\n\nexport interface ApiCallContext<TReq = unknown, TRes = unknown> {\n /**\n * 当前要调用的接口描述(由 spec 层提供)。\n * 这里不关心业务 service 的实现细节,只根据 endpoint 进行路由/拦截。\n */\n endpoint: EndpointSpec<TReq, TRes>\n /**\n * 业务请求参数,透传给具体 transport。\n */\n request?: TReq\n /**\n * 拦截器阶段累积出来的请求头。\n * transport 层会将它合并到各自的请求实现中。\n */\n headers: ApiHeaders\n /**\n * 透传元信息:用于承载不同 transport 的调用选项(如 callOptions/wsOptions),\n * 以及业务侧希望传入的额外 meta(打点、灰度标记等)。\n */\n meta?: Record<string, any>\n}\n\nexport type ApiCallNext = (ctx: ApiCallContext<any, any>) => Promise<any>\nexport type ApiInterceptor = (next: ApiCallNext) => ApiCallNext\n\nexport interface ApiLogger {\n debug?: (message: string, meta?: any) => void\n info?: (message: string, meta?: any) => void\n warn?: (message: string, meta?: any) => void\n error?: (message: string, meta?: any) => void\n}\n\nexport function isBizError(err: unknown): boolean {\n /**\n * “业务错误”用于区分网络/协议错误,便于日志/监控分层:\n * - transport_error:HTTP/gRPC/WS 连接/超时/序列化等基础设施错误\n * - biz_error:请求成功到达服务端,但返回了业务层失败(code/status/success)\n */\n if (!err || typeof err !== 'object') return false\n\n const anyErr = err as any\n if (anyErr.kind === 'biz') return true\n if (anyErr.name === 'GrpcBizError') return true\n\n if (anyErr.name === 'WsApiError') {\n const hasCause = 'cause' in anyErr && anyErr.cause != null\n const hasCodeOrStatus = typeof anyErr.code === 'number' || typeof anyErr.status === 'number'\n return !hasCause && hasCodeOrStatus\n }\n\n return false\n}\n\nexport function isTransportError(err: unknown): boolean {\n /**\n * “传输错误”包括:\n * - 显式标记 kind=transport 的错误\n * - 或者来自三种 transport 的统一错误类型\n */\n if (!err || typeof err !== 'object') return false\n\n const anyErr = err as any\n if (anyErr.kind === 'transport') return true\n\n return (\n anyErr.name === 'HttpApiError' || anyErr.name === 'GrpcApiError' || anyErr.name === 'WsApiError'\n )\n}\n\nexport function composeInterceptors(\n interceptors: ApiInterceptor[],\n terminal: ApiCallNext,\n): ApiCallNext {\n /**\n * 以“洋葱模型”组合拦截器:越靠前的拦截器越外层。\n * 例如 Auth/Log 等能力不依赖具体 transport,可统一复用。\n */\n return interceptors.reduceRight((next, itc) => itc(next), terminal)\n}\n\nexport function createAuthInterceptor(options: {\n getToken?: () => string | null | Promise<string | null>\n headerName?: string\n format?: (token: string) => string\n}): ApiInterceptor {\n /**\n * 统一鉴权:把业务侧 token 转成 header 注入到调用上下文。\n * 最终由各 transport 在发送请求时把 ctx.headers 合并进去。\n */\n const headerName = options.headerName ?? 'Authorization'\n const format = options.format ?? ((token) => `Bearer ${token}`)\n\n return (next) => async (ctx) => {\n if (options.getToken) {\n const token = await options.getToken()\n if (token) {\n ctx.headers[headerName] = format(token)\n }\n }\n return await next(ctx)\n }\n}\n\nexport function createLogInterceptor(options: {\n logger?: ApiLogger\n level?: 'debug' | 'info'\n}): ApiInterceptor {\n /**\n * 统一日志:围绕“一个 endpoint 的一次调用”打点。\n * 通过 isBizError/isTransportError 决定使用 warn 还是 error 上报。\n */\n const level = options.level ?? 'debug'\n const logger = options.logger\n const log = level === 'info' ? logger?.info : logger?.debug\n\n return (next) => async (ctx) => {\n const startedAt = Date.now()\n log?.('api.request', {\n endpointId: ctx.endpoint.id,\n transport: ctx.endpoint.transport,\n meta: ctx.meta,\n })\n try {\n const res = await next(ctx)\n log?.('api.response', {\n endpointId: ctx.endpoint.id,\n transport: ctx.endpoint.transport,\n durationMs: Date.now() - startedAt,\n meta: ctx.meta,\n })\n return res\n } catch (err) {\n const event = isBizError(err) ? 'api.biz_error' : 'api.transport_error'\n const report = isBizError(err)\n ? (logger?.warn ?? logger?.error)\n : (logger?.error ?? logger?.warn ?? logger?.info)\n\n report?.(event, {\n endpointId: ctx.endpoint.id,\n transport: ctx.endpoint.transport,\n durationMs: Date.now() - startedAt,\n error: err,\n meta: ctx.meta,\n })\n throw err\n }\n }\n}\n","import type { KeyValueStorage } from '../storage'\n\nexport const webStorage: KeyValueStorage = {\n get(key) {\n if (typeof window === 'undefined') return null\n try {\n const storage = window.localStorage\n if (!storage) return null\n return storage.getItem(key)\n } catch {\n return null\n }\n },\n set(key, value) {\n if (typeof window === 'undefined') return\n try {\n const storage = window.localStorage\n if (!storage) return\n storage.setItem(key, value)\n } catch {\n return\n }\n },\n}\n","import type { KeyValueStorage } from './storage'\n\nexport type FetchGuidOptions = {\n key?: string\n format?: 'uuid' | 'hex' | 'base64'\n prefix?: string\n}\n\nconst defaultKey = 'uKey'\nconst guidPattern = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i\nconst hex32Pattern = /^[0-9a-f]{32}$/i\n\nexport function createFetchGuid(storage: KeyValueStorage, options?: FetchGuidOptions) {\n return () => fetchGuidWithStorage(storage, options)\n}\n\nexport function fetchGuidWithStorage(storage: KeyValueStorage, options?: FetchGuidOptions) {\n const key = options?.key ?? defaultKey\n const current = safeGet(storage, key)\n\n if (current) {\n const unmasked = unmaskGuid(current)\n if (unmasked) return formatGuid(unmasked, options)\n }\n\n const guid = generateGuid()\n safeSet(storage, key, maskGuid(guid))\n return formatGuid(guid, options)\n}\n\nfunction safeGet(storage: KeyValueStorage, key: string): string | null {\n try {\n return storage.get(key)\n } catch {\n return null\n }\n}\n\nfunction safeSet(storage: KeyValueStorage, key: string, value: string): void {\n try {\n storage.set(key, value)\n } catch {\n return\n }\n}\n\nfunction generateGuid() {\n const cryptoObj = typeof globalThis !== 'undefined' ? (globalThis as any).crypto : undefined\n if (cryptoObj && cryptoObj.getRandomValues) {\n return '10000000-1000-4000-8000-100000000000'.replace(/[018]/g, (c) =>\n (+c ^ (cryptoObj.getRandomValues(new Uint8Array(1))[0] & (15 >> (+c / 4)))).toString(16),\n )\n }\n return 'xxxxxxxx-xxxx-4xxx-8xxx-xxxxxxxxxxxx'.replace(/[xy]/g, (ch) => {\n const r = (Math.random() * 16) | 0\n const v = ch === 'x' ? r : (r & 0x3) | 0x8\n return v.toString(16)\n })\n}\n\nfunction maskGuid(guid: string) {\n const hex = guid.replace(/-/g, '')\n const buffer = new Uint8Array(hex.length / 2)\n for (let i = 0; i < hex.length; i += 2) {\n buffer[i / 2] = parseInt(hex.slice(i, i + 2), 16)\n }\n return base64Encode(buffer)\n}\n\nfunction unmaskGuid(value: string) {\n const clean = value.replace(/\"/g, '').trim()\n\n if (guidPattern.test(clean)) return clean\n if (hex32Pattern.test(clean)) {\n return clean.replace(/^(.{8})(.{4})(.{4})(.{4})(.{12})$/, '$1-$2-$3-$4-$5')\n }\n\n const bytes = base64Decode(clean)\n if (!bytes) return null\n\n const hex = Array.prototype.map\n .call(bytes, (byte: number) => ('0' + (byte & 0xff).toString(16)).slice(-2))\n .join('')\n\n if (hex.length !== 32) return null\n return hex.replace(/^(.{8})(.{4})(.{4})(.{4})(.{12})$/, '$1-$2-$3-$4-$5')\n}\n\nfunction formatGuid(guid: string, options?: FetchGuidOptions) {\n const format = options?.format ?? 'uuid'\n const prefix = options?.prefix ?? ''\n\n if (format === 'uuid') return prefix + guid\n\n const hex = guid.replace(/-/g, '')\n if (format === 'hex') return prefix + hex\n\n const buffer = new Uint8Array(hex.length / 2)\n for (let i = 0; i < hex.length; i += 2) {\n buffer[i / 2] = parseInt(hex.slice(i, i + 2), 16)\n }\n return prefix + base64Encode(buffer)\n}\n\nfunction base64Encode(bytes: Uint8Array): string {\n const btoaFn = typeof globalThis !== 'undefined' ? (globalThis as any).btoa : undefined\n if (btoaFn) {\n let binary = ''\n for (let i = 0; i < bytes.length; i++) binary += String.fromCharCode(bytes[i])\n return btoaFn(binary)\n }\n const BufferCtor = typeof globalThis !== 'undefined' ? (globalThis as any).Buffer : undefined\n if (BufferCtor) return BufferCtor.from(bytes).toString('base64')\n const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'\n let out = ''\n let i = 0\n while (i < bytes.length) {\n const rem = bytes.length - i\n const b1 = bytes[i++]\n const b2 = rem > 1 ? bytes[i++] : 0\n const b3 = rem > 2 ? bytes[i++] : 0\n const n = (b1 << 16) | (b2 << 8) | b3\n out +=\n chars[(n >> 18) & 63] +\n chars[(n >> 12) & 63] +\n (rem > 1 ? chars[(n >> 6) & 63] : '=') +\n (rem > 2 ? chars[n & 63] : '=')\n }\n return out\n}\n\nfunction base64Decode(b64: string): Uint8Array | null {\n const atobFn = typeof globalThis !== 'undefined' ? (globalThis as any).atob : undefined\n if (atobFn) {\n try {\n const bin = atobFn(b64)\n const out = new Uint8Array(bin.length)\n for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i)\n return out\n } catch {\n return null\n }\n }\n const BufferCtor = typeof globalThis !== 'undefined' ? (globalThis as any).Buffer : undefined\n if (BufferCtor) {\n try {\n const buf = BufferCtor.from(b64, 'base64')\n return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength)\n } catch {\n return null\n }\n }\n const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'\n const map: Record<string, number> = {}\n for (let i = 0; i < chars.length; i++) map[chars[i]] = i\n const clean = b64.replace(/[^A-Za-z0-9+/=]/g, '')\n if (!clean) return null\n const bytes: number[] = []\n let i = 0\n while (i < clean.length) {\n const c1 = clean[i++]\n const c2 = clean[i++]\n const c3 = clean[i++]\n const c4 = clean[i++]\n if (!c1 || !c2) break\n const e1 = map[c1]\n const e2 = map[c2]\n if (e1 === undefined || e2 === undefined) return null\n const e3 = c3 === '=' || !c3 ? 0 : map[c3]\n const e4 = c4 === '=' || !c4 ? 0 : map[c4]\n if (e3 === undefined || e4 === undefined) return null\n const n = (e1 << 18) | (e2 << 12) | (e3 << 6) | e4\n const b1 = (n >> 16) & 255\n const b2 = (n >> 8) & 255\n const b3 = n & 255\n bytes.push(b1)\n if (c3 !== '=') bytes.push(b2)\n if (c4 !== '=') bytes.push(b3)\n }\n return new Uint8Array(bytes)\n}\n","import type { KeyValueStorage } from './storage'\nimport { webStorage } from './adapters/web'\nimport { createFetchGuid } from './fetchGuid'\n\nexport type { KeyValueStorage } from './storage'\nexport { createFetchGuid } from './fetchGuid'\nexport { webStorage } from './adapters/web'\n\nconst memoryStore = new Map<string, string>()\n\nconst memoryStorage: KeyValueStorage = {\n get(key) {\n return memoryStore.get(key) ?? null\n },\n set(key, val) {\n memoryStore.set(key, val)\n },\n}\n\nconst defaultStorage: KeyValueStorage = {\n get(key) {\n return webStorage.get(key) ?? memoryStorage.get(key)\n },\n set(key, val) {\n webStorage.set(key, val)\n memoryStorage.set(key, val)\n },\n}\n\nlet storageAdapter: KeyValueStorage = defaultStorage\nlet fetchGuidImpl = createFetchGuid(storageAdapter)\n\nexport const setUniqueKeyStorage = (adapter?: KeyValueStorage | null) => {\n storageAdapter = adapter ?? defaultStorage\n fetchGuidImpl = createFetchGuid(storageAdapter)\n}\n\nexport const fetchGuid = () => fetchGuidImpl()\n","import type { CallOptions } from '@connectrpc/connect'\nimport type { WsRequestOptions } from '../client/wsClient'\nimport type { WsRpcClient } from '../client/wsRpcClient'\nimport type { UnifiedApiClient } from '../client/unifiedApiClient'\nimport type { ApiMap, EndpointGroup, EndpointSpec, TransportKind } from '../spec'\nimport type { authService } from '../modules/auth'\nimport type { packetService } from '../modules/packet'\nimport type { paymentService } from '../modules/payment'\nimport type { playerService } from '../modules/player'\nimport type { promotionService } from '../modules/promotion'\nimport type { recommendService } from '../modules/recommend'\nimport type { riskcontrolService } from '../modules/riskcontrol'\nimport type { userEngagementService } from '../modules/userEngagement'\n\ntype Deferred<T> = {\n promise: Promise<T>\n resolve: (value: T) => void\n reject: (reason?: any) => void\n}\n\nfunction createDeferred<T>(): Deferred<T> {\n let resolve!: (value: T) => void\n let reject!: (reason?: any) => void\n const promise = new Promise<T>((res, rej) => {\n resolve = res\n reject = rej\n })\n return { promise, resolve, reject }\n}\n\nfunction waitMs(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\nlet serviceInstances: Record<string, any> = {}\nlet rpcClient: WsRpcClient | undefined\nlet unifiedClient: UnifiedApiClient | undefined\nlet endpointRegistry: Map<string, Map<TransportKind, EndpointSpec<any, any>>> = new Map()\nlet endpointDefaultTransports: Map<string, TransportKind | 'auto'> = new Map()\nlet endpointRegistryBuildPromise: Promise<void> | undefined\nlet endpointRegistryReady = false\nlet defaultTransport: TransportKind | 'auto' = 'auto'\nlet transportState: { hasHttp: boolean; hasWs: boolean; hasGrpc: boolean } = {\n hasHttp: false,\n hasWs: false,\n hasGrpc: false,\n}\n\nlet sdkInitDeferred: Deferred<void> = createDeferred<void>()\nlet requestApiInitWaitMs = 10_000\n\nexport function setRequestApiInitWaitMs(ms: number | undefined) {\n if (typeof ms !== 'number' || !Number.isFinite(ms)) return\n requestApiInitWaitMs = Math.max(0, Math.floor(ms))\n}\n\nfunction waitForSdkInit(): Promise<void> {\n if (unifiedClient) return Promise.resolve()\n if (requestApiInitWaitMs === 0) {\n return Promise.reject(new Error('SDK not initialized. Please call initSDK first.'))\n }\n return Promise.race([\n sdkInitDeferred.promise,\n waitMs(requestApiInitWaitMs).then(() => {\n throw new Error(\n `SDK not initialized. Please call initSDK first. (waited ${requestApiInitWaitMs}ms)`,\n )\n }),\n ])\n}\n\nexport function resetRoutingState() {\n const prevSdkInitDeferred = sdkInitDeferred\n serviceInstances = {}\n rpcClient = undefined\n unifiedClient = undefined\n endpointRegistry.clear()\n endpointDefaultTransports.clear()\n endpointRegistryReady = false\n endpointRegistryBuildPromise = undefined\n defaultTransport = 'auto'\n transportState = { hasHttp: false, hasWs: false, hasGrpc: false }\n sdkInitDeferred = createDeferred<void>()\n prevSdkInitDeferred.resolve()\n}\n\nexport function setServiceInstances(instances: Record<string, any>) {\n serviceInstances = instances\n}\n\nexport function setRpcClient(client: WsRpcClient | undefined) {\n rpcClient = client\n}\n\nexport function setUnifiedClient(client: UnifiedApiClient | undefined) {\n unifiedClient = client\n if (client) {\n sdkInitDeferred.resolve()\n }\n}\n\nexport function setTransportState(state: { hasHttp: boolean; hasWs: boolean; hasGrpc: boolean }) {\n transportState = state\n}\n\nexport function setDefaultTransport(transport: TransportKind | 'auto') {\n defaultTransport = transport\n}\n\nfunction makeEndpointKey(service: string, functionName: string): string {\n return `${service}:${functionName}`\n}\n\nfunction isEndpointSpec(value: unknown): value is EndpointSpec<any, any> {\n return !!value && typeof value === 'object' && 'transport' in (value as any)\n}\n\nfunction isEndpointGroup(value: unknown): value is EndpointGroup<any, any> {\n return !!value && typeof value === 'object' && 'transports' in (value as any)\n}\n\nfunction registerEndpointVariant(\n service: string,\n functionName: string,\n endpoint: EndpointSpec<any, any>,\n) {\n const key = makeEndpointKey(service, functionName)\n let byTransport = endpointRegistry.get(key)\n if (!byTransport) {\n byTransport = new Map()\n endpointRegistry.set(key, byTransport)\n }\n byTransport.set(endpoint.transport, endpoint)\n}\n\nfunction buildEndpointRegistry(apiMap: Record<string, any>) {\n endpointRegistry = new Map()\n endpointDefaultTransports = new Map()\n for (const [serviceName, service] of Object.entries(apiMap)) {\n for (const [functionName, endpoint] of Object.entries(service as Record<string, any>)) {\n if (isEndpointSpec(endpoint)) {\n registerEndpointVariant(serviceName, functionName, endpoint)\n continue\n }\n if (isEndpointGroup(endpoint)) {\n if (endpoint.defaultTransport) {\n endpointDefaultTransports.set(\n makeEndpointKey(serviceName, functionName),\n endpoint.defaultTransport,\n )\n }\n for (const [transport, config] of Object.entries(endpoint.transports ?? {})) {\n if (!config) continue\n if (transport === 'http') {\n registerEndpointVariant(serviceName, functionName, {\n id: endpoint.id,\n transport: 'http',\n http: config as any,\n request: (endpoint as any).request,\n response: (endpoint as any).response,\n })\n } else if (transport === 'ws') {\n registerEndpointVariant(serviceName, functionName, {\n id: endpoint.id,\n transport: 'ws',\n ws: config as any,\n request: (endpoint as any).request,\n response: (endpoint as any).response,\n })\n } else if (transport === 'grpc') {\n registerEndpointVariant(serviceName, functionName, {\n id: endpoint.id,\n transport: 'grpc',\n grpc: config as any,\n request: (endpoint as any).request,\n response: (endpoint as any).response,\n })\n }\n }\n continue\n }\n }\n }\n endpointRegistryReady = true\n}\n\nasync function ensureEndpointRegistry() {\n if (endpointRegistryReady) return\n if (endpointRegistryBuildPromise) return endpointRegistryBuildPromise\n endpointRegistryBuildPromise = import('../spec')\n .then((mod) => buildEndpointRegistry(mod.apiMap as any))\n .catch((err) => {\n endpointRegistryReady = false\n throw err\n })\n .finally(() => {\n endpointRegistryBuildPromise = undefined\n })\n return endpointRegistryBuildPromise\n}\n\nexport function rebuildEndpointRegistry() {\n endpointRegistryReady = false\n endpointRegistryBuildPromise = undefined\n void ensureEndpointRegistry()\n}\n\nexport async function getEndpointTransportHint(\n service: string,\n functionName: string,\n): Promise<TransportKind | 'multi' | undefined> {\n await ensureEndpointRegistry()\n const variants = endpointRegistry.get(makeEndpointKey(service, functionName))\n if (!variants) return undefined\n if (variants.size > 1) return 'multi'\n return variants.keys().next().value\n}\n\ntype EndpointRequest<TEndpoint> =\n TEndpoint extends EndpointSpec<infer TReq, any>\n ? TReq\n : TEndpoint extends EndpointGroup<infer TReq, any>\n ? TReq\n : never\ntype EndpointResponse<TEndpoint> =\n TEndpoint extends EndpointSpec<any, infer TRes>\n ? TRes\n : TEndpoint extends EndpointGroup<any, infer TRes>\n ? TRes\n : never\ntype ApiServiceName = Extract<keyof ApiMap, string>\ntype ApiFunctionName<TService extends ApiServiceName> = Extract<keyof ApiMap[TService], string>\n\ntype SdkServices = {\n auth: ReturnType<typeof authService>\n packet: ReturnType<typeof packetService>\n payment: ReturnType<typeof paymentService>\n player: ReturnType<typeof playerService>\n promotion: ReturnType<typeof promotionService>\n recommend: ReturnType<typeof recommendService>\n riskcontrol: ReturnType<typeof riskcontrolService>\n userEngagement: ReturnType<typeof userEngagementService>\n}\n\ntype SdkServiceName = keyof SdkServices\ntype AnyFn = (...args: any[]) => any\ntype FunctionKeys<T> = { [K in keyof T]-?: T[K] extends AnyFn ? K : never }[keyof T]\ntype SdkFunctionName<TService extends SdkServiceName> = FunctionKeys<SdkServices[TService]>\ntype ServiceFn<\n TService extends SdkServiceName,\n TFunctionName extends SdkFunctionName<TService>,\n> = Extract<SdkServices[TService][TFunctionName], AnyFn>\ntype SecondParam<TFn extends AnyFn> = Parameters<TFn> extends [any, infer B, ...any[]] ? B : never\n\nexport function requestApi<\n TService extends ApiServiceName,\n TFunctionName extends ApiFunctionName<TService>,\n>(args: {\n service: TService\n functionName: TFunctionName\n transport?: TransportKind | 'auto'\n requestParam?: EndpointRequest<ApiMap[TService][TFunctionName]>\n meta?: Record<string, any>\n wsOptions?: WsRequestOptions<EndpointResponse<ApiMap[TService][TFunctionName]>>\n callOptions?: CallOptions\n}): Promise<EndpointResponse<ApiMap[TService][TFunctionName]>>\nexport function requestApi<\n TService extends SdkServiceName,\n TFunctionName extends SdkFunctionName<TService>,\n>(args: {\n service: TService\n functionName: TFunctionName\n transport?: TransportKind | 'auto'\n requestParam: Parameters<ServiceFn<TService, TFunctionName>>[0]\n callOptions?: SecondParam<ServiceFn<TService, TFunctionName>> extends CallOptions\n ? CallOptions\n : never\n}): ReturnType<ServiceFn<TService, TFunctionName>>\nexport function requestApi<TReq = any, TRes = any>(args: {\n service: string\n functionName: string\n transport?: TransportKind | 'auto'\n requestParam?: TReq\n wsOptions?: WsRequestOptions<TRes>\n callOptions?: CallOptions\n meta?: Record<string, any>\n}): Promise<TRes>\nexport function requestApi(args: {\n service: string\n functionName: string\n transport?: TransportKind | 'auto'\n requestParam?: any\n wsOptions?: WsRequestOptions<any>\n callOptions?: CallOptions\n meta?: Record<string, any>\n}): any {\n if (!endpointRegistryReady) {\n return ensureEndpointRegistry().then(() => requestApi(args))\n }\n const key = makeEndpointKey(args.service, args.functionName)\n const endpointVariants = endpointRegistry.get(key)\n\n if (endpointVariants) {\n if (args.transport === 'ws' && !endpointVariants.has('ws')) {\n if (!rpcClient) {\n if (!unifiedClient) {\n return waitForSdkInit().then(() => requestApi(args))\n }\n throw new Error('SDK not initialized. Please call initSDK with ws config.')\n }\n return rpcClient.call(args.functionName, args.service, args.requestParam, args.wsOptions)\n }\n if (!unifiedClient) {\n return waitForSdkInit().then(() => requestApi(args))\n }\n const specDefaultTransport = endpointDefaultTransports.get(key)\n const endpoint = pickEndpoint(\n endpointVariants,\n args.transport,\n specDefaultTransport,\n args.service,\n args.functionName,\n )\n if (endpoint.transport === 'grpc' && !transportState.hasGrpc) {\n throw new Error('SDK not initialized. Please call initSDK with grpc config.')\n }\n if (endpoint.transport === 'ws' && !transportState.hasWs) {\n throw new Error('SDK not initialized. Please call initSDK with ws config.')\n }\n if (endpoint.transport === 'http' && !transportState.hasHttp) {\n throw new Error('SDK not initialized. Please call initSDK with http config.')\n }\n\n const meta =\n args.callOptions || args.wsOptions\n ? {\n ...(args.meta ?? {}),\n ...(args.callOptions ? { callOptions: args.callOptions } : {}),\n ...(args.wsOptions ? { wsOptions: args.wsOptions } : {}),\n }\n : args.meta\n\n return unifiedClient.call(endpoint, args.requestParam, meta)\n }\n\n if (args.transport === 'ws') {\n if (!rpcClient) {\n if (!unifiedClient) {\n return waitForSdkInit().then(() => requestApi(args))\n }\n throw new Error('SDK not initialized. Please call initSDK with ws config.')\n }\n return rpcClient.call(args.functionName, args.service, args.requestParam, args.wsOptions)\n }\n\n if (args.transport === 'grpc') {\n if (!unifiedClient) {\n return waitForSdkInit().then(() => requestApi(args))\n }\n const serviceInstance = (serviceInstances as any)[args.service]\n const method = serviceInstance?.[args.functionName]\n if (typeof method === 'function') {\n if (args.callOptions !== undefined) {\n return method(args.requestParam, args.callOptions)\n }\n return method(args.requestParam)\n }\n throw new Error(`Endpoint not found: ${args.service}.${args.functionName} (grpc)`)\n }\n\n if (args.transport === 'http') {\n throw new Error(`Endpoint not found: ${args.service}.${args.functionName} (http)`)\n }\n\n const serviceInstance = (serviceInstances as any)[args.service]\n const method = serviceInstance?.[args.functionName]\n if (typeof method === 'function') {\n if (args.callOptions !== undefined) {\n return method(args.requestParam, args.callOptions)\n }\n return method(args.requestParam)\n }\n\n if (!rpcClient) {\n return waitForSdkInit().then(() => requestApi(args))\n }\n\n return rpcClient.call(args.functionName, args.service, args.requestParam, args.wsOptions)\n}\n\nexport { requestApi as requestApiSpec, requestApi as callApi }\n\nfunction pickEndpoint(\n variants: Map<TransportKind, EndpointSpec<any, any>>,\n transport: TransportKind | 'auto' | undefined,\n specDefaultTransport: TransportKind | 'auto' | undefined,\n service: string,\n functionName: string,\n): EndpointSpec<any, any> {\n const resolvedTransport = transport ?? specDefaultTransport ?? defaultTransport\n\n if (resolvedTransport !== 'auto') {\n const found = variants.get(resolvedTransport)\n if (!found) {\n throw new Error(\n `Endpoint transport not found: ${service}.${functionName} (${resolvedTransport}). Available: ${Array.from(\n variants.keys(),\n ).join(', ')}`,\n )\n }\n return found\n }\n\n if (transportState.hasGrpc && variants.has('grpc')) return variants.get('grpc') as any\n if (transportState.hasWs && variants.has('ws')) return variants.get('ws') as any\n if (transportState.hasHttp && variants.has('http')) return variants.get('http') as any\n const fallback = variants.values().next().value\n if (!fallback) {\n throw new Error(`Endpoint not found: ${service}.${functionName}`)\n }\n return fallback\n}\n","import { RequestApi, RequestApiConfig } from './client/requestApi'\nimport { WsRpcClient, type WsResponseAdapter } from './client/wsRpcClient'\nimport {\n UnifiedApiClient,\n type GrpcResponseAdapter,\n normalizeApiError,\n} from './client/unifiedApiClient'\nimport { createAuthInterceptor, createLogInterceptor } from './client/interceptors'\nimport type { authService } from './modules/auth'\nimport type { packetService } from './modules/packet'\nimport type { paymentService } from './modules/payment'\nimport type { playerService } from './modules/player'\nimport type { promotionService } from './modules/promotion'\nimport type { recommendService } from './modules/recommend'\nimport type { riskcontrolService } from './modules/riskcontrol'\nimport type { userEngagementService } from './modules/userEngagement'\nimport type { CallOptions } from '@connectrpc/connect'\nimport { WsEvent, type WsNotifyCenter, type WsRequestOptions } from './client/wsClient'\nimport type { ApiMap, EndpointGroup, EndpointSpec, TransportKind } from './spec'\nimport type { ApiError } from './client/unifiedApiClient'\nimport { setUniqueKeyStorage as setUniqueKeyStorageImpl } from './utils/uniqueKey'\nimport {\n getEndpointTransportHint,\n rebuildEndpointRegistry,\n requestApi,\n resetRoutingState,\n setDefaultTransport,\n setRequestApiInitWaitMs,\n setRpcClient,\n setServiceInstances,\n setTransportState,\n setUnifiedClient,\n} from './routing/router'\nexport { callApi, requestApi, requestApiSpec } from './routing/router'\n\n// export * from './client/wsClient'\n// export * from './client/httpClient'\n// export * from './client/grpcClient'\n// export * from './client/requestApi'\n// export * from './client/wsRpcClient'\n// export * from './client/unifiedApiClient'\n// export * from './client/interceptors'\n// export * from './modules/admin'\n// export * from './modules/auth'\n// export * from './modules/cms'\n// export * from './modules/packet'\n// export * from './modules/payment'\n// export * from './modules/platform'\n// export * from './modules/player'\n// export * from './modules/promotion'\n// export * from './modules/recommend'\n// export * from './modules/riskcontrol'\n// export * from './modules/userEngagement'\n// export * from './spec'\n\nexport { fetchGuid, setUniqueKeyStorage, createFetchGuid, webStorage } from './utils/uniqueKey'\nexport type { KeyValueStorage } from './utils/uniqueKey'\n\nlet api: RequestApi | undefined\nlet apiErrorCenter: ApiErrorCenter | undefined\nlet notifyCenter: NotifyCenter | undefined\nconst wsStatusType = 'ws:status'\nlet wsStatusOffs: Array<() => void> = []\nlet wsStatusSnapshot: WsStatusPayload | undefined\n\nfunction createLazyObject<T extends Record<string, any>>(loader: () => Promise<T>): T {\n let loaded: T | undefined\n let loading: Promise<T> | undefined\n const load = () => {\n if (loaded) return Promise.resolve(loaded)\n if (loading) return loading\n loading = loader().then((value) => {\n loaded = value\n return value\n })\n return loading\n }\n if (typeof Proxy !== 'function') {\n throw new Error('Proxy is required for lazy-loading SDK modules.')\n }\n return new Proxy(\n {},\n {\n get(_target, prop) {\n if (prop === 'then') return undefined\n if (prop === '__load') return load\n return (...args: any[]) =>\n load().then((obj: any) => {\n const value = obj?.[prop as any]\n if (typeof value === 'function') return value.apply(obj, args)\n return value\n })\n },\n },\n ) as any\n}\n\nfunction schedulePreload(task: () => void) {\n const ric = (globalThis as any).requestIdleCallback as undefined | ((cb: () => void) => any)\n if (typeof ric === 'function') {\n ric(task)\n return\n }\n setTimeout(task, 0)\n}\n\ntype ApiErrorRegistration = { handler: ApiErrorMiddleware; off?: () => void }\nlet apiErrorRegistrationSeq = 0\nconst apiErrorRegistrations = new Map<number, ApiErrorRegistration>()\n\nfunction attachApiErrorRegistration(reg: ApiErrorRegistration) {\n if (!apiErrorCenter) return\n if (reg.off) reg.off()\n reg.off = apiErrorCenter.use(reg.handler)\n}\n\nfunction detachApiErrorRegistration(reg: ApiErrorRegistration) {\n if (reg.off) reg.off()\n reg.off = undefined\n}\n\ntype NotifyRegistration =\n | { kind: 'use'; handler: NotifyMiddleware<any>; off?: () => void }\n | { kind: 'subscribe'; listener: (payload: any) => void; off?: () => void }\n\nlet notifyRegistrationSeq = 0\nconst notifyRegistrationsByType = new Map<string, Map<number, NotifyRegistration>>()\n\nfunction ensureNotifyTypeRegistrations(type: string): Map<number, NotifyRegistration> {\n const existing = notifyRegistrationsByType.get(type)\n if (existing) return existing\n const created = new Map<number, NotifyRegistration>()\n notifyRegistrationsByType.set(type, created)\n return created\n}\n\nfunction attachNotifyRegistration(type: string, reg: NotifyRegistration) {\n if (!notifyCenter) return\n if (reg.off) reg.off()\n const channel = notifyCenter.channel<any>(type)\n reg.off = reg.kind === 'use' ? channel.use(reg.handler) : channel.subscribe(reg.listener)\n}\n\nfunction detachNotifyRegistration(reg: NotifyRegistration) {\n if (reg.off) reg.off()\n reg.off = undefined\n}\n\nexport type WsStatusState =\n | 'connected'\n | 'disconnected'\n | 'reconnecting'\n | 'reconnect_failed'\n | 'error'\n\nexport type WsStatusPayload =\n | { state: 'connected'; readyState?: number }\n | { state: 'disconnected'; code?: number; reason?: string; readyState?: number }\n | {\n state: 'reconnecting'\n attempt?: number\n maxRetries?: number\n interval?: number\n readyState?: number\n }\n | { state: 'reconnect_failed'; readyState?: number }\n | { state: 'error'; error?: unknown; readyState?: number }\n\nexport function getWsSnapshot(): {\n readyState?: number\n isConnected: boolean\n status?: WsStatusPayload\n} {\n return {\n readyState: api?.ws ? api.ws.state : undefined,\n isConnected: api?.ws ? api.ws.isConnected : false,\n status: wsStatusSnapshot,\n }\n}\n\nfunction clearWsStatusBridge() {\n for (const off of wsStatusOffs) {\n try {\n off()\n } catch {\n void 0\n }\n }\n wsStatusOffs = []\n}\n\ntype Next = () => void | Promise<void>\ntype Middleware<T, Ctx> = (value: T, ctx: Ctx, next: Next) => any\n\nclass Pipeline<T, Ctx> {\n private handlers: Middleware<T, Ctx>[] = []\n\n use(handler: Middleware<T, Ctx>) {\n this.handlers.push(handler)\n return () => {\n this.handlers = this.handlers.filter((h) => h !== handler)\n }\n }\n\n clear() {\n this.handlers = []\n }\n\n async run(value: T, ctx: Ctx) {\n let i = 0\n const next: Next = async () => {\n const handler = this.handlers[i++]\n if (!handler) return\n return await handler(value, ctx, next)\n }\n return await next()\n }\n}\n\nexport type ApiErrorMiddleware = Middleware<ApiError, { source?: string }>\n\nclass ApiErrorCenter {\n private pipeline = new Pipeline<ApiError, { source?: string }>()\n\n use(handler: ApiErrorMiddleware) {\n return this.pipeline.use(async (error, ctx, next) => {\n try {\n return await handler(error, ctx, next)\n } catch (e) {\n console.warn('ApiError middleware threw', e)\n return await next()\n }\n })\n }\n\n emit(error: ApiError, source?: string) {\n return this.pipeline.run(error, { source }).catch((e) => {\n console.warn('ApiError emit failed', e)\n })\n }\n\n clear() {\n this.pipeline.clear()\n }\n}\n\nexport const apiError = {\n use(handler: ApiErrorMiddleware) {\n const id = ++apiErrorRegistrationSeq\n const reg: ApiErrorRegistration = { handler }\n apiErrorRegistrations.set(id, reg)\n attachApiErrorRegistration(reg)\n return () => {\n const current = apiErrorRegistrations.get(id)\n if (!current) return\n detachApiErrorRegistration(current)\n apiErrorRegistrations.delete(id)\n }\n },\n emit(error: ApiError, source?: string) {\n if (!apiErrorCenter) {\n console.warn('SDK not initialized. apiError.emit is a no-op.')\n return\n }\n return apiErrorCenter.emit(error, source)\n },\n}\n\nexport type NotifyMiddleware<T = any> = Middleware<T, { type: string }>\n\nclass NotifyChannel<T = any> {\n private pipeline = new Pipeline<T, { type: string }>()\n private offWs?: () => void\n\n constructor(\n private type: string,\n private wsNotify?: WsNotifyCenter,\n ) {}\n\n private ensureAttached() {\n if (!this.wsNotify) return\n if (this.offWs) return\n this.offWs = this.wsNotify.on(this.type, (payload: any) => {\n void this.pipeline.run(payload as T, { type: this.type }).catch((e) => {\n console.warn(`Notify pipeline threw: ${this.type}`, e)\n })\n })\n }\n\n use(handler: NotifyMiddleware<T>) {\n this.ensureAttached()\n return this.pipeline.use(handler)\n }\n\n subscribe(listener: (payload: T) => void) {\n this.ensureAttached()\n return this.pipeline.use(async (value, _ctx, next) => {\n try {\n listener(value)\n } catch (e) {\n console.warn(`Notify subscriber threw: ${this.type}`, e)\n }\n return await next()\n })\n }\n\n emit(payload: T) {\n return this.pipeline.run(payload, { type: this.type }).catch((e) => {\n console.warn(`Notify emit failed: ${this.type}`, e)\n })\n }\n\n destroy() {\n if (this.offWs) {\n this.offWs()\n this.offWs = undefined\n }\n this.pipeline.clear()\n }\n}\n\nclass NotifyCenter {\n private channels = new Map<string, NotifyChannel<any>>()\n\n constructor(private wsNotify?: WsNotifyCenter) {}\n\n channel<T = any>(type: string): NotifyChannel<T> {\n const existing = this.channels.get(type)\n if (existing) return existing as NotifyChannel<T>\n const created = new NotifyChannel<T>(type, this.wsNotify)\n this.channels.set(type, created as NotifyChannel<any>)\n return created\n }\n\n destroy() {\n for (const channel of this.channels.values()) {\n channel.destroy()\n }\n this.channels.clear()\n }\n}\n\nexport function notify<T = any>(type: string): NotifyChannel<T> {\n const channel: NotifyChannel<T> = {\n use(handler: NotifyMiddleware<T>) {\n const id = ++notifyRegistrationSeq\n const reg: NotifyRegistration = { kind: 'use', handler }\n ensureNotifyTypeRegistrations(type).set(id, reg)\n attachNotifyRegistration(type, reg)\n return () => {\n const map = notifyRegistrationsByType.get(type)\n const current = map?.get(id)\n if (!map || !current) return\n detachNotifyRegistration(current)\n map.delete(id)\n if (map.size === 0) notifyRegistrationsByType.delete(type)\n }\n },\n subscribe(listener: (payload: T) => void) {\n const id = ++notifyRegistrationSeq\n const reg: NotifyRegistration = { kind: 'subscribe', listener }\n ensureNotifyTypeRegistrations(type).set(id, reg)\n attachNotifyRegistration(type, reg)\n return () => {\n const map = notifyRegistrationsByType.get(type)\n const current = map?.get(id)\n if (!map || !current) return\n detachNotifyRegistration(current)\n map.delete(id)\n if (map.size === 0) notifyRegistrationsByType.delete(type)\n }\n },\n emit(payload: T) {\n if (!notifyCenter) {\n console.warn(`SDK not initialized. notify('${type}').emit is a no-op.`)\n return\n }\n return notifyCenter.channel<T>(type).emit(payload)\n },\n destroy() {\n const map = notifyRegistrationsByType.get(type)\n if (map) {\n for (const reg of map.values()) {\n detachNotifyRegistration(reg)\n }\n notifyRegistrationsByType.delete(type)\n }\n notifyCenter?.channel(type).destroy()\n },\n } as unknown as NotifyChannel<T>\n return channel\n}\n\ntype WsAdapterRegistration = {\n adapter: WsResponseAdapter\n prepend: boolean\n off?: () => void\n}\n\nlet wsAdapterRegistrationSeq = 0\nconst wsAdapterRegistrations = new Map<number, WsAdapterRegistration>()\nlet wsDefaultAdapter: WsResponseAdapter | undefined\nlet wsAdapterRpc: WsRpcClient | undefined\n\nfunction attachWsAdapterRegistration(reg: WsAdapterRegistration) {\n if (!wsAdapterRpc) return\n if (reg.off) reg.off()\n reg.off = wsAdapterRpc.addAdapter(reg.adapter, { prepend: reg.prepend })\n}\n\nfunction detachWsAdapterRegistration(reg: WsAdapterRegistration) {\n if (reg.off) reg.off()\n reg.off = undefined\n}\n\nfunction setWsAdapterRpc(next: WsRpcClient | undefined) {\n if (wsAdapterRpc === next) return\n for (const reg of wsAdapterRegistrations.values()) {\n detachWsAdapterRegistration(reg)\n }\n wsAdapterRpc = next\n if (!wsAdapterRpc) return\n wsAdapterRpc.clearAdapters()\n wsAdapterRpc.setDefaultAdapter(wsDefaultAdapter)\n for (const reg of wsAdapterRegistrations.values()) {\n attachWsAdapterRegistration(reg)\n }\n}\n\nexport const adapters = {\n ws: {\n add(adapter: WsResponseAdapter, options?: { prepend?: boolean }) {\n const id = ++wsAdapterRegistrationSeq\n const reg: WsAdapterRegistration = { adapter, prepend: options?.prepend ?? true }\n wsAdapterRegistrations.set(id, reg)\n attachWsAdapterRegistration(reg)\n return () => {\n const current = wsAdapterRegistrations.get(id)\n if (!current) return\n detachWsAdapterRegistration(current)\n wsAdapterRegistrations.delete(id)\n }\n },\n setDefault(adapter?: WsResponseAdapter) {\n wsDefaultAdapter = adapter\n wsAdapterRpc?.setDefaultAdapter(adapter)\n },\n clear() {\n for (const reg of wsAdapterRegistrations.values()) {\n detachWsAdapterRegistration(reg)\n }\n wsAdapterRegistrations.clear()\n wsDefaultAdapter = undefined\n wsAdapterRpc?.clearAdapters()\n wsAdapterRpc?.setDefaultAdapter(undefined)\n },\n },\n grpc: {\n add(adapter: GrpcResponseAdapter, options?: { prepend?: boolean }) {\n const id = ++grpcAdapterRegistrationSeq\n const reg: GrpcAdapterRegistration = { adapter, prepend: options?.prepend ?? true }\n grpcAdapterRegistrations.set(id, reg)\n attachGrpcAdapterRegistration(reg)\n return () => {\n const current = grpcAdapterRegistrations.get(id)\n if (!current) return\n detachGrpcAdapterRegistration(current)\n grpcAdapterRegistrations.delete(id)\n }\n },\n setDefault(adapter?: GrpcResponseAdapter) {\n grpcDefaultAdapter = adapter\n grpcAdapterClient?.setGrpcDefaultAdapter(adapter)\n },\n clear() {\n for (const reg of grpcAdapterRegistrations.values()) {\n detachGrpcAdapterRegistration(reg)\n }\n grpcAdapterRegistrations.clear()\n grpcDefaultAdapter = undefined\n grpcAdapterClient?.clearGrpcAdapters()\n grpcAdapterClient?.setGrpcDefaultAdapter(undefined)\n },\n },\n}\n\ntype GrpcAdapterRegistration = {\n adapter: GrpcResponseAdapter\n prepend: boolean\n off?: () => void\n}\n\nlet grpcAdapterRegistrationSeq = 0\nconst grpcAdapterRegistrations = new Map<number, GrpcAdapterRegistration>()\nlet grpcDefaultAdapter: GrpcResponseAdapter | undefined\nlet grpcAdapterClient: UnifiedApiClient | undefined\n\nfunction attachGrpcAdapterRegistration(reg: GrpcAdapterRegistration) {\n if (!grpcAdapterClient) return\n if (reg.off) reg.off()\n reg.off = grpcAdapterClient.addGrpcAdapter(reg.adapter, { prepend: reg.prepend })\n}\n\nfunction detachGrpcAdapterRegistration(reg: GrpcAdapterRegistration) {\n if (reg.off) reg.off()\n reg.off = undefined\n}\n\nfunction setGrpcAdapterClient(next: UnifiedApiClient | undefined) {\n if (grpcAdapterClient === next) return\n for (const reg of grpcAdapterRegistrations.values()) {\n detachGrpcAdapterRegistration(reg)\n }\n grpcAdapterClient = next\n if (!grpcAdapterClient) return\n grpcAdapterClient.clearGrpcAdapters()\n grpcAdapterClient.setGrpcDefaultAdapter(grpcDefaultAdapter)\n for (const reg of grpcAdapterRegistrations.values()) {\n attachGrpcAdapterRegistration(reg)\n }\n}\n\n/**\n * 销毁 SDK 实例,释放资源\n * - 关闭 WS 连接\n * - 清空全局状态\n * - 重置 registry\n */\nexport function destroySDK() {\n if (api?.ws) {\n try {\n api.ws.disconnect()\n } catch (e) {\n console.warn('Failed to disconnect WS', e)\n }\n }\n\n for (const reg of apiErrorRegistrations.values()) {\n reg.off = undefined\n }\n for (const map of notifyRegistrationsByType.values()) {\n for (const reg of map.values()) {\n reg.off = undefined\n }\n }\n for (const reg of wsAdapterRegistrations.values()) {\n reg.off = undefined\n }\n\n api = undefined\n resetRoutingState()\n apiErrorCenter?.clear()\n apiErrorCenter = undefined\n notifyCenter?.destroy()\n notifyCenter = undefined\n setWsAdapterRpc(undefined)\n setGrpcAdapterClient(undefined)\n clearWsStatusBridge()\n wsStatusSnapshot = undefined\n}\n\ntype EndpointRequest<TEndpoint> =\n TEndpoint extends EndpointSpec<infer TReq, any>\n ? TReq\n : TEndpoint extends EndpointGroup<infer TReq, any>\n ? TReq\n : never\ntype EndpointResponse<TEndpoint> =\n TEndpoint extends EndpointSpec<any, infer TRes>\n ? TRes\n : TEndpoint extends EndpointGroup<any, infer TRes>\n ? TRes\n : never\ntype ApiServiceName = Extract<keyof ApiMap, string>\ntype ApiFunctionName<TService extends ApiServiceName> = Extract<keyof ApiMap[TService], string>\ntype ApiEndpoint<\n TService extends ApiServiceName,\n TFunctionName extends ApiFunctionName<TService>,\n> = ApiMap[TService][TFunctionName]\ntype ApiTransport<\n TService extends ApiServiceName,\n TFunctionName extends ApiFunctionName<TService>,\n> =\n ApiEndpoint<TService, TFunctionName> extends EndpointSpec<any, any>\n ? ApiEndpoint<TService, TFunctionName>['transport']\n : ApiEndpoint<TService, TFunctionName> extends EndpointGroup<any, any>\n ? 'multi'\n : never\ntype ApiWsOptions<\n TService extends ApiServiceName,\n TFunctionName extends ApiFunctionName<TService>,\n> = WsRequestOptions<EndpointResponse<ApiEndpoint<TService, TFunctionName>>>\ntype ApiMultiOptions<\n TService extends ApiServiceName,\n TFunctionName extends ApiFunctionName<TService>,\n> = {\n transport?: TransportKind | 'auto'\n wsOptions?: ApiWsOptions<TService, TFunctionName>\n callOptions?: CallOptions\n meta?: Record<string, any>\n}\ntype ApiMethod<TService extends ApiServiceName, TFunctionName extends ApiFunctionName<TService>> =\n ApiTransport<TService, TFunctionName> extends 'grpc'\n ? (\n payload?: EndpointRequest<ApiEndpoint<TService, TFunctionName>>,\n options?: CallOptions,\n ) => Promise<EndpointResponse<ApiEndpoint<TService, TFunctionName>>>\n : ApiTransport<TService, TFunctionName> extends 'ws'\n ? (\n payload?: EndpointRequest<ApiEndpoint<TService, TFunctionName>>,\n options?: ApiWsOptions<TService, TFunctionName>,\n ) => Promise<EndpointResponse<ApiEndpoint<TService, TFunctionName>>>\n : ApiTransport<TService, TFunctionName> extends 'multi'\n ? (\n payload?: EndpointRequest<ApiEndpoint<TService, TFunctionName>>,\n options?: ApiMultiOptions<TService, TFunctionName>,\n ) => Promise<EndpointResponse<ApiEndpoint<TService, TFunctionName>>>\n : (\n payload?: EndpointRequest<ApiEndpoint<TService, TFunctionName>>,\n ) => Promise<EndpointResponse<ApiEndpoint<TService, TFunctionName>>>\ntype ApiServiceClient<TService extends ApiServiceName> = {\n transport: ApiTransport<TService, ApiFunctionName<TService>>\n} & {\n [K in ApiFunctionName<TService>]: ApiMethod<TService, K>\n}\n\ntype SdkServices = {\n auth: ReturnType<typeof authService>\n packet: ReturnType<typeof packetService>\n payment: ReturnType<typeof paymentService>\n player: ReturnType<typeof playerService>\n promotion: ReturnType<typeof promotionService>\n recommend: ReturnType<typeof recommendService>\n riskcontrol: ReturnType<typeof riskcontrolService>\n userEngagement: ReturnType<typeof userEngagementService>\n}\n\n/**\n * 初始化 SDK\n *\n * ⚠️ SDK is a singleton.\n * Calling initSDK multiple times will override previous state.\n *\n * @param config SDK 配置\n * @returns RequestApi 实例\n */\nexport function initSDK(config: RequestApiConfig): {\n api: RequestApi\n rpc?: WsRpcClient\n client?: UnifiedApiClient\n wsNotify?: WsNotifyCenter\n apiError: typeof apiError\n notify: typeof notify\n adapters: typeof adapters\n auth?: ReturnType<typeof authService>\n admin?: ApiServiceClient<'admin'>\n cms?: ApiServiceClient<'cms'>\n packet?: ReturnType<typeof packetService>\n payment?: ReturnType<typeof paymentService>\n platform?: ApiServiceClient<'platform'>\n player?: ReturnType<typeof playerService>\n promotion?: ReturnType<typeof promotionService>\n recommend?: ReturnType<typeof recommendService>\n riskcontrol?: ReturnType<typeof riskcontrolService>\n userEngagement?: ReturnType<typeof userEngagementService>\n} {\n clearWsStatusBridge()\n wsStatusSnapshot = undefined\n if ('uniqueKeyStorage' in config) {\n setUniqueKeyStorageImpl(config.uniqueKeyStorage)\n }\n /**\n * 业务意图:initSDK 是唯一的“装配点”:\n * - 创建三种 transport(HTTP/WS/gRPC)并注入统一鉴权/日志\n * - 建立 WS 连接(只在这里 connect,避免重复建连)\n * - 建立统一调用入口 unifiedClient,用 EndpointSpec 做路由\n * - 对部分“老模块式”服务(auth/packet/...)保留实例,兼容历史调用方式\n */\n api = new RequestApi({\n ...config,\n })\n resetRoutingState()\n setRequestApiInitWaitMs(config.requestApiInitWaitMs ?? 10_000)\n setTransportState({ hasHttp: !!config.http, hasWs: !!config.ws, hasGrpc: !!config.grpc?.baseUrl })\n setDefaultTransport(config.defaultTransport ?? 'auto')\n schedulePreload(rebuildEndpointRegistry)\n\n config.logger?.info?.('sdk.initialized', {\n hasHttp: !!config.http,\n hasWs: !!config.ws,\n hasGrpc: !!config.grpc,\n })\n const sdk: {\n rpc?: WsRpcClient\n client?: UnifiedApiClient\n wsNotify?: WsNotifyCenter\n apiError: typeof apiError\n notify: typeof notify\n adapters: typeof adapters\n auth?: ReturnType<typeof authService>\n admin?: ApiServiceClient<'admin'>\n cms?: ApiServiceClient<'cms'>\n packet?: ReturnType<typeof packetService>\n payment?: ReturnType<typeof paymentService>\n platform?: ApiServiceClient<'platform'>\n player?: ReturnType<typeof playerService>\n promotion?: ReturnType<typeof promotionService>\n recommend?: ReturnType<typeof recommendService>\n riskcontrol?: ReturnType<typeof riskcontrolService>\n userEngagement?: ReturnType<typeof userEngagementService>\n } = { apiError, notify, adapters }\n\n apiErrorCenter = new ApiErrorCenter()\n if (config.onApiError) {\n apiErrorCenter.use((error, _ctx, next) => {\n config.onApiError?.(error)\n return next()\n })\n }\n for (const reg of apiErrorRegistrations.values()) {\n attachApiErrorRegistration(reg)\n }\n notifyCenter = new NotifyCenter(config.ws ? api.ws.notify : undefined)\n for (const [type, map] of notifyRegistrationsByType.entries()) {\n for (const reg of map.values()) {\n attachNotifyRegistration(type, reg)\n }\n }\n if (config.ws) {\n const channel = notifyCenter.channel<WsStatusPayload>(wsStatusType)\n const emitStatus = (payload: WsStatusPayload) => {\n wsStatusSnapshot = payload\n void channel.emit(payload)\n }\n\n wsStatusOffs.push(\n api.ws.on(WsEvent.OPEN, () => {\n emitStatus({ state: 'connected', readyState: api?.ws?.state })\n }),\n )\n wsStatusOffs.push(\n api.ws.on(WsEvent.CLOSE, (e: any) => {\n emitStatus({\n state: 'disconnected',\n code: e?.code,\n reason: e?.reason,\n readyState: api?.ws?.state,\n })\n }),\n )\n wsStatusOffs.push(\n api.ws.on(WsEvent.ERROR, (e: any) => {\n emitStatus({ state: 'error', error: e, readyState: api?.ws?.state })\n }),\n )\n wsStatusOffs.push(\n api.ws.on(WsEvent.RECONNECTING, (e: any) => {\n emitStatus({\n state: 'reconnecting',\n attempt: e?.attempt,\n maxRetries: e?.maxRetries,\n interval: e?.interval,\n readyState: api?.ws?.state,\n })\n }),\n )\n wsStatusOffs.push(\n api.ws.on(WsEvent.RECONNECT_FAILED, () => {\n emitStatus({ state: 'reconnect_failed', readyState: api?.ws?.state })\n }),\n )\n\n emitStatus({\n state: api.ws.isConnected ? 'connected' : 'disconnected',\n readyState: api.ws.state,\n })\n }\n\n const rpc = new WsRpcClient(api.ws, {\n onError: (err, source) => {\n if (!apiErrorCenter) return\n const apiErr = normalizeApiError(err, {\n transport: 'ws',\n endpointId: `${source.service}.${source.functionName}`,\n service: source.service,\n functionName: source.functionName,\n })\n void apiErrorCenter.emit(apiErr, 'ws')\n },\n })\n setWsAdapterRpc(rpc)\n if (config.ws) {\n /**\n * WS 只在 initSDK 时触发 connect:\n * - sdk.rpc 暴露给外部用于订阅/调试等\n * - rpcClient 用于 requestApi 的兜底调用(仅在 endpointRegistry 未命中时使用)\n */\n sdk.rpc = rpc\n setRpcClient(rpc)\n api.ws.connect()\n } else {\n setRpcClient(undefined)\n }\n sdk.wsNotify = config.ws ? api.ws.notify : undefined\n sdk.client = new UnifiedApiClient(\n { http: api.http, rpc, grpc: api.grpc },\n {\n onError: (error) => {\n if (!apiErrorCenter) return\n void apiErrorCenter.emit(error, 'unified')\n },\n interceptors: [\n ...(config.auth?.getToken\n ? [createAuthInterceptor({ getToken: config.auth.getToken })]\n : []),\n ...(config.logger ? [createLogInterceptor({ logger: config.logger, level: 'debug' })] : []),\n ],\n },\n )\n setGrpcAdapterClient(sdk.client)\n setUnifiedClient(sdk.client)\n\n if (config.grpc?.baseUrl) {\n /**\n * 这些服务来自历史 modules/*:通常是“grpc-web 生成代码 + 少量封装”。\n * 它们不走 endpointRegistry(不是 spec 驱动),这里保留实例用于兼容旧调用。\n */\n const legacyPromise = import('./modules/legacy').then((m) => m.createLegacyServices(api!.grpc))\n const loadLegacy = () => legacyPromise\n sdk.auth = createLazyObject<ReturnType<typeof authService>>(() =>\n loadLegacy().then((m) => m.auth),\n )\n sdk.packet = createLazyObject<ReturnType<typeof packetService>>(() =>\n loadLegacy().then((m) => m.packet),\n )\n sdk.payment = createLazyObject<ReturnType<typeof paymentService>>(() =>\n loadLegacy().then((m) => m.payment),\n )\n sdk.player = createLazyObject<ReturnType<typeof playerService>>(() =>\n loadLegacy().then((m) => m.player),\n )\n sdk.promotion = createLazyObject<ReturnType<typeof promotionService>>(() =>\n loadLegacy().then((m) => m.promotion),\n )\n sdk.recommend = createLazyObject<ReturnType<typeof recommendService>>(() =>\n loadLegacy().then((m) => m.recommend),\n )\n sdk.riskcontrol = createLazyObject<ReturnType<typeof riskcontrolService>>(() =>\n loadLegacy().then((m) => m.riskcontrol),\n )\n sdk.userEngagement = createLazyObject<ReturnType<typeof userEngagementService>>(() =>\n loadLegacy().then((m) => m.userEngagement),\n )\n const serviceInstances: Partial<SdkServices> = {}\n serviceInstances.auth = sdk.auth\n serviceInstances.packet = sdk.packet\n serviceInstances.payment = sdk.payment\n serviceInstances.player = sdk.player\n serviceInstances.promotion = sdk.promotion\n serviceInstances.recommend = sdk.recommend\n serviceInstances.riskcontrol = sdk.riskcontrol\n serviceInstances.userEngagement = sdk.userEngagement\n setServiceInstances(serviceInstances as any)\n\n sdk.admin = createApiServiceClient('admin')\n sdk.cms = createApiServiceClient('cms')\n } else {\n setServiceInstances({})\n }\n\n if (config.ws) {\n /**\n * platform 目前是 WS spec 驱动的服务:\n * - createApiServiceClient 会生成“类型安全的 service client”\n * - 其内部统一走 requestApi,从而复用 unifiedClient 的拦截器/路由\n */\n sdk.platform = createApiServiceClient('platform')\n }\n\n // gRPC 客户端通常不需要显式连接,它会在第一次请求时自动处理\n // 但如果需要预热或其他初始化逻辑,可以在这里添加\n\n return {\n api: api,\n ...sdk,\n }\n}\n\n/**\n * 获取 SDK 实例\n * @returns RequestApi 实例\n * @throws Error 如果 SDK 未初始化\n */\nexport function getSDK(): RequestApi {\n if (!api) {\n throw new Error('SDK not initialized. Please call initSDK first.')\n }\n return api\n}\n\nfunction createApiServiceClient<TService extends ApiServiceName>(\n service: TService,\n): ApiServiceClient<TService> {\n const base: Record<string, any> = { transport: undefined }\n if (typeof Proxy !== 'function') {\n throw new Error('Proxy is required for creating API service clients.')\n }\n\n const isNormalizedOptions = (\n value: any,\n ): value is {\n transport?: TransportKind | 'auto'\n wsOptions?: WsRequestOptions<any>\n callOptions?: CallOptions\n meta?: Record<string, any>\n } => {\n if (!value || typeof value !== 'object') return false\n return 'transport' in value || 'wsOptions' in value || 'callOptions' in value || 'meta' in value\n }\n\n const looksLikeWsOptions = (value: any): value is WsRequestOptions<any> => {\n if (!value || typeof value !== 'object') return false\n return (\n 'timeout' in value ||\n 'responseFunctionName' in value ||\n 'matchRequestId' in value ||\n 'filter' in value\n )\n }\n\n const looksLikeCallOptions = (value: any): value is CallOptions => {\n if (!value || typeof value !== 'object') return false\n return 'timeoutMs' in value || 'headers' in value || 'signal' in value\n }\n\n const client = new Proxy(base, {\n get(target, prop) {\n if (prop in target) return (target as any)[prop]\n if (prop === 'then') return undefined\n if (typeof prop !== 'string') return undefined\n\n return (payload?: any, options?: any) => {\n return getEndpointTransportHint(service, prop).then((hint) => {\n if (hint === 'grpc') {\n return requestApi({\n service,\n functionName: prop,\n requestParam: payload,\n callOptions: options,\n } as any)\n }\n if (hint === 'ws') {\n return requestApi({\n service,\n functionName: prop,\n requestParam: payload ?? {},\n wsOptions: options,\n } as any)\n }\n if (hint === 'http') {\n return requestApi({\n service,\n functionName: prop,\n requestParam: payload,\n } as any)\n }\n\n if (\n !isNormalizedOptions(options) &&\n looksLikeWsOptions(options) &&\n !looksLikeCallOptions(options)\n ) {\n return requestApi({\n service,\n functionName: prop,\n transport: 'ws',\n requestParam: payload ?? {},\n wsOptions: options,\n } as any)\n }\n\n if (\n !isNormalizedOptions(options) &&\n looksLikeCallOptions(options) &&\n !looksLikeWsOptions(options)\n ) {\n return requestApi({\n service,\n functionName: prop,\n transport: 'grpc',\n requestParam: payload,\n callOptions: options,\n } as any)\n }\n\n const normalized = isNormalizedOptions(options) ? options : undefined\n\n return requestApi({\n service,\n functionName: prop,\n transport: normalized?.transport,\n requestParam: payload,\n wsOptions: normalized?.wsOptions,\n callOptions: normalized?.callOptions,\n meta: normalized?.meta,\n } as any)\n })\n }\n },\n })\n\n return client as ApiServiceClient<TService>\n}\n// export { fetchGuid }\n"]}
|
|
1
|
+
{"version":3,"sources":["d:\\working\\GX\\tsup\\packages\\api\\dist\\index.cjs"],"names":[],"mappings":"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CA,YAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,wBAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,2BAAA;AACA,QAAA;AACA,wBAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,wBAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA,iBAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,YAAA;AACA,cAAA;AACA,YAAA;AACA,UAAA;AACA,UAAA;AACA,YAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,wBAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,wBAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,wBAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,sBAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,YAAA;AACA,YAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,sBAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,wBAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,wBAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,YAAA;AACA,cAAA;AACA,YAAA;AACA,cAAA;AACA,YAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA,kBAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,sBAAA;AACA,MAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,oBAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA,kBAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA,kBAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,oBAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,oBAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,kBAAA;AACA,kBAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA;AACA,kBAAA;AACA;AACA,kBAAA;AACA;AACA,kBAAA;AACA;AACA,mBAAA;AACA;AACA,mBAAA;AACA;AACA,mBAAA;AACA,mBAAA;AACA;AACA,mBAAA;AACA,mBAAA;AACA,mBAAA;AACA;AACA,mBAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,YAAA;AACA,YAAA;AACA,cAAA;AACA,cAAA;AACA,cAAA;AACA,cAAA;AACA,cAAA;AACA,YAAA;AACA,YAAA;AACA,cAAA;AACA,gBAAA;AACA,gBAAA;AACA,gBAAA;AACA,cAAA;AACA,YAAA;AACA,UAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,YAAA;AACA,UAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,YAAA;AACA,YAAA;AACA,YAAA;AACA,YAAA;AACA,YAAA;AACA,UAAA;AACA,UAAA;AACA,YAAA;AACA,cAAA;AACA,cAAA;AACA,cAAA;AACA,YAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,YAAA;AACA,UAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,YAAA;AACA,UAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA,oBAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,oBAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA,mBAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,mBAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,wBAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,wBAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,wBAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,wBAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,oBAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,sBAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,sBAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA,mBAAA;AACA,mBAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,mBAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,UAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,YAAA;AACA,UAAA;AACA,UAAA;AACA,YAAA;AACA,UAAA;AACA,UAAA;AACA,YAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,UAAA;AACA,YAAA;AACA,YAAA;AACA,UAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,YAAA;AACA,cAAA;AACA,cAAA;AACA,cAAA;AACA,cAAA;AACA,cAAA;AACA,YAAA;AACA,UAAA;AACA,YAAA;AACA,cAAA;AACA,cAAA;AACA,cAAA;AACA,cAAA;AACA,cAAA;AACA,YAAA;AACA,UAAA;AACA,YAAA;AACA,cAAA;AACA,cAAA;AACA,cAAA;AACA,cAAA;AACA,cAAA;AACA,YAAA;AACA,UAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,UAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA,mBAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA,mBAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,mBAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,mBAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,UAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,sBAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,sBAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,sBAAA;AACA,sBAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,sBAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,sBAAA;AACA,sBAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,kBAAA;AACA,EAAA;AACA,kBAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,kBAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,sBAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,MAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA,IAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACA,QAAA;AACA,UAAA;AACA,YAAA;AACA,cAAA;AACA,cAAA;AACA,cAAA;AACA,cAAA;AACA,YAAA;AACA,UAAA;AACA,UAAA;AACA,YAAA;AACA,cAAA;AACA,cAAA;AACA,cAAA;AACA,cAAA;AACA,YAAA;AACA,UAAA;AACA,UAAA;AACA,YAAA;AACA,cAAA;AACA,cAAA;AACA,cAAA;AACA,YAAA;AACA,UAAA;AACA,UAAA;AACA,YAAA;AACA,cAAA;AACA,cAAA;AACA,cAAA;AACA,cAAA;AACA,cAAA;AACA,YAAA;AACA,UAAA;AACA,UAAA;AACA,YAAA;AACA,cAAA;AACA,cAAA;AACA,cAAA;AACA,cAAA;AACA,cAAA;AACA,YAAA;AACA,UAAA;AACA,UAAA;AACA,UAAA;AACA,YAAA;AACA,YAAA;AACA,YAAA;AACA,YAAA;AACA,YAAA;AACA,YAAA;AACA,YAAA;AACA,UAAA;AACA,QAAA;AACA,MAAA;AACA,IAAA;AACA,EAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"D:\\working\\GX\\tsup\\packages\\api\\dist\\index.cjs","sourcesContent":[null]}
|
package/dist/index.d.cts
CHANGED
package/dist/index.d.ts
CHANGED