monsqlize 1.0.0 → 1.0.2

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.
Files changed (61) hide show
  1. package/CHANGELOG.md +92 -2419
  2. package/README.md +630 -1070
  3. package/index.d.ts +252 -15
  4. package/lib/cache.js +8 -8
  5. package/lib/common/validation.js +64 -1
  6. package/lib/connect.js +3 -3
  7. package/lib/errors.js +10 -0
  8. package/lib/index.js +118 -9
  9. package/lib/infrastructure/ssh-tunnel-ssh2.js +211 -0
  10. package/lib/infrastructure/ssh-tunnel.js +40 -0
  11. package/lib/infrastructure/uri-parser.js +35 -0
  12. package/lib/lock/Lock.js +66 -0
  13. package/lib/lock/errors.js +27 -0
  14. package/lib/lock/index.js +12 -0
  15. package/lib/logger.js +1 -1
  16. package/lib/model/examples/test.js +4 -4
  17. package/lib/mongodb/common/accessor-helpers.js +17 -3
  18. package/lib/mongodb/connect.js +68 -13
  19. package/lib/mongodb/index.js +140 -7
  20. package/lib/mongodb/management/collection-ops.js +4 -4
  21. package/lib/mongodb/management/index-ops.js +18 -18
  22. package/lib/mongodb/management/validation-ops.js +3 -3
  23. package/lib/mongodb/queries/aggregate.js +14 -5
  24. package/lib/mongodb/queries/chain.js +52 -45
  25. package/lib/mongodb/queries/count.js +16 -6
  26. package/lib/mongodb/queries/distinct.js +15 -6
  27. package/lib/mongodb/queries/find-and-count.js +22 -13
  28. package/lib/mongodb/queries/find-by-ids.js +5 -5
  29. package/lib/mongodb/queries/find-one-by-id.js +1 -1
  30. package/lib/mongodb/queries/find-one.js +12 -3
  31. package/lib/mongodb/queries/find-page.js +12 -0
  32. package/lib/mongodb/queries/find.js +15 -6
  33. package/lib/mongodb/queries/index.js +1 -0
  34. package/lib/mongodb/queries/watch.js +537 -0
  35. package/lib/mongodb/writes/delete-many.js +20 -11
  36. package/lib/mongodb/writes/delete-one.js +18 -9
  37. package/lib/mongodb/writes/find-one-and-delete.js +19 -10
  38. package/lib/mongodb/writes/find-one-and-replace.js +36 -20
  39. package/lib/mongodb/writes/find-one-and-update.js +36 -20
  40. package/lib/mongodb/writes/increment-one.js +16 -7
  41. package/lib/mongodb/writes/index.js +13 -13
  42. package/lib/mongodb/writes/insert-batch.js +46 -37
  43. package/lib/mongodb/writes/insert-many.js +22 -13
  44. package/lib/mongodb/writes/insert-one.js +18 -9
  45. package/lib/mongodb/writes/replace-one.js +33 -17
  46. package/lib/mongodb/writes/result-handler.js +14 -14
  47. package/lib/mongodb/writes/update-many.js +34 -18
  48. package/lib/mongodb/writes/update-one.js +33 -17
  49. package/lib/mongodb/writes/upsert-one.js +25 -9
  50. package/lib/operators.js +1 -1
  51. package/lib/redis-cache-adapter.js +3 -3
  52. package/lib/slow-query-log/base-storage.js +69 -0
  53. package/lib/slow-query-log/batch-queue.js +96 -0
  54. package/lib/slow-query-log/config-manager.js +195 -0
  55. package/lib/slow-query-log/index.js +237 -0
  56. package/lib/slow-query-log/mongodb-storage.js +323 -0
  57. package/lib/slow-query-log/query-hash.js +38 -0
  58. package/lib/transaction/DistributedCacheLockManager.js +240 -5
  59. package/lib/transaction/Transaction.js +1 -1
  60. package/lib/utils/objectid-converter.js +566 -0
  61. package/package.json +11 -5
package/index.d.ts CHANGED
@@ -51,6 +51,95 @@ declare module 'monsqlize' {
51
51
  // 事务相关类型定义(Transaction API)
52
52
  // ============================================================================
53
53
 
54
+ /**
55
+ * 业务锁配置选项
56
+ * @since v1.4.0
57
+ */
58
+ interface LockOptions {
59
+ /** 锁过期时间(毫秒),默认 10000 */
60
+ ttl?: number;
61
+ /** 获取锁失败时的重试次数,默认 3 */
62
+ retryTimes?: number;
63
+ /** 重试间隔(毫秒),默认 100 */
64
+ retryDelay?: number;
65
+ /** Redis 不可用时是否降级为无锁执行,默认 false */
66
+ fallbackToNoLock?: boolean;
67
+ }
68
+
69
+ /**
70
+ * 锁对象
71
+ * 表示一个已获取的锁,提供释放和续期方法
72
+ * @since v1.4.0
73
+ */
74
+ interface Lock {
75
+ /** 锁的 Key */
76
+ readonly key: string;
77
+ /** 锁的唯一ID */
78
+ readonly lockId: string;
79
+ /** 是否已释放 */
80
+ readonly released: boolean;
81
+
82
+ /**
83
+ * 释放锁
84
+ * @returns Promise<boolean> 是否成功释放
85
+ */
86
+ release(): Promise<boolean>;
87
+
88
+ /**
89
+ * 续期(延长 TTL)
90
+ * @param ttl - 新的过期时间(毫秒),默认使用原TTL
91
+ * @returns Promise<boolean> 是否成功续期
92
+ */
93
+ renew(ttl?: number): Promise<boolean>;
94
+
95
+ /**
96
+ * 检查锁是否仍被持有
97
+ * @returns boolean
98
+ */
99
+ isHeld(): boolean;
100
+
101
+ /**
102
+ * 获取锁持有时间(毫秒)
103
+ * @returns number
104
+ */
105
+ getHoldTime(): number;
106
+ }
107
+
108
+ /**
109
+ * 锁统计信息
110
+ * @since v1.4.0
111
+ */
112
+ interface LockStats {
113
+ /** 成功获取锁的次数 */
114
+ locksAcquired: number;
115
+ /** 成功释放锁的次数 */
116
+ locksReleased: number;
117
+ /** 锁检查次数 */
118
+ lockChecks: number;
119
+ /** 错误次数 */
120
+ errors: number;
121
+ /** 锁键前缀 */
122
+ lockKeyPrefix: string;
123
+ /** 锁最大持续时间 */
124
+ maxDuration: number;
125
+ }
126
+
127
+ /**
128
+ * 锁获取失败错误
129
+ * @since v1.4.0
130
+ */
131
+ class LockAcquireError extends Error {
132
+ readonly code: 'LOCK_ACQUIRE_FAILED';
133
+ }
134
+
135
+ /**
136
+ * 锁超时错误
137
+ * @since v1.4.0
138
+ */
139
+ class LockTimeoutError extends Error {
140
+ readonly code: 'LOCK_TIMEOUT';
141
+ }
142
+
54
143
  /**
55
144
  * MongoDB 事务会话(原生 ClientSession)
56
145
  * @since v0.2.0
@@ -302,6 +391,16 @@ declare module 'monsqlize' {
302
391
  wtimeout?: number; // 写超时时间(毫秒)
303
392
  }
304
393
 
394
+ /**
395
+ * 简化的插入选项(用于简化调用形式)
396
+ */
397
+ interface InsertOneSimplifiedOptions {
398
+ writeConcern?: WriteConcern; // 写确认级别(可选)
399
+ bypassDocumentValidation?: boolean; // 跳过文档验证(可选)
400
+ comment?: string; // 查询注释(用于生产环境日志跟踪)
401
+ session?: any; // 事务会话
402
+ }
403
+
305
404
  interface InsertOneOptions {
306
405
  document: any; // 要插入的文档
307
406
  writeConcern?: WriteConcern; // 写确认级别(可选)
@@ -314,6 +413,17 @@ declare module 'monsqlize' {
314
413
  insertedId: any; // 插入的文档 _id
315
414
  }
316
415
 
416
+ /**
417
+ * 简化的批量插入选项(用于简化调用形式)
418
+ */
419
+ interface InsertManySimplifiedOptions {
420
+ ordered?: boolean; // 是否有序插入(默认 true)
421
+ writeConcern?: WriteConcern; // 写确认级别(可选)
422
+ bypassDocumentValidation?: boolean; // 跳过文档验证(可选)
423
+ comment?: string; // 查询注释(用于生产环境日志跟踪)
424
+ session?: any; // 事务会话
425
+ }
426
+
317
427
  interface InsertManyOptions {
318
428
  documents: any[]; // 要插入的文档数组
319
429
  ordered?: boolean; // 是否有序插入(默认 true)
@@ -484,16 +594,16 @@ declare module 'monsqlize' {
484
594
  driver?: { connected: boolean };
485
595
  }
486
596
 
487
- interface CollectionAccessor {
597
+ interface CollectionAccessor<TSchema = any> {
488
598
  getNamespace(): { iid: string; type: string; db: string; collection: string };
489
599
  dropCollection(): Promise<boolean>;
490
600
  createCollection(name?: string | null, options?: any): Promise<boolean>;
491
601
  createView(viewName: string, source: string, pipeline?: any[]): Promise<boolean>;
492
602
 
493
- // findOne 重载:支持 meta 参数
494
- findOne(query?: any, options?: Omit<FindOptions, 'meta'>): Promise<any | null>;
495
- findOne(query: any, options: FindOptions & { meta: true | MetaOptions }): Promise<ResultWithMeta<any | null>>;
496
- findOne(query?: any, options?: FindOptions): Promise<any | null | ResultWithMeta<any | null>>;
603
+ // findOne 重载:支持 meta 参数和泛型
604
+ findOne<T = TSchema>(query?: any, options?: Omit<FindOptions, 'meta'>): Promise<T | null>;
605
+ findOne<T = TSchema>(query: any, options: FindOptions & { meta: true | MetaOptions }): Promise<ResultWithMeta<T | null>>;
606
+ findOne<T = TSchema>(query?: any, options?: FindOptions): Promise<T | null | ResultWithMeta<T | null>>;
497
607
 
498
608
  /**
499
609
  * 通过 _id 查询单个文档(便利方法)
@@ -563,9 +673,9 @@ u /**
563
673
  ): Promise<any[]>;
564
674
 
565
675
  // find 重载:支持 meta 参数和链式调用 (v2.0+)
566
- find<T = any>(query?: any): FindChain<T>;
567
- find<T = any>(query: any, options: FindOptions & { meta: true | MetaOptions }): Promise<ResultWithMeta<T[]>>;
568
- find<T = any>(query?: any, options?: FindOptions): Promise<T[]> | FindChain<T> | ResultWithMeta<T[]>;
676
+ find<T = TSchema>(query?: any): FindChain<T>;
677
+ find<T = TSchema>(query: any, options: FindOptions & { meta: true | MetaOptions }): Promise<ResultWithMeta<T[]>>;
678
+ find<T = TSchema>(query?: any, options?: FindOptions): Promise<T[]> | FindChain<T> | ResultWithMeta<T[]>;
569
679
 
570
680
  // count 重载:支持 meta 参数
571
681
  count(query?: any, options?: Omit<CountOptions, 'meta'>): Promise<number>;
@@ -573,9 +683,9 @@ u /**
573
683
  count(query?: any, options?: CountOptions): Promise<number | ResultWithMeta<number>>;
574
684
 
575
685
  // aggregate 重载:支持 meta 参数和链式调用 (v2.0+)
576
- aggregate<T = any>(pipeline?: any[]): AggregateChain<T>;
577
- aggregate<T = any>(pipeline: any[], options: AggregateOptions & { meta: true | MetaOptions }): Promise<ResultWithMeta<T[]>>;
578
- aggregate<T = any>(pipeline?: any[], options?: AggregateOptions): Promise<T[]> | AggregateChain<T> | ResultWithMeta<T[]>;
686
+ aggregate<T = TSchema>(pipeline?: any[]): AggregateChain<T>;
687
+ aggregate<T = TSchema>(pipeline: any[], options: AggregateOptions & { meta: true | MetaOptions }): Promise<ResultWithMeta<T[]>>;
688
+ aggregate<T = TSchema>(pipeline?: any[], options?: AggregateOptions): Promise<T[]> | AggregateChain<T> | ResultWithMeta<T[]>;
579
689
 
580
690
  // distinct 重载:支持 meta 参数
581
691
  distinct<T = any>(field: string, query?: any, options?: Omit<DistinctOptions, 'meta'>): Promise<T[]>;
@@ -594,10 +704,13 @@ u /**
594
704
  clearBookmarks(keyDims?: BookmarkKeyDims): Promise<ClearBookmarksResult>;
595
705
 
596
706
  // findPage:已在 PageResult 中包含 meta 字段,无需重载
597
- findPage(options: FindPageOptions): Promise<PageResult>;
707
+ findPage<T = TSchema>(options: FindPageOptions): Promise<PageResult<T>>;
598
708
 
599
- // 写入操作
709
+ // 写入操作 - 支持简化调用和完整配置
710
+ insertOne<T = TSchema>(document: T, options?: InsertOneSimplifiedOptions): Promise<InsertOneResult>;
600
711
  insertOne(options: InsertOneOptions): Promise<InsertOneResult>;
712
+
713
+ insertMany<T = TSchema>(documents: T[], options?: InsertManySimplifiedOptions): Promise<InsertManyResult>;
601
714
  insertMany(options: InsertManyOptions): Promise<InsertManyResult>;
602
715
 
603
716
  /**
@@ -672,8 +785,8 @@ u /**
672
785
  }
673
786
 
674
787
  type DbAccessor = {
675
- collection: (name: string) => CollectionAccessor;
676
- db: (dbName: string) => { collection: (name: string) => CollectionAccessor };
788
+ collection<TSchema = any>(name: string): CollectionAccessor<TSchema>;
789
+ db(dbName: string): { collection<TSchema = any>(name: string): CollectionAccessor<TSchema> };
677
790
  };
678
791
 
679
792
  export default class MonSQLize {
@@ -713,6 +826,46 @@ u /**
713
826
  /** 健康检查 */
714
827
  health(): Promise<HealthView>;
715
828
 
829
+ /**
830
+ * 获取慢查询日志(持久化存储)
831
+ * @param filter - 查询条件(可选)
832
+ * @param options - 查询选项(可选)
833
+ * @returns 慢查询日志数组
834
+ * @since v1.3.1
835
+ * @example
836
+ * // 查询所有慢查询
837
+ * const logs = await msq.getSlowQueryLogs({}, { limit: 10 });
838
+ *
839
+ * // 按collection过滤
840
+ * const userLogs = await msq.getSlowQueryLogs(
841
+ * { collection: 'users' },
842
+ * { sort: { count: -1 }, limit: 10 }
843
+ * );
844
+ *
845
+ * // 按操作类型过滤
846
+ * const findLogs = await msq.getSlowQueryLogs({ operation: 'find' });
847
+ */
848
+ getSlowQueryLogs(
849
+ filter?: Record<string, any>,
850
+ options?: {
851
+ sort?: Record<string, 1 | -1>;
852
+ limit?: number;
853
+ skip?: number;
854
+ }
855
+ ): Promise<Array<{
856
+ queryHash: string;
857
+ database: string;
858
+ collection: string;
859
+ operation: string;
860
+ count: number;
861
+ totalTimeMs: number;
862
+ avgTimeMs: number;
863
+ maxTimeMs: number;
864
+ minTimeMs: number;
865
+ firstSeen: Date;
866
+ lastSeen: Date;
867
+ }>>;
868
+
716
869
  /**
717
870
  * 创建手动事务会话
718
871
  * @param options - 事务选项
@@ -745,6 +898,90 @@ u /**
745
898
  callback: (transaction: Transaction) => Promise<T>,
746
899
  options?: TransactionOptions
747
900
  ): Promise<T>;
901
+
902
+ // ============================================================================
903
+ // 业务锁 API (v1.4.0+)
904
+ // ============================================================================
905
+
906
+ /**
907
+ * 业务锁:自动管理锁生命周期(推荐)
908
+ * @param key - 锁的唯一标识
909
+ * @param callback - 获取锁后执行的函数
910
+ * @param options - 锁选项
911
+ * @returns callback 的返回值
912
+ * @since v1.4.0
913
+ * @example
914
+ * // 库存扣减
915
+ * await db.withLock('inventory:SKU123', async () => {
916
+ * const product = await inventory.findOne({ sku: 'SKU123' });
917
+ * if (product.stock >= 1) {
918
+ * await inventory.updateOne({ sku: 'SKU123' }, { $inc: { stock: -1 } });
919
+ * }
920
+ * });
921
+ */
922
+ withLock?<T = any>(
923
+ key: string,
924
+ callback: () => Promise<T>,
925
+ options?: LockOptions
926
+ ): Promise<T>;
927
+
928
+ /**
929
+ * 业务锁:手动获取锁(阻塞重试)
930
+ * @param key - 锁的唯一标识
931
+ * @param options - 锁选项
932
+ * @returns Lock 对象
933
+ * @since v1.4.0
934
+ * @example
935
+ * const lock = await db.acquireLock('resource:123', { ttl: 5000 });
936
+ * try {
937
+ * // 业务逻辑
938
+ * } finally {
939
+ * await lock.release();
940
+ * }
941
+ */
942
+ acquireLock?(key: string, options?: LockOptions): Promise<Lock>;
943
+
944
+ /**
945
+ * 业务锁:尝试获取锁(不阻塞)
946
+ * @param key - 锁的唯一标识
947
+ * @param options - 锁选项(不包含 retryTimes)
948
+ * @returns Lock 对象或 null
949
+ * @since v1.4.0
950
+ * @example
951
+ * const lock = await db.tryAcquireLock('resource:123');
952
+ * if (lock) {
953
+ * try {
954
+ * // 业务逻辑
955
+ * } finally {
956
+ * await lock.release();
957
+ * }
958
+ * } else {
959
+ * console.log('资源被占用');
960
+ * }
961
+ */
962
+ tryAcquireLock?(key: string, options?: Omit<LockOptions, 'retryTimes'>): Promise<Lock | null>;
963
+
964
+ /**
965
+ * 获取锁统计信息
966
+ * @returns 锁统计信息
967
+ * @since v1.4.0
968
+ * @example
969
+ * const stats = db.getLockStats();
970
+ * console.log(stats.locksAcquired, stats.locksReleased);
971
+ */
972
+ getLockStats?(): LockStats;
973
+
974
+ /**
975
+ * 创建 Redis 缓存适配器(静态方法)
976
+ * @param client - Redis 客户端实例(ioredis)
977
+ * @param options - 可选配置
978
+ * @returns Redis 缓存适配器实例
979
+ * @example
980
+ * const Redis = require('ioredis');
981
+ * const redis = new Redis();
982
+ * const redisCache = MonSQLize.createRedisCacheAdapter(redis);
983
+ */
984
+ static createRedisCacheAdapter(client: any, options?: any): CacheLike;
748
985
  }
749
986
 
750
987
  // ============================================================================
package/lib/cache.js CHANGED
@@ -13,7 +13,7 @@ class Cache {
13
13
  enableStats: options.enableStats !== false, // 启用统计信息
14
14
  ...options
15
15
  };
16
-
16
+
17
17
  // 统计信息
18
18
  this.stats = {
19
19
  hits: 0,
@@ -141,13 +141,13 @@ class Cache {
141
141
  async delPattern(pattern) {
142
142
  const regex = this._patternToRegex(pattern);
143
143
  const keysToDelete = [];
144
-
144
+
145
145
  for (const key of this.cache.keys()) {
146
146
  if (regex.test(key)) {
147
147
  keysToDelete.push(key);
148
148
  }
149
149
  }
150
-
150
+
151
151
 
152
152
  return await this.delMany(keysToDelete);
153
153
  }
@@ -231,7 +231,7 @@ class Cache {
231
231
  _estimateSize(key, value) {
232
232
  const keySize = typeof key === 'string' ? key.length * 2 : 8;
233
233
  let valueSize = 8; // 默认值
234
-
234
+
235
235
  if (typeof value === 'string') {
236
236
  valueSize = value.length * 2;
237
237
  } else if (typeof value === 'object' && value !== null) {
@@ -241,7 +241,7 @@ class Cache {
241
241
  valueSize = 100; // 估算值
242
242
  }
243
243
  }
244
-
244
+
245
245
  return keySize + valueSize;
246
246
  }
247
247
 
@@ -471,7 +471,7 @@ module.exports = class CacheFactory {
471
471
  return (op, base = {}, fetcher) => {
472
472
  // 检查是否在事务中
473
473
  const inTransaction = base.session && base.session.__monSQLizeTransaction;
474
-
474
+
475
475
  // 事务内默认不缓存(除非显式指定 cache)
476
476
  let ttl = 0;
477
477
  if (inTransaction) {
@@ -481,11 +481,11 @@ module.exports = class CacheFactory {
481
481
  // 非事务:正常处理 cache 参数
482
482
  ttl = base.cache ? Number(base.cache) : 0;
483
483
  }
484
-
484
+
485
485
  // 使用浅拷贝构建用于键的对象,避免修改调用方入参
486
486
  const { cache: _cacheTTL, maxTimeMS: _maxTimeMS, session: _session, ...keyBase } = base || {};
487
487
  const key = this.buildCacheKey({ ...ctx, op, base: keyBase });
488
488
  return this.readThrough(cache, ttl, key, fetcher);
489
489
  };
490
490
  }
491
- }
491
+ };
@@ -46,4 +46,67 @@ function assertCursorSortCompatible(currentSort, cursorSort) {
46
46
  }
47
47
  }
48
48
 
49
- module.exports = { validateLimitAfterBefore, assertCursorSortCompatible };
49
+ /**
50
+ * 验证数值范围
51
+ * @param {number} value - 要验证的数值
52
+ * @param {number} min - 最小值(包含)
53
+ * @param {number} max - 最大值(包含)
54
+ * @param {string} name - 参数名称(用于错误消息)
55
+ * @returns {number} 验证通过后的值
56
+ * @throws {Error} 当值不在有效范围内时抛出 INVALID_ARGUMENT 错误
57
+ */
58
+ function validateRange(value, min, max, name) {
59
+ const { ErrorCodes, createError } = require('../errors');
60
+
61
+ // 检查是否为有效数字
62
+ if (typeof value !== 'number' || isNaN(value)) {
63
+ throw createError(
64
+ ErrorCodes.INVALID_ARGUMENT,
65
+ `${name} 必须是一个有效的数字`
66
+ );
67
+ }
68
+
69
+ // 检查是否为有限数(排除 Infinity)
70
+ if (!isFinite(value)) {
71
+ throw createError(
72
+ ErrorCodes.INVALID_ARGUMENT,
73
+ `${name} 必须是有限数字`
74
+ );
75
+ }
76
+
77
+ // 检查范围
78
+ if (value < min || value > max) {
79
+ throw createError(
80
+ ErrorCodes.INVALID_ARGUMENT,
81
+ `${name} 必须在 ${min} 到 ${max} 之间,当前值: ${value}`
82
+ );
83
+ }
84
+
85
+ return value;
86
+ }
87
+
88
+ /**
89
+ * 验证正整数
90
+ * @param {number} value - 要验证的数值
91
+ * @param {string} name - 参数名称(用于错误消息)
92
+ * @returns {number} 验证通过后的值
93
+ * @throws {Error} 当值不是正整数时抛出错误
94
+ */
95
+ function validatePositiveInteger(value, name) {
96
+ const { ErrorCodes, createError } = require('../errors');
97
+
98
+ if (!Number.isInteger(value) || value <= 0) {
99
+ throw createError(
100
+ ErrorCodes.INVALID_ARGUMENT,
101
+ `${name} 必须是正整数,当前值: ${value}`
102
+ );
103
+ }
104
+ return value;
105
+ }
106
+
107
+ module.exports = {
108
+ validateLimitAfterBefore,
109
+ assertCursorSortCompatible,
110
+ validateRange,
111
+ validatePositiveInteger
112
+ };
package/lib/connect.js CHANGED
@@ -68,9 +68,9 @@ module.exports = class ConnectionManager {
68
68
  const db = (databaseName)=>{
69
69
  return {
70
70
  collection:(collectionName)=>instance.collection(databaseName, collectionName)
71
- }
72
- }
71
+ };
72
+ };
73
73
 
74
74
  return { collection, db, instance };
75
75
  }
76
- }
76
+ };
package/lib/errors.js CHANGED
@@ -43,6 +43,10 @@ const ErrorCodes = {
43
43
  DOCUMENTS_REQUIRED: 'DOCUMENTS_REQUIRED',
44
44
  DUPLICATE_KEY: 'DUPLICATE_KEY',
45
45
  WRITE_CONFLICT: 'WRITE_CONFLICT',
46
+
47
+ // 🆕 v1.4.0: 锁相关错误
48
+ LOCK_ACQUIRE_FAILED: 'LOCK_ACQUIRE_FAILED',
49
+ LOCK_TIMEOUT: 'LOCK_TIMEOUT',
46
50
  };
47
51
 
48
52
  /**
@@ -145,6 +149,9 @@ function createWriteError(operation, message, cause = null) {
145
149
  );
146
150
  }
147
151
 
152
+ // 🆕 v1.4.0: 导入锁错误类
153
+ const { LockAcquireError, LockTimeoutError } = require('./lock/errors');
154
+
148
155
  module.exports = {
149
156
  ErrorCodes,
150
157
  createError,
@@ -153,5 +160,8 @@ module.exports = {
153
160
  createConnectionError,
154
161
  createQueryTimeoutError,
155
162
  createWriteError,
163
+ // 🆕 v1.4.0: 锁错误类
164
+ LockAcquireError,
165
+ LockTimeoutError,
156
166
  };
157
167