From ca1f6833e87214a446f12e74b8a3ea1510e109f6 Mon Sep 17 00:00:00 2001 From: Simon Schick Date: Thu, 14 Nov 2019 16:17:21 +0400 Subject: [PATCH 1/5] Fixed code formatting according to eslint configuration --- .eslintrc.json | 1 - collection-hooks.js | 50 +++++++++++++++++------------------- insert.js | 13 +++++----- remove.js | 16 ++++++------ server.js | 2 +- tests/find_findone_userid.js | 4 +-- tests/find_users.js | 18 ++++++------- tests/server/fetch.js | 7 ++--- tests/transform.js | 20 +++++++-------- tests/update_both.js | 2 +- tests/update_local.js | 2 +- update.js | 19 +++++++------- upsert.js | 26 +++++++++---------- 13 files changed, 89 insertions(+), 91 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index c206ebf..2f4b422 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -6,7 +6,6 @@ "standard" ], "parserOptions": { - "ecmaVersion": 6, "sourceType": "module", "ecmaFeatures": { "modules": true diff --git a/collection-hooks.js b/collection-hooks.js index 7aaf36b..49d0e27 100644 --- a/collection-hooks.js +++ b/collection-hooks.js @@ -1,10 +1,8 @@ -import { Meteor } from 'meteor/meteor'; -import { Mongo } from 'meteor/mongo'; -import { EJSON } from 'meteor/ejson'; -import { LocalCollection } from 'meteor/minimongo'; - -/* global Package Meteor Mongo LocalCollection CollectionHooks _ EJSON */ -/* eslint-disable no-proto, no-native-reassign, no-global-assign */ +import { Meteor } from 'meteor/meteor' +import { Mongo } from 'meteor/mongo' +import { EJSON } from 'meteor/ejson' +import { Tracker } from 'meteor/tracker' +import { LocalCollection } from 'meteor/minimongo' // Relevant AOP terminology: // Aspect: User code that runs before/after (hook) @@ -19,15 +17,15 @@ export const CollectionHooks = { all: { insert: {}, update: {}, remove: {}, find: {}, findOne: {}, all: {} } }, directEnv: new Meteor.EnvironmentVariable(), - directOp(func) { + directOp (func) { return this.directEnv.withValue(true, func) }, - hookedOp(func) { + hookedOp (func) { return this.directEnv.withValue(false, func) } } -CollectionHooks.getUserId = function getUserId() { +CollectionHooks.getUserId = function getUserId () { let userId if (Meteor.isClient) { @@ -56,7 +54,7 @@ CollectionHooks.getUserId = function getUserId() { return userId } -CollectionHooks.extendCollectionInstance = function extendCollectionInstance(self, constructor) { +CollectionHooks.extendCollectionInstance = function extendCollectionInstance (self, constructor) { // Offer a public API to allow the user to define aspects // Example: collection.before.insert(func); ['before', 'after'].forEach(function (pointcut) { @@ -74,13 +72,13 @@ CollectionHooks.extendCollectionInstance = function extendCollectionInstance(sel }) return { - replace(aspect, options) { + replace (aspect, options) { self._hookAspects[method][pointcut].splice(len - 1, 1, { aspect: aspect, options: CollectionHooks.initOptions(options, pointcut, method) }) }, - remove() { + remove () { self._hookAspects[method][pointcut].splice(len - 1, 1) } } @@ -134,8 +132,8 @@ CollectionHooks.extendCollectionInstance = function extendCollectionInstance(sel function (doc) { return ( typeof self._transform === 'function' - ? function (d) { return self._transform(d || doc) } - : function (d) { return d || doc } + ? function (d) { return self._transform(d || doc) } + : function (d) { return d || doc } ) }, args, @@ -149,16 +147,16 @@ CollectionHooks.defineAdvice = (method, advice) => { advices[method] = advice } -CollectionHooks.getAdvice = method => advices[method]; +CollectionHooks.getAdvice = method => advices[method] CollectionHooks.initOptions = (options, pointcut, method) => - CollectionHooks.extendOptions(CollectionHooks.defaults, options, pointcut, method); + CollectionHooks.extendOptions(CollectionHooks.defaults, options, pointcut, method) CollectionHooks.extendOptions = (source, options, pointcut, method) => - ({...options, ...source.all.all, ...source[pointcut].all, ...source.all[method], ...source[pointcut][method]}); + ({ ...options, ...source.all.all, ...source[pointcut].all, ...source.all[method], ...source[pointcut][method] }) CollectionHooks.getDocs = function getDocs (collection, selector, options) { - const findOptions = {transform: null, reactive: false} // added reactive: false + const findOptions = { transform: null, reactive: false } // added reactive: false /* // No "fetch" support at this time. @@ -181,7 +179,7 @@ CollectionHooks.getDocs = function getDocs (collection, selector, options) { findOptions.limit = 1 } const { multi, upsert, ...rest } = options - Object.assign(findOptions, rest); + Object.assign(findOptions, rest) } // Unlike validators, we iterate over multiple docs, so use @@ -204,7 +202,7 @@ CollectionHooks.normalizeSelector = function (selector) { // ~/.meteor/packages/mongo-livedata/collection.js // It's contained in these utility functions to make updates easier for us in // case this code changes. -CollectionHooks.getFields = function getFields(mutator) { +CollectionHooks.getFields = function getFields (mutator) { // compute modified fields const fields = [] // ====ADDED START======================= @@ -259,12 +257,12 @@ CollectionHooks.reassignPrototype = function reassignPrototype (instance, constr // Note: Assigning a prototype dynamically has performance implications if (hasSetPrototypeOf) { Object.setPrototypeOf(instance, constr.prototype) - } else if (instance.__proto__) { - instance.__proto__ = constr.prototype + } else if (instance.__proto__) { // eslint-disable-line no-proto + instance.__proto__ = constr.prototype // eslint-disable-line no-proto } } -CollectionHooks.wrapCollection = function wrapCollection(ns, as) { +CollectionHooks.wrapCollection = function wrapCollection (ns, as) { if (!as._CollectionConstructor) as._CollectionConstructor = as.Collection if (!as._CollectionPrototype) as._CollectionPrototype = new as.Collection(null) @@ -282,7 +280,7 @@ CollectionHooks.wrapCollection = function wrapCollection(ns, as) { ns.Collection.prototype = proto ns.Collection.prototype.constructor = ns.Collection - for (let prop of Object.keys(constructor)) { + for (const prop of Object.keys(constructor)) { ns.Collection[prop] = constructor[prop] } @@ -302,6 +300,6 @@ if (typeof Mongo !== 'undefined') { // Make the above available for packages with hooks that want to determine // whether they are running inside a publish function or not. -CollectionHooks.isWithinPublish = function isWithinPublish() { +CollectionHooks.isWithinPublish = function isWithinPublish () { return publishUserId.get() !== undefined } diff --git a/insert.js b/insert.js index 1105579..9be0107 100644 --- a/insert.js +++ b/insert.js @@ -1,9 +1,10 @@ -import { EJSON } from 'meteor/ejson'; -import { CollectionHooks } from './collection-hooks'; +import { EJSON } from 'meteor/ejson' +import { Mongo } from 'meteor/mongo' +import { CollectionHooks } from './collection-hooks' CollectionHooks.defineAdvice('insert', function (userId, _super, instance, aspects, getTransform, args, suppressAspects) { - const ctx = {context: this, _super, args} - let [doc, callback] = args; + const ctx = { context: this, _super, args } + let [doc, callback] = args const async = typeof callback === 'function' let abort let ret @@ -12,7 +13,7 @@ CollectionHooks.defineAdvice('insert', function (userId, _super, instance, aspec if (!suppressAspects) { try { aspects.before.forEach((o) => { - const r = o.aspect.call({transform: getTransform(doc), ...ctx}, userId, doc) + const r = o.aspect.call({ transform: getTransform(doc), ...ctx }, userId, doc) if (r === false) abort = true }) @@ -39,7 +40,7 @@ CollectionHooks.defineAdvice('insert', function (userId, _super, instance, aspec doc._id = id } if (!suppressAspects) { - const lctx = {transform: getTransform(doc), _id: id, err, ...ctx} + const lctx = { transform: getTransform(doc), _id: id, err, ...ctx } aspects.after.forEach((o) => { o.aspect.call(lctx, userId, doc) }) diff --git a/remove.js b/remove.js index fcdb9a9..663b21f 100644 --- a/remove.js +++ b/remove.js @@ -1,15 +1,15 @@ -import { EJSON } from 'meteor/ejson'; -import { CollectionHooks } from './collection-hooks'; +import { EJSON } from 'meteor/ejson' +import { CollectionHooks } from './collection-hooks' -const isEmpty = a => !Array.isArray(a) || !a.length; +const isEmpty = a => !Array.isArray(a) || !a.length CollectionHooks.defineAdvice('remove', function (userId, _super, instance, aspects, getTransform, args, suppressAspects) { - const ctx = {context: this, _super, args}; - const [ selector, callback ] = args; + const ctx = { context: this, _super, args } + const [selector, callback] = args const async = typeof callback === 'function' let docs let abort - let prev = [] + const prev = [] if (!suppressAspects) { try { @@ -25,7 +25,7 @@ CollectionHooks.defineAdvice('remove', function (userId, _super, instance, aspec // before aspects.before.forEach((o) => { docs.forEach((doc) => { - const r = o.aspect.call({transform: getTransform(doc), ...ctx}, userId, doc) + const r = o.aspect.call({ transform: getTransform(doc), ...ctx }, userId, doc) if (r === false) abort = true }) }) @@ -41,7 +41,7 @@ CollectionHooks.defineAdvice('remove', function (userId, _super, instance, aspec if (!suppressAspects) { aspects.after.forEach((o) => { prev.forEach((doc) => { - o.aspect.call({transform: getTransform(doc), err, ...ctx}, userId, doc) + o.aspect.call({ transform: getTransform(doc), err, ...ctx }, userId, doc) }) }) } diff --git a/server.js b/server.js index 7327bec..7cd6ff8 100644 --- a/server.js +++ b/server.js @@ -36,7 +36,7 @@ Meteor.publish = function (name, handler, options) { // Make the above available for packages with hooks that want to determine // whether they are running inside a publish function or not. -CollectionHooks.isWithinPublish = () => publishUserId.get() !== void 0 +CollectionHooks.isWithinPublish = () => publishUserId.get() !== undefined export { CollectionHooks diff --git a/tests/find_findone_userid.js b/tests/find_findone_userid.js index 6a9908e..19bb5e6 100644 --- a/tests/find_findone_userid.js +++ b/tests/find_findone_userid.js @@ -117,14 +117,14 @@ if (Meteor.isServer) { } if (Meteor.isClient) { - function cleanup () { + const cleanup = () => { beforeFindUserId = null afterFindUserId = null beforeFindOneUserId = null afterFindOneUserId = null } - function withLogin (testFunc) { + const withLogin = (testFunc) => { return function (...args) { const wrapper = (cb) => { InsecureLogin.ready(() => { diff --git a/tests/find_users.js b/tests/find_users.js index 508e27e..7875cb8 100644 --- a/tests/find_users.js +++ b/tests/find_users.js @@ -1,6 +1,6 @@ -import { Meteor } from 'meteor/meteor'; -import { Tinytest } from 'meteor/tinytest'; -import { InsecureLogin } from './insecure_login'; +import { Meteor } from 'meteor/meteor' +import { Tinytest } from 'meteor/tinytest' +import { InsecureLogin } from './insecure_login' Tinytest.addAsync('users - find hooks should be capable of being used on special Meteor.users collection', function (test, next) { const aspect1 = Meteor.users.before.find(function (userId, selector, options) { @@ -16,10 +16,10 @@ Tinytest.addAsync('users - find hooks should be capable of being used on special }) InsecureLogin.ready(function () { - const selector = {test: 1} + const selector = { test: 1 } Meteor.users.find(selector) - test.equal(selector.hasOwnProperty('a'), true) - test.equal(selector.hasOwnProperty('b'), true) + test.equal(Object.prototype.hasOwnProperty.call(selector, 'a'), true) + test.equal(Object.prototype.hasOwnProperty.call(selector, 'b'), true) aspect1.remove() aspect2.remove() @@ -34,7 +34,7 @@ Tinytest.addAsync('users - find hooks should be capable of being used on wrapped return Object.assign(this, doc) } - Meteor.users.__transform = doc => new TestUser(doc); + Meteor.users.__transform = doc => new TestUser(doc) const MeteorUsersFind = Meteor.users.find @@ -57,8 +57,8 @@ Tinytest.addAsync('users - find hooks should be capable of being used on wrapped InsecureLogin.ready(function () { const selector = { test: 1 } Meteor.users.find(selector) - test.equal(selector.hasOwnProperty('a'), true) - test.equal(selector.hasOwnProperty('b'), true) + test.equal(Object.prototype.hasOwnProperty.call(selector, 'a'), true) + test.equal(Object.prototype.hasOwnProperty.call(selector, 'b'), true) aspect1.remove() aspect2.remove() diff --git a/tests/server/fetch.js b/tests/server/fetch.js index 0dba949..6e1ab52 100644 --- a/tests/server/fetch.js +++ b/tests/server/fetch.js @@ -1,5 +1,6 @@ -import { Mongo } from 'meteor/mongo'; -import { Tinytest } from 'meteor/tinytest'; +import { Mongo } from 'meteor/mongo' +import { Tinytest } from 'meteor/tinytest' +import { InsecureLogin } from '../insecure_login' Tinytest.addAsync('general - local collection documents should only have fetched fields', function (test, next) { const collection = new Mongo.Collection(null) @@ -12,7 +13,7 @@ Tinytest.addAsync('general - local collection documents should only have fetched const fields = ['fetch_value1', 'fetch_value2'] collection.after.update(function (userId, doc, fieldNames, modifier) { - let { _id, ...docKeys } = Object.keys(doc); + const { _id, ...docKeys } = Object.keys(doc) test.equal(same(docKeys, fields), true) next() }, { diff --git a/tests/transform.js b/tests/transform.js index 6c59532..9e7f5de 100644 --- a/tests/transform.js +++ b/tests/transform.js @@ -1,8 +1,8 @@ -import { Mongo } from 'meteor/mongo'; -import { Tinytest } from 'meteor/tinytest'; -import { InsecureLogin } from './insecure_login'; +import { Mongo } from 'meteor/mongo' +import { Tinytest } from 'meteor/tinytest' +import { InsecureLogin } from './insecure_login' -const isFunction = (fn) => typeof fn === 'function'; +const isFunction = (fn) => typeof fn === 'function' Tinytest.addAsync('general - hook callbacks should have this.transform function that works', function (test, next) { const collection = new Mongo.Collection(null, { @@ -10,9 +10,9 @@ Tinytest.addAsync('general - hook callbacks should have this.transform function }) collection.allow({ - insert() { return true }, - update() { return true }, - remove() { return true } + insert () { return true }, + update () { return true }, + remove () { return true } }) const counts = { @@ -41,11 +41,11 @@ Tinytest.addAsync('general - hook callbacks should have this.transform function // to pass? Probably not. Think more on this -- it could be that we simply // shouldn't be running a .transform() in a before.insert -- how will we // know the _id? And that's what transform is complaining about. - collection.insert({_id: '1', start_value: true}, function (err, id) { + collection.insert({ _id: '1', start_value: true }, function (err, id) { if (err) throw err - collection.update({_id: id}, {$set: {update_value: true}}, function (err) { + collection.update({ _id: id }, { $set: { update_value: true } }, function (err) { if (err) throw err - collection.remove({_id: id}, function (nil) { + collection.remove({ _id: id }, function (nil) { test.equal(counts.before.insert, 1, 'before insert should have 1 count') test.equal(counts.before.update, 1, 'before update should have 1 count') test.equal(counts.before.remove, 1, 'before remove should have 1 count') diff --git a/tests/update_both.js b/tests/update_both.js index d38afb1..c5fe929 100644 --- a/tests/update_both.js +++ b/tests/update_both.js @@ -81,7 +81,7 @@ if (Meteor.isClient) { collection2.after.update(function (userId, doc, fieldNames, modifier) { test.equal(doc.update_value, true) - test.equal(this.previous.hasOwnProperty('update_value'), false) + test.equal(Object.prototype.hasOwnProperty.call(this.previous, 'update_value'), false) n() }) diff --git a/tests/update_local.js b/tests/update_local.js index ad214c5..3b26d00 100644 --- a/tests/update_local.js +++ b/tests/update_local.js @@ -60,7 +60,7 @@ Tinytest.addAsync('update - local collection should fire after-update hook', fun test.equal(fieldNames[0], 'update_value') test.equal(doc.update_value, true) - test.equal((this.previous || {}).hasOwnProperty('update_value'), false) + test.equal(Object.prototype.hasOwnProperty.call(this.previous, 'update_value'), false) n() }) diff --git a/update.js b/update.js index 9c91cb6..1953fb0 100644 --- a/update.js +++ b/update.js @@ -1,15 +1,14 @@ -import { EJSON } from 'meteor/ejson'; -import { CollectionHooks } from './collection-hooks'; +import { EJSON } from 'meteor/ejson' +import { CollectionHooks } from './collection-hooks' -const isEmpty = a => !Array.isArray(a) || !a.length; +const isEmpty = a => !Array.isArray(a) || !a.length CollectionHooks.defineAdvice('update', function (userId, _super, instance, aspects, getTransform, args, suppressAspects) { - - const ctx = {context: this, _super, args} - let [selector, mutator, options, callback] = args; + const ctx = { context: this, _super, args } + let [selector, mutator, options, callback] = args if (typeof options === 'function') { - callback = options; - options = {}; + callback = options + options = {} } const async = typeof callback === 'function' let docs @@ -44,7 +43,7 @@ CollectionHooks.defineAdvice('update', function (userId, _super, instance, aspec // before aspects.before.forEach(function (o) { docs.forEach(function (doc) { - const r = o.aspect.call({transform: getTransform(doc), ...ctx}, userId, doc, fields, mutator, options) + const r = o.aspect.call({ transform: getTransform(doc), ...ctx }, userId, doc, fields, mutator, options) if (r === false) abort = true }) }) @@ -59,7 +58,7 @@ CollectionHooks.defineAdvice('update', function (userId, _super, instance, aspec const after = (affected, err) => { if (!suppressAspects && !isEmpty(aspects.after)) { const fields = CollectionHooks.getFields(mutator) - const docs = CollectionHooks.getDocs.call(this, instance, {_id: {$in: docIds}}, options).fetch() + const docs = CollectionHooks.getDocs.call(this, instance, { _id: { $in: docIds } }, options).fetch() aspects.after.forEach((o) => { docs.forEach((doc) => { diff --git a/upsert.js b/upsert.js index c5b0f50..d003c9d 100644 --- a/upsert.js +++ b/upsert.js @@ -1,7 +1,7 @@ -import { EJSON } from 'meteor/ejson'; -import { CollectionHooks } from './collection-hooks'; +import { EJSON } from 'meteor/ejson' +import { CollectionHooks } from './collection-hooks' -const isEmpty = a => !Array.isArray(a) || !a.length; +const isEmpty = a => !Array.isArray(a) || !a.length CollectionHooks.defineAdvice('upsert', function (userId, _super, instance, aspectGroup, getTransform, args, suppressAspects) { // args[0] : selector @@ -9,13 +9,13 @@ CollectionHooks.defineAdvice('upsert', function (userId, _super, instance, aspec // args[2] : options (optional) // args[3] : callback - args[0] = CollectionHooks.normalizeSelector(instance._getFindSelector(args)); + args[0] = CollectionHooks.normalizeSelector(instance._getFindSelector(args)) - const ctx = {context: this, _super, args} - let [selector, mutator, options, callback] = args; + const ctx = { context: this, _super, args } + let [selector, mutator, options, callback] = args if (typeof options === 'function') { - callback = options; - options = {}; + callback = options + options = {} } const async = typeof callback === 'function' @@ -56,7 +56,7 @@ CollectionHooks.defineAdvice('upsert', function (userId, _super, instance, aspec const afterUpdate = (affected, err) => { if (!suppressAspects && !isEmpty(aspectGroup.update.after)) { const fields = CollectionHooks.getFields(selector) - const docs = CollectionHooks.getDocs.call(this, instance, {_id: {$in: docIds}}, options).fetch() + const docs = CollectionHooks.getDocs.call(this, instance, { _id: { $in: docIds } }, options).fetch() aspectGroup.update.after.forEach((o) => { docs.forEach((doc) => { @@ -74,8 +74,8 @@ CollectionHooks.defineAdvice('upsert', function (userId, _super, instance, aspec const afterInsert = (_id, err) => { if (!suppressAspects && !isEmpty(aspectGroup.insert.after)) { - const doc = CollectionHooks.getDocs.call(this, instance, {_id}, selector, {}).fetch()[0] // 3rd argument passes empty object which causes magic logic to imply limit:1 - const lctx = {transform: getTransform(doc), _id, err, ...ctx} + const doc = CollectionHooks.getDocs.call(this, instance, { _id }, selector, {}).fetch()[0] // 3rd argument passes empty object which causes magic logic to imply limit:1 + const lctx = { transform: getTransform(doc), _id, err, ...ctx } aspectGroup.insert.after.forEach((o) => { o.aspect.call(lctx, userId, doc) @@ -97,9 +97,9 @@ CollectionHooks.defineAdvice('upsert', function (userId, _super, instance, aspec }) } - return CollectionHooks.directOp(() => _super.call(this, selector, mutator, options,wrappedCallback)); + return CollectionHooks.directOp(() => _super.call(this, selector, mutator, options, wrappedCallback)) } else { - const ret = CollectionHooks.directOp(() => _super.call(this, selector, mutator, options, callback)); + const ret = CollectionHooks.directOp(() => _super.call(this, selector, mutator, options, callback)) if (ret && ret.insertedId) { afterInsert(ret.insertedId) From 63292cd900072bbd9e048d270f0cbd19def10f42 Mon Sep 17 00:00:00 2001 From: Simon Schick Date: Thu, 14 Nov 2019 16:26:31 +0400 Subject: [PATCH 2/5] Some other cleanup ... --- collection-hooks.js | 38 +------------------------------------- findone.js | 3 --- upsert.js | 5 ----- 3 files changed, 1 insertion(+), 45 deletions(-) diff --git a/collection-hooks.js b/collection-hooks.js index 49d0e27..c8c5a50 100644 --- a/collection-hooks.js +++ b/collection-hooks.js @@ -1,7 +1,6 @@ import { Meteor } from 'meteor/meteor' import { Mongo } from 'meteor/mongo' import { EJSON } from 'meteor/ejson' -import { Tracker } from 'meteor/tracker' import { LocalCollection } from 'meteor/minimongo' // Relevant AOP terminology: @@ -25,35 +24,6 @@ export const CollectionHooks = { } } -CollectionHooks.getUserId = function getUserId () { - let userId - - if (Meteor.isClient) { - Tracker.nonreactive(function () { - userId = Meteor.userId && Meteor.userId() - }) - } - - if (Meteor.isServer) { - try { - // Will throw an error unless within method call. - // Attempt to recover gracefully by catching: - userId = Meteor.userId && Meteor.userId() - } catch (e) { } - - if (userId == null) { - // Get the userId if we are in a publish function. - userId = publishUserId.get() - } - } - - if (userId == null) { - userId = CollectionHooks.defaultUserId - } - - return userId -} - CollectionHooks.extendCollectionInstance = function extendCollectionInstance (self, constructor) { // Offer a public API to allow the user to define aspects // Example: collection.before.insert(func); @@ -74,7 +44,7 @@ CollectionHooks.extendCollectionInstance = function extendCollectionInstance (se return { replace (aspect, options) { self._hookAspects[method][pointcut].splice(len - 1, 1, { - aspect: aspect, + aspect, options: CollectionHooks.initOptions(options, pointcut, method) }) }, @@ -297,9 +267,3 @@ if (typeof Mongo !== 'undefined') { } else { CollectionHooks.wrapCollection(Meteor, Meteor) } - -// Make the above available for packages with hooks that want to determine -// whether they are running inside a publish function or not. -CollectionHooks.isWithinPublish = function isWithinPublish () { - return publishUserId.get() !== undefined -} diff --git a/findone.js b/findone.js index 3e2d292..310213d 100644 --- a/findone.js +++ b/findone.js @@ -1,9 +1,6 @@ import { CollectionHooks } from './collection-hooks' CollectionHooks.defineAdvice('findOne', function (userId, _super, instance, aspects, getTransform, args, suppressAspects) { - // args[0] : selector - // args[1] : options - const ctx = { context: this, _super, args } const selector = CollectionHooks.normalizeSelector(instance._getFindSelector(args)) const options = instance._getFindOptions(args) diff --git a/upsert.js b/upsert.js index d003c9d..3319a3b 100644 --- a/upsert.js +++ b/upsert.js @@ -4,11 +4,6 @@ import { CollectionHooks } from './collection-hooks' const isEmpty = a => !Array.isArray(a) || !a.length CollectionHooks.defineAdvice('upsert', function (userId, _super, instance, aspectGroup, getTransform, args, suppressAspects) { - // args[0] : selector - // args[1] : mutator - // args[2] : options (optional) - // args[3] : callback - args[0] = CollectionHooks.normalizeSelector(instance._getFindSelector(args)) const ctx = { context: this, _super, args } From 3ab52a38dbcd943116f8d4cddd1dd8441e9c465c Mon Sep 17 00:00:00 2001 From: Simon Schick Date: Thu, 14 Nov 2019 16:58:00 +0400 Subject: [PATCH 3/5] If no `upsert.before` hook is defined, `update.after` will not contain the original documents --- tests/upsert.js | 15 +++++++++++++++ upsert.js | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/tests/upsert.js b/tests/upsert.js index ad10ae4..0047540 100644 --- a/tests/upsert.js +++ b/tests/upsert.js @@ -95,6 +95,21 @@ if (Meteor.isServer) { }) } +Tinytest.addAsync('upsert after.update should have a correct prev-doc', function (test, next) { + const collection = new Mongo.Collection(null) + + collection.after.update(function (userId, doc) { + test.isNotUndefined(this.previous, 'this.previous should not be undefined') + test.equal(this.previous.step, 'inserted', 'previous doc should have a step property equal to inserted') + test.equal(doc.step, 'updated', 'doc should have a step property equal to updated') + next() + }) + + collection.remove({ test: true }) + collection.insert({ test: true, step: 'inserted' }) + collection.upsert({ test: true }, { $set: { test: true, step: 'updated' } }) +}) + Tinytest.addAsync('issue #156 - upsert after.insert should have a correct doc using $set', function (test, next) { const collection = new Mongo.Collection(null) diff --git a/upsert.js b/upsert.js index 3319a3b..19c2255 100644 --- a/upsert.js +++ b/upsert.js @@ -20,7 +20,7 @@ CollectionHooks.defineAdvice('upsert', function (userId, _super, instance, aspec const prev = {} if (!suppressAspects) { - if (!isEmpty(aspectGroup.upsert.before)) { + if (!isEmpty(aspectGroup.upsert.before) || !isEmpty(aspectGroup.update.after)) { docs = CollectionHooks.getDocs.call(this, instance, selector, options).fetch() docIds = docs.map(doc => doc._id) } From c79a7c82d0bd7c5a7cb5cfb930d2f89f467ba492 Mon Sep 17 00:00:00 2001 From: Simon Schick Date: Thu, 14 Nov 2019 16:59:00 +0400 Subject: [PATCH 4/5] Returning `false` in `upsert.before` hook throws an error --- tests/upsert.js | 12 ++++++++++++ upsert.js | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/tests/upsert.js b/tests/upsert.js index 0047540..b7d268c 100644 --- a/tests/upsert.js +++ b/tests/upsert.js @@ -95,6 +95,18 @@ if (Meteor.isServer) { }) } +Tinytest.addAsync('upsert before.upsert can stop the execution', function (test, next) { + const collection = new Mongo.Collection(null) + + collection.before.upsert(() => false) + + collection.remove({ test: true }) + collection.upsert({ test: true }, { $set: { test: true } }) + + test.isUndefined(collection.findOne({ test: true }), 'doc should not exist') + next() +}) + Tinytest.addAsync('upsert after.update should have a correct prev-doc', function (test, next) { const collection = new Mongo.Collection(null) diff --git a/upsert.js b/upsert.js index 19c2255..9f64230 100644 --- a/upsert.js +++ b/upsert.js @@ -42,7 +42,7 @@ CollectionHooks.defineAdvice('upsert', function (userId, _super, instance, aspec // before aspectGroup.upsert.before.forEach((o) => { const r = o.aspect.call(ctx, userId, selector, mutator, options) - if (r === false) abortMongo.Collection = true + if (r === false) abort = true }) if (abort) return { numberAffected: 0 } From 22de33c4bb9622b248c90d99947d5e211b3e682a Mon Sep 17 00:00:00 2001 From: Simon Schick Date: Thu, 14 Nov 2019 17:00:21 +0400 Subject: [PATCH 5/5] On upsert, the hook `after.update` doesn't return the manipulated fields but the selectors fields. --- tests/upsert.js | 13 +++++++++++++ upsert.js | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/tests/upsert.js b/tests/upsert.js index b7d268c..90635d5 100644 --- a/tests/upsert.js +++ b/tests/upsert.js @@ -122,6 +122,19 @@ Tinytest.addAsync('upsert after.update should have a correct prev-doc', function collection.upsert({ test: true }, { $set: { test: true, step: 'updated' } }) }) +Tinytest.addAsync('upsert after.update should have the list of manipulated fields', function (test, next) { + const collection = new Mongo.Collection(null) + + collection.after.update(function (userId, doc, fields) { + test.equal(fields, ['step']) + next() + }) + + collection.remove({ test: true }) + collection.insert({ test: true, step: 'inserted' }) + collection.upsert({ test: true }, { $set: { step: 'updated' } }) +}) + Tinytest.addAsync('issue #156 - upsert after.insert should have a correct doc using $set', function (test, next) { const collection = new Mongo.Collection(null) diff --git a/upsert.js b/upsert.js index 9f64230..1c7c031 100644 --- a/upsert.js +++ b/upsert.js @@ -50,7 +50,7 @@ CollectionHooks.defineAdvice('upsert', function (userId, _super, instance, aspec const afterUpdate = (affected, err) => { if (!suppressAspects && !isEmpty(aspectGroup.update.after)) { - const fields = CollectionHooks.getFields(selector) + const fields = CollectionHooks.getFields(mutator) const docs = CollectionHooks.getDocs.call(this, instance, { _id: { $in: docIds } }, options).fetch() aspectGroup.update.after.forEach((o) => {