@cloudcome/utils-uni 1.19.0 → 1.20.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.
@@ -1,3 +1,4 @@
1
+ import { UniErrorData } from '../_types';
1
2
  import { HasProperty, IsEmptyObject, IsOnlyProperty } from '@cloudcome/utils-core/types';
2
3
  import { DbMutateCommand, DbQueryCommand } from './_command.class';
3
4
  /**
@@ -5,16 +6,7 @@ import { DbMutateCommand, DbQueryCommand } from './_command.class';
5
6
  * @template T - 原始数据类型
6
7
  */
7
8
  export type ClientDatabaseOutput<T> = {
8
- result: T & {
9
- /** 状态码 */
10
- code?: number | string;
11
- /** 错误码 */
12
- errCode?: number | string;
13
- /** 错误信息 */
14
- errMsg?: string;
15
- /** 消息 */
16
- message?: string;
17
- };
9
+ result: T & UniErrorData;
18
10
  };
19
11
  /**
20
12
  * 云端数据库输出类型
package/dist/database.cjs CHANGED
@@ -176,6 +176,9 @@ class Db {
176
176
  get table() {
177
177
  return this._options.table;
178
178
  }
179
+ get options() {
180
+ return this._options;
181
+ }
179
182
  /**
180
183
  * 获取聚合操作实例
181
184
  * @returns 聚合操作实例
@@ -323,9 +326,13 @@ class Db {
323
326
  if (this._hasLimit) returnAggRef = returnAggRef.limit(this._limit);
324
327
  return returnAggRef;
325
328
  }
326
- _endHost() {
329
+ _endHost(action) {
327
330
  if (this._hasWhere) {
328
- this._host = this._host.where(_mapCommandRaw(this._where));
331
+ if (action === "update" && this._isTransaction) {
332
+ this._host = this._host.doc(this._where._id);
333
+ } else {
334
+ this._host = this._host.where(_mapCommandRaw(this._where));
335
+ }
329
336
  }
330
337
  if (this._hasSelect) {
331
338
  this._host = this._host.field(this._select);
@@ -336,27 +343,31 @@ class Db {
336
343
  });
337
344
  }
338
345
  if (this._hasSkip) this._host = this._host.skip(this._skip);
339
- if (this._hasLimit) this._host = this._host.limit(this._limit);
340
- else if (this._hasWhereId) this._host = this._host.limit(1);
346
+ if (this._hasLimit && action === "query") this._host = this._host.limit(this._limit);
347
+ else if (this._hasWhereId && action === "query") this._host = this._host.limit(1);
341
348
  }
342
349
  /**
343
350
  * 执行查询操作
344
351
  * @returns 查询结果
345
352
  */
346
353
  async query() {
347
- if (this._isTransaction) throw new Error("db.query() 方法不支持事务模式");
348
- let res;
349
- if (this._hasLookup) {
350
- const aggRef = this.aggregate();
351
- this._endAggregate(aggRef);
352
- res = await aggRef.end();
353
- } else {
354
- this._endHost();
355
- res = await this._host.get();
354
+ try {
355
+ if (this._isTransaction) throw new Error("db.query() 方法不支持事务模式");
356
+ let res;
357
+ if (this._hasLookup) {
358
+ const aggRef = this.aggregate();
359
+ this._endAggregate(aggRef);
360
+ res = await aggRef.end();
361
+ } else {
362
+ this._endHost("query");
363
+ res = await this._host.get();
364
+ }
365
+ const { data } = _helpers.parseDatabaseOutput(res);
366
+ return data;
367
+ } catch (err) {
368
+ const dbErr = err;
369
+ throw this._options.parseError?.(dbErr) || dbErr;
356
370
  }
357
- type.isArray(res.data) ? res.data : [res.data];
358
- const { data } = _helpers.parseDatabaseOutput(res);
359
- return data;
360
371
  }
361
372
  async queryOne(allowMiss = false) {
362
373
  if (this._isTransaction) throw new Error("db.queryOne() 方法不支持事务模式");
@@ -364,7 +375,7 @@ class Db {
364
375
  if (!this._hasWhereId) this.limit(1);
365
376
  const data = await this.query();
366
377
  const res = data.at(0);
367
- if (!allowMiss && !res) throw error.createCloudObjectError("查询数据为空", "queryOneNotFound");
378
+ if (!allowMiss && !res) throw error.createCloudObjectError("查询数据为空", "queryOneMiss");
368
379
  return res || null;
369
380
  }
370
381
  /**
@@ -377,10 +388,15 @@ class Db {
377
388
  if (this._hasOrder) throw new Error("db.count() 方法不支持 order 条件");
378
389
  if (this._hasSkip) throw new Error("db.count() 方法不支持 skip 条件");
379
390
  if (this._hasLimit) throw new Error("db.count() 方法不支持 limit 条件");
380
- this._endHost();
381
- const res = await this._host.count();
382
- const { total } = _helpers.parseDatabaseOutput(res);
383
- return total;
391
+ try {
392
+ this._endHost("count");
393
+ const res = await this._host.count();
394
+ const { total } = _helpers.parseDatabaseOutput(res);
395
+ return total;
396
+ } catch (err) {
397
+ const dbErr = err;
398
+ throw this._options.parseError?.(dbErr) || dbErr;
399
+ }
384
400
  }
385
401
  /**
386
402
  * 创建新记录
@@ -394,10 +410,15 @@ class Db {
394
410
  if (this._hasOrder) throw new Error("db.create() 方法不支持 order 条件");
395
411
  if (this._hasSkip) throw new Error("db.create() 方法不支持 skip 条件");
396
412
  if (this._hasLimit) throw new Error("db.create() 方法不支持 limit 条件");
397
- this._endHost();
398
- const res = await this._host.add(data);
399
- const { id } = _helpers.parseDatabaseOutput(res);
400
- return id;
413
+ try {
414
+ this._endHost("create");
415
+ const res = await this._host.add(data);
416
+ const { id } = _helpers.parseDatabaseOutput(res);
417
+ return id;
418
+ } catch (err) {
419
+ const dbErr = err;
420
+ throw this._options.parseError?.(dbErr) || dbErr;
421
+ }
401
422
  }
402
423
  /**
403
424
  * 更新记录
@@ -412,10 +433,15 @@ class Db {
412
433
  if (this._hasSkip) throw new Error("db.update() 方法不支持 skip 条件");
413
434
  if (this._hasLimit) throw new Error("db.update() 方法不支持 limit 条件");
414
435
  if (this._isTransaction && !this._hasWhereId) throw new Error("事务模式下 db.update() 的 where 条件必须是 _id");
415
- this._endHost();
416
- const res = await this._host.update(_mapCommandRaw(data));
417
- const { updated } = _helpers.parseDatabaseOutput(res);
418
- return updated;
436
+ try {
437
+ this._endHost("update");
438
+ const res = await this._host.update(_mapCommandRaw(data));
439
+ const { updated } = _helpers.parseDatabaseOutput(res);
440
+ return updated;
441
+ } catch (err) {
442
+ const dbErr = err;
443
+ throw this._options.parseError?.(dbErr) || dbErr;
444
+ }
419
445
  }
420
446
  /**
421
447
  * 删除记录
@@ -429,10 +455,15 @@ class Db {
429
455
  if (this._hasSkip) throw new Error("db.remove() 方法不支持 skip 条件");
430
456
  if (this._hasLimit) throw new Error("db.remove() 方法不支持 limit 条件");
431
457
  if (this._isTransaction && !this._hasWhereId) throw new Error("事务模式下 db.remove() 的 where 条件必须是 _id");
432
- this._endHost();
433
- const res = await this._host.remove();
434
- const { deleted } = _helpers.parseDatabaseOutput(res);
435
- return deleted;
458
+ try {
459
+ this._endHost("remove");
460
+ const res = await this._host.remove();
461
+ const { deleted } = _helpers.parseDatabaseOutput(res);
462
+ return deleted;
463
+ } catch (err) {
464
+ const dbErr = err;
465
+ throw this._options.parseError?.(dbErr) || dbErr;
466
+ }
436
467
  }
437
468
  }
438
469
  function _toWhereMethod(whereFrom) {
@@ -446,13 +477,13 @@ function _mapCommandRaw(where) {
446
477
  return type.isObject(val) && val instanceof DbBaseCommand ? DbBaseCommand.getValue(val, db0) : val;
447
478
  });
448
479
  }
449
- function dbProxy(name) {
480
+ function dbProxy(name, options) {
450
481
  return new Proxy(
451
482
  {},
452
483
  {
453
484
  get(target, prop) {
454
485
  if (prop === "_isProxy") return true;
455
- const table = new Db({ table: name });
486
+ const table = new Db({ table: name, ...options });
456
487
  const tableProp = prop;
457
488
  const ref = table[tableProp];
458
489
  return type.isFunction(ref) ? ref.bind(table) : ref;
@@ -504,7 +535,7 @@ async function dbTransaction(transacting, _mockDatabase, _mockDbInstance) {
504
535
  const [err1, transaction] = await _try.tryFlatten(transactionDb.startTransaction());
505
536
  if (err1) throw err1;
506
537
  const withTransaction = (dbProxy2) => {
507
- return _mockDbInstance || new Db({ table: dbProxy2.table, transaction });
538
+ return _mockDbInstance || new Db({ ...dbProxy2.options, transaction });
508
539
  };
509
540
  const [err2, result] = await _try.tryFlatten(async () => {
510
541
  const result2 = await transacting(withTransaction);
@@ -1 +1 @@
1
- {"version":3,"file":"database.cjs","sources":["../src/database/_command.class.ts","../src/database/command.ts","../src/database/_db.class.ts","../src/database/proxy.ts","../src/database/upsert.ts","../src/database/unique.ts","../src/database/transaction.ts"],"sourcesContent":["// 设置私有属性和静态方法是避免在 update 的时候提示类属性\n\nexport class DbBaseCommand {\n protected _isQuery = false;\n protected _isMutate = false;\n\n constructor(\n private _command: string,\n private _parameter: unknown,\n ) {}\n\n static getValue(cmd: DbBaseCommand, db: UniCloud.Database) {\n return (db.command as unknown as Record<string, (value: unknown) => unknown>)[cmd._command].call(\n db.command,\n cmd._parameter,\n );\n }\n\n static getExpression(cmd: DbBaseCommand, fieldName: string) {\n return {\n [`$${cmd._command}`]: [fieldName, cmd._parameter],\n };\n }\n\n static isQueryCommand(cmd: DbBaseCommand) {\n return cmd._isQuery;\n }\n\n static isMutateCommand(cmd: DbBaseCommand) {\n return cmd._isMutate;\n }\n}\n\nexport class DbQueryCommand extends DbBaseCommand {\n protected _isQuery = true;\n}\n\nexport class DbMutateCommand extends DbBaseCommand {\n protected _isMutate = true;\n}\n","import { DbMutateCommand, DbQueryCommand } from './_command.class';\n\n/**\n * 数据库查询命令对象,提供各种查询操作符\n */\nexport const dbQuery = {\n /**\n * 等于操作符\n * @param value 比较值\n * @returns DbQueryCommand 查询命令对象\n */\n eq: (value: unknown) => new DbQueryCommand('eq', value),\n\n /**\n * 不等于操作符\n * @param value 比较值\n * @returns DbQueryCommand 查询命令对象\n */\n neq: (value: unknown) => new DbQueryCommand('neq', value),\n\n /**\n * 大于操作符\n * @param value 比较值\n * @returns DbQueryCommand 查询命令对象\n */\n gt: (value: unknown) => new DbQueryCommand('gt', value),\n\n /**\n * 大于等于操作符\n * @param value 比较值\n * @returns DbQueryCommand 查询命令对象\n */\n gte: (value: unknown) => new DbQueryCommand('gte', value),\n\n /**\n * 小于操作符\n * @param value 比较值\n * @returns DbQueryCommand 查询命令对象\n */\n lt: (value: unknown) => new DbQueryCommand('lt', value),\n\n /**\n * 小于等于操作符\n * @param value 比较值\n * @returns DbQueryCommand 查询命令对象\n */\n lte: (value: unknown) => new DbQueryCommand('lte', value),\n\n /**\n * 包含在数组中操作符\n * @param value 值数组\n * @returns DbQueryCommand 查询命令对象\n */\n in: (value: unknown[]) => new DbQueryCommand('in', value),\n\n /**\n * 不包含在数组中操作符\n * @param value 值数组\n * @returns DbQueryCommand 查询命令对象\n */\n nin: (value: unknown[]) => new DbQueryCommand('nin', value),\n\n /**\n * 逻辑与操作符\n * @param conditions 查询条件参数\n * @returns DbQueryCommand 查询命令对象\n */\n and: (conditions: unknown[]) => new DbQueryCommand('and', conditions),\n\n /**\n * 逻辑或操作符\n * @param conditions 查询条件参数\n * @returns DbQueryCommand 查询命令对象\n */\n or: (conditions: unknown[]) => new DbQueryCommand('or', conditions),\n\n /**\n * 数组长度匹配操作符\n * @param size 数组长度\n * @returns DbQueryCommand 查询命令对象\n */\n size: (size: number) => new DbQueryCommand('size', size),\n};\n\n/**\n * 数据库变更命令对象,提供各种数据更新操作符\n */\nexport const dbMutate = {\n /**\n * 数值增加操作符\n * @param value 增加的数值\n * @returns DbMutateCommand 变更命令对象\n */\n inc: (value: number) => new DbMutateCommand('inc', value),\n\n /**\n * 数值乘法操作符\n * @param value 乘数\n * @returns DbMutateCommand 变更命令对象\n */\n mul: (value: number) => new DbMutateCommand('mul', value),\n\n /**\n * 设置字段值操作符\n * @param value 设置的值\n * @returns DbMutateCommand 变更命令对象\n */\n set: (value: unknown) => new DbMutateCommand('set', value),\n\n /**\n * 向数组末尾添加元素操作符\n * @param value 添加的值\n * @returns DbMutateCommand 变更命令对象\n */\n push: (value: unknown) => new DbMutateCommand('push', value),\n\n /**\n * 向数组开头添加元素操作符\n * @param value 添加的值\n * @returns DbMutateCommand 变更命令对象\n */\n unshift: (value: unknown) => new DbMutateCommand('unshift', value),\n\n /**\n * 从数组末尾移除元素操作符\n * @returns DbMutateCommand 变更命令对象\n */\n pop: () => new DbMutateCommand('pop', undefined),\n\n /**\n * 从数组开头移除元素操作符\n * @returns DbMutateCommand 变更命令对象\n */\n shift: () => new DbMutateCommand('shift', undefined),\n\n /**\n * 移除字段操作符\n * @returns DbMutateCommand 变更命令对象\n */\n remove: () => new DbMutateCommand('remove', undefined),\n};\n","import { parseDatabaseOutput } from '@/_helpers';\nimport { createCloudObjectError } from '@/cloud';\nimport { objectEach, objectMap } from '@cloudcome/utils-core/object';\nimport { isArray, isNumber, isObject, isString } from '@cloudcome/utils-core/type';\nimport type { AnyObject, MergeIntersection } from '@cloudcome/utils-core/types';\nimport { DbBaseCommand, type DbQueryCommand } from './_command.class';\nimport type { DbCreate, DbForeign, DbOrder, DbQuery, DbRelation, DbSelect, DbUpdate, DbWhere } from './types';\n\n/**\n * 数据库聚合操作符命令\n */\nconst dbAgg = uniCloud.database().command.aggregate as UniCloud.AggregateCommand & {\n pipeline: () => UniCloud.AggregateReference & {\n done: () => unknown;\n };\n};\n\ntype _WhereFrom = 'where' | 'whereId';\n\nconst db0 = uniCloud.database();\n\nexport type DbOptions = {\n /**\n * 数据表名称\n */\n table: string;\n\n /**\n * 事务对象,用于事务操作\n */\n // biome-ignore lint/suspicious/noExplicitAny: <explanation>\n transaction?: any;\n\n /**\n * 模拟数据库,用于单元测试\n */\n // biome-ignore lint/suspicious/noExplicitAny: <explanation>\n _mockDatabase?: any;\n};\n\n// biome-ignore lint/suspicious/noConfusingVoidType: <explanation>\nexport type DbLookupOptions<RL extends DbRelation, D1, FD1, AS, US extends boolean | undefined | void = undefined> = {\n /**\n * 关联类型\n */\n relation: RL;\n\n /**\n * 主表字段\n */\n localField: keyof D1 & string;\n\n /**\n * 关联表字段\n */\n foreignField: keyof FD1 & string;\n\n /**\n * 关联数据在结果中的字段名\n */\n as: AS;\n\n /**\n * 是否取消筛选关联数据\n */\n unselect?: US;\n};\n\n// biome-ignore lint/suspicious/noExplicitAny: <explanation>\nexport type DbLookup = DbLookupOptions<any, unknown, unknown, string, boolean> & {\n /**\n * 关联表\n */\n table: Db<unknown>;\n};\n\nlet gid = 0;\n\n/**\n * 数据库类\n * @template D1 - 主表数据\n * @template S1 - 主表筛选\n * @template D2 - 副表数据\n * @template W2 - 副表查询\n */\n// biome-ignore lint/complexity/noBannedTypes: <explanation>\nexport class Db<D1, S1 extends DbSelect<D1> = {}, D2 extends AnyObject = {}, W2 extends AnyObject = {}> {\n private _host: UniCloud.CollectionReference;\n\n /**\n * 是否为事务环境\n * - 查询条件只能是 id\n * - 不能聚合操作\n */\n private _isTransaction = false;\n\n private _options: DbOptions;\n\n /**\n * 构造函数,初始化数据库集合引用\n * @param collection 数据表名称\n * @param _mockDatabase 模拟数据库,用于单元测试\n */\n constructor(options: DbOptions) {\n this._options = options;\n this._host =\n options._mockDatabase || options.transaction?.collection(options.table) || db0.collection(options.table);\n this._isTransaction = !!options.transaction;\n }\n\n get table() {\n return this._options.table;\n }\n\n /**\n * 获取聚合操作实例\n * @returns 聚合操作实例\n */\n aggregate() {\n return this._host.aggregate();\n }\n\n private _hasWhere: _WhereFrom | undefined = undefined;\n private _hasWhereId: _WhereFrom | undefined = undefined;\n private _where = {};\n\n private _doWhere(where: DbWhere<D1>, from: _WhereFrom) {\n if (this._hasWhere) throw new Error(`已调用过一次 db.${_toWhereMethod(this._hasWhere)} 了`);\n\n const whereKeys = Object.keys(where);\n // 只有 _id 值为字符串或数字时,才能调用 doc 方法\n const isWhereId = whereKeys.length === 1 && '_id' in where && (isString(where._id) || isNumber(where._id));\n\n if (isWhereId && this._hasLimit) {\n throw new Error(`db.${_toWhereIdMethod(from)} 方法不能与 db.limit() 方法同时调用`);\n }\n\n this._hasWhere = from;\n this._where = where;\n if (isWhereId) this._hasWhereId = from;\n\n return this;\n }\n\n /**\n * 设置查询条件\n * @param where 查询条件对象\n * @returns 当前Db实例,支持链式调用\n */\n where(where: DbWhere<D1> & W2) {\n return this._doWhere(where, 'where');\n }\n\n /**\n * 根据ID设置查询条件\n * @param id 记录ID\n * @returns 当前Db实例,支持链式调用\n */\n whereId(id: string | number) {\n // @ts-ignore\n return this._doWhere({ _id: id }, 'whereId');\n }\n\n private _hasSelect = 0;\n private _select = {};\n\n /**\n * 指定要返回的字段\n * @param fields 要返回的字段对象,true表示返回,false表示不返回\n * @returns 当前Db实例,支持链式调用\n */\n select<const S extends DbSelect<D1>>(fields: S) {\n if (this._hasSelect) throw new Error('db.select() 方法只能调用一次');\n\n this._hasSelect++;\n this._select = fields;\n\n // @ts-ignore\n return this as Db<D1, S, D2, W2>;\n }\n\n private _hasOrder = 0;\n private _order = {};\n\n /**\n * 设置排序规则\n * @param order 排序规则对象,key为字段名,value为\"asc\"或\"desc\"\n * @returns 当前Db实例,支持链式调用\n */\n order(order: DbOrder<D1>) {\n this._hasOrder++;\n this._order = order;\n\n return this;\n }\n\n private _hasSkip = 0;\n private _skip = 0;\n\n /**\n * 跳过指定数量的记录\n * @param skip 要跳过的记录数\n * @returns 当前Db实例,支持链式调用\n */\n skip(skip: number) {\n if (this._hasSkip) throw new Error('db.skip() 方法只能调用一次');\n\n this._hasSkip++;\n this._skip = skip;\n\n return this;\n }\n\n private _hasLimit = 0;\n private _limit = 0;\n\n /**\n * 限制返回的记录数量\n * @param limit 最大返回记录数\n * @returns 当前Db实例,支持链式调用\n */\n limit(limit: number) {\n if (this._hasLimit) throw new Error('db.limit() 方法只能调用一次');\n\n if (this._hasWhereId) {\n throw new Error(`db.limit() 方法不能与 ${_toWhereIdMethod(this._hasWhereId)} 方法同时调用`);\n }\n\n this._hasLimit++;\n this._limit = limit;\n\n return this;\n }\n\n private _hasLookup = 0;\n get hasLookup() {\n return this._hasLookup > 0;\n }\n\n private _lookups: DbLookup[] = [];\n lookup<\n FD1,\n FS1 extends DbSelect<FD1>,\n FD2 extends AnyObject,\n FW2 extends AnyObject,\n RL extends DbRelation,\n AS extends string,\n // biome-ignore lint/suspicious/noConfusingVoidType: <explanation>\n US extends boolean | undefined | void = undefined,\n >(table: Db<FD1, FS1, FD2, FW2>, lookup: DbLookupOptions<RL, D1, FD1, AS, US>) {\n // 对方表也记为关联查询,避免做表更新操作\n table._hasLookup++;\n this._hasLookup++;\n this._lookups.push({\n ...lookup,\n table,\n } as unknown as DbLookup);\n\n // @ts-ignore\n return this as Db<\n D1,\n S1,\n US extends true ? D2 : MergeIntersection<D2 & DbForeign<FD1, FS1, FD2, RL, AS>>,\n MergeIntersection<W2 & Partial<Record<AS, DbQueryCommand>>>\n >;\n }\n\n private _aggregated = false;\n private _endAggregate(aggRef: UniCloud.AggregateReference) {\n if (this._aggregated) throw new Error(`相同的数据表实例(${this.table})不能重复使用`);\n\n this._aggregated = true;\n let returnAggRef = aggRef;\n const projects: Record<string, true> = {};\n\n for (const { relation: type, as, foreignField, localField, table, unselect } of this._lookups) {\n const letName = `let${gid++}`;\n let pipeline = dbAgg.pipeline();\n\n // 关联条件\n // @ts-ignore\n pipeline = pipeline.match({\n $expr: {\n $and: [\n type === 'n:1'\n ? { $in: [`$${foreignField}`, `$$${letName}`] }\n : { $eq: [`$${foreignField}`, `$$${letName}`] },\n ],\n },\n });\n\n // 其他查询条件\n // @ts-ignore\n pipeline = table._endAggregate(pipeline);\n\n // @ts-ignore\n pipeline = pipeline.done();\n\n returnAggRef = returnAggRef.lookup({\n let: {\n [letName]: `$${localField}`,\n },\n as,\n from: table.table,\n pipeline,\n });\n\n // 1对1,展开数组\n if (type === '1:1') {\n // @ts-ignore\n returnAggRef = returnAggRef.unwind({\n path: `$${as}`,\n preserveNullAndEmptyArrays: true,\n });\n }\n\n if (as && !unselect) projects[as] = true;\n }\n\n // 主表查询\n if (this._hasWhere) returnAggRef = returnAggRef.match(_mapCommandRaw(this._where));\n if (this._hasSelect) returnAggRef = returnAggRef.project({ ...this._select, ...projects });\n if (this._hasOrder) returnAggRef = returnAggRef.sort(objectMap(this._order, (v) => (v === 'asc' ? 1 : -1)));\n if (this._hasSkip) returnAggRef = returnAggRef.skip(this._skip);\n if (this._hasLimit) returnAggRef = returnAggRef.limit(this._limit);\n\n return returnAggRef;\n }\n\n private _endHost() {\n if (this._hasWhere) {\n // @ts-ignore\n this._host = this._host.where(_mapCommandRaw(this._where));\n }\n\n if (this._hasSelect) {\n // @ts-ignore\n this._host = this._host.field(this._select);\n }\n\n if (this._hasOrder) {\n objectEach(this._order, (val, key) => {\n // @ts-ignore\n this._host = this._host.orderBy(key, val);\n });\n }\n\n // @ts-ignore\n if (this._hasSkip) this._host = this._host.skip(this._skip);\n\n // @ts-ignore\n if (this._hasLimit) this._host = this._host.limit(this._limit);\n // @ts-ignore\n else if (this._hasWhereId) this._host = this._host.limit(1);\n }\n\n /**\n * 执行查询操作\n * @returns 查询结果\n */\n async query() {\n if (this._isTransaction) throw new Error('db.query() 方法不支持事务模式');\n\n let res: { data: DbQuery<D1, S1, D2>[] };\n\n // 关联查询\n if (this._hasLookup) {\n const aggRef = this.aggregate();\n this._endAggregate(aggRef);\n res = await aggRef.end();\n }\n // 单表查询\n else {\n this._endHost();\n res = await this._host.get();\n }\n\n const rows = isArray(res.data) ? res.data : [res.data];\n const { data } = parseDatabaseOutput(res);\n return data;\n }\n\n /**\n * 只查询一条,自动添加 limit(1) 条件\n * @param allowMiss 是否允许没有匹配到记录,如果为 true,则可能返回 null\n * @returns 查询结果\n */\n async queryOne(): Promise<DbQuery<D1, S1, D2>>;\n async queryOne(allowMiss: false): Promise<DbQuery<D1, S1, D2>>;\n async queryOne(allowMiss: true): Promise<DbQuery<D1, S1, D2> | null>;\n async queryOne(allowMiss = false): Promise<DbQuery<D1, S1, D2> | null> {\n if (this._isTransaction) throw new Error('db.queryOne() 方法不支持事务模式');\n if (this._hasLimit) throw new Error('db.queryOne() 方法不支持 limit 条件');\n if (!this._hasWhereId) this.limit(1);\n\n const data = await this.query();\n const res = data.at(0);\n\n if (!allowMiss && !res) throw createCloudObjectError('查询数据为空', 'queryOneNotFound');\n return res || null;\n }\n\n /**\n * 获取匹配记录的数量\n * @returns 记录总数\n */\n async count() {\n if (this._hasLookup) throw new Error('db.count() 方法不支持 lookup 聚合');\n if (this._hasSelect) throw new Error('db.count() 方法不支持 select 条件');\n if (this._hasOrder) throw new Error('db.count() 方法不支持 order 条件');\n if (this._hasSkip) throw new Error('db.count() 方法不支持 skip 条件');\n if (this._hasLimit) throw new Error('db.count() 方法不支持 limit 条件');\n\n this._endHost();\n const res = await this._host.count();\n const { total } = parseDatabaseOutput<{ total: number }>(res);\n return total;\n }\n\n /**\n * 创建新记录\n * @param data 要创建的数据\n * @returns 创建结果\n */\n async create(data: DbCreate<D1>) {\n if (this._hasLookup) throw new Error('db.create() 方法不支持 lookup 聚合');\n if (this._hasWhere) throw new Error('db.create() 方法不支持 where 条件');\n if (this._hasSelect) throw new Error('db.create() 方法不支持 select 条件');\n if (this._hasOrder) throw new Error('db.create() 方法不支持 order 条件');\n if (this._hasSkip) throw new Error('db.create() 方法不支持 skip 条件');\n if (this._hasLimit) throw new Error('db.create() 方法不支持 limit 条件');\n\n this._endHost();\n const res = await this._host.add(data);\n const { id } = parseDatabaseOutput<{ id: string }>(res);\n return id;\n }\n\n /**\n * 更新记录\n * @param data 要更新的数据\n * @returns 更新结果\n */\n async update(data: DbUpdate<D1>) {\n if (this._hasLookup) throw new Error('db.update() 方法不支持 lookup 聚合');\n if (!this._hasWhere) throw new Error('设置 where 条件后才能执行 db.update() 方法');\n if (this._hasSelect) throw new Error('db.update() 方法不支持 select 条件');\n if (this._hasOrder) throw new Error('db.update() 方法不支持 order 条件');\n if (this._hasSkip) throw new Error('db.update() 方法不支持 skip 条件');\n if (this._hasLimit) throw new Error('db.update() 方法不支持 limit 条件');\n\n if (this._isTransaction && !this._hasWhereId) throw new Error('事务模式下 db.update() 的 where 条件必须是 _id');\n\n this._endHost();\n const res = await this._host.update(_mapCommandRaw(data));\n const { updated } = parseDatabaseOutput<{ updated: number }>(res);\n return updated;\n }\n\n /**\n * 删除记录\n * @returns 删除结果\n */\n async remove() {\n if (this._hasLookup) throw new Error('db.remove() 方法不支持 lookup 聚合');\n if (!this._hasWhere) throw new Error('设置 where 条件后才能执行 db.remove() 方法');\n if (this._hasSelect) throw new Error('db.remove() 方法不支持 select 条件');\n if (this._hasOrder) throw new Error('db.remove() 方法不支持 order 条件');\n if (this._hasSkip) throw new Error('db.remove() 方法不支持 skip 条件');\n if (this._hasLimit) throw new Error('db.remove() 方法不支持 limit 条件');\n\n if (this._isTransaction && !this._hasWhereId) throw new Error('事务模式下 db.remove() 的 where 条件必须是 _id');\n\n this._endHost();\n const res = await this._host.remove();\n const { deleted } = parseDatabaseOutput<{ deleted: number }>(res);\n return deleted;\n }\n}\n\nfunction _toWhereMethod(whereFrom: _WhereFrom) {\n return whereFrom === 'where' ? 'where({...})' : 'whereId(id)';\n}\n\nfunction _toWhereIdMethod(whereFrom: _WhereFrom) {\n return whereFrom === 'where' ? 'where({ _id })' : 'whereId(id)';\n}\n\n// biome-ignore lint/suspicious/noExplicitAny: <explanation>\nfunction _mapCommandRaw(where: any) {\n return objectMap(where, (val, key) => {\n return isObject(val) && val instanceof DbBaseCommand ? DbBaseCommand.getValue(val, db0) : val;\n });\n}\n","import { isFunction } from '@cloudcome/utils-core/type';\nimport type { AnyObject } from '@cloudcome/utils-core/types';\nimport { Db } from './_db.class';\nimport type { DbSelect } from './types';\n\n/**\n * DbProxy 类型定义,用于创建数据库代理对象\n * @template D1 - 主表数据\n * @template S1 - 主表筛选\n */\n// biome-ignore lint/complexity/noBannedTypes: <explanation>\nexport type DbProxy<D1, S1 extends DbSelect<D1> = {}> = Db<D1, S1> & {\n _isProxy: true;\n};\n\n/**\n * 创建一个数据库代理对象,用于延迟实例化数据库操作类\n * @template D1 - 主表数据\n * @template S1 - 主表筛选\n * @param name - 数据库表名\n * @returns 返回一个代理对象,该对象会将属性访问转发到实际的数据库操作实例\n */\n// biome-ignore lint/complexity/noBannedTypes: <explanation>\nexport function dbProxy<D1, S1 extends DbSelect<D1> = {}>(name: string) {\n return new Proxy(\n {},\n {\n get(target, prop) {\n if (prop === '_isProxy') return true;\n\n const table = new Db<D1, S1>({ table: name });\n const tableProp = prop as keyof Db<D1, S1>;\n const ref = table[tableProp];\n\n return isFunction(ref) ? ref.bind(table) : ref;\n },\n },\n ) as DbProxy<D1, S1>;\n}\n","import { isFunction } from '@cloudcome/utils-core/type';\nimport type { Exact } from '@cloudcome/utils-core/types';\nimport type { DbProxy } from './proxy';\nimport type { DbCreate, DbQuery, DbSelect, DbUpdate, DbWhere } from './types';\n\nexport type DbUpsertOptions<T, S extends DbSelect<T>, C extends DbCreate<T>, U extends DbUpdate<T>> = {\n /** 查询条件 */\n where: DbWhere<T>;\n\n /** 查询返回字段 */\n select?: Exact<S, DbSelect<T>>;\n\n /** 创建数据 */\n create: C;\n\n /**\n * 更新数据,可以是对象或根据查询结果生成更新对象的函数\n * @param row 查询到的文档数据,仅在传入函数时可用\n */\n // biome-ignore lint/complexity/noBannedTypes: <explanation>\n update: U | ((exist: DbQuery<T, S, {}>) => U);\n\n /** 创建前回调函数 */\n onBeforeCreate?: () => unknown;\n\n /**\n * 创建后回调函数\n * @param id 创建的文档ID\n */\n onAfterCreate?: (id: string) => unknown;\n\n /**\n * 更新前回调函数\n * @param exist 查询到的原始文档数据\n * @returns 如果返回 false,则取消更新操作\n */\n // biome-ignore lint/complexity/noBannedTypes: <explanation>\n onBeforeUpdate?: (exist: DbQuery<T, S, {}>) => false | unknown;\n\n /**\n * 更新后回调函数\n * @param updateData 实际更新的数据\n * @param exist 查询到的原始文档数据\n */\n // biome-ignore lint/complexity/noBannedTypes: <explanation>\n onAfterUpdate?: (updateData: U, exist: DbQuery<T, S, {}>) => unknown;\n\n /** 用于测试的模拟数据库实例 */\n // biome-ignore lint/suspicious/noExplicitAny: <explanation>\n _mockDbInstance?: any;\n};\n\n/**\n * 数据库 upsert 操作的返回结果类型\n */\nexport type DbUpsertOutput = {\n /** 操作的文档ID */\n id: string;\n /** 是否为创建操作 */\n created: boolean;\n /** 是否为更新操作 */\n updated: boolean;\n};\n\nexport async function dbUpsert<D1, S1 extends DbSelect<D1>, C extends DbCreate<D1>, U extends DbUpdate<D1>>(\n dbProxy: DbProxy<D1>,\n options: DbUpsertOptions<D1, S1, C, U>,\n): Promise<DbUpsertOutput> {\n const {\n where,\n select = {},\n create,\n update,\n onBeforeCreate,\n onAfterCreate,\n onBeforeUpdate,\n onAfterUpdate,\n _mockDbInstance,\n } = options;\n\n // @ts-ignore\n if ('_id' in select) throw new Error('select 条件不能包含 _id 字段');\n\n const _db = (_mockDbInstance || dbProxy) as DbProxy<D1>;\n const exist = (await _db\n .where(where)\n .select(select || {})\n // biome-ignore lint/complexity/noBannedTypes: <explanation>\n .queryOne(true)) as DbQuery<D1, S1, {}> | null;\n\n if (exist) {\n const skipUpdate = (await onBeforeUpdate?.(exist)) === false;\n\n if (skipUpdate) {\n // @ts-ignore\n return { id: exist._id as string, updated: false, created: false };\n }\n\n const updateData = isFunction(update) ? update(exist) : update;\n // @ts-ignore\n const updated = await _db.whereId(exist._id).update(updateData);\n onAfterUpdate?.(updateData, exist);\n\n // @ts-ignore\n return { id: exist._id as string, updated: true, created: false };\n }\n\n await onBeforeCreate?.();\n const createdId = await _db.create(create);\n await onAfterCreate?.(createdId);\n\n return { id: createdId, updated: false, created: true };\n}\n","import type { DbProxy } from './proxy';\nimport type { DbCreate, DbSelect, DbUpdate, DbWhere } from './types';\nimport { dbUpsert } from './upsert';\n\nexport type DbUniqueOptions<T, S extends DbSelect<T>, C extends DbCreate<T>, U extends DbUpdate<T>> = {\n /** 查询条件 */\n where: DbWhere<T>;\n\n /** 创建数据 */\n create: C;\n\n /** 创建前回调函数 */\n onBeforeCreate?: () => unknown;\n\n /**\n * 创建后回调函数\n * @param id 创建的文档ID\n */\n onAfterCreate?: (id: string) => unknown;\n\n /** 用于测试的模拟数据库实例 */\n // biome-ignore lint/suspicious/noExplicitAny: <explanation>\n _mockDbInstance?: any;\n};\n\n/**\n * 数据库 upsert 操作的返回结果类型\n */\nexport type DbUniqueOutput = {\n /** 操作的文档ID */\n id: string;\n /** 是否为创建操作 */\n created: boolean;\n};\n\nexport async function dbUnique<T, S extends DbSelect<T>, C extends DbCreate<T>, U extends DbUpdate<T>>(\n dbProxy: DbProxy<T>,\n options: DbUniqueOptions<T, S, C, U>,\n): Promise<DbUniqueOutput> {\n const { id, created } = await dbUpsert(dbProxy, {\n ...options,\n // @ts-ignore\n update: {},\n onBeforeUpdate: () => false,\n });\n return { id, created };\n}\n","import { tryFlatten } from '@cloudcome/utils-core/try';\nimport { Db } from './_db.class';\nimport type { DbProxy } from './proxy';\n\ntype _TransactionDb = {\n startTransaction: () => Promise<_Transaction>;\n};\n\ntype _Transaction = {\n commit: () => Promise<unknown>;\n rollback: () => Promise<unknown>;\n};\n\nexport type WithTransaction = <D1>(table: DbProxy<D1>) => Db<D1>;\n\n/**\n * 在数据库事务中执行操作\n *\n * @template K - 事务操作返回值类型\n * @param transacting - 事务执行函数,接收事务数据库实例作为参数\n * @param _mockDatabase - 用于测试的模拟数据库对象\n * @param _mockDbInstance - 用于测试的模拟数据库实例\n * @returns 事务操作的返回结果\n *\n * @example\n * ```typescript\n * const result = await dbTransaction(async (withTransaction) => {\n * const userId = await withTransaction(db.table('user')).create({ name: 'John' });\n * const order = await withTransaction(db.table('orders')).create({ userId, amount: 100 });\n * return { user, order };\n * });\n * ```\n */\nexport async function dbTransaction<K>(\n transacting: (withTransaction: WithTransaction) => Promise<K>,\n // biome-ignore lint/suspicious/noExplicitAny: <explanation>\n _mockDatabase?: any,\n // biome-ignore lint/suspicious/noExplicitAny: <explanation>\n _mockDbInstance?: any,\n) {\n const transactionDb = (_mockDatabase || uniCloud.database()) as _TransactionDb;\n\n const [err1, transaction] = await tryFlatten(transactionDb.startTransaction());\n if (err1) throw err1;\n\n const withTransaction: WithTransaction = <D1>(dbProxy: DbProxy<D1>) => {\n return _mockDbInstance || new Db<D1>({ table: dbProxy.table, transaction });\n };\n\n const [err2, result] = await tryFlatten(async () => {\n const result = await transacting(withTransaction);\n await transaction.commit();\n return result;\n });\n\n if (err2) {\n await tryFlatten(transaction.rollback());\n throw err2;\n }\n\n return result as unknown as K;\n}\n"],"names":["isString","isNumber","type","objectMap","objectEach","isArray","parseDatabaseOutput","createCloudObjectError","isObject","isFunction","dbProxy","tryFlatten","result"],"mappings":"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"}
1
+ {"version":3,"file":"database.cjs","sources":["../src/database/_command.class.ts","../src/database/command.ts","../src/database/_db.class.ts","../src/database/proxy.ts","../src/database/upsert.ts","../src/database/unique.ts","../src/database/transaction.ts"],"sourcesContent":["// 设置私有属性和静态方法是避免在 update 的时候提示类属性\n\nexport class DbBaseCommand {\n protected _isQuery = false;\n protected _isMutate = false;\n\n constructor(\n private _command: string,\n private _parameter: unknown,\n ) {}\n\n static getValue(cmd: DbBaseCommand, db: UniCloud.Database) {\n return (db.command as unknown as Record<string, (value: unknown) => unknown>)[cmd._command].call(\n db.command,\n cmd._parameter,\n );\n }\n\n static getExpression(cmd: DbBaseCommand, fieldName: string) {\n return {\n [`$${cmd._command}`]: [fieldName, cmd._parameter],\n };\n }\n\n static isQueryCommand(cmd: DbBaseCommand) {\n return cmd._isQuery;\n }\n\n static isMutateCommand(cmd: DbBaseCommand) {\n return cmd._isMutate;\n }\n}\n\nexport class DbQueryCommand extends DbBaseCommand {\n protected _isQuery = true;\n}\n\nexport class DbMutateCommand extends DbBaseCommand {\n protected _isMutate = true;\n}\n","import { DbMutateCommand, DbQueryCommand } from './_command.class';\n\n/**\n * 数据库查询命令对象,提供各种查询操作符\n */\nexport const dbQuery = {\n /**\n * 等于操作符\n * @param value 比较值\n * @returns DbQueryCommand 查询命令对象\n */\n eq: (value: unknown) => new DbQueryCommand('eq', value),\n\n /**\n * 不等于操作符\n * @param value 比较值\n * @returns DbQueryCommand 查询命令对象\n */\n neq: (value: unknown) => new DbQueryCommand('neq', value),\n\n /**\n * 大于操作符\n * @param value 比较值\n * @returns DbQueryCommand 查询命令对象\n */\n gt: (value: unknown) => new DbQueryCommand('gt', value),\n\n /**\n * 大于等于操作符\n * @param value 比较值\n * @returns DbQueryCommand 查询命令对象\n */\n gte: (value: unknown) => new DbQueryCommand('gte', value),\n\n /**\n * 小于操作符\n * @param value 比较值\n * @returns DbQueryCommand 查询命令对象\n */\n lt: (value: unknown) => new DbQueryCommand('lt', value),\n\n /**\n * 小于等于操作符\n * @param value 比较值\n * @returns DbQueryCommand 查询命令对象\n */\n lte: (value: unknown) => new DbQueryCommand('lte', value),\n\n /**\n * 包含在数组中操作符\n * @param value 值数组\n * @returns DbQueryCommand 查询命令对象\n */\n in: (value: unknown[]) => new DbQueryCommand('in', value),\n\n /**\n * 不包含在数组中操作符\n * @param value 值数组\n * @returns DbQueryCommand 查询命令对象\n */\n nin: (value: unknown[]) => new DbQueryCommand('nin', value),\n\n /**\n * 逻辑与操作符\n * @param conditions 查询条件参数\n * @returns DbQueryCommand 查询命令对象\n */\n and: (conditions: unknown[]) => new DbQueryCommand('and', conditions),\n\n /**\n * 逻辑或操作符\n * @param conditions 查询条件参数\n * @returns DbQueryCommand 查询命令对象\n */\n or: (conditions: unknown[]) => new DbQueryCommand('or', conditions),\n\n /**\n * 数组长度匹配操作符\n * @param size 数组长度\n * @returns DbQueryCommand 查询命令对象\n */\n size: (size: number) => new DbQueryCommand('size', size),\n};\n\n/**\n * 数据库变更命令对象,提供各种数据更新操作符\n */\nexport const dbMutate = {\n /**\n * 数值增加操作符\n * @param value 增加的数值\n * @returns DbMutateCommand 变更命令对象\n */\n inc: (value: number) => new DbMutateCommand('inc', value),\n\n /**\n * 数值乘法操作符\n * @param value 乘数\n * @returns DbMutateCommand 变更命令对象\n */\n mul: (value: number) => new DbMutateCommand('mul', value),\n\n /**\n * 设置字段值操作符\n * @param value 设置的值\n * @returns DbMutateCommand 变更命令对象\n */\n set: (value: unknown) => new DbMutateCommand('set', value),\n\n /**\n * 向数组末尾添加元素操作符\n * @param value 添加的值\n * @returns DbMutateCommand 变更命令对象\n */\n push: (value: unknown) => new DbMutateCommand('push', value),\n\n /**\n * 向数组开头添加元素操作符\n * @param value 添加的值\n * @returns DbMutateCommand 变更命令对象\n */\n unshift: (value: unknown) => new DbMutateCommand('unshift', value),\n\n /**\n * 从数组末尾移除元素操作符\n * @returns DbMutateCommand 变更命令对象\n */\n pop: () => new DbMutateCommand('pop', undefined),\n\n /**\n * 从数组开头移除元素操作符\n * @returns DbMutateCommand 变更命令对象\n */\n shift: () => new DbMutateCommand('shift', undefined),\n\n /**\n * 移除字段操作符\n * @returns DbMutateCommand 变更命令对象\n */\n remove: () => new DbMutateCommand('remove', undefined),\n};\n","import { parseDatabaseOutput } from '@/_helpers';\nimport type { UniError } from '@/_types';\nimport { createCloudObjectError } from '@/cloud';\nimport { objectEach, objectMap } from '@cloudcome/utils-core/object';\nimport { isArray, isNumber, isObject, isString } from '@cloudcome/utils-core/type';\nimport type { AnyObject, MergeIntersection } from '@cloudcome/utils-core/types';\nimport { DbBaseCommand, type DbQueryCommand } from './_command.class';\nimport type { DbCreate, DbForeign, DbOrder, DbQuery, DbRelation, DbSelect, DbUpdate, DbWhere } from './types';\n\n/**\n * 数据库聚合操作符命令\n */\nconst dbAgg = uniCloud.database().command.aggregate as UniCloud.AggregateCommand & {\n pipeline: () => UniCloud.AggregateReference & {\n done: () => unknown;\n };\n};\n\ntype _WhereFrom = 'where' | 'whereId';\n\nconst db0 = uniCloud.database();\n\nexport type DbOptions = {\n /**\n * 数据表名称\n */\n table: string;\n\n /**\n * 事务对象,用于事务操作\n */\n // biome-ignore lint/suspicious/noExplicitAny: <explanation>\n transaction?: any;\n\n /**\n * 模拟数据库,用于单元测试\n */\n // biome-ignore lint/suspicious/noExplicitAny: <explanation>\n _mockDatabase?: any;\n\n /**\n * 自定义错误处理函数\n * @param error 数据库错误对象\n * @returns 处理后的数据库错误对象\n */\n parseError?: (error: UniError) => UniError;\n};\n\n// biome-ignore lint/suspicious/noConfusingVoidType: <explanation>\nexport type DbLookupOptions<RL extends DbRelation, D1, FD1, AS, US extends boolean | undefined | void = undefined> = {\n /**\n * 关联类型\n */\n relation: RL;\n\n /**\n * 主表字段\n */\n localField: keyof D1 & string;\n\n /**\n * 关联表字段\n */\n foreignField: keyof FD1 & string;\n\n /**\n * 关联数据在结果中的字段名\n */\n as: AS;\n\n /**\n * 是否取消筛选关联数据\n */\n unselect?: US;\n};\n\n// biome-ignore lint/suspicious/noExplicitAny: <explanation>\nexport type DbLookup = DbLookupOptions<any, unknown, unknown, string, boolean> & {\n /**\n * 关联表\n */\n table: Db<unknown>;\n};\n\nlet gid = 0;\n\n/**\n * 数据库类\n * @template D1 - 主表数据\n * @template S1 - 主表筛选\n * @template D2 - 副表数据\n * @template W2 - 副表查询\n */\n// biome-ignore lint/complexity/noBannedTypes: <explanation>\nexport class Db<D1, S1 extends DbSelect<D1> = {}, D2 extends AnyObject = {}, W2 extends AnyObject = {}> {\n private _host: UniCloud.CollectionReference;\n\n /**\n * 是否为事务环境\n * - 查询条件只能是 id\n * - 不能聚合操作\n */\n private _isTransaction = false;\n\n private _options: DbOptions;\n\n /**\n * 构造函数,初始化数据库集合引用\n * @param collection 数据表名称\n * @param _mockDatabase 模拟数据库,用于单元测试\n */\n constructor(options: DbOptions) {\n this._options = options;\n this._host =\n options._mockDatabase || options.transaction?.collection(options.table) || db0.collection(options.table);\n this._isTransaction = !!options.transaction;\n }\n\n get table() {\n return this._options.table;\n }\n\n get options() {\n return this._options;\n }\n\n /**\n * 获取聚合操作实例\n * @returns 聚合操作实例\n */\n aggregate() {\n return this._host.aggregate();\n }\n\n private _hasWhere: _WhereFrom | undefined = undefined;\n private _hasWhereId: _WhereFrom | undefined = undefined;\n private _where = {};\n\n private _doWhere(where: DbWhere<D1>, from: _WhereFrom) {\n if (this._hasWhere) throw new Error(`已调用过一次 db.${_toWhereMethod(this._hasWhere)} 了`);\n\n const whereKeys = Object.keys(where);\n // 只有 _id 值为字符串或数字时,才能调用 doc 方法\n const isWhereId = whereKeys.length === 1 && '_id' in where && (isString(where._id) || isNumber(where._id));\n\n if (isWhereId && this._hasLimit) {\n throw new Error(`db.${_toWhereIdMethod(from)} 方法不能与 db.limit() 方法同时调用`);\n }\n\n this._hasWhere = from;\n this._where = where;\n if (isWhereId) this._hasWhereId = from;\n\n return this;\n }\n\n /**\n * 设置查询条件\n * @param where 查询条件对象\n * @returns 当前Db实例,支持链式调用\n */\n where(where: DbWhere<D1> & W2) {\n return this._doWhere(where, 'where');\n }\n\n /**\n * 根据ID设置查询条件\n * @param id 记录ID\n * @returns 当前Db实例,支持链式调用\n */\n whereId(id: string | number) {\n // @ts-ignore\n return this._doWhere({ _id: id }, 'whereId');\n }\n\n private _hasSelect = 0;\n private _select = {};\n\n /**\n * 指定要返回的字段\n * @param fields 要返回的字段对象,true表示返回,false表示不返回\n * @returns 当前Db实例,支持链式调用\n */\n select<const S extends DbSelect<D1>>(fields: S) {\n if (this._hasSelect) throw new Error('db.select() 方法只能调用一次');\n\n this._hasSelect++;\n this._select = fields;\n\n // @ts-ignore\n return this as Db<D1, S, D2, W2>;\n }\n\n private _hasOrder = 0;\n private _order = {};\n\n /**\n * 设置排序规则\n * @param order 排序规则对象,key为字段名,value为\"asc\"或\"desc\"\n * @returns 当前Db实例,支持链式调用\n */\n order(order: DbOrder<D1>) {\n this._hasOrder++;\n this._order = order;\n\n return this;\n }\n\n private _hasSkip = 0;\n private _skip = 0;\n\n /**\n * 跳过指定数量的记录\n * @param skip 要跳过的记录数\n * @returns 当前Db实例,支持链式调用\n */\n skip(skip: number) {\n if (this._hasSkip) throw new Error('db.skip() 方法只能调用一次');\n\n this._hasSkip++;\n this._skip = skip;\n\n return this;\n }\n\n private _hasLimit = 0;\n private _limit = 0;\n\n /**\n * 限制返回的记录数量\n * @param limit 最大返回记录数\n * @returns 当前Db实例,支持链式调用\n */\n limit(limit: number) {\n if (this._hasLimit) throw new Error('db.limit() 方法只能调用一次');\n\n if (this._hasWhereId) {\n throw new Error(`db.limit() 方法不能与 ${_toWhereIdMethod(this._hasWhereId)} 方法同时调用`);\n }\n\n this._hasLimit++;\n this._limit = limit;\n\n return this;\n }\n\n private _hasLookup = 0;\n get hasLookup() {\n return this._hasLookup > 0;\n }\n\n private _lookups: DbLookup[] = [];\n lookup<\n FD1,\n FS1 extends DbSelect<FD1>,\n FD2 extends AnyObject,\n FW2 extends AnyObject,\n RL extends DbRelation,\n AS extends string,\n // biome-ignore lint/suspicious/noConfusingVoidType: <explanation>\n US extends boolean | undefined | void = undefined,\n >(table: Db<FD1, FS1, FD2, FW2>, lookup: DbLookupOptions<RL, D1, FD1, AS, US>) {\n // 对方表也记为关联查询,避免做表更新操作\n table._hasLookup++;\n this._hasLookup++;\n this._lookups.push({\n ...lookup,\n table,\n } as unknown as DbLookup);\n\n // @ts-ignore\n return this as Db<\n D1,\n S1,\n US extends true ? D2 : MergeIntersection<D2 & DbForeign<FD1, FS1, FD2, RL, AS>>,\n MergeIntersection<W2 & Partial<Record<AS, DbQueryCommand>>>\n >;\n }\n\n private _aggregated = false;\n private _endAggregate(aggRef: UniCloud.AggregateReference) {\n if (this._aggregated) throw new Error(`相同的数据表实例(${this.table})不能重复使用`);\n\n this._aggregated = true;\n let returnAggRef = aggRef;\n const projects: Record<string, true> = {};\n\n for (const { relation: type, as, foreignField, localField, table, unselect } of this._lookups) {\n const letName = `let${gid++}`;\n let pipeline = dbAgg.pipeline();\n\n // 关联条件\n // @ts-ignore\n pipeline = pipeline.match({\n $expr: {\n $and: [\n type === 'n:1'\n ? { $in: [`$${foreignField}`, `$$${letName}`] }\n : { $eq: [`$${foreignField}`, `$$${letName}`] },\n ],\n },\n });\n\n // 其他查询条件\n // @ts-ignore\n pipeline = table._endAggregate(pipeline);\n\n // @ts-ignore\n pipeline = pipeline.done();\n\n returnAggRef = returnAggRef.lookup({\n let: {\n [letName]: `$${localField}`,\n },\n as,\n from: table.table,\n pipeline,\n });\n\n // 1对1,展开数组\n if (type === '1:1') {\n // @ts-ignore\n returnAggRef = returnAggRef.unwind({\n path: `$${as}`,\n preserveNullAndEmptyArrays: true,\n });\n }\n\n if (as && !unselect) projects[as] = true;\n }\n\n // 主表查询\n if (this._hasWhere) returnAggRef = returnAggRef.match(_mapCommandRaw(this._where));\n if (this._hasSelect) returnAggRef = returnAggRef.project({ ...this._select, ...projects });\n if (this._hasOrder) returnAggRef = returnAggRef.sort(objectMap(this._order, (v) => (v === 'asc' ? 1 : -1)));\n if (this._hasSkip) returnAggRef = returnAggRef.skip(this._skip);\n if (this._hasLimit) returnAggRef = returnAggRef.limit(this._limit);\n\n return returnAggRef;\n }\n\n private _endHost(action: 'query' | 'create' | 'update' | 'remove' | 'count') {\n if (this._hasWhere) {\n // 事务模式更新只能用 doc(id)\n if (action === 'update' && this._isTransaction) {\n // @ts-ignore\n this._host = this._host.doc(this._where._id);\n } else {\n // @ts-ignore\n this._host = this._host.where(_mapCommandRaw(this._where));\n }\n }\n\n if (this._hasSelect) {\n // @ts-ignore\n this._host = this._host.field(this._select);\n }\n\n if (this._hasOrder) {\n objectEach(this._order, (val, key) => {\n // @ts-ignore\n this._host = this._host.orderBy(key, val);\n });\n }\n\n // @ts-ignore\n if (this._hasSkip) this._host = this._host.skip(this._skip);\n\n // @ts-ignore\n if (this._hasLimit && action === 'query') this._host = this._host.limit(this._limit);\n // @ts-ignore\n else if (this._hasWhereId && action === 'query') this._host = this._host.limit(1);\n }\n\n /**\n * 执行查询操作\n * @returns 查询结果\n */\n async query() {\n try {\n if (this._isTransaction) throw new Error('db.query() 方法不支持事务模式');\n\n let res: { data: DbQuery<D1, S1, D2>[] };\n\n // 关联查询\n if (this._hasLookup) {\n const aggRef = this.aggregate();\n this._endAggregate(aggRef);\n res = await aggRef.end();\n }\n // 单表查询\n else {\n this._endHost('query');\n res = await this._host.get();\n }\n\n const { data } = parseDatabaseOutput(res);\n return data;\n } catch (err) {\n const dbErr = err as UniError;\n throw this._options.parseError?.(dbErr) || dbErr;\n }\n }\n\n /**\n * 只查询一条,自动添加 limit(1) 条件\n * @param allowMiss 是否允许没有匹配到记录,如果为 true,则可能返回 null\n * @returns 查询结果\n */\n async queryOne(): Promise<DbQuery<D1, S1, D2>>;\n async queryOne(allowMiss: false): Promise<DbQuery<D1, S1, D2>>;\n async queryOne(allowMiss: true): Promise<DbQuery<D1, S1, D2> | null>;\n async queryOne(allowMiss = false): Promise<DbQuery<D1, S1, D2> | null> {\n if (this._isTransaction) throw new Error('db.queryOne() 方法不支持事务模式');\n if (this._hasLimit) throw new Error('db.queryOne() 方法不支持 limit 条件');\n if (!this._hasWhereId) this.limit(1);\n\n const data = await this.query();\n const res = data.at(0);\n\n if (!allowMiss && !res) throw createCloudObjectError('查询数据为空', 'queryOneMiss');\n return res || null;\n }\n\n /**\n * 获取匹配记录的数量\n * @returns 记录总数\n */\n async count() {\n if (this._hasLookup) throw new Error('db.count() 方法不支持 lookup 聚合');\n if (this._hasSelect) throw new Error('db.count() 方法不支持 select 条件');\n if (this._hasOrder) throw new Error('db.count() 方法不支持 order 条件');\n if (this._hasSkip) throw new Error('db.count() 方法不支持 skip 条件');\n if (this._hasLimit) throw new Error('db.count() 方法不支持 limit 条件');\n\n try {\n this._endHost('count');\n const res = await this._host.count();\n const { total } = parseDatabaseOutput<{ total: number }>(res);\n return total;\n } catch (err) {\n const dbErr = err as UniError;\n throw this._options.parseError?.(dbErr) || dbErr;\n }\n }\n\n /**\n * 创建新记录\n * @param data 要创建的数据\n * @returns 创建结果\n */\n async create(data: DbCreate<D1>) {\n if (this._hasLookup) throw new Error('db.create() 方法不支持 lookup 聚合');\n if (this._hasWhere) throw new Error('db.create() 方法不支持 where 条件');\n if (this._hasSelect) throw new Error('db.create() 方法不支持 select 条件');\n if (this._hasOrder) throw new Error('db.create() 方法不支持 order 条件');\n if (this._hasSkip) throw new Error('db.create() 方法不支持 skip 条件');\n if (this._hasLimit) throw new Error('db.create() 方法不支持 limit 条件');\n\n try {\n this._endHost('create');\n const res = await this._host.add(data);\n const { id } = parseDatabaseOutput<{ id: string }>(res);\n return id;\n } catch (err) {\n const dbErr = err as UniError;\n throw this._options.parseError?.(dbErr) || dbErr;\n }\n }\n\n /**\n * 更新记录\n * @param data 要更新的数据\n * @returns 更新结果\n */\n async update(data: DbUpdate<D1>) {\n if (this._hasLookup) throw new Error('db.update() 方法不支持 lookup 聚合');\n if (!this._hasWhere) throw new Error('设置 where 条件后才能执行 db.update() 方法');\n if (this._hasSelect) throw new Error('db.update() 方法不支持 select 条件');\n if (this._hasOrder) throw new Error('db.update() 方法不支持 order 条件');\n if (this._hasSkip) throw new Error('db.update() 方法不支持 skip 条件');\n if (this._hasLimit) throw new Error('db.update() 方法不支持 limit 条件');\n\n if (this._isTransaction && !this._hasWhereId) throw new Error('事务模式下 db.update() 的 where 条件必须是 _id');\n\n try {\n this._endHost('update');\n const res = await this._host.update(_mapCommandRaw(data));\n const { updated } = parseDatabaseOutput<{ updated: number }>(res);\n return updated;\n } catch (err) {\n const dbErr = err as UniError;\n throw this._options.parseError?.(dbErr) || dbErr;\n }\n }\n\n /**\n * 删除记录\n * @returns 删除结果\n */\n async remove() {\n if (this._hasLookup) throw new Error('db.remove() 方法不支持 lookup 聚合');\n if (!this._hasWhere) throw new Error('设置 where 条件后才能执行 db.remove() 方法');\n if (this._hasSelect) throw new Error('db.remove() 方法不支持 select 条件');\n if (this._hasOrder) throw new Error('db.remove() 方法不支持 order 条件');\n if (this._hasSkip) throw new Error('db.remove() 方法不支持 skip 条件');\n if (this._hasLimit) throw new Error('db.remove() 方法不支持 limit 条件');\n\n if (this._isTransaction && !this._hasWhereId) throw new Error('事务模式下 db.remove() 的 where 条件必须是 _id');\n\n try {\n this._endHost('remove');\n const res = await this._host.remove();\n const { deleted } = parseDatabaseOutput<{ deleted: number }>(res);\n return deleted;\n } catch (err) {\n const dbErr = err as UniError;\n throw this._options.parseError?.(dbErr) || dbErr;\n }\n }\n}\n\nfunction _toWhereMethod(whereFrom: _WhereFrom) {\n return whereFrom === 'where' ? 'where({...})' : 'whereId(id)';\n}\n\nfunction _toWhereIdMethod(whereFrom: _WhereFrom) {\n return whereFrom === 'where' ? 'where({ _id })' : 'whereId(id)';\n}\n\n// biome-ignore lint/suspicious/noExplicitAny: <explanation>\nfunction _mapCommandRaw(where: any) {\n return objectMap(where, (val, key) => {\n return isObject(val) && val instanceof DbBaseCommand ? DbBaseCommand.getValue(val, db0) : val;\n });\n}\n","import type { UniError } from '@/_types';\nimport { isFunction } from '@cloudcome/utils-core/type';\nimport { Db } from './_db.class';\nimport type { DbSelect } from './types';\n\n/**\n * DbProxy 类型定义,用于创建数据库代理对象\n * @template D1 - 主表数据\n * @template S1 - 主表筛选\n */\n// biome-ignore lint/complexity/noBannedTypes: <explanation>\nexport type DbProxy<D1, S1 extends DbSelect<D1> = {}> = Db<D1, S1> & {\n _isProxy: true;\n};\n\nexport type DbProxyOptions = {\n /**\n * 自定义错误处理函数\n * @param error 数据库错误对象\n * @returns 处理后的数据库错误对象\n */\n parseError?: (error: UniError) => UniError;\n};\n\n/**\n * 创建一个数据库代理对象,用于延迟实例化数据库操作类\n * @template D1 - 主表数据\n * @template S1 - 主表筛选\n * @param name - 数据库表名\n * @returns 返回一个代理对象,该对象会将属性访问转发到实际的数据库操作实例\n */\n// biome-ignore lint/complexity/noBannedTypes: <explanation>\nexport function dbProxy<D1, S1 extends DbSelect<D1> = {}>(name: string, options?: DbProxyOptions) {\n return new Proxy(\n {},\n {\n get(target, prop) {\n if (prop === '_isProxy') return true;\n\n const table = new Db<D1, S1>({ table: name, ...options });\n const tableProp = prop as keyof Db<D1, S1>;\n const ref = table[tableProp];\n\n return isFunction(ref) ? ref.bind(table) : ref;\n },\n },\n ) as DbProxy<D1, S1>;\n}\n","import { isFunction } from '@cloudcome/utils-core/type';\nimport type { Exact } from '@cloudcome/utils-core/types';\nimport type { DbProxy } from './proxy';\nimport type { DbCreate, DbQuery, DbSelect, DbUpdate, DbWhere } from './types';\n\nexport type DbUpsertOptions<T, S extends DbSelect<T>, C extends DbCreate<T>, U extends DbUpdate<T>> = {\n /** 查询条件 */\n where: DbWhere<T>;\n\n /** 查询返回字段 */\n select?: Exact<S, DbSelect<T>>;\n\n /** 创建数据 */\n create: C;\n\n /**\n * 更新数据,可以是对象或根据查询结果生成更新对象的函数\n * @param row 查询到的文档数据,仅在传入函数时可用\n */\n // biome-ignore lint/complexity/noBannedTypes: <explanation>\n update: U | ((exist: DbQuery<T, S, {}>) => U);\n\n /** 创建前回调函数 */\n onBeforeCreate?: () => unknown;\n\n /**\n * 创建后回调函数\n * @param id 创建的文档ID\n */\n onAfterCreate?: (id: string) => unknown;\n\n /**\n * 更新前回调函数\n * @param exist 查询到的原始文档数据\n * @returns 如果返回 false,则取消更新操作\n */\n // biome-ignore lint/complexity/noBannedTypes: <explanation>\n onBeforeUpdate?: (exist: DbQuery<T, S, {}>) => false | unknown;\n\n /**\n * 更新后回调函数\n * @param updateData 实际更新的数据\n * @param exist 查询到的原始文档数据\n */\n // biome-ignore lint/complexity/noBannedTypes: <explanation>\n onAfterUpdate?: (updateData: U, exist: DbQuery<T, S, {}>) => unknown;\n\n /** 用于测试的模拟数据库实例 */\n // biome-ignore lint/suspicious/noExplicitAny: <explanation>\n _mockDbInstance?: any;\n};\n\n/**\n * 数据库 upsert 操作的返回结果类型\n */\nexport type DbUpsertOutput = {\n /** 操作的文档ID */\n id: string;\n /** 是否为创建操作 */\n created: boolean;\n /** 是否为更新操作 */\n updated: boolean;\n};\n\nexport async function dbUpsert<D1, S1 extends DbSelect<D1>, C extends DbCreate<D1>, U extends DbUpdate<D1>>(\n dbProxy: DbProxy<D1>,\n options: DbUpsertOptions<D1, S1, C, U>,\n): Promise<DbUpsertOutput> {\n const {\n where,\n select = {},\n create,\n update,\n onBeforeCreate,\n onAfterCreate,\n onBeforeUpdate,\n onAfterUpdate,\n _mockDbInstance,\n } = options;\n\n // @ts-ignore\n if ('_id' in select) throw new Error('select 条件不能包含 _id 字段');\n\n const _db = (_mockDbInstance || dbProxy) as DbProxy<D1>;\n const exist = (await _db\n .where(where)\n .select(select || {})\n // biome-ignore lint/complexity/noBannedTypes: <explanation>\n .queryOne(true)) as DbQuery<D1, S1, {}> | null;\n\n if (exist) {\n const skipUpdate = (await onBeforeUpdate?.(exist)) === false;\n\n if (skipUpdate) {\n // @ts-ignore\n return { id: exist._id as string, updated: false, created: false };\n }\n\n const updateData = isFunction(update) ? update(exist) : update;\n // @ts-ignore\n const updated = await _db.whereId(exist._id).update(updateData);\n onAfterUpdate?.(updateData, exist);\n\n // @ts-ignore\n return { id: exist._id as string, updated: true, created: false };\n }\n\n await onBeforeCreate?.();\n const createdId = await _db.create(create);\n await onAfterCreate?.(createdId);\n\n return { id: createdId, updated: false, created: true };\n}\n","import type { DbProxy } from './proxy';\nimport type { DbCreate, DbSelect, DbUpdate, DbWhere } from './types';\nimport { dbUpsert } from './upsert';\n\nexport type DbUniqueOptions<T, S extends DbSelect<T>, C extends DbCreate<T>, U extends DbUpdate<T>> = {\n /** 查询条件 */\n where: DbWhere<T>;\n\n /** 创建数据 */\n create: C;\n\n /** 创建前回调函数 */\n onBeforeCreate?: () => unknown;\n\n /**\n * 创建后回调函数\n * @param id 创建的文档ID\n */\n onAfterCreate?: (id: string) => unknown;\n\n /** 用于测试的模拟数据库实例 */\n // biome-ignore lint/suspicious/noExplicitAny: <explanation>\n _mockDbInstance?: any;\n};\n\n/**\n * 数据库 upsert 操作的返回结果类型\n */\nexport type DbUniqueOutput = {\n /** 操作的文档ID */\n id: string;\n /** 是否为创建操作 */\n created: boolean;\n};\n\nexport async function dbUnique<T, S extends DbSelect<T>, C extends DbCreate<T>, U extends DbUpdate<T>>(\n dbProxy: DbProxy<T>,\n options: DbUniqueOptions<T, S, C, U>,\n): Promise<DbUniqueOutput> {\n const { id, created } = await dbUpsert(dbProxy, {\n ...options,\n // @ts-ignore\n update: {},\n onBeforeUpdate: () => false,\n });\n return { id, created };\n}\n","import { tryFlatten } from '@cloudcome/utils-core/try';\nimport { Db } from './_db.class';\nimport type { DbProxy } from './proxy';\n\ntype _TransactionDb = {\n startTransaction: () => Promise<_Transaction>;\n};\n\ntype _Transaction = {\n commit: () => Promise<unknown>;\n rollback: () => Promise<unknown>;\n};\n\nexport type WithTransaction = <D1>(table: DbProxy<D1>) => Db<D1>;\n\n/**\n * 在数据库事务中执行操作\n *\n * @template K - 事务操作返回值类型\n * @param transacting - 事务执行函数,接收事务数据库实例作为参数\n * @param _mockDatabase - 用于测试的模拟数据库对象\n * @param _mockDbInstance - 用于测试的模拟数据库实例\n * @returns 事务操作的返回结果\n *\n * @example\n * ```typescript\n * const result = await dbTransaction(async (withTransaction) => {\n * const userId = await withTransaction(db.table('user')).create({ name: 'John' });\n * const order = await withTransaction(db.table('orders')).create({ userId, amount: 100 });\n * return { user, order };\n * });\n * ```\n */\nexport async function dbTransaction<K>(\n transacting: (withTransaction: WithTransaction) => Promise<K>,\n // biome-ignore lint/suspicious/noExplicitAny: <explanation>\n _mockDatabase?: any,\n // biome-ignore lint/suspicious/noExplicitAny: <explanation>\n _mockDbInstance?: any,\n) {\n const transactionDb = (_mockDatabase || uniCloud.database()) as _TransactionDb;\n\n const [err1, transaction] = await tryFlatten(transactionDb.startTransaction());\n if (err1) throw err1;\n\n const withTransaction: WithTransaction = <D1>(dbProxy: DbProxy<D1>) => {\n return _mockDbInstance || new Db<D1>({ ...dbProxy.options, transaction });\n };\n\n const [err2, result] = await tryFlatten(async () => {\n const result = await transacting(withTransaction);\n await transaction.commit();\n return result;\n });\n\n if (err2) {\n await tryFlatten(transaction.rollback());\n throw err2;\n }\n\n return result as unknown as K;\n}\n"],"names":["isString","isNumber","type","objectMap","objectEach","parseDatabaseOutput","createCloudObjectError","isObject","isFunction","dbProxy","tryFlatten","result"],"mappings":"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"}
@@ -5,3 +5,4 @@ export * from './database/unique';
5
5
  export * from './database/transaction';
6
6
  export * from './database/types';
7
7
  export { parseDatabaseOutput } from './_helpers';
8
+ export type { UniError } from './_types';
package/dist/database.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { isString, isNumber, isArray, isObject, isFunction } from "@cloudcome/utils-core/type";
1
+ import { isString, isNumber, isObject, isFunction } from "@cloudcome/utils-core/type";
2
2
  import { a as parseDatabaseOutput } from "./_helpers.mjs";
3
3
  import { c as createCloudObjectError } from "./error.mjs";
4
4
  import { objectMap, objectEach } from "@cloudcome/utils-core/object";
@@ -174,6 +174,9 @@ class Db {
174
174
  get table() {
175
175
  return this._options.table;
176
176
  }
177
+ get options() {
178
+ return this._options;
179
+ }
177
180
  /**
178
181
  * 获取聚合操作实例
179
182
  * @returns 聚合操作实例
@@ -321,9 +324,13 @@ class Db {
321
324
  if (this._hasLimit) returnAggRef = returnAggRef.limit(this._limit);
322
325
  return returnAggRef;
323
326
  }
324
- _endHost() {
327
+ _endHost(action) {
325
328
  if (this._hasWhere) {
326
- this._host = this._host.where(_mapCommandRaw(this._where));
329
+ if (action === "update" && this._isTransaction) {
330
+ this._host = this._host.doc(this._where._id);
331
+ } else {
332
+ this._host = this._host.where(_mapCommandRaw(this._where));
333
+ }
327
334
  }
328
335
  if (this._hasSelect) {
329
336
  this._host = this._host.field(this._select);
@@ -334,27 +341,31 @@ class Db {
334
341
  });
335
342
  }
336
343
  if (this._hasSkip) this._host = this._host.skip(this._skip);
337
- if (this._hasLimit) this._host = this._host.limit(this._limit);
338
- else if (this._hasWhereId) this._host = this._host.limit(1);
344
+ if (this._hasLimit && action === "query") this._host = this._host.limit(this._limit);
345
+ else if (this._hasWhereId && action === "query") this._host = this._host.limit(1);
339
346
  }
340
347
  /**
341
348
  * 执行查询操作
342
349
  * @returns 查询结果
343
350
  */
344
351
  async query() {
345
- if (this._isTransaction) throw new Error("db.query() 方法不支持事务模式");
346
- let res;
347
- if (this._hasLookup) {
348
- const aggRef = this.aggregate();
349
- this._endAggregate(aggRef);
350
- res = await aggRef.end();
351
- } else {
352
- this._endHost();
353
- res = await this._host.get();
352
+ try {
353
+ if (this._isTransaction) throw new Error("db.query() 方法不支持事务模式");
354
+ let res;
355
+ if (this._hasLookup) {
356
+ const aggRef = this.aggregate();
357
+ this._endAggregate(aggRef);
358
+ res = await aggRef.end();
359
+ } else {
360
+ this._endHost("query");
361
+ res = await this._host.get();
362
+ }
363
+ const { data } = parseDatabaseOutput(res);
364
+ return data;
365
+ } catch (err) {
366
+ const dbErr = err;
367
+ throw this._options.parseError?.(dbErr) || dbErr;
354
368
  }
355
- isArray(res.data) ? res.data : [res.data];
356
- const { data } = parseDatabaseOutput(res);
357
- return data;
358
369
  }
359
370
  async queryOne(allowMiss = false) {
360
371
  if (this._isTransaction) throw new Error("db.queryOne() 方法不支持事务模式");
@@ -362,7 +373,7 @@ class Db {
362
373
  if (!this._hasWhereId) this.limit(1);
363
374
  const data = await this.query();
364
375
  const res = data.at(0);
365
- if (!allowMiss && !res) throw createCloudObjectError("查询数据为空", "queryOneNotFound");
376
+ if (!allowMiss && !res) throw createCloudObjectError("查询数据为空", "queryOneMiss");
366
377
  return res || null;
367
378
  }
368
379
  /**
@@ -375,10 +386,15 @@ class Db {
375
386
  if (this._hasOrder) throw new Error("db.count() 方法不支持 order 条件");
376
387
  if (this._hasSkip) throw new Error("db.count() 方法不支持 skip 条件");
377
388
  if (this._hasLimit) throw new Error("db.count() 方法不支持 limit 条件");
378
- this._endHost();
379
- const res = await this._host.count();
380
- const { total } = parseDatabaseOutput(res);
381
- return total;
389
+ try {
390
+ this._endHost("count");
391
+ const res = await this._host.count();
392
+ const { total } = parseDatabaseOutput(res);
393
+ return total;
394
+ } catch (err) {
395
+ const dbErr = err;
396
+ throw this._options.parseError?.(dbErr) || dbErr;
397
+ }
382
398
  }
383
399
  /**
384
400
  * 创建新记录
@@ -392,10 +408,15 @@ class Db {
392
408
  if (this._hasOrder) throw new Error("db.create() 方法不支持 order 条件");
393
409
  if (this._hasSkip) throw new Error("db.create() 方法不支持 skip 条件");
394
410
  if (this._hasLimit) throw new Error("db.create() 方法不支持 limit 条件");
395
- this._endHost();
396
- const res = await this._host.add(data);
397
- const { id } = parseDatabaseOutput(res);
398
- return id;
411
+ try {
412
+ this._endHost("create");
413
+ const res = await this._host.add(data);
414
+ const { id } = parseDatabaseOutput(res);
415
+ return id;
416
+ } catch (err) {
417
+ const dbErr = err;
418
+ throw this._options.parseError?.(dbErr) || dbErr;
419
+ }
399
420
  }
400
421
  /**
401
422
  * 更新记录
@@ -410,10 +431,15 @@ class Db {
410
431
  if (this._hasSkip) throw new Error("db.update() 方法不支持 skip 条件");
411
432
  if (this._hasLimit) throw new Error("db.update() 方法不支持 limit 条件");
412
433
  if (this._isTransaction && !this._hasWhereId) throw new Error("事务模式下 db.update() 的 where 条件必须是 _id");
413
- this._endHost();
414
- const res = await this._host.update(_mapCommandRaw(data));
415
- const { updated } = parseDatabaseOutput(res);
416
- return updated;
434
+ try {
435
+ this._endHost("update");
436
+ const res = await this._host.update(_mapCommandRaw(data));
437
+ const { updated } = parseDatabaseOutput(res);
438
+ return updated;
439
+ } catch (err) {
440
+ const dbErr = err;
441
+ throw this._options.parseError?.(dbErr) || dbErr;
442
+ }
417
443
  }
418
444
  /**
419
445
  * 删除记录
@@ -427,10 +453,15 @@ class Db {
427
453
  if (this._hasSkip) throw new Error("db.remove() 方法不支持 skip 条件");
428
454
  if (this._hasLimit) throw new Error("db.remove() 方法不支持 limit 条件");
429
455
  if (this._isTransaction && !this._hasWhereId) throw new Error("事务模式下 db.remove() 的 where 条件必须是 _id");
430
- this._endHost();
431
- const res = await this._host.remove();
432
- const { deleted } = parseDatabaseOutput(res);
433
- return deleted;
456
+ try {
457
+ this._endHost("remove");
458
+ const res = await this._host.remove();
459
+ const { deleted } = parseDatabaseOutput(res);
460
+ return deleted;
461
+ } catch (err) {
462
+ const dbErr = err;
463
+ throw this._options.parseError?.(dbErr) || dbErr;
464
+ }
434
465
  }
435
466
  }
436
467
  function _toWhereMethod(whereFrom) {
@@ -444,13 +475,13 @@ function _mapCommandRaw(where) {
444
475
  return isObject(val) && val instanceof DbBaseCommand ? DbBaseCommand.getValue(val, db0) : val;
445
476
  });
446
477
  }
447
- function dbProxy(name) {
478
+ function dbProxy(name, options) {
448
479
  return new Proxy(
449
480
  {},
450
481
  {
451
482
  get(target, prop) {
452
483
  if (prop === "_isProxy") return true;
453
- const table = new Db({ table: name });
484
+ const table = new Db({ table: name, ...options });
454
485
  const tableProp = prop;
455
486
  const ref = table[tableProp];
456
487
  return isFunction(ref) ? ref.bind(table) : ref;
@@ -502,7 +533,7 @@ async function dbTransaction(transacting, _mockDatabase, _mockDbInstance) {
502
533
  const [err1, transaction] = await tryFlatten(transactionDb.startTransaction());
503
534
  if (err1) throw err1;
504
535
  const withTransaction = (dbProxy2) => {
505
- return _mockDbInstance || new Db({ table: dbProxy2.table, transaction });
536
+ return _mockDbInstance || new Db({ ...dbProxy2.options, transaction });
506
537
  };
507
538
  const [err2, result] = await tryFlatten(async () => {
508
539
  const result2 = await transacting(withTransaction);