From e4532a8b4e4447a941d413036c1023f9e2776b3c Mon Sep 17 00:00:00 2001 From: Dawid Teper Date: Fri, 27 Jun 2025 15:12:05 +0100 Subject: [PATCH 1/8] feat: Adapt the engine collection calls to MongoDB 8 (from callbacks to promises, but still return callbacks from the engine to ensure compatibility) --- example/simple.js | 10 +- example/stream.js | 12 +- lib/cast-id-property.js | 66 ++++----- lib/mongodb-engine.js | 262 +++++++++++++++++++--------------- package.json | 6 +- test/cast-id-property.test.js | 40 +++--- test/mongodb-engine.test.js | 114 +++++++++------ yarn.lock | 133 ++++++----------- 8 files changed, 322 insertions(+), 321 deletions(-) diff --git a/example/simple.js b/example/simple.js index 2ba4050..84b772c 100644 --- a/example/simple.js +++ b/example/simple.js @@ -1,17 +1,17 @@ -var MongoClient = require('mongodb').MongoClient // npm install mongodb -var save = require('save') // npm install save -var saveMongodb = require('..') +const MongoClient = require('mongodb').MongoClient // npm install mongodb +const save = require('save') // npm install save +const saveMongodb = require('..') // connect to your mongodb database. MongoClient.connect('mongodb://localhost:27017/', function(error, client) { if (error) return console.error(error.message) - var connection = client.db('test') + const connection = client.db('test') // Get a collection. This will create the collection if it doesn't exist. connection.collection('contact', function(error, collection) { if (error) return console.error(error.message) // Create a save object and pass in a mongodb engine. - var contactStore = save('Contact', { engine: saveMongodb(collection) }) + const contactStore = save('Contact', { engine: saveMongodb(collection) }) // Then we can create a new object. contactStore.create({ name: 'Paul', email: 'paul@serby.net' }, function( diff --git a/example/stream.js b/example/stream.js index 61a4a1b..efecfc7 100644 --- a/example/stream.js +++ b/example/stream.js @@ -1,18 +1,18 @@ -var MongoClient = require('mongodb').MongoClient // npm install mongodb -var save = require('save') // npm install save -var saveMongodb = require('..') -var es = require('event-stream') +const MongoClient = require('mongodb').MongoClient // npm install mongodb +const save = require('save') // npm install save +const saveMongodb = require('..') +const es = require('event-stream') // connect to your mongodb database. MongoClient.connect('mongodb://localhost:27017/', function(error, client) { if (error) return console.error(error.message) - var connection = client.db('test') + const connection = client.db('test') // Get a collection. This will create the collection if it doesn't exist. connection.collection('contact', function(error, collection) { if (error) return console.error(error.message) // Create a save object and pass in a mongodb engine. - var contactStore = save('Contact', { engine: saveMongodb(collection) }) + const contactStore = save('Contact', { engine: saveMongodb(collection) }) // Then we can create a new object. contactStore.create({ name: 'Paul', email: 'paul@serby.net' }, function( diff --git a/lib/cast-id-property.js b/lib/cast-id-property.js index 6e63ee8..7824fc2 100644 --- a/lib/cast-id-property.js +++ b/lib/cast-id-property.js @@ -1,43 +1,39 @@ -module.exports = init +const ObjectId = require('mongodb').ObjectId + +const init = property => query => { + let newQuery = Object.assign({}, query) + const idQuery = query[property] + // only convert if id is present + if (!idQuery) { + return newQuery + } -var ObjectId = require('mongodb').ObjectId + if (Object(idQuery) === idQuery) { + newQuery[property] = castComplexId(idQuery) + } else { + newQuery[property] = ObjectId.isValid(newQuery[property]) + ? new ObjectId(newQuery[property]) + : newQuery[property] + } -function init(property) { - return castIdProperty + return newQuery +} - function castIdProperty(query) { - var newQuery = Object.assign({}, query) - var idQuery = query[property] - // only convert if id is present - if (!idQuery) { - return newQuery - } +const castComplexId = query => { + var newQuery = Object.assign({}, query) - if (Object(idQuery) === idQuery) { - newQuery[property] = castComplexId(idQuery) + Object.keys(newQuery).map(function(key) { + var value = newQuery[key] + if (Array.isArray(value)) { + newQuery[key] = value.map(function(item) { + return ObjectId.isValid(item) ? new ObjectId(item) : item + }) } else { - newQuery[property] = ObjectId.isValid(newQuery[property]) - ? new ObjectId(newQuery[property]) - : newQuery[property] + newQuery[key] = ObjectId.isValid(value) ? new ObjectId(value) : value } + }) - return newQuery - } - - function castComplexId(query) { - var newQuery = Object.assign({}, query) - - Object.keys(newQuery).map(function(key) { - var value = newQuery[key] - if (Array.isArray(value)) { - newQuery[key] = value.map(function(item) { - return ObjectId.isValid(item) ? new ObjectId(item) : item - }) - } else { - newQuery[key] = ObjectId.isValid(value) ? new ObjectId(value) : value - } - }) - - return newQuery - } + return newQuery } + +module.exports = init diff --git a/lib/mongodb-engine.js b/lib/mongodb-engine.js index 1ebb27c..a061f9b 100644 --- a/lib/mongodb-engine.js +++ b/lib/mongodb-engine.js @@ -1,32 +1,34 @@ -module.exports = createEngine - -var emptyFn = function() {} -var ObjectId = require('mongodb').ObjectId -var through = require('through2') -var es = require('event-stream') -var createCastIdProperty = require('./cast-id-property') +const emptyFn = () => {} +const { ObjectId } = require('mongodb') +const through = require('through2') +const es = require('event-stream') +const createCastIdProperty = require('./cast-id-property') function createEngine(collection, engineOptions) { - var self = es.map(createOrUpdate) - var options = Object.assign({}, { idProperty: '_id' }, engineOptions) - var castIdProperty = createCastIdProperty(options.idProperty) + const self = es.map(createOrUpdate) + const options = Object.assign({}, { idProperty: '_id' }, engineOptions) + const castIdProperty = createCastIdProperty(options.idProperty) - function create(object, callback) { - callback = callback || emptyFn + function create(object, callback = emptyFn) { // if id is any falsy consider it empty if (!object[options.idProperty]) { delete object[options.idProperty] } self.emit('create', object) - var entity = Object.assign({}, object) - collection.insertOne(entity, function(error, res) { - if (error) return callback(error) - entity[options.idProperty] = res.insertedId - var data = objectIdToString(entity) - self.emit('afterCreate', data) - self.emit('received', data) - callback(null, data) - }) + const entity = Object.assign({}, object) + + collection + .insertOne(entity) + .then(res => { + entity[options.idProperty] = res.insertedId + const data = objectIdToString(entity) + self.emit('afterCreate', data) + self.emit('received', data) + callback(null, data) + }) + .catch(error => { + callback(error) + }) } function createOrUpdate(object, callback) { @@ -35,7 +37,7 @@ function createEngine(collection, engineOptions) { self.create(object, callback) } else { // Try and find the object first to update - self.read(object[options.idProperty], function(err, entity) { + self.read(object[options.idProperty], (err, entity) => { if (err) return callback(err) if (entity) { // We found the object so update @@ -48,19 +50,22 @@ function createEngine(collection, engineOptions) { } } - function read(id, callback) { - var query = {} + function read(id, callback = emptyFn) { + const query = {} query[options.idProperty] = id self.emit('read', id) - callback = callback || emptyFn - - collection.findOne(castIdProperty(query), function(error, entity) { - var data = entity === null ? undefined : objectIdToString(entity) - self.emit('received', data) - callback(error, data) - }) + collection + .findOne(castIdProperty(query)) + .then(entity => { + const data = entity === null ? undefined : objectIdToString(entity) + self.emit('received', data) + callback(null, data) + }) + .catch(error => { + callback(error) + }) } function update(object, overwrite, callback) { @@ -71,70 +76,72 @@ function createEngine(collection, engineOptions) { self.emit('update', object, overwrite) callback = callback || emptyFn - var query = {} - var updateObject = Object.assign({}, object) - var updateData = overwrite ? updateObject : { $set: updateObject } - var updateFunction = overwrite ? 'findOneAndReplace' : 'findOneAndUpdate' - var id = object[options.idProperty] - var typedId + const query = {} + const updateObject = Object.assign({}, object) + const updateData = overwrite ? updateObject : { $set: updateObject } + const updateFunction = overwrite ? 'findOneAndReplace' : 'findOneAndUpdate' + const id = object[options.idProperty] if (id === undefined || id === null) { return callback( - new Error("Object has no '" + options.idProperty + "' property") + new Error(`Object has no '${options.idProperty}' property`) ) } query[options.idProperty] = id delete updateObject[options.idProperty] - typedId = castIdProperty(query) - - collection[updateFunction]( - typedId, - updateData, - { returnDocument: 'after', sort: { _id: 1 } }, - function(error, res) { - if (error) return callback(error) - if (res.value === null) { - return callback( - new Error( - "No object found with '" + options.idProperty + "' = '" + id + "'" - ) + const typedId = castIdProperty(query) + + collection[updateFunction](typedId, updateData, { + returnDocument: 'after', + sort: { _id: 1 } + }) + .then(res => { + if (res === null || res.value === null) { + throw new Error( + `No object found with '${options.idProperty}' = '${id}'` ) } - var entity = objectIdToString(res.value) + // Handle both old and new response formats + const resultValue = res.value || res + const entity = objectIdToString(resultValue) self.emit('afterUpdate', entity) self.emit('received', entity) - callback(error, entity) - } - ) + callback(null, entity) + }) + .catch(error => { + callback(error) + }) } - function updateMany(query, object, callback) { + function updateMany(query, object, callback = emptyFn) { self.emit('updateMany', query, object) - callback = callback || emptyFn - collection.update( - query, - { $set: object }, - { multi: true, safe: true, upsert: false }, - function(error) { - if (error) return callback(error) + collection + .updateMany(query, { $set: object }, { upsert: false }) + .then(result => { self.emit('afterUpdateMany', query, object) self.emit('received', object) + callback(null, result) + }) + .catch(error => { callback(error) - } - ) + }) } - function deleteMany(query, callback) { + function deleteMany(query, callback = emptyFn) { self.emit('deleteMany', query) - callback = callback || emptyFn - collection.deleteMany(castIdProperty(query), function(error) { - if (error) return callback(error) - self.emit('afterDeleteMany', query) - callback() - }) + + collection + .deleteMany(castIdProperty(query)) + .then(result => { + self.emit('afterDeleteMany', query) + callback(null, result) + }) + .catch(error => { + callback(error) + }) } /** @@ -145,28 +152,33 @@ function createEngine(collection, engineOptions) { * @param {Function} callback * @api public */ - function del(id, callback) { - callback = callback || emptyFn - + function del(id, callback = emptyFn) { if (typeof callback !== 'function') { throw new TypeError('callback must be a function or empty') } self.emit('delete', id) - var query = {} + const query = {} query[options.idProperty] = id - collection.deleteOne(castIdProperty(query), function(error) { - if (error) return callback(error) - self.emit('afterDelete', id) - callback() - }) + + collection + .deleteOne(castIdProperty(query)) + .then(result => { + self.emit('afterDelete', id) + callback(undefined, result) + }) + .catch(error => { + callback(error) + }) } // Because your application using save shouldn't know about engine internals // ObjectId must be converted to strings before returning. function objectIdToString(entity) { - entity[options.idProperty] = entity[options.idProperty].toString() + if (entity && entity[options.idProperty]) { + entity[options.idProperty] = entity[options.idProperty].toString() + } return entity } @@ -179,35 +191,40 @@ function createEngine(collection, engineOptions) { if (saveOptions === undefined) { saveOptions = {} } - var options = Object.assign({}, saveOptions) + const findOptions = Object.assign({}, saveOptions) - if (options.fields) { - options.projection = options.fields - delete options.fields + if (findOptions.fields) { + findOptions.projection = findOptions.fields + delete findOptions.fields } + // This is the streaming implementation if (callback === undefined) { - self.emit('find', query, options) - var convertIdStream = through.obj(function(chunk, enc, cb) { - var mappedData = objectIdToString(chunk) + self.emit('find', query, findOptions) + const convertIdStream = through.obj((chunk, enc, cb) => { + const mappedData = objectIdToString(chunk) self.emit('received', mappedData) cb(null, mappedData) }) - var cursor = collection.find(castIdProperty(query), options) + const cursor = collection.find(castIdProperty(query), findOptions) return cursor.stream().pipe(convertIdStream) } else if (typeof callback !== 'function') { throw new Error('callback must be a function') } + // Callback implementation - Uses lots of memory - self.emit('find', query, options) + self.emit('find', query, findOptions) collection - .find(castIdProperty(query), options) - .toArray(function(error, data) { - if (error) return callback(error) - var mappedData = data.map(objectIdToString) + .find(castIdProperty(query), findOptions) + .toArray() + .then(data => { + const mappedData = data.map(objectIdToString) self.emit('received', mappedData) callback(null, mappedData) }) + .catch(error => { + callback(error) + }) } function findOne(query, options, callback) { @@ -216,35 +233,48 @@ function createEngine(collection, engineOptions) { options = {} } self.emit('findOne', query) - collection.findOne(castIdProperty(query), options, function(error, entity) { - if (error) return callback(error) - var mappedEntity = entity === null ? undefined : objectIdToString(entity) - self.emit('received', mappedEntity) - callback(error, mappedEntity) - }) + + collection + .findOne(castIdProperty(query), options) + .then(entity => { + const mappedEntity = + entity === null ? undefined : objectIdToString(entity) + self.emit('received', mappedEntity) + callback(null, mappedEntity) + }) + .catch(error => { + callback(error) + }) } function count(query, callback) { self.emit('count', query) - collection.countDocuments(castIdProperty(query), function(error, data) { - if (error) return callback(error) - self.emit('received', data) - callback(null, data) - }) + + collection + .countDocuments(castIdProperty(query)) + .then(data => { + self.emit('received', data) + callback(null, data) + }) + .catch(error => { + callback(error) + }) } return Object.assign(self, { - create: create, - createOrUpdate: createOrUpdate, - read: read, - update: update, - updateMany: updateMany, - deleteMany: deleteMany, + create, + createOrUpdate, + read, + update, + updateMany, + deleteMany, delete: del, - find: find, - findOne: findOne, - count: count, + find, + findOne, + count, idProperty: options.idProperty, - idType: ObjectId + idType: id => new ObjectId(id) }) } + +module.exports = createEngine diff --git a/package.json b/package.json index 814a0ba..b619d4c 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "author": "Paul Serby ", "name": "@clocklimited/save-mongodb", "description": "mongodb persistence engine for save", - "version": "4.0.0", + "version": "5.0.0", "tags": [ "database", "save", @@ -27,7 +27,7 @@ "posttest": "(nyc check-coverage --statements 85 --branches 75 --functions 90 --lines 90 && rm -rf coverage) || nyc report --reporter=html && echo Look at 'coverage/index.html' to find out more" }, "engines": { - "node": ">=12" + "node": ">=18" }, "dependencies": { "event-stream": "^4.0.1", @@ -41,7 +41,7 @@ "eslint-plugin-prettier": "^4.0.0", "jsinspect": "^0.12.6", "mocha": "^6.2.0", - "mongodb": "^4.6.0", + "mongodb": "~6.16.0", "nyc": "^14.1.1", "prettier": "^1.18.2", "save": "^2.4.0", diff --git a/test/cast-id-property.test.js b/test/cast-id-property.test.js index 4383cc2..965d054 100644 --- a/test/cast-id-property.test.js +++ b/test/cast-id-property.test.js @@ -1,44 +1,44 @@ -var assert = require('assert') -var ObjectID = require('mongodb').ObjectID -var castIdProperty = require('../lib/cast-id-property') +const assert = require('assert') +const { ObjectId } = require('mongodb') // Changed ObjectID to ObjectId +const castIdProperty = require('../lib/cast-id-property') describe('cast-id-property', function() { it('should return original query if idProperty doesnt exist in query', function() { - var query = { a: 'something' } - var result = castIdProperty('_id')(query) + const query = { a: 'something' } + const result = castIdProperty('_id')(query) assert.deepStrictEqual(result, query) }) it('should return cast property if single value provided', function() { - var objectId = new ObjectID() - var query = { _id: objectId.toString() } - var result = castIdProperty('_id')(query) + const objectId = new ObjectId() // Changed ObjectID to ObjectId + const query = { _id: objectId.toString() } + const result = castIdProperty('_id')(query) assert.deepStrictEqual(result, { _id: objectId }) }) it('should return string if single string value provided', function() { - var stringA = 'something' - var query = { _id: { $neq: stringA } } - var result = castIdProperty('_id')(query) + const stringA = 'something' + const query = { _id: { $neq: stringA } } + const result = castIdProperty('_id')(query) assert.deepStrictEqual(result, query) }) it('should return cast object if object provided', function() { - var objectA = new ObjectID() - var objectB = new ObjectID() - var query = { _id: { $in: [objectA.toString(), objectB.toString()] } } - var result = castIdProperty('_id')(query) + const objectA = new ObjectId() // Changed ObjectID to ObjectId + const objectB = new ObjectId() // Changed ObjectID to ObjectId + const query = { _id: { $in: [objectA.toString(), objectB.toString()] } } + const result = castIdProperty('_id')(query) assert.deepStrictEqual(result, { _id: { $in: [objectA, objectB] } }) }) it('should cast only object if mixture is provided', function() { - var objectA = new ObjectID() - var objectB = new ObjectID() - var stringA = 'something' - var query = { + const objectA = new ObjectId() // Changed ObjectID to ObjectId + const objectB = new ObjectId() // Changed ObjectID to ObjectId + const stringA = 'something' + const query = { _id: { $in: [objectA.toString(), stringA, objectB.toString()] } } - var result = castIdProperty('_id')(query) + const result = castIdProperty('_id')(query) assert.deepStrictEqual(result, { _id: { $in: [objectA, stringA, objectB] } }) diff --git a/test/mongodb-engine.test.js b/test/mongodb-engine.test.js index a173e9d..7d83e51 100644 --- a/test/mongodb-engine.test.js +++ b/test/mongodb-engine.test.js @@ -1,53 +1,75 @@ -var idProperty = '_id' -var MongoClient = require('mongodb').MongoClient -var assert = require('assert') -var Stream = require('stream').Stream -var mapSeries = require('async').mapSeries -var streamAssert = require('stream-assert') -var engine = require('../lib/mongodb-engine') -var connection -var collection -var mongoClient - -function getEngine(options, callback) { +const idProperty = '_id' +const MongoClient = require('mongodb').MongoClient +const assert = require('assert') +const Stream = require('stream').Stream +const mapSeries = require('async').mapSeries // This is callback-based, fine as is +const streamAssert = require('stream-assert') +const engine = require('../lib/mongodb-engine') // Your updated engine + +let connection +let collection +let mongoClient + +async function getEngine(options, callback) { if (callback === undefined) { callback = options options = {} } - collection.deleteMany({}, function(error) { - if (error) { - console.error('GetEngine', error) - return callback(error) + + try { + if (!collection) { + throw new Error( + 'MongoDB collection not initialized. Check connect() function.' + ) } - collection.countDocuments({}, function(error, results) { - if (error) { - console.error('GetEngine', error) - return callback(error) - } - if (results.length > 0) { - console.error('GetEngine Check Empty Collection', error) - return console.log(results) + + try { + await collection.drop() + collection = connection.collection('test') + } catch (dropError) { + if (dropError.codeName !== 'NamespaceNotFound') { + throw dropError } - callback(null, engine(collection, options)) - }) - }) + } + + const results = await collection.countDocuments({}) + + if (results > 0) { + const errorMessage = `Collection not empty after drop/re-init, count: ${results}` + console.error('GetEngine Check Empty Collection:', errorMessage) + return callback(new Error(errorMessage)) + } + callback(null, engine(collection, options)) + } catch (error) { + console.error('GetEngine Error:', error) + callback(error) + } } -function connect(done) { - MongoClient.connect('mongodb://localhost:27017/test', function(err, client) { - if (err) return done(err) +async function connect(done) { + try { + const client = await MongoClient.connect('mongodb://localhost:27019/test') mongoClient = client connection = client.db('test') collection = connection.collection('test') done() - }) + } catch (err) { + done(err) + } } -function drop(done) { - connection.dropDatabase(function(err) { - if (err) return done(err) - mongoClient.close(done) - }) +async function drop() { + try { + if (connection) { + await connection.dropDatabase() + } + if (mongoClient) { + await mongoClient.close() + } + return Promise.resolve() + } catch (err) { + return Promise.reject(err) + } } require('save/test/engine.tests')(idProperty, getEngine, connect) @@ -63,7 +85,7 @@ describe('mongodb-engine', function() { documents ) { if (err) return done(err) - var query = {} + const query = {} query[idProperty] = { $in: [documents[0][idProperty], documents[1][idProperty]] } @@ -81,7 +103,7 @@ describe('mongodb-engine', function() { if (err) return done(err) mapSeries([{ a: 1 }, { a: 2 }], engine.create, function(err, documents) { if (err) return done(err) - var query = {} + const query = {} query[idProperty] = { $nin: [documents[0][idProperty]] } engine.find(query, function(err, queryResults) { if (err) return done(err) @@ -101,7 +123,7 @@ describe('mongodb-engine', function() { if (err) return done(err) mapSeries([{ a: 1 }, { a: 2 }], engine.create, function(err, documents) { if (err) return done(err) - var query = {} + const query = {} query[idProperty] = { $ne: documents[0][idProperty] } engine.find(query, function(err, queryResults) { if (err) return done(err) @@ -121,11 +143,11 @@ describe('mongodb-engine', function() { if (err) return done(err) engine.create({ a: 1 }, function(err, saved) { if (err) return done(err) - engine.update({ _id: saved._id }, false, function(err) { + engine.update({ _id: saved._id, b: 2 }, false, function(err) { assert.strictEqual( - /No object found with '_id' =/.test(err.message), + /No object found with '_id' =/.test(err ? err.message : ''), false, - 'Unexpected error message: ' + err.message + 'Unexpected error message: ' + (err ? err.message : 'No error') ) done() }) @@ -150,7 +172,7 @@ describe('mongodb-engine', function() { documents ) { if (error) return done(error) - var stream = engine.find({ b: 0 }, { cheese: 12, sort: { a: 1 } }) + const stream = engine.find({ b: 0 }, { cheese: 12, sort: { a: 1 } }) stream .pipe( streamAssert.first(function(data) { @@ -172,7 +194,7 @@ describe('mongodb-engine', function() { if (err) return done(err) mapSeries([{}, {}, {}, {}, {}], engine.create, function(err) { if (err) return done(err) - var stream = engine.find({}) + const stream = engine.find({}) setTimeout(function() { stream.pipe(streamAssert.length(5)).pipe(streamAssert.end(done)) }, 100) @@ -188,7 +210,7 @@ describe('mongodb-engine', function() { const objects = [{ a: 1 }, { a: 2 }, { a: 3 }] mapSeries(objects, engine.create, function(err, documents) { if (err) return done(err) - var query = {} + const query = {} query[idProperty] = { $in: [ documents[0][idProperty], @@ -215,7 +237,7 @@ describe('mongodb-engine', function() { ] mapSeries(objects, engine.create, function(err, documents) { if (err) return done(err) - var query = {} + const query = {} query[idProperty] = { $in: [ documents[0][idProperty], diff --git a/yarn.lock b/yarn.lock index 521db64..fdcdc8a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -126,22 +126,23 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== -"@types/node@*": - version "17.0.36" - resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.36.tgz#c0d5f2fe76b47b63e0e0efc3d2049a9970d68794" - integrity sha512-V3orv+ggDsWVHP99K3JlwtH20R7J4IhI1Kksgc+64q5VxgfRkQG8Ws3MFm/FZOKDYGy9feGFlZ70/HpCNe9QaA== +"@mongodb-js/saslprep@^1.1.9": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@mongodb-js/saslprep/-/saslprep-1.3.0.tgz#75bb770b4b0908047b6c6ac2ec841047660e1c82" + integrity sha512-zlayKCsIjYb7/IdfqxorK5+xUMyi4vOKcFy10wKJYc63NSdKI8mNME+uJqfatkPmOSMMUiojrL58IePKBm3gvQ== + dependencies: + sparse-bitfield "^3.0.3" "@types/webidl-conversions@*": version "6.1.1" resolved "https://registry.yarnpkg.com/@types/webidl-conversions/-/webidl-conversions-6.1.1.tgz#e33bc8ea812a01f63f90481c666334844b12a09e" integrity sha512-XAahCdThVuCFDQLT7R7Pk/vqeObFNL3YqRyFZg+AqAP/W1/w3xHaIxuW7WszQqTbIBOPRcItYJIou3i/mppu3Q== -"@types/whatwg-url@^8.2.1": - version "8.2.1" - resolved "https://registry.yarnpkg.com/@types/whatwg-url/-/whatwg-url-8.2.1.tgz#f1aac222dab7c59e011663a0cb0a3117b2ef05d4" - integrity sha512-2YubE1sjj5ifxievI5Ge1sckb9k/Er66HyR2c+3+I6VDUUg1TLPdYYTEbQ+DjRkS4nTxMJhgWfSfMRD2sl2EYQ== +"@types/whatwg-url@^11.0.2": + version "11.0.5" + resolved "https://registry.yarnpkg.com/@types/whatwg-url/-/whatwg-url-11.0.5.tgz#aaa2546e60f0c99209ca13360c32c78caf2c409f" + integrity sha512-coYR071JRaHa+xoEvvYqvnIHaVqaYrLPbsufM9BF63HkwI5Lgmy2QR8Q5K/lYDYo5AK82wOvSOS0UsLTpTG7uQ== dependencies: - "@types/node" "*" "@types/webidl-conversions" "*" acorn-jsx@^5.3.2: @@ -253,11 +254,6 @@ balanced-match@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" -base64-js@^1.3.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" - integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== - brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -270,20 +266,10 @@ browser-stdout@1.3.1: resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== -bson@^4.6.3: - version "4.6.4" - resolved "https://registry.yarnpkg.com/bson/-/bson-4.6.4.tgz#e66d4a334f1ab230dfcfb9ec4ea9091476dd372e" - integrity sha512-TdQ3FzguAu5HKPPlr0kYQCyrYUYh8tFM+CMTpxjNzVzxeiJY00Rtuj3LXLHSgiGvmaWlZ8PE+4KyM2thqE38pQ== - dependencies: - buffer "^5.6.0" - -buffer@^5.6.0: - version "5.7.1" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" - integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== - dependencies: - base64-js "^1.3.1" - ieee754 "^1.1.13" +bson@^6.10.3: + version "6.10.4" + resolved "https://registry.yarnpkg.com/bson/-/bson-6.10.4.tgz#d530733bb5bb16fb25c162e01a3344fab332fd2b" + integrity sha512-WIsKqkSC0ABoBJuT1LEX+2HEvNmNKKgnTAyd0fL8qzK4SH2i9NXg+t08YtdZp/V9IZ33cxe3iV4yM0qg8lMQng== builtin-modules@^1.0.0: version "1.1.1" @@ -491,11 +477,6 @@ define-properties@^1.1.2: dependencies: object-keys "^1.0.12" -denque@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/denque/-/denque-2.0.1.tgz#bcef4c1b80dc32efe97515744f21a4229ab8934a" - integrity sha512-tfiWc6BQLXNLpNiR5iGd0Ocu3P3VpxfzFiqubLgMfhfOw9WyvgJBd46CClNn9k3qfbjvT//0cf7AlYRX/OslMQ== - diff@3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" @@ -957,11 +938,6 @@ hosted-git-info@^2.1.4: version "2.7.1" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.7.1.tgz#97f236977bd6e125408930ff6de3eec6281ec047" -ieee754@^1.1.13: - version "1.2.1" - resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" - integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== - ignore@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.1.tgz#2fc6b8f518aff48fef65a7f348ed85632448e4a5" @@ -1008,11 +984,6 @@ invert-kv@^2.0.0: resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02" integrity sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA== -ip@^1.1.5: - version "1.1.8" - resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.8.tgz#ae05948f6b075435ed3307acce04629da8cdbf48" - integrity sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg== - is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" @@ -1373,25 +1344,22 @@ mocha@^6.2.0: yargs-parser "13.0.0" yargs-unparser "1.5.0" -mongodb-connection-string-url@^2.5.2: - version "2.5.2" - resolved "https://registry.yarnpkg.com/mongodb-connection-string-url/-/mongodb-connection-string-url-2.5.2.tgz#f075c8d529e8d3916386018b8a396aed4f16e5ed" - integrity sha512-tWDyIG8cQlI5k3skB6ywaEA5F9f5OntrKKsT/Lteub2zgwSUlhqEN2inGgBTm8bpYJf8QYBdA/5naz65XDpczA== +mongodb-connection-string-url@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.2.tgz#e223089dfa0a5fa9bf505f8aedcbc67b077b33e7" + integrity sha512-rMO7CGo/9BFwyZABcKAWL8UJwH/Kc2x0g72uhDWzG48URRax5TCIcJ7Rc3RZqffZzO/Gwff/jyKwCU9TN8gehA== dependencies: - "@types/whatwg-url" "^8.2.1" - whatwg-url "^11.0.0" + "@types/whatwg-url" "^11.0.2" + whatwg-url "^14.1.0 || ^13.0.0" -mongodb@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-4.6.0.tgz#a69216da61f4cb1498d68cb396c52313fa39cef6" - integrity sha512-1gsxVXmjFTPJ+CkMG9olE4bcVsyY8lBJN9m5B5vj+LZ7wkBqq3PO8RVmNX9GwCBOBz1KV0zM00vPviUearSv7A== +mongodb@~6.16.0: + version "6.16.0" + resolved "https://registry.yarnpkg.com/mongodb/-/mongodb-6.16.0.tgz#2a7a1986ec151d9c738fc8ce4cf4324c3f728a2f" + integrity sha512-D1PNcdT0y4Grhou5Zi/qgipZOYeWrhLEpk33n3nm6LGtz61jvO88WlrWCK/bigMjpnOdAUKKQwsGIl0NtWMyYw== dependencies: - bson "^4.6.3" - denque "^2.0.1" - mongodb-connection-string-url "^2.5.2" - socks "^2.6.2" - optionalDependencies: - saslprep "^1.0.3" + "@mongodb-js/saslprep" "^1.1.9" + bson "^6.10.3" + mongodb-connection-string-url "^3.0.0" ms@2.1.1, ms@^2.1.1: version "2.1.1" @@ -1685,11 +1653,16 @@ pump@^3.0.0: end-of-stream "^1.1.0" once "^1.3.1" -punycode@^2.1.0, punycode@^2.1.1: +punycode@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== +punycode@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" + integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== + read-pkg-up@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-4.0.0.tgz#1b221c6088ba7799601c808f91161c66e58f8978" @@ -1787,13 +1760,6 @@ safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" -saslprep@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/saslprep/-/saslprep-1.0.3.tgz#4c02f946b56cf54297e347ba1093e7acac4cf226" - integrity sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag== - dependencies: - sparse-bitfield "^3.0.3" - save@^2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/save/-/save-2.4.0.tgz#af93ff9b3d7a41d0aff49a23433870613a460f9b" @@ -1890,19 +1856,6 @@ signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" -smart-buffer@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae" - integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg== - -socks@^2.6.2: - version "2.6.2" - resolved "https://registry.yarnpkg.com/socks/-/socks-2.6.2.tgz#ec042d7960073d40d94268ff3bb727dc685f111a" - integrity sha512-zDZhHhZRY9PxRruRMR7kMhnf3I8hDs4S3f9RecfnGxvcBHQcKcIH/oUcEWffsfl1XxdYlA7nnlGbbTvPz9D8gA== - dependencies: - ip "^1.1.5" - smart-buffer "^4.2.0" - source-map@^0.5.0: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" @@ -2140,12 +2093,12 @@ to-fast-properties@^2.0.0: resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= -tr46@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/tr46/-/tr46-3.0.0.tgz#555c4e297a950617e8eeddef633c87d4d9d6cbf9" - integrity sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA== +tr46@^5.1.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-5.1.1.tgz#96ae867cddb8fdb64a49cc3059a8d428bcf238ca" + integrity sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw== dependencies: - punycode "^2.1.1" + punycode "^2.3.1" trim-right@^1.0.1: version "1.0.1" @@ -2206,12 +2159,12 @@ webidl-conversions@^7.0.0: resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-7.0.0.tgz#256b4e1882be7debbf01d05f0aa2039778ea080a" integrity sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g== -whatwg-url@^11.0.0: - version "11.0.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-11.0.0.tgz#0a849eebb5faf2119b901bb76fd795c2848d4018" - integrity sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ== +"whatwg-url@^14.1.0 || ^13.0.0": + version "14.2.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-14.2.0.tgz#4ee02d5d725155dae004f6ae95c73e7ef5d95663" + integrity sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw== dependencies: - tr46 "^3.0.0" + tr46 "^5.1.0" webidl-conversions "^7.0.0" which-module@^2.0.0: From 51528bdcbf526a57b8d76978aef353c7e246a738 Mon Sep 17 00:00:00 2001 From: Dawid Teper Date: Fri, 27 Jun 2025 15:12:29 +0100 Subject: [PATCH 2/8] chore: Update readme and tests --- .circleci/config.yml | 39 ------------------------------ .github/workflows/ci.yaml | 51 +++++++++++++++++++++++++++++++++++++++ .naverc | 1 + README.md | 20 +++++++-------- 4 files changed, 62 insertions(+), 49 deletions(-) delete mode 100644 .circleci/config.yml create mode 100644 .github/workflows/ci.yaml create mode 100644 .naverc diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index 544cdce..0000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,39 +0,0 @@ -version: 2 - -jobs: - build: - name: 'Test' - docker: - - image: circleci/node:16 - - image: mongo:4.2.0 - resource_class: small - working_directory: ~/save-mongodb - parallelism: 4 - steps: - - run: - name: Waiting for MongoDB - command: dockerize -wait tcp://localhost:27017 -timeout 1m - - checkout - - setup_remote_docker - - run: - name: Switch Node Version - command: | - wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.38.0/install.sh | bash - export NVM_DIR="$HOME/.nvm" - . "$NVM_DIR/nvm.sh" --install - echo 'export NVM_DIR="$HOME/.nvm"' >> $BASH_ENV; - echo '[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"' >> $BASH_ENV; - case $CIRCLE_NODE_INDEX in \ - 0) NODE_VERSION=12 ;; \ - 1) NODE_VERSION=14 ;; \ - 2) NODE_VERSION=16 ;; \ - 3) NODE_VERSION=18 ;; \ - esac; - nvm install $NODE_VERSION && nvm alias default $NODE_VERSION - - run: - name: Print Versions - command: | - node --version - npm --version - - run: yarn install - - run: yarn test diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000..bd06e7a --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,51 @@ +name: Test + +on: [push, pull_request] + +jobs: + test: + name: Test (Node ${{ matrix.node-version }}) + runs-on: ubuntu-latest + strategy: + matrix: + node-version: [18, 20] + services: + mongo: + image: mongo:8 + ports: + - 27017:27017 + options: >- + --health-cmd="mongosh --eval 'db.runCommand({ ping: 1 })'" + --health-interval=10s + --health-timeout=5s + --health-retries=5 + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node-version }} + cache: yarn + + - name: Wait for MongoDB + run: | + for i in {1..30}; do + nc -z localhost 27017 && echo "MongoDB is up!" && break + echo "Waiting for MongoDB..." + sleep 2 + done + + - name: Print versions + run: | + node -v + npm -v + yarn -v + + - name: Install dependencies + run: yarn install + + - name: Run tests + run: yarn test diff --git a/.naverc b/.naverc new file mode 100644 index 0000000..25bf17f --- /dev/null +++ b/.naverc @@ -0,0 +1 @@ +18 \ No newline at end of file diff --git a/README.md b/README.md index 75da17d..f4964df 100644 --- a/README.md +++ b/README.md @@ -1,35 +1,35 @@ # @clocklimited/save-mongodb - mongodb persistence engine for **save** -[![CircleCI](https://circleci.com/gh/clocklimited/save-mongodb/tree/master.svg?style=svg)](https://circleci.com/gh/clocklimited/save-mongodb/tree/master) - ## Installation ``` npm install @clocklimited/save-mongodb // There is a peer dependency of mongodb - you have to bring your own! -npm install mongodb@^4 +npm install mongodb@^8 ``` ## Usage +Version >=5 is compatible with MongoDB 8. + If you want to see how this works look at the tests or this simple example: ```js -var MongoClient = require('mongodb').MongoClient // npm install mongodb -var save = require('save') // npm install save -var saveMongodb = require('@clocklimited/save-mongodb') +const MongoClient = require('mongodb').MongoClient // npm install mongodb +const save = require('save') // npm install save +const saveMongodb = require('@clocklimited/save-mongodb') // connect to your mongodb database. MongoClient.connect('mongodb://localhost:27017/', function(error, client) { if (error) return console.error(error.message) - var connection = client.db('test') + const connection = client.db('test') // Get a collection. This will create the collection if it doesn't exist. connection.collection('contact', function(error, collection) { if (error) return console.error(error.message) // Create a save object and pass in a mongodb engine. - var contactStore = save('Contact', { engine: saveMongodb(collection) }) + const contactStore = save('Contact', { engine: saveMongodb(collection) }) // Then we can create a new object. contactStore.create({ name: 'Paul', email: 'paul@serby.net' }, function( @@ -54,8 +54,8 @@ Find now has a streaming interface ```js -var contactStore = save('Contact', { engine: saveMongodb(collection) }) -var es = require('event-stream') +const contactStore = save('Contact', { engine: saveMongodb(collection) }) +const es = require('event-stream') contactStore.find({}) .pipe(es.stringify()) From 3f81c6b611dbe3a8b2e8d9bc105b4b67cdab8970 Mon Sep 17 00:00:00 2001 From: Dawid Teper Date: Fri, 27 Jun 2025 15:21:47 +0100 Subject: [PATCH 3/8] fix: Tests --- lib/cast-id-property.js | 2 +- lib/mongodb-engine.js | 10 ---------- test/cast-id-property.test.js | 12 ++++++------ test/mongodb-engine.test.js | 6 +++--- 4 files changed, 10 insertions(+), 20 deletions(-) diff --git a/lib/cast-id-property.js b/lib/cast-id-property.js index 7824fc2..afd1f31 100644 --- a/lib/cast-id-property.js +++ b/lib/cast-id-property.js @@ -3,7 +3,7 @@ const ObjectId = require('mongodb').ObjectId const init = property => query => { let newQuery = Object.assign({}, query) const idQuery = query[property] - // only convert if id is present + if (!idQuery) { return newQuery } diff --git a/lib/mongodb-engine.js b/lib/mongodb-engine.js index a061f9b..95a1132 100644 --- a/lib/mongodb-engine.js +++ b/lib/mongodb-engine.js @@ -10,7 +10,6 @@ function createEngine(collection, engineOptions) { const castIdProperty = createCastIdProperty(options.idProperty) function create(object, callback = emptyFn) { - // if id is any falsy consider it empty if (!object[options.idProperty]) { delete object[options.idProperty] } @@ -33,17 +32,13 @@ function createEngine(collection, engineOptions) { function createOrUpdate(object, callback) { if (typeof object[options.idProperty] === 'undefined') { - // Create a new object self.create(object, callback) } else { - // Try and find the object first to update self.read(object[options.idProperty], (err, entity) => { if (err) return callback(err) if (entity) { - // We found the object so update self.update(object, callback) } else { - // We didn't find the object so create self.create(object, callback) } }) @@ -103,7 +98,6 @@ function createEngine(collection, engineOptions) { `No object found with '${options.idProperty}' = '${id}'` ) } - // Handle both old and new response formats const resultValue = res.value || res const entity = objectIdToString(resultValue) self.emit('afterUpdate', entity) @@ -173,8 +167,6 @@ function createEngine(collection, engineOptions) { }) } - // Because your application using save shouldn't know about engine internals - // ObjectId must be converted to strings before returning. function objectIdToString(entity) { if (entity && entity[options.idProperty]) { entity[options.idProperty] = entity[options.idProperty].toString() @@ -198,7 +190,6 @@ function createEngine(collection, engineOptions) { delete findOptions.fields } - // This is the streaming implementation if (callback === undefined) { self.emit('find', query, findOptions) const convertIdStream = through.obj((chunk, enc, cb) => { @@ -212,7 +203,6 @@ function createEngine(collection, engineOptions) { throw new Error('callback must be a function') } - // Callback implementation - Uses lots of memory self.emit('find', query, findOptions) collection .find(castIdProperty(query), findOptions) diff --git a/test/cast-id-property.test.js b/test/cast-id-property.test.js index 965d054..bfade47 100644 --- a/test/cast-id-property.test.js +++ b/test/cast-id-property.test.js @@ -1,5 +1,5 @@ const assert = require('assert') -const { ObjectId } = require('mongodb') // Changed ObjectID to ObjectId +const { ObjectId } = require('mongodb') const castIdProperty = require('../lib/cast-id-property') describe('cast-id-property', function() { @@ -10,7 +10,7 @@ describe('cast-id-property', function() { }) it('should return cast property if single value provided', function() { - const objectId = new ObjectId() // Changed ObjectID to ObjectId + const objectId = new ObjectId() const query = { _id: objectId.toString() } const result = castIdProperty('_id')(query) assert.deepStrictEqual(result, { _id: objectId }) @@ -24,16 +24,16 @@ describe('cast-id-property', function() { }) it('should return cast object if object provided', function() { - const objectA = new ObjectId() // Changed ObjectID to ObjectId - const objectB = new ObjectId() // Changed ObjectID to ObjectId + const objectA = new ObjectId() + const objectB = new ObjectId() const query = { _id: { $in: [objectA.toString(), objectB.toString()] } } const result = castIdProperty('_id')(query) assert.deepStrictEqual(result, { _id: { $in: [objectA, objectB] } }) }) it('should cast only object if mixture is provided', function() { - const objectA = new ObjectId() // Changed ObjectID to ObjectId - const objectB = new ObjectId() // Changed ObjectID to ObjectId + const objectA = new ObjectId() + const objectB = new ObjectId() const stringA = 'something' const query = { _id: { $in: [objectA.toString(), stringA, objectB.toString()] } diff --git a/test/mongodb-engine.test.js b/test/mongodb-engine.test.js index 7d83e51..c24cd3a 100644 --- a/test/mongodb-engine.test.js +++ b/test/mongodb-engine.test.js @@ -2,9 +2,9 @@ const idProperty = '_id' const MongoClient = require('mongodb').MongoClient const assert = require('assert') const Stream = require('stream').Stream -const mapSeries = require('async').mapSeries // This is callback-based, fine as is +const mapSeries = require('async').mapSeries const streamAssert = require('stream-assert') -const engine = require('../lib/mongodb-engine') // Your updated engine +const engine = require('../lib/mongodb-engine') let connection let collection @@ -48,7 +48,7 @@ async function getEngine(options, callback) { async function connect(done) { try { - const client = await MongoClient.connect('mongodb://localhost:27019/test') + const client = await MongoClient.connect('mongodb://localhost:27017/test') mongoClient = client connection = client.db('test') collection = connection.collection('test') From 75fbc89043a77c78514446a4326c131346642550 Mon Sep 17 00:00:00 2001 From: Dawid Teper Date: Fri, 27 Jun 2025 15:23:17 +0100 Subject: [PATCH 4/8] fix: clean up --- lib/cast-id-property.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/cast-id-property.js b/lib/cast-id-property.js index afd1f31..7887271 100644 --- a/lib/cast-id-property.js +++ b/lib/cast-id-property.js @@ -20,10 +20,10 @@ const init = property => query => { } const castComplexId = query => { - var newQuery = Object.assign({}, query) + const newQuery = Object.assign({}, query) Object.keys(newQuery).map(function(key) { - var value = newQuery[key] + const value = newQuery[key] if (Array.isArray(value)) { newQuery[key] = value.map(function(item) { return ObjectId.isValid(item) ? new ObjectId(item) : item From 6ee7f250fae0295c7f16991721662b2d2b11cba9 Mon Sep 17 00:00:00 2001 From: Dawid Teper Date: Fri, 27 Jun 2025 15:30:52 +0100 Subject: [PATCH 5/8] chore: Bump mongodb peer dep --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b619d4c..193341e 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,6 @@ "stream-assert": "^2.0.3" }, "peerDependencies": { - "mongodb": "~4" + "mongodb": "~6" } } From 064f42164188e2161d2cf0b7088fe94aad7bb3bb Mon Sep 17 00:00:00 2001 From: Dawid Teper Date: Fri, 27 Jun 2025 15:45:27 +0100 Subject: [PATCH 6/8] 5.0.0-beta-1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 193341e..50a2d5c 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "author": "Paul Serby ", "name": "@clocklimited/save-mongodb", "description": "mongodb persistence engine for save", - "version": "5.0.0", + "version": "5.0.0-beta-1", "tags": [ "database", "save", From 96ef1e3089d30e784245384124a022f708293127 Mon Sep 17 00:00:00 2001 From: Dawid Teper Date: Fri, 27 Jun 2025 15:51:38 +0100 Subject: [PATCH 7/8] chore: Update readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f4964df..7c8f6c0 100644 --- a/README.md +++ b/README.md @@ -6,12 +6,12 @@ npm install @clocklimited/save-mongodb // There is a peer dependency of mongodb - you have to bring your own! -npm install mongodb@^8 +npm install mongodb@^6 ``` ## Usage -Version >=5 is compatible with MongoDB 8. +Version >=5 of this package is compatible with MongoDB 8. If you want to see how this works look at the tests or this simple example: From dd3d9710673a1479ba481c4b3c108e0d36adda5b Mon Sep 17 00:00:00 2001 From: Dawid Teper Date: Fri, 27 Jun 2025 15:51:50 +0100 Subject: [PATCH 8/8] 5.0.0-beta-2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 50a2d5c..cf6fbc1 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "author": "Paul Serby ", "name": "@clocklimited/save-mongodb", "description": "mongodb persistence engine for save", - "version": "5.0.0-beta-1", + "version": "5.0.0-beta-2", "tags": [ "database", "save",