Skip to content

Commit 3ef6e14

Browse files
committed
fix: address v3.3.0 audit findings
1 parent 369f3c8 commit 3ef6e14

83 files changed

Lines changed: 2572 additions & 827 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎README.md‎

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -332,18 +332,33 @@ Relative model paths are resolved from `process.cwd()`. In production services,
332332
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:
333333

334334
```js
335+
const MonSQLize = require('monsqlize');
336+
337+
async function main() {
338+
MonSQLize.Model.define('users', {
339+
schema: { email: 'email!' },
340+
indexes: [{ key: { email: 1 }, unique: true }]
341+
});
342+
335343
const msq = new MonSQLize({
336344
type: 'mongodb',
337345
databaseName: 'mydb',
338346
config: { uri: 'mongodb://localhost:27017' },
339347
autoIndex: false
340348
});
341349

342-
const plan = await msq.ensureModelIndexes({ models: ['users'], dryRun: true });
343-
344-
if (plan.totals.conflicts === 0) {
345-
await msq.ensureModelIndexes({ models: ['users'], throwOnError: true });
350+
try {
351+
await msq.connect();
352+
const plan = await msq.ensureModelIndexes({ models: ['users'], dryRun: true });
353+
if (plan.totals.conflicts === 0) {
354+
await msq.ensureModelIndexes({ models: ['users'], throwOnError: true });
355+
}
356+
} finally {
357+
await msq.close();
346358
}
359+
}
360+
361+
main().catch((error) => { console.error(error); process.exitCode = 1; });
347362
```
348363

349364
`ensureModelIndexes()` creates only missing indexes. It does not drop, rename, or rebuild conflicting indexes.
@@ -449,6 +464,8 @@ Transaction cache invalidations are recorded during the transaction and flushed
449464
### Connection Pools
450465

451466
```js
467+
const MonSQLize = require('monsqlize');
468+
async function main() {
452469
const msq = new MonSQLize({
453470
type: 'mongodb',
454471
databaseName: 'main',
@@ -458,7 +475,16 @@ const msq = new MonSQLize({
458475
]
459476
});
460477

461-
const reports = msq.pool('analytics').collection('reports');
478+
try {
479+
await msq.connect();
480+
const reports = msq.pool('analytics').collection('reports');
481+
console.log(await reports.countDocuments({}));
482+
} finally {
483+
await msq.close();
484+
}
485+
}
486+
487+
main().catch((error) => { console.error(error); process.exitCode = 1; });
462488
```
463489

464490
### Change Streams

‎docs/en/cache-invalidation.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
Read caching is opt-in per query, and write invalidation is opt-in per write or per runtime configuration.
44

5+
Distributed invalidation received from another instance clears local cache entries without publishing another invalidation. Locally initiated invalidation still publishes normally, so concurrent local writes and incoming messages are handled independently.
6+
57
## Default Behavior
68

79
Writes do not invalidate read caches by default:

‎docs/en/count-queue.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
## Overview
44

5+
For direct `CountQueue.execute(task, { signal })` calls, an aborted queued task is removed before execution. Timeout or caller abort rejects the caller and aborts the task signal, but the running slot remains occupied until the underlying task actually settles. Tasks that ignore abort can therefore keep a slot occupied.
6+
57
Count queue control is an advanced feature of monSQLize that limits the number of `countDocuments` operations that can be executed simultaneously.
68

79

‎docs/en/data-tasks.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
`dataTasks` uses one `DataTaskJob` configuration for release-scoped index checks, filtered data synchronization, local field edits, reviewed preview, affected-scope backup, and restore.
44

5+
Backup manifests and data rows are read as canonical EJSON. Only manifest control fields (`version`, `entryCount`, `maxBytes`) are converted from safe numeric BSON values to JavaScript numbers. Identity, target IDs, before/after images, and index keys retain their BSON types and key order. An unsafe or ambiguous legacy control value fails backup validation instead of being guessed.
6+
57
Start with [Production Data Migration](./production-data-migration.md) to choose the right tool. See [Production Rollout](./production-rollout.md) for the complete release sequence.
68

79
## Entry Point and Four Methods

‎docs/en/deleteBatch.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
## API parameter description
44

5+
The original business filter is checked again for each selected document at write time. A document that changed before deletion is skipped. After a fatal batch error, workers stop acquiring new batches and wait for in-flight batches to settle before returning the error.
6+
57
## Method signature
68

79
```typescript

‎docs/en/model.md‎

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
The Model layer adds schema validation, custom methods, lifecycle hooks, relations, and model-scoped write helpers on top of the MongoDB runtime. It keeps collection access explicit while giving repeated document workflows a consistent Model surface.
44

5+
Migration note for 3.3.0 fixes: hydrated `remove()` now follows Model delete hooks and soft-delete rules. Boolean soft delete treats only `true` as deleted; `false`, `null`, and a missing field remain visible. Strict versioned updates enumerate all matching candidates without the public `find` limit, and classify a changed business filter or removed document as skipped rather than a version conflict. Populate `skip`/`limit` is applied per parent; an unlimited populate can retain a large result in memory.
6+
57
**Features**: Schema validation · Custom methods · Lifecycle hooks · Automatic indexing · Data source binding
68

79
---
@@ -134,7 +136,7 @@ Model.define('users', {
134136
username: 'string:3-32!',
135137
email: 'email!',
136138
password: 'string!',
137-
role: this.enums.role.default('user')
139+
role: s(this.enums.role).default('user')
138140
});
139141
},
140142
methods: (model) => ({
@@ -843,7 +845,7 @@ schema: function(s) {
843845
username: 'string:3-32!',
844846
email: 'email!',
845847
age: 'number:0-120',
846-
role: this.enums.role.default('user') //Reference enums
848+
role: s(this.enums.role).default('user') //Reference enums
847849
});
848850
}
849851

@@ -1029,7 +1031,7 @@ enums: {
10291031
//Referenced in schema
10301032
schema: function(s) {
10311033
return s({
1032-
role: this.enums.role.default('user')
1034+
role: s(this.enums.role).default('user')
10331035
});
10341036
}
10351037
```
@@ -1052,10 +1054,10 @@ Model.define('users', {
10521054
return s({
10531055
username: 'string:3-32!',
10541056
email: 'email!',
1055-
password: 'string!'.pattern(/^[a-zA-Z0-9]{6,30}$/),
1056-
role: this.enums.role.default('user'),
1057-
status: this.enums.status.default('active'),
1058-
loginCount: 'number'.default(0),
1057+
password: s('string!').pattern(/^[a-zA-Z0-9]{6,30}$/),
1058+
role: s(this.enums.role).default('user'),
1059+
status: s(this.enums.status).default('active'),
1060+
loginCount: s('number').default(0),
10591061
lastLoginAt: 'date',
10601062
createdAt: 'date!',
10611063
updatedAt: 'date!'

‎docs/en/multi-pool.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
## Introduction
44

5+
Opening pools reserve capacity before the client factory completes. Closing the manager rejects new additions, waits for pending additions, and closes clients that finish opening after shutdown began.
6+
57
Use this page when your application needs more than one MongoDB connection, such as a primary pool plus read replicas, an analytics pool, or tenant-specific pools. The recommended runtime path is to declare pools when creating the `MonSQLize` instance:
68

79
- `pools: PoolConfig[]` defines named connection pools.

‎docs/en/ssh-tunnel.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
## Function Overview
44

5+
`ssh.hostHash` and `ssh.hostVerifier` are optional ssh2 host-key verification settings. With `hostHash: 'sha256'`, the verifier receives a hexadecimal SHA-256 fingerprint; returning `false` rejects the handshake and closes the tunnel listener. If no verifier is configured, the previous ssh2 default behavior is retained.
6+
57
## What is an SSH tunnel?
68

79
SSH Tunneling, also known as SSH port forwarding, is a technology that establishes an encrypted channel between local and remote servers through the SSH protocol.

‎docs/en/transaction.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
monSQLize wraps MongoDB driver sessions with `withTransaction()` and `startSession()` helpers. The ACID boundary is MongoDB's transaction/session boundary; monSQLize adds retry, timeout, statistics, and cache-invalidation coordination around that driver behavior.
66

7+
Managed transaction writes stop being accepted as soon as commit or abort begins, including lazy aggregate writes and batch subwrites. An unknown commit result retries commit without rerunning the business callback; errors after a successful commit also do not rerun it. Native sessions passed directly to the MongoDB driver keep their native behavior.
8+
79

810
## Core Features
911

‎docs/en/updateBatch.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
## API parameter description
44

5+
Each selected document is checked against the original business filter again when its write is dispatched. Documents that no longer match are skipped. On a fatal batch error, no new batch is acquired; already running batches finish before the error is returned. For strict Model updates, `conflictCount` refers to a version mismatch, while a changed filter or concurrent deletion is counted as skipped.
6+
57
## Method signature
68

79
```typescript

0 commit comments

Comments
 (0)