@cloudcome/utils-uni 1.31.0 → 1.32.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.
- package/README.md +1 -1
- package/dist/_helpers.cjs +41 -18
- package/dist/_helpers.cjs.map +1 -1
- package/dist/_helpers.mjs +28 -17
- package/dist/_helpers.mjs.map +1 -1
- package/dist/app.cjs +40 -5
- package/dist/app.cjs.map +1 -1
- package/dist/app.mjs +40 -6
- package/dist/app.mjs.map +1 -1
- package/dist/client.cjs +72 -54
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.ts +2 -2
- package/dist/client.mjs +70 -55
- package/dist/client.mjs.map +1 -1
- package/dist/cloud/request.d.ts +82 -0
- package/dist/cloud/types.d.ts +2 -2
- package/dist/cloud.cjs +229 -112
- package/dist/cloud.cjs.map +1 -1
- package/dist/cloud.d.ts +3 -2
- package/dist/cloud.mjs +225 -114
- package/dist/cloud.mjs.map +1 -1
- package/dist/database/_db.class.d.ts +1 -1
- package/dist/database/each.d.ts +31 -0
- package/dist/database/types.d.ts +1 -1
- package/dist/database.cjs +684 -615
- package/dist/database.cjs.map +1 -1
- package/dist/database.d.ts +8 -7
- package/dist/database.mjs +682 -622
- package/dist/database.mjs.map +1 -1
- package/dist/index.cjs +8 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +9 -5
- package/dist/index.mjs.map +1 -1
- package/dist/page.cjs +98 -13
- package/dist/page.cjs.map +1 -1
- package/dist/page.mjs +97 -15
- package/dist/page.mjs.map +1 -1
- package/package.json +36 -37
- package/dist/error.cjs +0 -10
- package/dist/error.cjs.map +0 -1
- package/dist/error.mjs +0 -11
- package/dist/error.mjs.map +0 -1
package/dist/database.cjs
CHANGED
|
@@ -1,637 +1,704 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
static isMutateCommand(cmd) {
|
|
34
|
-
return cmd._isMutate;
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
class DbQueryCommand extends DbBaseCommand {
|
|
38
|
-
_isQuery = true;
|
|
39
|
-
}
|
|
40
|
-
class DbMutateCommand extends DbBaseCommand {
|
|
41
|
-
_isMutate = true;
|
|
42
|
-
}
|
|
43
|
-
const dbQuery = {
|
|
44
|
-
/**
|
|
45
|
-
* 等于操作符
|
|
46
|
-
* @param value 比较值
|
|
47
|
-
* @returns DbQueryCommand 查询命令对象
|
|
48
|
-
*/
|
|
49
|
-
eq: (value) => new DbQueryCommand("eq", value),
|
|
50
|
-
/**
|
|
51
|
-
* 不等于操作符
|
|
52
|
-
* @param value 比较值
|
|
53
|
-
* @returns DbQueryCommand 查询命令对象
|
|
54
|
-
*/
|
|
55
|
-
neq: (value) => new DbQueryCommand("neq", value),
|
|
56
|
-
/**
|
|
57
|
-
* 大于操作符
|
|
58
|
-
* @param value 比较值
|
|
59
|
-
* @returns DbQueryCommand 查询命令对象
|
|
60
|
-
*/
|
|
61
|
-
gt: (value) => new DbQueryCommand("gt", value),
|
|
62
|
-
/**
|
|
63
|
-
* 大于等于操作符
|
|
64
|
-
* @param value 比较值
|
|
65
|
-
* @returns DbQueryCommand 查询命令对象
|
|
66
|
-
*/
|
|
67
|
-
gte: (value) => new DbQueryCommand("gte", value),
|
|
68
|
-
/**
|
|
69
|
-
* 小于操作符
|
|
70
|
-
* @param value 比较值
|
|
71
|
-
* @returns DbQueryCommand 查询命令对象
|
|
72
|
-
*/
|
|
73
|
-
lt: (value) => new DbQueryCommand("lt", value),
|
|
74
|
-
/**
|
|
75
|
-
* 小于等于操作符
|
|
76
|
-
* @param value 比较值
|
|
77
|
-
* @returns DbQueryCommand 查询命令对象
|
|
78
|
-
*/
|
|
79
|
-
lte: (value) => new DbQueryCommand("lte", value),
|
|
80
|
-
/**
|
|
81
|
-
* 包含在数组中操作符
|
|
82
|
-
* @param value 值数组
|
|
83
|
-
* @returns DbQueryCommand 查询命令对象
|
|
84
|
-
*/
|
|
85
|
-
in: (value) => new DbQueryCommand("in", value),
|
|
86
|
-
/**
|
|
87
|
-
* 不包含在数组中操作符
|
|
88
|
-
* @param value 值数组
|
|
89
|
-
* @returns DbQueryCommand 查询命令对象
|
|
90
|
-
*/
|
|
91
|
-
nin: (value) => new DbQueryCommand("nin", value),
|
|
92
|
-
/**
|
|
93
|
-
* 数组长度匹配操作符
|
|
94
|
-
* @param size 数组长度
|
|
95
|
-
* @returns DbQueryCommand 查询命令对象
|
|
96
|
-
*/
|
|
97
|
-
size: (size) => new DbQueryCommand("size", size),
|
|
98
|
-
/**
|
|
99
|
-
* 正则表达式匹配操作符
|
|
100
|
-
* @param regExp 正则表达式
|
|
101
|
-
* @returns DbQueryCommand 查询命令对象
|
|
102
|
-
*/
|
|
103
|
-
regExp: (regExp) => new DbQueryCommand("regExp", regExp, {
|
|
104
|
-
rewriteValue: (db, parameter) => parameter
|
|
105
|
-
}),
|
|
106
|
-
/**
|
|
107
|
-
* 逻辑与操作符
|
|
108
|
-
* @param conditions 查询条件参数
|
|
109
|
-
* @returns DbQueryCommand 查询命令对象
|
|
110
|
-
*/
|
|
111
|
-
and: (conditions) => new DbQueryCommand("and", conditions, {
|
|
112
|
-
formatParameter: (db) => conditions.map((c) => DbBaseCommand.getValue(c, db))
|
|
113
|
-
}),
|
|
114
|
-
/**
|
|
115
|
-
* 逻辑或操作符
|
|
116
|
-
* @param conditions 查询条件参数
|
|
117
|
-
* @returns DbQueryCommand 查询命令对象
|
|
118
|
-
*/
|
|
119
|
-
or: (conditions) => new DbQueryCommand("or", conditions, {
|
|
120
|
-
formatParameter: (db) => conditions.map((c) => DbBaseCommand.getValue(c, db))
|
|
121
|
-
})
|
|
2
|
+
const require__helpers = require("./_helpers.cjs");
|
|
3
|
+
const require_cloud = require("./cloud.cjs");
|
|
4
|
+
let _cloudcome_utils_core_type = require("@cloudcome/utils-core/type");
|
|
5
|
+
let _cloudcome_utils_core_object = require("@cloudcome/utils-core/object");
|
|
6
|
+
let _cloudcome_utils_core_try = require("@cloudcome/utils-core/try");
|
|
7
|
+
//#region src/database/_command.class.ts
|
|
8
|
+
var DbBaseCommand = class {
|
|
9
|
+
_isQuery = false;
|
|
10
|
+
_isMutate = false;
|
|
11
|
+
constructor(_command, _parameter, _options) {
|
|
12
|
+
this._command = _command;
|
|
13
|
+
this._parameter = _parameter;
|
|
14
|
+
this._options = _options;
|
|
15
|
+
}
|
|
16
|
+
static getValue(cmd, db) {
|
|
17
|
+
if (cmd._options?.rewriteValue) return cmd._options.rewriteValue(db, cmd._parameter);
|
|
18
|
+
return db.command[cmd._command].call(db.command, cmd._options?.formatParameter?.(db) || cmd._parameter);
|
|
19
|
+
}
|
|
20
|
+
static getExpression(cmd, fieldName) {
|
|
21
|
+
return { [`$${cmd._command}`]: [fieldName, cmd._parameter] };
|
|
22
|
+
}
|
|
23
|
+
static isQueryCommand(cmd) {
|
|
24
|
+
return cmd._isQuery;
|
|
25
|
+
}
|
|
26
|
+
static isMutateCommand(cmd) {
|
|
27
|
+
return cmd._isMutate;
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
var DbQueryCommand = class extends DbBaseCommand {
|
|
31
|
+
_isQuery = true;
|
|
122
32
|
};
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
* 数值增加操作符
|
|
126
|
-
* @param value 增加的数值
|
|
127
|
-
* @returns DbMutateCommand 变更命令对象
|
|
128
|
-
*/
|
|
129
|
-
inc: (value) => new DbMutateCommand("inc", value),
|
|
130
|
-
/**
|
|
131
|
-
* 数值乘法操作符
|
|
132
|
-
* @param value 乘数
|
|
133
|
-
* @returns DbMutateCommand 变更命令对象
|
|
134
|
-
*/
|
|
135
|
-
mul: (value) => new DbMutateCommand("mul", value),
|
|
136
|
-
/**
|
|
137
|
-
* 设置字段值操作符
|
|
138
|
-
* @param value 设置的值
|
|
139
|
-
* @returns DbMutateCommand 变更命令对象
|
|
140
|
-
*/
|
|
141
|
-
set: (value) => new DbMutateCommand("set", value),
|
|
142
|
-
/**
|
|
143
|
-
* 向数组末尾添加元素操作符
|
|
144
|
-
* @param value 添加的值
|
|
145
|
-
* @returns DbMutateCommand 变更命令对象
|
|
146
|
-
*/
|
|
147
|
-
push: (value) => new DbMutateCommand("push", value),
|
|
148
|
-
/**
|
|
149
|
-
* 向数组开头添加元素操作符
|
|
150
|
-
* @param value 添加的值
|
|
151
|
-
* @returns DbMutateCommand 变更命令对象
|
|
152
|
-
*/
|
|
153
|
-
unshift: (value) => new DbMutateCommand("unshift", value),
|
|
154
|
-
/**
|
|
155
|
-
* 从数组末尾移除元素操作符
|
|
156
|
-
* @returns DbMutateCommand 变更命令对象
|
|
157
|
-
*/
|
|
158
|
-
pop: () => new DbMutateCommand("pop", void 0),
|
|
159
|
-
/**
|
|
160
|
-
* 从数组开头移除元素操作符
|
|
161
|
-
* @returns DbMutateCommand 变更命令对象
|
|
162
|
-
*/
|
|
163
|
-
shift: () => new DbMutateCommand("shift", void 0),
|
|
164
|
-
/**
|
|
165
|
-
* 移除字段操作符
|
|
166
|
-
* @returns DbMutateCommand 变更命令对象
|
|
167
|
-
*/
|
|
168
|
-
remove: () => new DbMutateCommand("remove", void 0)
|
|
33
|
+
var DbMutateCommand = class extends DbBaseCommand {
|
|
34
|
+
_isMutate = true;
|
|
169
35
|
};
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
});
|
|
353
|
-
if (type2 === "1:1") {
|
|
354
|
-
returnAggRef = returnAggRef.unwind({
|
|
355
|
-
path: `$${as}`,
|
|
356
|
-
preserveNullAndEmptyArrays: true
|
|
357
|
-
});
|
|
358
|
-
}
|
|
359
|
-
if (unselect) {
|
|
360
|
-
hasAggUnselect++;
|
|
361
|
-
aggUnselect[as] = false;
|
|
362
|
-
} else {
|
|
363
|
-
aggSelect[as] = true;
|
|
364
|
-
}
|
|
365
|
-
this._lookupAs[as] = true;
|
|
366
|
-
}
|
|
367
|
-
if (this._hasWhere) returnAggRef = returnAggRef.match(_mapCommandRaw(this._where));
|
|
368
|
-
if (this._hasOrder) returnAggRef = returnAggRef.sort(object.objectMap(this._order, (v) => v === "asc" ? 1 : -1));
|
|
369
|
-
if (this._hasSkip) returnAggRef = returnAggRef.skip(this._skip);
|
|
370
|
-
if (this._hasLimit) returnAggRef = returnAggRef.limit(this._limit);
|
|
371
|
-
if (this._hasSelect) {
|
|
372
|
-
returnAggRef = returnAggRef.project(_mergeSelect({ ...this._select, ...aggSelect }, this._order));
|
|
373
|
-
} else if (hasAggUnselect) {
|
|
374
|
-
returnAggRef = returnAggRef.project(aggUnselect);
|
|
375
|
-
}
|
|
376
|
-
return returnAggRef;
|
|
377
|
-
}
|
|
378
|
-
_endHost(action) {
|
|
379
|
-
if (this._hasWhere) {
|
|
380
|
-
if ((action === "update" || action === "remove") && this._isTransaction) {
|
|
381
|
-
this._host = this._host.doc(this._where._id);
|
|
382
|
-
} else {
|
|
383
|
-
this._host = this._host.where(_mapCommandRaw(this._where));
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
if (this._hasSelect) {
|
|
387
|
-
this._host = this._host.field(_mergeSelect(this._select, this._order));
|
|
388
|
-
}
|
|
389
|
-
if (this._hasOrder) {
|
|
390
|
-
object.objectEach(this._order, (val, key) => {
|
|
391
|
-
this._host = this._host.orderBy(key, val);
|
|
392
|
-
});
|
|
393
|
-
}
|
|
394
|
-
if (this._hasSkip) this._host = this._host.skip(this._skip);
|
|
395
|
-
if (this._hasLimit && action === "query") this._host = this._host.limit(this._limit);
|
|
396
|
-
else if (this._hasWhereId && action === "query") this._host = this._host.limit(1);
|
|
397
|
-
}
|
|
398
|
-
/**
|
|
399
|
-
* 执行查询操作
|
|
400
|
-
* @returns 查询结果
|
|
401
|
-
*/
|
|
402
|
-
async many() {
|
|
403
|
-
try {
|
|
404
|
-
if (this._isTransaction) throw new Error("db.many() 方法不支持事务模式");
|
|
405
|
-
let res;
|
|
406
|
-
if (this._hasLookup) {
|
|
407
|
-
const aggRef = this.aggregate();
|
|
408
|
-
this._endAggregate(aggRef);
|
|
409
|
-
res = await aggRef.end();
|
|
410
|
-
} else {
|
|
411
|
-
this._endHost("query");
|
|
412
|
-
res = await this._host.get();
|
|
413
|
-
}
|
|
414
|
-
const { data } = _helpers.parseDatabaseOutput(res);
|
|
415
|
-
return data;
|
|
416
|
-
} catch (err) {
|
|
417
|
-
const dbErr = err;
|
|
418
|
-
throw this._options.parseError?.(dbErr) || dbErr;
|
|
419
|
-
}
|
|
420
|
-
}
|
|
421
|
-
/**
|
|
422
|
-
* 只查询一条,自动添加 limit(1) 条件
|
|
423
|
-
* 如果没有匹配到记录,会抛出错误
|
|
424
|
-
* @returns 查询结果
|
|
425
|
-
*/
|
|
426
|
-
async firstOrThrow() {
|
|
427
|
-
if (this._isTransaction) throw new Error("db.firstOrThrow() 方法不支持事务模式");
|
|
428
|
-
if (this._hasLimit) throw new Error("db.firstOrThrow() 方法不支持 limit 条件");
|
|
429
|
-
if (!this._hasWhereId) this.limit(1);
|
|
430
|
-
const data = await this.many();
|
|
431
|
-
const res = data.at(0);
|
|
432
|
-
if (!res) throw error.createCloudObjectError("查询数据为空", "firstOrThrow");
|
|
433
|
-
return res;
|
|
434
|
-
}
|
|
435
|
-
/**
|
|
436
|
-
* 只查询一条,自动添加 limit(1) 条件
|
|
437
|
-
* 如果没有匹配到记录,返回 null
|
|
438
|
-
* @returns 查询结果或 null
|
|
439
|
-
*/
|
|
440
|
-
async firstOrNull() {
|
|
441
|
-
if (this._isTransaction) throw new Error("db.firstOrNull() 方法不支持事务模式");
|
|
442
|
-
if (this._hasLimit) throw new Error("db.firstOrNull() 方法不支持 limit 条件");
|
|
443
|
-
if (!this._hasWhereId) this.limit(1);
|
|
444
|
-
const data = await this.many();
|
|
445
|
-
return data.at(0) || null;
|
|
446
|
-
}
|
|
447
|
-
/**
|
|
448
|
-
* 获取匹配记录的数量
|
|
449
|
-
* @returns 记录总数
|
|
450
|
-
*/
|
|
451
|
-
async count() {
|
|
452
|
-
if (this._isTransaction) throw new Error("db.count() 方法不支持事务模式");
|
|
453
|
-
if (this._hasLookup) throw new Error("db.count() 方法不支持 lookup 聚合");
|
|
454
|
-
if (this._hasSelect) throw new Error("db.count() 方法不支持 select 条件");
|
|
455
|
-
if (this._hasOrder) throw new Error("db.count() 方法不支持 order 条件");
|
|
456
|
-
if (this._hasSkip) throw new Error("db.count() 方法不支持 skip 条件");
|
|
457
|
-
if (this._hasLimit) throw new Error("db.count() 方法不支持 limit 条件");
|
|
458
|
-
try {
|
|
459
|
-
this._endHost("count");
|
|
460
|
-
const res = await this._host.count();
|
|
461
|
-
const { total } = _helpers.parseDatabaseOutput(res);
|
|
462
|
-
return total;
|
|
463
|
-
} catch (err) {
|
|
464
|
-
const dbErr = err;
|
|
465
|
-
throw this._options.parseError?.(dbErr) || dbErr;
|
|
466
|
-
}
|
|
467
|
-
}
|
|
468
|
-
/**
|
|
469
|
-
* 创建新记录
|
|
470
|
-
* @param data 要创建的数据
|
|
471
|
-
* @returns 创建结果
|
|
472
|
-
*/
|
|
473
|
-
async create(data) {
|
|
474
|
-
if (this._hasLookup) throw new Error("db.create() 方法不支持 lookup 聚合");
|
|
475
|
-
if (this._hasWhere) throw new Error("db.create() 方法不支持 where 条件");
|
|
476
|
-
if (this._hasSelect) throw new Error("db.create() 方法不支持 select 条件");
|
|
477
|
-
if (this._hasOrder) throw new Error("db.create() 方法不支持 order 条件");
|
|
478
|
-
if (this._hasSkip) throw new Error("db.create() 方法不支持 skip 条件");
|
|
479
|
-
if (this._hasLimit) throw new Error("db.create() 方法不支持 limit 条件");
|
|
480
|
-
try {
|
|
481
|
-
this._endHost("create");
|
|
482
|
-
const res = await this._host.add(data);
|
|
483
|
-
const { id } = _helpers.parseDatabaseOutput(res);
|
|
484
|
-
return id;
|
|
485
|
-
} catch (err) {
|
|
486
|
-
const dbErr = err;
|
|
487
|
-
throw this._options.parseError?.(dbErr) || dbErr;
|
|
488
|
-
}
|
|
489
|
-
}
|
|
490
|
-
/**
|
|
491
|
-
* 更新记录
|
|
492
|
-
* @param data 要更新的数据
|
|
493
|
-
* @returns 更新结果
|
|
494
|
-
*/
|
|
495
|
-
async update(data) {
|
|
496
|
-
if (this._hasLookup) throw new Error("db.update() 方法不支持 lookup 聚合");
|
|
497
|
-
if (!this._hasWhere) throw new Error("设置 where 条件后才能执行 db.update() 方法");
|
|
498
|
-
if (this._hasSelect) throw new Error("db.update() 方法不支持 select 条件");
|
|
499
|
-
if (this._hasOrder) throw new Error("db.update() 方法不支持 order 条件");
|
|
500
|
-
if (this._hasSkip) throw new Error("db.update() 方法不支持 skip 条件");
|
|
501
|
-
if (this._hasLimit) throw new Error("db.update() 方法不支持 limit 条件");
|
|
502
|
-
if (this._isTransaction && !this._hasWhereId) throw new Error("事务模式下 db.update() 的 where 条件必须是 _id");
|
|
503
|
-
try {
|
|
504
|
-
this._endHost("update");
|
|
505
|
-
const res = await this._host.update(object.objectOmit(_mapCommandRaw(data), ["_id"]));
|
|
506
|
-
const { updated } = _helpers.parseDatabaseOutput(res);
|
|
507
|
-
return updated;
|
|
508
|
-
} catch (err) {
|
|
509
|
-
const dbErr = err;
|
|
510
|
-
throw this._options.parseError?.(dbErr) || dbErr;
|
|
511
|
-
}
|
|
512
|
-
}
|
|
513
|
-
/**
|
|
514
|
-
* 删除记录
|
|
515
|
-
* @returns 删除结果
|
|
516
|
-
*/
|
|
517
|
-
async remove() {
|
|
518
|
-
if (this._hasLookup) throw new Error("db.remove() 方法不支持 lookup 聚合");
|
|
519
|
-
if (!this._hasWhere) throw new Error("设置 where 条件后才能执行 db.remove() 方法");
|
|
520
|
-
if (this._hasSelect) throw new Error("db.remove() 方法不支持 select 条件");
|
|
521
|
-
if (this._hasOrder) throw new Error("db.remove() 方法不支持 order 条件");
|
|
522
|
-
if (this._hasSkip) throw new Error("db.remove() 方法不支持 skip 条件");
|
|
523
|
-
if (this._hasLimit) throw new Error("db.remove() 方法不支持 limit 条件");
|
|
524
|
-
if (this._isTransaction && !this._hasWhereId) throw new Error("事务模式下 db.remove() 的 where 条件必须是 _id");
|
|
525
|
-
try {
|
|
526
|
-
this._endHost("remove");
|
|
527
|
-
const res = await this._host.remove();
|
|
528
|
-
const { deleted } = _helpers.parseDatabaseOutput(res);
|
|
529
|
-
return deleted;
|
|
530
|
-
} catch (err) {
|
|
531
|
-
const dbErr = err;
|
|
532
|
-
throw this._options.parseError?.(dbErr) || dbErr;
|
|
533
|
-
}
|
|
534
|
-
}
|
|
36
|
+
//#endregion
|
|
37
|
+
//#region src/database/command.ts
|
|
38
|
+
/**
|
|
39
|
+
* 数据库查询命令对象,提供各种查询操作符
|
|
40
|
+
*/
|
|
41
|
+
var dbQuery = {
|
|
42
|
+
/**
|
|
43
|
+
* 等于操作符
|
|
44
|
+
* @param value 比较值
|
|
45
|
+
* @returns DbQueryCommand 查询命令对象
|
|
46
|
+
*/
|
|
47
|
+
eq: (value) => new DbQueryCommand("eq", value),
|
|
48
|
+
/**
|
|
49
|
+
* 不等于操作符
|
|
50
|
+
* @param value 比较值
|
|
51
|
+
* @returns DbQueryCommand 查询命令对象
|
|
52
|
+
*/
|
|
53
|
+
neq: (value) => new DbQueryCommand("neq", value),
|
|
54
|
+
/**
|
|
55
|
+
* 大于操作符
|
|
56
|
+
* @param value 比较值
|
|
57
|
+
* @returns DbQueryCommand 查询命令对象
|
|
58
|
+
*/
|
|
59
|
+
gt: (value) => new DbQueryCommand("gt", value),
|
|
60
|
+
/**
|
|
61
|
+
* 大于等于操作符
|
|
62
|
+
* @param value 比较值
|
|
63
|
+
* @returns DbQueryCommand 查询命令对象
|
|
64
|
+
*/
|
|
65
|
+
gte: (value) => new DbQueryCommand("gte", value),
|
|
66
|
+
/**
|
|
67
|
+
* 小于操作符
|
|
68
|
+
* @param value 比较值
|
|
69
|
+
* @returns DbQueryCommand 查询命令对象
|
|
70
|
+
*/
|
|
71
|
+
lt: (value) => new DbQueryCommand("lt", value),
|
|
72
|
+
/**
|
|
73
|
+
* 小于等于操作符
|
|
74
|
+
* @param value 比较值
|
|
75
|
+
* @returns DbQueryCommand 查询命令对象
|
|
76
|
+
*/
|
|
77
|
+
lte: (value) => new DbQueryCommand("lte", value),
|
|
78
|
+
/**
|
|
79
|
+
* 包含在数组中操作符
|
|
80
|
+
* @param value 值数组
|
|
81
|
+
* @returns DbQueryCommand 查询命令对象
|
|
82
|
+
*/
|
|
83
|
+
in: (value) => new DbQueryCommand("in", value),
|
|
84
|
+
/**
|
|
85
|
+
* 不包含在数组中操作符
|
|
86
|
+
* @param value 值数组
|
|
87
|
+
* @returns DbQueryCommand 查询命令对象
|
|
88
|
+
*/
|
|
89
|
+
nin: (value) => new DbQueryCommand("nin", value),
|
|
90
|
+
/**
|
|
91
|
+
* 数组长度匹配操作符
|
|
92
|
+
* @param size 数组长度
|
|
93
|
+
* @returns DbQueryCommand 查询命令对象
|
|
94
|
+
*/
|
|
95
|
+
size: (size) => new DbQueryCommand("size", size),
|
|
96
|
+
/**
|
|
97
|
+
* 正则表达式匹配操作符
|
|
98
|
+
* @param regExp 正则表达式
|
|
99
|
+
* @returns DbQueryCommand 查询命令对象
|
|
100
|
+
*/
|
|
101
|
+
regExp: (regExp) => new DbQueryCommand("regExp", regExp, { rewriteValue: (_db, parameter) => parameter }),
|
|
102
|
+
/**
|
|
103
|
+
* 逻辑与操作符
|
|
104
|
+
* @param conditions 查询条件参数
|
|
105
|
+
* @returns DbQueryCommand 查询命令对象
|
|
106
|
+
*/
|
|
107
|
+
and: (conditions) => new DbQueryCommand("and", conditions, { formatParameter: (db) => conditions.map((c) => DbBaseCommand.getValue(c, db)) }),
|
|
108
|
+
/**
|
|
109
|
+
* 逻辑或操作符
|
|
110
|
+
* @param conditions 查询条件参数
|
|
111
|
+
* @returns DbQueryCommand 查询命令对象
|
|
112
|
+
*/
|
|
113
|
+
or: (conditions) => new DbQueryCommand("or", conditions, { formatParameter: (db) => conditions.map((c) => DbBaseCommand.getValue(c, db)) })
|
|
114
|
+
};
|
|
115
|
+
/**
|
|
116
|
+
* 数据库变更命令对象,提供各种数据更新操作符
|
|
117
|
+
*/
|
|
118
|
+
var dbMutate = {
|
|
119
|
+
/**
|
|
120
|
+
* 数值增加操作符
|
|
121
|
+
* @param value 增加的数值
|
|
122
|
+
* @returns DbMutateCommand 变更命令对象
|
|
123
|
+
*/
|
|
124
|
+
inc: (value) => new DbMutateCommand("inc", value),
|
|
125
|
+
/**
|
|
126
|
+
* 数值乘法操作符
|
|
127
|
+
* @param value 乘数
|
|
128
|
+
* @returns DbMutateCommand 变更命令对象
|
|
129
|
+
*/
|
|
130
|
+
mul: (value) => new DbMutateCommand("mul", value),
|
|
131
|
+
/**
|
|
132
|
+
* 设置字段值操作符
|
|
133
|
+
* @param value 设置的值
|
|
134
|
+
* @returns DbMutateCommand 变更命令对象
|
|
135
|
+
*/
|
|
136
|
+
set: (value) => new DbMutateCommand("set", value),
|
|
137
|
+
/**
|
|
138
|
+
* 向数组末尾添加元素操作符
|
|
139
|
+
* @param value 添加的值
|
|
140
|
+
* @returns DbMutateCommand 变更命令对象
|
|
141
|
+
*/
|
|
142
|
+
push: (value) => new DbMutateCommand("push", value),
|
|
143
|
+
/**
|
|
144
|
+
* 向数组开头添加元素操作符
|
|
145
|
+
* @param value 添加的值
|
|
146
|
+
* @returns DbMutateCommand 变更命令对象
|
|
147
|
+
*/
|
|
148
|
+
unshift: (value) => new DbMutateCommand("unshift", value),
|
|
149
|
+
/**
|
|
150
|
+
* 从数组末尾移除元素操作符
|
|
151
|
+
* @returns DbMutateCommand 变更命令对象
|
|
152
|
+
*/
|
|
153
|
+
pop: () => new DbMutateCommand("pop", void 0),
|
|
154
|
+
/**
|
|
155
|
+
* 从数组开头移除元素操作符
|
|
156
|
+
* @returns DbMutateCommand 变更命令对象
|
|
157
|
+
*/
|
|
158
|
+
shift: () => new DbMutateCommand("shift", void 0),
|
|
159
|
+
/**
|
|
160
|
+
* 移除字段操作符
|
|
161
|
+
* @returns DbMutateCommand 变更命令对象
|
|
162
|
+
*/
|
|
163
|
+
remove: () => new DbMutateCommand("remove", void 0)
|
|
164
|
+
};
|
|
165
|
+
//#endregion
|
|
166
|
+
//#region src/database/each.ts
|
|
167
|
+
/**
|
|
168
|
+
* 遍历表中的每一行数据并执行回调函数
|
|
169
|
+
*
|
|
170
|
+
* 采用分批查询策略,每批查询 100 条记录,通过 skip/limit 实现分页遍历,
|
|
171
|
+
* 避免一次性加载大量数据导致内存溢出。
|
|
172
|
+
*
|
|
173
|
+
* 迭代器按顺序串行执行,即每一行数据的迭代器完成后才会处理下一行。
|
|
174
|
+
*
|
|
175
|
+
* @template T - 数据行类型
|
|
176
|
+
* @param table 数据库表代理对象
|
|
177
|
+
* @param where 查询条件
|
|
178
|
+
* @param iterator 对每一行数据执行的异步迭代器函数
|
|
179
|
+
* @param maxCount 最大遍历数量,默认值为 Number.MAX_SAFE_INTEGER。
|
|
180
|
+
* 注意:由于分批查询机制(每批 100 条),实际遍历的行数可能略大于 maxCount,
|
|
181
|
+
* 例如 maxCount=150 时,会分两批查询(0-99、100-199),实际遍历 200 行。
|
|
182
|
+
* @example
|
|
183
|
+
* ```ts
|
|
184
|
+
* // 遍历所有状态为 active 的用户
|
|
185
|
+
* await dbEach(userTable, { status: 'active' }, async (user) => {
|
|
186
|
+
* await sendEmail(user.email);
|
|
187
|
+
* });
|
|
188
|
+
*
|
|
189
|
+
* // 限制最多遍历 500 条记录
|
|
190
|
+
* await dbEach(orderTable, { status: 'pending' }, async (order) => {
|
|
191
|
+
* await processOrder(order);
|
|
192
|
+
* }, 500);
|
|
193
|
+
* ```
|
|
194
|
+
*/
|
|
195
|
+
async function dbEach(table, where, iterator, maxCount = Number.MAX_SAFE_INTEGER) {
|
|
196
|
+
const count = Math.min(await table.where(where).count(), maxCount);
|
|
197
|
+
const limit = 100;
|
|
198
|
+
for (let skip = 0; skip < count; skip += limit) {
|
|
199
|
+
const rows = await table.where(where).limit(limit).skip(skip).many();
|
|
200
|
+
for (const row of rows) await iterator(row);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
//#endregion
|
|
204
|
+
//#region src/database/paging.ts
|
|
205
|
+
/**
|
|
206
|
+
* 数据库分页查询函数
|
|
207
|
+
* @template T - 数据类型
|
|
208
|
+
* @param queryDb - 数据库查询实例
|
|
209
|
+
* @returns 包含数据列表和总数的对象
|
|
210
|
+
*/
|
|
211
|
+
async function dbPaging(queryDb) {
|
|
212
|
+
const where = queryDb.getWhere(true);
|
|
213
|
+
const countDb = queryDb.clone();
|
|
214
|
+
return {
|
|
215
|
+
list: await queryDb.many(),
|
|
216
|
+
total: await countDb.where(where).count()
|
|
217
|
+
};
|
|
535
218
|
}
|
|
219
|
+
//#endregion
|
|
220
|
+
//#region src/database/_db.class.ts
|
|
221
|
+
/**
|
|
222
|
+
* 数据库聚合操作符命令
|
|
223
|
+
*/
|
|
224
|
+
var dbAgg = uniCloud.database().command.aggregate;
|
|
225
|
+
var db0 = uniCloud.database();
|
|
226
|
+
var gid = 0;
|
|
227
|
+
/**
|
|
228
|
+
* 数据库类
|
|
229
|
+
* @template D1 - 主表数据
|
|
230
|
+
* @template S1 - 主表筛选
|
|
231
|
+
* @template D2 - 副表数据
|
|
232
|
+
* @template W2 - 副表查询
|
|
233
|
+
*/
|
|
234
|
+
var Db = class Db {
|
|
235
|
+
_host;
|
|
236
|
+
/**
|
|
237
|
+
* 是否为事务环境
|
|
238
|
+
* - 查询条件只能是 id
|
|
239
|
+
* - 不能聚合操作
|
|
240
|
+
*/
|
|
241
|
+
_isTransaction = false;
|
|
242
|
+
_options;
|
|
243
|
+
/**
|
|
244
|
+
* 构造函数,初始化数据库集合引用
|
|
245
|
+
* @param collection 数据表名称
|
|
246
|
+
* @param _mockDatabase 模拟数据库,用于单元测试
|
|
247
|
+
*/
|
|
248
|
+
constructor(options) {
|
|
249
|
+
this._options = options;
|
|
250
|
+
this._host = options._mockDatabase || options.transaction?.collection(options.table) || db0.collection(options.table);
|
|
251
|
+
this._isTransaction = !!options.transaction;
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* 创建一个新的数据库实例,可选是否移除事务
|
|
255
|
+
* @param withoutTransaction 是否移除事务,默认 false
|
|
256
|
+
* @returns 新的数据库实例
|
|
257
|
+
*/
|
|
258
|
+
clone(withoutTransaction) {
|
|
259
|
+
return new Db({
|
|
260
|
+
...this._options,
|
|
261
|
+
transaction: withoutTransaction ? null : this._options.transaction
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
get table() {
|
|
265
|
+
return this._options.table;
|
|
266
|
+
}
|
|
267
|
+
get options() {
|
|
268
|
+
return this._options;
|
|
269
|
+
}
|
|
270
|
+
get isTransaction() {
|
|
271
|
+
return this._isTransaction;
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* 获取聚合操作实例
|
|
275
|
+
* @returns 聚合操作实例
|
|
276
|
+
*/
|
|
277
|
+
aggregate() {
|
|
278
|
+
return this._host.aggregate();
|
|
279
|
+
}
|
|
280
|
+
_hasWhere = void 0;
|
|
281
|
+
_hasWhereId = void 0;
|
|
282
|
+
_where = {};
|
|
283
|
+
_doWhere(where, from) {
|
|
284
|
+
if (this._hasWhere) throw new Error(`已调用过一次 db.${_toWhereMethod(this._hasWhere)} 了`);
|
|
285
|
+
const realWhere = (0, _cloudcome_utils_core_object.objectFilter)(where, (value) => value !== void 0);
|
|
286
|
+
const isWhereId = Object.keys(realWhere).length === 1 && "_id" in realWhere && ((0, _cloudcome_utils_core_type.isString)(realWhere._id) || (0, _cloudcome_utils_core_type.isNumber)(realWhere._id));
|
|
287
|
+
if (isWhereId && this._hasLimit) throw new Error(`db.${_toWhereIdMethod(from)} 方法不能与 db.limit() 方法同时调用`);
|
|
288
|
+
this._hasWhere = from;
|
|
289
|
+
this._where = realWhere;
|
|
290
|
+
if (isWhereId) this._hasWhereId = from;
|
|
291
|
+
return this;
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* 设置查询条件
|
|
295
|
+
* @param where 查询条件对象
|
|
296
|
+
* @returns 当前Db实例,支持链式调用
|
|
297
|
+
*/
|
|
298
|
+
where(where) {
|
|
299
|
+
return this._doWhere(where, "where");
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* 获取当前查询条件
|
|
303
|
+
* @param plain 是否返回原始查询条件对象,默认 false
|
|
304
|
+
* @returns 当前查询条件对象
|
|
305
|
+
*/
|
|
306
|
+
getWhere(plain) {
|
|
307
|
+
return plain ? (0, _cloudcome_utils_core_object.objectOmit)(this._where, Object.keys(this._lookupAs)) : this._where;
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* 根据ID设置查询条件
|
|
311
|
+
* @param id 记录ID
|
|
312
|
+
* @returns 当前Db实例,支持链式调用
|
|
313
|
+
*/
|
|
314
|
+
whereId(id) {
|
|
315
|
+
return this._doWhere({ _id: id }, "whereId");
|
|
316
|
+
}
|
|
317
|
+
_hasSelect = 0;
|
|
318
|
+
_select = {};
|
|
319
|
+
/**
|
|
320
|
+
* 指定要返回的字段
|
|
321
|
+
* @param fields 要返回的字段对象,true表示返回,false表示不返回
|
|
322
|
+
* @returns 当前Db实例,支持链式调用
|
|
323
|
+
*/
|
|
324
|
+
select(fields) {
|
|
325
|
+
if (this._hasSelect) throw new Error("db.select() 方法只能调用一次");
|
|
326
|
+
this._hasSelect++;
|
|
327
|
+
this._select = fields;
|
|
328
|
+
return this;
|
|
329
|
+
}
|
|
330
|
+
_hasOrder = 0;
|
|
331
|
+
_order = {};
|
|
332
|
+
/**
|
|
333
|
+
* 设置排序规则
|
|
334
|
+
* @param order 排序规则对象,key为字段名,value为"asc"或"desc"
|
|
335
|
+
* @returns 当前Db实例,支持链式调用
|
|
336
|
+
*/
|
|
337
|
+
order(order) {
|
|
338
|
+
this._hasOrder++;
|
|
339
|
+
this._order = order;
|
|
340
|
+
return this;
|
|
341
|
+
}
|
|
342
|
+
_hasSkip = 0;
|
|
343
|
+
_skip = 0;
|
|
344
|
+
/**
|
|
345
|
+
* 跳过指定数量的记录
|
|
346
|
+
* @param skip 要跳过的记录数
|
|
347
|
+
* @returns 当前Db实例,支持链式调用
|
|
348
|
+
*/
|
|
349
|
+
skip(skip) {
|
|
350
|
+
if (this._hasSkip) throw new Error("db.skip() 方法只能调用一次");
|
|
351
|
+
this._hasSkip++;
|
|
352
|
+
this._skip = skip;
|
|
353
|
+
return this;
|
|
354
|
+
}
|
|
355
|
+
_hasLimit = 0;
|
|
356
|
+
_limit = 0;
|
|
357
|
+
/**
|
|
358
|
+
* 限制返回的记录数量
|
|
359
|
+
* @param limit 最大返回记录数
|
|
360
|
+
* @returns 当前Db实例,支持链式调用
|
|
361
|
+
*/
|
|
362
|
+
limit(limit) {
|
|
363
|
+
if (this._hasLimit) throw new Error("db.limit() 方法只能调用一次");
|
|
364
|
+
if (this._hasWhereId) throw new Error(`db.limit() 方法不能与 ${_toWhereIdMethod(this._hasWhereId)} 方法同时调用`);
|
|
365
|
+
this._hasLimit++;
|
|
366
|
+
this._limit = limit;
|
|
367
|
+
return this;
|
|
368
|
+
}
|
|
369
|
+
_hasLookup = 0;
|
|
370
|
+
get hasLookup() {
|
|
371
|
+
return this._hasLookup > 0;
|
|
372
|
+
}
|
|
373
|
+
_lookups = [];
|
|
374
|
+
lookup(table, lookup) {
|
|
375
|
+
table._hasLookup++;
|
|
376
|
+
this._hasLookup++;
|
|
377
|
+
this._lookups.push({
|
|
378
|
+
...lookup,
|
|
379
|
+
table
|
|
380
|
+
});
|
|
381
|
+
return this;
|
|
382
|
+
}
|
|
383
|
+
_aggregated = false;
|
|
384
|
+
_lookupAs = {};
|
|
385
|
+
_endAggregate(aggRef) {
|
|
386
|
+
if (this._aggregated) throw new Error(`相同的数据表实例(${this.table})不能重复使用`);
|
|
387
|
+
this._aggregated = true;
|
|
388
|
+
let returnAggRef = aggRef;
|
|
389
|
+
let _hasAggSelect = 0;
|
|
390
|
+
const aggSelect = {};
|
|
391
|
+
let hasAggUnselect = 0;
|
|
392
|
+
const aggUnselect = {};
|
|
393
|
+
for (const { relation: type, as, foreignField, localField, table, unselect } of this._lookups) {
|
|
394
|
+
const letName = `let${gid++}`;
|
|
395
|
+
let pipeline = dbAgg.pipeline();
|
|
396
|
+
pipeline = pipeline.match({ $expr: { $and: [type === "n:1" ? { $in: [`$${foreignField}`, `$$${letName}`] } : { $eq: [`$${foreignField}`, `$$${letName}`] }] } });
|
|
397
|
+
pipeline = table._endAggregate(pipeline);
|
|
398
|
+
pipeline = pipeline.done();
|
|
399
|
+
returnAggRef = returnAggRef.lookup({
|
|
400
|
+
let: { [letName]: `$${localField}` },
|
|
401
|
+
as,
|
|
402
|
+
from: table.table,
|
|
403
|
+
pipeline
|
|
404
|
+
});
|
|
405
|
+
if (type === "1:1") returnAggRef = returnAggRef.unwind({
|
|
406
|
+
path: `$${as}`,
|
|
407
|
+
preserveNullAndEmptyArrays: true
|
|
408
|
+
});
|
|
409
|
+
if (unselect) {
|
|
410
|
+
hasAggUnselect++;
|
|
411
|
+
aggUnselect[as] = false;
|
|
412
|
+
} else {
|
|
413
|
+
_hasAggSelect++;
|
|
414
|
+
aggSelect[as] = true;
|
|
415
|
+
}
|
|
416
|
+
this._lookupAs[as] = true;
|
|
417
|
+
}
|
|
418
|
+
if (this._hasWhere) returnAggRef = returnAggRef.match(_mapCommandRaw(this._where));
|
|
419
|
+
if (this._hasOrder) returnAggRef = returnAggRef.sort((0, _cloudcome_utils_core_object.objectMap)(this._order, (v) => v === "asc" ? 1 : -1));
|
|
420
|
+
if (this._hasSkip) returnAggRef = returnAggRef.skip(this._skip);
|
|
421
|
+
if (this._hasLimit) returnAggRef = returnAggRef.limit(this._limit);
|
|
422
|
+
if (this._hasSelect) returnAggRef = returnAggRef.project(_mergeSelect({
|
|
423
|
+
...this._select,
|
|
424
|
+
...aggSelect
|
|
425
|
+
}, this._order));
|
|
426
|
+
else if (hasAggUnselect) returnAggRef = returnAggRef.project(aggUnselect);
|
|
427
|
+
return returnAggRef;
|
|
428
|
+
}
|
|
429
|
+
_endHost(action) {
|
|
430
|
+
if (this._hasWhere) if ((action === "update" || action === "remove") && this._isTransaction) this._host = this._host.doc(this._where._id);
|
|
431
|
+
else this._host = this._host.where(_mapCommandRaw(this._where));
|
|
432
|
+
if (this._hasSelect) this._host = this._host.field(_mergeSelect(this._select, this._order));
|
|
433
|
+
if (this._hasOrder) (0, _cloudcome_utils_core_object.objectEach)(this._order, (val, key) => {
|
|
434
|
+
this._host = this._host.orderBy(key, val);
|
|
435
|
+
});
|
|
436
|
+
if (this._hasSkip) this._host = this._host.skip(this._skip);
|
|
437
|
+
if (this._hasLimit && action === "query") this._host = this._host.limit(this._limit);
|
|
438
|
+
else if (this._hasWhereId && action === "query") this._host = this._host.limit(1);
|
|
439
|
+
}
|
|
440
|
+
/**
|
|
441
|
+
* 执行查询操作
|
|
442
|
+
* @returns 查询结果
|
|
443
|
+
*/
|
|
444
|
+
async many() {
|
|
445
|
+
try {
|
|
446
|
+
if (this._isTransaction) throw new Error("db.many() 方法不支持事务模式");
|
|
447
|
+
let res;
|
|
448
|
+
if (this._hasLookup) {
|
|
449
|
+
const aggRef = this.aggregate();
|
|
450
|
+
this._endAggregate(aggRef);
|
|
451
|
+
res = await aggRef.end();
|
|
452
|
+
} else {
|
|
453
|
+
this._endHost("query");
|
|
454
|
+
res = await this._host.get();
|
|
455
|
+
}
|
|
456
|
+
const { data } = require__helpers.parseDatabaseOutput(res);
|
|
457
|
+
return data;
|
|
458
|
+
} catch (err) {
|
|
459
|
+
const dbErr = err;
|
|
460
|
+
throw this._options.parseError?.(dbErr) || dbErr;
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
/**
|
|
464
|
+
* 只查询一条,自动添加 limit(1) 条件
|
|
465
|
+
* 如果没有匹配到记录,会抛出错误
|
|
466
|
+
* @returns 查询结果
|
|
467
|
+
*/
|
|
468
|
+
async firstOrThrow() {
|
|
469
|
+
if (this._isTransaction) throw new Error("db.firstOrThrow() 方法不支持事务模式");
|
|
470
|
+
if (this._hasLimit) throw new Error("db.firstOrThrow() 方法不支持 limit 条件");
|
|
471
|
+
if (!this._hasWhereId) this.limit(1);
|
|
472
|
+
const res = (await this.many()).at(0);
|
|
473
|
+
if (!res) throw require_cloud.createCloudObjectError("查询数据为空", "firstOrThrow");
|
|
474
|
+
return res;
|
|
475
|
+
}
|
|
476
|
+
/**
|
|
477
|
+
* 只查询一条,自动添加 limit(1) 条件
|
|
478
|
+
* 如果没有匹配到记录,返回 null
|
|
479
|
+
* @returns 查询结果或 null
|
|
480
|
+
*/
|
|
481
|
+
async firstOrNull() {
|
|
482
|
+
if (this._isTransaction) throw new Error("db.firstOrNull() 方法不支持事务模式");
|
|
483
|
+
if (this._hasLimit) throw new Error("db.firstOrNull() 方法不支持 limit 条件");
|
|
484
|
+
if (!this._hasWhereId) this.limit(1);
|
|
485
|
+
return (await this.many()).at(0) || null;
|
|
486
|
+
}
|
|
487
|
+
/**
|
|
488
|
+
* 获取匹配记录的数量
|
|
489
|
+
* @returns 记录总数
|
|
490
|
+
*/
|
|
491
|
+
async count() {
|
|
492
|
+
if (this._isTransaction) throw new Error("db.count() 方法不支持事务模式");
|
|
493
|
+
if (this._hasLookup) throw new Error("db.count() 方法不支持 lookup 聚合");
|
|
494
|
+
if (this._hasSelect) throw new Error("db.count() 方法不支持 select 条件");
|
|
495
|
+
if (this._hasOrder) throw new Error("db.count() 方法不支持 order 条件");
|
|
496
|
+
if (this._hasSkip) throw new Error("db.count() 方法不支持 skip 条件");
|
|
497
|
+
if (this._hasLimit) throw new Error("db.count() 方法不支持 limit 条件");
|
|
498
|
+
try {
|
|
499
|
+
this._endHost("count");
|
|
500
|
+
const { total } = require__helpers.parseDatabaseOutput(await this._host.count());
|
|
501
|
+
return total;
|
|
502
|
+
} catch (err) {
|
|
503
|
+
const dbErr = err;
|
|
504
|
+
throw this._options.parseError?.(dbErr) || dbErr;
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
/**
|
|
508
|
+
* 创建新记录
|
|
509
|
+
* @param data 要创建的数据
|
|
510
|
+
* @returns 创建结果
|
|
511
|
+
*/
|
|
512
|
+
async create(data) {
|
|
513
|
+
if (this._hasLookup) throw new Error("db.create() 方法不支持 lookup 聚合");
|
|
514
|
+
if (this._hasWhere) throw new Error("db.create() 方法不支持 where 条件");
|
|
515
|
+
if (this._hasSelect) throw new Error("db.create() 方法不支持 select 条件");
|
|
516
|
+
if (this._hasOrder) throw new Error("db.create() 方法不支持 order 条件");
|
|
517
|
+
if (this._hasSkip) throw new Error("db.create() 方法不支持 skip 条件");
|
|
518
|
+
if (this._hasLimit) throw new Error("db.create() 方法不支持 limit 条件");
|
|
519
|
+
try {
|
|
520
|
+
this._endHost("create");
|
|
521
|
+
const { id } = require__helpers.parseDatabaseOutput(await this._host.add(data));
|
|
522
|
+
return id;
|
|
523
|
+
} catch (err) {
|
|
524
|
+
const dbErr = err;
|
|
525
|
+
throw this._options.parseError?.(dbErr) || dbErr;
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
/**
|
|
529
|
+
* 更新记录
|
|
530
|
+
* @param data 要更新的数据
|
|
531
|
+
* @returns 更新结果
|
|
532
|
+
*/
|
|
533
|
+
async update(data) {
|
|
534
|
+
if (this._hasLookup) throw new Error("db.update() 方法不支持 lookup 聚合");
|
|
535
|
+
if (!this._hasWhere) throw new Error("设置 where 条件后才能执行 db.update() 方法");
|
|
536
|
+
if (this._hasSelect) throw new Error("db.update() 方法不支持 select 条件");
|
|
537
|
+
if (this._hasOrder) throw new Error("db.update() 方法不支持 order 条件");
|
|
538
|
+
if (this._hasSkip) throw new Error("db.update() 方法不支持 skip 条件");
|
|
539
|
+
if (this._hasLimit) throw new Error("db.update() 方法不支持 limit 条件");
|
|
540
|
+
if (this._isTransaction && !this._hasWhereId) throw new Error("事务模式下 db.update() 的 where 条件必须是 _id");
|
|
541
|
+
try {
|
|
542
|
+
this._endHost("update");
|
|
543
|
+
const { updated } = require__helpers.parseDatabaseOutput(await this._host.update((0, _cloudcome_utils_core_object.objectOmit)(_mapCommandRaw(data), ["_id"])));
|
|
544
|
+
return updated;
|
|
545
|
+
} catch (err) {
|
|
546
|
+
const dbErr = err;
|
|
547
|
+
throw this._options.parseError?.(dbErr) || dbErr;
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
/**
|
|
551
|
+
* 删除记录
|
|
552
|
+
* @returns 删除结果
|
|
553
|
+
*/
|
|
554
|
+
async remove() {
|
|
555
|
+
if (this._hasLookup) throw new Error("db.remove() 方法不支持 lookup 聚合");
|
|
556
|
+
if (!this._hasWhere) throw new Error("设置 where 条件后才能执行 db.remove() 方法");
|
|
557
|
+
if (this._hasSelect) throw new Error("db.remove() 方法不支持 select 条件");
|
|
558
|
+
if (this._hasOrder) throw new Error("db.remove() 方法不支持 order 条件");
|
|
559
|
+
if (this._hasSkip) throw new Error("db.remove() 方法不支持 skip 条件");
|
|
560
|
+
if (this._hasLimit) throw new Error("db.remove() 方法不支持 limit 条件");
|
|
561
|
+
if (this._isTransaction && !this._hasWhereId) throw new Error("事务模式下 db.remove() 的 where 条件必须是 _id");
|
|
562
|
+
try {
|
|
563
|
+
this._endHost("remove");
|
|
564
|
+
const { deleted } = require__helpers.parseDatabaseOutput(await this._host.remove());
|
|
565
|
+
return deleted;
|
|
566
|
+
} catch (err) {
|
|
567
|
+
const dbErr = err;
|
|
568
|
+
throw this._options.parseError?.(dbErr) || dbErr;
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
};
|
|
536
572
|
function _toWhereMethod(whereFrom) {
|
|
537
|
-
|
|
573
|
+
return whereFrom === "where" ? "where({...})" : "whereId(id)";
|
|
538
574
|
}
|
|
539
575
|
function _toWhereIdMethod(whereFrom) {
|
|
540
|
-
|
|
576
|
+
return whereFrom === "where" ? "where({ _id })" : "whereId(id)";
|
|
541
577
|
}
|
|
542
578
|
function _mapCommandRaw(data) {
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
579
|
+
const map = (val) => {
|
|
580
|
+
if (!(0, _cloudcome_utils_core_type.isObject)(val)) return val;
|
|
581
|
+
if (val instanceof DbBaseCommand) return DbBaseCommand.getValue(val, db0);
|
|
582
|
+
return (0, _cloudcome_utils_core_object.objectMap)(val, map);
|
|
583
|
+
};
|
|
584
|
+
return (0, _cloudcome_utils_core_object.objectMap)(data, map);
|
|
549
585
|
}
|
|
550
586
|
function _mapOrderSelect(order) {
|
|
551
|
-
|
|
587
|
+
return (0, _cloudcome_utils_core_object.objectMap)(order, (_val, _key) => true);
|
|
552
588
|
}
|
|
553
589
|
function _mergeSelect(select, order) {
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
..._mapOrderSelect(order)
|
|
561
|
-
};
|
|
590
|
+
if (Object.keys(select).length === 0) return select;
|
|
591
|
+
if (Object.keys(select).length === 1 && "_id" in select && select._id === false) return select;
|
|
592
|
+
return {
|
|
593
|
+
...select,
|
|
594
|
+
..._mapOrderSelect(order)
|
|
595
|
+
};
|
|
562
596
|
}
|
|
597
|
+
//#endregion
|
|
598
|
+
//#region src/database/proxy.ts
|
|
599
|
+
/**
|
|
600
|
+
* 创建一个数据库代理对象,用于延迟实例化数据库操作类
|
|
601
|
+
* @template D1 - 主表数据
|
|
602
|
+
* @template S1 - 主表筛选
|
|
603
|
+
* @param name - 数据库表名
|
|
604
|
+
* @returns 返回一个代理对象,该对象会将属性访问转发到实际的数据库操作实例
|
|
605
|
+
*/
|
|
563
606
|
function dbProxy(name, options) {
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
607
|
+
return new Proxy({}, { get(_target, prop) {
|
|
608
|
+
if (prop === "_isProxy") return true;
|
|
609
|
+
const table = new Db({
|
|
610
|
+
table: name,
|
|
611
|
+
...options
|
|
612
|
+
});
|
|
613
|
+
const ref = table[prop];
|
|
614
|
+
return (0, _cloudcome_utils_core_type.isFunction)(ref) ? ref.bind(table) : ref;
|
|
615
|
+
} });
|
|
616
|
+
}
|
|
617
|
+
//#endregion
|
|
618
|
+
//#region src/database/transaction.ts
|
|
619
|
+
/**
|
|
620
|
+
* 在数据库事务中执行操作
|
|
621
|
+
*
|
|
622
|
+
* @template K - 事务操作返回值类型
|
|
623
|
+
* @param transacting - 事务执行函数,接收事务数据库实例作为参数
|
|
624
|
+
* @param _mockDatabase - 用于测试的模拟数据库对象
|
|
625
|
+
* @param _mockDbInstance - 用于测试的模拟数据库实例
|
|
626
|
+
* @returns 事务操作的返回结果
|
|
627
|
+
*
|
|
628
|
+
* @example
|
|
629
|
+
* ```typescript
|
|
630
|
+
* const result = await dbTransaction(async (withTransaction) => {
|
|
631
|
+
* const userId = await withTransaction(db.table('user')).create({ name: 'John' });
|
|
632
|
+
* const order = await withTransaction(db.table('orders')).create({ userId, amount: 100 });
|
|
633
|
+
* return { user, order };
|
|
634
|
+
* });
|
|
635
|
+
* ```
|
|
636
|
+
*/
|
|
637
|
+
async function dbTransaction(transacting, _mockDatabase, _mockDbInstance) {
|
|
638
|
+
const [err1, transaction] = await (0, _cloudcome_utils_core_try.tryFlatten)((_mockDatabase || uniCloud.database()).startTransaction());
|
|
639
|
+
if (err1) throw err1;
|
|
640
|
+
const withTransaction = (db) => {
|
|
641
|
+
return _mockDbInstance || new Db({
|
|
642
|
+
...db.options,
|
|
643
|
+
transaction
|
|
644
|
+
});
|
|
645
|
+
};
|
|
646
|
+
const [err2, result] = await (0, _cloudcome_utils_core_try.tryFlatten)(async () => {
|
|
647
|
+
const result = await transacting(withTransaction);
|
|
648
|
+
await transaction.commit();
|
|
649
|
+
return result;
|
|
650
|
+
});
|
|
651
|
+
if (err2) {
|
|
652
|
+
await (0, _cloudcome_utils_core_try.tryFlatten)(transaction.rollback());
|
|
653
|
+
throw err2;
|
|
654
|
+
}
|
|
655
|
+
return result;
|
|
576
656
|
}
|
|
657
|
+
//#endregion
|
|
658
|
+
//#region src/database/upsert.ts
|
|
577
659
|
async function dbUpsert(db, options) {
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
660
|
+
const { create, update, onBeforeCreate, onAfterCreate, onBeforeUpdate, onAfterUpdate, _mockDbInstance } = options;
|
|
661
|
+
const _mutateDb = _mockDbInstance || db.clone();
|
|
662
|
+
const exist = await (_mockDbInstance || db.clone(true)).where(db.getWhere(true)).firstOrNull();
|
|
663
|
+
if (exist) {
|
|
664
|
+
if (await onBeforeUpdate?.(exist) === false) return {
|
|
665
|
+
id: exist._id,
|
|
666
|
+
updated: false,
|
|
667
|
+
created: false
|
|
668
|
+
};
|
|
669
|
+
const updateData = (0, _cloudcome_utils_core_type.isFunction)(update) ? update(exist) : update;
|
|
670
|
+
await _mutateDb.whereId(exist._id).update(updateData);
|
|
671
|
+
onAfterUpdate?.(updateData, exist);
|
|
672
|
+
return {
|
|
673
|
+
id: exist._id,
|
|
674
|
+
updated: true,
|
|
675
|
+
created: false
|
|
676
|
+
};
|
|
677
|
+
}
|
|
678
|
+
await onBeforeCreate?.();
|
|
679
|
+
const createdId = await _mutateDb.create(create);
|
|
680
|
+
await onAfterCreate?.(createdId);
|
|
681
|
+
return {
|
|
682
|
+
id: createdId,
|
|
683
|
+
updated: false,
|
|
684
|
+
created: true
|
|
685
|
+
};
|
|
596
686
|
}
|
|
687
|
+
//#endregion
|
|
688
|
+
//#region src/database/unique.ts
|
|
597
689
|
async function dbUnique(db, options) {
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
const transactionDb = _mockDatabase || uniCloud.database();
|
|
608
|
-
const [err1, transaction] = await _try.tryFlatten(transactionDb.startTransaction());
|
|
609
|
-
if (err1) throw err1;
|
|
610
|
-
const withTransaction = (db) => {
|
|
611
|
-
return _mockDbInstance || new Db({ ...db.options, transaction });
|
|
612
|
-
};
|
|
613
|
-
const [err2, result] = await _try.tryFlatten(async () => {
|
|
614
|
-
const result2 = await transacting(withTransaction);
|
|
615
|
-
await transaction.commit();
|
|
616
|
-
return result2;
|
|
617
|
-
});
|
|
618
|
-
if (err2) {
|
|
619
|
-
await _try.tryFlatten(transaction.rollback());
|
|
620
|
-
throw err2;
|
|
621
|
-
}
|
|
622
|
-
return result;
|
|
623
|
-
}
|
|
624
|
-
async function dbPaging(queryDb) {
|
|
625
|
-
const where = queryDb.getWhere(true);
|
|
626
|
-
const countDb = queryDb.clone();
|
|
627
|
-
const list = await queryDb.many();
|
|
628
|
-
const total = await countDb.where(where).count();
|
|
629
|
-
return {
|
|
630
|
-
list,
|
|
631
|
-
total
|
|
632
|
-
};
|
|
690
|
+
const { id, created } = await dbUpsert(db, {
|
|
691
|
+
...options,
|
|
692
|
+
update: {},
|
|
693
|
+
onBeforeUpdate: () => false
|
|
694
|
+
});
|
|
695
|
+
return {
|
|
696
|
+
id,
|
|
697
|
+
created
|
|
698
|
+
};
|
|
633
699
|
}
|
|
634
|
-
|
|
700
|
+
//#endregion
|
|
701
|
+
exports.dbEach = dbEach;
|
|
635
702
|
exports.dbMutate = dbMutate;
|
|
636
703
|
exports.dbPaging = dbPaging;
|
|
637
704
|
exports.dbProxy = dbProxy;
|
|
@@ -639,4 +706,6 @@ exports.dbQuery = dbQuery;
|
|
|
639
706
|
exports.dbTransaction = dbTransaction;
|
|
640
707
|
exports.dbUnique = dbUnique;
|
|
641
708
|
exports.dbUpsert = dbUpsert;
|
|
642
|
-
|
|
709
|
+
exports.parseDatabaseOutput = require__helpers.parseDatabaseOutput;
|
|
710
|
+
|
|
711
|
+
//# sourceMappingURL=database.cjs.map
|