monsqlize 1.3.1 → 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 (113) hide show
  1. package/CHANGELOG.md +415 -146
  2. package/LICENSE +201 -21
  3. package/README.md +537 -928
  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 +69 -67
  27. package/index.d.ts +0 -1289
  28. package/lib/cache.js +0 -491
  29. package/lib/common/cursor.js +0 -58
  30. package/lib/common/docs-urls.js +0 -72
  31. package/lib/common/index-options.js +0 -222
  32. package/lib/common/log.js +0 -60
  33. package/lib/common/namespace.js +0 -21
  34. package/lib/common/normalize.js +0 -33
  35. package/lib/common/page-result.js +0 -42
  36. package/lib/common/runner.js +0 -56
  37. package/lib/common/server-features.js +0 -231
  38. package/lib/common/shape-builders.js +0 -26
  39. package/lib/common/validation.js +0 -112
  40. package/lib/connect.js +0 -76
  41. package/lib/constants.js +0 -54
  42. package/lib/count-queue.js +0 -187
  43. package/lib/distributed-cache-invalidator.js +0 -259
  44. package/lib/errors.js +0 -167
  45. package/lib/index.js +0 -461
  46. package/lib/infrastructure/ssh-tunnel-ssh2.js +0 -211
  47. package/lib/infrastructure/ssh-tunnel.js +0 -40
  48. package/lib/infrastructure/uri-parser.js +0 -35
  49. package/lib/lock/Lock.js +0 -66
  50. package/lib/lock/errors.js +0 -27
  51. package/lib/lock/index.js +0 -12
  52. package/lib/logger.js +0 -224
  53. package/lib/model/examples/test.js +0 -114
  54. package/lib/mongodb/common/accessor-helpers.js +0 -58
  55. package/lib/mongodb/common/agg-pipeline.js +0 -32
  56. package/lib/mongodb/common/iid.js +0 -27
  57. package/lib/mongodb/common/lexicographic-expr.js +0 -52
  58. package/lib/mongodb/common/shape.js +0 -31
  59. package/lib/mongodb/common/sort.js +0 -38
  60. package/lib/mongodb/common/transaction-aware.js +0 -24
  61. package/lib/mongodb/connect.js +0 -233
  62. package/lib/mongodb/index.js +0 -591
  63. package/lib/mongodb/management/admin-ops.js +0 -199
  64. package/lib/mongodb/management/bookmark-ops.js +0 -166
  65. package/lib/mongodb/management/cache-ops.js +0 -49
  66. package/lib/mongodb/management/collection-ops.js +0 -386
  67. package/lib/mongodb/management/database-ops.js +0 -201
  68. package/lib/mongodb/management/index-ops.js +0 -474
  69. package/lib/mongodb/management/index.js +0 -16
  70. package/lib/mongodb/management/namespace.js +0 -30
  71. package/lib/mongodb/management/validation-ops.js +0 -267
  72. package/lib/mongodb/queries/aggregate.js +0 -142
  73. package/lib/mongodb/queries/chain.js +0 -630
  74. package/lib/mongodb/queries/count.js +0 -98
  75. package/lib/mongodb/queries/distinct.js +0 -77
  76. package/lib/mongodb/queries/find-and-count.js +0 -192
  77. package/lib/mongodb/queries/find-by-ids.js +0 -235
  78. package/lib/mongodb/queries/find-one-by-id.js +0 -170
  79. package/lib/mongodb/queries/find-one.js +0 -70
  80. package/lib/mongodb/queries/find-page.js +0 -577
  81. package/lib/mongodb/queries/find.js +0 -170
  82. package/lib/mongodb/queries/index.js +0 -50
  83. package/lib/mongodb/queries/watch.js +0 -537
  84. package/lib/mongodb/writes/delete-many.js +0 -190
  85. package/lib/mongodb/writes/delete-one.js +0 -182
  86. package/lib/mongodb/writes/find-one-and-delete.js +0 -202
  87. package/lib/mongodb/writes/find-one-and-replace.js +0 -238
  88. package/lib/mongodb/writes/find-one-and-update.js +0 -239
  89. package/lib/mongodb/writes/increment-one.js +0 -252
  90. package/lib/mongodb/writes/index.js +0 -41
  91. package/lib/mongodb/writes/insert-batch.js +0 -507
  92. package/lib/mongodb/writes/insert-many.js +0 -227
  93. package/lib/mongodb/writes/insert-one.js +0 -180
  94. package/lib/mongodb/writes/replace-one.js +0 -215
  95. package/lib/mongodb/writes/result-handler.js +0 -236
  96. package/lib/mongodb/writes/update-many.js +0 -221
  97. package/lib/mongodb/writes/update-one.js +0 -223
  98. package/lib/mongodb/writes/upsert-one.js +0 -206
  99. package/lib/multi-level-cache.js +0 -189
  100. package/lib/operators.js +0 -330
  101. package/lib/redis-cache-adapter.js +0 -237
  102. package/lib/slow-query-log/base-storage.js +0 -69
  103. package/lib/slow-query-log/batch-queue.js +0 -96
  104. package/lib/slow-query-log/config-manager.js +0 -195
  105. package/lib/slow-query-log/index.js +0 -237
  106. package/lib/slow-query-log/mongodb-storage.js +0 -323
  107. package/lib/slow-query-log/query-hash.js +0 -38
  108. package/lib/transaction/CacheLockManager.js +0 -161
  109. package/lib/transaction/DistributedCacheLockManager.js +0 -474
  110. package/lib/transaction/Transaction.js +0 -314
  111. package/lib/transaction/TransactionManager.js +0 -266
  112. package/lib/transaction/index.js +0 -10
  113. package/lib/utils/objectid-converter.js +0 -566
package/README.md CHANGED
@@ -1,928 +1,537 @@
1
- <div align="center">
2
-
3
- # 🚀 monSQLize
4
-
5
- ### MongoDB 的性能加速器 - 让数据库查询快 10~100 倍
6
-
7
- **100% API 兼容 · 零学习成本 · 开箱即用**
8
-
9
- [![npm version](https://img.shields.io/npm/v/monsqlize.svg)](https://www.npmjs.com/package/monsqlize)
10
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
11
- [![Test Coverage](https://img.shields.io/badge/Coverage-77%25-brightgreen.svg)](https://codecov.io/gh/vextjs/monSQLize)
12
- [![MongoDB](https://img.shields.io/badge/MongoDB-4.4%2B-green.svg)](https://www.mongodb.com/)
13
- [![Node.js](https://img.shields.io/badge/Node.js-16%2B-brightgreen)](https://nodejs.org/)
14
-
15
- ```bash
16
- npm install monsqlize
17
- ```
18
-
19
- [快速开始](#-快速开始) · [为什么选择](#-为什么选择-monsqlize) · [核心特性](#-核心特性) · [完整文档](./docs/INDEX.md)
20
-
21
- </div>
22
-
23
- ---
24
-
25
- ## 📑 目录
26
-
27
- - [⚡ 性能对比](#-性能对比)
28
- - [🎯 一句话介绍](#-一句话介绍)
29
- - [💡 为什么选择 monSQLize?](#-为什么选择-monsqlize)
30
- - [🎯 何时使用 monSQLize?](#-何时使用-monsqlize)
31
- - [🚀 快速开始](#-快速开始)
32
- - [🌟 核心特性](#-核心特性)
33
- - [1. ⚡ 智能缓存系统](#1--智能缓存系统---性能提升-10100-倍)
34
- - [2. 🔄 事务管理优化](#2--事务管理优化---减少-30-数据库访问)
35
- - [3. 📦 便利方法](#3--便利方法---减少-6080-代码)
36
- - [4. 🌐 分布式部署支持](#4--分布式部署支持)
37
- - [5. 🆕 业务级分布式锁](#5--业务级分布式锁v140)
38
- - [6. 🚀 高性能批量插入](#6--高性能批量插入)
39
- - [7. 📊 深度分页](#7--深度分页---支持千万级数据)
40
- - [8. 🛠️ 运维监控](#8-️-运维监控开箱即用)
41
- - [9. 🔐 SSH隧道](#9--ssh隧道---安全连接内网数据库v13)
42
- - [📊 性能测试报告](#-性能测试报告)
43
- - [🎨 完整功能清单](#-完整功能清单)
44
- - [🆚 MongoDB 原生驱动对比](#-与-mongodb-原生驱动对比)
45
- - [🚀 快速迁移指南](#-快速迁移指南)
46
- - [📖 完整文档](#-完整文档)
47
- - [🌍 兼容性](#-兼容性)
48
- - [🗺️ 产品路线图](#️-产品路线图)
49
- - [🤝 贡献指南](#-贡献指南)
50
- - [📄 许可证](#-许可证)
51
- - [💬 社区与支持](#-社区与支持)
52
-
53
- ---
54
-
55
- ## 性能对比
56
-
57
- ```javascript
58
- // MongoDB 原生驱动
59
- const users = await collection.find({ status: 'active' }).toArray(); // 50ms
60
- const product = await products.findOne({ _id: productId }); // 10ms
61
-
62
- // ✅ monSQLize(启用缓存)
63
- const users = await collection.find({ status: 'active' }, { cache: 60000 }); // 0.5ms ⚡ 100x faster
64
- const product = await products.findOne({ _id: productId }, { cache: 60000 }); // 0.1ms ⚡ 100x faster
65
- ```
66
-
67
- **只需在初始化时配置缓存,业务代码一行不改,性能立即提升!**
68
-
69
- ---
70
-
71
- ## 🎯 一句话介绍
72
-
73
- monSQLize 是一个**100% 兼容 MongoDB API** 的增强库。
74
-
75
- 在保持完全兼容的前提下,为你的应用提供:
76
-
77
- <table>
78
- <tr>
79
- <td width="25%" align="center">
80
- <h3>🚀</h3>
81
- <h4>智能缓存</h4>
82
- <p>LRU/TTL 策略<br>自动失效<br>10~100 倍性能提升</p>
83
- </td>
84
- <td width="25%" align="center">
85
- <h3>🔄</h3>
86
- <h4>事务优化</h4>
87
- <p>自动管理<br>只读优化<br>减少 30% DB 访问</p>
88
- </td>
89
- <td width="25%" align="center">
90
- <h3>🌐</h3>
91
- <h4>分布式支持</h4>
92
- <p>Redis 广播<br>多实例一致性<br>业务级分布式锁</p>
93
- </td>
94
- <td width="25%" align="center">
95
- <h3>🔐</h3>
96
- <h4>SSH 隧道</h4>
97
- <p>安全连接内网数据库<br>密码/私钥认证<br>开箱即用</p>
98
- </td>
99
- </tr>
100
- </table>
101
-
102
- **设计理念**:零学习成本 · 渐进式采用 · 性能优先 · 生产可靠
103
-
104
- ---
105
-
106
- ## 💡 为什么选择 monSQLize?
107
-
108
- ### 你遇到的问题
109
-
110
- <table>
111
- <tr>
112
- <td width="50%">
113
-
114
- **😫 数据库性能瓶颈**
115
- - 高并发时查询变慢
116
- - 热点数据重复查询数据库
117
- - 聚合统计拖慢响应速度
118
- - 用户抱怨页面加载慢
119
-
120
- **😫 代码重复繁琐**
121
- - ObjectId 转换到处都是
122
- - 批量查询要写很多代码
123
- - Upsert 操作不够直观
124
- - 事务代码复杂易错
125
-
126
- **😫 多实例部署问题**
127
- - 缓存不一致导致脏读
128
- - 定时任务重复执行
129
- - 库存扣减并发冲突
130
- - 需要额外的锁机制
131
-
132
- </td>
133
- <td width="50%">
134
-
135
- **✅ monSQLize 的解决方案**
136
- - **智能缓存系统** - 热点数据走缓存,10~100倍性能提升
137
- - **自动失效机制** - 写操作自动清理,保证数据一致性
138
- - **缓存命中率 70~90%** - 真实业务场景验证
139
- - **响应时间 < 1ms** - 从 10~50ms 降至毫秒级
140
-
141
- **✅ monSQLize 的解决方案**
142
- - **便利方法** - findOneById、findByIds、upsertOne
143
- - **自动转换 ObjectId** - 无需手动处理
144
- - **语义化 API** - 代码更清晰易读
145
- - **事务自动管理** - withTransaction 简化事务代码
146
-
147
- **✅ monSQLize 的解决方案**
148
- - **Redis 广播** - 多实例缓存自动同步
149
- - **分布式锁** - 解决并发控制问题
150
- - **定时任务防重** - tryAcquireLock 机制
151
- - **开箱即用** - 配置简单,无需额外组件
152
-
153
- </td>
154
- </tr>
155
- </table>
156
-
157
- ### 真实效果
158
-
159
- | 场景 | 优化前 | 优化后 | 提升 |
160
- |------|--------|--------|------|
161
- | **商品详情页** | 50ms/次 | 0.5ms/次 | **100x** |
162
- | **用户列表** | 80ms/次 | 0.8ms/次 | **100x** ⚡ |
163
- | **订单统计** | 200ms/次 | 2ms/次 | **100x** ⚡ |
164
- | **批量插入 10万条** | 30s | 1.2s | **25x** ⚡ |
165
-
166
- **缓存命中率**:电商 85% · 内容平台 75% · 社交应用 80%
167
-
168
- ---
169
-
170
- ## 🎯 何时使用 monSQLize?
171
-
172
- ### ✅ 适合的场景
173
-
174
- | 场景 | 说明 | 预期效果 |
175
- |------|------|---------|
176
- | **高并发读取** | 商品详情、用户信息等热点数据 | 缓存命中率 70~90%,响应时间从 10~50ms 降至 < 1ms |
177
- | **复杂查询** | 聚合统计、关联查询 | 重复查询直接走缓存,避免重复计算 |
178
- | **多实例部署** | 负载均衡、水平扩展 | Redis 广播保证缓存一致性 |
179
- | **事务密集** | 订单、支付等业务 | 自动管理事务,优化只读操作 |
180
- | **并发控制** | 库存扣减、定时任务 | 分布式锁解决复杂并发场景 |
181
-
182
- ### ⚠️ 不适合的场景
183
-
184
- | 场景 | 原因 | 建议 |
185
- |------|------|------|
186
- | **纯写入应用** | 大量写入,很少查询 | 缓存作用有限,使用原生驱动即可 |
187
- | **实时性要求极高** | 必须每次查询最新数据 | 不启用缓存,或使用极短 TTL |
188
- | **简单 CRUD** | 简单应用,流量不大 | 原生驱动足够,无需引入复杂度 |
189
- | **内存受限** | 服务器内存紧张 | 缓存会占用额外内存 |
190
-
191
- ### 💡 使用建议
192
-
193
- - **渐进式采用**:先在热点查询启用缓存,观察效果后逐步扩展
194
- - **监控指标**:关注缓存命中率、内存使用、慢查询日志
195
- - **合理配置**:根据业务特点调整 TTL、缓存大小
196
- - **混合使用**:可与原生驱动混用,性能敏感用 monSQLize,简单查询用原生
197
-
198
- ---
199
-
200
- ## 🚀 快速开始
201
-
202
- ### 安装
203
-
204
- ```bash
205
- npm install monsqlize
206
- ```
207
-
208
- ### 基础使用
209
-
210
- ```javascript
211
- const MonSQLize = require('monsqlize');
212
-
213
- // 1. 初始化
214
- const db = new MonSQLize({
215
- type: 'mongodb',
216
- config: { uri: 'mongodb://localhost:27017/mydb' },
217
- cache: {
218
- enabled: true,
219
- maxSize: 100000, // 最多缓存 10 万条
220
- ttl: 60000 // 默认 TTL 60 秒
221
- }
222
- });
223
-
224
- await db.connect();
225
-
226
- // 2. 使用(完全兼容 MongoDB API)
227
- const users = db.collection('users');
228
-
229
- // 启用缓存
230
- const user = await users.findOne({ email }, { cache: 60000 });
231
-
232
- // 写操作自动失效缓存
233
- await users.updateOne({ email }, { $set: { lastLogin: new Date() } });
234
-
235
- // 便利方法
236
- const user = await users.findOneById(userId);
237
- const list = await users.findByIds([id1, id2, id3]);
238
-
239
- // 事务
240
- await db.withTransaction(async (tx) => {
241
- await users.updateOne({...}, {...}, { session: tx.session });
242
- await orders.insertOne({...}, { session: tx.session });
243
- });
244
-
245
- // 业务锁(v1.4.0)
246
- await db.withLock('resource:key', async () => {
247
- // 临界区代码
248
- });
249
-
250
- // SSH隧道(v1.3+)- 安全连接防火墙后的MongoDB
251
- const db = new MonSQLize({
252
- type: 'mongodb',
253
- config: {
254
- ssh: {
255
- host: 'bastion.example.com',
256
- username: 'deploy',
257
- password: 'your-password', // 或使用 privateKeyPath
258
- },
259
- // 自动从URI解析remoteHost和remotePort
260
- uri: 'mongodb://user:pass@internal-mongo:27017/mydb'
261
- }
262
- });
263
- ```
264
-
265
- ### 从原生驱动迁移
266
-
267
- ```javascript
268
- // 原来的代码
269
- const { MongoClient } = require('mongodb');
270
- const client = await MongoClient.connect('mongodb://localhost:27017');
271
- const db = client.db('mydb');
272
- const users = db.collection('users');
273
-
274
- // 迁移后(只需改初始化)
275
- const MonSQLize = require('monsqlize');
276
- const db = new MonSQLize({
277
- type: 'mongodb',
278
- config: { uri: 'mongodb://localhost:27017/mydb' },
279
- cache: { enabled: true } // 启用缓存
280
- });
281
- await db.connect();
282
- const users = db.collection('users');
283
-
284
- // ✅ 后续代码完全不变
285
- const user = await users.findOne({ email });
286
- ```
287
-
288
- ---
289
-
290
- ## 🌟 核心特性
291
-
292
- ### 1. 智能缓存系统 - 性能提升 10~100 倍
293
-
294
- <table>
295
- <tr>
296
- <td width="50%">
297
-
298
- **特性**
299
-
300
- - **TTL 过期策略** - 指定缓存时间
301
- - **LRU 淘汰策略** - 自动淘汰旧数据
302
- - **自动失效** - 写操作自动清理缓存
303
- - ✅ **并发去重** - 相同查询只执行一次
304
- - ✅ **多层缓存** - 内存 + Redis
305
- - **命名空间隔离** - 按集合独立管理
306
-
307
- </td>
308
- <td width="50%">
309
-
310
- **性能提升**
311
-
312
- | 操作 | 原生驱动 | monSQLize | 提升 |
313
- |------|---------|-----------|------|
314
- | 热点查询 | 50ms | 0.5ms | **100x** ⚡ |
315
- | 复杂聚合 | 200ms | 2ms | **100x** ⚡ |
316
- | 列表查询 | 30ms | 0.3ms | **100x** ⚡ |
317
-
318
- </td>
319
- </tr>
320
- </table>
321
-
322
- ```javascript
323
- // 一行代码启用缓存
324
- const users = await collection.find({ status: 'active' }, { cache: 60000 });
325
- ```
326
-
327
- ### 2. 🔄 事务管理优化 - 减少 30% 数据库访问
328
-
329
- ```javascript
330
- // 自动管理事务生命周期
331
- await db.withTransaction(async (tx) => {
332
- // 只读操作会被优化(不加锁,减少 30% 访问)
333
- const user = await users.findOne({ _id: userId }, { session: tx.session });
334
-
335
- // 写操作自动加锁
336
- await users.updateOne({ _id: userId }, { $inc: { balance: -100 } }, { session: tx.session });
337
-
338
- // 自动提交 or 回滚
339
- });
340
- ```
341
-
342
- ### 3. 📦 便利方法 - 减少 60~80% 代码
343
-
344
- <table>
345
- <tr>
346
- <td width="50%">
347
-
348
- **❌ 原生驱动**
349
-
350
- ```javascript
351
- // 查询单个文档(需要手动转换 ObjectId)
352
- const { ObjectId } = require('mongodb');
353
- const user = await users.findOne({
354
- _id: new ObjectId(userId)
355
- });
356
-
357
- // 批量查询(需要手动构建 $in)
358
- const userList = await users.find({
359
- _id: { $in: ids.map(id => new ObjectId(id)) }
360
- }).toArray();
361
-
362
- // Upsert(需要手动设置选项)
363
- await users.updateOne(
364
- { email: 'alice@example.com' },
365
- { $set: { name: 'Alice', age: 30 } },
366
- { upsert: true }
367
- );
368
- ```
369
-
370
- </td>
371
- <td width="50%">
372
-
373
- **✅ monSQLize**
374
-
375
- ```javascript
376
- // 查询单个文档(自动转换)
377
- const user = await users.findOneById(userId);
378
-
379
-
380
-
381
-
382
- // 批量查询(一行搞定)
383
- const userList = await users.findByIds(ids);
384
-
385
-
386
-
387
-
388
- // Upsert(语义化)
389
- await users.upsertOne(
390
- { email: 'alice@example.com' },
391
- { name: 'Alice', age: 30 }
392
- );
393
- ```
394
-
395
- **代码减少 60~80%!**
396
-
397
- </td>
398
- </tr>
399
- </table>
400
-
401
- ### 4. 🌐 分布式部署支持
402
-
403
- ```javascript
404
- // 多实例部署,Redis 自动同步缓存
405
- const db = new MonSQLize({
406
- cache: {
407
- distributed: {
408
- enabled: true,
409
- redis: redisInstance // 使用 Redis 广播缓存失效
410
- }
411
- }
412
- });
413
-
414
- // 实例 A 更新数据
415
- await users.updateOne({ _id: userId }, { $set: { name: 'Bob' } });
416
- // 实例 B/C/D 的缓存自动失效
417
- ```
418
-
419
- ### 5. 🆕 业务级分布式锁(v1.4.0)
420
-
421
- ```javascript
422
- // 🔥 解决复杂业务场景的并发问题
423
-
424
- // 场景1:库存扣减
425
- await db.withLock(`inventory:${sku}`, async () => {
426
- const product = await inventory.findOne({ sku });
427
- const price = calculatePrice(product, user, coupon); // 复杂计算
428
- if (user.balance < price) throw new Error('余额不足');
429
-
430
- await inventory.updateOne({ sku }, { $inc: { stock: -1 } });
431
- await users.updateOne({ userId }, { $inc: { balance: -price } });
432
- await orders.insertOne({ userId, sku, price });
433
- });
434
-
435
- // 场景2:定时任务防重(多实例环境)
436
- const lock = await db.tryAcquireLock('cron:daily-report');
437
- if (lock) {
438
- try {
439
- await generateDailyReport(); // 只有一个实例执行
440
- } finally {
441
- await lock.release();
442
- }
443
- }
444
- ```
445
-
446
- **特性**:基于 Redis · 自动重试 · TTL 防死锁 · 支持续期 · 降级策略
447
-
448
- [📖 完整文档](./docs/business-lock.md)
449
-
450
- ### 6. 🚀 高性能批量插入
451
-
452
- ```javascript
453
- // 批量插入 10 万条数据
454
- await users.insertBatch(documents, {
455
- batchSize: 1000, // 每批 1000 条
456
- retryTimes: 3, // 失败重试 3
457
- onProgress: (stats) => {
458
- console.log(`进度: ${stats.inserted}/${stats.total}`);
459
- }
460
- });
461
- ```
462
-
463
- **性能**: 比原生 `insertMany` 快 **10~50 倍** ⚡
464
-
465
- ### 7. 📊 深度分页 - 支持千万级数据
466
-
467
- ```javascript
468
- // 千万级数据分页(游标分页,性能稳定)
469
- const result = await users.findPage({
470
- query: { status: 'active' },
471
- page: 1000, // 第 1000 页
472
- limit: 20,
473
- totals: {
474
- mode: 'async', // 异步统计总数
475
- ttl: 300000 // 缓存 5 分钟
476
- }
477
- });
478
-
479
- console.log(`总计: ${result.totals.total}, 共 ${result.totals.totalPages} 页`);
480
- ```
481
-
482
- ### 8. 🛠️ 运维监控(开箱即用)
483
-
484
- ```javascript
485
- // 🆕 慢查询日志持久化存储(v1.3+)
486
- const msq = new MonSQLize({
487
- type: 'mongodb',
488
- config: { uri: 'mongodb://localhost:27017/mydb' },
489
- slowQueryMs: 500,
490
- slowQueryLog: true // ✅ 零配置启用,自动存储到 admin.slow_query_logs
491
- });
492
-
493
- await msq.connect();
494
-
495
- // 查询慢查询日志(支持去重聚合)
496
- const logs = await msq.getSlowQueryLogs(
497
- { collection: 'users' },
498
- { sort: { count: -1 }, limit: 10 } // 查询高频慢查询Top10
499
- );
500
- // [{ queryHash: 'abc123', count: 2400, avgTimeMs: 520, maxTimeMs: 1200, ... }]
501
-
502
- // 自动记录慢查询(原有功能)
503
- // [WARN] Slow query { ns: 'mydb.users', duration: 1200ms, query: {...} }
504
-
505
- // 健康检查
506
- const health = await db.health();
507
- // { status: 'ok', uptime: 3600, connections: 10 }
508
-
509
- // 性能指标
510
- const stats = await db.getStats();
511
- // { queries: 10000, cacheHits: 9000, hitRate: 0.9 }
512
- ```
513
-
514
- ### 9. 🔐 SSH隧道 - 安全连接内网数据库(v1.3+)
515
-
516
- ```javascript
517
- // 场景:数据库位于防火墙后,无法直接访问
518
- const db = new MonSQLize({
519
- type: 'mongodb',
520
- config: {
521
- // SSH隧道配置
522
- ssh: {
523
- host: 'bastion.example.com', // SSH服务器(跳板机)
524
- port: 22,
525
- username: 'deploy',
526
- password: 'your-password', // 支持密码认证
527
- // 或使用私钥认证(推荐)
528
- // privateKeyPath: '~/.ssh/id_rsa',
529
- },
530
- // MongoDB连接配置(内网地址,自动从URI解析remoteHost和remotePort)
531
- uri: 'mongodb://user:pass@internal-mongo:27017/mydb'
532
- }
533
- });
534
-
535
- await db.connect(); // 自动建立SSH隧道
536
- // 正常使用MongoDB,无需关心隧道细节
537
- const users = db.collection('users');
538
- const data = await users.findOne({});
539
- await db.close(); // 自动关闭SSH隧道
540
- ```
541
-
542
- **特性**:
543
- - ✅ 支持密码和私钥认证
544
- - ✅ 自动管理隧道生命周期
545
- - ✅ 完美跨平台(基于ssh2库)
546
- - ✅ 开箱即用,零额外配置
547
-
548
- [📖 SSH隧道详细文档](./docs/ssh-tunnel.md)
549
-
550
- ---
551
-
552
- ## 📊 性能测试报告
553
-
554
- ### 测试环境
555
-
556
- - **CPU**: Intel i7-9700K
557
- - **内存**: 16GB
558
- - **数据库**: MongoDB 5.0
559
- - **数据量**: 100 万条
560
-
561
- ### 查询性能对比
562
-
563
- | 场景 | 原生驱动 | monSQLize (缓存) | 提升倍数 |
564
- |------|---------|------------------|---------|
565
- | 热点查询 (findOne) | 10ms | 0.1ms | **100x** ⚡ |
566
- | 列表查询 (find) | 50ms | 0.5ms | **100x** ⚡ |
567
- | 复杂聚合 (aggregate) | 200ms | 2ms | **100x** ⚡ |
568
- | 批量插入 (10万条) | 30s | 1.2s | **25x** ⚡ |
569
-
570
- ### 缓存命中率
571
-
572
- - **电商场景**: 85% (商品/用户查询)
573
- - **内容平台**: 75% (文章/评论查询)
574
- - **社交应用**: 80% (个人资料/动态)
575
-
576
- **结论**: 在真实业务场景中,缓存命中率通常在 **70~90%**,性能提升 **10~100 倍**。
577
-
578
- ---
579
-
580
- ## 🎨 完整功能清单
581
-
582
- <table>
583
- <tr>
584
- <td width="33%">
585
-
586
- ### 📦 MongoDB 原生功能
587
-
588
- ✅ **CRUD 操作**
589
- - find / findOne
590
- - insertOne / insertMany
591
- - updateOne / updateMany
592
- - deleteOne / deleteMany
593
- - replaceOne
594
- - findOneAndUpdate
595
- - findOneAndReplace
596
- - findOneAndDelete
597
-
598
- ✅ **聚合 & 查询**
599
- - aggregate
600
- - count / distinct
601
- - watch (Change Streams)
602
- - explain
603
-
604
- ✅ **索引管理**
605
- - createIndex / createIndexes
606
- - listIndexes
607
- - dropIndex / dropIndexes
608
-
609
- ✅ **事务支持**
610
- - withTransaction
611
- - startTransaction
612
-
613
- </td>
614
- <td width="33%">
615
-
616
- ### 🚀 增强功能
617
-
618
- ✅ **智能缓存**
619
- - TTL 过期策略
620
- - LRU 淘汰策略
621
- - 自动失效机制
622
- - 并发去重
623
- - 多层缓存 (内存+Redis)
624
-
625
- ✅ **便利方法**
626
- - findOneById
627
- - findByIds
628
- - upsertOne
629
- - incrementOne
630
- - findAndCount
631
-
632
- ✅ **性能优化**
633
- - 批量插入优化
634
- - 只读事务优化
635
- - Count 队列控制
636
- - 连接池管理
637
-
638
- ✅ **分布式支持**
639
- - Redis 广播缓存失效
640
- - 分布式锁
641
- - 多实例一致性
642
-
643
- </td>
644
- <td width="33%">
645
-
646
- ### 🛠️ 企业级特性
647
-
648
- ✅ **运维监控**
649
- - 慢查询日志(支持持久化存储)🆕
650
- - 性能指标统计
651
- - 健康检查
652
- - 缓存命中率监控
653
-
654
- ✅ **深度分页**
655
- - 游标分页
656
- - 异步总数统计
657
- - 书签管理
658
- - 跳页优化
659
-
660
- ✅ **数据库管理**
661
- - 跨库访问
662
- - Schema 验证
663
- - 集合管理
664
- - 数据库命令
665
-
666
- ✅ **开发体验**
667
- - TypeScript 支持
668
- - 链式调用 API
669
- - ESM/CommonJS 双模式
670
- - 77% 测试覆盖率
671
-
672
- </td>
673
- </tr>
674
- </table>
675
-
676
- ---
677
-
678
- ## 🆚 与 MongoDB 原生驱动对比
679
-
680
- <table>
681
- <tr>
682
- <th width="25%">特性</th>
683
- <th width="25%">MongoDB 原生</th>
684
- <th width="50%"><strong>monSQLize</strong></th>
685
- </tr>
686
- <tr>
687
- <td><strong>API 兼容性</strong></td>
688
- <td>✅ 原生</td>
689
- <td>✅ 100% 兼容原生,无需学习新 API</td>
690
- </tr>
691
- <tr>
692
- <td><strong>智能缓存</strong></td>
693
- <td>❌ 需要自己实现</td>
694
- <td>✅ 内置 TTL/LRU,开箱即用,10~100倍提升</td>
695
- </tr>
696
- <tr>
697
- <td><strong>性能</strong></td>
698
- <td>⭐⭐⭐ 基准性能</td>
699
- <td>⭐⭐⭐⭐⭐ 缓存命中时性能提升 10~100 倍</td>
700
- </tr>
701
- <tr>
702
- <td><strong>事务支持</strong></td>
703
- <td>⭐⭐ 需要手动管理</td>
704
- <td>⭐⭐⭐⭐⭐ 自动管理生命周期,优化只读操作</td>
705
- </tr>
706
- <tr>
707
- <td><strong>分布式部署</strong></td>
708
- <td>❌ 缓存不一致</td>
709
- <td>✅ Redis 广播自动同步,保证一致性</td>
710
- </tr>
711
- <tr>
712
- <td><strong>便利方法</strong></td>
713
- <td>❌ 需要自己封装</td>
714
- <td>✅ findOneById、findByIds、upsertOne 等</td>
715
- </tr>
716
- <tr>
717
- <td><strong>运维监控</strong></td>
718
- <td>⚠️ 需要额外配置</td>
719
- <td>✅ 慢查询日志、性能统计,开箱即用</td>
720
- </tr>
721
- <tr>
722
- <td><strong>学习成本</strong></td>
723
- <td>⭐⭐⭐ MongoDB 语法</td>
724
- <td>⭐ 零学习成本,API 完全一致</td>
725
- </tr>
726
- <tr>
727
- <td><strong>迁移成本</strong></td>
728
- <td>-</td>
729
- <td>⭐ 只需修改初始化代码,业务代码不变</td>
730
- </tr>
731
- </table>
732
-
733
- ### 📌 何时选择 monSQLize
734
-
735
- ✅ **适合场景**:
736
- - 高并发读取场景(商品详情、用户信息)
737
- - 需要缓存但不想自己实现
738
- - 多实例部署需要缓存一致性
739
- - 希望零学习成本提升性能
740
-
741
- ⚠️ **不适合场景**:
742
- - 纯写入应用(缓存作用有限)
743
- - 实时性要求极高(每次必查最新)
744
- - 简单应用,流量不大(原生驱动足够)
745
-
746
- ---
747
-
748
- ## 🚀 快速迁移指南
749
-
750
- ### 从 MongoDB 原生驱动迁移
751
-
752
- ```javascript
753
- // ❌ 原来的代码
754
- const { MongoClient } = require('mongodb');
755
- const client = await MongoClient.connect('mongodb://localhost:27017');
756
- const db = client.db('mydb');
757
- const users = db.collection('users');
758
-
759
- // ✅ 迁移后的代码(只需改 3 行)
760
- const MonSQLize = require('monsqlize'); // 1. 引入 monSQLize
761
- const db = new MonSQLize({ // 2. 修改初始化
762
- type: 'mongodb',
763
- config: { uri: 'mongodb://localhost:27017/mydb' },
764
- cache: { enabled: true } // 3. 启用缓存
765
- });
766
- await db.connect();
767
- const users = db.collection('users');
768
-
769
- // 🎉 后续所有代码不需要改动,性能提升 10~100 倍!
770
- const user = await users.findOne({ email }); // 完全一样的 API
771
- ```
772
-
773
- ### 渐进式迁移
774
-
775
- ```javascript
776
- // ✅ 可以混用原生驱动和 monSQLize
777
- const nativeClient = await MongoClient.connect('...');
778
- const monsqlize = new MonSQLize({ cache: { enabled: true } });
779
-
780
- // 性能敏感的查询用 monSQLize(启用缓存)
781
- const hotData = await monsqlize.collection('products').find({}, { cache: 60000 });
782
-
783
- // 简单查询用原生驱动
784
- const coldData = await nativeClient.db('mydb').collection('logs').find({});
785
- ```
786
-
787
- ---
788
-
789
- ## 📖 完整文档
790
-
791
- ### 核心文档
792
-
793
- - 📖 [完整 API 文档索引](./docs/INDEX.md)
794
- - 📖 [MongoDB 原生 vs monSQLize 对比](./docs/mongodb-native-vs-extensions.md)
795
- - 📖 [事务使用指南](./docs/transaction.md)
796
- - 📖 [业务级分布式锁](./docs/business-lock.md) 🆕 v1.4.0
797
- - 📖 [SSH隧道使用指南](./docs/ssh-tunnel.md) 🆕 v1.3+
798
- - 📖 [分布式部署指南](./docs/distributed-deployment.md)
799
- - 📖 [性能优化指南](./docs/transaction-optimizations.md)
800
-
801
- ### 功能文档
802
-
803
- **CRUD 操作**:
804
- - [find](./docs/find.md) | [findOne](./docs/findOne.md) | [findPage](./docs/findPage.md)
805
- - [insertOne](./docs/insert-one.md) | [insertMany](./docs/insert-many.md) | [insertBatch](./docs/insertBatch.md)
806
- - [updateOne](./docs/update-one.md) | [updateMany](./docs/update-many.md) | [replaceOne](./docs/replace-one.md)
807
- - [deleteOne](./docs/delete-one.md) | [deleteMany](./docs/delete-many.md)
808
-
809
- **便利方法**:
810
- - [findOneById](./docs/find-one-by-id.md) | [findByIds](./docs/find-by-ids.md)
811
- - [upsertOne](./docs/upsert-one.md) | [incrementOne](./docs/increment-one.md) | [findAndCount](./docs/find-and-count.md)
812
-
813
- **其他功能**:
814
- - [索引管理](./docs/create-index.md) | [聚合查询](./docs/aggregate.md)
815
- - [缓存系统](./docs/cache.md) | [链式调用](./docs/chaining-api.md)
816
-
817
- ### 示例代码
818
-
819
- - 📁 [完整示例代码目录](./examples/) - 50+ 可运行示例
820
-
821
- ---
822
-
823
- ## 🌍 兼容性
824
-
825
- | 环境 | 支持版本 |
826
- |------|---------|
827
- | **Node.js** | 16.x, 18.x, 20.x, 21.x |
828
- | **MongoDB** | 4.4+, 5.x, 6.x, 7.x |
829
- | **MongoDB Driver** | 4.x, 5.x, 6.x, 7.x |
830
- | **模块系统** | CommonJS, ESM |
831
-
832
- [查看完整兼容性矩阵](./docs/COMPATIBILITY.md)
833
-
834
- ---
835
-
836
- ## 🗺️ 产品路线图
837
-
838
- ### ✅ v1.4 (当前版本)
839
-
840
- - ✅ 业务级分布式锁
841
- - ✅ 智能缓存系统
842
- - ✅ 事务优化
843
- - ✅ 便利方法
844
- - ✅ 分布式支持
845
-
846
- ### 🚧 v1.5 (计划中)
847
-
848
- - 🔄 查询分析器
849
- - 🔄 自动索引建议
850
- - 🔄 数据迁移工具
851
- - 🔄 GraphQL 支持
852
-
853
- ### 🔮 v2.0 (未来)
854
-
855
- - 🔮 统一 API 支持 MySQL
856
- - 🔮 统一 API 支持 PostgreSQL
857
- - 🔮 ORM 功能
858
- - 🔮 数据同步中间件
859
-
860
- ---
861
-
862
- ## 🤝 贡献指南
863
-
864
- 我们欢迎所有形式的贡献!
865
-
866
- - 🐛 [提交 Bug](https://github.com/vextjs/monSQLize/issues)
867
- - 💡 [提出新功能](https://github.com/vextjs/monSQLize/issues)
868
- - 📖 [改进文档](https://github.com/vextjs/monSQLize/pulls)
869
- - 💻 [提交代码](https://github.com/vextjs/monSQLize/pulls)
870
-
871
- ### 开发
872
-
873
- ```bash
874
- # 克隆仓库
875
- git clone https://github.com/vextjs/monSQLize.git
876
- cd monSQLize
877
-
878
- # 安装依赖
879
- npm install
880
-
881
- # 运行测试
882
- npm test
883
-
884
- # 运行基准测试
885
- npm run benchmark
886
- ```
887
-
888
- ---
889
-
890
- ## 📄 许可证
891
-
892
- [MIT License](./LICENSE)
893
-
894
- ---
895
-
896
- ## 💬 社区与支持
897
-
898
- - 📧 **Email**: support@monsqlize.dev
899
- - 💬 **Issues**: [GitHub Issues](https://github.com/vextjs/monSQLize/issues)
900
- - 📖 **文档**: [完整文档](./docs/INDEX.md)
901
- - 🌟 **Star**: 如果觉得有用,请给我们一个 Star ⭐
902
-
903
- ---
904
-
905
- ## 🎉 快速链接
906
-
907
- <div align="center">
908
-
909
- **[🚀 快速开始](#-5分钟快速开始)** ·
910
- **[📚 完整文档](./docs/INDEX.md)** ·
911
- **[💻 示例代码](./examples/)** ·
912
- **[🐛 报告问题](https://github.com/vextjs/monSQLize/issues)** ·
913
- **[⭐ Star 项目](https://github.com/vextjs/monSQLize)**
914
-
915
- ---
916
-
917
- ### 让 MongoDB 快 10~100 倍,从现在开始 🚀
918
-
919
- ```bash
920
- npm install monsqlize
921
- ```
922
-
923
- ---
924
-
925
- Made with ❤️ by monSQLize Team
926
-
927
- </div>
928
-
1
+ # monSQLize
2
+
3
+ TypeScript-native MongoDB ODM and enhancement layer with v1-compatible APIs, multi-level caching, distributed locks, transactions, Saga orchestration, model validation, connection pools, Change Stream sync, slow-query logging, and CommonJS / ESM / TypeScript declaration outputs.
4
+
5
+ [![npm version](https://img.shields.io/npm/v/monsqlize.svg)](https://www.npmjs.com/package/monsqlize)
6
+ [![License: Apache-2.0](https://img.shields.io/badge/License-Apache--2.0-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0)
7
+ [![MongoDB](https://img.shields.io/badge/MongoDB-6.x%20%2F%207.x-green.svg)](https://www.mongodb.com/)
8
+ [![Node.js](https://img.shields.io/badge/Node.js-18%2B-brightgreen)](https://nodejs.org/)
9
+
10
+ ```bash
11
+ npm install monsqlize
12
+ ```
13
+
14
+ monSQLize is currently a MongoDB-focused package. The long-term product direction is to keep the MongoDB-style query experience while gradually extending the same high-level API shape to additional database backends.
15
+
16
+ ## Table of Contents
17
+
18
+ - [Why monSQLize](#why-monsqlize)
19
+ - [When to Use It](#when-to-use-it)
20
+ - [Installation](#installation)
21
+ - [Quick Start](#quick-start)
22
+ - [Model Layer](#model-layer)
23
+ - [Caching and Performance](#caching-and-performance)
24
+ - [Advanced Capabilities](#advanced-capabilities)
25
+ - [Migration from the MongoDB Driver](#migration-from-the-mongodb-driver)
26
+ - [Compatibility](#compatibility)
27
+ - [Documentation](#documentation)
28
+ - [Development](#development)
29
+ - [Release Status](#release-status)
30
+ - [Roadmap](#roadmap)
31
+ - [License](#license)
32
+ - [Support](#support)
33
+
34
+ ## Why monSQLize
35
+
36
+ monSQLize keeps the MongoDB driver mental model while adding the production features most teams end up building around it:
37
+
38
+ - Drop-in collection helpers that preserve MongoDB-style CRUD, aggregation, indexes, transactions, and Change Streams.
39
+ - Smart caching through `cache-hub`, including local memory caching, optional Redis-backed L2 caching, automatic invalidation, and function-level caching.
40
+ - A lightweight Model layer with `schema-dsl` validation, hooks, relations, populate, custom methods, timestamps, soft delete, and optimistic locking.
41
+ - Multi-connection-pool support, pool health checks, pool-scoped collections/models, and fallback strategies.
42
+ - Business locks and distributed locks for multi-instance deployments.
43
+ - Saga orchestration for multi-step business workflows.
44
+ - Change Stream sync helpers with resume token storage.
45
+ - Slow-query logging and query diagnostics.
46
+ - CommonJS, ESM, and TypeScript declaration outputs from `dist/**`.
47
+
48
+ ## When to Use It
49
+
50
+ monSQLize is a good fit when you need:
51
+
52
+ | Scenario | Benefit |
53
+ |---|---|
54
+ | High-concurrency reads | Cache hot data and reduce repeated database work. |
55
+ | MongoDB API compatibility | Keep familiar query syntax while adding higher-level helpers. |
56
+ | Multi-instance services | Use Redis invalidation and distributed locks to keep instances coordinated. |
57
+ | Transaction-heavy flows | Use `withTransaction()` and transaction-aware helpers instead of hand-rolled lifecycle code. |
58
+ | Model-level ergonomics | Add schema validation, hooks, populate, and custom methods only where needed. |
59
+ | Smooth upgrade from v1 | Keep legacy application source stable while adopting the TypeScript rewrite. |
60
+
61
+ monSQLize is usually not the best first choice for pure write-heavy workloads, extremely strict real-time reads where every query must bypass cache, or very small applications that do not need the extra operational layer.
62
+
63
+ ## Installation
64
+
65
+ ```bash
66
+ npm install monsqlize
67
+ ```
68
+
69
+ Runtime dependencies installed with the package:
70
+
71
+ - `mongodb` - official MongoDB driver.
72
+ - `schema-dsl` - model schema validation runtime dependency.
73
+ - `cache-hub` - cache and function-cache foundation.
74
+ - `async-lock` - local concurrency lock support.
75
+
76
+ Optional dependencies:
77
+
78
+ - `ioredis` - required only when you enable Redis / L2 cache features.
79
+ - `ssh2` - required only when you connect through an SSH tunnel.
80
+
81
+ ```bash
82
+ npm install ioredis ssh2
83
+ ```
84
+
85
+ ## Quick Start
86
+
87
+ ### CommonJS
88
+
89
+ ```js
90
+ const MonSQLize = require('monsqlize');
91
+
92
+ const db = new MonSQLize({
93
+ type: 'mongodb',
94
+ databaseName: 'mydb',
95
+ config: {
96
+ uri: 'mongodb://localhost:27017'
97
+ },
98
+ cache: {
99
+ enabled: true,
100
+ ttl: 60_000
101
+ }
102
+ });
103
+
104
+ await db.connect();
105
+
106
+ const users = db.collection('users');
107
+
108
+ await users.insertOne({
109
+ username: 'john',
110
+ email: 'john@example.com',
111
+ createdAt: new Date()
112
+ });
113
+
114
+ const user = await users.findOne({ email: 'john@example.com' });
115
+ const userById = await users.findOneById('507f1f77bcf86cd799439011');
116
+
117
+ await users.updateOne(
118
+ { email: 'john@example.com' },
119
+ { $set: { lastLoginAt: new Date() } }
120
+ );
121
+
122
+ await db.close();
123
+ ```
124
+
125
+ ### ESM and TypeScript
126
+
127
+ ```ts
128
+ import MonSQLize from 'monsqlize';
129
+ import type { Collection } from 'monsqlize';
130
+
131
+ const db = new MonSQLize({
132
+ type: 'mongodb',
133
+ databaseName: 'mydb',
134
+ config: {
135
+ uri: 'mongodb://localhost:27017'
136
+ }
137
+ });
138
+
139
+ await db.connect();
140
+
141
+ const users: Collection = db.collection('users');
142
+ const activeUsers = await users.find({ status: 'active' }).toArray();
143
+
144
+ await db.close();
145
+ ```
146
+
147
+ Published entry points:
148
+
149
+ | Format | Entry |
150
+ |---|---|
151
+ | CommonJS | `dist/cjs/index.cjs` |
152
+ | ESM | `dist/esm/index.mjs` |
153
+ | Types | `dist/types/index.d.ts` |
154
+
155
+ The package root exports only the public package contract. Deep imports into historical `lib/**` files are not part of the v2 publishing surface.
156
+
157
+ ## Model Layer
158
+
159
+ The Model layer is optional. Use it when you want schema validation, hooks, relations, populate, custom methods, timestamps, soft delete, or optimistic locking.
160
+
161
+ `schema-dsl` is installed automatically as a runtime dependency of monSQLize. You only need to declare `schema-dsl` in your own app if your application imports it directly.
162
+
163
+ ### Manual Model Registration
164
+
165
+ ```js
166
+ const MonSQLize = require('monsqlize');
167
+ const { Model } = MonSQLize;
168
+
169
+ Model.define('users', {
170
+ schema: (dsl) => dsl({
171
+ username: 'string:3-32!',
172
+ email: 'email!',
173
+ password: 'string:6-!',
174
+ age: 'number:0-120'
175
+ }),
176
+ relations: {
177
+ posts: {
178
+ from: 'posts',
179
+ localField: '_id',
180
+ foreignField: 'userId',
181
+ single: false
182
+ }
183
+ },
184
+ hooks: (model) => ({
185
+ insert: {
186
+ before: async (ctx, doc) => {
187
+ doc.createdAt = new Date();
188
+ return doc;
189
+ }
190
+ }
191
+ }),
192
+ methods: (model) => ({
193
+ instance: {
194
+ checkPassword(password) {
195
+ return this.password === password;
196
+ }
197
+ },
198
+ static: {
199
+ async findByUsername(username) {
200
+ return model.findOne({ username });
201
+ }
202
+ }
203
+ })
204
+ });
205
+
206
+ const db = new MonSQLize({
207
+ type: 'mongodb',
208
+ databaseName: 'mydb',
209
+ config: { uri: 'mongodb://localhost:27017' }
210
+ });
211
+
212
+ await db.connect();
213
+
214
+ const User = db.model('users');
215
+ const user = await User.insertOne({
216
+ username: 'john',
217
+ email: 'john@example.com',
218
+ password: 'secret123',
219
+ age: 25
220
+ });
221
+ ```
222
+
223
+ ### Automatic Model Loading
224
+
225
+ ```js
226
+ const path = require('path');
227
+ const MonSQLize = require('monsqlize');
228
+
229
+ const db = new MonSQLize({
230
+ type: 'mongodb',
231
+ databaseName: 'mydb',
232
+ config: { uri: 'mongodb://localhost:27017' },
233
+ models: path.join(__dirname, 'models')
234
+ });
235
+
236
+ await db.connect();
237
+
238
+ const User = db.model('users');
239
+ ```
240
+
241
+ ```js
242
+ // models/user.model.js
243
+ module.exports = {
244
+ name: 'users',
245
+ schema: (dsl) => dsl({
246
+ username: 'string:3-32!',
247
+ email: 'email!'
248
+ }),
249
+ methods: (model) => ({
250
+ static: {
251
+ async findByUsername(username) {
252
+ return model.findOne({ username });
253
+ }
254
+ }
255
+ })
256
+ };
257
+ ```
258
+
259
+ Relative model paths are resolved from `process.cwd()`. In production services, prefer absolute paths such as `path.join(__dirname, 'models')`.
260
+
261
+ ### Populate
262
+
263
+ ```js
264
+ Model.define('posts', {
265
+ schema: (dsl) => dsl({
266
+ title: 'string:1-200!',
267
+ content: 'string!',
268
+ userId: 'objectId!'
269
+ })
270
+ });
271
+
272
+ const userWithPosts = await User.findOne({ username: 'john' })
273
+ .populate('posts', {
274
+ select: 'title content',
275
+ match: { status: 'published' },
276
+ sort: { createdAt: -1 },
277
+ limit: 10
278
+ });
279
+ ```
280
+
281
+ Populate is supported by `find()`, `findOne()`, `findByIds()`, `findOneById()`, `findAndCount()`, and `findPage()`.
282
+
283
+ ## Caching and Performance
284
+
285
+ monSQLize can cache collection queries and arbitrary async functions.
286
+
287
+ ```js
288
+ const users = db.collection('users');
289
+
290
+ const hotUser = await users.findOne(
291
+ { email: 'john@example.com' },
292
+ { cache: 60_000 }
293
+ );
294
+ ```
295
+
296
+ ```js
297
+ const { withCache } = require('monsqlize');
298
+
299
+ async function getUserProfile(userId) {
300
+ const user = await db.collection('users').findOneById(userId);
301
+ const orders = await db.collection('orders').find({ userId }).toArray();
302
+ return { user, orders };
303
+ }
304
+
305
+ const cachedGetUserProfile = withCache(getUserProfile, {
306
+ ttl: 300_000,
307
+ cache: db.getCache()
308
+ });
309
+
310
+ await cachedGetUserProfile('user-1');
311
+ ```
312
+
313
+ Cache capabilities include:
314
+
315
+ - In-memory L1 cache.
316
+ - Optional Redis-backed L2 cache.
317
+ - Automatic invalidation after writes.
318
+ - Function-level caching through `withCache()`.
319
+ - In-flight request deduplication.
320
+ - Namespaces, TTLs, statistics, and conditional caching.
321
+
322
+ ## Advanced Capabilities
323
+
324
+ ### Transactions
325
+
326
+ ```js
327
+ await db.withTransaction(async (session) => {
328
+ await db.collection('orders').insertOne({ userId, status: 'pending' }, { session });
329
+ await db.collection('users').updateOne(
330
+ { _id: userId },
331
+ { $inc: { orderCount: 1 } },
332
+ { session }
333
+ );
334
+ });
335
+ ```
336
+
337
+ ### Connection Pools
338
+
339
+ ```js
340
+ const db = new MonSQLize({
341
+ type: 'mongodb',
342
+ databaseName: 'main',
343
+ config: { uri: 'mongodb://primary:27017' },
344
+ pools: [
345
+ { name: 'analytics', uri: 'mongodb://analytics:27017' }
346
+ ]
347
+ });
348
+
349
+ const reports = db.pool('analytics').collection('reports');
350
+ ```
351
+
352
+ ### Distributed Locks
353
+
354
+ ```js
355
+ await db.withLock('inventory:sku-1', async () => {
356
+ await db.collection('inventory').updateOne(
357
+ { sku: 'sku-1' },
358
+ { $inc: { stock: -1 } }
359
+ );
360
+ });
361
+ ```
362
+
363
+ ### Change Streams
364
+
365
+ ```js
366
+ const watcher = db.collection('orders').watch([
367
+ { $match: { 'fullDocument.status': 'pending' } }
368
+ ]);
369
+
370
+ watcher.on('change', (change) => {
371
+ console.log('Order changed:', change.fullDocument);
372
+ });
373
+ ```
374
+
375
+ ### Saga Orchestration
376
+
377
+ ```js
378
+ db.defineSaga('checkout', [
379
+ {
380
+ name: 'reserveInventory',
381
+ execute: async (ctx) => reserveInventory(ctx),
382
+ compensate: async (ctx) => releaseInventory(ctx)
383
+ },
384
+ {
385
+ name: 'chargePayment',
386
+ execute: async (ctx) => chargePayment(ctx),
387
+ compensate: async (ctx) => refundPayment(ctx)
388
+ }
389
+ ]);
390
+
391
+ await db.executeSaga('checkout', { orderId });
392
+ ```
393
+
394
+ ## Migration from the MongoDB Driver
395
+
396
+ The smallest migration is usually to replace only initialization:
397
+
398
+ ```js
399
+ const { MongoClient } = require('mongodb');
400
+
401
+ const nativeClient = await MongoClient.connect('mongodb://localhost:27017');
402
+ const nativeUsers = nativeClient.db('mydb').collection('users');
403
+ ```
404
+
405
+ ```js
406
+ const MonSQLize = require('monsqlize');
407
+
408
+ const db = new MonSQLize({
409
+ type: 'mongodb',
410
+ databaseName: 'mydb',
411
+ config: { uri: 'mongodb://localhost:27017' },
412
+ cache: { enabled: true }
413
+ });
414
+
415
+ await db.connect();
416
+ const users = db.collection('users');
417
+ ```
418
+
419
+ MongoDB-style collection calls can remain unchanged in most cases:
420
+
421
+ ```js
422
+ const user = await users.findOne({ email });
423
+ const list = await users.find({ status: 'active' }).toArray();
424
+ ```
425
+
426
+ The current v2.0.0 release candidate has been validated against the workspace consumers `chat`, `payment`, `user`, `admin`, `search`, `vext`, and `permission-core` without requiring business-source changes in those projects.
427
+
428
+ ## Compatibility
429
+
430
+ | Surface | Current Support |
431
+ |---|---|
432
+ | Node.js | `>=18.0.0`; CI covers Node 18 / 20 / 22. |
433
+ | MongoDB driver | `mongodb@^6.21.0` baseline; driver 7 has additional compatibility coverage. |
434
+ | MongoDB server | Memory-server based 6.x / 7.x validation is covered by the project test matrix. |
435
+ | Module systems | CommonJS and ESM are both validated. |
436
+ | TypeScript | Public declarations are published from `dist/types/index.d.ts`. |
437
+ | Package license | Apache-2.0. |
438
+
439
+ See the current support and verification documents:
440
+
441
+ - [docs/README.md](https://github.com/vextjs/monSQLize/blob/main/docs/README.md)
442
+ - [docs/support-matrix.md](https://github.com/vextjs/monSQLize/blob/main/docs/support-matrix.md)
443
+ - [docs/verification-entrypoints.md](https://github.com/vextjs/monSQLize/blob/main/docs/verification-entrypoints.md)
444
+ - [test/compatibility/README.md](https://github.com/vextjs/monSQLize/blob/main/test/compatibility/README.md)
445
+ - [test/validation/VERIFICATION-PROGRESS.md](https://github.com/vextjs/monSQLize/blob/main/test/validation/VERIFICATION-PROGRESS.md)
446
+
447
+ ## Documentation
448
+
449
+ Current TypeScript documentation and examples are the source of truth for the v2 package:
450
+
451
+ - `docs/**` - current documentation.
452
+ - `examples/**` - TypeScript examples.
453
+ - `test/compatibility/**` - package exports and compatibility guards.
454
+ - `test/validation/**` - verification ledgers and mapping notes.
455
+
456
+ Historical v1 assets are useful for tracing old behavior, but they are not the current publishing surface for v2.
457
+
458
+ ## Development
459
+
460
+ ```bash
461
+ git clone https://github.com/vextjs/monSQLize.git
462
+ cd monSQLize
463
+ npm install
464
+ ```
465
+
466
+ Common commands:
467
+
468
+ ```bash
469
+ npm run build
470
+ npm run type-check
471
+ npm test
472
+ npm run verify:fast
473
+ npm run release:preflight
474
+ ```
475
+
476
+ Release preflight runs linting, type checks, size guards, runtime checks, compatibility checks, refactor guards, the default test suite, and `npm pack --dry-run`.
477
+
478
+ `npm run release:publish` runs the preflight gate once and then calls `npm publish --ignore-scripts` so the final publish step does not repeat the full lifecycle gate. Raw `npm publish` is still guarded by `prepublishOnly`.
479
+
480
+ Optional commands:
481
+
482
+ ```bash
483
+ npm run test:examples
484
+ npm run test:coverage
485
+ npm run test:server-matrix
486
+ npm run test:real-env:private
487
+ ```
488
+
489
+ `test:real-env:private` is intentionally opt-in and expects private environment variables. It is not part of the default CI or release gate.
490
+
491
+ ## Release Status
492
+
493
+ The current release candidate is `v2.0.0`.
494
+
495
+ Key release-readiness points:
496
+
497
+ - TypeScript rewrite completed for the current runtime and test entry points.
498
+ - Package exports are consolidated under `dist/cjs`, `dist/esm`, and `dist/types`.
499
+ - npm packages include the runtime bundles and declaration files only; source maps are disabled by default and can be generated locally with `MONSQLIZE_BUILD_SOURCEMAPS=1 npm run build`.
500
+ - v1 smooth-upgrade compatibility has been validated against the target workspace consumers.
501
+ - `schema-dsl` follows the npm `latest` TypeScript line `^2.0.3`; deprecated `2.3.x` mistake releases are intentionally excluded.
502
+ - GitHub Actions publishes to npm from `v*` tags after running `npm run release:preflight`; the publish step skips duplicate lifecycle scripts because the gate already ran in the same job.
503
+
504
+ ## Roadmap
505
+
506
+ ### v2.0.0
507
+
508
+ - TypeScript-native runtime and declarations.
509
+ - v1 smooth-upgrade compatibility bridge.
510
+ - Multi-level cache and function-cache support through `cache-hub`.
511
+ - Transactions, business locks, distributed locks, Saga orchestration, connection pools, Change Stream sync, and slow-query logging.
512
+ - Model layer with `schema-dsl` validation, relations, populate, hooks, and custom methods.
513
+
514
+ ### v2.x
515
+
516
+ - Query analyzer improvements.
517
+ - Automatic index suggestions.
518
+ - Migration tooling.
519
+ - GraphQL integration experiments.
520
+ - More real-environment validation coverage.
521
+
522
+ ### v3.0+
523
+
524
+ - Unified API experiments for MySQL.
525
+ - Unified API experiments for PostgreSQL.
526
+ - Broader ORM capabilities.
527
+ - Cross-database sync middleware.
528
+
529
+ ## License
530
+
531
+ monSQLize is released under the [Apache License 2.0](./LICENSE).
532
+
533
+ ## Support
534
+
535
+ - Issues: [GitHub Issues](https://github.com/vextjs/monSQLize/issues)
536
+ - npm: [monsqlize](https://www.npmjs.com/package/monsqlize)
537
+ - Website: [https://vextjs.github.io/monSQLize/](https://vextjs.github.io/monSQLize/)