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.
- package/CHANGELOG.md +415 -146
- package/LICENSE +201 -21
- package/README.md +537 -928
- package/changelogs/README.md +160 -0
- package/changelogs/v2.0.0.md +222 -0
- package/dist/cjs/index.cjs +10600 -0
- package/dist/cjs/mongodb/common/transaction-aware.cjs +10 -0
- package/dist/cjs/transaction/CacheLockManager.cjs +100 -0
- package/dist/cjs/transaction/Transaction.cjs +158 -0
- package/dist/cjs/transaction/TransactionManager.cjs +298 -0
- package/dist/esm/index.mjs +10650 -0
- package/dist/types/base.d.ts +81 -0
- package/dist/types/collection.d.ts +1031 -0
- package/dist/types/expression.d.ts +115 -0
- package/dist/types/index.d.ts +23 -0
- package/dist/types/lock.d.ts +74 -0
- package/dist/types/model.d.ts +526 -0
- package/dist/types/mongodb.d.ts +49 -0
- package/dist/types/monsqlize.d.ts +491 -0
- package/dist/types/pool.d.ts +84 -0
- package/dist/types/runtime.d.ts +362 -0
- package/dist/types/saga.d.ts +143 -0
- package/dist/types/slow-query-log.d.ts +126 -0
- package/dist/types/sync.d.ts +103 -0
- package/dist/types/transaction.d.ts +132 -0
- package/package.json +69 -67
- package/index.d.ts +0 -1289
- package/lib/cache.js +0 -491
- package/lib/common/cursor.js +0 -58
- package/lib/common/docs-urls.js +0 -72
- package/lib/common/index-options.js +0 -222
- package/lib/common/log.js +0 -60
- package/lib/common/namespace.js +0 -21
- package/lib/common/normalize.js +0 -33
- package/lib/common/page-result.js +0 -42
- package/lib/common/runner.js +0 -56
- package/lib/common/server-features.js +0 -231
- package/lib/common/shape-builders.js +0 -26
- package/lib/common/validation.js +0 -112
- package/lib/connect.js +0 -76
- package/lib/constants.js +0 -54
- package/lib/count-queue.js +0 -187
- package/lib/distributed-cache-invalidator.js +0 -259
- package/lib/errors.js +0 -167
- package/lib/index.js +0 -461
- package/lib/infrastructure/ssh-tunnel-ssh2.js +0 -211
- package/lib/infrastructure/ssh-tunnel.js +0 -40
- package/lib/infrastructure/uri-parser.js +0 -35
- package/lib/lock/Lock.js +0 -66
- package/lib/lock/errors.js +0 -27
- package/lib/lock/index.js +0 -12
- package/lib/logger.js +0 -224
- package/lib/model/examples/test.js +0 -114
- package/lib/mongodb/common/accessor-helpers.js +0 -58
- package/lib/mongodb/common/agg-pipeline.js +0 -32
- package/lib/mongodb/common/iid.js +0 -27
- package/lib/mongodb/common/lexicographic-expr.js +0 -52
- package/lib/mongodb/common/shape.js +0 -31
- package/lib/mongodb/common/sort.js +0 -38
- package/lib/mongodb/common/transaction-aware.js +0 -24
- package/lib/mongodb/connect.js +0 -233
- package/lib/mongodb/index.js +0 -591
- package/lib/mongodb/management/admin-ops.js +0 -199
- package/lib/mongodb/management/bookmark-ops.js +0 -166
- package/lib/mongodb/management/cache-ops.js +0 -49
- package/lib/mongodb/management/collection-ops.js +0 -386
- package/lib/mongodb/management/database-ops.js +0 -201
- package/lib/mongodb/management/index-ops.js +0 -474
- package/lib/mongodb/management/index.js +0 -16
- package/lib/mongodb/management/namespace.js +0 -30
- package/lib/mongodb/management/validation-ops.js +0 -267
- package/lib/mongodb/queries/aggregate.js +0 -142
- package/lib/mongodb/queries/chain.js +0 -630
- package/lib/mongodb/queries/count.js +0 -98
- package/lib/mongodb/queries/distinct.js +0 -77
- package/lib/mongodb/queries/find-and-count.js +0 -192
- package/lib/mongodb/queries/find-by-ids.js +0 -235
- package/lib/mongodb/queries/find-one-by-id.js +0 -170
- package/lib/mongodb/queries/find-one.js +0 -70
- package/lib/mongodb/queries/find-page.js +0 -577
- package/lib/mongodb/queries/find.js +0 -170
- package/lib/mongodb/queries/index.js +0 -50
- package/lib/mongodb/queries/watch.js +0 -537
- package/lib/mongodb/writes/delete-many.js +0 -190
- package/lib/mongodb/writes/delete-one.js +0 -182
- package/lib/mongodb/writes/find-one-and-delete.js +0 -202
- package/lib/mongodb/writes/find-one-and-replace.js +0 -238
- package/lib/mongodb/writes/find-one-and-update.js +0 -239
- package/lib/mongodb/writes/increment-one.js +0 -252
- package/lib/mongodb/writes/index.js +0 -41
- package/lib/mongodb/writes/insert-batch.js +0 -507
- package/lib/mongodb/writes/insert-many.js +0 -227
- package/lib/mongodb/writes/insert-one.js +0 -180
- package/lib/mongodb/writes/replace-one.js +0 -215
- package/lib/mongodb/writes/result-handler.js +0 -236
- package/lib/mongodb/writes/update-many.js +0 -221
- package/lib/mongodb/writes/update-one.js +0 -223
- package/lib/mongodb/writes/upsert-one.js +0 -206
- package/lib/multi-level-cache.js +0 -189
- package/lib/operators.js +0 -330
- package/lib/redis-cache-adapter.js +0 -237
- package/lib/slow-query-log/base-storage.js +0 -69
- package/lib/slow-query-log/batch-queue.js +0 -96
- package/lib/slow-query-log/config-manager.js +0 -195
- package/lib/slow-query-log/index.js +0 -237
- package/lib/slow-query-log/mongodb-storage.js +0 -323
- package/lib/slow-query-log/query-hash.js +0 -38
- package/lib/transaction/CacheLockManager.js +0 -161
- package/lib/transaction/DistributedCacheLockManager.js +0 -474
- package/lib/transaction/Transaction.js +0 -314
- package/lib/transaction/TransactionManager.js +0 -266
- package/lib/transaction/index.js +0 -10
- package/lib/utils/objectid-converter.js +0 -566
package/README.md
CHANGED
|
@@ -1,928 +1,537 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
- [
|
|
28
|
-
- [
|
|
29
|
-
- [
|
|
30
|
-
- [
|
|
31
|
-
- [
|
|
32
|
-
- [
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
-
|
|
43
|
-
-
|
|
44
|
-
-
|
|
45
|
-
-
|
|
46
|
-
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
const
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
const
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
})
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
```
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
const
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
```
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
})
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
```
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
await
|
|
416
|
-
|
|
417
|
-
```
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
```
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
###
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
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
|
+
[](https://www.npmjs.com/package/monsqlize)
|
|
6
|
+
[](https://www.apache.org/licenses/LICENSE-2.0)
|
|
7
|
+
[](https://www.mongodb.com/)
|
|
8
|
+
[](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/)
|