@ctil/gql 1.0.0

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.
@@ -0,0 +1,180 @@
1
+ import { buildWhere, buildFields,toPascalCase } from './baseType.ts';
2
+ import type { WhereInput, FieldInput } from './baseType.ts';
3
+ // 列表查询入参
4
+ export interface QueryInput {
5
+ operationName: string;
6
+ fields?: FieldInput[];
7
+ variables?: Record<string, any>; // 传入的变量名和初始值
8
+ where?: WhereInput;
9
+ orderBy?: Record<string, any>;
10
+ distinctOn?: string[];
11
+ limit?: number;
12
+ offset?: number;
13
+ }
14
+
15
+ // 分页查询入参
16
+ export interface QueryPageListInput {
17
+ operationName: string;
18
+ fields: FieldInput[];
19
+ variables?: Record<string, any>; // 传入的变量名和初始值
20
+ where?: WhereInput;
21
+ orderBy?: Record<string, any>;
22
+ distinctOn?: string[];
23
+ size?: number;
24
+ page?: number;
25
+ }
26
+
27
+ // 根据ID查询入参
28
+ export interface QueryByIdInput {
29
+ operationName: string;
30
+ fields: FieldInput[];
31
+ pk: string | number
32
+ }
33
+
34
+ // =================== 聚合查询 InputType ===================
35
+ export interface QueryAggregateInput {
36
+ operationName: string; // 操作名称,例如 user
37
+ fields: FieldInput[]; // 节点数据的字段
38
+ aggregateFields?: AggregateFieldInput; // 聚合字段配置
39
+ variables?: Record<string, any>;
40
+ where?: WhereInput;
41
+ distinctOn?: string[];
42
+ }
43
+
44
+ export interface AggregateFieldInput {
45
+ count?: boolean; // count 不带子字段
46
+ sum?: string[]; // sum { age salary }
47
+ avg?: string[];
48
+ max?: string[];
49
+ min?: string[];
50
+ }
51
+
52
+
53
+ /** 生成完整 query,包括变量定义 */
54
+ export function buildGraphQLQueryList(input: QueryInput) {
55
+ const { operationName, fields, variables, where, orderBy, distinctOn, limit, offset } = input;
56
+
57
+ // 生成顶层变量定义
58
+ const varDefs = variables
59
+ ? Object.keys(variables)
60
+ .map(k => `$${k}: String!`) // 暂时默认全部 String!
61
+ .join(", ")
62
+ : "";
63
+
64
+ const topArgs: string[] = [];
65
+ if (where) topArgs.push(`where: { ${buildWhere(where)} }`);
66
+ if (distinctOn) topArgs.push(`distinct_on: [${distinctOn.map(s => `${s}`).join(" ")}]`);
67
+ if (orderBy)
68
+ topArgs.push(
69
+ `order_by: {${Object.entries(orderBy)
70
+ .map(([k, v]) => `${k}: ${v}`) // 顶层 order_by 值不加引号
71
+ .join(" ")}}`
72
+ );
73
+ if (limit !== undefined) topArgs.push(`limit: ${limit}`);
74
+ if (offset !== undefined) topArgs.push(`offset: ${offset}`);
75
+ const topArgsStr = topArgs.length ? `(${topArgs.join(" ")})` : "";
76
+ const query = `query ${operationName}${varDefs ? `(${varDefs})` : ""} { ${operationName}${topArgsStr} ${fields? '{'+buildFields(fields)+'}':''} }`;
77
+ return { query, variables };
78
+ }
79
+
80
+ /** 生成按 ID 查询的 GraphQL query(固定主键参数名为 id) */
81
+ export function buildGraphQLQueryByIdFixed(queryByIdInput: QueryByIdInput) {
82
+ const { pk, fields, operationName } = queryByIdInput
83
+ const variables: Record<string, any> = { id: pk };
84
+
85
+ const query = `query ${operationName + '_by_pk'}($id: Long!) {
86
+ ${operationName + '_by_pk'}(id: $id) {
87
+ ${buildFields(fields)}
88
+ }
89
+ }`;
90
+
91
+ return { query, variables };
92
+ }
93
+
94
+ /** 生成分页查询的输入 */
95
+ export function buildGraphQLQueryPageList(input: QueryPageListInput) {
96
+ const { operationName, fields, variables, where, orderBy, distinctOn, page, size } = input;
97
+
98
+ // 生成顶层变量定义
99
+ const varDefs = variables
100
+ ? Object.keys(variables)
101
+ .map(k => `$${k}: String!`) // 暂时默认全部 String!
102
+ .join(", ")
103
+ : "";
104
+
105
+ const topArgs: string[] = [];
106
+ if (where) topArgs.push(`where: { ${buildWhere(where)} }`);
107
+ if (distinctOn) topArgs.push(`distinct_on: [${distinctOn.map(s => `${s}`).join(" ")}]`);
108
+ if (orderBy)
109
+ topArgs.push(
110
+ `order_by: {${Object.entries(orderBy)
111
+ .map(([k, v]) => `${k}: ${v}`) // 顶层 order_by 值不加引号
112
+ .join(" ")}}`
113
+ );
114
+ if (size !== undefined) topArgs.push(`size: ${size}`);
115
+ if (page !== undefined) topArgs.push(`page: ${page}`);
116
+ const topArgsStr = topArgs.length ? `(${topArgs.join(" ")})` : "";
117
+
118
+
119
+ const query = `query ${'get' + toPascalCase(operationName) + 'PageList'}${varDefs ? `(${varDefs})` : ""} { ${'get' + toPascalCase(operationName) + 'PageList'}${topArgsStr} { hasMore list{${buildFields(fields)}} page size total } }`;
120
+
121
+ return { query, variables };
122
+ }
123
+
124
+
125
+ // =================== 构造聚合查询函数 ===================
126
+ export function buildGraphQLQueryAggregate(input: QueryAggregateInput) {
127
+ const { operationName, fields, aggregateFields, variables, where, distinctOn } = input;
128
+
129
+ // 变量定义
130
+ const varDefs = variables
131
+ ? Object.keys(variables)
132
+ .map(k => `$${k}: String!`)
133
+ .join(", ")
134
+ : "";
135
+
136
+ // 顶层参数
137
+ const topArgs: string[] = [];
138
+ if (where) topArgs.push(`where: { ${buildWhere(where)} }`);
139
+ if (distinctOn) topArgs.push(`distinct_on: [${distinctOn.map(s => `${s}`).join(" ")}]`);
140
+
141
+ const topArgsStr = topArgs.length ? `(${topArgs.join(" ")})` : "";
142
+
143
+ // ✅ 构建 aggregate 字段
144
+ const aggregateParts: string[] = [];
145
+
146
+ if (aggregateFields) {
147
+ if (aggregateFields.count) aggregateParts.push("count");
148
+
149
+ (["sum", "avg", "max", "min"] as const).forEach(key => {
150
+ const fields = aggregateFields[key];
151
+ if (fields && fields.length > 0) {
152
+ aggregateParts.push(`${key} { ${fields.join(" ")} }`);
153
+ }
154
+ });
155
+ } else {
156
+ // 默认只取 count
157
+ aggregateParts.push("count");
158
+ }
159
+
160
+ const aggregateStr = aggregateParts.join(" ");
161
+
162
+ // ✅ 拼接 query
163
+ const query = `
164
+ query ${operationName + '_aggregateount'}${varDefs ? `(${varDefs})` : ""} {
165
+ ${operationName}_aggregateount${topArgsStr} {
166
+ aggregate { ${aggregateStr} }
167
+ nodes { ${buildFields(fields)} }
168
+ }
169
+ }
170
+ `;
171
+
172
+ return { query, variables };
173
+ }
174
+
175
+
176
+
177
+
178
+
179
+
180
+
@@ -0,0 +1,59 @@
1
+ import { buildFields, buildCommonResultSelection,buildDataValue } from './baseType.ts';
2
+ import type { FieldInput } from './baseType.ts';
3
+
4
+ // ------------------- sendCode -------------------
5
+ export interface SendCodeInput {
6
+ phone: string;
7
+ dataFields?: FieldInput[]; // SmsSendResult 字段
8
+ variables?: Record<string, any>;
9
+ }
10
+
11
+ export function buildGraphQLMutationSendCode(input: SendCodeInput) {
12
+ const { phone } = input;
13
+ const finalVariables: Record<string, any> = { ...(input.variables || {}) };
14
+ if (finalVariables.phone === undefined) finalVariables.phone = phone;
15
+
16
+ const varDefs = Object.keys(finalVariables).length
17
+ ? Object.keys(finalVariables).map(k => `$${k}: String!`).join(', ')
18
+ : '';
19
+
20
+ const selection = buildCommonResultSelection(input.dataFields);
21
+
22
+ const query = `mutation sendCode${varDefs ? `(${varDefs})` : ''} {
23
+ sendCode(phone: $phone) {
24
+ ${selection}
25
+ }
26
+ }`;
27
+
28
+ return { query, variables: finalVariables };
29
+ }
30
+
31
+ // ------------------- verifyCode -------------------
32
+ export interface VerifyCodeInput {
33
+ code: string;
34
+ phone: string;
35
+ variables?: Record<string, any>;
36
+ }
37
+
38
+ export function buildGraphQLMutationVerifyCode(input: VerifyCodeInput) {
39
+ const { code, phone } = input;
40
+ const finalVariables: Record<string, any> = { ...(input.variables || {}) };
41
+ if (finalVariables.code === undefined) finalVariables.code = code;
42
+ if (finalVariables.phone === undefined) finalVariables.phone = phone;
43
+
44
+ const varDefs = Object.keys(finalVariables).length
45
+ ? Object.keys(finalVariables).map(k => `$${k}: String!`).join(', ')
46
+ : '';
47
+
48
+ const query = `mutation verifyCode${varDefs ? `(${varDefs})` : ''} {
49
+ verifyCode(code: $code, phone: $phone) {
50
+ ${buildCommonResultSelection()}
51
+ }
52
+ }`;
53
+
54
+ return { query, variables: finalVariables };
55
+ }
56
+
57
+
58
+
59
+
@@ -0,0 +1,34 @@
1
+ interface CacheItem<T> {
2
+ data: T;
3
+ expire: number;
4
+ }
5
+
6
+ export const DEFAULT_TTL = 5 * 60 * 1000; // 5 分钟
7
+ const cache = new Map<string, CacheItem<any>>();
8
+
9
+ export function getCacheKey(key: string, variables?: any): string {
10
+ return variables ? `${key}::${JSON.stringify(variables)}` : key;
11
+ }
12
+
13
+ export function getFromCache<T>(key: string): T | null {
14
+ const item = cache.get(key);
15
+ if (!item) return null;
16
+ if (Date.now() > item.expire) {
17
+ cache.delete(key);
18
+ return null;
19
+ }
20
+ return item.data;
21
+ }
22
+
23
+ export function setCache<T>(key: string, data: T, ttl = DEFAULT_TTL) {
24
+ cache.set(key, { data, expire: Date.now() + ttl });
25
+ }
26
+
27
+ export function deleteCache(key: string) {
28
+ cache.delete(key);
29
+ }
30
+
31
+ export function clearCache() {
32
+ cache.clear();
33
+ }
34
+
@@ -0,0 +1,86 @@
1
+ import { execute } from '../executor.ts';
2
+ import {
3
+ buildGraphQLMutationLogin,
4
+ buildGraphQLMutationRegisterUser,
5
+ buildGraphQLMutationLogout,
6
+ buildGraphQLMutationLogoutAllDevices,
7
+ buildGraphQLMutationLogoutDevice,
8
+ buildGraphQLMutationRefreshToken,
9
+ } from '../../builders/index.ts';
10
+ import type {
11
+ LoginInput,
12
+ RegisterUserInput,
13
+ RefreshTokenInput,
14
+ } from '../../builders/index.ts';
15
+ import type { UserToken, requestResult } from '../type.ts';
16
+ import { rateLimit } from '../../rateLimit/rateLimit.ts';
17
+ import { rateLimitConfig } from '../../rateLimit/rateLimitConfig.ts';
18
+ import { clearCache } from '../../cache/memoryCache.ts';
19
+ import {
20
+ setLoginInfo,
21
+ removeLoginInfo,
22
+ getLoginInfo
23
+ } from '../../core/client.js';
24
+
25
+ export const auth = {
26
+ async login<T = requestResult<UserToken>>(input: LoginInput) {
27
+ return rateLimit('login', 'mutation', async () => {
28
+ const { query, variables } = buildGraphQLMutationLogin(input);
29
+ const result = await execute<T>({ query, variables });
30
+ setLoginInfo((result as any).login,input.remember)
31
+ clearCache(); // 登录后刷新缓存
32
+ return result;
33
+ }, rateLimitConfig);
34
+ },
35
+
36
+ async refreshToken<T = requestResult<UserToken>>(input: RefreshTokenInput) {
37
+ return rateLimit('refreshToken', 'mutation', async () => {
38
+ const { query, variables } = buildGraphQLMutationRefreshToken(input);
39
+ const result = await execute<T>({ query, variables });
40
+ setLoginInfo((result as any).refreshToken,input.remember)
41
+ clearCache();
42
+ return result;
43
+ }, rateLimitConfig);
44
+ },
45
+
46
+ async register<T = requestResult<any>>(input: RegisterUserInput) {
47
+ return rateLimit('registerUser', 'mutation', async () => {
48
+ const { query, variables } = buildGraphQLMutationRegisterUser(input);
49
+ const result = await execute<T>({ query, variables });
50
+ clearCache();
51
+ return result;
52
+ }, rateLimitConfig);
53
+ },
54
+
55
+ async logout<T = requestResult<any>>() {
56
+ return rateLimit('logout', 'mutation', async () => {
57
+ const { query, variables } = buildGraphQLMutationLogout();
58
+ const result = await execute<T>({ query, variables });
59
+ removeLoginInfo()
60
+ clearCache();
61
+ return result;
62
+ }, rateLimitConfig);
63
+ },
64
+
65
+ async logoutAllDevices<T = requestResult<any>>() {
66
+ return rateLimit('logoutAllDevices', 'mutation', async () => {
67
+ const { query, variables } = buildGraphQLMutationLogoutAllDevices();
68
+ const result = await execute<T>({ query, variables });
69
+ removeLoginInfo()
70
+ clearCache();
71
+ return result;
72
+ }, rateLimitConfig);
73
+ },
74
+
75
+ async logoutDevice<T = requestResult<any>>(deviceId: string) {
76
+ return rateLimit('logoutDevice', 'mutation', async () => {
77
+ const { query, variables } = buildGraphQLMutationLogoutDevice({ deviceId });
78
+ const result = await execute<T>({ query, variables });
79
+ if (getLoginInfo()?.deviceId==deviceId) {
80
+ removeLoginInfo()
81
+ }
82
+ clearCache();
83
+ return result;
84
+ }, rateLimitConfig);
85
+ },
86
+ };
@@ -0,0 +1,22 @@
1
+ // src/core/api/gql.ts
2
+ import { execute } from '../executor.js';
3
+ import type { DocumentNode } from 'graphql';
4
+ import type { requestResult } from '../type.ts';
5
+ /**
6
+ * 原生 GraphQL 执行模块
7
+ * 可执行任意 query / mutation / subscription
8
+ */
9
+ export const gql = {
10
+ /**
11
+ * 执行任意 GraphQL 文本或 DocumentNode
12
+ * @param query 原生 GQL 文本或 DocumentNode
13
+ * @param variables 可选变量
14
+ * @returns Promise<T>
15
+ */
16
+ async execute<T = requestResult<any>>(
17
+ query: string | DocumentNode,
18
+ variables?: Record<string, any>
19
+ ): Promise<T> {
20
+ return execute<T>({ query, variables });
21
+ },
22
+ };
@@ -0,0 +1,100 @@
1
+ import { execute } from '../executor.ts';
2
+ import {
3
+ buildGraphQLMutationInsertOne,
4
+ buildGraphQLMutationBatchInsert,
5
+
6
+ buildGraphQLMutationUpdate,
7
+ buildGraphQLMutationBatchUpdate,
8
+ buildGraphQLMutationUpdateByPk,
9
+
10
+ buildGraphQLMutationDelete,
11
+ buildGraphQLMutationDeleteById,
12
+ } from '../../builders/index.ts';
13
+ import type {
14
+ InsertOneInput,
15
+ BatchInsertInput,
16
+
17
+ DeleteInput,
18
+ DeleteByIdInput,
19
+
20
+
21
+ BatchUpdateInput,
22
+ UpdateByPkInput,
23
+ UpdateInput,
24
+ } from '../../builders/index.ts';
25
+ import type { requestResult } from '../type.ts';
26
+ import { clearCache } from '../../cache/memoryCache.ts';
27
+ import { rateLimit } from '../../rateLimit/rateLimit.ts';
28
+
29
+ export const mutation = {
30
+ async insertOne<T = requestResult<any>>(input: InsertOneInput) {
31
+ return rateLimit('insertOne', 'mutation', async () => {
32
+ const { query, variables } = buildGraphQLMutationInsertOne(input);
33
+ const result = await execute<T>({ query, variables });
34
+
35
+ // 清空缓存,保证数据一致
36
+ clearCache();
37
+ return result;
38
+ });
39
+ },
40
+
41
+ async batchInsert<T = requestResult<any>>(input: BatchInsertInput) {
42
+ return rateLimit('batchInsert', 'mutation', async () => {
43
+ const { query, variables } = buildGraphQLMutationBatchInsert(input);
44
+ const result = await execute<T>({ query, variables });
45
+
46
+ clearCache();
47
+ return result;
48
+ });
49
+ },
50
+
51
+ async update<T = requestResult<any>>(input: UpdateInput) {
52
+ return rateLimit('update', 'mutation', async () => {
53
+ const { query, variables } = buildGraphQLMutationUpdate(input);
54
+ const result = await execute<T>({ query, variables });
55
+
56
+ clearCache();
57
+ return result;
58
+ });
59
+ },
60
+
61
+ async batchUpdate<T = requestResult<any>>(input: BatchUpdateInput) {
62
+ return rateLimit('batchUpdate', 'mutation', async () => {
63
+ const { query, variables } = buildGraphQLMutationBatchUpdate(input);
64
+ const result = await execute<T>({ query, variables });
65
+
66
+ clearCache();
67
+ return result;
68
+ });
69
+ },
70
+
71
+ async updateByPk<T = requestResult<any>>(input: UpdateByPkInput) {
72
+ return rateLimit('updateByPk', 'mutation', async () => {
73
+ const { query, variables } = buildGraphQLMutationUpdateByPk(input);
74
+ const result = await execute<T>({ query, variables });
75
+
76
+ clearCache();
77
+ return result;
78
+ });
79
+ },
80
+
81
+ async delete<T = requestResult<any>>(input: DeleteInput) {
82
+ return rateLimit('delete', 'mutation', async () => {
83
+ const { query, variables } = buildGraphQLMutationDelete(input);
84
+ const result = await execute<T>({ query, variables });
85
+
86
+ clearCache();
87
+ return result;
88
+ });
89
+ },
90
+
91
+ async deleteById<T = requestResult<any>>(input: DeleteByIdInput) {
92
+ return rateLimit('deleteById', 'mutation', async () => {
93
+ const { query, variables } = buildGraphQLMutationDeleteById(input);
94
+ const result = await execute<T>({ query, variables });
95
+
96
+ clearCache();
97
+ return result;
98
+ });
99
+ },
100
+ };
@@ -0,0 +1,82 @@
1
+ import { execute } from '../executor.ts';
2
+ import {
3
+ buildGraphQLQueryList,
4
+ buildGraphQLQueryByIdFixed,
5
+ buildGraphQLQueryPageList,
6
+ buildGraphQLQueryAggregate,
7
+ } from '../../builders/index.ts';
8
+ import type {
9
+ QueryInput,
10
+ QueryByIdInput,
11
+ QueryPageListInput,
12
+ QueryAggregateInput,
13
+ } from '../../builders/index.ts';
14
+ import type { requestResult } from '../type.ts';
15
+ import { getCacheKey, getFromCache, setCache, DEFAULT_TTL } from '../../cache/memoryCache.ts';
16
+ import { rateLimit } from '../../rateLimit/rateLimit.ts';
17
+
18
+ export const query = {
19
+ async list<T = requestResult<any>>(input: QueryInput, useCache = true, ttl?: number) {
20
+ return rateLimit('list', 'query', async () => {
21
+ const { query: q, variables } = buildGraphQLQueryList(input);
22
+ const key = getCacheKey(q, variables);
23
+
24
+ if (useCache) {
25
+ const cached = getFromCache<T>(key);
26
+ if (cached) return cached;
27
+ }
28
+
29
+ const result = await execute<T>({ query: q, variables });
30
+ if (useCache) setCache(key, result, ttl ?? DEFAULT_TTL);
31
+ return result;
32
+ });
33
+ },
34
+
35
+ async byId<T = requestResult<any>>(input: QueryByIdInput, useCache = true, ttl?: number) {
36
+ return rateLimit('byId', 'query', async () => {
37
+ const { query: q, variables } = buildGraphQLQueryByIdFixed(input);
38
+ const key = getCacheKey(q, variables);
39
+
40
+ if (useCache) {
41
+ const cached = getFromCache<T>(key);
42
+ if (cached) return cached;
43
+ }
44
+
45
+ const result = await execute<T>({ query: q, variables });
46
+ if (useCache) setCache(key, result, ttl ?? DEFAULT_TTL);
47
+ return result;
48
+ });
49
+ },
50
+
51
+ async page<T = requestResult<any>>(input: QueryPageListInput, useCache = true, ttl?: number) {
52
+ return rateLimit('page', 'query', async () => {
53
+ const { query: q, variables } = buildGraphQLQueryPageList(input);
54
+ const key = getCacheKey(q, variables);
55
+
56
+ if (useCache) {
57
+ const cached = getFromCache<T>(key);
58
+ if (cached) return cached;
59
+ }
60
+
61
+ const result = await execute<T>({ query: q, variables });
62
+ if (useCache) setCache(key, result, ttl ?? DEFAULT_TTL);
63
+ return result;
64
+ });
65
+ },
66
+
67
+ async aggregate<T = requestResult<any>>(input: QueryAggregateInput, useCache = true, ttl?: number) {
68
+ return rateLimit('aggregate', 'query', async () => {
69
+ const { query: q, variables } = buildGraphQLQueryAggregate(input);
70
+ const key = getCacheKey(q, variables);
71
+
72
+ if (useCache) {
73
+ const cached = getFromCache<T>(key);
74
+ if (cached) return cached;
75
+ }
76
+
77
+ const result = await execute<T>({ query: q, variables });
78
+ if (useCache) setCache(key, result, ttl ?? DEFAULT_TTL);
79
+ return result;
80
+ });
81
+ },
82
+ };
@@ -0,0 +1,18 @@
1
+ import { execute } from '../executor.ts';
2
+ import {
3
+ buildGraphQLMutationSendCode,
4
+ buildGraphQLMutationVerifyCode,
5
+ } from '../../builders/index.ts';
6
+ import type { SendCodeInput, VerifyCodeInput } from '../../builders/index.ts';
7
+ import type { requestResult } from '../type.ts';
8
+ export const sms = {
9
+ async send<T = requestResult<any>>(input: SendCodeInput) {
10
+ const { query, variables } = buildGraphQLMutationSendCode(input);
11
+ return execute<T>({ query, variables });
12
+ },
13
+
14
+ async verify<T = requestResult<any>>(input: VerifyCodeInput) {
15
+ const { query, variables } = buildGraphQLMutationVerifyCode(input);
16
+ return execute<T>({ query, variables });
17
+ },
18
+ };
@@ -0,0 +1,47 @@
1
+ // src/core/client.ts
2
+ import { CCRequest } from './core.ts';
3
+ import type { RequestConfig, RequestInterceptor, UserToken } from './type.ts';
4
+
5
+ let client: CCRequest | null = null;
6
+
7
+ /** 初始化全局客户端 */
8
+ export function initGraphQLClient(config: RequestConfig): CCRequest {
9
+ client = new CCRequest(config);
10
+ return client;
11
+ }
12
+
13
+ /** 获取全局客户端实例 */
14
+ export function getClient(): CCRequest {
15
+ if (!client) throw new Error('GraphQL client not initialized. Call initGraphQLClient() first.');
16
+ return client;
17
+ }
18
+ /** 注册全局拦截器 */
19
+ export const useInterceptor = (interceptor: RequestInterceptor) =>
20
+ getClient().use(interceptor);
21
+
22
+
23
+
24
+ // ===== 便捷操作函数 =====
25
+ // token 修改 → 重建实例
26
+ export const setToken = (token: string) => getClient().setToken(token);
27
+ export const removeToken = () => getClient().removeToken();
28
+
29
+ // 登录信息
30
+ export const setLoginInfo = (loginInfo: UserToken, remember: boolean = false) => getClient().setLoginInfo(loginInfo,remember)
31
+ export const removeLoginInfo = () => getClient().removeLoginInfo()
32
+ export const getLoginInfo = () => getClient().getLoginInfo()
33
+
34
+
35
+
36
+
37
+
38
+ // endpoint 修改 → 重建实例
39
+ export const setEndpoint = (endpoint: string) => getClient().setEndpoint(endpoint);
40
+
41
+ // 普通 header 操作 → 不重建实例
42
+ export const setHeader = (key: string, value: string) => getClient().setHeader(key, value);
43
+ export const setHeaders = (headers: Record<string, string>) => getClient().setHeaders(headers);
44
+ export const removeHeader = (key: string) => getClient().removeHeader(key);
45
+ export const clearHeaders = () => getClient().clearHeaders();
46
+
47
+