@ctil/gql 1.0.4 → 1.0.6
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/README.md +29 -8
- package/dist/index.cjs +215 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +61 -1
- package/dist/index.d.ts +61 -1
- package/dist/index.js +214 -9
- package/dist/index.js.map +1 -1
- package/package.json +10 -3
- package/.vscode/launch.json +0 -18
- package/ctil-gql-1.0.4.tgz +0 -0
- package/src/builders/auth.ts +0 -182
- package/src/builders/baseType.ts +0 -194
- package/src/builders/index.ts +0 -5
- package/src/builders/mutation.ts +0 -341
- package/src/builders/query.ts +0 -180
- package/src/builders/sms.ts +0 -59
- package/src/cache/memoryCache.ts +0 -34
- package/src/core/api/auth.ts +0 -86
- package/src/core/api/gql.ts +0 -22
- package/src/core/api/mutation.ts +0 -100
- package/src/core/api/query.ts +0 -82
- package/src/core/api/sms.ts +0 -18
- package/src/core/client.ts +0 -47
- package/src/core/core.ts +0 -284
- package/src/core/executor.ts +0 -19
- package/src/core/type.ts +0 -76
- package/src/device/index.ts +0 -116
- package/src/index.ts +0 -60
- package/src/rateLimit/rateLimit.ts +0 -51
- package/src/rateLimit/rateLimitConfig.ts +0 -12
- package/src/test.ts +0 -80
- package/tsconfig.json +0 -17
- package/tsup.config.ts +0 -10
package/src/builders/mutation.ts
DELETED
|
@@ -1,341 +0,0 @@
|
|
|
1
|
-
import { buildWhere, buildFields, buildDataValue,formatGraphQLValue,buildMutationFields,buildCommonResultSelection } from './baseType.ts';
|
|
2
|
-
import type { WhereInput, FieldInput } from './baseType.ts';
|
|
3
|
-
|
|
4
|
-
// =================== 插入 ===================
|
|
5
|
-
|
|
6
|
-
// 单个插入入参
|
|
7
|
-
export interface InsertOneInput {
|
|
8
|
-
operationName: string; // 实体名,例如 user
|
|
9
|
-
fields: FieldInput[]; // 返回字段
|
|
10
|
-
data: Record<string, any>; // 插入的数据
|
|
11
|
-
variables?: Record<string, any>; // 传入的变量名和初始值
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
// 批量插入入参
|
|
15
|
-
export interface BatchInsertInput {
|
|
16
|
-
operationName: string; // 实体名,例如 user
|
|
17
|
-
fields: FieldInput[]; // 返回字段
|
|
18
|
-
datas: Record<string, any>[]; // 插入的数据列表
|
|
19
|
-
variables?: Record<string, any>; // 传入的变量名和初始值
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// =================== 修改 ===================
|
|
23
|
-
|
|
24
|
-
// 根据条件更新入参
|
|
25
|
-
export interface UpdateInput {
|
|
26
|
-
operationName: string; // 实体名,例如 user
|
|
27
|
-
fields: FieldInput[]; // 返回字段
|
|
28
|
-
_set: Record<string, any>; // 更新的数据
|
|
29
|
-
where: WhereInput; // 条件(必需)
|
|
30
|
-
variables?: Record<string, any>; // 传入的变量名和初始值
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// 批量更新入参(根据 ID)
|
|
34
|
-
export interface BatchUpdateInput {
|
|
35
|
-
operationName: string; // 实体名,例如 user
|
|
36
|
-
fields: FieldInput[]; // 返回字段
|
|
37
|
-
_set: Record<string, any>[]; // 更新的数据列表(每条必须包含 id)
|
|
38
|
-
variables?: Record<string, any>; // 传入的变量名和初始值
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// 根据主键更新入参
|
|
42
|
-
export interface UpdateByPkInput {
|
|
43
|
-
operationName: string; // 实体名,例如 user
|
|
44
|
-
fields: FieldInput[]; // 返回字段
|
|
45
|
-
_set: Record<string, any>; // 更新的数据
|
|
46
|
-
pk_columns: string | number; // 主键ID
|
|
47
|
-
variables?: Record<string, any>; // 传入的变量名和初始值
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// =================== 删除 ===================
|
|
51
|
-
|
|
52
|
-
// 根据主键删除入参
|
|
53
|
-
export interface DeleteByIdInput {
|
|
54
|
-
operationName: string; // 实体名,例如 user
|
|
55
|
-
fields: FieldInput[]; // 返回字段(删除前的数据)
|
|
56
|
-
pk_columns: string | number; // 主键ID
|
|
57
|
-
variables?: Record<string, any>; // 传入的变量名和初始值
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// 根据条件删除入参
|
|
61
|
-
export interface DeleteInput {
|
|
62
|
-
operationName: string; // 实体名,例如 user
|
|
63
|
-
fields: FieldInput[]; // 返回字段(删除前的数据)
|
|
64
|
-
where: WhereInput; // 条件(必需)
|
|
65
|
-
variables?: Record<string, any>; // 传入的变量名和初始值
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// =================== 返回字段类型 ===================
|
|
69
|
-
|
|
70
|
-
// Mutation 返回字段
|
|
71
|
-
export type MutationField = {
|
|
72
|
-
affected_rows?: boolean; // 是否返回受影响行数
|
|
73
|
-
returning?: FieldInput[]; // 返回的数据字段
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
// =================== 插入操作 ===================
|
|
80
|
-
|
|
81
|
-
/** 生成单个插入的 GraphQL mutation */
|
|
82
|
-
export function buildGraphQLMutationInsertOne(input: InsertOneInput) {
|
|
83
|
-
const { operationName, fields, data, variables } = input;
|
|
84
|
-
const entityName = operationName.toLowerCase();
|
|
85
|
-
|
|
86
|
-
// 生成变量定义
|
|
87
|
-
const varDefs = variables
|
|
88
|
-
? Object.keys(variables)
|
|
89
|
-
.map(k => `$${k}: String!`)
|
|
90
|
-
.join(', ')
|
|
91
|
-
: '';
|
|
92
|
-
|
|
93
|
-
// 构建 data 参数(可以作为变量传入,或直接内联)
|
|
94
|
-
let dataArg: string;
|
|
95
|
-
if (variables && variables.data) {
|
|
96
|
-
dataArg = '$data';
|
|
97
|
-
} else {
|
|
98
|
-
dataArg = `{ ${buildDataValue(data)} }`;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// 更新 variables
|
|
102
|
-
const finalVariables: Record<string, any> = variables || {};
|
|
103
|
-
if (!variables || !variables.data) {
|
|
104
|
-
finalVariables.data = data;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
const mutationName = `insert_${entityName}_one`;
|
|
108
|
-
const query = `mutation ${mutationName}${varDefs ? `(${varDefs})` : ''} {
|
|
109
|
-
${mutationName}(${operationName}: ${dataArg}) {
|
|
110
|
-
${buildMutationFields(fields)}
|
|
111
|
-
}
|
|
112
|
-
}`;
|
|
113
|
-
|
|
114
|
-
return { query, variables: finalVariables };
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/** 生成批量插入的 GraphQL mutation */
|
|
118
|
-
export function buildGraphQLMutationBatchInsert(input: BatchInsertInput) {
|
|
119
|
-
const { operationName, fields, datas, variables } = input;
|
|
120
|
-
const entityName = operationName.toLowerCase();
|
|
121
|
-
|
|
122
|
-
// 生成变量定义
|
|
123
|
-
const varDefs = variables
|
|
124
|
-
? Object.keys(variables)
|
|
125
|
-
.map(k => `$${k}: String!`)
|
|
126
|
-
.join(', ')
|
|
127
|
-
: '';
|
|
128
|
-
|
|
129
|
-
// 构建 datas 参数
|
|
130
|
-
let datasArg: string;
|
|
131
|
-
if (variables && variables.datas) {
|
|
132
|
-
datasArg = '$datas';
|
|
133
|
-
} else {
|
|
134
|
-
const datasArr = datas.map(d => `{ ${buildDataValue(d)} }`).join(' ');
|
|
135
|
-
datasArg = `[${datasArr}]`;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
// 更新 variables
|
|
139
|
-
const finalVariables: Record<string, any> = variables || {};
|
|
140
|
-
if (!variables || !variables.datas) {
|
|
141
|
-
finalVariables.datas = datas;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
const mutationName = `insert_${entityName}s`;
|
|
145
|
-
const query = `mutation ${mutationName}${varDefs ? `(${varDefs})` : ''} {
|
|
146
|
-
${mutationName}(${operationName}s: ${datasArg}) {
|
|
147
|
-
affected_rows
|
|
148
|
-
returning { ${buildFields(fields)} }
|
|
149
|
-
}
|
|
150
|
-
}`;
|
|
151
|
-
|
|
152
|
-
return { query, variables: finalVariables };
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
// =================== 修改操作 ===================
|
|
159
|
-
|
|
160
|
-
/** 生成根据条件更新的 GraphQL mutation */
|
|
161
|
-
export function buildGraphQLMutationUpdate(input: UpdateInput) {
|
|
162
|
-
const { operationName, fields, _set, where, variables } = input;
|
|
163
|
-
const entityName = operationName.toLowerCase();
|
|
164
|
-
|
|
165
|
-
// 生成变量定义
|
|
166
|
-
const varDefs = variables
|
|
167
|
-
? Object.keys(variables)
|
|
168
|
-
.map(k => `$${k}: String!`)
|
|
169
|
-
.join(', ')
|
|
170
|
-
: '';
|
|
171
|
-
|
|
172
|
-
// 构建参数
|
|
173
|
-
const args: string[] = [];
|
|
174
|
-
|
|
175
|
-
// _set 参数
|
|
176
|
-
let setArg: string;
|
|
177
|
-
if (variables && variables._set) {
|
|
178
|
-
setArg = '$_set';
|
|
179
|
-
} else {
|
|
180
|
-
setArg = `{ ${buildDataValue(_set)} }`;
|
|
181
|
-
}
|
|
182
|
-
args.push(`_set: ${setArg}`);
|
|
183
|
-
|
|
184
|
-
// where 参数
|
|
185
|
-
args.push(`where: { ${buildWhere(where)} }`);
|
|
186
|
-
|
|
187
|
-
// 更新 variables
|
|
188
|
-
const finalVariables: Record<string, any> = variables || {};
|
|
189
|
-
if (!variables || !variables._set) {
|
|
190
|
-
finalVariables._set = _set;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
const mutationName = `update_${entityName}`;
|
|
194
|
-
const query = `mutation ${mutationName}${varDefs ? `(${varDefs})` : ''} {
|
|
195
|
-
${mutationName}(${args.join(', ')}) {
|
|
196
|
-
${buildMutationFields(fields)}
|
|
197
|
-
}
|
|
198
|
-
}`;
|
|
199
|
-
|
|
200
|
-
return { query, variables: finalVariables };
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
/** 生成批量更新的 GraphQL mutation(根据 ID) */
|
|
204
|
-
export function buildGraphQLMutationBatchUpdate(input: BatchUpdateInput) {
|
|
205
|
-
const { operationName, fields, _set, variables } = input;
|
|
206
|
-
const entityName = operationName.toLowerCase();
|
|
207
|
-
|
|
208
|
-
// 生成变量定义
|
|
209
|
-
const varDefs = variables
|
|
210
|
-
? Object.keys(variables)
|
|
211
|
-
.map(k => `$${k}: String!`)
|
|
212
|
-
.join(', ')
|
|
213
|
-
: '';
|
|
214
|
-
|
|
215
|
-
// 构建 _set 参数
|
|
216
|
-
let setArg: string;
|
|
217
|
-
if (variables && variables._set) {
|
|
218
|
-
setArg = '$_set';
|
|
219
|
-
} else {
|
|
220
|
-
const setsArr = _set.map(s => `{ ${buildDataValue(s)} }`).join(' ');
|
|
221
|
-
setArg = `[${setsArr}]`;
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
// 更新 variables
|
|
225
|
-
const finalVariables: Record<string, any> = variables || {};
|
|
226
|
-
if (!variables || !variables._set) {
|
|
227
|
-
finalVariables._set = _set;
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
const mutationName = `update_${entityName}_many`;
|
|
231
|
-
const query = `mutation ${mutationName}${varDefs ? `(${varDefs})` : ''} {
|
|
232
|
-
${mutationName}(_set: ${setArg}) {
|
|
233
|
-
affected_rows
|
|
234
|
-
returning { ${buildFields(fields)} }
|
|
235
|
-
}
|
|
236
|
-
}`;
|
|
237
|
-
|
|
238
|
-
return { query, variables: finalVariables };
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
/** 生成根据主键更新的 GraphQL mutation */
|
|
242
|
-
export function buildGraphQLMutationUpdateByPk(input: UpdateByPkInput) {
|
|
243
|
-
const { operationName, fields, _set, pk_columns, variables } = input;
|
|
244
|
-
const entityName = operationName.toLowerCase();
|
|
245
|
-
|
|
246
|
-
// 生成变量定义
|
|
247
|
-
const varDefs = variables
|
|
248
|
-
? Object.keys(variables)
|
|
249
|
-
.map(k => `$${k}: String!`)
|
|
250
|
-
.join(', ')
|
|
251
|
-
: '';
|
|
252
|
-
|
|
253
|
-
// 构建参数
|
|
254
|
-
const args: string[] = [];
|
|
255
|
-
|
|
256
|
-
// _set 参数
|
|
257
|
-
let setArg: string;
|
|
258
|
-
if (variables && variables._set) {
|
|
259
|
-
setArg = '$_set';
|
|
260
|
-
} else {
|
|
261
|
-
setArg = `{ ${buildDataValue(_set)} }`;
|
|
262
|
-
}
|
|
263
|
-
args.push(`_set: ${setArg}`);
|
|
264
|
-
|
|
265
|
-
// pk_columns 参数(固定使用 Long! 类型)
|
|
266
|
-
args.push(`pk_columns: ${formatGraphQLValue(pk_columns)}`);
|
|
267
|
-
|
|
268
|
-
// 更新 variables
|
|
269
|
-
const finalVariables: Record<string, any> = variables || {};
|
|
270
|
-
if (!variables || !variables._set) {
|
|
271
|
-
finalVariables._set = _set;
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
const mutationName = `update_${entityName}_by_pk`;
|
|
275
|
-
const query = `mutation ${mutationName}${varDefs ? `(${varDefs})` : ''} {
|
|
276
|
-
${mutationName}(${args.join(', ')}) {
|
|
277
|
-
${buildMutationFields(fields)}
|
|
278
|
-
}
|
|
279
|
-
}`;
|
|
280
|
-
|
|
281
|
-
return { query, variables: finalVariables };
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
// =================== 删除操作 ===================
|
|
287
|
-
|
|
288
|
-
/** 生成根据主键删除的 GraphQL mutation */
|
|
289
|
-
export function buildGraphQLMutationDeleteById(input: DeleteByIdInput) {
|
|
290
|
-
const { operationName, fields, pk_columns, variables } = input;
|
|
291
|
-
const entityName = operationName.toLowerCase();
|
|
292
|
-
|
|
293
|
-
// 生成变量定义
|
|
294
|
-
const varDefs = variables
|
|
295
|
-
? Object.keys(variables)
|
|
296
|
-
.map(k => `$${k}: String!`)
|
|
297
|
-
.join(', ')
|
|
298
|
-
: '';
|
|
299
|
-
|
|
300
|
-
// pk_columns 参数(固定使用 Long! 类型)
|
|
301
|
-
const args = `pk_columns: ${formatGraphQLValue(pk_columns)}`;
|
|
302
|
-
|
|
303
|
-
const mutationName = `delete_${entityName}_by_pk`;
|
|
304
|
-
const query = `mutation ${mutationName}${varDefs ? `(${varDefs})` : ''} {
|
|
305
|
-
${mutationName}(${args}) {
|
|
306
|
-
${buildMutationFields(fields)}
|
|
307
|
-
}
|
|
308
|
-
}`;
|
|
309
|
-
|
|
310
|
-
return { query, variables: variables || {} };
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
/** 生成根据条件删除的 GraphQL mutation */
|
|
314
|
-
export function buildGraphQLMutationDelete(input: DeleteInput) {
|
|
315
|
-
const { operationName, fields, where, variables } = input;
|
|
316
|
-
const entityName = operationName.toLowerCase();
|
|
317
|
-
|
|
318
|
-
// 生成变量定义
|
|
319
|
-
const varDefs = variables
|
|
320
|
-
? Object.keys(variables)
|
|
321
|
-
.map(k => `$${k}: String!`)
|
|
322
|
-
.join(', ')
|
|
323
|
-
: '';
|
|
324
|
-
|
|
325
|
-
// where 参数
|
|
326
|
-
const args = `where: { ${buildWhere(where)} }`;
|
|
327
|
-
|
|
328
|
-
const mutationName = `delete_${entityName}`;
|
|
329
|
-
const query = `mutation ${mutationName}${varDefs ? `(${varDefs})` : ''} {
|
|
330
|
-
${mutationName}(${args}) {
|
|
331
|
-
affected_rows
|
|
332
|
-
returning { ${buildFields(fields)} }
|
|
333
|
-
}
|
|
334
|
-
}`;
|
|
335
|
-
|
|
336
|
-
return { query, variables: variables || {} };
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
package/src/builders/query.ts
DELETED
|
@@ -1,180 +0,0 @@
|
|
|
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
|
-
|
package/src/builders/sms.ts
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
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
|
-
|
package/src/cache/memoryCache.ts
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
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
|
-
|
package/src/core/api/auth.ts
DELETED
|
@@ -1,86 +0,0 @@
|
|
|
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
|
-
};
|