Skip to content

Commit

Permalink
remove remaining callbacks
Browse files Browse the repository at this point in the history
  • Loading branch information
vkarpov15 committed Feb 12, 2023
1 parent adc1481 commit b911bef
Show file tree
Hide file tree
Showing 17 changed files with 500 additions and 616 deletions.
10 changes: 10 additions & 0 deletions docs/migrating_to_7.md
Expand Up @@ -78,16 +78,21 @@ They always return promises.

- `Aggregate.prototype.exec`
- `Aggregate.prototype.explain`
- `AggregationCursor.prototype.close`
- `Connection.prototype.startSession`
- `Connection.prototype.dropCollection`
- `Connection.prototype.createCollection`
- `Connection.prototype.dropDatabase`
- `Connection.prototype.openUri`
- `Connection.prototype.close`
- `Connection.prototype.destroy`
- `Document.prototype.populate`
- `Document.prototype.validate`
- `Mongoose.prototype.connect`
- `Mongoose.prototype.createConnection`
- `Model.prototype.save`
- `Model.aggregate`
- `Model.bulkWrite`
- `Model.cleanIndexes`
- `Model.create`
- `Model.createCollection`
Expand All @@ -106,14 +111,19 @@ They always return promises.
- `Model.findOneAndDelete`
- `Model.findOneAndUpdate`
- `Model.findOneAndRemove`
- `Model.insertMany`
- `Model.listIndexes`
- `Model.replaceOne`
- `Model.syncIndexes`
- `Model.updateMany`
- `Model.updateOne`
- `Query.prototype.find`
- `Query.prototype.findOne`
- `Query.prototype.findOneAndDelete`
- `Query.prototype.findOneAndUpdate`
- `Query.prototype.findOneAndRemove`
- `Query.prototype.findOneAndReplace`
- `Query.prototype.validate`
- `QueryCursor.prototype.close`
- `QueryCursor.prototype.next`

Expand Down
38 changes: 22 additions & 16 deletions lib/cursor/AggregationCursor.js
Expand Up @@ -6,7 +6,6 @@

const MongooseError = require('../error/mongooseError');
const Readable = require('stream').Readable;
const promiseOrCallback = require('../helpers/promiseOrCallback');
const eachAsync = require('../helpers/cursor/eachAsync');
const immediate = require('../helpers/immediate');
const util = require('util');
Expand Down Expand Up @@ -176,32 +175,39 @@ AggregationCursor.prototype._markError = function(error) {
* @see AggregationCursor.close https://mongodb.github.io/node-mongodb-native/4.9/classes/AggregationCursor.html#close
*/

AggregationCursor.prototype.close = function(callback) {
return promiseOrCallback(callback, cb => {
this.cursor.close(error => {
if (error) {
cb(error);
return this.listeners('error').length > 0 && this.emit('error', error);
}
this.emit('close');
cb(null);
});
});
AggregationCursor.prototype.close = async function close() {
if (typeof arguments[0] === 'function') {
throw new MongooseError('AggregationCursor.prototype.close() no longer accepts a callback');
}
try {
await this.cursor.close();
} catch (error) {
this.listeners('error').length > 0 && this.emit('error', error);
throw error;
}
this.emit('close');
};

/**
* Get the next document from this cursor. Will return `null` when there are
* no documents left.
*
* @param {Function} callback
* @return {Promise}
* @api public
* @method next
*/

AggregationCursor.prototype.next = function(callback) {
return promiseOrCallback(callback, cb => {
_next(this, cb);
AggregationCursor.prototype.next = async function next() {
if (typeof arguments[0] === 'function') {
throw new MongooseError('AggregationCursor.prototype.next() no longer accepts a callback');
}
return new Promise((resolve, reject) => {
_next(this, (err, res) => {
if (err != null) {
return reject(err);
}
resolve(res);
});
});
};

Expand Down
25 changes: 14 additions & 11 deletions lib/cursor/QueryCursor.js
Expand Up @@ -428,12 +428,14 @@ function _next(ctx, cb) {
return _nextDoc(ctx, doc, null, callback);
}

ctx.query.model.populate(doc, ctx._pop, function(err, doc) {
if (err) {
return callback(err);
ctx.query.model.populate(doc, ctx._pop).then(
doc => {
_nextDoc(ctx, doc, ctx._pop, callback);
},
err => {
callback(err);
}
return _nextDoc(ctx, doc, ctx._pop, callback);
});
);
},
error => {
callback(error);
Expand Down Expand Up @@ -495,13 +497,14 @@ function _populateBatch() {
return this.callback(null, null);
}
const _this = this;
this.ctx.query.model.populate(this.ctx._batchDocs, this.ctx._pop, function(err) {
if (err) {
return _this.callback(err);
this.ctx.query.model.populate(this.ctx._batchDocs, this.ctx._pop).then(
() => {
_nextDoc(_this.ctx, _this.ctx._batchDocs.shift(), _this.ctx._pop, _this.callback);
},
err => {
_this.callback(err);
}

_nextDoc(_this.ctx, _this.ctx._batchDocs.shift(), _this.ctx._pop, _this.callback);
});
);
}

/*!
Expand Down
46 changes: 18 additions & 28 deletions lib/document.js
Expand Up @@ -17,7 +17,6 @@ const ValidationError = require('./error/validation');
const ValidatorError = require('./error/validator');
const VirtualType = require('./virtualtype');
const $__hasIncludedChildren = require('./helpers/projection/hasIncludedChildren');
const promiseOrCallback = require('./helpers/promiseOrCallback');
const castNumber = require('./cast/number');
const applyDefaults = require('./helpers/document/applyDefaults');
const cleanModifiedSubpaths = require('./helpers/document/cleanModifiedSubpaths');
Expand Down Expand Up @@ -2475,7 +2474,10 @@ Document.prototype.isDirectSelected = function isDirectSelected(path) {
* @api public
*/

Document.prototype.validate = function(pathsToValidate, options, callback) {
Document.prototype.validate = async function validate(pathsToValidate, options) {
if (typeof pathsToValidate === 'function' || typeof options === 'function' || typeof arguments[2] === 'function') {
throw new MongooseError('Document.prototype.validate() no longer accepts a callback');
}
let parallelValidate;
this.$op = 'validate';

Expand All @@ -2493,38 +2495,28 @@ Document.prototype.validate = function(pathsToValidate, options, callback) {
if (arguments.length === 1) {
if (typeof arguments[0] === 'object' && !Array.isArray(arguments[0])) {
options = arguments[0];
callback = null;
pathsToValidate = null;
} else if (typeof arguments[0] === 'function') {
callback = arguments[0];
options = null;
pathsToValidate = null;
}
} else if (typeof pathsToValidate === 'function') {
callback = pathsToValidate;
options = null;
pathsToValidate = null;
} else if (typeof options === 'function') {
callback = options;
options = pathsToValidate;
pathsToValidate = null;
}
if (options && typeof options.pathsToSkip === 'string') {
const isOnePathOnly = options.pathsToSkip.indexOf(' ') === -1;
options.pathsToSkip = isOnePathOnly ? [options.pathsToSkip] : options.pathsToSkip.split(' ');
}

return promiseOrCallback(callback, cb => {
if (parallelValidate != null) {
return cb(parallelValidate);
}
if (parallelValidate != null) {
throw parallelValidate;
}

return new Promise((resolve, reject) => {
this.$__validate(pathsToValidate, options, (error) => {
this.$op = null;
this.$__.validating = null;
cb(error);
if (error != null) {
return reject(error);
}
resolve();
});
}, this.constructor.events);
});
};

/**
Expand Down Expand Up @@ -4299,16 +4291,14 @@ Document.prototype.equals = function(doc) {
* @api public
*/

Document.prototype.populate = function populate() {
Document.prototype.populate = async function populate() {
const pop = {};
const args = [...arguments];
let fn;
if (typeof args[args.length - 1] === 'function') {
throw new MongooseError('Document.prototype.populate() no longer accepts a callback');
}

if (args.length !== 0) {
if (typeof args[args.length - 1] === 'function') {
fn = args.pop();
}

// use hash to remove duplicate paths
const res = utils.populate.apply(null, args);
for (const populateOptions of res) {
Expand Down Expand Up @@ -4345,7 +4335,7 @@ Document.prototype.populate = function populate() {
p._localModel = topLevelModel;
});

return topLevelModel.populate(this, paths, fn);
return topLevelModel.populate(this, paths);
};

/**
Expand Down
17 changes: 10 additions & 7 deletions lib/helpers/cursor/eachAsync.js
Expand Up @@ -6,7 +6,6 @@

const EachAsyncMultiError = require('../../error/eachAsyncMultiError');
const immediate = require('../immediate');
const promiseOrCallback = require('../promiseOrCallback');

/**
* Execute `fn` for every document in the cursor. If `fn` returns a promise,
Expand All @@ -19,13 +18,12 @@ const promiseOrCallback = require('../promiseOrCallback');
* @param {Number} [options.batchSize=null] if set, Mongoose will call `fn` with an array of at most `batchSize` documents, instead of a single document
* @param {Number} [options.parallel=1] maximum number of `fn` calls that Mongoose will run in parallel
* @param {AbortSignal} [options.signal] allow cancelling this eachAsync(). Once the abort signal is fired, `eachAsync()` will immediately fulfill the returned promise (or call the callback) and not fetch any more documents.
* @param {Function} [callback] executed when all docs have been processed
* @return {Promise}
* @api public
* @method eachAsync
*/

module.exports = function eachAsync(next, fn, options, callback) {
module.exports = async function eachAsync(next, fn, options) {
const parallel = options.parallel || 1;
const batchSize = options.batchSize;
const signal = options.signal;
Expand All @@ -35,15 +33,15 @@ module.exports = function eachAsync(next, fn, options, callback) {

let aborted = false;

return promiseOrCallback(callback, cb => {
return new Promise((resolve, reject) => {
if (signal != null) {
if (signal.aborted) {
return cb(null);
return resolve(null);
}

signal.addEventListener('abort', () => {
aborted = true;
return cb(null);
return resolve(null);
}, { once: true });
}

Expand All @@ -57,7 +55,12 @@ module.exports = function eachAsync(next, fn, options, callback) {
}
}

iterate(cb);
iterate((err, res) => {
if (err != null) {
return reject(err);
}
resolve(res);
});
});

function iterate(finalCallback) {
Expand Down
24 changes: 12 additions & 12 deletions lib/helpers/model/castBulkWrite.js
Expand Up @@ -37,12 +37,10 @@ module.exports = function castBulkWrite(originalModel, op, options) {
return;
}

op['insertOne']['document'].$validate({ __noPromise: true }, function(error) {
if (error) {
return callback(error, null);
}
callback(null);
});
op['insertOne']['document'].$validate().then(
() => { callback(null); },
err => { callback(err, null); }
);
};
} else if (op['updateOne']) {
return (callback) => {
Expand Down Expand Up @@ -170,13 +168,15 @@ module.exports = function castBulkWrite(originalModel, op, options) {
return;
}

op['replaceOne']['replacement'].$validate({ __noPromise: true }, function(error) {
if (error) {
return callback(error, null);
op['replaceOne']['replacement'].$validate().then(
() => {
op['replaceOne']['replacement'] = op['replaceOne']['replacement'].toBSON();
callback(null);
},
error => {
callback(error, null);
}
op['replaceOne']['replacement'] = op['replaceOne']['replacement'].toBSON();
callback(null);
});
);
};
} else if (op['deleteOne']) {
return (callback) => {
Expand Down
18 changes: 8 additions & 10 deletions lib/helpers/query/applyQueryMiddleware.js
Expand Up @@ -25,23 +25,21 @@ applyQueryMiddleware.middlewareFunctions = validOps.concat([
*/

function applyQueryMiddleware(Query, model) {
const kareemOptions = {
useErrorHandlers: true,
numCallbackParams: 1,
nullResultByDefault: true
};

const middleware = model.hooks.filter(hook => {
const queryMiddleware = model.schema.s.hooks.filter(hook => {
const contexts = _getContexts(hook);
if (hook.name === 'validate') {
return !!contexts.query;
}
if (hook.name === 'deleteOne' || hook.name === 'updateOne') {
return !!contexts.query || Object.keys(contexts).length === 0;
}
if (hook.query != null || hook.document != null) {
return !!hook.query;
}
return true;
});

// `validate()` doesn't have a thunk because it doesn't execute a query.
Query.prototype.validate = middleware.createWrapper('validate',
Query.prototype.validate, null, kareemOptions);
Query.prototype._queryMiddleware = queryMiddleware;
}

function _getContexts(hook) {
Expand Down
9 changes: 0 additions & 9 deletions lib/index.js
Expand Up @@ -21,7 +21,6 @@ const Model = require('./model');
const applyPlugins = require('./helpers/schema/applyPlugins');
const builtinPlugins = require('./plugins');
const driver = require('./driver');
const promiseOrCallback = require('./helpers/promiseOrCallback');
const legacyPluralize = require('./helpers/pluralize');
const utils = require('./utils');
const pkg = require('../package.json');
Expand Down Expand Up @@ -1229,14 +1228,6 @@ Mongoose.prototype.sanitizeFilter = sanitizeFilter;

Mongoose.prototype.trusted = trusted;

/*!
* ignore
*/

Mongoose.prototype._promiseOrCallback = function(callback, fn, ee) {
return promiseOrCallback(callback, fn, ee, this.Promise);
};

/**
* Use this function in `pre()` middleware to skip calling the wrapped function.
*
Expand Down

0 comments on commit b911bef

Please sign in to comment.