@cloudcome/utils-uni 1.12.0 → 1.14.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/dist/database.mjs CHANGED
@@ -1,53 +1,192 @@
1
- import { errorAssign } from "@cloudcome/utils-core/error";
2
- import { objectMap, objectEach, objectOmit } from "@cloudcome/utils-core/object";
3
- import { isString, isNumber, isArray, isFunction } from "@cloudcome/utils-core/type";
1
+ import { isString, isNumber, isArray, isObject, isFunction } from "@cloudcome/utils-core/type";
2
+ import { a as parseDatabaseOutput } from "./_helpers.mjs";
3
+ import { objectMap, objectEach } from "@cloudcome/utils-core/object";
4
4
  import { tryFlatten } from "@cloudcome/utils-core/try";
5
+ class DbBaseCommand {
6
+ command;
7
+ parameter;
8
+ constructor(command, parameter) {
9
+ this.command = command;
10
+ this.parameter = parameter;
11
+ }
12
+ getValue(db) {
13
+ return db.command[this.command].call(
14
+ db.command,
15
+ this.parameter
16
+ );
17
+ }
18
+ getExpression(fieldName) {
19
+ return {
20
+ [`$${this.command}`]: [fieldName, this.parameter]
21
+ };
22
+ }
23
+ }
24
+ class DbQueryCommand extends DbBaseCommand {
25
+ isQueryCommand = true;
26
+ }
27
+ class DbMutateCommand extends DbBaseCommand {
28
+ isMutateCommand = true;
29
+ }
30
+ const dbQuery = {
31
+ /**
32
+ * 等于操作符
33
+ * @param value 比较值
34
+ * @returns DbQueryCommand 查询命令对象
35
+ */
36
+ eq: (value) => new DbQueryCommand("eq", value),
37
+ /**
38
+ * 不等于操作符
39
+ * @param value 比较值
40
+ * @returns DbQueryCommand 查询命令对象
41
+ */
42
+ neq: (value) => new DbQueryCommand("neq", value),
43
+ /**
44
+ * 大于操作符
45
+ * @param value 比较值
46
+ * @returns DbQueryCommand 查询命令对象
47
+ */
48
+ gt: (value) => new DbQueryCommand("gt", value),
49
+ /**
50
+ * 大于等于操作符
51
+ * @param value 比较值
52
+ * @returns DbQueryCommand 查询命令对象
53
+ */
54
+ gte: (value) => new DbQueryCommand("gte", value),
55
+ /**
56
+ * 小于操作符
57
+ * @param value 比较值
58
+ * @returns DbQueryCommand 查询命令对象
59
+ */
60
+ lt: (value) => new DbQueryCommand("lt", value),
61
+ /**
62
+ * 小于等于操作符
63
+ * @param value 比较值
64
+ * @returns DbQueryCommand 查询命令对象
65
+ */
66
+ lte: (value) => new DbQueryCommand("lte", value),
67
+ /**
68
+ * 包含在数组中操作符
69
+ * @param value 值数组
70
+ * @returns DbQueryCommand 查询命令对象
71
+ */
72
+ in: (value) => new DbQueryCommand("in", value),
73
+ /**
74
+ * 不包含在数组中操作符
75
+ * @param value 值数组
76
+ * @returns DbQueryCommand 查询命令对象
77
+ */
78
+ nin: (value) => new DbQueryCommand("nin", value),
79
+ /**
80
+ * 逻辑与操作符
81
+ * @param conditions 查询条件参数
82
+ * @returns DbQueryCommand 查询命令对象
83
+ */
84
+ and: (conditions) => new DbQueryCommand("and", conditions),
85
+ /**
86
+ * 逻辑或操作符
87
+ * @param conditions 查询条件参数
88
+ * @returns DbQueryCommand 查询命令对象
89
+ */
90
+ or: (conditions) => new DbQueryCommand("or", conditions),
91
+ /**
92
+ * 数组长度匹配操作符
93
+ * @param size 数组长度
94
+ * @returns DbQueryCommand 查询命令对象
95
+ */
96
+ size: (size) => new DbQueryCommand("size", size)
97
+ };
98
+ const dbMutate = {
99
+ /**
100
+ * 数值增加操作符
101
+ * @param value 增加的数值
102
+ * @returns DbMutateCommand 变更命令对象
103
+ */
104
+ inc: (value) => new DbMutateCommand("inc", value),
105
+ /**
106
+ * 数值乘法操作符
107
+ * @param value 乘数
108
+ * @returns DbMutateCommand 变更命令对象
109
+ */
110
+ mul: (value) => new DbMutateCommand("mul", value),
111
+ /**
112
+ * 设置字段值操作符
113
+ * @param value 设置的值
114
+ * @returns DbMutateCommand 变更命令对象
115
+ */
116
+ set: (value) => new DbMutateCommand("set", value),
117
+ /**
118
+ * 向数组末尾添加元素操作符
119
+ * @param value 添加的值
120
+ * @returns DbMutateCommand 变更命令对象
121
+ */
122
+ push: (value) => new DbMutateCommand("push", value),
123
+ /**
124
+ * 向数组开头添加元素操作符
125
+ * @param value 添加的值
126
+ * @returns DbMutateCommand 变更命令对象
127
+ */
128
+ unshift: (value) => new DbMutateCommand("unshift", value),
129
+ /**
130
+ * 从数组末尾移除元素操作符
131
+ * @returns DbMutateCommand 变更命令对象
132
+ */
133
+ pop: () => new DbMutateCommand("pop", void 0),
134
+ /**
135
+ * 从数组开头移除元素操作符
136
+ * @returns DbMutateCommand 变更命令对象
137
+ */
138
+ shift: () => new DbMutateCommand("shift", void 0),
139
+ /**
140
+ * 移除字段操作符
141
+ * @returns DbMutateCommand 变更命令对象
142
+ */
143
+ remove: () => new DbMutateCommand("remove", void 0)
144
+ };
145
+ const dbAgg = uniCloud.database().command.aggregate;
5
146
  const db0 = uniCloud.database();
6
- const dbCmd = db0.command;
7
- const dbAgg = db0.command.aggregate;
8
147
  let gid = 0;
9
148
  class Db {
10
- #host;
149
+ _host;
11
150
  /**
12
151
  * 是否为事务环境
13
152
  * - 查询条件只能是 id
14
153
  * - 不能聚合操作
15
154
  */
16
- #isTransaction = false;
17
- #options;
155
+ _isTransaction = false;
156
+ _options;
18
157
  /**
19
158
  * 构造函数,初始化数据库集合引用
20
159
  * @param collection 数据表名称
21
160
  * @param _mockDatabase 模拟数据库,用于单元测试
22
161
  */
23
162
  constructor(options) {
24
- this.#options = options;
25
- this.#host = options._mockDatabase || options.transaction?.collection(options.table) || db0.collection(options.table);
26
- this.#isTransaction = !!options.transaction;
163
+ this._options = options;
164
+ this._host = options._mockDatabase || options.transaction?.collection(options.table) || db0.collection(options.table);
165
+ this._isTransaction = !!options.transaction;
27
166
  }
28
167
  get table() {
29
- return this.#options.table;
168
+ return this._options.table;
30
169
  }
31
170
  /**
32
171
  * 获取聚合操作实例
33
172
  * @returns 聚合操作实例
34
173
  */
35
174
  aggregate() {
36
- return this.#host.aggregate();
175
+ return this._host.aggregate();
37
176
  }
38
- #hasWhere = void 0;
39
- #hasWhereId = void 0;
40
- #where = {};
41
- #doWhere(where, from) {
42
- if (this.#hasWhere) throw new Error(`已调用过一次 db.${_toWhereMethod(this.#hasWhere)} 了`);
177
+ _hasWhere = void 0;
178
+ _hasWhereId = void 0;
179
+ _where = {};
180
+ _doWhere(where, from) {
181
+ if (this._hasWhere) throw new Error(`已调用过一次 db.${_toWhereMethod(this._hasWhere)} 了`);
43
182
  const whereKeys = Object.keys(where);
44
183
  const isWhereId = whereKeys.length === 1 && "_id" in where && (isString(where._id) || isNumber(where._id));
45
- if (isWhereId && this.#hasLimit) {
184
+ if (isWhereId && this._hasLimit) {
46
185
  throw new Error(`db.${_toWhereIdMethod(from)} 方法不能与 db.limit() 方法同时调用`);
47
186
  }
48
- this.#hasWhere = from;
49
- this.#where = where;
50
- if (isWhereId) this.#hasWhereId = from;
187
+ this._hasWhere = from;
188
+ this._where = where;
189
+ if (isWhereId) this._hasWhereId = from;
51
190
  return this;
52
191
  }
53
192
  /**
@@ -56,7 +195,7 @@ class Db {
56
195
  * @returns 当前Db实例,支持链式调用
57
196
  */
58
197
  where(where) {
59
- return this.#doWhere(where, "where");
198
+ return this._doWhere(where, "where");
60
199
  }
61
200
  /**
62
201
  * 根据ID设置查询条件
@@ -64,102 +203,100 @@ class Db {
64
203
  * @returns 当前Db实例,支持链式调用
65
204
  */
66
205
  whereId(id) {
67
- return this.#doWhere({ _id: id }, "whereId");
206
+ return this._doWhere({ _id: id }, "whereId");
68
207
  }
69
- #hasSelect = 0;
70
- #select = {};
208
+ _hasSelect = 0;
209
+ _select = {};
71
210
  /**
72
211
  * 指定要返回的字段
73
212
  * @param fields 要返回的字段对象,true表示返回,false表示不返回
74
213
  * @returns 当前Db实例,支持链式调用
75
214
  */
76
215
  select(fields) {
77
- if (this.#hasSelect) throw new Error("db.select() 方法只能调用一次");
78
- this.#hasSelect++;
79
- this.#select = fields;
216
+ if (this._hasSelect) throw new Error("db.select() 方法只能调用一次");
217
+ this._hasSelect++;
218
+ this._select = fields;
80
219
  return this;
81
220
  }
82
- #hasOrder = 0;
83
- #order = {};
221
+ _hasOrder = 0;
222
+ _order = {};
84
223
  /**
85
224
  * 设置排序规则
86
225
  * @param order 排序规则对象,key为字段名,value为"asc"或"desc"
87
226
  * @returns 当前Db实例,支持链式调用
88
227
  */
89
228
  order(order) {
90
- this.#hasOrder++;
91
- this.#order = order;
229
+ this._hasOrder++;
230
+ this._order = order;
92
231
  return this;
93
232
  }
94
- #hasSkip = 0;
95
- #skip = 0;
233
+ _hasSkip = 0;
234
+ _skip = 0;
96
235
  /**
97
236
  * 跳过指定数量的记录
98
237
  * @param skip 要跳过的记录数
99
238
  * @returns 当前Db实例,支持链式调用
100
239
  */
101
240
  skip(skip) {
102
- if (this.#hasSkip) throw new Error("db.skip() 方法只能调用一次");
103
- this.#hasSkip++;
104
- this.#skip = skip;
241
+ if (this._hasSkip) throw new Error("db.skip() 方法只能调用一次");
242
+ this._hasSkip++;
243
+ this._skip = skip;
105
244
  return this;
106
245
  }
107
- #hasLimit = 0;
108
- #limit = 0;
246
+ _hasLimit = 0;
247
+ _limit = 0;
109
248
  /**
110
249
  * 限制返回的记录数量
111
250
  * @param limit 最大返回记录数
112
251
  * @returns 当前Db实例,支持链式调用
113
252
  */
114
253
  limit(limit) {
115
- if (this.#hasLimit) throw new Error("db.limit() 方法只能调用一次");
116
- if (this.#hasWhereId) {
117
- throw new Error(`db.limit() 方法不能与 ${_toWhereIdMethod(this.#hasWhereId)} 方法同时调用`);
254
+ if (this._hasLimit) throw new Error("db.limit() 方法只能调用一次");
255
+ if (this._hasWhereId) {
256
+ throw new Error(`db.limit() 方法不能与 ${_toWhereIdMethod(this._hasWhereId)} 方法同时调用`);
118
257
  }
119
- this.#hasLimit++;
120
- this.#limit = limit;
258
+ this._hasLimit++;
259
+ this._limit = limit;
121
260
  return this;
122
261
  }
123
- #hasLookup = 0;
262
+ _hasLookup = 0;
124
263
  get hasLookup() {
125
- return this.#hasLookup > 0;
264
+ return this._hasLookup > 0;
126
265
  }
127
- #lookups = [];
266
+ _lookups = [];
128
267
  lookup(table, lookup) {
129
- table.#hasLookup++;
130
- this.#hasLookup++;
131
- this.#lookups.push({
268
+ table._hasLookup++;
269
+ this._hasLookup++;
270
+ this._lookups.push({
132
271
  ...lookup,
133
- table,
134
- from: table.table
272
+ table
135
273
  });
136
274
  return this;
137
275
  }
138
- #aggregated = false;
139
- #endAggregate(aggRef) {
140
- if (this.#aggregated) throw new Error(`相同的数据表实例(${this.table})不能重复使用`);
141
- this.#aggregated = true;
276
+ _aggregated = false;
277
+ _endAggregate(aggRef) {
278
+ if (this._aggregated) throw new Error(`相同的数据表实例(${this.table})不能重复使用`);
279
+ this._aggregated = true;
142
280
  let returnAggRef = aggRef;
143
281
  const projects = {};
144
- for (const { type, as, foreignField, from, localField, table } of this.#lookups) {
145
- const varName = `v${gid++}`;
282
+ for (const { type, as, foreignField, localField, table, unselect } of this._lookups) {
283
+ const letName = `let${gid++}`;
146
284
  let pipeline = dbAgg.pipeline();
147
- pipeline = pipeline.match(
148
- dbCmd.expr(
149
- type === "n:1" ? (
150
- // @ts-ignore
151
- dbAgg.in([`$${foreignField}`, `$$${varName}`])
152
- ) : dbAgg.eq([`$${foreignField}`, `$$${varName}`])
153
- )
154
- );
155
- pipeline = table.#endAggregate(pipeline);
285
+ pipeline = pipeline.match({
286
+ $expr: {
287
+ $and: [
288
+ type === "n:1" ? { $in: [`$${foreignField}`, `$$${letName}`] } : { $eq: [`$${foreignField}`, `$$${letName}`] }
289
+ ]
290
+ }
291
+ });
292
+ pipeline = table._endAggregate(pipeline);
156
293
  pipeline = pipeline.done();
157
294
  returnAggRef = returnAggRef.lookup({
158
295
  let: {
159
- [varName]: `$${localField}`
296
+ [letName]: `$${localField}`
160
297
  },
161
298
  as,
162
- from,
299
+ from: table.table,
163
300
  pipeline
164
301
  });
165
302
  if (type === "1:1") {
@@ -168,30 +305,30 @@ class Db {
168
305
  preserveNullAndEmptyArrays: true
169
306
  });
170
307
  }
171
- projects[as] = true;
308
+ if (as && !unselect) projects[as] = true;
172
309
  }
173
- if (this.#hasWhere) returnAggRef = returnAggRef.match(this.#where);
174
- if (this.#hasSelect) returnAggRef = returnAggRef.project({ ...this.#select, ...projects });
175
- if (this.#hasOrder) returnAggRef = returnAggRef.sort(objectMap(this.#order, (v) => v === "asc" ? 1 : -1));
176
- if (this.#hasSkip) returnAggRef = returnAggRef.skip(this.#skip);
177
- if (this.#hasLimit) returnAggRef = returnAggRef.limit(this.#limit);
310
+ if (this._hasWhere) returnAggRef = returnAggRef.match(_mapQueryCommandWhere(this._where));
311
+ if (this._hasSelect) returnAggRef = returnAggRef.project({ ...this._select, ...projects });
312
+ if (this._hasOrder) returnAggRef = returnAggRef.sort(objectMap(this._order, (v) => v === "asc" ? 1 : -1));
313
+ if (this._hasSkip) returnAggRef = returnAggRef.skip(this._skip);
314
+ if (this._hasLimit) returnAggRef = returnAggRef.limit(this._limit);
178
315
  return returnAggRef;
179
316
  }
180
- #endHost() {
181
- if (this.#hasWhere) {
182
- this.#host = this.#host.where(this.#where);
317
+ _endHost() {
318
+ if (this._hasWhere) {
319
+ this._host = this._host.where(_mapQueryCommandWhere(this._where));
183
320
  }
184
- if (this.#hasSelect) {
185
- this.#host = this.#host.field(this.#select);
321
+ if (this._hasSelect) {
322
+ this._host = this._host.field(this._select);
186
323
  }
187
- if (this.#hasOrder) {
188
- objectEach(this.#order, (val, key) => {
189
- this.#host = this.#host.orderBy(key, val);
324
+ if (this._hasOrder) {
325
+ objectEach(this._order, (val, key) => {
326
+ this._host = this._host.orderBy(key, val);
190
327
  });
191
328
  }
192
- if (this.#hasSkip) this.#host = this.#host.skip(this.#skip);
193
- if (this.#hasLimit) this.#host = this.#host.limit(this.#limit);
194
- else if (this.#hasWhereId) this.#host = this.#host.limit(1);
329
+ if (this._hasSkip) this._host = this._host.skip(this._skip);
330
+ if (this._hasLimit) this._host = this._host.limit(this._limit);
331
+ else if (this._hasWhereId) this._host = this._host.limit(1);
195
332
  }
196
333
  /**
197
334
  * 执行查询操作
@@ -199,24 +336,24 @@ class Db {
199
336
  */
200
337
  async query() {
201
338
  let res;
202
- if (this.#hasLookup) {
339
+ if (this._hasLookup) {
203
340
  const aggRef = this.aggregate();
204
- this.#endAggregate(aggRef);
341
+ this._endAggregate(aggRef);
205
342
  res = await aggRef.end();
206
343
  } else {
207
- this.#endHost();
208
- res = await this.#host.get();
344
+ this._endHost();
345
+ res = await this._host.get();
209
346
  }
210
347
  isArray(res.data) ? res.data : [res.data];
211
348
  const { data } = parseDatabaseOutput(res);
212
349
  return data;
213
350
  }
214
- async queryOne(ignoreMiss = false) {
215
- if (this.#hasLimit) throw new Error("db.queryOne() 方法不支持 limit 条件");
216
- if (!this.#hasWhereId) this.limit(1);
351
+ async queryOne(allowMiss = false) {
352
+ if (this._hasLimit) throw new Error("db.queryOne() 方法不支持 limit 条件");
353
+ if (!this._hasWhereId) this.limit(1);
217
354
  const data = await this.query();
218
355
  const res = data.at(0);
219
- if (!ignoreMiss && !res) throw new Error("未找到匹配记录");
356
+ if (!allowMiss && !res) throw new Error("未找到匹配记录");
220
357
  return res;
221
358
  }
222
359
  /**
@@ -224,13 +361,13 @@ class Db {
224
361
  * @returns 记录总数
225
362
  */
226
363
  async count() {
227
- if (this.#hasLookup) throw new Error("db.count() 方法不支持 lookup 聚合");
228
- if (this.#hasSelect) throw new Error("db.count() 方法不支持 select 条件");
229
- if (this.#hasOrder) throw new Error("db.count() 方法不支持 order 条件");
230
- if (this.#hasSkip) throw new Error("db.count() 方法不支持 skip 条件");
231
- if (this.#hasLimit) throw new Error("db.count() 方法不支持 limit 条件");
232
- this.#endHost();
233
- const res = await this.#host.count();
364
+ if (this._hasLookup) throw new Error("db.count() 方法不支持 lookup 聚合");
365
+ if (this._hasSelect) throw new Error("db.count() 方法不支持 select 条件");
366
+ if (this._hasOrder) throw new Error("db.count() 方法不支持 order 条件");
367
+ if (this._hasSkip) throw new Error("db.count() 方法不支持 skip 条件");
368
+ if (this._hasLimit) throw new Error("db.count() 方法不支持 limit 条件");
369
+ this._endHost();
370
+ const res = await this._host.count();
234
371
  const { total } = parseDatabaseOutput(res);
235
372
  return total;
236
373
  }
@@ -240,14 +377,14 @@ class Db {
240
377
  * @returns 创建结果
241
378
  */
242
379
  async create(data) {
243
- if (this.#hasLookup) throw new Error("db.create() 方法不支持 lookup 聚合");
244
- if (this.#hasWhere) throw new Error("db.create() 方法不支持 where 条件");
245
- if (this.#hasSelect) throw new Error("db.create() 方法不支持 select 条件");
246
- if (this.#hasOrder) throw new Error("db.create() 方法不支持 order 条件");
247
- if (this.#hasSkip) throw new Error("db.create() 方法不支持 skip 条件");
248
- if (this.#hasLimit) throw new Error("db.create() 方法不支持 limit 条件");
249
- this.#endHost();
250
- const res = await this.#host.add(data);
380
+ if (this._hasLookup) throw new Error("db.create() 方法不支持 lookup 聚合");
381
+ if (this._hasWhere) throw new Error("db.create() 方法不支持 where 条件");
382
+ if (this._hasSelect) throw new Error("db.create() 方法不支持 select 条件");
383
+ if (this._hasOrder) throw new Error("db.create() 方法不支持 order 条件");
384
+ if (this._hasSkip) throw new Error("db.create() 方法不支持 skip 条件");
385
+ if (this._hasLimit) throw new Error("db.create() 方法不支持 limit 条件");
386
+ this._endHost();
387
+ const res = await this._host.add(data);
251
388
  const { id } = parseDatabaseOutput(res);
252
389
  return id;
253
390
  }
@@ -257,15 +394,15 @@ class Db {
257
394
  * @returns 更新结果
258
395
  */
259
396
  async update(data) {
260
- if (this.#hasLookup) throw new Error("db.update() 方法不支持 lookup 聚合");
261
- if (!this.#hasWhere) throw new Error("设置 where 条件后才能执行 db.update() 方法");
262
- if (this.#hasSelect) throw new Error("db.update() 方法不支持 select 条件");
263
- if (this.#hasOrder) throw new Error("db.update() 方法不支持 order 条件");
264
- if (this.#hasSkip) throw new Error("db.update() 方法不支持 skip 条件");
265
- if (this.#hasLimit) throw new Error("db.update() 方法不支持 limit 条件");
266
- if (this.#isTransaction && !this.#hasWhereId) throw new Error("事务模式下 db.update() 的 where 条件必须是 _id");
267
- this.#endHost();
268
- const res = await this.#host.update(data);
397
+ if (this._hasLookup) throw new Error("db.update() 方法不支持 lookup 聚合");
398
+ if (!this._hasWhere) throw new Error("设置 where 条件后才能执行 db.update() 方法");
399
+ if (this._hasSelect) throw new Error("db.update() 方法不支持 select 条件");
400
+ if (this._hasOrder) throw new Error("db.update() 方法不支持 order 条件");
401
+ if (this._hasSkip) throw new Error("db.update() 方法不支持 skip 条件");
402
+ if (this._hasLimit) throw new Error("db.update() 方法不支持 limit 条件");
403
+ if (this._isTransaction && !this._hasWhereId) throw new Error("事务模式下 db.update() 的 where 条件必须是 _id");
404
+ this._endHost();
405
+ const res = await this._host.update(data);
269
406
  const { updated } = parseDatabaseOutput(res);
270
407
  return updated;
271
408
  }
@@ -274,58 +411,45 @@ class Db {
274
411
  * @returns 删除结果
275
412
  */
276
413
  async remove() {
277
- if (this.#hasLookup) throw new Error("db.remove() 方法不支持 lookup 聚合");
278
- if (!this.#hasWhere) throw new Error("设置 where 条件后才能执行 db.remove() 方法");
279
- if (this.#hasSelect) throw new Error("db.remove() 方法不支持 select 条件");
280
- if (this.#hasOrder) throw new Error("db.remove() 方法不支持 order 条件");
281
- if (this.#hasSkip) throw new Error("db.remove() 方法不支持 skip 条件");
282
- if (this.#hasLimit) throw new Error("db.remove() 方法不支持 limit 条件");
283
- if (this.#isTransaction && !this.#hasWhereId) throw new Error("事务模式下 db.remove() 的 where 条件必须是 _id");
284
- this.#endHost();
285
- const res = await this.#host.remove();
414
+ if (this._hasLookup) throw new Error("db.remove() 方法不支持 lookup 聚合");
415
+ if (!this._hasWhere) throw new Error("设置 where 条件后才能执行 db.remove() 方法");
416
+ if (this._hasSelect) throw new Error("db.remove() 方法不支持 select 条件");
417
+ if (this._hasOrder) throw new Error("db.remove() 方法不支持 order 条件");
418
+ if (this._hasSkip) throw new Error("db.remove() 方法不支持 skip 条件");
419
+ if (this._hasLimit) throw new Error("db.remove() 方法不支持 limit 条件");
420
+ if (this._isTransaction && !this._hasWhereId) throw new Error("事务模式下 db.remove() 的 where 条件必须是 _id");
421
+ this._endHost();
422
+ const res = await this._host.remove();
286
423
  const { deleted } = parseDatabaseOutput(res);
287
424
  return deleted;
288
425
  }
289
426
  }
290
- const db = {
291
- /**
292
- * 获取指定名称的数据库集合实例
293
- * @param name 数据表名称
294
- * @returns Db类实例,用于执行数据库操作
295
- */
296
- // biome-ignore lint/complexity/noBannedTypes: <explanation>
297
- table(name) {
298
- return new Proxy(
299
- {},
300
- {
301
- get(target, prop) {
302
- if (prop === "_isProxy") return true;
303
- const table = new Db({ table: name });
304
- const tableProp = prop;
305
- const ref = table[tableProp];
306
- return isFunction(ref) ? ref.bind(table) : ref;
307
- }
308
- }
309
- );
310
- }
311
- };
312
- function parseDatabaseOutput(res) {
313
- const keys = Object.keys(res);
314
- const isClient = keys.length === 1 && keys[0] === "result";
315
- if (isClient) {
316
- const { result } = res;
317
- if (!result.errCode) return objectOmit(result, ["errCode", "errMsg", "code", "message"]);
318
- throw errorAssign(new Error(result.errMsg), result);
319
- }
320
- return res;
321
- }
322
427
  function _toWhereMethod(whereFrom) {
323
428
  return whereFrom === "where" ? "where({...})" : "whereId(id)";
324
429
  }
325
430
  function _toWhereIdMethod(whereFrom) {
326
431
  return whereFrom === "where" ? "where({ _id })" : "whereId(id)";
327
432
  }
328
- async function dbUpsert(dbProxy, options) {
433
+ function _mapQueryCommandWhere(where) {
434
+ return objectMap(where, (val, key) => {
435
+ return isObject(val) && val instanceof DbQueryCommand ? val.getValue(db0) : val;
436
+ });
437
+ }
438
+ function dbProxy(name) {
439
+ return new Proxy(
440
+ {},
441
+ {
442
+ get(target, prop) {
443
+ if (prop === "_isProxy") return true;
444
+ const table = new Db({ table: name });
445
+ const tableProp = prop;
446
+ const ref = table[tableProp];
447
+ return isFunction(ref) ? ref.bind(table) : ref;
448
+ }
449
+ }
450
+ );
451
+ }
452
+ async function dbUpsert(dbProxy2, options) {
329
453
  const {
330
454
  where,
331
455
  select = {},
@@ -338,7 +462,7 @@ async function dbUpsert(dbProxy, options) {
338
462
  _mockDbInstance
339
463
  } = options;
340
464
  if ("_id" in select) throw new Error("select 条件不能包含 _id 字段");
341
- const _db = _mockDbInstance || dbProxy;
465
+ const _db = _mockDbInstance || dbProxy2;
342
466
  const exist = await _db.where(where).select(select || {}).queryOne(true);
343
467
  if (exist) {
344
468
  const skipUpdate = await onBeforeUpdate?.(exist) === false;
@@ -355,12 +479,20 @@ async function dbUpsert(dbProxy, options) {
355
479
  await onAfterCreate?.(createdId);
356
480
  return { id: createdId, updated: false, created: true };
357
481
  }
482
+ async function dbUnique(dbProxy2, options) {
483
+ const { id, created } = await dbUpsert(dbProxy2, {
484
+ ...options,
485
+ update: {},
486
+ onBeforeUpdate: () => false
487
+ });
488
+ return { id, created };
489
+ }
358
490
  async function dbTransaction(transacting, _mockDatabase, _mockDbInstance) {
359
491
  const transactionDb = _mockDatabase || uniCloud.database();
360
492
  const [err1, transaction] = await tryFlatten(transactionDb.startTransaction());
361
493
  if (err1) throw err1;
362
- const withTransaction = (dbProxy) => {
363
- return _mockDbInstance || new Db({ table: dbProxy.table, transaction });
494
+ const withTransaction = (dbProxy2) => {
495
+ return _mockDbInstance || new Db({ table: dbProxy2.table, transaction });
364
496
  };
365
497
  const [err2, result] = await tryFlatten(async () => {
366
498
  const result2 = await transacting(withTransaction);
@@ -374,11 +506,11 @@ async function dbTransaction(transacting, _mockDatabase, _mockDbInstance) {
374
506
  return result;
375
507
  }
376
508
  export {
377
- Db,
378
- db,
379
- dbAgg,
380
- dbCmd,
509
+ dbMutate,
510
+ dbProxy,
511
+ dbQuery,
381
512
  dbTransaction,
513
+ dbUnique,
382
514
  dbUpsert,
383
515
  parseDatabaseOutput
384
516
  };