This guide starts with the v2.0.6 to v3.0.0 upgrade path, then retains the v1-to-v2 compatibility notes for older applications. Review every tightened contract that intersects your application before changing the installed major.
monSQLize v3.1 consumes schema-dsl v3 without installing schema-dsl's legacy
String prototype extensions. Applications that need those extensions must opt
in through schema-dsl/compat or schema-dsl/register-string; monSQLize itself
continues to use the isolated schema-dsl/runtime entry and does not require
them.
Successful full-document Model validation now persists schema-dsl's normalized
data for insertOne, insertMany, insertBatch, replaceOne,
findOneAndReplace, and hydrated document save(). Coerced values and schema
defaults therefore reach MongoDB. The order is model defaults, before hook,
schema normalization, timestamps, version, then driver write. Replacement
writes do not apply model defaults, and save() has no new before-hook stage.
Validation failures still throw VALIDATION_ERROR, and public errors remain
{ field, message }; field is mapped from schema-dsl's canonical path.
Update operators and pipelines do not expose a complete final document and are
not included in normalized-data persistence. If an application relied on
schema-dsl coercion being discarded before v3.1, review stored value types in a
staging environment before upgrading.
Use Node.js 18 or newer, install v3 in a staging branch, and run your own
Model, cache, sync, transaction, and data rollout tests. monSQLize v3 pins
schema-dsl@2.1.6 and keeps the isolated schema-dsl/runtime integration.
find()defaults to 500 documents. Configure an explicit safe limit when a service previously depended on an unbounded result.- Versioned single-document Model writes use optimistic concurrency control and
may throw
WRITE_CONFLICTfor stale state. - Versioned
updateMany()defaults tocounter; selectstrictoroffwhen that better matches the existing write contract. updateBatch({ upsert: true })is rejected. UseupsertOne()or MongoDB's nativeupdateMany(..., { upsert: true })according to the required semantics.
- Resume-token persistence failures stop Change Stream sync unless a legacy best-effort option is selected explicitly.
autoIndex: truenow preflights withlistIndexes(), creates only missing indexes, and reports conflicts. Keep production index rollout reviewed.production,prod, andliveall activate production-like safety guards.
For selected release data and declared indexes, use
dataTasks.preview(job) followed by dataTasks.apply(job, { approval }).
Production jobs require a durable affected-scope backup directory. This feature
does not replace schema migrations, full database export/import, or disaster
recovery. See the data-tasks and production-rollout guides before first use.
The sections below document intentional behavioural and contract changes between monSQLize v1.x and v2.x. Most v2 type-level differences from v1 have been softened (optional fields, alias keys, permissive callbacks) so that v1 fixtures and call sites continue to type-check unchanged. The items below are the deliberately tightened semantics that v2 keeps for safety; v1 callers in these spots may need code changes.
- v1 returned
undefinedwhen no document matched. - v2 returns
null, matching the underlying MongoDB driver and removing theundefinedvsnullambiguity. - Migration: replace
result === undefinedwithresult === null, or use!resultwhich works for both.
- v1 returned an opaque object whose shape was not declared.
- v2 returns a
PoolHandleinterface with documented fields (name,client, etc.). - Migration: no source change is required if you only consume fields
v2 declares. If your v1 code accessed undeclared fields, declare them
through module augmentation or assert through
as unknown as ....
- The cache
publish()/ subscriber callback payload type is nowunknowninstead ofany, forcing call sites to narrow before use. - Migration: add a runtime check or a type assertion at the consumption point. The wire shape is unchanged.
For reference, v2 type files were extended with the following alias / optional fields so that v1 fixtures and runtime payloads continue to type-check; you do not need to migrate code for these:
BatchRetryRecord: added optionalattempts(alias ofattempt) andsuccess?: boolean. The runtime now also emits both fields on retry records to match v1.FindPageOptions: added top-levelcomment?: stringshortcut that mirrorsoptions.comment.SagaContext.get<T = any>: default generic relaxed fromunknowntoanyto match v1 ergonomics.SagaResult.sagaId/sagaName: marked optional alongsideexecutionId.SagaStats: aliased v2-only fields (successfulExecutions/failedExecutions/compensatedExecutions) are optional;successCount/failureCount/compensationCountremain the v1 primary fields.MongoSession.transaction?.state: re-exposed for v1 callers readingsession.transaction?.state.SyncConfig.transform: accepts both v1 single-arg(document) => ...and v2(document, event) => ...forms.Lock.released: markedreadonlyto match v1.PoolStats: counter fields are optional to accept v1 fixture shapes.
If a previously-undocumented field still does not type-check, please file an issue with the v1 reproduction so the public types can be extended.