monsqlize 1.3.0 → 2.0.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.
Files changed (172) hide show
  1. package/CHANGELOG.md +56 -60
  2. package/LICENSE +201 -21
  3. package/README.md +537 -1828
  4. package/changelogs/README.md +160 -0
  5. package/changelogs/v2.0.0.md +222 -0
  6. package/dist/cjs/index.cjs +10600 -0
  7. package/dist/cjs/mongodb/common/transaction-aware.cjs +10 -0
  8. package/dist/cjs/transaction/CacheLockManager.cjs +100 -0
  9. package/dist/cjs/transaction/Transaction.cjs +158 -0
  10. package/dist/cjs/transaction/TransactionManager.cjs +298 -0
  11. package/dist/esm/index.mjs +10650 -0
  12. package/dist/types/base.d.ts +81 -0
  13. package/dist/types/collection.d.ts +1031 -0
  14. package/dist/types/expression.d.ts +115 -0
  15. package/dist/types/index.d.ts +23 -0
  16. package/dist/types/lock.d.ts +74 -0
  17. package/dist/types/model.d.ts +526 -0
  18. package/dist/types/mongodb.d.ts +49 -0
  19. package/dist/types/monsqlize.d.ts +491 -0
  20. package/dist/types/pool.d.ts +84 -0
  21. package/dist/types/runtime.d.ts +362 -0
  22. package/dist/types/saga.d.ts +143 -0
  23. package/dist/types/slow-query-log.d.ts +126 -0
  24. package/dist/types/sync.d.ts +103 -0
  25. package/dist/types/transaction.d.ts +132 -0
  26. package/package.json +67 -69
  27. package/index.d.ts +0 -206
  28. package/index.mjs +0 -52
  29. package/lib/cache-invalidation.js +0 -279
  30. package/lib/cache.js +0 -530
  31. package/lib/common/cursor.js +0 -59
  32. package/lib/common/docs-urls.js +0 -73
  33. package/lib/common/index-options.js +0 -223
  34. package/lib/common/log.js +0 -61
  35. package/lib/common/namespace.js +0 -22
  36. package/lib/common/normalize.js +0 -34
  37. package/lib/common/page-result.js +0 -43
  38. package/lib/common/runner.js +0 -57
  39. package/lib/common/server-features.js +0 -232
  40. package/lib/common/shape-builders.js +0 -27
  41. package/lib/common/validation.js +0 -113
  42. package/lib/connect.js +0 -99
  43. package/lib/constants.js +0 -55
  44. package/lib/count-queue.js +0 -188
  45. package/lib/distributed-cache-invalidator.js +0 -260
  46. package/lib/errors.js +0 -168
  47. package/lib/expression/cache/ExpressionCache.js +0 -114
  48. package/lib/expression/compiler/ExpressionCompiler.js +0 -1090
  49. package/lib/expression/compiler/ExpressionCompilerExtensions.js +0 -531
  50. package/lib/expression/detector.js +0 -84
  51. package/lib/expression/factory.js +0 -29
  52. package/lib/expression/index.js +0 -19
  53. package/lib/function-cache.js +0 -533
  54. package/lib/index.js +0 -1251
  55. package/lib/infrastructure/ConnectionPoolManager.js +0 -464
  56. package/lib/infrastructure/HealthChecker.js +0 -281
  57. package/lib/infrastructure/PoolConfig.js +0 -199
  58. package/lib/infrastructure/PoolSelector.js +0 -225
  59. package/lib/infrastructure/PoolStats.js +0 -244
  60. package/lib/infrastructure/ssh-tunnel-ssh2.js +0 -212
  61. package/lib/infrastructure/ssh-tunnel.js +0 -41
  62. package/lib/infrastructure/uri-parser.js +0 -36
  63. package/lib/lock/Lock.js +0 -67
  64. package/lib/lock/errors.js +0 -28
  65. package/lib/lock/index.js +0 -13
  66. package/lib/logger.js +0 -225
  67. package/lib/model/examples/test.js +0 -311
  68. package/lib/model/features/defaults.js +0 -161
  69. package/lib/model/features/populate.js +0 -568
  70. package/lib/model/features/relations.js +0 -120
  71. package/lib/model/features/soft-delete.js +0 -349
  72. package/lib/model/features/version.js +0 -157
  73. package/lib/model/features/virtuals.js +0 -219
  74. package/lib/model/index.js +0 -1265
  75. package/lib/mongodb/common/accessor-helpers.js +0 -59
  76. package/lib/mongodb/common/agg-pipeline.js +0 -36
  77. package/lib/mongodb/common/aggregation-validator.js +0 -127
  78. package/lib/mongodb/common/iid.js +0 -28
  79. package/lib/mongodb/common/lexicographic-expr.js +0 -53
  80. package/lib/mongodb/common/shape.js +0 -32
  81. package/lib/mongodb/common/sort.js +0 -39
  82. package/lib/mongodb/common/transaction-aware.js +0 -25
  83. package/lib/mongodb/connect.js +0 -234
  84. package/lib/mongodb/index.js +0 -639
  85. package/lib/mongodb/management/admin-ops.js +0 -200
  86. package/lib/mongodb/management/bookmark-ops.js +0 -167
  87. package/lib/mongodb/management/cache-ops.js +0 -50
  88. package/lib/mongodb/management/collection-ops.js +0 -387
  89. package/lib/mongodb/management/database-ops.js +0 -202
  90. package/lib/mongodb/management/index-ops.js +0 -475
  91. package/lib/mongodb/management/index.js +0 -17
  92. package/lib/mongodb/management/namespace.js +0 -31
  93. package/lib/mongodb/management/validation-ops.js +0 -268
  94. package/lib/mongodb/queries/aggregate.js +0 -172
  95. package/lib/mongodb/queries/chain.js +0 -631
  96. package/lib/mongodb/queries/count.js +0 -99
  97. package/lib/mongodb/queries/distinct.js +0 -78
  98. package/lib/mongodb/queries/find-and-count.js +0 -193
  99. package/lib/mongodb/queries/find-by-ids.js +0 -236
  100. package/lib/mongodb/queries/find-one-by-id.js +0 -171
  101. package/lib/mongodb/queries/find-one.js +0 -71
  102. package/lib/mongodb/queries/find-page.js +0 -618
  103. package/lib/mongodb/queries/find.js +0 -171
  104. package/lib/mongodb/queries/index.js +0 -51
  105. package/lib/mongodb/queries/watch.js +0 -538
  106. package/lib/mongodb/writes/common/batch-retry.js +0 -65
  107. package/lib/mongodb/writes/delete-batch.js +0 -323
  108. package/lib/mongodb/writes/delete-many.js +0 -181
  109. package/lib/mongodb/writes/delete-one.js +0 -173
  110. package/lib/mongodb/writes/find-one-and-delete.js +0 -203
  111. package/lib/mongodb/writes/find-one-and-replace.js +0 -239
  112. package/lib/mongodb/writes/find-one-and-update.js +0 -240
  113. package/lib/mongodb/writes/increment-one.js +0 -259
  114. package/lib/mongodb/writes/index.js +0 -46
  115. package/lib/mongodb/writes/insert-batch.js +0 -508
  116. package/lib/mongodb/writes/insert-many.js +0 -223
  117. package/lib/mongodb/writes/insert-one.js +0 -169
  118. package/lib/mongodb/writes/replace-one.js +0 -226
  119. package/lib/mongodb/writes/result-handler.js +0 -237
  120. package/lib/mongodb/writes/update-batch.js +0 -416
  121. package/lib/mongodb/writes/update-many.js +0 -275
  122. package/lib/mongodb/writes/update-one.js +0 -273
  123. package/lib/mongodb/writes/upsert-one.js +0 -203
  124. package/lib/multi-level-cache.js +0 -244
  125. package/lib/operators.js +0 -330
  126. package/lib/redis-cache-adapter.js +0 -267
  127. package/lib/saga/SagaContext.js +0 -67
  128. package/lib/saga/SagaDefinition.js +0 -32
  129. package/lib/saga/SagaExecutor.js +0 -201
  130. package/lib/saga/SagaOrchestrator.js +0 -186
  131. package/lib/saga/index.js +0 -11
  132. package/lib/slow-query-log/base-storage.js +0 -70
  133. package/lib/slow-query-log/batch-queue.js +0 -97
  134. package/lib/slow-query-log/config-manager.js +0 -196
  135. package/lib/slow-query-log/index.js +0 -238
  136. package/lib/slow-query-log/mongodb-storage.js +0 -324
  137. package/lib/slow-query-log/query-hash.js +0 -39
  138. package/lib/sync/ChangeStreamSyncManager.js +0 -405
  139. package/lib/sync/ResumeTokenStore.js +0 -192
  140. package/lib/sync/SyncConfig.js +0 -127
  141. package/lib/sync/SyncTarget.js +0 -240
  142. package/lib/sync/index.js +0 -20
  143. package/lib/transaction/CacheLockManager.js +0 -162
  144. package/lib/transaction/DistributedCacheLockManager.js +0 -475
  145. package/lib/transaction/Transaction.js +0 -315
  146. package/lib/transaction/TransactionManager.js +0 -267
  147. package/lib/transaction/index.js +0 -11
  148. package/lib/utils/objectid-converter.js +0 -632
  149. package/types/README.md +0 -122
  150. package/types/base.ts +0 -94
  151. package/types/batch.ts +0 -187
  152. package/types/cache.ts +0 -71
  153. package/types/chain.ts +0 -254
  154. package/types/collection.ts +0 -357
  155. package/types/expression.ts +0 -109
  156. package/types/function-cache.d.ts +0 -135
  157. package/types/lock.ts +0 -95
  158. package/types/model/definition.ts +0 -152
  159. package/types/model/index.ts +0 -10
  160. package/types/model/instance.ts +0 -121
  161. package/types/model/relations.ts +0 -121
  162. package/types/model/virtuals.ts +0 -32
  163. package/types/monsqlize.ts +0 -245
  164. package/types/options.ts +0 -192
  165. package/types/pagination.ts +0 -154
  166. package/types/pool.ts +0 -125
  167. package/types/query.ts +0 -71
  168. package/types/saga.ts +0 -125
  169. package/types/stream.ts +0 -64
  170. package/types/sync.ts +0 -79
  171. package/types/transaction.ts +0 -79
  172. package/types/write.ts +0 -77
package/lib/logger.js DELETED
@@ -1,225 +0,0 @@
1
- /**
2
- * 默认日志记录器工具类
3
- * 提供标准的日志记录功能,支持不同级别的日志输出
4
- *
5
- * v2.0 新增功能:
6
- * - traceId 支持(用于分布式追踪)
7
- * - 结构化日志输出(JSON 格式)
8
- * - 上下文信息(数据库、集合、操作等)
9
- */
10
-
11
- const crypto = require('crypto');
12
-
13
- /**
14
- * 生成唯一的 traceId
15
- * @returns {string} 16 字符的唯一 ID
16
- */
17
- function generateTraceId() {
18
- return crypto.randomBytes(8).toString('hex');
19
- }
20
-
21
- /**
22
- * 异步本地存储(用于在异步调用链中传递 traceId)
23
- */
24
- let AsyncLocalStorage;
25
- try {
26
- AsyncLocalStorage = require('async_hooks').AsyncLocalStorage;
27
- } catch (e) {
28
- // Node.js < 12.17.0 不支持 AsyncLocalStorage
29
- AsyncLocalStorage = null;
30
- }
31
-
32
- const traceStorage = AsyncLocalStorage ? new AsyncLocalStorage() : null;
33
-
34
- module.exports = class Logger {
35
-
36
- /**
37
- * 创建日志记录器实例
38
- * @param {Object} [customLogger] - 自定义日志记录器
39
- * @param {Function} customLogger.debug - debug级别日志方法
40
- * @param {Function} customLogger.info - info级别日志方法
41
- * @param {Function} customLogger.warn - warn级别日志方法
42
- * @param {Function} customLogger.error - error级别日志方法
43
- * @param {Object} [options] - 日志选项
44
- * @param {boolean} [options.structured=false] - 是否使用结构化日志(JSON)
45
- * @param {boolean} [options.enableTraceId=false] - 是否启用 traceId
46
- * @returns {Object} 日志记录器对象
47
- */
48
- static create(customLogger, options = {}) {
49
- if (customLogger && this.isValidLogger(customLogger)) {
50
- // 如果提供自定义 logger,包装它以支持新特性
51
- return this.wrapLogger(customLogger, options);
52
- }
53
-
54
- return this.createDefaultLogger(options);
55
- }
56
-
57
- /**
58
- * 验证自定义日志记录器是否有效
59
- * @param {Object} logger - 待验证的日志记录器
60
- * @returns {boolean} 是否为有效的日志记录器
61
- */
62
- static isValidLogger(logger) {
63
- const requiredMethods = ['debug', 'info', 'warn', 'error'];
64
- return requiredMethods.every(method =>
65
- typeof logger[method] === 'function'
66
- );
67
- }
68
-
69
- /**
70
- * 包装自定义 logger 以支持新特性
71
- * @param {Object} baseLogger - 基础 logger
72
- * @param {Object} options - 选项
73
- * @returns {Object} 包装后的 logger
74
- */
75
- static wrapLogger(baseLogger, options = {}) {
76
- const { structured = false, enableTraceId = false } = options;
77
-
78
- const wrap = (level) => (msg, ...args) => {
79
- const logData = this._prepareLogData(level, msg, args, { structured, enableTraceId });
80
-
81
- if (structured) {
82
- baseLogger[level](JSON.stringify(logData));
83
- } else {
84
- const prefix = enableTraceId && logData.traceId ? `[${logData.traceId}] ` : '';
85
- baseLogger[level](`${prefix}${msg}`, ...args);
86
- }
87
- };
88
-
89
- return {
90
- debug: wrap('debug'),
91
- info: wrap('info'),
92
- warn: wrap('warn'),
93
- error: wrap('error'),
94
- // 暴露 traceId 管理方法
95
- withTraceId: enableTraceId ? this.withTraceId : undefined,
96
- getTraceId: enableTraceId ? this.getTraceId : undefined,
97
- };
98
- }
99
-
100
- /**
101
- * 准备日志数据
102
- * @private
103
- */
104
- static _prepareLogData(level, msg, args, options) {
105
- const logData = {
106
- timestamp: new Date().toISOString(),
107
- level: level.toUpperCase(),
108
- message: msg,
109
- };
110
-
111
- // 添加 traceId
112
- if (options.enableTraceId) {
113
- const traceId = this.getTraceId();
114
- if (traceId) logData.traceId = traceId;
115
- }
116
-
117
- // 处理额外参数(上下文信息)
118
- if (args.length > 0) {
119
- const context = args[0];
120
- if (context && typeof context === 'object') {
121
- logData.context = context;
122
- }
123
- }
124
-
125
- return logData;
126
- }
127
-
128
- /**
129
- * 创建默认的控制台日志记录器
130
- * @param {Object} [options] - 日志选项
131
- * @returns {Object} 默认日志记录器对象
132
- */
133
- static createDefaultLogger(options = {}) {
134
- const { structured = false, enableTraceId = false } = options;
135
-
136
- const createLogFn = (level, consoleFn) => {
137
- return (msg, ...args) => {
138
- const logData = this._prepareLogData(level, msg, args, { structured, enableTraceId });
139
-
140
- if (structured) {
141
- consoleFn(JSON.stringify(logData));
142
- } else {
143
- const prefix = enableTraceId && logData.traceId ? `[${logData.traceId}] ` : '';
144
- consoleFn(`[${level.toUpperCase()}] ${prefix}${msg}`, ...args);
145
- }
146
- };
147
- };
148
-
149
- return {
150
- debug: createLogFn('debug', console.debug),
151
- info: createLogFn('info', console.log),
152
- warn: createLogFn('warn', console.warn),
153
- error: createLogFn('error', console.error),
154
- // 暴露 traceId 管理方法
155
- withTraceId: enableTraceId ? this.withTraceId.bind(this) : undefined,
156
- getTraceId: enableTraceId ? this.getTraceId.bind(this) : undefined,
157
- };
158
- }
159
-
160
- /**
161
- * 创建带时间戳的日志记录器
162
- * @param {Object} [customLogger] - 自定义日志记录器
163
- * @returns {Object} 带时间戳的日志记录器
164
- */
165
- static createWithTimestamp(customLogger) {
166
- const baseLogger = this.create(customLogger);
167
- const getTimestamp = () => new Date().toISOString();
168
-
169
- return {
170
- debug: (msg, ...args) => baseLogger.debug(`${getTimestamp()} ${msg}`, ...args),
171
- info: (msg, ...args) => baseLogger.info(`${getTimestamp()} ${msg}`, ...args),
172
- warn: (msg, ...args) => baseLogger.warn(`${getTimestamp()} ${msg}`, ...args),
173
- error: (msg, ...args) => baseLogger.error(`${getTimestamp()} ${msg}`, ...args)
174
- };
175
- }
176
-
177
- /**
178
- * 创建静默日志记录器(不输出任何内容)
179
- * @returns {Object} 静默日志记录器
180
- */
181
- static createSilent() {
182
- const noop = () => {};
183
- return {
184
- debug: noop,
185
- info: noop,
186
- warn: noop,
187
- error: noop
188
- };
189
- }
190
-
191
- /**
192
- * 在指定的 traceId 上下文中运行函数
193
- * @param {Function} fn - 要执行的函数
194
- * @param {string} [traceId] - 可选的 traceId,不提供则自动生成
195
- * @returns {*} 函数执行结果
196
- */
197
- static withTraceId(fn, traceId = null) {
198
- if (!traceStorage) {
199
- // 不支持 AsyncLocalStorage,直接执行
200
- return fn();
201
- }
202
-
203
- const id = traceId || generateTraceId();
204
- return traceStorage.run(id, fn);
205
- }
206
-
207
- /**
208
- * 获取当前上下文的 traceId
209
- * @returns {string|null} traceId 或 null
210
- */
211
- static getTraceId() {
212
- if (!traceStorage) return null;
213
- return traceStorage.getStore() || null;
214
- }
215
-
216
- /**
217
- * 生成新的 traceId
218
- * @returns {string} 新的 traceId
219
- */
220
- static generateTraceId() {
221
- return generateTraceId();
222
- }
223
- };
224
-
225
-
@@ -1,311 +0,0 @@
1
- /**
2
- * Model 定义示例模板
3
- *
4
- * 使用说明:
5
- * 1. enums - 枚举配置可被外部代码直接访问
6
- * 例如:UserModel.enums.role
7
- *
8
- * 2. schema - 由 schema-dsl 包提供验证能力
9
- * 使用 function 定义时,this 自动绑定到当前模型定义对象
10
- * 例如:UserModel.schema(dsl) 时,this === UserModel
11
- *
12
- * 3. methods/hooks - 接收 model 实例作为参数
13
- * 可以调用 model 的所有查询方法
14
- *
15
- * 注意:这是 API 设计示例,展示:
16
- * - schema 中 this.enums 引用同一对象内的枚举配置
17
- * - methods 通过参数接收 model 实例
18
- * - hooks 通过 ctx 上下文传递状态(如事务)
19
- */
20
-
21
- module.exports = {
22
-
23
- // 枚举配置(可被外部代码直接访问)
24
- enums: {
25
- role: 'admin|user',
26
- status: 'active|inactive|banned'
27
- },
28
-
29
- // 定义 schema(使用 function 时,this 自动绑定到当前对象)
30
- schema: function(dsl) {
31
- return dsl({
32
- username: 'string:3-32!',
33
- password: 'string!'.pattern(/^[a-zA-Z0-9]{6,30}$/),
34
- age: 'number:0-18!',
35
- role: this.enums.role.default('user'), // this 指向 module.exports
36
- })
37
- },
38
-
39
- // 自定义方法
40
- //
41
- // 说明:
42
- // - methods 接收 model 参数(ModelInstance 实例)
43
- // - 返回对象必须包含 instance 和/或 static 两个固定分组
44
- // - instance: 实例方法,注入到查询结果文档对象(this 指向文档)
45
- // - static: 静态方法,挂载到 Model 实例(通过 model 参数操作)
46
- //
47
- // 设计原因:
48
- // - 明确区分方法类型,避免混淆
49
- // - 实例方法:操作具体文档数据(需要 this)
50
- // - 静态方法:执行查询操作(不需要 this)
51
- //
52
- // 可选配置:
53
- // - 只需要 instance:只写 instance 分组
54
- // - 只需要 static:只写 static 分组
55
- // - 都不需要:整个 methods 配置项可省略
56
- //
57
- methods: (model)=>{
58
- return {
59
- // 实例方法(注入到文档对象)
60
- // 用法:const user = await User.findOne(...); user.checkPassword('123');
61
- instance: {
62
- checkPassword(password) {
63
- return this.password === password; // this 指向文档对象
64
- },
65
- async getPosts(_id) {
66
- return await model.find({ userId: _id }); // 可以调用 model 查询
67
- }
68
- },
69
-
70
- // 静态方法(挂载到 Model 实例)
71
- // 用法:const User = msq.model('users'); await User.findByName('test');
72
- static: {
73
- findByName(name) {
74
- return model.find({ username: name }); // 使用 model 参数
75
- }
76
- }
77
- };
78
- },
79
-
80
- // 支持操作前、后处理
81
- hooks:(model)=>{
82
- return {
83
- find: {
84
- before:(ctx,options)=>{},
85
- after:(ctx,docs,result)=>{},
86
- },
87
- insert:{
88
- before:async (ctx,docs)=>{
89
- // ctx.session = await model.startTransaction(); // ctx 里传递事务对象
90
- // return ctx.data;
91
- },
92
- after:async (ctx,docs,result)=>{
93
- // await ctx.session.commitTransaction();
94
- },
95
- },
96
- update:{
97
- before:(ctx,options)=>{},
98
- after:(ctx,result)=>{},
99
- },
100
- delete:{
101
- before:(ctx,options)=>{},
102
- after:(ctx,result)=>{},
103
- }
104
- };
105
- },
106
-
107
- // 创建索引
108
- indexes: [
109
- { key: { username: 1 }, unique: true }, // 唯一索引
110
- { key: { age: -1 } }, // 普通索引,降序
111
- ],
112
-
113
- // 关系
114
- relations: {
115
- posts: {
116
- type: 'hasMany', // 一对多
117
- target: 'Post', // 目标模型
118
- foreignKey: 'userId', // 外键字段(存在哪张表里)
119
- localKey: '_id', // 本表对应字段
120
- as: 'posts', // 实例访问属性 user.posts
121
- cascade: false // 是否级联删除/更新
122
- },
123
- profile: {
124
- type: 'hasOne', // 一对一
125
- target: 'Profile',
126
- foreignKey: 'userId',
127
- localKey: '_id',
128
- as: 'profile', // 实例访问属性 user.profile
129
- cascade: true, // 删除用户时级联删除 profile
130
- required: false // 是否必须关联
131
- },
132
- roles: { // 多对多
133
- type: 'manyToMany',
134
- target: 'Role',
135
- through: 'UserRole', // 中间表
136
- foreignKey: 'userId',
137
- otherKey: 'roleId',
138
- as: 'roles'
139
- }
140
- },
141
-
142
- // 模型选项配置(核心功能)
143
- options: {
144
- // 1️⃣ 时间戳自动维护
145
- // 默认值:{ enabled: false, createdAt: 'createdAt', updatedAt: 'updatedAt' }
146
- timestamps: {
147
- enabled: true, // 启用时间戳
148
- createdAt: 'createdAt', // 创建时间字段名
149
- updatedAt: 'updatedAt' // 更新时间字段名
150
- },
151
- // 简化配置方式:
152
- // timestamps: true // 使用默认字段名(createdAt, updatedAt)
153
- // timestamps: false // 禁用时间戳
154
-
155
- // 2️⃣ 软删除配置
156
- // 默认值:{ enabled: false, field: 'deletedAt', type: 'timestamp', ttl: null, index: true }
157
- softDelete: {
158
- enabled: true, // 启用软删除
159
- field: 'deletedAt', // 软删除字段名
160
- type: 'timestamp', // 类型:timestamp | boolean
161
- ttl: 30 * 24 * 60 * 60 * 1000, // 30天后物理删除(null=永久保留)
162
- index: true, // 自动创建索引
163
- },
164
- // 简化配置方式:
165
- // softDelete: true // 使用默认值
166
- // softDelete: false // 禁用软删除({ enabled: false })
167
-
168
- // 3️⃣ 乐观锁版本控制(防止并发冲突)
169
- // 默认值:{ enabled: false, field: 'version', strategy: 'increment' }
170
- version: {
171
- enabled: true, // 启用版本号
172
- field: 'version', // 版本字段名
173
- strategy: 'increment' // 策略:increment | timestamp
174
- },
175
- // 简化配置方式:
176
- // version: true // 使用默认值
177
- // version: false // 禁用版本控制({ enabled: false })
178
-
179
- // 4️⃣ 索引自动同步
180
- // 默认值:{ enabled: false, mode: 'safe', background: true }
181
- sync: {
182
- enabled: true, // 启用索引自动同步
183
- mode: 'safe', // 模式:safe | force
184
- background: true, // 后台创建索引
185
- },
186
- // 简化配置方式:
187
- // sync: true // 使用默认值(safe 模式)
188
- // sync: false // 禁用同步({ enabled: false })
189
- },
190
-
191
- // ========================================
192
- // 📝 默认配置值速查表
193
- // ========================================
194
- // timestamps: { enabled: false, createdAt: 'createdAt', updatedAt: 'updatedAt' }
195
- // softDelete: { enabled: false, field: 'deletedAt', type: 'timestamp', ttl: null, index: true }
196
- // version: { enabled: false, field: 'version', strategy: 'increment' }
197
- // sync: { enabled: false, mode: 'safe', background: true }
198
- //
199
- // 说明:
200
- // - 默认所有功能都禁用(enabled: false),用户需要主动启用
201
- // - ttl: null = 软删除数据永久保留
202
- // - ttl: 数字 = 指定天数后物理删除
203
- // - mode: 'safe' = 只创建缺失的索引(生产环境推荐)
204
- // - mode: 'force' = 创建+删除索引,完全同步(开发环境)
205
- //
206
- // ========================================
207
- // 📝 配置方式说明(三层递进)
208
- // ========================================
209
- //
210
- // 【第1层】完全默认(什么都不改)
211
- // options: {} // 所有功能禁用
212
- //
213
- // 【第2层】简化配置(快速启用功能)
214
- // options: {
215
- // timestamps: true,
216
- // softDelete: true,
217
- // version: true,
218
- // sync: true
219
- // }
220
- //
221
- // 【第3层】详细配置(精细控制)
222
- // options: {
223
- // timestamps: { enabled: true, createdAt: 'createdAt', updatedAt: 'updatedAt' },
224
- // softDelete: { enabled: true, field: 'deletedAt', type: 'timestamp', ttl: ..., index: true },
225
- // version: { enabled: true, field: 'version', strategy: 'increment' },
226
- // sync: { enabled: true, mode: 'safe', background: true }
227
- // }
228
- //
229
- // ========================================
230
- // 📝 日常开发场景最佳实践
231
- // ========================================
232
- //
233
- // 场景1: 用户/订单表(需要完整功能)
234
- // options: {
235
- // timestamps: true,
236
- // softDelete: true, // 删除后保留30天便于恢复
237
- // version: true, // 防止并发冲突
238
- // sync: true
239
- // }
240
- //
241
- // 场景2: 会话/缓存表(最小化配置)
242
- // options: {
243
- // timestamps: false, // 不需要时间戳
244
- // softDelete: false, // 不需要软删除,过期自动删除
245
- // version: false, // 不需要版本控制
246
- // sync: true // 需要同步 TTL 索引
247
- // }
248
- // indexes: [
249
- // { key: { expireAt: 1 }, expireAfterSeconds: 0 } // TTL 索引
250
- // ]
251
- //
252
- // 场景3: 中间表(极简配置)
253
- // options: {
254
- // timestamps: false,
255
- // softDelete: false,
256
- // version: false,
257
- // sync: true // 需要同步唯一索引
258
- // }
259
- //
260
- // 场景4: 日志/事件表(无删除需求)
261
- // options: {
262
- // timestamps: true, // 记录事件时间
263
- // softDelete: false, // 日志不删除
264
- // version: false, // 日志不并发更新
265
- // sync: true
266
- // }
267
- //
268
- // 场景5: 商品/内容表(高频并发)
269
- // options: {
270
- // timestamps: true,
271
- // softDelete: true, // 下架商品保留
272
- // version: true, // 防止秒杀并发冲突
273
- // sync: { // 生产环境用 safe,开发用 force
274
- // enabled: true,
275
- // mode: 'safe', // 生产环境
276
- // background: true
277
- // }
278
- // }
279
- //
280
- // ========================================
281
- // 📝 全局配置已包含:
282
- // - 缓存系统(MemoryCache)
283
- // - 日志系统(Logger)
284
- // - 慢查询日志(SlowQueryLogManager)
285
- // - 默认值(defaultLimit, maxLimit, validation等)
286
- //
287
- // 📝 Model options 只配置模型特异的功能:
288
- // - timestamps: 某些表不需要(如中间表)
289
- // - softDelete: 某些表不需要(如会话表)
290
- // - version: 高并发表才需要
291
- // - sync: 模型特异的索引定义
292
- //
293
- // 📝 数据生命周期处理方式:
294
- // - 在 schema 中定义 expireAt 字段
295
- // - 在 indexes 中定义 TTL 索引
296
- // - 不需要单独的 lifecycle 配置项
297
- //
298
- // 📝 自动注入的方法(仅当 softDelete.enabled = true):
299
- // - model.restore(id) - 恢复软删除数据
300
- // - model.forceDelete(id) - 强制物理删除
301
- // - model.findWithDeleted() - 查询包含软删除数据
302
- // - model.findOnlyDeleted() - 只查询软删除数据
303
- //
304
- // 📝 开发建议:
305
- // 1. 开发阶段:使用简化配置快速迭代(timestamps: true, ...)
306
- // 2. 优化阶段:根据实际需求调整(可禁用不需要的功能)
307
- // 3. 生产部署:确认 sync.mode 为 'safe'(避免误删索引)
308
- // 4. 高并发表:必须启用 version,防止并发冲突
309
- // 5. 敏感数据:启用 softDelete,避免误删无法恢复
310
- };
311
-
@@ -1,161 +0,0 @@
1
- /**
2
- * Default Values Manager - 默认值管理器
3
- *
4
- * 为字段提供默认值功能,在插入文档时自动填充
5
- *
6
- * 支持:
7
- * - 静态默认值(如 status: 'active')
8
- * - 函数默认值(如 createdAt: () => new Date())
9
- * - 上下文默认值(如 createdBy: (ctx) => ctx.userId)
10
- *
11
- * @module lib/model/features/defaults
12
- * @since v1.0.6
13
- */
14
-
15
- /**
16
- * DefaultsManager - 默认值管理器
17
- */
18
- class DefaultsManager {
19
- /**
20
- * 构造函数
21
- * @param {Model} model - 所属的 Model 实例
22
- */
23
- constructor(model) {
24
- this.model = model;
25
- this.defaults = new Map(); // 默认值定义缓存
26
- }
27
-
28
- /**
29
- * 定义字段默认值
30
- *
31
- * @param {string} field - 字段名
32
- * @param {*|Function} value - 默认值或默认值函数
33
- *
34
- * @example
35
- * // 静态默认值
36
- * defaults.define('status', 'active');
37
- *
38
- * // 函数默认值
39
- * defaults.define('createdAt', () => new Date());
40
- *
41
- * // 上下文默认值
42
- * defaults.define('createdBy', (ctx) => ctx.userId);
43
- */
44
- define(field, value) {
45
- if (!field || typeof field !== 'string') {
46
- throw new Error('字段名必须是字符串');
47
- }
48
-
49
- this.defaults.set(field, value);
50
- }
51
-
52
- /**
53
- * 获取字段默认值
54
- * @param {string} field - 字段名
55
- * @returns {*} 默认值
56
- */
57
- get(field) {
58
- return this.defaults.get(field);
59
- }
60
-
61
- /**
62
- * 获取所有默认值定义
63
- * @returns {Map} 所有默认值
64
- */
65
- getAll() {
66
- return this.defaults;
67
- }
68
-
69
- /**
70
- * 检查字段是否有默认值
71
- * @param {string} field - 字段名
72
- * @returns {boolean}
73
- */
74
- has(field) {
75
- return this.defaults.has(field);
76
- }
77
-
78
- /**
79
- * 应用默认值到文档
80
- *
81
- * @param {Object|Array} docs - 文档或文档数组
82
- * @param {Object} [context] - 上下文对象(可选)
83
- * @returns {Object|Array} 应用默认值后的文档
84
- */
85
- apply(docs, context = {}) {
86
- if (!docs) {
87
- return docs;
88
- }
89
-
90
- // 处理数组
91
- if (Array.isArray(docs)) {
92
- return docs.map(doc => this.applyToDocument(doc, context));
93
- }
94
-
95
- // 处理单个文档
96
- return this.applyToDocument(docs, context);
97
- }
98
-
99
- /**
100
- * 应用默认值到单个文档
101
- *
102
- * @private
103
- * @param {Object} doc - 文档对象
104
- * @param {Object} context - 上下文对象
105
- * @returns {Object} 应用默认值后的文档
106
- */
107
- applyToDocument(doc, context) {
108
- if (!doc || typeof doc !== 'object' || Buffer.isBuffer(doc)) {
109
- return doc;
110
- }
111
-
112
- const result = { ...doc };
113
-
114
- // 遍历所有默认值定义
115
- for (const [field, defaultValue] of this.defaults.entries()) {
116
- // 只在字段不存在或为 undefined 时应用默认值
117
- if (result[field] === undefined) {
118
- // 如果默认值是函数,调用函数获取值
119
- if (typeof defaultValue === 'function') {
120
- result[field] = defaultValue(context, doc);
121
- } else {
122
- result[field] = defaultValue;
123
- }
124
- }
125
- }
126
-
127
- return result;
128
- }
129
- }
130
-
131
- /**
132
- * 设置默认值功能
133
- *
134
- * @param {ModelInstance} modelInstance - Model 实例
135
- * @param {Object} defaultsConfig - 默认值配置
136
- *
137
- * @example
138
- * setupDefaults(modelInstance, {
139
- * status: 'active',
140
- * createdAt: () => new Date(),
141
- * score: 0
142
- * });
143
- */
144
- function setupDefaults(modelInstance, defaultsConfig) {
145
- // 初始化 DefaultsManager
146
- modelInstance._defaults = new DefaultsManager(modelInstance);
147
-
148
- // 注册默认值
149
- if (defaultsConfig && typeof defaultsConfig === 'object') {
150
- for (const [field, value] of Object.entries(defaultsConfig)) {
151
- modelInstance._defaults.define(field, value);
152
- }
153
- }
154
- }
155
-
156
- module.exports = {
157
- DefaultsManager,
158
- setupDefaults
159
- };
160
-
161
-