monsqlize 2.0.6 → 3.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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # monSQLize
2
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.
3
+ Database-native production data runtime layer for TypeScript services. monSQLize keeps database semantics explicit while adding shared runtime capabilities for caching, transactions, connection pools, models, synchronization, observability, and CommonJS / ESM / TypeScript declaration outputs.
4
4
 
5
5
  [![npm version](https://img.shields.io/npm/v/monsqlize.svg)](https://www.npmjs.com/package/monsqlize)
6
6
  [![License: Apache-2.0](https://img.shields.io/badge/License-Apache--2.0-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0)
@@ -8,45 +8,64 @@ TypeScript-native MongoDB ODM and enhancement layer with v1-compatible APIs, mul
8
8
  [![Node.js](https://img.shields.io/badge/Node.js-18%2B-brightgreen)](https://nodejs.org/)
9
9
 
10
10
  Documentation: [English](https://vextjs.github.io/monSQLize/) · [简体中文](https://vextjs.github.io/monSQLize/zh/)
11
+ Quick path: [Installation](https://vextjs.github.io/monSQLize/getting-started) · [Basic Usage](https://vextjs.github.io/monSQLize/basic-operations)
12
+ Configuration reference: [English](https://vextjs.github.io/monSQLize/configuration) · [简体中文](https://vextjs.github.io/monSQLize/zh/configuration)
13
+ Upgrade and security: [Migration Guide](./MIGRATION.md) · [Private Vulnerability Reporting](./SECURITY.md)
14
+
15
+ The npm `latest` dist-tag and GitHub Pages are the stable channel; `main` may contain the next release. Pages deployment accepts only a versioned Git tag whose package version is already present on npm, so unpublished APIs are not promoted as stable documentation.
11
16
 
12
17
  ```bash
13
18
  npm install monsqlize
14
19
  ```
15
20
 
16
- 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.
17
-
18
- ## Table of Contents
19
-
20
- - [Why monSQLize](#why-monsqlize)
21
- - [When to Use It](#when-to-use-it)
22
- - [Installation](#installation)
23
- - [Quick Start](#quick-start)
24
- - [Model Layer](#model-layer)
25
- - [Caching and Performance](#caching-and-performance)
26
- - [Advanced Capabilities](#advanced-capabilities)
27
- - [Migration from the MongoDB Driver](#migration-from-the-mongodb-driver)
28
- - [Compatibility](#compatibility)
29
- - [Documentation](#documentation)
30
- - [Development](#development)
31
- - [Release Status](#release-status)
32
- - [Roadmap](#roadmap)
33
- - [License](#license)
34
- - [Support](#support)
21
+ MongoDB is the first complete adapter. MySQL and PostgreSQL adapters are planned as database-native runtime adapters, not as a transparent promise that every database already accepts the same query syntax.
35
22
 
36
23
  ## Why monSQLize
37
24
 
38
- monSQLize keeps the MongoDB driver mental model while adding the production features most teams end up building around it:
25
+ monSQLize is not an ORM and it is not just a CRUD wrapper. It is a production data runtime layer: the database driver remains visible, while the operational features teams usually build around the driver are provided in one runtime.
39
26
 
40
- - Drop-in collection helpers that preserve MongoDB-style CRUD, aggregation, indexes, transactions, and Change Streams.
41
- - Smart caching through `cache-hub`, including local memory caching, optional Redis-backed L2 caching, automatic invalidation, and function-level caching.
27
+ - Database-native adapter APIs: the current stable adapter preserves MongoDB-style CRUD, aggregation, indexes, transactions, and Change Streams.
28
+ - Smart database caching through `cache-hub`, including local memory caching, optional Redis-backed L2 caching, and automatic invalidation.
42
29
  - A lightweight Model layer with `schema-dsl` validation, hooks, relations, populate, custom methods, timestamps, soft delete, optimistic locking, and production-safe index preflight.
43
30
  - Multi-connection-pool support, pool health checks, pool-scoped collections/models, and fallback strategies.
44
- - Business locks and distributed locks for multi-instance deployments.
45
- - Saga orchestration for multi-step business workflows.
46
31
  - Change Stream sync helpers with resume token storage.
47
32
  - Slow-query logging and query diagnostics.
48
33
  - CommonJS, ESM, and TypeScript declaration outputs from `dist/**`.
49
34
 
35
+ ## Adapter Status
36
+
37
+ | Adapter | Current status | Public entry |
38
+ |---|---|---|
39
+ | MongoDB | Stable and fully implemented | `type: 'mongodb'`, `collection()`, `db()`, `use()`, `pool()` |
40
+ | MySQL | Planned / in development | Not part of the current npm runtime yet |
41
+ | PostgreSQL | Planned / in development | Not part of the current npm runtime yet |
42
+
43
+ The shared runtime direction is cache consistency, connection lifecycle, transaction helpers, model constraints, synchronization, and observability across adapters. Adapter-native query, transaction, and connection semantics will stay explicit.
44
+
45
+ ## Runtime Consistency Contract
46
+
47
+ monSQLize coordinates cache, transactions, sync, and queues inside the runtime, but it does not provide a global strict-consistency kernel. MongoDB transactions keep MongoDB session ACID semantics. Query caching is opt-in, and write-side cache invalidation is explicit: use `cache.invalidate` for precise entries or `autoInvalidate` / `cache.autoInvalidate` for broad invalidation. Cache invalidation runs after successful writes or transaction commit and is best-effort; Redis/L2 cache and Pub/Sub invalidation provide eventual cross-instance coherence rather than atomic cache/DB commits. Change Stream sync is at-least-once; custom targets should be idempotent by change event `_id`, and `sync.idempotency` can record per-target replay markers when a durable store is provided. Transaction cache locks are process-local in the v2 runtime; use explicit business coordination, idempotency/fencing, or cache bypassing for cross-instance strict flows.
48
+
49
+ ## Write Path Policy
50
+
51
+ By default, both `collection()` and `model()` may write. Applications that want all writes for selected namespaces to pass through Model defaults, hooks, timestamps, versioning, and soft-delete rules can enable `writePathPolicy`.
52
+
53
+ ```ts
54
+ const msq = new MonSQLize({
55
+ type: 'mongodb',
56
+ databaseName: 'app',
57
+ config: { uri: 'mongodb://localhost:27017' },
58
+ writePathPolicy: {
59
+ default: 'model-only',
60
+ namespaces: {
61
+ 'app.audit_logs': 'allow-both'
62
+ }
63
+ }
64
+ });
65
+ ```
66
+
67
+ `model-only` blocks direct collection/db/legacy write surfaces by default, including raw access and `$out` / `$merge` aggregate writes, while Model write and Model management methods remain available. See [Write Path Policy](./docs/en/write-path-policy.md).
68
+
50
69
  ## When to Use It
51
70
 
52
71
  monSQLize is a good fit when you need:
@@ -54,8 +73,9 @@ monSQLize is a good fit when you need:
54
73
  | Scenario | Benefit |
55
74
  |---|---|
56
75
  | High-concurrency reads | Cache hot data and reduce repeated database work. |
57
- | MongoDB API compatibility | Keep familiar query syntax while adding higher-level helpers. |
58
- | Multi-instance services | Use Redis invalidation and distributed locks to keep instances coordinated. |
76
+ | MongoDB API compatibility today | Keep familiar MongoDB syntax while adding higher-level runtime helpers. |
77
+ | A future multi-database runtime boundary | Prepare for MySQL/PostgreSQL adapters without turning SQL into fake MongoDB syntax. |
78
+ | Multi-instance services | Use Redis invalidation and pool health checks to keep instances coordinated. |
59
79
  | Transaction-heavy flows | Use `withTransaction()` and transaction-aware helpers instead of hand-rolled lifecycle code. |
60
80
  | Model-level ergonomics | Add schema validation, hooks, populate, and custom methods only where needed. |
61
81
  | Smooth upgrade from v1 | Keep legacy application source stable while adopting the TypeScript rewrite. |
@@ -68,37 +88,32 @@ monSQLize is usually not the best first choice for pure write-heavy workloads, e
68
88
  npm install monsqlize
69
89
  ```
70
90
 
71
- Runtime dependencies installed with the package:
72
-
73
- - `mongodb` - official MongoDB driver.
74
- - `schema-dsl` - model schema validation runtime dependency.
75
- - `cache-hub` - cache and function-cache foundation.
76
- - `async-lock` - local concurrency lock support.
77
- - `ioredis` - Redis-backed L2 cache, distributed invalidation, and distributed lock support.
78
- - `ssh2` - SSH tunnel support for restricted/private network deployment.
91
+ Use Node.js 18 or newer and provide a MongoDB connection URI. Optional Redis, SSH tunnel, cache, Model, and sync features are configured only when your application enables them.
79
92
 
80
93
  ## Quick Start
81
94
 
95
+ The current stable quick start uses the MongoDB adapter.
96
+
82
97
  ### CommonJS
83
98
 
84
99
  ```js
85
100
  const MonSQLize = require('monsqlize');
86
101
 
87
- const db = new MonSQLize({
102
+ const msq = new MonSQLize({
88
103
  type: 'mongodb',
89
104
  databaseName: 'mydb',
90
105
  config: {
91
106
  uri: 'mongodb://localhost:27017'
92
107
  },
93
108
  cache: {
94
- enabled: true,
95
- ttl: 60_000
109
+ maxEntries: 10000,
110
+ defaultTtl: 60_000
96
111
  }
97
112
  });
98
113
 
99
- await db.connect();
114
+ await msq.connect();
100
115
 
101
- const users = db.collection('users');
116
+ const users = msq.collection('users');
102
117
 
103
118
  await users.insertOne({
104
119
  username: 'john',
@@ -107,23 +122,25 @@ await users.insertOne({
107
122
  });
108
123
 
109
124
  const user = await users.findOne({ email: 'john@example.com' });
110
- const userById = await users.findOneById('507f1f77bcf86cd799439011');
125
+ const sameUser = await users.findOne({ _id: '507f1f77bcf86cd799439011' });
111
126
 
112
127
  await users.updateOne(
113
128
  { email: 'john@example.com' },
114
129
  { $set: { lastLoginAt: new Date() } }
115
130
  );
116
131
 
117
- await db.close();
132
+ await msq.close();
118
133
  ```
119
134
 
135
+ Next, use the [Basic Usage guide](https://vextjs.github.io/monSQLize/basic-operations) for common CRUD, pagination, read cache, and Model entry-point examples.
136
+
120
137
  ### ESM and TypeScript
121
138
 
122
139
  ```ts
123
140
  import MonSQLize from 'monsqlize';
124
141
  import type { Collection } from 'monsqlize';
125
142
 
126
- const db = new MonSQLize({
143
+ const msq = new MonSQLize({
127
144
  type: 'mongodb',
128
145
  databaseName: 'mydb',
129
146
  config: {
@@ -131,12 +148,12 @@ const db = new MonSQLize({
131
148
  }
132
149
  });
133
150
 
134
- await db.connect();
151
+ await msq.connect();
135
152
 
136
- const users: Collection = db.collection('users');
153
+ const users: Collection = msq.collection('users');
137
154
  const activeUsers = await users.find({ status: 'active' }).toArray();
138
155
 
139
- await db.close();
156
+ await msq.close();
140
157
  ```
141
158
 
142
159
  Published entry points:
@@ -153,7 +170,7 @@ The package root exports only the public package contract. Deep imports into his
153
170
 
154
171
  The Model layer is optional. Use it when you want schema validation, hooks, relations, populate, custom methods, timestamps, soft delete, or optimistic locking.
155
172
 
156
- `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.
173
+ Models use the current `schema-dsl/runtime` path through monSQLize. monSQLize creates an isolated schema runtime for each `MonSQLize` instance, then compiles Model schema callbacks when a Model is bound to that runtime.
157
174
 
158
175
  ### Manual Model Registration
159
176
 
@@ -162,7 +179,7 @@ const MonSQLize = require('monsqlize');
162
179
  const { Model } = MonSQLize;
163
180
 
164
181
  Model.define('users', {
165
- schema: (dsl) => dsl({
182
+ schema: (s) => s({
166
183
  username: 'string:3-32!',
167
184
  email: 'email!',
168
185
  password: 'string:6-!',
@@ -198,15 +215,15 @@ Model.define('users', {
198
215
  })
199
216
  });
200
217
 
201
- const db = new MonSQLize({
218
+ const msq = new MonSQLize({
202
219
  type: 'mongodb',
203
220
  databaseName: 'mydb',
204
221
  config: { uri: 'mongodb://localhost:27017' }
205
222
  });
206
223
 
207
- await db.connect();
224
+ await msq.connect();
208
225
 
209
- const User = db.model('users');
226
+ const User = msq.model('users');
210
227
  const user = await User.insertOne({
211
228
  username: 'john',
212
229
  email: 'john@example.com',
@@ -215,29 +232,58 @@ const user = await User.insertOne({
215
232
  });
216
233
  ```
217
234
 
235
+ When a service needs runtime-local custom types, messages, locale, or an already-owned schema-dsl runtime, configure `schemaDsl` on the MonSQLize instance:
236
+
237
+ ```js
238
+ const { createRuntime } = require('schema-dsl/runtime');
239
+
240
+ const schemaRuntime = createRuntime({
241
+ types: {
242
+ tenantId: { type: 'string', pattern: '^tenant_[a-z0-9]+$' }
243
+ }
244
+ });
245
+
246
+ Model.define('tenantUsers', {
247
+ schema: (s) => s({
248
+ tenantId: 'tenantId!',
249
+ email: 'email!'
250
+ })
251
+ });
252
+
253
+ const msq = new MonSQLize({
254
+ type: 'mongodb',
255
+ databaseName: 'mydb',
256
+ config: { uri: 'mongodb://localhost:27017' },
257
+ schemaDsl: { runtime: schemaRuntime }
258
+ });
259
+ ```
260
+
261
+ For monSQLize-only Model validation, no direct application import from `schema-dsl` is required. Direct application imports should use `schema-dsl/runtime` when they need to share the same isolated runtime state with monSQLize.
262
+ Use `schemaDsl: { extensions }` when monSQLize should own the runtime and register extension definitions. When the application owns the schema-dsl lifecycle, configure that runtime directly, including `runtime.registerExtensions([...])`, and inject it with `schemaDsl: { runtime }`. If the default `schema-dsl/runtime` entry cannot be resolved or does not expose the required runtime APIs, monSQLize throws `INVALID_CONFIG`; validation is disabled only when `schemaDsl: false` or `schemaDsl: { enabled: false }` is set explicitly.
263
+
218
264
  ### Automatic Model Loading
219
265
 
220
266
  ```js
221
267
  const path = require('path');
222
268
  const MonSQLize = require('monsqlize');
223
269
 
224
- const db = new MonSQLize({
270
+ const msq = new MonSQLize({
225
271
  type: 'mongodb',
226
272
  databaseName: 'mydb',
227
273
  config: { uri: 'mongodb://localhost:27017' },
228
274
  models: path.join(__dirname, 'models')
229
275
  });
230
276
 
231
- await db.connect();
277
+ await msq.connect();
232
278
 
233
- const User = db.model('users');
279
+ const User = msq.model('users');
234
280
  ```
235
281
 
236
282
  ```js
237
283
  // models/user.model.js
238
284
  module.exports = {
239
285
  name: 'users',
240
- schema: (dsl) => dsl({
286
+ schema: (s) => s({
241
287
  username: 'string:3-32!',
242
288
  email: 'email!'
243
289
  }),
@@ -258,27 +304,56 @@ Relative model paths are resolved from `process.cwd()`. In production services,
258
304
  Model-declared indexes are still created automatically by default for backward compatibility. Production services can turn off automatic indexing and run an explicit preflight before creating missing indexes:
259
305
 
260
306
  ```js
261
- const db = new MonSQLize({
307
+ const msq = new MonSQLize({
262
308
  type: 'mongodb',
263
309
  databaseName: 'mydb',
264
310
  config: { uri: 'mongodb://localhost:27017' },
265
311
  autoIndex: false
266
312
  });
267
313
 
268
- const plan = await db.ensureModelIndexes({ models: ['users'], dryRun: true });
314
+ const plan = await msq.ensureModelIndexes({ models: ['users'], dryRun: true });
269
315
 
270
316
  if (plan.totals.conflicts === 0) {
271
- await db.ensureModelIndexes({ models: ['users'], throwOnError: true });
317
+ await msq.ensureModelIndexes({ models: ['users'], throwOnError: true });
272
318
  }
273
319
  ```
274
320
 
275
321
  `ensureModelIndexes()` creates only missing indexes. It does not drop, rename, or rebuild conflicting indexes.
276
322
 
323
+ ### Versioned Writes
324
+
325
+ Models with `options.version` use single-document optimistic concurrency control. When the filter contains a direct `_id`, monSQLize reads the current version automatically. You can still pass an explicit version in the filter or as `expectedVersion` when you want to control the expected version yourself:
326
+
327
+ ```js
328
+ await User.updateOne(
329
+ { _id: userId },
330
+ { $set: { status: 'active' } }
331
+ );
332
+
333
+ await User.replaceOne(
334
+ { _id: userId },
335
+ nextUser,
336
+ { expectedVersion: user.version }
337
+ );
338
+ ```
339
+
340
+ Successful `save()`, `updateOne()`, `replaceOne()`, `findOneAndUpdate()`, and `findOneAndReplace()` advance the version. Stale writes throw a `WRITE_CONFLICT` error.
341
+
342
+ For `updateMany()` and `updateBatch()`, choose the batch version behavior explicitly when needed:
343
+
344
+ ```js
345
+ await User.updateMany({ status: 'pending' }, { $set: { status: 'active' } }, {
346
+ versionMode: 'strict' // 'counter' | 'strict' | 'off'
347
+ });
348
+ ```
349
+
350
+ `counter` is the default and only increments the version counter; it is not optimistic locking. `strict` pre-reads matching document IDs and versions, conditionally updates each document, and returns `conflictCount` / `conflictedIds` on the result object.
351
+
277
352
  ### Populate
278
353
 
279
354
  ```js
280
355
  Model.define('posts', {
281
- schema: (dsl) => dsl({
356
+ schema: (s) => s({
282
357
  title: 'string:1-200!',
283
358
  content: 'string!',
284
359
  userId: 'objectId!'
@@ -296,12 +371,20 @@ const userWithPosts = await User.findOne({ username: 'john' })
296
371
 
297
372
  Populate is supported by `find()`, `findOne()`, `findByIds()`, `findOneById()`, `findAndCount()`, and `findPage()`.
298
373
 
374
+ For has-many relations, `skip` and `limit` are applied per parent document after related records are grouped. Nested populate has a default `maxDepth` of `5`; set `maxDepth` on a populate branch when a self-referencing relation needs a different cap.
375
+
376
+ ### Soft Delete Visibility
377
+
378
+ When `softDelete` is enabled, standard model read paths hide deleted documents by default: `find()`, `findOne()`, `findOneById()`, `findByIds()`, `findPage()`, `findAndCount()`, `count()`, `distinct()`, `aggregate()`, `stream()`, and `explain()`. Pass `withDeleted: true` to include deleted documents or `onlyDeleted: true` to query only deleted documents.
379
+
380
+ For aggregation, monSQLize prepends a soft-delete `$match` stage before the user pipeline, or after `$geoNear` when that stage is first. Soft-delete filtering inside user-authored `$lookup` pipelines remains the application's responsibility.
381
+
299
382
  ## Caching and Performance
300
383
 
301
- monSQLize can cache collection queries and arbitrary async functions.
384
+ monSQLize can cache collection queries and coordinate local/Redis-backed invalidation for database runtime usage.
302
385
 
303
386
  ```js
304
- const users = db.collection('users');
387
+ const users = msq.collection('users');
305
388
 
306
389
  const hotUser = await users.findOne(
307
390
  { email: 'john@example.com' },
@@ -309,51 +392,36 @@ const hotUser = await users.findOne(
309
392
  );
310
393
  ```
311
394
 
312
- ```js
313
- const { withCache } = require('monsqlize');
314
-
315
- async function getUserProfile(userId) {
316
- const user = await db.collection('users').findOneById(userId);
317
- const orders = await db.collection('orders').find({ userId }).toArray();
318
- return { user, orders };
319
- }
320
-
321
- const cachedGetUserProfile = withCache(getUserProfile, {
322
- ttl: 300_000,
323
- cache: db.getCache()
324
- });
325
-
326
- await cachedGetUserProfile('user-1');
327
- ```
328
-
329
395
  Cache capabilities include:
330
396
 
331
397
  - In-memory L1 cache.
332
398
  - Optional Redis-backed L2 cache.
333
399
  - Automatic invalidation after writes.
334
- - Function-level caching through `withCache()`.
335
- - In-flight request deduplication.
336
- - Namespaces, TTLs, statistics, and conditional caching.
400
+ - Cache namespace, TTL, and distributed invalidation controls.
337
401
 
338
402
  ## Advanced Capabilities
339
403
 
340
404
  ### Transactions
341
405
 
342
406
  ```js
343
- await db.withTransaction(async (session) => {
344
- await db.collection('orders').insertOne({ userId, status: 'pending' }, { session });
345
- await db.collection('users').updateOne(
407
+ await msq.withTransaction(async (tx) => {
408
+ await msq.collection('orders').insertOne({ userId, status: 'pending' }, { session: tx.session });
409
+ await msq.collection('users').updateOne(
346
410
  { _id: userId },
347
411
  { $inc: { orderCount: 1 } },
348
- { session }
412
+ { session: tx.session }
349
413
  );
350
414
  });
351
415
  ```
352
416
 
417
+ Read options such as `session`, `readConcern`, `readPreference`, `collation`, `hint`, `maxTimeMS`, and `allowDiskUse` are forwarded to the MongoDB driver. Query caches are bypassed while a `session` is present, so transaction reads use the driver snapshot instead of a shared cache entry.
418
+
419
+ Transaction cache invalidations are recorded during the transaction and flushed only after a successful commit. If the transaction aborts, pending invalidations are discarded.
420
+
353
421
  ### Connection Pools
354
422
 
355
423
  ```js
356
- const db = new MonSQLize({
424
+ const msq = new MonSQLize({
357
425
  type: 'mongodb',
358
426
  databaseName: 'main',
359
427
  config: { uri: 'mongodb://primary:27017' },
@@ -362,24 +430,13 @@ const db = new MonSQLize({
362
430
  ]
363
431
  });
364
432
 
365
- const reports = db.pool('analytics').collection('reports');
366
- ```
367
-
368
- ### Distributed Locks
369
-
370
- ```js
371
- await db.withLock('inventory:sku-1', async () => {
372
- await db.collection('inventory').updateOne(
373
- { sku: 'sku-1' },
374
- { $inc: { stock: -1 } }
375
- );
376
- });
433
+ const reports = msq.pool('analytics').collection('reports');
377
434
  ```
378
435
 
379
436
  ### Change Streams
380
437
 
381
438
  ```js
382
- const watcher = db.collection('orders').watch([
439
+ const watcher = msq.collection('orders').watch([
383
440
  { $match: { 'fullDocument.status': 'pending' } }
384
441
  ]);
385
442
 
@@ -388,25 +445,6 @@ watcher.on('change', (change) => {
388
445
  });
389
446
  ```
390
447
 
391
- ### Saga Orchestration
392
-
393
- ```js
394
- db.defineSaga('checkout', [
395
- {
396
- name: 'reserveInventory',
397
- execute: async (ctx) => reserveInventory(ctx),
398
- compensate: async (ctx) => releaseInventory(ctx)
399
- },
400
- {
401
- name: 'chargePayment',
402
- execute: async (ctx) => chargePayment(ctx),
403
- compensate: async (ctx) => refundPayment(ctx)
404
- }
405
- ]);
406
-
407
- await db.executeSaga('checkout', { orderId });
408
- ```
409
-
410
448
  ## Migration from the MongoDB Driver
411
449
 
412
450
  The smallest migration is usually to replace only initialization:
@@ -421,15 +459,15 @@ const nativeUsers = nativeClient.db('mydb').collection('users');
421
459
  ```js
422
460
  const MonSQLize = require('monsqlize');
423
461
 
424
- const db = new MonSQLize({
462
+ const msq = new MonSQLize({
425
463
  type: 'mongodb',
426
464
  databaseName: 'mydb',
427
465
  config: { uri: 'mongodb://localhost:27017' },
428
466
  cache: { enabled: true }
429
467
  });
430
468
 
431
- await db.connect();
432
- const users = db.collection('users');
469
+ await msq.connect();
470
+ const users = msq.collection('users');
433
471
  ```
434
472
 
435
473
  MongoDB-style collection calls can remain unchanged in most cases:
@@ -446,7 +484,7 @@ The v2 line has been validated against the workspace consumers `chat`, `payment`
446
484
  | Surface | Current Support |
447
485
  |---|---|
448
486
  | Node.js | `>=18.0.0`; CI covers Node 18 / 20 / 22. |
449
- | MongoDB driver | `mongodb@6.21.0` runtime baseline; driver 7.2.0 has additional compatibility coverage. |
487
+ | MongoDB driver | `mongodb@6.21.0` runtime baseline; driver 7.5.0 has additional compatibility coverage. |
450
488
  | MongoDB server | Memory-server based 6.x / 7.x validation is covered by the project test matrix. |
451
489
  | Module systems | CommonJS and ESM are both validated. |
452
490
  | TypeScript | Public declarations are published from `dist/types/index.d.ts`. |
@@ -456,9 +494,8 @@ See the current support and verification documents:
456
494
 
457
495
  - [English documentation](https://github.com/vextjs/monSQLize/blob/main/docs/en/README.md)
458
496
  - [Chinese documentation](https://github.com/vextjs/monSQLize/blob/main/docs/zh/README.md)
459
- - [English recipes](https://github.com/vextjs/monSQLize/blob/main/docs/en/recipes.md)
497
+ - [English common scenarios](https://github.com/vextjs/monSQLize/blob/main/docs/en/recipes.md)
460
498
  - [Support matrix](https://github.com/vextjs/monSQLize/blob/main/docs/en/support-matrix.md)
461
- - [Verification entry points](https://github.com/vextjs/monSQLize/blob/main/docs/en/verification-entrypoints.md)
462
499
  - [test/compatibility/README.md](https://github.com/vextjs/monSQLize/blob/main/test/compatibility/README.md)
463
500
  - [test/validation/VERIFICATION-PROGRESS.md](https://github.com/vextjs/monSQLize/blob/main/test/validation/VERIFICATION-PROGRESS.md)
464
501
 
@@ -467,12 +504,15 @@ See the current support and verification documents:
467
504
  Current TypeScript documentation and examples are the source of truth for the v2 package:
468
505
 
469
506
  - Complete docs: [English](https://vextjs.github.io/monSQLize/) · [简体中文](https://vextjs.github.io/monSQLize/zh/)
470
- - `docs/en/**` - default English documentation.
471
- - `docs/zh/**` - Simplified Chinese documentation.
472
- - `docs/en/recipes.md` / `docs/zh/recipes.md` - shortest copy-ready paths for common setup scenarios.
473
- - `examples/**` - TypeScript examples.
474
- - `test/compatibility/**` - package exports and compatibility guards.
475
- - `test/validation/**` - verification ledgers and mapping notes.
507
+ - Constructor configuration: [English](https://vextjs.github.io/monSQLize/configuration) · [简体中文](https://vextjs.github.io/monSQLize/zh/configuration)
508
+ - Production rollout: [English](https://vextjs.github.io/monSQLize/production-rollout) · [简体中文](https://vextjs.github.io/monSQLize/zh/production-rollout)
509
+ - Production data migration: [English](https://vextjs.github.io/monSQLize/production-data-migration) · [简体中文](https://vextjs.github.io/monSQLize/zh/production-data-migration)
510
+ - Data tasks API: [English](https://vextjs.github.io/monSQLize/data-tasks) · [简体中文](https://vextjs.github.io/monSQLize/zh/data-tasks)
511
+ - Common scenarios: [English](https://vextjs.github.io/monSQLize/recipes) · [简体中文](https://vextjs.github.io/monSQLize/zh/recipes)
512
+ - Example source: [examples index](https://github.com/vextjs/monSQLize/blob/main/examples/README.md)
513
+ - Documentation source: [docs/en](https://github.com/vextjs/monSQLize/tree/main/docs/en) · [docs/zh](https://github.com/vextjs/monSQLize/tree/main/docs/zh)
514
+ - Compatibility checks: [test/compatibility](https://github.com/vextjs/monSQLize/tree/main/test/compatibility)
515
+ - Verification mapping: [test/validation](https://github.com/vextjs/monSQLize/tree/main/test/validation)
476
516
 
477
517
  Historical v1 assets are useful for tracing old behavior, but they are not the current publishing surface for v2.
478
518
 
@@ -495,9 +535,9 @@ npm run verify:full
495
535
  npm run release:preflight
496
536
  ```
497
537
 
498
- Release preflight runs linting, type checks, size guards, runtime checks, compatibility checks, refactor guards, production dependency audit, the default test suite, and `npm pack --dry-run`.
538
+ The package self-check command runs linting, documentation/type/size/runtime/compatibility/refactor guards, the default test suite, 90% source coverage, all runnable examples, the MongoDB server matrix, real dataTasks and CLI integration, production dependency audit, a temporary package-install smoke, and a final `npm pack --dry-run`.
499
539
 
500
- `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`.
540
+ `npm run release:publish` runs the package self-check once and then calls `npm publish --ignore-scripts` so the final publish step does not repeat the full lifecycle check. Raw `npm publish` is still guarded by `prepublishOnly`.
501
541
 
502
542
  Optional commands:
503
543
 
@@ -507,82 +547,30 @@ npm run test:examples
507
547
  npm run test:coverage
508
548
  npm run test:audit
509
549
  npm run test:server-matrix
550
+ npm run test:data-tasks:integration
551
+ npm run test:data-task-cli
552
+ npm run test:pack-install
510
553
  npm run test:real-env:private
511
554
  ```
512
555
 
513
- `check:docs-examples` verifies the 97/97 bilingual documentation matrix, runnable-example runner parity, shared-example targets, doc-check targets, and user-facing path text.
514
-
515
- `test:examples`, `test:server-matrix`, and `config.useMemoryServer` use a fixed `mongodb-memory-server` policy: MongoDB `7.0.14` by default, binaries cached under `.cache/mongodb-memory-server/binaries`, and temporary data paths created under `.cache/mongodb-memory-server/db` with forced cleanup for project-managed paths. Stale managed data paths whose owner PID is no longer alive are pruned before new memory-server launches. Override with `MONSQLIZE_MEMORY_MONGO_BINARY_VERSION`, `MONSQLIZE_REPLSET_BINARY_VERSION`, `MONGOMS_DOWNLOAD_DIR`, or `MONSQLIZE_MEMORY_SERVER_DB_DIR` when needed.
556
+ `check:docs-examples` verifies the bilingual documentation matrix, runnable-example runner parity, shared-example targets, doc-check targets, and user-facing path text.
516
557
 
517
- `test:coverage` is the independent 90% coverage governance gate for the published CJS runtime artifact. `test:audit` checks production dependencies against the npm registry. `test:real-env:private` is intentionally opt-in and expects private environment variables. Coverage and private real-environment checks are not part of the default CI or release gate.
558
+ `test:examples`, `test:server-matrix`, and `config.useMemoryServer` use a fixed `mongodb-memory-server` policy: MongoDB `7.0.37` by default, binaries cached under `.cache/mongodb-memory-server/binaries`, and temporary data paths created under `.cache/mongodb-memory-server/db` with forced cleanup for project-managed paths. The release matrix strictly requires MongoDB `7.0.37` and `8.0.26`; a missing binary, failed probe, or failed combination exits nonzero. Stale managed data paths whose owner PID is no longer alive are pruned before new memory-server launches. Override with `MONSQLIZE_MEMORY_MONGO_BINARY_VERSION`, `MONSQLIZE_REPLSET_BINARY_VERSION`, `MONGOMS_DOWNLOAD_DIR`, or `MONSQLIZE_MEMORY_SERVER_DB_DIR` when needed.
518
559
 
519
- ## Release Status
520
-
521
- The current release train targets `v2.0.6`.
522
-
523
- Key release-readiness points:
524
-
525
- - TypeScript rewrite completed for the current runtime and test entry points.
526
- - Package exports are consolidated under `dist/cjs`, `dist/esm`, and `dist/types`.
527
- - 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`.
528
- - v1 smooth-upgrade compatibility has been validated against the target workspace consumers.
529
- - `schema-dsl` follows the npm `latest` TypeScript line `schema-dsl@2.0.11`; deprecated `2.3.x` mistake releases are intentionally excluded.
530
- - 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.
560
+ `test:coverage` remains an independently runnable 90% governance command for the published CJS runtime plus source-level gap coverage resolved through sourcemaps, and the single-source release preflight requires it. Public CI runs that same preflight in its release-gate job. `test:audit` checks production dependencies against the npm registry. Only `test:real-env:private` remains opt-in because it expects private environment variables.
531
561
 
532
562
  ## Roadmap
533
563
 
534
- ### v2.0.6
535
-
536
- - Dependency alignment to `schema-dsl@2.0.11`, carrying the shared ESM/CJS custom type registry fix to downstream vext applications.
537
- - NodeNext declaration compatibility for ESM consumers through generated `*.d.mts` mirrors and import-side `types` conditions.
538
- - Restored v1-compatible root option type exports.
539
-
540
- ### v2.0.4
541
-
542
- - Production-safe Model index rollout controls with `autoIndex`, dry-run preflight, conflict reporting, and explicit `ensureIndexes()` / `ensureModelIndexes()` APIs.
543
- - `schema-dsl` updated to `2.0.9`, with transitive `cache-hub` aligned to `2.2.4`.
544
- - User-facing capability and verification documentation wording cleaned up, plus documentation home experience refinements.
545
-
546
- ### v2.0.3
547
-
548
- - v1 compatibility patch for documented `findPage({ cache })` behavior.
549
- - Public transaction and distributed cache invalidator statistics APIs.
550
- - Standalone documentation-site link safety and bilingual docs consistency fixes.
551
- - Release preflight alignment for bilingual docs paths and production dependency audit.
552
-
553
- ### v2.0.2
554
-
555
- - Deterministic dependency metadata patch.
556
- - `ioredis` and `ssh2` are installed with monSQLize by default, so Redis-backed cache/locks and SSH tunnels no longer require a separate dependency install step.
557
-
558
- ### v2.0.1
559
-
560
- - v1 smooth-upgrade compatibility patch for Model actual collection names, scoped pools/databases, automatic-index dedupe, and cache/pool option aliases.
561
- - Documentation and public types aligned with the current runtime behavior.
562
-
563
- ### v2.0.0
564
-
565
- - TypeScript-native runtime and declarations.
566
- - v1 smooth-upgrade compatibility bridge.
567
- - Multi-level cache and function-cache support through `cache-hub`.
568
- - Transactions, business locks, distributed locks, Saga orchestration, connection pools, Change Stream sync, and slow-query logging.
569
- - Model layer with `schema-dsl` validation, relations, populate, hooks, and custom methods.
570
-
571
- ### v2.x
572
-
564
+ - MongoDB remains the stable adapter and the current production runtime.
565
+ - MySQL and PostgreSQL adapters will be introduced as database-native adapters under the same production runtime contract.
566
+ - Adapter status will move from planned to alpha/stable only after runtime support, public types, examples, and verification coverage are present.
567
+ - The project does not currently promise production-ready "one query syntax automatically adapts to every database" behavior.
573
568
  - Query analyzer improvements.
574
569
  - Automatic index suggestions.
575
- - Migration tooling.
570
+ - Additional data-task observability and large-scope operational probes.
576
571
  - GraphQL integration experiments.
577
572
  - More real-environment validation coverage.
578
573
 
579
- ### v3.0+
580
-
581
- - Unified API experiments for MySQL.
582
- - Unified API experiments for PostgreSQL.
583
- - Broader ORM capabilities.
584
- - Cross-database sync middleware.
585
-
586
574
  ## License
587
575
 
588
576
  monSQLize is released under the [Apache License 2.0](./LICENSE).