From 4aaa6eedfc144bd4c913f4d11306159d55c84bbf Mon Sep 17 00:00:00 2001 From: Berislav Date: Sat, 16 Nov 2019 13:39:36 +0000 Subject: [PATCH 1/2] updateOptions parameter instead of bypassSchema --- .npm/package/npm-shrinkwrap.json | 7 +- README.md | 24 +- cache.js | 63 +++--- cacheCount.js | 8 +- cacheField.js | 14 +- package.js | 8 +- testing/.gitignore | 1 + testing/.meteor/.finished-upgraders | 18 ++ testing/.meteor/.gitignore | 1 + testing/.meteor/.id | 7 + testing/.meteor/packages | 19 ++ testing/.meteor/platforms | 2 + testing/.meteor/release | 1 + testing/.meteor/versions | 71 ++++++ testing/package-lock.json | 336 ++++++++++++++++++++++++++++ testing/package.json | 16 ++ tests.js | 109 ++++++++- 17 files changed, 645 insertions(+), 60 deletions(-) create mode 100644 testing/.gitignore create mode 100644 testing/.meteor/.finished-upgraders create mode 100644 testing/.meteor/.gitignore create mode 100644 testing/.meteor/.id create mode 100644 testing/.meteor/packages create mode 100644 testing/.meteor/platforms create mode 100644 testing/.meteor/release create mode 100644 testing/.meteor/versions create mode 100644 testing/package-lock.json create mode 100644 testing/package.json diff --git a/.npm/package/npm-shrinkwrap.json b/.npm/package/npm-shrinkwrap.json index 7768286..7662124 100644 --- a/.npm/package/npm-shrinkwrap.json +++ b/.npm/package/npm-shrinkwrap.json @@ -1,9 +1,10 @@ { + "lockfileVersion": 1, "dependencies": { "lodash": { - "version": "4.17.4", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", - "from": "lodash@4.17.4" + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" } } } diff --git a/README.md b/README.md index cb7a493..27e5ac9 100644 --- a/README.md +++ b/README.md @@ -70,9 +70,9 @@ Posts.cache({ The field on the parent where children are cached. Can be a nested field, like 'caches.field', but it can not be in the same top level field as the referenceField. For type:'one', cacheField will store a single child. For all others, it will store an array of children. - bypassSchema - Boolean (optional) - If set to true, it will bypass any collection2 schema that may exist. Otherwise you must add the cacheField to your schema. + updateOptions + Object (optional) + Options that will be passed to Collection.update method, for example: Collection.update(selector, updateExpression, options). Can be used to bypass collection2 by passing {bypassCollection2: true}. Otherwise you must add the cacheField to your schema (if you are using collection2). @@ -121,9 +121,9 @@ cacheCount() can be used on "inverse" and "many-inverse" relationships Can be used to filter the counted documents. [referenceField]:parent._id will always be included though. - bypassSchema - Boolean (optional) - If set to true, it will bypass any collection2 schema that may exist. Otherwise you must add the cacheField to your schema. + updateOptions + Object (optional) + Options that will be passed to Collection.update method, for example: Collection.update(selector, updateExpression, options). Can be used to bypass collection2 by passing {bypassCollection2: true}. Otherwise you must add the cacheField to your schema (if you are using collection2). @@ -160,9 +160,9 @@ Meteor.users.cacheField({ The function used to compute the result. If not defined, the default is to return a string of all watched fields concatenated with ', '
The document provided to the function only contains the fields specified in fields - bypassSchema - Boolean (optional) - If set to true, it will bypass any collection2 schema that may exist. Otherwise you must add the cacheField to your schema. + updateOptions + Object (optional) + Options that will be passed to Collection.update method, for example: Collection.update(selector, updateExpression, options). Can be used to bypass collection2 by passing {bypassCollection2: true}. Otherwise you must add the cacheField to your schema (if you are using collection2). @@ -311,8 +311,10 @@ Meteor.setTimeout(()=>{ ## Testing the package ``` -meteor test-packages packages/denormalize --driver-package=practicalmeteor:mocha +cd testing +meteor npm i +meteor npm run test[:watch] ``` (Then open localhost:3000 in your browser)
-The package currently has over 120 tests
+The package currently has over 130 tests
Note: The "slowness warnings" in the results are just due to the asynchronous tests \ No newline at end of file diff --git a/cache.js b/cache.js index 0fbb581..f630478 100644 --- a/cache.js +++ b/cache.js @@ -23,13 +23,12 @@ Mongo.Collection.prototype.cache = function(options){ type:Match.OneOf('one', 'many', 'inversed', 'inverse', 'many-inversed', 'many-inverse'), referenceField:String, cacheField:String, - bypassSchema:Match.Optional(Boolean) + updateOptions:Match.Optional(Object) }) if(options.type == 'inverse') options.type = 'inversed' //Not sure which is best, so why not support both and be typo-friendly if(options.type == 'many-inverse') options.type = 'many-inversed' - //Bypass collection2 schemas - let parentCollection = options.bypassSchema && Package['aldeed:collection2'] ? this._collection : this + let parentCollection = this let childCollection = options.collection let type = options.type let referenceField = options.referenceField @@ -86,7 +85,7 @@ Mongo.Collection.prototype.cache = function(options){ if(_.get(parent, referenceField)){ let child = childCollection.findOne(_.get(parent, referenceField), childOpts) if(child){ - parentCollection.update(parent._id, {$set:{[cacheField]:child}}) + parentCollection.update(parent._id, {$set:{[cacheField]:child}}, options.updateOptions) } } } @@ -97,27 +96,27 @@ Mongo.Collection.prototype.cache = function(options){ if(_.includes(changedFields, referenceField.split('.')[0])){ let child = _.get(parent, referenceField) && childCollection.findOne(_.get(parent, referenceField), childOpts) if(child){ - parentCollection.update(parent._id, {$set:{[cacheField]:child}}) + parentCollection.update(parent._id, {$set:{[cacheField]:child}}, options.updateOptions) } else { - parentCollection.update(parent._id, {$unset:{[cacheField]:1}}) + parentCollection.update(parent._id, {$unset:{[cacheField]:1}}, options.updateOptions) } } }) childCollection.after.insert(function(userId, child){ let pickedChild = _.pick(child, childFields) - parentCollection.update({[referenceField]:child._id}, {$set:{[cacheField]:pickedChild}}, {multi:true}) + parentCollection.update({[referenceField]:child._id}, {$set:{[cacheField]:pickedChild}}, {...options.updateOptions, multi:true}) }) childCollection.after.update(function(userId, child, changedFields){ if(_.intersection(changedFields, topFields).length){ let pickedChild = _.pick(child, childFields) - parentCollection.update({[referenceField]:child._id}, {$set:{[cacheField]:pickedChild}}, {multi:true}) + parentCollection.update({[referenceField]:child._id}, {$set:{[cacheField]:pickedChild}}, {...options.updateOptions, multi:true}) } }) childCollection.after.remove(function(userId, child){ - parentCollection.update({[referenceField]:child._id}, {$unset:{[cacheField]:1}}, {multi:true}) + parentCollection.update({[referenceField]:child._id}, {$unset:{[cacheField]:1}}, {...options.updateOptions, multi:true}) }) } @@ -126,9 +125,9 @@ Mongo.Collection.prototype.cache = function(options){ let references = getNestedReferences(parent) if(references.length){ let children = childCollection.find({_id:{$in:references}}, childOpts).fetch() - parentCollection.update(parent._id, {$set:{[cacheField]:children}}) + parentCollection.update(parent._id, {$set:{[cacheField]:children}}, options.updateOptions) } else { - parentCollection.update(parent._id, {$set:{[cacheField]:[]}}) + parentCollection.update(parent._id, {$set:{[cacheField]:[]}}, options.updateOptions) } } addMigration(parentCollection, insert, options) @@ -139,16 +138,16 @@ Mongo.Collection.prototype.cache = function(options){ let references = getNestedReferences(parent) if(references.length){ let children = childCollection.find({_id:{$in:references}}, childOpts).fetch() - parentCollection.update(parent._id, {$set:{[cacheField]:children}}) + parentCollection.update(parent._id, {$set:{[cacheField]:children}}, options.updateOptions) } else { - parentCollection.update(parent._id, {$set:{[cacheField]:[]}}) + parentCollection.update(parent._id, {$set:{[cacheField]:[]}}, options.updateOptions) } } }) childCollection.after.insert(function(userId, child){ let pickedChild = _.pick(child, childFields) - parentCollection.update({[referencePath]:child._id}, {$push:{[cacheField]:pickedChild}}, {multi:true}) + parentCollection.update({[referencePath]:child._id}, {$push:{[cacheField]:pickedChild}}, {...options.updateOptions, multi:true}) }) childCollection.after.update(function(userId, child, changedFields){ @@ -157,16 +156,16 @@ Mongo.Collection.prototype.cache = function(options){ parentCollection.find({[referencePath]:child._id}, parentOpts).forEach(parent => { let index = _.findIndex(_.get(parent, cacheField), {_id:child._id}) if(index > -1){ - parentCollection.update(parent._id, {$set:{[cacheField + '.' + index]:pickedChild}}) + parentCollection.update(parent._id, {$set:{[cacheField + '.' + index]:pickedChild}}, options.updateOptions) } else { - parentCollection.update(parent._id, {$push:{[cacheField]:pickedChild}}) + parentCollection.update(parent._id, {$push:{[cacheField]:pickedChild}}, options.updateOptions) } }) } }) childCollection.after.remove(function(userId, child){ - parentCollection.update({[referencePath]:child._id}, {$pull:{[cacheField]:{_id:child._id}}}, {multi:true}) + parentCollection.update({[referencePath]:child._id}, {$pull:{[cacheField]:{_id:child._id}}}, {...options.updateOptions, multi:true}) }) } @@ -174,7 +173,7 @@ Mongo.Collection.prototype.cache = function(options){ else if(type == 'inversed'){ let insert = function insert(userId, parent){ let children = childCollection.find({[referenceField]:parent._id}, childOpts).fetch() - parentCollection.update(parent._id, {$set:{[cacheField]:children}}) + parentCollection.update(parent._id, {$set:{[cacheField]:children}}, options.updateOptions) } addMigration(parentCollection, insert, options) @@ -184,9 +183,9 @@ Mongo.Collection.prototype.cache = function(options){ if(_.includes(changedFields, referenceField.split('.')[0])){ if(_.get(parent, referenceField)){ let children = childCollection.find({[referenceField]:parent._id}, childOpts).fetch() - parentCollection.update(parent._id, {$set:{[cacheField]:children}}) + parentCollection.update(parent._id, {$set:{[cacheField]:children}}, options.updateOptions) } else { - parentCollection.update(parent._id, {$set:{[cacheField]:[]}}) + parentCollection.update(parent._id, {$set:{[cacheField]:[]}}, options.updateOptions) } } }) @@ -194,7 +193,7 @@ Mongo.Collection.prototype.cache = function(options){ childCollection.after.insert(function(userId, child){ let pickedChild = _.pick(child, childFields) if(_.get(child, referenceField)){ - parentCollection.update({_id:_.get(child, referenceField)}, {$push:{[cacheField]:pickedChild}}) + parentCollection.update({_id:_.get(child, referenceField)}, {$push:{[cacheField]:pickedChild}}, options.updateOptions) } }) @@ -203,28 +202,28 @@ Mongo.Collection.prototype.cache = function(options){ let pickedChild = _.pick(child, childFields) let previousId = this.previous && _.get(this.previous, referenceField) if(previousId && previousId !== _.get(child, referenceField)){ - parentCollection.update({_id:previousId}, {$pull:{[cacheField]:{_id:child._id}}}) + parentCollection.update({_id:previousId}, {$pull:{[cacheField]:{_id:child._id}}}, options.updateOptions) } parentCollection.find({_id:_.get(child, referenceField)}, parentOpts).forEach(parent => { let index = _.findIndex(_.get(parent, cacheField), {_id:child._id}) if(index > -1){ - parentCollection.update(parent._id, {$set:{[cacheField + '.' + index]:pickedChild}}) + parentCollection.update(parent._id, {$set:{[cacheField + '.' + index]:pickedChild}}, options.updateOptions) } else { - parentCollection.update(parent._id, {$push:{[cacheField]:pickedChild}}) + parentCollection.update(parent._id, {$push:{[cacheField]:pickedChild}}, options.updateOptions) } }) } }) childCollection.after.remove(function(userId, child){ - parentCollection.update({_id:_.get(child, referenceField)}, {$pull:{[cacheField]:{_id:child._id}}}) + parentCollection.update({_id:_.get(child, referenceField)}, {$pull:{[cacheField]:{_id:child._id}}}, options.updateOptions) }) } else if(type == 'many-inversed'){ let insert = function insert(userId, parent){ let children = childCollection.find({[referencePath]:parent._id}, childOpts).fetch() - parentCollection.update(parent._id, {$set:{[cacheField]:children}}) + parentCollection.update(parent._id, {$set:{[cacheField]:children}}, options.updateOptions) } addMigration(parentCollection, insert, options) @@ -233,7 +232,7 @@ Mongo.Collection.prototype.cache = function(options){ parentCollection.after.update(function(userId, parent, changedFields){ if(_.includes(changedFields, referencePath.split('.')[0])){ let children = childCollection.find({[referencePath]:parent._id}, childOpts).fetch() - parentCollection.update(parent._id, {$set:{[cacheField]:children}}) + parentCollection.update(parent._id, {$set:{[cacheField]:children}}, options.updateOptions) } }) @@ -241,7 +240,7 @@ Mongo.Collection.prototype.cache = function(options){ let references = getNestedReferences(child) if(references.length){ let pickedChild = _.pick(child, childFields) - parentCollection.update({_id:{$in:references}}, {$push:{[cacheField]:pickedChild}}, {multi:true}) + parentCollection.update({_id:{$in:references}}, {$push:{[cacheField]:pickedChild}}, {...options.updateOptions,multi:true}) } }) @@ -251,16 +250,16 @@ Mongo.Collection.prototype.cache = function(options){ let previousIds = this.previous && getNestedReferences(this.previous) previousIds = _.difference(previousIds, references) if(previousIds.length){ - parentCollection.update({_id:{$in:previousIds}}, {$pull:{[cacheField]:{_id:child._id}}}, {multi:true}) + parentCollection.update({_id:{$in:previousIds}}, {$pull:{[cacheField]:{_id:child._id}}}, {...options.updateOptions, multi:true}) } if(references.length){ let pickedChild = _.pick(child, childFields) parentCollection.find({_id:{$in:references}}, parentOpts).forEach(parent => { let index = _.findIndex(_.get(parent, cacheField), {_id:child._id}) if(index > -1){ - parentCollection.update(parent._id, {$set:{[cacheField + '.' + index]:pickedChild}}) + parentCollection.update(parent._id, {$set:{[cacheField + '.' + index]:pickedChild}}, options.updateOptions) } else { - parentCollection.update(parent._id, {$push:{[cacheField]:pickedChild}}) + parentCollection.update(parent._id, {$push:{[cacheField]:pickedChild}}, options.updateOptions) } }) } @@ -270,7 +269,7 @@ Mongo.Collection.prototype.cache = function(options){ childCollection.after.remove(function(userId, child){ let references = getNestedReferences(child) if(references.length){ - parentCollection.update({_id:{$in:references}}, {$pull:{[cacheField]:{_id:child._id}}}, {multi:true}) + parentCollection.update({_id:{$in:references}}, {$pull:{[cacheField]:{_id:child._id}}}, {...options.updateOptions, multi:true}) } }) } diff --git a/cacheCount.js b/cacheCount.js index 4a26557..b92aaa1 100644 --- a/cacheCount.js +++ b/cacheCount.js @@ -7,10 +7,10 @@ Mongo.Collection.prototype.cacheCount = function(options) { cacheField:String, referenceField:String, selector:Match.Optional(Object), - bypassSchema:Match.Optional(Boolean) + updateOptions:Match.Optional(Object) }) - let parentCollection = options.bypassSchema && Package['aldeed:collection2'] ? this._collection : this + let parentCollection = this let childCollection = options.collection let selector = options.selector || {} let cacheField = options.cacheField @@ -25,13 +25,13 @@ Mongo.Collection.prototype.cacheCount = function(options) { let ref = _.get(child, referenceField) if(ref){ let select = _.merge(selector, {[referenceField]:ref}) - parentCollection.update({_id:ref}, {$set:{[cacheField]:childCollection.find(select).count()}}) + parentCollection.update({_id:ref}, {$set:{[cacheField]:childCollection.find(select).count()}}, options.updateOptions) } } function insert(userId, parent){ let select = _.merge(selector, {[referenceField]:parent._id}) - parentCollection.update(parent._id, {$set:{[cacheField]:childCollection.find(select).count()}}) + parentCollection.update(parent._id, {$set:{[cacheField]:childCollection.find(select).count()}}, options.updateOptions) } addMigration(parentCollection, insert, options) diff --git a/cacheField.js b/cacheField.js index 610babb..4f69cf2 100644 --- a/cacheField.js +++ b/cacheField.js @@ -7,10 +7,10 @@ Mongo.Collection.prototype.cacheField = function(options) { cacheField:String, fields:[String], transform:Match.Optional(Function), - bypassSchema:Match.Optional(Boolean) + updateOptions:Match.Optional(Object) }) - let collection = options.bypassSchema && Package['aldeed:collection2'] ? this._collection : this + let collection = this let cacheField = options.cacheField let fields = options.fields let topFields = _.uniq(_.map(fields, field => field.split('.')[0])) @@ -25,8 +25,12 @@ Mongo.Collection.prototype.cacheField = function(options) { throw new Error('watching the cacheField for changes would cause an infinite loop') } - function insertHook(userid, doc){ - collection.update(doc._id, {$set:{[cacheField]:transform(_.pick(doc, fields))}}) + function insert(doc) { + collection.update(doc._id, {$set:{[cacheField]:transform(_.pick(doc, fields))}}, options.updateOptions) + } + + function insertHook(userId, doc){ + insert(doc); } addMigration(collection, insertHook, options) @@ -36,7 +40,7 @@ Mongo.Collection.prototype.cacheField = function(options) { collection.after.update((userId, doc, changedFields) => { if(_.intersection(changedFields, topFields).length){ Meteor.defer(()=>{ - collection.update(doc._id, {$set:{[cacheField]:transform(_.pick(doc, fields))}}) + insert(doc) }) } }) diff --git a/package.js b/package.js index cb0cb14..cef8ef2 100644 --- a/package.js +++ b/package.js @@ -11,7 +11,7 @@ Package.describe({ }) Npm.depends({ - 'lodash': '4.17.4', + 'lodash': '4.17.15', }) Package.onUse(function (api) { @@ -34,10 +34,10 @@ Package.onTest(function (api) { 'ecmascript', 'mongo', 'check', + 'aldeed:collection2@3.0.3', 'matb33:collection-hooks@0.8.4', - 'practicalmeteor:mocha', - 'practicalmeteor:chai' + 'meteortesting:mocha' ]) api.addFiles('tests.js', 'server') -}) \ No newline at end of file +}) diff --git a/testing/.gitignore b/testing/.gitignore new file mode 100644 index 0000000..40b878d --- /dev/null +++ b/testing/.gitignore @@ -0,0 +1 @@ +node_modules/ \ No newline at end of file diff --git a/testing/.meteor/.finished-upgraders b/testing/.meteor/.finished-upgraders new file mode 100644 index 0000000..4538749 --- /dev/null +++ b/testing/.meteor/.finished-upgraders @@ -0,0 +1,18 @@ +# This file contains information which helps Meteor properly upgrade your +# app when you run 'meteor update'. You should check it into version control +# with your project. + +notices-for-0.9.0 +notices-for-0.9.1 +0.9.4-platform-file +notices-for-facebook-graph-api-2 +1.2.0-standard-minifiers-package +1.2.0-meteor-platform-split +1.2.0-cordova-changes +1.2.0-breaking-changes +1.3.0-split-minifiers-package +1.4.0-remove-old-dev-bundle-link +1.4.1-add-shell-server-package +1.4.3-split-account-service-packages +1.5-add-dynamic-import-package +1.7-split-underscore-from-meteor-base diff --git a/testing/.meteor/.gitignore b/testing/.meteor/.gitignore new file mode 100644 index 0000000..4083037 --- /dev/null +++ b/testing/.meteor/.gitignore @@ -0,0 +1 @@ +local diff --git a/testing/.meteor/.id b/testing/.meteor/.id new file mode 100644 index 0000000..e326eac --- /dev/null +++ b/testing/.meteor/.id @@ -0,0 +1,7 @@ +# This file contains a token that is unique to your project. +# Check it into your repository along with the rest of this directory. +# It can be used for purposes such as: +# - ensuring you don't accidentally deploy one app on top of another +# - providing package authors with aggregated statistics + +jgja3fs3j5rj.is255jkkrpjp diff --git a/testing/.meteor/packages b/testing/.meteor/packages new file mode 100644 index 0000000..31f8f17 --- /dev/null +++ b/testing/.meteor/packages @@ -0,0 +1,19 @@ +# Meteor packages used by this project, one per line. +# Check this file (and the other files in this directory) into your repository. +# +# 'meteor add' and 'meteor remove' will edit this file for you, +# but you can also edit it by hand. + +meteor-base@1.4.0 # Packages every Meteor app needs to have +mobile-experience@1.0.5 # Packages for a great mobile UX +mongo@1.6.2 # The database Meteor supports right now +static-html # Define static page content in .html files +reactive-var@1.0.11 # Reactive variable for tracker +tracker@1.2.0 # Meteor's client-side reactive programming library + +standard-minifier-css@1.5.3 # CSS minifier run for production mode +standard-minifier-js@2.4.1 # JS minifier run for production mode +es5-shim@4.8.0 # ECMAScript 5 compatibility for older browsers +ecmascript@0.12.4 # Enable ECMAScript2015+ syntax in app code +shell-server@0.4.0 # Server-side component of the `meteor shell` command +aldeed:collection2@3.0.0 diff --git a/testing/.meteor/platforms b/testing/.meteor/platforms new file mode 100644 index 0000000..efeba1b --- /dev/null +++ b/testing/.meteor/platforms @@ -0,0 +1,2 @@ +server +browser diff --git a/testing/.meteor/release b/testing/.meteor/release new file mode 100644 index 0000000..97064e1 --- /dev/null +++ b/testing/.meteor/release @@ -0,0 +1 @@ +METEOR@1.8.1 diff --git a/testing/.meteor/versions b/testing/.meteor/versions new file mode 100644 index 0000000..477bf94 --- /dev/null +++ b/testing/.meteor/versions @@ -0,0 +1,71 @@ +aldeed:collection2@3.0.3 +allow-deny@1.1.0 +autoupdate@1.6.0 +babel-compiler@7.3.4 +babel-runtime@1.3.0 +base64@1.0.12 +binary-heap@1.0.11 +blaze-tools@1.0.10 +boilerplate-generator@1.6.0 +caching-compiler@1.2.1 +caching-html-compiler@1.1.3 +callback-hook@1.1.0 +check@1.3.1 +ddp@1.4.0 +ddp-client@2.3.3 +ddp-common@1.4.0 +ddp-server@2.3.0 +deps@1.0.12 +diff-sequence@1.1.1 +dynamic-import@0.5.1 +ecmascript@0.12.7 +ecmascript-runtime@0.7.0 +ecmascript-runtime-client@0.8.0 +ecmascript-runtime-server@0.7.1 +ejson@1.1.0 +es5-shim@4.8.0 +fetch@0.1.1 +geojson-utils@1.0.10 +hot-code-push@1.0.4 +html-tools@1.0.11 +htmljs@1.0.11 +id-map@1.1.0 +inter-process-messaging@0.1.0 +launch-screen@1.1.1 +livedata@1.0.18 +logging@1.1.20 +meteor@1.9.3 +meteor-base@1.4.0 +minifier-css@1.4.2 +minifier-js@2.4.1 +minimongo@1.4.5 +mobile-experience@1.0.5 +mobile-status-bar@1.0.14 +modern-browsers@0.1.4 +modules@0.13.0 +modules-runtime@0.10.3 +mongo@1.6.3 +mongo-decimal@0.1.1 +mongo-dev-server@1.1.0 +mongo-id@1.0.7 +npm-mongo@3.1.2 +ordered-dict@1.1.0 +promise@0.11.2 +raix:eventemitter@0.1.3 +random@1.1.0 +reactive-var@1.0.11 +reload@1.3.0 +retry@1.1.0 +routepolicy@1.1.0 +shell-server@0.4.0 +socket-stream-client@0.2.2 +spacebars-compiler@1.1.3 +standard-minifier-css@1.5.3 +standard-minifier-js@2.4.1 +static-html@1.2.2 +templating-tools@1.1.2 +tmeasday:check-npm-versions@0.3.2 +tracker@1.2.0 +underscore@1.0.10 +webapp@1.7.4 +webapp-hashing@1.0.9 diff --git a/testing/package-lock.json b/testing/package-lock.json new file mode 100644 index 0000000..a24620a --- /dev/null +++ b/testing/package-lock.json @@ -0,0 +1,336 @@ +{ + "name": "testing", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==" + }, + "chai": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", + "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", + "requires": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.2", + "deep-eql": "^3.0.1", + "get-func-name": "^2.0.0", + "pathval": "^1.1.0", + "type-detect": "^4.0.5" + } + }, + "check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=" + }, + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=" + }, + "cross-env": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-6.0.3.tgz", + "integrity": "sha512-+KqxF6LCvfhWvADcDPqo64yVIB31gv/jQulX2NGzKS/g3GEVz6/pt4wjHFtFWsHMddebWD/sDthJemzM4MaAag==", + "requires": { + "cross-spawn": "^7.0.0" + } + }, + "cross-spawn": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.1.tgz", + "integrity": "sha512-u7v4o84SwFpD32Z8IIcPZ6z1/ie24O6RU3RbtL5Y316l3KuHVPx9ItBgWQ6VlfAFnRnTtMUrsQ9MUUTuEZjogg==", + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "deep-eql": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", + "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "requires": { + "type-detect": "^4.0.0" + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "get-func-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" + }, + "lodash._basecallback": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/lodash._basecallback/-/lodash._basecallback-3.3.1.tgz", + "integrity": "sha1-t7K7Q9whYEJKIczybFfkQ3cqjic=", + "requires": { + "lodash._baseisequal": "^3.0.0", + "lodash._bindcallback": "^3.0.0", + "lodash.isarray": "^3.0.0", + "lodash.pairs": "^3.0.0" + } + }, + "lodash._baseeach": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash._baseeach/-/lodash._baseeach-3.0.4.tgz", + "integrity": "sha1-z4cGVyyhROjZ11InyZDamC+TKvM=", + "requires": { + "lodash.keys": "^3.0.0" + } + }, + "lodash._basefind": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._basefind/-/lodash._basefind-3.0.0.tgz", + "integrity": "sha1-srugXMZF+XLeLPkl+iv2Og9gyK4=" + }, + "lodash._basefindindex": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/lodash._basefindindex/-/lodash._basefindindex-3.6.0.tgz", + "integrity": "sha1-8IM2ChsCJBjtgbyJm+sxLiHnSk8=" + }, + "lodash._baseisequal": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/lodash._baseisequal/-/lodash._baseisequal-3.0.7.tgz", + "integrity": "sha1-2AJfdjOdKTQnZ9zIh85cuVpbUfE=", + "requires": { + "lodash.isarray": "^3.0.0", + "lodash.istypedarray": "^3.0.0", + "lodash.keys": "^3.0.0" + } + }, + "lodash._baseismatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lodash._baseismatch/-/lodash._baseismatch-3.1.3.tgz", + "integrity": "sha1-Byj8SO+hFpnT1fLXMEnyqxPED9U=", + "requires": { + "lodash._baseisequal": "^3.0.0" + } + }, + "lodash._basematches": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash._basematches/-/lodash._basematches-3.2.0.tgz", + "integrity": "sha1-9H4D8H7CB4SrCWjQy2y1l+IQEVg=", + "requires": { + "lodash._baseismatch": "^3.0.0", + "lodash.pairs": "^3.0.0" + } + }, + "lodash._bindcallback": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz", + "integrity": "sha1-5THCdkTPi1epnhftlbNcdIeJOS4=" + }, + "lodash._getnative": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", + "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=" + }, + "lodash.every": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.every/-/lodash.every-4.6.0.tgz", + "integrity": "sha1-64mYS+vENkJ5uzrvu9HKGb+mxqc=" + }, + "lodash.find": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.find/-/lodash.find-4.6.0.tgz", + "integrity": "sha1-ywcE1Hq3F4n/oN6Ll92Sb7iLE7E=" + }, + "lodash.findwhere": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.findwhere/-/lodash.findwhere-3.1.0.tgz", + "integrity": "sha1-eTfTTz6sgY3sf6lOjKXib9uhz8E=", + "requires": { + "lodash._basematches": "^3.0.0", + "lodash.find": "^3.0.0" + }, + "dependencies": { + "lodash.find": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/lodash.find/-/lodash.find-3.2.1.tgz", + "integrity": "sha1-BG4xnzrOkSrGySRsf2g8XsB7Nq0=", + "requires": { + "lodash._basecallback": "^3.0.0", + "lodash._baseeach": "^3.0.0", + "lodash._basefind": "^3.0.0", + "lodash._basefindindex": "^3.0.0", + "lodash.isarray": "^3.0.0", + "lodash.keys": "^3.0.0" + } + } + } + }, + "lodash.foreach": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz", + "integrity": "sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM=" + }, + "lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=" + }, + "lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=" + }, + "lodash.isarray": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=" + }, + "lodash.isempty": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.isempty/-/lodash.isempty-4.4.0.tgz", + "integrity": "sha1-b4bL7di+TsmHvpqvM8loTbGzHn4=" + }, + "lodash.isobject": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-3.0.2.tgz", + "integrity": "sha1-PI+41bW/S/kK4G4U8qUwpO2TXh0=" + }, + "lodash.istypedarray": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/lodash.istypedarray/-/lodash.istypedarray-3.0.6.tgz", + "integrity": "sha1-yaR3SYYHUB2OhJTSg7h8OSgc72I=" + }, + "lodash.keys": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", + "requires": { + "lodash._getnative": "^3.0.0", + "lodash.isarguments": "^3.0.0", + "lodash.isarray": "^3.0.0" + } + }, + "lodash.omit": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.omit/-/lodash.omit-4.5.0.tgz", + "integrity": "sha1-brGa5aHuHdnfC5aeZs4Lf6MLXmA=" + }, + "lodash.pairs": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash.pairs/-/lodash.pairs-3.0.1.tgz", + "integrity": "sha1-u+CNV4bu6qCaFckevw3LfSvjJqk=", + "requires": { + "lodash.keys": "^3.0.0" + } + }, + "lodash.pick": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", + "integrity": "sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM=" + }, + "lodash.union": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", + "integrity": "sha1-SLtQiECfFvGCFmZkHETdGqrjzYg=" + }, + "lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=" + }, + "lodash.without": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.without/-/lodash.without-4.4.0.tgz", + "integrity": "sha1-PNRXSgC2e643OpS3SHcmQFB7eqw=" + }, + "message-box": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/message-box/-/message-box-0.2.2.tgz", + "integrity": "sha512-A32m9D2ZaE08ZaXoE74AjcKwjtwwEhDT2EeY7A3YMAEB4ypL0uMZw7HegwZ806GIWyY4VLwe3kGO9reIdjwiRg==", + "requires": { + "lodash": "^4.17.14" + } + }, + "mongo-object": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/mongo-object/-/mongo-object-0.1.3.tgz", + "integrity": "sha512-m3vs+a1JkvRXELJMe2ieMmBe03NUy6bctGjWicRhReYj8brDi0ojKHLKLmXWr/RupNaFP8Q7/x8xG8GpFtp9wg==", + "requires": { + "lodash.foreach": "^4.5.0", + "lodash.isempty": "^4.4.0", + "lodash.isobject": "^3.0.2", + "lodash.without": "^4.4.0" + } + }, + "path-key": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.0.tgz", + "integrity": "sha512-8cChqz0RP6SHJkMt48FW0A7+qUOn+OsnOsVtzI59tZ8m+5bCSk7hzwET0pulwOM2YMn9J1efb07KB9l9f30SGg==" + }, + "pathval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", + "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=" + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" + }, + "simpl-schema": { + "version": "1.5.6", + "resolved": "https://registry.npmjs.org/simpl-schema/-/simpl-schema-1.5.6.tgz", + "integrity": "sha512-fo06b4LsqXrFX159K+/e9/PYFa6/f3783uJZBhiASdRiPCCrx5FG8DbVPSkwEPkAV+4Sufxkee1eneckPFa2Tg==", + "requires": { + "clone": "^2.1.1", + "extend": "^3.0.2", + "lodash.every": "^4.6.0", + "lodash.find": "^4.6.0", + "lodash.findwhere": "^3.1.0", + "lodash.includes": "^4.3.0", + "lodash.isempty": "^4.4.0", + "lodash.isobject": "^3.0.2", + "lodash.omit": "^4.5.0", + "lodash.pick": "^4.4.0", + "lodash.union": "^4.6.0", + "lodash.uniq": "^4.5.0", + "message-box": "^0.2.0", + "mongo-object": "^0.1.3" + } + }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==" + }, + "which": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.1.tgz", + "integrity": "sha512-N7GBZOTswtB9lkQBZA4+zAXrjEIWAUOB93AvzUiudRzRxhUdLURQ7D/gAIMY1gatT/LTbmbcv8SiYazy3eYB7w==", + "requires": { + "isexe": "^2.0.0" + } + } + } +} diff --git a/testing/package.json b/testing/package.json new file mode 100644 index 0000000..2fb97af --- /dev/null +++ b/testing/package.json @@ -0,0 +1,16 @@ +{ + "name": "testing", + "version": "1.0.0", + "description": "", + "scripts": { + "test": "meteor npm run test:watch -- --once", + "test:watch": "cross-env ROOT_URL= MONGO_URL= TEST_CLIENT=0 meteor test-packages --driver-package=meteortesting:mocha ../" + }, + "author": "", + "license": "ISC", + "dependencies": { + "chai": "^4.2.0", + "cross-env": "^6.0.3", + "simpl-schema": "^1.5.6" + } +} diff --git a/tests.js b/tests.js index bae34a5..fbd13cd 100644 --- a/tests.js +++ b/tests.js @@ -1,5 +1,7 @@ +import {assert} from 'chai' import {Mongo} from 'meteor/mongo' import _ from 'lodash' +import SimpleSchema from 'simpl-schema' import {MigrationHistory, migrate, autoMigrate} from './migrations.js' function report(result, expected, path = ''){ let keys = _.union(_.keys(result), _.keys(expected)) @@ -31,7 +33,13 @@ Customers = new Mongo.Collection('customers') //recursive caches Bills = new Mongo.Collection('bills') //recursive caches Items = new Mongo.Collection('items') //recursive caches - +const schema = new SimpleSchema({ + name: String, + last_name: String, +}) +const UsesWithSchema = new Mongo.Collection('users_with_schema') +UsesWithSchema.attachSchema(schema) +const ShoppingCart = new Mongo.Collection('shopping_cart') describe('setup', function(){ it('clear collections', function(){ @@ -42,6 +50,7 @@ describe('setup', function(){ Tags.remove({}) Likes.remove({}) MigrationHistory.remove({}) + UsesWithSchema.remove({}) }) it('clear hooks', function(){ //Remove all collection hooks so that migration tests work properly @@ -1678,4 +1687,102 @@ describe('Recursive caching', function(){ }, 100) }) }) + + describe('updateOptions', () => { + beforeEach(() => { + UsesWithSchema.remove({}) + ShoppingCart.remove({}) + }) + + it('bypasses schema - cache', () => { + UsesWithSchema.cache({ + type: 'inversed', + collection: ShoppingCart, + cacheField: 'carts', + fields: ['quantity', 'title'], + referenceField: 'userId', + updateOptions: { + bypassCollection2: true + } + }) + + const id = UsesWithSchema.insert({ + name: 'John', + last_name: 'Doe' + }) + + const cartId = ShoppingCart.insert({ + title: 'Product', + quantity: 2, + total: 250, + userId: id, + }) + + const res = UsesWithSchema.findOne() + compare(_.omit(res, '_id'), { + name: 'John', + last_name: 'Doe', + carts: [{ + _id: cartId, + title: 'Product', + quantity: 2 + }] + }) + }) + + it('bypasses schema - cacheCount', () => { + UsesWithSchema.cacheCount({ + collection: ShoppingCart, + cacheField: 'cartsCount', + referenceField: 'userId', + updateOptions: { + bypassCollection2: true + } + }) + + const id = UsesWithSchema.insert({ + name: 'John', + last_name: 'Doe' + }) + + const cartId = ShoppingCart.insert({ + title: 'Product', + quantity: 2, + total: 250, + userId: id, + }) + + const res = UsesWithSchema.findOne() + compare(_.omit(res, '_id', 'carts'), { + name: 'John', + last_name: 'Doe', + cartsCount: 1 + }) + }) + + it('bypasses schema - cacheField', () => { + UsesWithSchema.cacheField({ + fields: ['name', 'last_name'], + cacheField: 'full_name', + transform({name, last_name}) { + return `${name} ${last_name}` + }, + updateOptions: { + bypassCollection2: true + } + }) + + UsesWithSchema.insert({ + name: 'John', + last_name: 'Doe' + }) + + const res = UsesWithSchema.findOne() + compare(_.omit(res, '_id', 'carts', 'cartsCount'), { + name: 'John', + last_name: 'Doe', + full_name: 'John Doe', + }) + }) + }) }) From a243bd83c306f33cb6a4577a77df3a972030c969 Mon Sep 17 00:00:00 2001 From: Berislav Date: Sat, 16 Nov 2019 14:04:09 +0000 Subject: [PATCH 2/2] transform() to support undefined values --- cacheField.js | 5 ++++- tests.js | 24 ++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/cacheField.js b/cacheField.js index 4f69cf2..0fe17d1 100644 --- a/cacheField.js +++ b/cacheField.js @@ -26,7 +26,10 @@ Mongo.Collection.prototype.cacheField = function(options) { } function insert(doc) { - collection.update(doc._id, {$set:{[cacheField]:transform(_.pick(doc, fields))}}, options.updateOptions) + const value = transform(_.pick(doc, fields)); + if (!_.isUndefined(value)) { + collection.update(doc._id, {$set:{[cacheField]: value}}, options.updateOptions) + } } function insertHook(userId, doc){ diff --git a/tests.js b/tests.js index fbd13cd..c48e7d8 100644 --- a/tests.js +++ b/tests.js @@ -41,6 +41,8 @@ const UsesWithSchema = new Mongo.Collection('users_with_schema') UsesWithSchema.attachSchema(schema) const ShoppingCart = new Mongo.Collection('shopping_cart') +const OptionalCacheField = new Mongo.Collection('optional_cache_field') + describe('setup', function(){ it('clear collections', function(){ Posts.remove({}) @@ -806,6 +808,28 @@ describe('cacheField', function(){ }, 100) }) }) + describe('Transform that skips cache update by returning undefined', () => { + it('works', () => { + OptionalCacheField.cacheField({ + cacheField:'value', + fields:['username'], + transform(doc) { + if (doc.truthy) { + return doc.username; + } + } + }) + + /* + * This could crash on update with the error: + * MongoError: '$set' is empty. You must specify a field like so: {$set: {: ...}} + * Reason for this is explained here: https://github.com/meteor/meteor/blob/devel/History.md#breaking-changes-15 + * + * From 1.6.1 Meteor uses ignoreUndefined connection option: "... when inserted/updated. undefined values are now removed from all Mongo queries and insert/update documents." + * */ + OptionalCacheField.insert({a: 1}) + }) + }) }) //Run the same tests but with nested fields