From f55d676186876168fbdd1944b9cb958b6b8ca895 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 29 Apr 2025 16:34:36 -0400 Subject: [PATCH 1/5] BREAKING CHANGE: remove browser build, move to @mongoosejs/browser instead Fix #15296 --- browser.js | 8 -- docs/nextjs.md | 1 - lib/browser.js | 143 ------------------------------ lib/browserDocument.js | 117 ------------------------ lib/document.js | 14 +-- lib/documentProvider.js | 30 ------- lib/drivers/browser/binary.js | 14 --- lib/drivers/browser/decimal128.js | 7 -- lib/drivers/browser/index.js | 13 --- lib/drivers/browser/objectid.js | 29 ------ lib/helpers/model/applyHooks.js | 24 +---- lib/mongoose.js | 12 +-- lib/schema.js | 28 ++++++ package.json | 13 +-- scripts/build-browser.js | 18 ---- test/browser.test.js | 88 ------------------ test/deno_mocha.js | 2 +- test/docs/lean.test.js | 3 + test/files/index.html | 9 -- test/files/sample.js | 7 -- webpack.config.js | 59 ------------ 21 files changed, 44 insertions(+), 595 deletions(-) delete mode 100644 browser.js delete mode 100644 lib/browser.js delete mode 100644 lib/browserDocument.js delete mode 100644 lib/documentProvider.js delete mode 100644 lib/drivers/browser/binary.js delete mode 100644 lib/drivers/browser/decimal128.js delete mode 100644 lib/drivers/browser/index.js delete mode 100644 lib/drivers/browser/objectid.js delete mode 100644 scripts/build-browser.js delete mode 100644 test/browser.test.js delete mode 100644 test/files/index.html delete mode 100644 test/files/sample.js delete mode 100644 webpack.config.js diff --git a/browser.js b/browser.js deleted file mode 100644 index 4cf822804e8..00000000000 --- a/browser.js +++ /dev/null @@ -1,8 +0,0 @@ -/** - * Export lib/mongoose - * - */ - -'use strict'; - -module.exports = require('./lib/browser'); diff --git a/docs/nextjs.md b/docs/nextjs.md index 673587c6829..94d0071f472 100644 --- a/docs/nextjs.md +++ b/docs/nextjs.md @@ -34,5 +34,4 @@ And Next.js forces ESM mode. ## Next.js Edge Runtime Mongoose does **not** currently support [Next.js Edge Runtime](https://nextjs.org/docs/app/building-your-application/rendering/edge-and-nodejs-runtimes#edge-runtime). -While you can import Mongoose in Edge Runtime, you'll get [Mongoose's browser library](browser.html). There is no way for Mongoose to connect to MongoDB in Edge Runtime, because [Edge Runtime currently doesn't support Node.js `net` API](https://edge-runtime.vercel.app/features/available-apis#unsupported-apis), which is what the MongoDB Node Driver uses to connect to MongoDB. diff --git a/lib/browser.js b/lib/browser.js deleted file mode 100644 index 5369dedf44c..00000000000 --- a/lib/browser.js +++ /dev/null @@ -1,143 +0,0 @@ -/* eslint-env browser */ - -'use strict'; - -require('./driver').set(require('./drivers/browser')); - -const DocumentProvider = require('./documentProvider.js'); -const applyHooks = require('./helpers/model/applyHooks.js'); - -DocumentProvider.setBrowser(true); - -/** - * The [MongooseError](https://mongoosejs.com/docs/api/error.html#Error()) constructor. - * - * @method Error - * @api public - */ - -exports.Error = require('./error/index'); - -/** - * The Mongoose [Schema](https://mongoosejs.com/docs/api/schema.html#Schema()) constructor - * - * #### Example: - * - * const mongoose = require('mongoose'); - * const Schema = mongoose.Schema; - * const CatSchema = new Schema(..); - * - * @method Schema - * @api public - */ - -exports.Schema = require('./schema'); - -/** - * The various Mongoose Types. - * - * #### Example: - * - * const mongoose = require('mongoose'); - * const array = mongoose.Types.Array; - * - * #### Types: - * - * - [Array](https://mongoosejs.com/docs/schematypes.html#arrays) - * - [Buffer](https://mongoosejs.com/docs/schematypes.html#buffers) - * - [Embedded](https://mongoosejs.com/docs/schematypes.html#schemas) - * - [DocumentArray](https://mongoosejs.com/docs/api/documentarraypath.html) - * - [Decimal128](https://mongoosejs.com/docs/api/decimal128.html#Decimal128()) - * - [ObjectId](https://mongoosejs.com/docs/schematypes.html#objectids) - * - [Map](https://mongoosejs.com/docs/schematypes.html#maps) - * - [Subdocument](https://mongoosejs.com/docs/schematypes.html#schemas) - * - * Using this exposed access to the `ObjectId` type, we can construct ids on demand. - * - * const ObjectId = mongoose.Types.ObjectId; - * const id1 = new ObjectId; - * - * @property Types - * @api public - */ -exports.Types = require('./types'); - -/** - * The Mongoose [VirtualType](https://mongoosejs.com/docs/api/virtualtype.html#VirtualType()) constructor - * - * @method VirtualType - * @api public - */ -exports.VirtualType = require('./virtualType'); - -/** - * The various Mongoose SchemaTypes. - * - * #### Note: - * - * _Alias of mongoose.Schema.Types for backwards compatibility._ - * - * @property SchemaTypes - * @see Schema.SchemaTypes https://mongoosejs.com/docs/api/schema.html#Schema.Types - * @api public - */ - -exports.SchemaType = require('./schemaType.js'); - -/** - * The constructor used for schematype options - * - * @method SchemaTypeOptions - * @api public - */ - -exports.SchemaTypeOptions = require('./options/schemaTypeOptions'); - -/** - * Internal utils - * - * @property utils - * @api private - */ - -exports.utils = require('./utils.js'); - -/** - * The Mongoose browser [Document](/api/document.html) constructor. - * - * @method Document - * @api public - */ -exports.Document = DocumentProvider(); - -/** - * Return a new browser model. In the browser, a model is just - * a simplified document with a schema - it does **not** have - * functions like `findOne()`, etc. - * - * @method model - * @api public - * @param {String} name - * @param {Schema} schema - * @return Class - */ -exports.model = function(name, schema) { - class Model extends exports.Document { - constructor(obj, fields) { - super(obj, schema, fields); - } - } - Model.modelName = name; - applyHooks(Model, schema); - - return Model; -}; - -/*! - * Module exports. - */ - -if (typeof window !== 'undefined') { - window.mongoose = module.exports; - window.Buffer = Buffer; -} diff --git a/lib/browserDocument.js b/lib/browserDocument.js deleted file mode 100644 index 6bd73318b9a..00000000000 --- a/lib/browserDocument.js +++ /dev/null @@ -1,117 +0,0 @@ -/*! - * Module dependencies. - */ - -'use strict'; - -const NodeJSDocument = require('./document'); -const EventEmitter = require('events').EventEmitter; -const MongooseError = require('./error/index'); -const Schema = require('./schema'); -const ObjectId = require('./types/objectid'); -const ValidationError = MongooseError.ValidationError; -const applyHooks = require('./helpers/model/applyHooks'); -const isObject = require('./helpers/isObject'); - -/** - * Document constructor. - * - * @param {Object} obj the values to set - * @param {Object} schema - * @param {Object} [fields] optional object containing the fields which were selected in the query returning this document and any populated paths data - * @param {Boolean} [skipId] bool, should we auto create an ObjectId _id - * @inherits NodeJS EventEmitter https://nodejs.org/api/events.html#class-eventemitter - * @event `init`: Emitted on a document after it has was retrieved from the db and fully hydrated by Mongoose. - * @event `save`: Emitted when the document is successfully saved - * @api private - */ - -function Document(obj, schema, fields, skipId, skipInit) { - if (!(this instanceof Document)) { - return new Document(obj, schema, fields, skipId, skipInit); - } - - if (isObject(schema) && !schema.instanceOfSchema) { - schema = new Schema(schema); - } - - // When creating EmbeddedDocument, it already has the schema and he doesn't need the _id - schema = this.schema || schema; - - // Generate ObjectId if it is missing, but it requires a scheme - if (!this.schema && schema.options._id) { - obj = obj || {}; - - if (obj._id === undefined) { - obj._id = new ObjectId(); - } - } - - if (!schema) { - throw new MongooseError.MissingSchemaError(); - } - - this.$__setSchema(schema); - - NodeJSDocument.call(this, obj, fields, skipId, skipInit); - - applyHooks(this, schema, { decorateDoc: true }); - - // apply methods - for (const m in schema.methods) { - this[m] = schema.methods[m]; - } - // apply statics - for (const s in schema.statics) { - this[s] = schema.statics[s]; - } -} - -/*! - * Inherit from the NodeJS document - */ - -Document.prototype = Object.create(NodeJSDocument.prototype); -Document.prototype.constructor = Document; - -/*! - * ignore - */ - -Document.events = new EventEmitter(); - -/*! - * Browser doc exposes the event emitter API - */ - -Document.$emitter = new EventEmitter(); - -['on', 'once', 'emit', 'listeners', 'removeListener', 'setMaxListeners', - 'removeAllListeners', 'addListener'].forEach(function(emitterFn) { - Document[emitterFn] = function() { - return Document.$emitter[emitterFn].apply(Document.$emitter, arguments); - }; -}); - -/*! - * ignore - */ - -Document.prototype._execDocumentPreHooks = async function _execDocumentPreHooks(opName) { - return this._middleware.execPre(opName, this, []); -}; - -/*! - * ignore - */ - -Document.prototype._execDocumentPostHooks = async function _execDocumentPostHooks(opName, error) { - return this._middleware.execPost(opName, this, [this], { error }); -}; - -/*! - * Module exports. - */ - -Document.ValidationError = ValidationError; -module.exports = exports = Document; diff --git a/lib/document.js b/lib/document.js index 5a9795fe65c..1291a77aea0 100644 --- a/lib/document.js +++ b/lib/document.js @@ -92,19 +92,20 @@ function Document(obj, fields, skipId, options) { } options = Object.assign({}, options); + this.$__ = new InternalCache(); + // Support `browserDocument.js` syntax if (this.$__schema == null) { const _schema = utils.isObject(fields) && !fields.instanceOfSchema ? new Schema(fields) : fields; + this.$__setSchema(_schema); fields = skipId; skipId = options; options = arguments[4] || {}; } - this.$__ = new InternalCache(); - // Avoid setting `isNew` to `true`, because it is `true` by default if (options.isNew != null && options.isNew !== true) { this.$isNew = options.isNew; @@ -848,10 +849,10 @@ Document.prototype.updateOne = function updateOne(doc, options, callback) { const query = this.constructor.updateOne({ _id: this._doc._id }, doc, options); const self = this; query.pre(function queryPreUpdateOne() { - return self.constructor._middleware.execPre('updateOne', self, [self]); + return self._execDocumentPreHooks('updateOne', [self]); }); query.post(function queryPostUpdateOne() { - return self.constructor._middleware.execPost('updateOne', self, [self], {}); + return self._execDocumentPostHooks('updateOne'); }); if (this.$session() != null) { @@ -2903,7 +2904,7 @@ function _pushNestedArrayPaths(val, paths, path) { */ Document.prototype._execDocumentPreHooks = async function _execDocumentPreHooks(opName, ...args) { - return this.constructor._middleware.execPre(opName, this, [...args]); + return this.$__middleware.execPre(opName, this, [...args]); }; /*! @@ -2911,7 +2912,7 @@ Document.prototype._execDocumentPreHooks = async function _execDocumentPreHooks( */ Document.prototype._execDocumentPostHooks = async function _execDocumentPostHooks(opName, error) { - return this.constructor._middleware.execPost(opName, this, [this], { error }); + return this.$__middleware.execPost(opName, this, [this], { error }); }; /*! @@ -3653,6 +3654,7 @@ Document.prototype.$__setSchema = function(schema) { this.schema = schema; } this.$__schema = schema; + this.$__middleware = schema._getDocumentMiddleware(); this[documentSchemaSymbol] = schema; }; diff --git a/lib/documentProvider.js b/lib/documentProvider.js deleted file mode 100644 index 894494403f4..00000000000 --- a/lib/documentProvider.js +++ /dev/null @@ -1,30 +0,0 @@ -'use strict'; - -/* eslint-env browser */ - -/*! - * Module dependencies. - */ -const Document = require('./document.js'); -const BrowserDocument = require('./browserDocument.js'); - -let isBrowser = false; - -/** - * Returns the Document constructor for the current context - * - * @api private - */ -module.exports = function documentProvider() { - if (isBrowser) { - return BrowserDocument; - } - return Document; -}; - -/*! - * ignore - */ -module.exports.setBrowser = function(flag) { - isBrowser = flag; -}; diff --git a/lib/drivers/browser/binary.js b/lib/drivers/browser/binary.js deleted file mode 100644 index 4658f7b9e0f..00000000000 --- a/lib/drivers/browser/binary.js +++ /dev/null @@ -1,14 +0,0 @@ - -/*! - * Module dependencies. - */ - -'use strict'; - -const Binary = require('bson').Binary; - -/*! - * Module exports. - */ - -module.exports = exports = Binary; diff --git a/lib/drivers/browser/decimal128.js b/lib/drivers/browser/decimal128.js deleted file mode 100644 index 5668182b354..00000000000 --- a/lib/drivers/browser/decimal128.js +++ /dev/null @@ -1,7 +0,0 @@ -/*! - * ignore - */ - -'use strict'; - -module.exports = require('bson').Decimal128; diff --git a/lib/drivers/browser/index.js b/lib/drivers/browser/index.js deleted file mode 100644 index 2c77c712dde..00000000000 --- a/lib/drivers/browser/index.js +++ /dev/null @@ -1,13 +0,0 @@ -/*! - * Module exports. - */ - -'use strict'; - -exports.Collection = function() { - throw new Error('Cannot create a collection from browser library'); -}; -exports.Connection = function() { - throw new Error('Cannot create a connection from browser library'); -}; -exports.BulkWriteResult = function() {}; diff --git a/lib/drivers/browser/objectid.js b/lib/drivers/browser/objectid.js deleted file mode 100644 index d847afe3b8e..00000000000 --- a/lib/drivers/browser/objectid.js +++ /dev/null @@ -1,29 +0,0 @@ - -/*! - * [node-mongodb-native](https://github.com/mongodb/node-mongodb-native) ObjectId - * @constructor NodeMongoDbObjectId - * @see ObjectId - */ - -'use strict'; - -const ObjectId = require('bson').ObjectID; - -/** - * Getter for convenience with populate, see gh-6115 - * @api private - */ - -Object.defineProperty(ObjectId.prototype, '_id', { - enumerable: false, - configurable: true, - get: function() { - return this; - } -}); - -/*! - * ignore - */ - -module.exports = exports = ObjectId; diff --git a/lib/helpers/model/applyHooks.js b/lib/helpers/model/applyHooks.js index 95980adf204..bd187ff0372 100644 --- a/lib/helpers/model/applyHooks.js +++ b/lib/helpers/model/applyHooks.js @@ -65,7 +65,7 @@ function applyHooks(model, schema, options) { applyHooks(childModel, type.schema, { ...options, - decorateDoc: false, // Currently subdocs inherit directly from NodeJSDocument in browser + decorateDoc: false, isChildSchema: true }); if (childModel.discriminators != null) { @@ -81,27 +81,7 @@ function applyHooks(model, schema, options) { // promises and make it so that `doc.save.toString()` provides meaningful // information. - const middleware = schema.s.hooks. - filter(hook => { - if (hook.name === 'updateOne' || hook.name === 'deleteOne') { - return !!hook['document']; - } - if (hook.name === 'remove' || hook.name === 'init') { - return hook['document'] == null || !!hook['document']; - } - if (hook.query != null || hook.document != null) { - return hook.document !== false; - } - return true; - }). - filter(hook => { - // If user has overwritten the method, don't apply built-in middleware - if (schema.methods[hook.name]) { - return !hook.fn[symbols.builtInMiddleware]; - } - - return true; - }); + const middleware = schema._getDocumentMiddleware(); model._middleware = middleware; diff --git a/lib/mongoose.js b/lib/mongoose.js index ca035eb1e6d..acdf46ec625 100644 --- a/lib/mongoose.js +++ b/lib/mongoose.js @@ -39,7 +39,7 @@ require('./helpers/printJestWarning'); const objectIdHexRegexp = /^[0-9A-Fa-f]{24}$/; -const { AsyncLocalStorage } = require('node:async_hooks'); +const { AsyncLocalStorage } = require('async_hooks'); /** * Mongoose constructor. @@ -1029,16 +1029,6 @@ Mongoose.prototype.Model = Model; Mongoose.prototype.Document = Document; -/** - * The Mongoose DocumentProvider constructor. Mongoose users should not have to - * use this directly - * - * @method DocumentProvider - * @api public - */ - -Mongoose.prototype.DocumentProvider = require('./documentProvider'); - /** * The Mongoose ObjectId [SchemaType](https://mongoosejs.com/docs/schematypes.html). Used for * declaring paths in your schema that should be diff --git a/lib/schema.js b/lib/schema.js index a9e795120d9..4ebc0d32eb5 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -23,6 +23,7 @@ const merge = require('./helpers/schema/merge'); const mpath = require('mpath'); const setPopulatedVirtualValue = require('./helpers/populate/setPopulatedVirtualValue'); const setupTimestamps = require('./helpers/timestamps/setupTimestamps'); +const symbols = require('./schema/symbols'); const utils = require('./utils'); const validateRef = require('./helpers/populate/validateRef'); @@ -643,6 +644,33 @@ Schema.prototype.discriminator = function(name, schema, options) { return this; }; +/*! + * Get the document middleware for this schema, filtering out any hooks that are specific to queries. + */ +Schema.prototype._getDocumentMiddleware = function _getDocumentMiddleware() { + return this.s.hooks. + filter(hook => { + if (hook.name === 'updateOne' || hook.name === 'deleteOne') { + return !!hook['document']; + } + if (hook.name === 'remove' || hook.name === 'init') { + return hook['document'] == null || !!hook['document']; + } + if (hook.query != null || hook.document != null) { + return hook.document !== false; + } + return true; + }). + filter(hook => { + // If user has overwritten the method, don't apply built-in middleware + if (this.methods[hook.name]) { + return !hook.fn[symbols.builtInMiddleware]; + } + + return true; + }); +} + /*! * Get this schema's default toObject/toJSON options, including Mongoose global * options. diff --git a/package.json b/package.json index 756e6dfe84d..a5881d5bb9a 100644 --- a/package.json +++ b/package.json @@ -29,20 +29,14 @@ "sift": "17.1.3" }, "devDependencies": { - "@babel/core": "7.26.10", - "@babel/preset-env": "7.26.9", "@typescript-eslint/eslint-plugin": "^8.19.1", "@typescript-eslint/parser": "^8.19.1", "acquit": "1.3.0", "acquit-ignore": "0.2.1", "acquit-require": "0.1.1", "ajv": "8.17.1", - "assert-browserify": "2.0.0", - "babel-loader": "8.2.5", "broken-link-checker": "^0.7.8", - "buffer": "^5.6.0", "cheerio": "1.0.0", - "crypto-browserify": "3.12.1", "dox": "1.0.0", "eslint": "8.57.1", "eslint-plugin-markdown": "^5.1.0", @@ -62,11 +56,9 @@ "nyc": "15.1.0", "pug": "3.0.3", "sinon": "20.0.0", - "stream-browserify": "3.0.0", "tsd": "0.31.2", "typescript": "5.7.3", - "uuid": "11.1.0", - "webpack": "5.98.0" + "uuid": "11.1.0" }, "directories": { "lib": "./lib/mongoose" @@ -92,8 +84,6 @@ "lint-js": "eslint . --ext .js --ext .cjs", "lint-ts": "eslint . --ext .ts", "lint-md": "markdownlint-cli2 \"**/*.md\" \"#node_modules\" \"#benchmarks\"", - "build-browser": "(rm ./dist/* || true) && node ./scripts/build-browser.js", - "prepublishOnly": "npm run build-browser", "release": "git pull && git push origin master --tags && npm publish", "release-5x": "git pull origin 5.x && git push origin 5.x && git push origin 5.x --tags && npm publish --tag 5x", "release-6x": "git pull origin 6.x && git push origin 6.x && git push origin 6.x --tags && npm publish --tag 6x", @@ -122,7 +112,6 @@ "url": "git://github.com/Automattic/mongoose.git" }, "homepage": "https://mongoosejs.com", - "browser": "./dist/browser.umd.js", "config": { "mongodbMemoryServer": { "disablePostinstall": true diff --git a/scripts/build-browser.js b/scripts/build-browser.js deleted file mode 100644 index f6f0680f9af..00000000000 --- a/scripts/build-browser.js +++ /dev/null @@ -1,18 +0,0 @@ -'use strict'; - -const config = require('../webpack.config.js'); -const webpack = require('webpack'); - -const compiler = webpack(config); - -console.log('Starting browser build...'); -compiler.run((err, stats) => { - if (err) { - console.err(stats.toString()); - console.err('Browser build unsuccessful.'); - process.exit(1); - } - console.log(stats.toString()); - console.log('Browser build successful.'); - process.exit(0); -}); diff --git a/test/browser.test.js b/test/browser.test.js deleted file mode 100644 index e26251f07f9..00000000000 --- a/test/browser.test.js +++ /dev/null @@ -1,88 +0,0 @@ -'use strict'; - -/** - * Module dependencies. - */ - -const Document = require('../lib/browserDocument'); -const Schema = require('../lib/schema'); -const assert = require('assert'); -const exec = require('child_process').exec; - -/** - * Test. - */ -describe('browser', function() { - it('require() works with no other require calls (gh-5842)', function(done) { - exec('node --eval "require(\'./lib/browser\')"', done); - }); - - it('using schema (gh-7170)', function(done) { - exec('node --eval "const mongoose = require(\'./lib/browser\'); new mongoose.Schema();"', done); - }); - - it('document works (gh-4987)', function() { - const schema = new Schema({ - name: { type: String, required: true }, - quest: { type: String, match: /Holy Grail/i, required: true }, - favoriteColor: { type: String, enum: ['Red', 'Blue'], required: true } - }); - - assert.doesNotThrow(function() { - new Document({}, schema); - }); - }); - - it('document validation with arrays (gh-6175)', async function() { - const Point = new Schema({ - latitude: { - type: Number, - required: true, - min: -90, - max: 90 - }, - longitude: { - type: Number, - required: true, - min: -180, - max: 180 - } - }); - - const schema = new Schema({ - name: { - type: String, - required: true - }, - vertices: { - type: [Point], - required: true - } - }); - - let test = new Document({ - name: 'Test Polygon', - vertices: [ - { - latitude: -37.81902680201739, - longitude: 144.9821037054062 - } - ] - }, schema); - - // Should not throw - await test.validate(); - - test = new Document({ - name: 'Test Polygon', - vertices: [ - { - latitude: -37.81902680201739 - } - ] - }, schema); - - const error = await test.validate().then(() => null, err => err); - assert.ok(error.errors['vertices.0.longitude']); - }); -}); diff --git a/test/deno_mocha.js b/test/deno_mocha.js index a5cf5af5e0b..bd06f431737 100644 --- a/test/deno_mocha.js +++ b/test/deno_mocha.js @@ -38,7 +38,7 @@ const files = fs.readdirSync(testDir). concat(fs.readdirSync(path.join(testDir, 'docs')).map(file => path.join('docs', file))). concat(fs.readdirSync(path.join(testDir, 'helpers')).map(file => path.join('helpers', file))); -const ignoreFiles = new Set(['browser.test.js']); +const ignoreFiles = new Set([]); for (const file of files) { if (!file.endsWith('.test.js') || ignoreFiles.has(file)) { diff --git a/test/docs/lean.test.js b/test/docs/lean.test.js index e571987864b..c784c8c1cf7 100644 --- a/test/docs/lean.test.js +++ b/test/docs/lean.test.js @@ -41,6 +41,9 @@ describe('Lean Tutorial', function() { // To enable the `lean` option for a query, use the `lean()` function. const leanDoc = await MyModel.findOne().lean(); + // acquit:ignore:start + delete normalDoc.$__.middleware; // To make v8Serialize() not crash because it can't clone functions + // acquit:ignore:end v8Serialize(normalDoc).length; // approximately 180 v8Serialize(leanDoc).length; // approximately 55, about 3x smaller! diff --git a/test/files/index.html b/test/files/index.html deleted file mode 100644 index 67526cc96dd..00000000000 --- a/test/files/index.html +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - Test - - diff --git a/test/files/sample.js b/test/files/sample.js deleted file mode 100644 index 8328e6f27cf..00000000000 --- a/test/files/sample.js +++ /dev/null @@ -1,7 +0,0 @@ -'use strict'; -import mongoose from './dist/browser.umd.js'; - -const doc = new mongoose.Document({}, new mongoose.Schema({ - name: String -})); -console.log(doc.validateSync()); diff --git a/webpack.config.js b/webpack.config.js deleted file mode 100644 index 49a5c1eb83d..00000000000 --- a/webpack.config.js +++ /dev/null @@ -1,59 +0,0 @@ -'use strict'; - -const webpack = require('webpack'); -const paths = require('path'); - -const webpackConfig = { - entry: require.resolve('./browser.js'), - output: { - filename: './dist/browser.umd.js', - path: paths.resolve(__dirname, ''), - library: 'mongoose', - libraryTarget: 'umd', - // override default 'window' globalObject so browser build will work in SSR environments - // may become unnecessary in webpack 5 - globalObject: 'typeof self !== \'undefined\' ? self : this' - }, - externals: [ - /^node_modules\/.+$/ - ], - module: { - rules: [ - { - test: /\.js$/, - include: [ - /\/mongoose\//i, - /\/kareem\//i - ], - loader: 'babel-loader', - options: { - presets: ['@babel/preset-env'] - } - } - ] - }, - resolve: { - alias: { - 'bn.js': require.resolve('bn.js') - }, - fallback: { - assert: require.resolve('assert-browserify'), - buffer: require.resolve('buffer'), - crypto: require.resolve('crypto-browserify'), - stream: require.resolve('stream-browserify') - } - }, - target: 'web', - mode: 'production', - plugins: [ - new webpack.DefinePlugin({ - process: '({env:{}})' - }), - new webpack.ProvidePlugin({ - Buffer: ['buffer', 'Buffer'] - }) - ] -}; - -module.exports = webpackConfig; - From 0ab148bb4a9394325cdf755c2ea27f22319dc1d7 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 29 Apr 2025 16:45:54 -0400 Subject: [PATCH 2/5] style: fix lint --- lib/helpers/model/applyHooks.js | 2 -- lib/schema.js | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/helpers/model/applyHooks.js b/lib/helpers/model/applyHooks.js index bd187ff0372..451bdd7fc06 100644 --- a/lib/helpers/model/applyHooks.js +++ b/lib/helpers/model/applyHooks.js @@ -1,7 +1,5 @@ 'use strict'; -const symbols = require('../../schema/symbols'); - /*! * ignore */ diff --git a/lib/schema.js b/lib/schema.js index 4ebc0d32eb5..1bb8cc022cc 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -669,7 +669,7 @@ Schema.prototype._getDocumentMiddleware = function _getDocumentMiddleware() { return true; }); -} +}; /*! * Get this schema's default toObject/toJSON options, including Mongoose global From 42ed27e9d4eb318f6b8bc69855ef881313e99a76 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 29 Apr 2025 16:54:07 -0400 Subject: [PATCH 3/5] Update test/docs/lean.test.js Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- test/docs/lean.test.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/docs/lean.test.js b/test/docs/lean.test.js index c784c8c1cf7..3205586744c 100644 --- a/test/docs/lean.test.js +++ b/test/docs/lean.test.js @@ -42,7 +42,11 @@ describe('Lean Tutorial', function() { const leanDoc = await MyModel.findOne().lean(); // acquit:ignore:start - delete normalDoc.$__.middleware; // To make v8Serialize() not crash because it can't clone functions + // The `normalDoc.$__.middleware` property is an internal Mongoose object that stores middleware functions. + // These functions cannot be cloned by `v8.serialize()`, which causes the method to throw an error. + // Since this test only compares the serialized size of the document, it is safe to delete this property + // to prevent the crash. This operation does not affect the document's data or behavior in this context. + delete normalDoc.$__.middleware; // acquit:ignore:end v8Serialize(normalDoc).length; // approximately 180 v8Serialize(leanDoc).length; // approximately 55, about 3x smaller! From a8363e527d33402839448c7a8c4e75e8b0f15f03 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 5 May 2025 14:54:21 -0400 Subject: [PATCH 4/5] fix lint --- scripts/website.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/website.js b/scripts/website.js index 70568b2ca00..f8cdb9c49d8 100644 --- a/scripts/website.js +++ b/scripts/website.js @@ -612,7 +612,7 @@ if (isMain) { const config = generateSearch.getConfig(); generateSearchPromise = generateSearch.generateSearch(config); } catch (err) { - console.error("Generating Search failed:", err); + console.error('Generating Search failed:', err); } await deleteAllHtmlFiles(); await pugifyAllFiles(); @@ -621,7 +621,7 @@ if (isMain) { await moveDocsToTemp(); } - if (!!generateSearchPromise) { + if (generateSearchPromise) { await generateSearchPromise; } From aa23bad027ebb7c136a992e8a38a41797fc74985 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 5 May 2025 15:01:08 -0400 Subject: [PATCH 5/5] docs: link browser docs out to @mongoosejs/browser readme --- docs/browser.md | 37 ++----------------------------------- 1 file changed, 2 insertions(+), 35 deletions(-) diff --git a/docs/browser.md b/docs/browser.md index 43bc487384a..3044900eebc 100644 --- a/docs/browser.md +++ b/docs/browser.md @@ -1,37 +1,4 @@ # Mongoose in the Browser -Mongoose supports creating schemas and validating documents in the browser. -Mongoose's browser library does **not** support saving documents, [queries](http://mongoosejs.com/docs/queries.html), [populate](http://mongoosejs.com/docs/populate.html), [discriminators](http://mongoosejs.com/docs/discriminators.html), or any other Mongoose feature other than schemas and validating documents. - -Mongoose has a pre-built bundle of the browser library. If you're bundling your code with [Webpack](https://webpack.js.org/), you should be able to import Mongoose's browser library as shown below if your Webpack `target` is `'web'`: - -```javascript -import mongoose from 'mongoose'; -``` - -You can use the below syntax to access the Mongoose browser library from Node.js: - -```javascript -// Using `require()` -const mongoose = require('mongoose/browser'); - -// Using ES6 imports -import mongoose from 'mongoose/browser'; -``` - -## Using the Browser Library {#usage} - -Mongoose's browser library is very limited. The only use case it supports is validating documents as shown below. - -```javascript -import mongoose from 'mongoose'; - -// Mongoose's browser library does **not** have models. It only supports -// schemas and documents. The primary use case is validating documents -// against Mongoose schemas. -const doc = new mongoose.Document({}, new mongoose.Schema({ - name: { type: String, required: true } -})); -// Prints an error because `name` is required. -console.log(doc.validateSync()); -``` +As of Mongoose 9, [Mongoose's browser build is now in the `@mongoosejs/browser` npm package](https://github.com/mongoosejs/mongoose-browser). +The documentation has been moved to the [`@mongoosejs/browser` REAME](https://github.com/mongoosejs/mongoose-browser?tab=readme-ov-file#mongoosejsbrowser).