diff --git a/index.js b/index.js index e17ae59..15177fb 100644 --- a/index.js +++ b/index.js @@ -34,29 +34,24 @@ exports.initialize = function (connection) { }; // The function to use when invoking the plugin on a custom schema. -exports.plugin = function (schema, options) { +exports.plugin = async function (schema, options) { - // If we don't have reference to the counterSchema or the IdentityCounter model then the plugin was most likely not - // initialized properly so throw an error. if (!counterSchema || !IdentityCounter) throw new Error("mongoose-auto-increment has not been initialized"); - // Default settings and plugin scope variables. var settings = { - model: null, // The model to configure the plugin for. - field: '_id', // The field the plugin should track. - startAt: 0, // The number the count should start at. - incrementBy: 1, // The number by which to increment the count each time. - unique: true, // Should we create a unique index for the field, + model: null, + field: '_id', + startAt: 0, + incrementBy: 1, + unique: true, }, - fields = {}, // A hash of fields to add properties to in Mongoose. - ready = false; // True if the counter collection has been updated and the document is ready to be saved. + fields = {}, + ready = false; switch (typeof(options)) { - // If string, the user chose to pass in just the model name. case 'string': settings.model = options; break; - // If object, the user passed in a hash of options. case 'object': extend(settings, options); break; @@ -65,7 +60,6 @@ exports.plugin = function (schema, options) { if (settings.model == null) throw new Error("model must be set"); - // Add properties for field in schema. fields[settings.field] = { type: Number, require: true, @@ -75,109 +69,73 @@ exports.plugin = function (schema, options) { fields[settings.field].unique = settings.unique schema.add(fields); - // Find the counter for this model and the relevant field. - IdentityCounter.findOne( - { model: settings.model, field: settings.field }, - function (err, counter) { - if (!counter) { - // If no counter exists then create one and save it. - counter = new IdentityCounter({ model: settings.model, field: settings.field, count: settings.startAt - settings.incrementBy }); - counter.save(function () { - ready = true; - }); - } - else { - ready = true; - } - } - ); + const counter = await IdentityCounter.findOne({ model: settings.model, field: settings.field }); + + if (!counter) { + counter = new IdentityCounter({ model: settings.model, field: settings.field, count: settings.startAt - settings.incrementBy }); + await counter.save(); + ready = true; + } + else { + ready = true; + } - // Declare a function to get the next counter for the model/schema. - var nextCount = function (callback) { - IdentityCounter.findOne({ - model: settings.model, - field: settings.field - }, function (err, counter) { - if (err) return callback(err); - callback(null, counter === null ? settings.startAt : counter.count + settings.incrementBy); + var nextCount = function () { + return new Promise((resolve, reject) => { + IdentityCounter.findOne({ + model: settings.model, + field: settings.field + }, function (err, counter) { + if (err) return reject(err); + resolve(counter === null ? settings.startAt : counter.count + settings.incrementBy); + }); }); }; - // Add nextCount as both a method on documents and a static on the schema for convenience. schema.method('nextCount', nextCount); schema.static('nextCount', nextCount); - // Declare a function to reset counter at the start value - increment value. - var resetCount = function (callback) { - IdentityCounter.findOneAndUpdate( - { model: settings.model, field: settings.field }, - { count: settings.startAt - settings.incrementBy }, - { new: true }, // new: true specifies that the callback should get the updated counter. - function (err) { - if (err) return callback(err); - callback(null, settings.startAt); - } - ); + var resetCount = function () { + return new Promise((resolve, reject) => { + IdentityCounter.findOneAndUpdate( + { model: settings.model, field: settings.field }, + { count: settings.startAt - settings.incrementBy }, + { new: true }, + function (err) { + if (err) return reject(err); + resolve(settings.startAt); + } + ); + }); }; - // Add resetCount as both a method on documents and a static on the schema for convenience. schema.method('resetCount', resetCount); schema.static('resetCount', resetCount); - // Every time documents in this schema are saved, run this logic. - schema.pre('save', function (next) { - // Get reference to the document being saved. + schema.pre('save', async function (next) { var doc = this; - // Only do this if it is a new document (see http://mongoosejs.com/docs/api.html#document_Document-isNew) if (doc.isNew) { - // Declare self-invoking save function. - (function save() { - // If ready, run increment logic. - // Note: ready is true when an existing counter collection is found or after it is created for the - // first time. + (async function save() { if (ready) { - // check that a number has already been provided, and update the counter to that number if it is - // greater than the current count if (typeof doc[settings.field] === 'number') { - IdentityCounter.findOneAndUpdate( - // IdentityCounter documents are identified by the model and field that the plugin was invoked for. - // Check also that count is less than field value. + await IdentityCounter.findOneAndUpdate( { model: settings.model, field: settings.field, count: { $lt: doc[settings.field] } }, - // Change the count of the value found to the new field value. - { count: doc[settings.field] }, - function (err) { - if (err) return next(err); - // Continue with default document save functionality. - next(); - } + { count: doc[settings.field] } ); + next(); } else { - // Find the counter collection entry for this model and field and update it. - IdentityCounter.findOneAndUpdate( - // IdentityCounter documents are identified by the model and field that the plugin was invoked for. + const updatedIdentityCounter = await IdentityCounter.findOneAndUpdate( { model: settings.model, field: settings.field }, - // Increment the count by `incrementBy`. { $inc: { count: settings.incrementBy } }, - // new:true specifies that the callback should get the counter AFTER it is updated (incremented). - { new: true }, - // Receive the updated counter. - function (err, updatedIdentityCounter) { - if (err) return next(err); - // If there are no errors then go ahead and set the document's field to the current count. - doc[settings.field] = updatedIdentityCounter.count; - // Continue with default document save functionality. - next(); - } + { new: true } ); + doc[settings.field] = updatedIdentityCounter.count; + next(); } } - // If not ready then set a 5 millisecond timer and try to save again. It will keep doing this until - // the counter collection is ready. else setTimeout(save, 5); })(); } - // If the document does not have the field we're interested in or that field isn't a number AND the user did - // not specify that we should increment on updates, then just continue the save without any increment logic. else next(); }); diff --git a/package.json b/package.json index 2d63bf6..53f0470 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "extend": "^3.0.0" }, "peerDependencies": { - "mongoose": "^6.5.0" + "mongoose": "^7.5.4" }, "devDependencies": { "async": "*",