Skip to content

Commit

Permalink
Merge branch 'master' into modernize & update
Browse files Browse the repository at this point in the history
  • Loading branch information
StorytellerCZ committed Oct 9, 2019
2 parents 6636180 + c2001e7 commit 48da964
Show file tree
Hide file tree
Showing 49 changed files with 2,798 additions and 373 deletions.
3 changes: 1 addition & 2 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
"extends": [
"standard"
],
"installedESLint": true,
"plugins": [
"standard"
],
Expand All @@ -13,4 +12,4 @@
"modules": true
}
}
}
}
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
sudo: false
language: node_js
node_js:
- "4"
- "8"

before_install:
- curl https://install.meteor.com | sh
Expand Down
11 changes: 9 additions & 2 deletions History.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
## vNEXT
## v0.9.1
* Fixed selector not being able to be modified when String or MongoID is used
* Add `npm prune --production` to publication script to prevent addition of dev only packages to the bundle. Fixes issue [#246](https://github.com/Meteor-Community-Packages/meteor-collection-hooks/issues/246)

## v0.9.0

* BREAKING CHANGE: Minimum required Meteor version is now 1.6.1
* Fix unsafe `selector` in `before.find` and `before.findOne` when called without arguments. This is potentially a *BREAKING CHANGE* for those who are relying on the current behavior of `selector` in `before.find` and `before.findOne`
* Align return values with original methods when a hook returns `false`
* Always run `find` hooks when fetching documents for `update`, `upsert` and `remove` hooks
* Fix unsafe `selector` in `before.find` and `before.findOne` when called without arguments. This is potentially a *breaking change* for those who are relying on the current behavior of `selector` in `before.find` and `before.findOne`
* Add support for update/upsert hooks to run on a different selector based on custom options when used together with a find hook that manipulates the selector based on custom options
* Fix Meteor.publish override, the previous override resulted in false positives of autopublish warning
* Use spacejam for headless testing, will make headless testing work locally
* Add support for the new modifiers $max, $min and $currentDate
* No longer fetch documents when no hooks are defined
* Fix conflict with [sewdn:collection-behaviours](https://github.com/Sewdn/meteor-collection-behaviours) package
* Updated dependencies and node version in tests

## v0.8.3

Expand Down
18 changes: 15 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Meteor Collection Hooks [![Build Status](https://travis-ci.org/matb33/meteor-collection-hooks.png?branch=master)](https://travis-ci.org/matb33/meteor-collection-hooks)
# Meteor Collection Hooks [![Build Status](https://travis-ci.org/Meteor-Community-Packages/meteor-collection-hooks.png?branch=master)](https://travis-ci.org/matb33/meteor-collection-hooks)

Extends Mongo.Collection with `before`/`after` hooks for `insert`, `update`, `remove`, `find`, and `findOne`.

Expand Down Expand Up @@ -27,7 +27,8 @@ functionality
defined.

```javascript
var test = new Mongo.Collection("test");
import { Mongo } from 'meteor/mongo';
const test = new Mongo.Collection("test");

test.before.insert(function (userId, doc) {
doc.createdAt = Date.now();
Expand Down Expand Up @@ -252,6 +253,8 @@ with more specific ones having higher specificity.
Examples (in order of least specific to most specific):

```javascript
import { CollectionHooks } from 'meteor/matb33:collection-hooks';

CollectionHooks.defaults.all.all = {exampleOption: 1};

CollectionHooks.defaults.before.all = {exampleOption: 2};
Expand All @@ -268,7 +271,8 @@ Similarly, collection-wide options can be defined (these have a higher
specificity than the global defaults from above):

```javascript
var testCollection = new Mongo.Collection("test");
import { Mongo } from 'meteor/mongo';
const testCollection = new Mongo.Collection("test");

testCollection.hookOptions.all.all = {exampleOption: 1};

Expand Down Expand Up @@ -328,13 +332,20 @@ server.*

- `find` hooks are also fired when fetching documents for `update`, `upsert` and `remove` hooks.

- If using the `direct` version to bypass a hook, any mongo operations done within nested
callbacks of the `direct` operation will also by default run as `direct`. You can use the following
line in a nested callback before the operation to unset the `direct` setting:
`CollectionHooks.directEnv = new Meteor.EnvironmentVariable(false)`

--------------------------------------------------------------------------------

## Maintainers
Maintained by [Meteor Community Packages](https://github.com/Meteor-Community-Packages) and in particular by:

- Mathieu Bouchard ([matb33](https://github.com/matb33))
- Andrew Mao ([mizzao](https://github.com/mizzao))
- Simon Fridlund ([zimme](https://github.com/zimme))
- Jan Dvorak ([StorytellerCZ](https://github.com/StorytellerCZ))

## Contributors

Expand All @@ -351,3 +362,4 @@ server.*
- Pierre Ozoux ([pierreozoux](https://github.com/pierreozoux))
- Tom Coleman ([tmeasday](https://github.com/tmeasday))
- Eric Jackson ([repjackson](https://github.com/repjackson))
- Koen Lav ([KoenLav](https://github.com/KoenLav))
2 changes: 1 addition & 1 deletion advices.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ import './find.js'
import './findone.js'

// Load after all advices have been defined
import './users-compat.js'
import './users-compat.js'
16 changes: 8 additions & 8 deletions client.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
import { Meteor } from 'meteor/meteor';
import { Tracker } from 'meteor/tracker';
import { CollectionHooks} from './collection-hooks.js'
import { Meteor } from 'meteor/meteor'
import { Tracker } from 'meteor/tracker'
import { CollectionHooks } from './collection-hooks.js'

import './advices'

CollectionHooks.getUserId = function getUserId () {
let userId

Tracker.nonreactive(() => {
userId = Meteor.userId && Meteor.userId()
userId = Meteor.userId && Meteor.userId()
})

if (userId == null) {
userId = CollectionHooks.defaultUserId
}

return userId
}

import './advices';

export {
CollectionHooks
};
}
67 changes: 59 additions & 8 deletions collection-hooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ const advices = {}

export const CollectionHooks = {
defaults: {
before: {insert: {}, update: {}, remove: {}, upsert: {}, find: {}, findOne: {}, all: {}},
after: {insert: {}, update: {}, remove: {}, find: {}, findOne: {}, all: {}},
all: {insert: {}, update: {}, remove: {}, find: {}, findOne: {}, all: {}}
before: { insert: {}, update: {}, remove: {}, upsert: {}, find: {}, findOne: {}, all: {} },
after: { insert: {}, update: {}, remove: {}, find: {}, findOne: {}, all: {} },
all: { insert: {}, update: {}, remove: {}, find: {}, findOne: {}, all: {} }
},
directEnv: new Meteor.EnvironmentVariable(),
directOp(func) {
Expand All @@ -27,7 +27,36 @@ export const CollectionHooks = {
}
}

CollectionHooks.extendCollectionInstance = function extendCollectionInstance (self, constructor) {
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);
['before', 'after'].forEach(function (pointcut) {
Expand Down Expand Up @@ -122,7 +151,7 @@ CollectionHooks.defineAdvice = (method, advice) => {

CollectionHooks.getAdvice = method => advices[method];

CollectionHooks.initOptions = (options, pointcut, method) =>
CollectionHooks.initOptions = (options, pointcut, method) =>
CollectionHooks.extendOptions(CollectionHooks.defaults, options, pointcut, method);

CollectionHooks.extendOptions = (source, options, pointcut, method) =>
Expand Down Expand Up @@ -160,11 +189,22 @@ CollectionHooks.getDocs = function getDocs (collection, selector, options) {
return collection.find(selector, findOptions)
}

// This function normalizes the selector (converting it to an Object)
CollectionHooks.normalizeSelector = function (selector) {
if (typeof selector === 'string' || (selector && selector.constructor === Mongo.ObjectID)) {
return {
_id: selector
}
} else {
return selector
}
}

// This function contains a snippet of code pulled and modified from:
// ~/.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=======================
Expand Down Expand Up @@ -224,25 +264,31 @@ CollectionHooks.reassignPrototype = function reassignPrototype (instance, constr
}
}

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)

const constructor = as._CollectionConstructor
const constructor = ns._NewCollectionContructor || as._CollectionConstructor
const proto = as._CollectionPrototype

ns.Collection = function (...args) {
const ret = constructor.apply(this, args)
CollectionHooks.extendCollectionInstance(this, constructor)
return ret
}
// Retain a reference to the new constructor to allow further wrapping.
ns._NewCollectionContructor = ns.Collection

ns.Collection.prototype = proto
ns.Collection.prototype.constructor = ns.Collection

for (let prop of Object.keys(constructor)) {
ns.Collection[prop] = constructor[prop]
}

// Meteor overrides the apply method which is copied from the constructor in the loop above. Replace it with the
// default method which we need if we were to further wrap ns.Collection.
ns.Collection.apply = Function.prototype.apply
}

CollectionHooks.modify = LocalCollection._modify
Expand All @@ -254,3 +300,8 @@ if (typeof Mongo !== 'undefined') {
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
}
11 changes: 4 additions & 7 deletions find.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
import { CollectionHooks } from './collection-hooks';

import { CollectionHooks } from './collection-hooks'

CollectionHooks.defineAdvice('find', function (userId, _super, instance, aspects, getTransform, args, suppressAspects) {
const ctx = {context: this, _super, args}
const selector = instance._getFindSelector(args)
const ctx = { context: this, _super, args }
const selector = CollectionHooks.normalizeSelector(instance._getFindSelector(args))
const options = instance._getFindOptions(args)
let ret
let abort

// before
if (!suppressAspects) {
aspects.before.forEach((o) => {
Expand All @@ -26,7 +23,7 @@ CollectionHooks.defineAdvice('find', function (userId, _super, instance, aspects
}
}

ret = _super.call(this, selector, options)
const ret = _super.call(this, selector, options)
after(ret)

return ret
Expand Down
12 changes: 7 additions & 5 deletions findone.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { CollectionHooks } from './collection-hooks';
import { CollectionHooks } from './collection-hooks'

CollectionHooks.defineAdvice('findOne', function (userId, _super, instance, aspects, getTransform, args, suppressAspects) {
const ctx = {context: this, _super, args};
const selector = instance._getFindSelector(args)
// args[0] : selector
// args[1] : options

const ctx = { context: this, _super, args }
const selector = CollectionHooks.normalizeSelector(instance._getFindSelector(args))
const options = instance._getFindOptions(args)
let ret
let abort

// before
Expand All @@ -25,7 +27,7 @@ CollectionHooks.defineAdvice('findOne', function (userId, _super, instance, aspe
}
}

ret = _super.call(this, selector, options)
const ret = _super.call(this, selector, options)
after(ret)

return ret
Expand Down
Loading

0 comments on commit 48da964

Please sign in to comment.