diff options
author | 2020-11-16 00:10:28 +0100 | |
---|---|---|
committer | 2020-11-16 00:10:28 +0100 | |
commit | e06ec920f7a5d784e674c4c4b4e6d1da3dc7391d (patch) | |
tree | 55713f725f77b44ebfec86e4eec3ce33e71458ca /node_modules/kareem | |
download | website_creator-e06ec920f7a5d784e674c4c4b4e6d1da3dc7391d.tar.gz website_creator-e06ec920f7a5d784e674c4c4b4e6d1da3dc7391d.tar.bz2 website_creator-e06ec920f7a5d784e674c4c4b4e6d1da3dc7391d.zip |
api, login, auth
Diffstat (limited to 'node_modules/kareem')
-rw-r--r-- | node_modules/kareem/.travis.yml | 12 | ||||
-rw-r--r-- | node_modules/kareem/CHANGELOG.md | 790 | ||||
-rw-r--r-- | node_modules/kareem/LICENSE | 202 | ||||
-rw-r--r-- | node_modules/kareem/Makefile | 5 | ||||
-rw-r--r-- | node_modules/kareem/README.md | 428 | ||||
-rw-r--r-- | node_modules/kareem/docs.js | 37 | ||||
-rw-r--r-- | node_modules/kareem/gulpfile.js | 18 | ||||
-rw-r--r-- | node_modules/kareem/index.js | 511 | ||||
-rw-r--r-- | node_modules/kareem/package.json | 53 | ||||
-rw-r--r-- | node_modules/kareem/test/examples.test.js | 379 | ||||
-rw-r--r-- | node_modules/kareem/test/misc.test.js | 71 | ||||
-rw-r--r-- | node_modules/kareem/test/post.test.js | 198 | ||||
-rw-r--r-- | node_modules/kareem/test/pre.test.js | 320 | ||||
-rw-r--r-- | node_modules/kareem/test/wrap.test.js | 342 |
14 files changed, 3366 insertions, 0 deletions
diff --git a/node_modules/kareem/.travis.yml b/node_modules/kareem/.travis.yml new file mode 100644 index 0000000..0a388b9 --- /dev/null +++ b/node_modules/kareem/.travis.yml @@ -0,0 +1,12 @@ +language: node_js +node_js: + - "12" + - "10" + - "9" + - "8" + - "7" + - "6" + - "5" + - "4" +script: "npm run-script test-travis" +after_script: "npm install coveralls@2.10.0 && cat ./coverage/lcov.info | coveralls" diff --git a/node_modules/kareem/CHANGELOG.md b/node_modules/kareem/CHANGELOG.md new file mode 100644 index 0000000..aa011f4 --- /dev/null +++ b/node_modules/kareem/CHANGELOG.md @@ -0,0 +1,790 @@ +# Change Log + +All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. + +<a name="2.3.0"></a> +## 2.3.0 (2018-09-24) + +* chore(release): 2.2.3 ([c8f2695](https://github.com/vkarpov15/kareem/commit/c8f2695)) +* chore(release): 2.2.4 ([a377a4f](https://github.com/vkarpov15/kareem/commit/a377a4f)) +* chore(release): 2.2.5 ([5a495e3](https://github.com/vkarpov15/kareem/commit/5a495e3)) +* fix(filter): copy async pres correctly with `filter()` ([1b1ed8a](https://github.com/vkarpov15/kareem/commit/1b1ed8a)), closes [Automattic/mongoose#3054](https://github.com/Automattic/mongoose/issues/3054) +* feat: add filter() function ([1f641f4](https://github.com/vkarpov15/kareem/commit/1f641f4)) +* feat: support storing options on pre and post hooks ([59220b9](https://github.com/vkarpov15/kareem/commit/59220b9)) + + + +<a name="2.2.3"></a> +## <small>2.2.3 (2018-09-10)</small> + +* chore: release 2.2.3 ([af653a3](https://github.com/vkarpov15/kareem/commit/af653a3)) + + + +<a name="2.2.2"></a> +## <small>2.2.2 (2018-09-10)</small> + +* chore: release 2.2.2 ([3f0144d](https://github.com/vkarpov15/kareem/commit/3f0144d)) +* fix: allow merge() to not clone ([e628d65](https://github.com/vkarpov15/kareem/commit/e628d65)) + + + +<a name="2.2.1"></a> +## <small>2.2.1 (2018-06-05)</small> + +* chore: release 2.2.1 ([4625a64](https://github.com/vkarpov15/kareem/commit/4625a64)) +* chore: remove lockfile from git ([7f3e4e6](https://github.com/vkarpov15/kareem/commit/7f3e4e6)) +* fix: handle numAsync correctly when merging ([fef8e7e](https://github.com/vkarpov15/kareem/commit/fef8e7e)) +* test: repro issue with not copying numAsync ([952d9db](https://github.com/vkarpov15/kareem/commit/952d9db)) + + + +<a name="2.2.0"></a> +## 2.2.0 (2018-06-05) + +* chore: release 2.2.0 ([ff9ad03](https://github.com/vkarpov15/kareem/commit/ff9ad03)) +* fix: use maps instead of objects for _pres and _posts so `toString()` doesn't get reported as having ([55df303](https://github.com/vkarpov15/kareem/commit/55df303)), closes [Automattic/mongoose#6538](https://github.com/Automattic/mongoose/issues/6538) + + + +<a name="2.1.0"></a> +## 2.1.0 (2018-05-16) + +* chore: release 2.1.0 ([ba5f1bc](https://github.com/vkarpov15/kareem/commit/ba5f1bc)) +* feat: add option to check wrapped function return value for promises ([c9d7dd1](https://github.com/vkarpov15/kareem/commit/c9d7dd1)) +* refactor: use const in wrap() ([0fc21f9](https://github.com/vkarpov15/kareem/commit/0fc21f9)) + + + +<a name="2.0.7"></a> +## <small>2.0.7 (2018-04-28)</small> + +* chore: release 2.0.7 ([0bf91e6](https://github.com/vkarpov15/kareem/commit/0bf91e6)) +* feat: add `hasHooks()` ([225f18d](https://github.com/vkarpov15/kareem/commit/225f18d)), closes [Automattic/mongoose#6385](https://github.com/Automattic/mongoose/issues/6385) + + + +<a name="2.0.6"></a> +## <small>2.0.6 (2018-03-22)</small> + +* chore: release 2.0.6 ([f3d406b](https://github.com/vkarpov15/kareem/commit/f3d406b)) +* fix(wrap): ensure fast path still wraps function in `nextTick()` for chaining ([7000494](https://github.com/vkarpov15/kareem/commit/7000494)), closes [Automattic/mongoose#6250](https://github.com/Automattic/mongoose/issues/6250) [dsanel/mongoose-delete#36](https://github.com/dsanel/mongoose-delete/issues/36) + + + +<a name="2.0.5"></a> +## <small>2.0.5 (2018-02-22)</small> + +* chore: release 2.0.5 ([3286612](https://github.com/vkarpov15/kareem/commit/3286612)) +* perf(createWrapper): don't create wrapper if there are no hooks ([5afc5b9](https://github.com/vkarpov15/kareem/commit/5afc5b9)), closes [Automattic/mongoose#6126](https://github.com/Automattic/mongoose/issues/6126) + + + +<a name="2.0.4"></a> +## <small>2.0.4 (2018-02-08)</small> + +* chore: release 2.0.4 ([2ab0293](https://github.com/vkarpov15/kareem/commit/2ab0293)) + + + +<a name="2.0.3"></a> +## <small>2.0.3 (2018-02-01)</small> + +* chore: release 2.0.3 ([3c1abe5](https://github.com/vkarpov15/kareem/commit/3c1abe5)) +* fix: use process.nextTick() re: Automattic/mongoose#6074 ([e5bfe33](https://github.com/vkarpov15/kareem/commit/e5bfe33)), closes [Automattic/mongoose#6074](https://github.com/Automattic/mongoose/issues/6074) + + + +<a name="2.0.2"></a> +## <small>2.0.2 (2018-01-24)</small> + +* chore: fix license ([a9d755c](https://github.com/vkarpov15/kareem/commit/a9d755c)), closes [#10](https://github.com/vkarpov15/kareem/issues/10) +* chore: release 2.0.2 ([fe87ab6](https://github.com/vkarpov15/kareem/commit/fe87ab6)) + + + +<a name="2.0.1"></a> +## <small>2.0.1 (2018-01-09)</small> + +* chore: release 2.0.1 with lockfile bump ([09c44fb](https://github.com/vkarpov15/kareem/commit/09c44fb)) + + + +<a name="2.0.0"></a> +## 2.0.0 (2018-01-09) + +* chore: bump marked re: security ([cc564a9](https://github.com/vkarpov15/kareem/commit/cc564a9)) +* chore: release 2.0.0 ([f511d1c](https://github.com/vkarpov15/kareem/commit/f511d1c)) + + + +<a name="2.0.0-rc5"></a> +## 2.0.0-rc5 (2017-12-23) + +* chore: fix build on node 4+5 ([6dac5a4](https://github.com/vkarpov15/kareem/commit/6dac5a4)) +* chore: fix built on node 4 + 5 again ([434ef0a](https://github.com/vkarpov15/kareem/commit/434ef0a)) +* chore: release 2.0.0-rc5 ([25a32ee](https://github.com/vkarpov15/kareem/commit/25a32ee)) + + + +<a name="2.0.0-rc4"></a> +## 2.0.0-rc4 (2017-12-22) + +* chore: release 2.0.0-rc4 ([49fc083](https://github.com/vkarpov15/kareem/commit/49fc083)) +* BREAKING CHANGE: deduplicate when merging hooks re: Automattic/mongoose#2945 ([d458573](https://github.com/vkarpov15/kareem/commit/d458573)), closes [Automattic/mongoose#2945](https://github.com/Automattic/mongoose/issues/2945) + + + +<a name="2.0.0-rc3"></a> +## 2.0.0-rc3 (2017-12-22) + +* chore: release 2.0.0-rc3 ([adaaa00](https://github.com/vkarpov15/kareem/commit/adaaa00)) +* feat: support returning promises from middleware functions ([05b4480](https://github.com/vkarpov15/kareem/commit/05b4480)), closes [Automattic/mongoose#3779](https://github.com/Automattic/mongoose/issues/3779) + + + +<a name="2.0.0-rc2"></a> +## 2.0.0-rc2 (2017-12-21) + +* chore: release 2.0.0-rc2 ([76325fa](https://github.com/vkarpov15/kareem/commit/76325fa)) +* fix: ensure next() and done() run in next tick ([6c20684](https://github.com/vkarpov15/kareem/commit/6c20684)) + + + +<a name="2.0.0-rc1"></a> +## 2.0.0-rc1 (2017-12-21) + +* chore: improve test coverage re: Automattic/mongoose#3232 ([7b45cf0](https://github.com/vkarpov15/kareem/commit/7b45cf0)), closes [Automattic/mongoose#3232](https://github.com/Automattic/mongoose/issues/3232) +* chore: release 2.0.0-rc1 ([9b83f52](https://github.com/vkarpov15/kareem/commit/9b83f52)) +* BREAKING CHANGE: report sync exceptions as errors, only allow calling next() and done() once ([674adcc](https://github.com/vkarpov15/kareem/commit/674adcc)), closes [Automattic/mongoose#3483](https://github.com/Automattic/mongoose/issues/3483) + + + +<a name="2.0.0-rc0"></a> +## 2.0.0-rc0 (2017-12-17) + +* chore: release 2.0.0-rc0 ([16b44b5](https://github.com/vkarpov15/kareem/commit/16b44b5)) +* BREAKING CHANGE: drop support for node < 4 ([9cbb8c7](https://github.com/vkarpov15/kareem/commit/9cbb8c7)) +* BREAKING CHANGE: remove useLegacyPost and add several new features ([6dd8531](https://github.com/vkarpov15/kareem/commit/6dd8531)), closes [Automattic/mongoose#3232](https://github.com/Automattic/mongoose/issues/3232) + + + +<a name="1.5.0"></a> +## 1.5.0 (2017-07-20) + +* chore: release 1.5.0 ([9c491a0](https://github.com/vkarpov15/kareem/commit/9c491a0)) +* fix: improve post error handlers results ([9928dd5](https://github.com/vkarpov15/kareem/commit/9928dd5)), closes [Automattic/mongoose#5466](https://github.com/Automattic/mongoose/issues/5466) + + + +<a name="1.4.2"></a> +## <small>1.4.2 (2017-07-06)</small> + +* chore: release 1.4.2 ([8d14ac5](https://github.com/vkarpov15/kareem/commit/8d14ac5)) +* fix: correct args re: Automattic/mongoose#5405 ([3f28ae6](https://github.com/vkarpov15/kareem/commit/3f28ae6)), closes [Automattic/mongoose#5405](https://github.com/Automattic/mongoose/issues/5405) + + + +<a name="1.4.1"></a> +## <small>1.4.1 (2017-04-25)</small> + +* chore: release 1.4.1 ([5ecf0c2](https://github.com/vkarpov15/kareem/commit/5ecf0c2)) +* fix: handle numAsyncPres with clone() ([c72e857](https://github.com/vkarpov15/kareem/commit/c72e857)), closes [#8](https://github.com/vkarpov15/kareem/issues/8) +* test: repro #8 ([9b4d6b2](https://github.com/vkarpov15/kareem/commit/9b4d6b2)), closes [#8](https://github.com/vkarpov15/kareem/issues/8) + + + +<a name="1.4.0"></a> +## 1.4.0 (2017-04-19) + +* chore: release 1.4.0 ([101c5f5](https://github.com/vkarpov15/kareem/commit/101c5f5)) +* feat: add merge() function ([285325e](https://github.com/vkarpov15/kareem/commit/285325e)) + + + +<a name="1.3.0"></a> +## 1.3.0 (2017-03-26) + +* chore: release 1.3.0 ([f3a9e50](https://github.com/vkarpov15/kareem/commit/f3a9e50)) +* feat: pass function args to execPre ([4dd466d](https://github.com/vkarpov15/kareem/commit/4dd466d)) + + + +<a name="1.2.1"></a> +## <small>1.2.1 (2017-02-03)</small> + +* chore: release 1.2.1 ([d97081f](https://github.com/vkarpov15/kareem/commit/d97081f)) +* fix: filter out _kareemIgnored args for error handlers re: Automattic/mongoose#4925 ([ddc7aeb](https://github.com/vkarpov15/kareem/commit/ddc7aeb)), closes [Automattic/mongoose#4925](https://github.com/Automattic/mongoose/issues/4925) +* fix: make error handlers handle errors in pre hooks ([af38033](https://github.com/vkarpov15/kareem/commit/af38033)), closes [Automattic/mongoose#4927](https://github.com/Automattic/mongoose/issues/4927) + + + +<a name="1.2.0"></a> +## 1.2.0 (2017-01-02) + +* chore: release 1.2.0 ([033225c](https://github.com/vkarpov15/kareem/commit/033225c)) +* chore: upgrade deps ([f9e9a09](https://github.com/vkarpov15/kareem/commit/f9e9a09)) +* feat: add _kareemIgnore re: Automattic/mongoose#4836 ([7957771](https://github.com/vkarpov15/kareem/commit/7957771)), closes [Automattic/mongoose#4836](https://github.com/Automattic/mongoose/issues/4836) + + + +<a name="1.1.5"></a> +## <small>1.1.5 (2016-12-13)</small> + +* chore: release 1.1.5 ([1a9f684](https://github.com/vkarpov15/kareem/commit/1a9f684)) +* fix: correct field name ([04a0e9d](https://github.com/vkarpov15/kareem/commit/04a0e9d)) + + + +<a name="1.1.4"></a> +## <small>1.1.4 (2016-12-09)</small> + +* chore: release 1.1.4 ([ece401c](https://github.com/vkarpov15/kareem/commit/ece401c)) +* chore: run tests on node 6 ([e0cb1cb](https://github.com/vkarpov15/kareem/commit/e0cb1cb)) +* fix: only copy own properties in clone() ([dfe28ce](https://github.com/vkarpov15/kareem/commit/dfe28ce)), closes [#7](https://github.com/vkarpov15/kareem/issues/7) + + + +<a name="1.1.3"></a> +## <small>1.1.3 (2016-06-27)</small> + +* chore: release 1.1.3 ([87171c8](https://github.com/vkarpov15/kareem/commit/87171c8)) +* fix: couple more issues with arg processing ([c65f523](https://github.com/vkarpov15/kareem/commit/c65f523)) + + + +<a name="1.1.2"></a> +## <small>1.1.2 (2016-06-27)</small> + +* chore: release 1.1.2 ([8e102b6](https://github.com/vkarpov15/kareem/commit/8e102b6)) +* fix: add early return ([4feda4e](https://github.com/vkarpov15/kareem/commit/4feda4e)) + + + +<a name="1.1.1"></a> +## <small>1.1.1 (2016-06-27)</small> + +* chore: release 1.1.1 ([8bb3050](https://github.com/vkarpov15/kareem/commit/8bb3050)) +* fix: skip error handlers if no error ([0eb3a44](https://github.com/vkarpov15/kareem/commit/0eb3a44)) + + + +<a name="1.1.0"></a> +## 1.1.0 (2016-05-11) + +* chore: release 1.1.0 ([85332d9](https://github.com/vkarpov15/kareem/commit/85332d9)) +* chore: test on node 4 and node 5 ([1faefa1](https://github.com/vkarpov15/kareem/commit/1faefa1)) +* 100% coverage again ([c9aee4e](https://github.com/vkarpov15/kareem/commit/c9aee4e)) +* add support for error post hooks ([d378113](https://github.com/vkarpov15/kareem/commit/d378113)) +* basic setup for sync hooks #4 ([55aa081](https://github.com/vkarpov15/kareem/commit/55aa081)), closes [#4](https://github.com/vkarpov15/kareem/issues/4) +* proof of concept for error handlers ([e4a07d9](https://github.com/vkarpov15/kareem/commit/e4a07d9)) +* refactor out handleWrapError helper ([b19af38](https://github.com/vkarpov15/kareem/commit/b19af38)) + + + +<a name="1.0.1"></a> +## <small>1.0.1 (2015-05-10)</small> + +* Fix #1 ([de60dc6](https://github.com/vkarpov15/kareem/commit/de60dc6)), closes [#1](https://github.com/vkarpov15/kareem/issues/1) +* release 1.0.1 ([6971088](https://github.com/vkarpov15/kareem/commit/6971088)) +* Run tests on iojs in travis ([adcd201](https://github.com/vkarpov15/kareem/commit/adcd201)) +* support legacy post hook behavior in wrap() ([23fa74c](https://github.com/vkarpov15/kareem/commit/23fa74c)) +* Use node 0.12 in travis ([834689d](https://github.com/vkarpov15/kareem/commit/834689d)) + + + +<a name="1.0.0"></a> +## 1.0.0 (2015-01-28) + +* Tag 1.0.0 ([4c5a35a](https://github.com/vkarpov15/kareem/commit/4c5a35a)) + + + +<a name="0.0.8"></a> +## <small>0.0.8 (2015-01-27)</small> + +* Add clone function ([688bba7](https://github.com/vkarpov15/kareem/commit/688bba7)) +* Add jscs for style checking ([5c93149](https://github.com/vkarpov15/kareem/commit/5c93149)) +* Bump 0.0.8 ([03c0d2f](https://github.com/vkarpov15/kareem/commit/03c0d2f)) +* Fix jscs config, add gulp rules ([9989abf](https://github.com/vkarpov15/kareem/commit/9989abf)) +* fix Makefile typo ([1f7e61a](https://github.com/vkarpov15/kareem/commit/1f7e61a)) + + + +<a name="0.0.7"></a> +## <small>0.0.7 (2015-01-04)</small> + +* Bump 0.0.7 ([98ef173](https://github.com/vkarpov15/kareem/commit/98ef173)) +* fix LearnBoost/mongoose#2553 - use null instead of undefined for err ([9157b48](https://github.com/vkarpov15/kareem/commit/9157b48)), closes [LearnBoost/mongoose#2553](https://github.com/LearnBoost/mongoose/issues/2553) +* Regenerate docs ([2331cdf](https://github.com/vkarpov15/kareem/commit/2331cdf)) + + + +<a name="0.0.6"></a> +## <small>0.0.6 (2015-01-01)</small> + +* Update docs and bump 0.0.6 ([92c12a7](https://github.com/vkarpov15/kareem/commit/92c12a7)) + + + +<a name="0.0.5"></a> +## <small>0.0.5 (2015-01-01)</small> + +* Add coverage rule to Makefile ([825a91c](https://github.com/vkarpov15/kareem/commit/825a91c)) +* Add coveralls to README ([fb52369](https://github.com/vkarpov15/kareem/commit/fb52369)) +* Add coveralls to travis ([93f6f15](https://github.com/vkarpov15/kareem/commit/93f6f15)) +* Add createWrapper() function ([ea77741](https://github.com/vkarpov15/kareem/commit/ea77741)) +* Add istanbul code coverage ([6eceeef](https://github.com/vkarpov15/kareem/commit/6eceeef)) +* Add some more comments for examples ([c5b0c6f](https://github.com/vkarpov15/kareem/commit/c5b0c6f)) +* Add travis ([e6dcb06](https://github.com/vkarpov15/kareem/commit/e6dcb06)) +* Add travis badge to docs ([ad8c9b3](https://github.com/vkarpov15/kareem/commit/ad8c9b3)) +* Add wrap() tests, 100% coverage ([6945be4](https://github.com/vkarpov15/kareem/commit/6945be4)) +* Better test coverage for execPost ([d9ad539](https://github.com/vkarpov15/kareem/commit/d9ad539)) +* Bump 0.0.5 ([69875b1](https://github.com/vkarpov15/kareem/commit/69875b1)) +* Docs fix ([15b7098](https://github.com/vkarpov15/kareem/commit/15b7098)) +* Fix silly mistake in docs generation ([50373eb](https://github.com/vkarpov15/kareem/commit/50373eb)) +* Fix typo in readme ([fec4925](https://github.com/vkarpov15/kareem/commit/fec4925)) +* Linkify travis badge ([92b25fe](https://github.com/vkarpov15/kareem/commit/92b25fe)) +* Make travis run coverage ([747157b](https://github.com/vkarpov15/kareem/commit/747157b)) +* Move travis status badge ([d52e89b](https://github.com/vkarpov15/kareem/commit/d52e89b)) +* Quick fix for coverage ([50bbddb](https://github.com/vkarpov15/kareem/commit/50bbddb)) +* Typo fix ([adea794](https://github.com/vkarpov15/kareem/commit/adea794)) + + + +<a name="0.0.4"></a> +## <small>0.0.4 (2014-12-13)</small> + +* Bump 0.0.4, run docs generation ([51a15fe](https://github.com/vkarpov15/kareem/commit/51a15fe)) +* Use correct post parameters in wrap() ([9bb5da3](https://github.com/vkarpov15/kareem/commit/9bb5da3)) + + + +<a name="0.0.3"></a> +## <small>0.0.3 (2014-12-12)</small> + +* Add npm test script, fix small bug with args not getting passed through post ([49e3e68](https://github.com/vkarpov15/kareem/commit/49e3e68)) +* Bump 0.0.3 ([65621d8](https://github.com/vkarpov15/kareem/commit/65621d8)) +* Update readme ([901388b](https://github.com/vkarpov15/kareem/commit/901388b)) + + + +<a name="0.0.2"></a> +## <small>0.0.2 (2014-12-12)</small> + +* Add github repo and bump 0.0.2 ([59db8be](https://github.com/vkarpov15/kareem/commit/59db8be)) + + + +<a name="0.0.1"></a> +## <small>0.0.1 (2014-12-12)</small> + +* Add basic docs ([ad29ea4](https://github.com/vkarpov15/kareem/commit/ad29ea4)) +* Add pre hooks ([2ffc356](https://github.com/vkarpov15/kareem/commit/2ffc356)) +* Add wrap function ([68c540c](https://github.com/vkarpov15/kareem/commit/68c540c)) +* Bump to version 0.0.1 ([a4bfd68](https://github.com/vkarpov15/kareem/commit/a4bfd68)) +* Initial commit ([4002458](https://github.com/vkarpov15/kareem/commit/4002458)) +* Initial deposit ([98fc489](https://github.com/vkarpov15/kareem/commit/98fc489)) +* Post hooks ([395b67c](https://github.com/vkarpov15/kareem/commit/395b67c)) +* Some basic setup work ([82df75e](https://github.com/vkarpov15/kareem/commit/82df75e)) +* Support sync pre hooks ([1cc1b9f](https://github.com/vkarpov15/kareem/commit/1cc1b9f)) +* Update package.json description ([978da18](https://github.com/vkarpov15/kareem/commit/978da18)) + + + +<a name="2.2.5"></a> +## <small>2.2.5 (2018-09-24)</small> + + + + +<a name="2.2.4"></a> +## <small>2.2.4 (2018-09-24)</small> + + + + +<a name="2.2.3"></a> +## <small>2.2.3 (2018-09-24)</small> + +* fix(filter): copy async pres correctly with `filter()` ([1b1ed8a](https://github.com/vkarpov15/kareem/commit/1b1ed8a)), closes [Automattic/mongoose#3054](https://github.com/Automattic/mongoose/issues/3054) +* feat: add filter() function ([1f641f4](https://github.com/vkarpov15/kareem/commit/1f641f4)) +* feat: support storing options on pre and post hooks ([59220b9](https://github.com/vkarpov15/kareem/commit/59220b9)) + + + +<a name="2.2.3"></a> +## <small>2.2.3 (2018-09-10)</small> + +* chore: release 2.2.3 ([af653a3](https://github.com/vkarpov15/kareem/commit/af653a3)) + + + +<a name="2.2.2"></a> +## <small>2.2.2 (2018-09-10)</small> + +* chore: release 2.2.2 ([3f0144d](https://github.com/vkarpov15/kareem/commit/3f0144d)) +* fix: allow merge() to not clone ([e628d65](https://github.com/vkarpov15/kareem/commit/e628d65)) + + + +<a name="2.2.1"></a> +## <small>2.2.1 (2018-06-05)</small> + +* chore: release 2.2.1 ([4625a64](https://github.com/vkarpov15/kareem/commit/4625a64)) +* chore: remove lockfile from git ([7f3e4e6](https://github.com/vkarpov15/kareem/commit/7f3e4e6)) +* fix: handle numAsync correctly when merging ([fef8e7e](https://github.com/vkarpov15/kareem/commit/fef8e7e)) +* test: repro issue with not copying numAsync ([952d9db](https://github.com/vkarpov15/kareem/commit/952d9db)) + + + +<a name="2.2.0"></a> +## 2.2.0 (2018-06-05) + +* chore: release 2.2.0 ([ff9ad03](https://github.com/vkarpov15/kareem/commit/ff9ad03)) +* fix: use maps instead of objects for _pres and _posts so `toString()` doesn't get reported as having ([55df303](https://github.com/vkarpov15/kareem/commit/55df303)), closes [Automattic/mongoose#6538](https://github.com/Automattic/mongoose/issues/6538) + + + +<a name="2.1.0"></a> +## 2.1.0 (2018-05-16) + +* chore: release 2.1.0 ([ba5f1bc](https://github.com/vkarpov15/kareem/commit/ba5f1bc)) +* feat: add option to check wrapped function return value for promises ([c9d7dd1](https://github.com/vkarpov15/kareem/commit/c9d7dd1)) +* refactor: use const in wrap() ([0fc21f9](https://github.com/vkarpov15/kareem/commit/0fc21f9)) + + + +<a name="2.0.7"></a> +## <small>2.0.7 (2018-04-28)</small> + +* chore: release 2.0.7 ([0bf91e6](https://github.com/vkarpov15/kareem/commit/0bf91e6)) +* feat: add `hasHooks()` ([225f18d](https://github.com/vkarpov15/kareem/commit/225f18d)), closes [Automattic/mongoose#6385](https://github.com/Automattic/mongoose/issues/6385) + + + +<a name="2.0.6"></a> +## <small>2.0.6 (2018-03-22)</small> + +* chore: release 2.0.6 ([f3d406b](https://github.com/vkarpov15/kareem/commit/f3d406b)) +* fix(wrap): ensure fast path still wraps function in `nextTick()` for chaining ([7000494](https://github.com/vkarpov15/kareem/commit/7000494)), closes [Automattic/mongoose#6250](https://github.com/Automattic/mongoose/issues/6250) [dsanel/mongoose-delete#36](https://github.com/dsanel/mongoose-delete/issues/36) + + + +<a name="2.0.5"></a> +## <small>2.0.5 (2018-02-22)</small> + +* chore: release 2.0.5 ([3286612](https://github.com/vkarpov15/kareem/commit/3286612)) +* perf(createWrapper): don't create wrapper if there are no hooks ([5afc5b9](https://github.com/vkarpov15/kareem/commit/5afc5b9)), closes [Automattic/mongoose#6126](https://github.com/Automattic/mongoose/issues/6126) + + + +<a name="2.0.4"></a> +## <small>2.0.4 (2018-02-08)</small> + +* chore: release 2.0.4 ([2ab0293](https://github.com/vkarpov15/kareem/commit/2ab0293)) + + + +<a name="2.0.3"></a> +## <small>2.0.3 (2018-02-01)</small> + +* chore: release 2.0.3 ([3c1abe5](https://github.com/vkarpov15/kareem/commit/3c1abe5)) +* fix: use process.nextTick() re: Automattic/mongoose#6074 ([e5bfe33](https://github.com/vkarpov15/kareem/commit/e5bfe33)), closes [Automattic/mongoose#6074](https://github.com/Automattic/mongoose/issues/6074) + + + +<a name="2.0.2"></a> +## <small>2.0.2 (2018-01-24)</small> + +* chore: fix license ([a9d755c](https://github.com/vkarpov15/kareem/commit/a9d755c)), closes [#10](https://github.com/vkarpov15/kareem/issues/10) +* chore: release 2.0.2 ([fe87ab6](https://github.com/vkarpov15/kareem/commit/fe87ab6)) + + + +<a name="2.0.1"></a> +## <small>2.0.1 (2018-01-09)</small> + +* chore: release 2.0.1 with lockfile bump ([09c44fb](https://github.com/vkarpov15/kareem/commit/09c44fb)) + + + +<a name="2.0.0"></a> +## 2.0.0 (2018-01-09) + +* chore: bump marked re: security ([cc564a9](https://github.com/vkarpov15/kareem/commit/cc564a9)) +* chore: release 2.0.0 ([f511d1c](https://github.com/vkarpov15/kareem/commit/f511d1c)) + + + +<a name="2.0.0-rc5"></a> +## 2.0.0-rc5 (2017-12-23) + +* chore: fix build on node 4+5 ([6dac5a4](https://github.com/vkarpov15/kareem/commit/6dac5a4)) +* chore: fix built on node 4 + 5 again ([434ef0a](https://github.com/vkarpov15/kareem/commit/434ef0a)) +* chore: release 2.0.0-rc5 ([25a32ee](https://github.com/vkarpov15/kareem/commit/25a32ee)) + + + +<a name="2.0.0-rc4"></a> +## 2.0.0-rc4 (2017-12-22) + +* chore: release 2.0.0-rc4 ([49fc083](https://github.com/vkarpov15/kareem/commit/49fc083)) +* BREAKING CHANGE: deduplicate when merging hooks re: Automattic/mongoose#2945 ([d458573](https://github.com/vkarpov15/kareem/commit/d458573)), closes [Automattic/mongoose#2945](https://github.com/Automattic/mongoose/issues/2945) + + + +<a name="2.0.0-rc3"></a> +## 2.0.0-rc3 (2017-12-22) + +* chore: release 2.0.0-rc3 ([adaaa00](https://github.com/vkarpov15/kareem/commit/adaaa00)) +* feat: support returning promises from middleware functions ([05b4480](https://github.com/vkarpov15/kareem/commit/05b4480)), closes [Automattic/mongoose#3779](https://github.com/Automattic/mongoose/issues/3779) + + + +<a name="2.0.0-rc2"></a> +## 2.0.0-rc2 (2017-12-21) + +* chore: release 2.0.0-rc2 ([76325fa](https://github.com/vkarpov15/kareem/commit/76325fa)) +* fix: ensure next() and done() run in next tick ([6c20684](https://github.com/vkarpov15/kareem/commit/6c20684)) + + + +<a name="2.0.0-rc1"></a> +## 2.0.0-rc1 (2017-12-21) + +* chore: improve test coverage re: Automattic/mongoose#3232 ([7b45cf0](https://github.com/vkarpov15/kareem/commit/7b45cf0)), closes [Automattic/mongoose#3232](https://github.com/Automattic/mongoose/issues/3232) +* chore: release 2.0.0-rc1 ([9b83f52](https://github.com/vkarpov15/kareem/commit/9b83f52)) +* BREAKING CHANGE: report sync exceptions as errors, only allow calling next() and done() once ([674adcc](https://github.com/vkarpov15/kareem/commit/674adcc)), closes [Automattic/mongoose#3483](https://github.com/Automattic/mongoose/issues/3483) + + + +<a name="2.0.0-rc0"></a> +## 2.0.0-rc0 (2017-12-17) + +* chore: release 2.0.0-rc0 ([16b44b5](https://github.com/vkarpov15/kareem/commit/16b44b5)) +* BREAKING CHANGE: drop support for node < 4 ([9cbb8c7](https://github.com/vkarpov15/kareem/commit/9cbb8c7)) +* BREAKING CHANGE: remove useLegacyPost and add several new features ([6dd8531](https://github.com/vkarpov15/kareem/commit/6dd8531)), closes [Automattic/mongoose#3232](https://github.com/Automattic/mongoose/issues/3232) + + + +<a name="1.5.0"></a> +## 1.5.0 (2017-07-20) + +* chore: release 1.5.0 ([9c491a0](https://github.com/vkarpov15/kareem/commit/9c491a0)) +* fix: improve post error handlers results ([9928dd5](https://github.com/vkarpov15/kareem/commit/9928dd5)), closes [Automattic/mongoose#5466](https://github.com/Automattic/mongoose/issues/5466) + + + +<a name="1.4.2"></a> +## <small>1.4.2 (2017-07-06)</small> + +* chore: release 1.4.2 ([8d14ac5](https://github.com/vkarpov15/kareem/commit/8d14ac5)) +* fix: correct args re: Automattic/mongoose#5405 ([3f28ae6](https://github.com/vkarpov15/kareem/commit/3f28ae6)), closes [Automattic/mongoose#5405](https://github.com/Automattic/mongoose/issues/5405) + + + +<a name="1.4.1"></a> +## <small>1.4.1 (2017-04-25)</small> + +* chore: release 1.4.1 ([5ecf0c2](https://github.com/vkarpov15/kareem/commit/5ecf0c2)) +* fix: handle numAsyncPres with clone() ([c72e857](https://github.com/vkarpov15/kareem/commit/c72e857)), closes [#8](https://github.com/vkarpov15/kareem/issues/8) +* test: repro #8 ([9b4d6b2](https://github.com/vkarpov15/kareem/commit/9b4d6b2)), closes [#8](https://github.com/vkarpov15/kareem/issues/8) + + + +<a name="1.4.0"></a> +## 1.4.0 (2017-04-19) + +* chore: release 1.4.0 ([101c5f5](https://github.com/vkarpov15/kareem/commit/101c5f5)) +* feat: add merge() function ([285325e](https://github.com/vkarpov15/kareem/commit/285325e)) + + + +<a name="1.3.0"></a> +## 1.3.0 (2017-03-26) + +* chore: release 1.3.0 ([f3a9e50](https://github.com/vkarpov15/kareem/commit/f3a9e50)) +* feat: pass function args to execPre ([4dd466d](https://github.com/vkarpov15/kareem/commit/4dd466d)) + + + +<a name="1.2.1"></a> +## <small>1.2.1 (2017-02-03)</small> + +* chore: release 1.2.1 ([d97081f](https://github.com/vkarpov15/kareem/commit/d97081f)) +* fix: filter out _kareemIgnored args for error handlers re: Automattic/mongoose#4925 ([ddc7aeb](https://github.com/vkarpov15/kareem/commit/ddc7aeb)), closes [Automattic/mongoose#4925](https://github.com/Automattic/mongoose/issues/4925) +* fix: make error handlers handle errors in pre hooks ([af38033](https://github.com/vkarpov15/kareem/commit/af38033)), closes [Automattic/mongoose#4927](https://github.com/Automattic/mongoose/issues/4927) + + + +<a name="1.2.0"></a> +## 1.2.0 (2017-01-02) + +* chore: release 1.2.0 ([033225c](https://github.com/vkarpov15/kareem/commit/033225c)) +* chore: upgrade deps ([f9e9a09](https://github.com/vkarpov15/kareem/commit/f9e9a09)) +* feat: add _kareemIgnore re: Automattic/mongoose#4836 ([7957771](https://github.com/vkarpov15/kareem/commit/7957771)), closes [Automattic/mongoose#4836](https://github.com/Automattic/mongoose/issues/4836) + + + +<a name="1.1.5"></a> +## <small>1.1.5 (2016-12-13)</small> + +* chore: release 1.1.5 ([1a9f684](https://github.com/vkarpov15/kareem/commit/1a9f684)) +* fix: correct field name ([04a0e9d](https://github.com/vkarpov15/kareem/commit/04a0e9d)) + + + +<a name="1.1.4"></a> +## <small>1.1.4 (2016-12-09)</small> + +* chore: release 1.1.4 ([ece401c](https://github.com/vkarpov15/kareem/commit/ece401c)) +* chore: run tests on node 6 ([e0cb1cb](https://github.com/vkarpov15/kareem/commit/e0cb1cb)) +* fix: only copy own properties in clone() ([dfe28ce](https://github.com/vkarpov15/kareem/commit/dfe28ce)), closes [#7](https://github.com/vkarpov15/kareem/issues/7) + + + +<a name="1.1.3"></a> +## <small>1.1.3 (2016-06-27)</small> + +* chore: release 1.1.3 ([87171c8](https://github.com/vkarpov15/kareem/commit/87171c8)) +* fix: couple more issues with arg processing ([c65f523](https://github.com/vkarpov15/kareem/commit/c65f523)) + + + +<a name="1.1.2"></a> +## <small>1.1.2 (2016-06-27)</small> + +* chore: release 1.1.2 ([8e102b6](https://github.com/vkarpov15/kareem/commit/8e102b6)) +* fix: add early return ([4feda4e](https://github.com/vkarpov15/kareem/commit/4feda4e)) + + + +<a name="1.1.1"></a> +## <small>1.1.1 (2016-06-27)</small> + +* chore: release 1.1.1 ([8bb3050](https://github.com/vkarpov15/kareem/commit/8bb3050)) +* fix: skip error handlers if no error ([0eb3a44](https://github.com/vkarpov15/kareem/commit/0eb3a44)) + + + +<a name="1.1.0"></a> +## 1.1.0 (2016-05-11) + +* chore: release 1.1.0 ([85332d9](https://github.com/vkarpov15/kareem/commit/85332d9)) +* chore: test on node 4 and node 5 ([1faefa1](https://github.com/vkarpov15/kareem/commit/1faefa1)) +* 100% coverage again ([c9aee4e](https://github.com/vkarpov15/kareem/commit/c9aee4e)) +* add support for error post hooks ([d378113](https://github.com/vkarpov15/kareem/commit/d378113)) +* basic setup for sync hooks #4 ([55aa081](https://github.com/vkarpov15/kareem/commit/55aa081)), closes [#4](https://github.com/vkarpov15/kareem/issues/4) +* proof of concept for error handlers ([e4a07d9](https://github.com/vkarpov15/kareem/commit/e4a07d9)) +* refactor out handleWrapError helper ([b19af38](https://github.com/vkarpov15/kareem/commit/b19af38)) + + + +<a name="1.0.1"></a> +## <small>1.0.1 (2015-05-10)</small> + +* Fix #1 ([de60dc6](https://github.com/vkarpov15/kareem/commit/de60dc6)), closes [#1](https://github.com/vkarpov15/kareem/issues/1) +* release 1.0.1 ([6971088](https://github.com/vkarpov15/kareem/commit/6971088)) +* Run tests on iojs in travis ([adcd201](https://github.com/vkarpov15/kareem/commit/adcd201)) +* support legacy post hook behavior in wrap() ([23fa74c](https://github.com/vkarpov15/kareem/commit/23fa74c)) +* Use node 0.12 in travis ([834689d](https://github.com/vkarpov15/kareem/commit/834689d)) + + + +<a name="1.0.0"></a> +## 1.0.0 (2015-01-28) + +* Tag 1.0.0 ([4c5a35a](https://github.com/vkarpov15/kareem/commit/4c5a35a)) + + + +<a name="0.0.8"></a> +## <small>0.0.8 (2015-01-27)</small> + +* Add clone function ([688bba7](https://github.com/vkarpov15/kareem/commit/688bba7)) +* Add jscs for style checking ([5c93149](https://github.com/vkarpov15/kareem/commit/5c93149)) +* Bump 0.0.8 ([03c0d2f](https://github.com/vkarpov15/kareem/commit/03c0d2f)) +* Fix jscs config, add gulp rules ([9989abf](https://github.com/vkarpov15/kareem/commit/9989abf)) +* fix Makefile typo ([1f7e61a](https://github.com/vkarpov15/kareem/commit/1f7e61a)) + + + +<a name="0.0.7"></a> +## <small>0.0.7 (2015-01-04)</small> + +* Bump 0.0.7 ([98ef173](https://github.com/vkarpov15/kareem/commit/98ef173)) +* fix LearnBoost/mongoose#2553 - use null instead of undefined for err ([9157b48](https://github.com/vkarpov15/kareem/commit/9157b48)), closes [LearnBoost/mongoose#2553](https://github.com/LearnBoost/mongoose/issues/2553) +* Regenerate docs ([2331cdf](https://github.com/vkarpov15/kareem/commit/2331cdf)) + + + +<a name="0.0.6"></a> +## <small>0.0.6 (2015-01-01)</small> + +* Update docs and bump 0.0.6 ([92c12a7](https://github.com/vkarpov15/kareem/commit/92c12a7)) + + + +<a name="0.0.5"></a> +## <small>0.0.5 (2015-01-01)</small> + +* Add coverage rule to Makefile ([825a91c](https://github.com/vkarpov15/kareem/commit/825a91c)) +* Add coveralls to README ([fb52369](https://github.com/vkarpov15/kareem/commit/fb52369)) +* Add coveralls to travis ([93f6f15](https://github.com/vkarpov15/kareem/commit/93f6f15)) +* Add createWrapper() function ([ea77741](https://github.com/vkarpov15/kareem/commit/ea77741)) +* Add istanbul code coverage ([6eceeef](https://github.com/vkarpov15/kareem/commit/6eceeef)) +* Add some more comments for examples ([c5b0c6f](https://github.com/vkarpov15/kareem/commit/c5b0c6f)) +* Add travis ([e6dcb06](https://github.com/vkarpov15/kareem/commit/e6dcb06)) +* Add travis badge to docs ([ad8c9b3](https://github.com/vkarpov15/kareem/commit/ad8c9b3)) +* Add wrap() tests, 100% coverage ([6945be4](https://github.com/vkarpov15/kareem/commit/6945be4)) +* Better test coverage for execPost ([d9ad539](https://github.com/vkarpov15/kareem/commit/d9ad539)) +* Bump 0.0.5 ([69875b1](https://github.com/vkarpov15/kareem/commit/69875b1)) +* Docs fix ([15b7098](https://github.com/vkarpov15/kareem/commit/15b7098)) +* Fix silly mistake in docs generation ([50373eb](https://github.com/vkarpov15/kareem/commit/50373eb)) +* Fix typo in readme ([fec4925](https://github.com/vkarpov15/kareem/commit/fec4925)) +* Linkify travis badge ([92b25fe](https://github.com/vkarpov15/kareem/commit/92b25fe)) +* Make travis run coverage ([747157b](https://github.com/vkarpov15/kareem/commit/747157b)) +* Move travis status badge ([d52e89b](https://github.com/vkarpov15/kareem/commit/d52e89b)) +* Quick fix for coverage ([50bbddb](https://github.com/vkarpov15/kareem/commit/50bbddb)) +* Typo fix ([adea794](https://github.com/vkarpov15/kareem/commit/adea794)) + + + +<a name="0.0.4"></a> +## <small>0.0.4 (2014-12-13)</small> + +* Bump 0.0.4, run docs generation ([51a15fe](https://github.com/vkarpov15/kareem/commit/51a15fe)) +* Use correct post parameters in wrap() ([9bb5da3](https://github.com/vkarpov15/kareem/commit/9bb5da3)) + + + +<a name="0.0.3"></a> +## <small>0.0.3 (2014-12-12)</small> + +* Add npm test script, fix small bug with args not getting passed through post ([49e3e68](https://github.com/vkarpov15/kareem/commit/49e3e68)) +* Bump 0.0.3 ([65621d8](https://github.com/vkarpov15/kareem/commit/65621d8)) +* Update readme ([901388b](https://github.com/vkarpov15/kareem/commit/901388b)) + + + +<a name="0.0.2"></a> +## <small>0.0.2 (2014-12-12)</small> + +* Add github repo and bump 0.0.2 ([59db8be](https://github.com/vkarpov15/kareem/commit/59db8be)) + + + +<a name="0.0.1"></a> +## <small>0.0.1 (2014-12-12)</small> + +* Add basic docs ([ad29ea4](https://github.com/vkarpov15/kareem/commit/ad29ea4)) +* Add pre hooks ([2ffc356](https://github.com/vkarpov15/kareem/commit/2ffc356)) +* Add wrap function ([68c540c](https://github.com/vkarpov15/kareem/commit/68c540c)) +* Bump to version 0.0.1 ([a4bfd68](https://github.com/vkarpov15/kareem/commit/a4bfd68)) +* Initial commit ([4002458](https://github.com/vkarpov15/kareem/commit/4002458)) +* Initial deposit ([98fc489](https://github.com/vkarpov15/kareem/commit/98fc489)) +* Post hooks ([395b67c](https://github.com/vkarpov15/kareem/commit/395b67c)) +* Some basic setup work ([82df75e](https://github.com/vkarpov15/kareem/commit/82df75e)) +* Support sync pre hooks ([1cc1b9f](https://github.com/vkarpov15/kareem/commit/1cc1b9f)) +* Update package.json description ([978da18](https://github.com/vkarpov15/kareem/commit/978da18)) diff --git a/node_modules/kareem/LICENSE b/node_modules/kareem/LICENSE new file mode 100644 index 0000000..e06d208 --- /dev/null +++ b/node_modules/kareem/LICENSE @@ -0,0 +1,202 @@ +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/node_modules/kareem/Makefile b/node_modules/kareem/Makefile new file mode 100644 index 0000000..f71ba90 --- /dev/null +++ b/node_modules/kareem/Makefile @@ -0,0 +1,5 @@ +docs: + node ./docs.js + +coverage: + ./node_modules/istanbul/lib/cli.js cover ./node_modules/mocha/bin/_mocha -- -R spec ./test/* diff --git a/node_modules/kareem/README.md b/node_modules/kareem/README.md new file mode 100644 index 0000000..49a4abc --- /dev/null +++ b/node_modules/kareem/README.md @@ -0,0 +1,428 @@ +# kareem + + [](https://travis-ci.org/vkarpov15/kareem) + [](https://coveralls.io/r/vkarpov15/kareem) + +Re-imagined take on the [hooks](http://npmjs.org/package/hooks) module, meant to offer additional flexibility in allowing you to execute hooks whenever necessary, as opposed to simply wrapping a single function. + +Named for the NBA's all-time leading scorer Kareem Abdul-Jabbar, known for his mastery of the [hook shot](http://en.wikipedia.org/wiki/Kareem_Abdul-Jabbar#Skyhook) + +<img src="http://upload.wikimedia.org/wikipedia/commons/0/00/Kareem-Abdul-Jabbar_Lipofsky.jpg" width="220"> + +# API + +## pre hooks + +Much like [hooks](https://npmjs.org/package/hooks), kareem lets you define +pre and post hooks: pre hooks are called before a given function executes. +Unlike hooks, kareem stores hooks and other internal state in a separate +object, rather than relying on inheritance. Furthermore, kareem exposes +an `execPre()` function that allows you to execute your pre hooks when +appropriate, giving you more fine-grained control over your function hooks. + + +#### It runs without any hooks specified + +```javascript + + hooks.execPre('cook', null, function() { + done(); + }); + +``` + +#### It runs basic serial pre hooks + +pre hook functions take one parameter, a "done" function that you execute +when your pre hook is finished. + + +```javascript + + var count = 0; + + hooks.pre('cook', function(done) { + ++count; + done(); + }); + + hooks.execPre('cook', null, function() { + assert.equal(1, count); + done(); + }); + +``` + +#### It can run multipe pre hooks + +```javascript + + var count1 = 0; + var count2 = 0; + + hooks.pre('cook', function(done) { + ++count1; + done(); + }); + + hooks.pre('cook', function(done) { + ++count2; + done(); + }); + + hooks.execPre('cook', null, function() { + assert.equal(1, count1); + assert.equal(1, count2); + done(); + }); + +``` + +#### It can run fully synchronous pre hooks + +If your pre hook function takes no parameters, its assumed to be +fully synchronous. + + +```javascript + + var count1 = 0; + var count2 = 0; + + hooks.pre('cook', function() { + ++count1; + }); + + hooks.pre('cook', function() { + ++count2; + }); + + hooks.execPre('cook', null, function(error) { + assert.equal(null, error); + assert.equal(1, count1); + assert.equal(1, count2); + done(); + }); + +``` + +#### It properly attaches context to pre hooks + +Pre save hook functions are bound to the second parameter to `execPre()` + + +```javascript + + hooks.pre('cook', function(done) { + this.bacon = 3; + done(); + }); + + hooks.pre('cook', function(done) { + this.eggs = 4; + done(); + }); + + var obj = { bacon: 0, eggs: 0 }; + + // In the pre hooks, `this` will refer to `obj` + hooks.execPre('cook', obj, function(error) { + assert.equal(null, error); + assert.equal(3, obj.bacon); + assert.equal(4, obj.eggs); + done(); + }); + +``` + +#### It can execute parallel (async) pre hooks + +Like the hooks module, you can declare "async" pre hooks - these take two +parameters, the functions `next()` and `done()`. `next()` passes control to +the next pre hook, but the underlying function won't be called until all +async pre hooks have called `done()`. + + +```javascript + + hooks.pre('cook', true, function(next, done) { + this.bacon = 3; + next(); + setTimeout(function() { + done(); + }, 5); + }); + + hooks.pre('cook', true, function(next, done) { + next(); + var _this = this; + setTimeout(function() { + _this.eggs = 4; + done(); + }, 10); + }); + + hooks.pre('cook', function(next) { + this.waffles = false; + next(); + }); + + var obj = { bacon: 0, eggs: 0 }; + + hooks.execPre('cook', obj, function() { + assert.equal(3, obj.bacon); + assert.equal(4, obj.eggs); + assert.equal(false, obj.waffles); + done(); + }); + +``` + +#### It supports returning a promise + +You can also return a promise from your pre hooks instead of calling +`next()`. When the returned promise resolves, kareem will kick off the +next middleware. + + +```javascript + + hooks.pre('cook', function() { + return new Promise(resolve => { + setTimeout(() => { + this.bacon = 3; + resolve(); + }, 100); + }); + }); + + var obj = { bacon: 0 }; + + hooks.execPre('cook', obj, function() { + assert.equal(3, obj.bacon); + done(); + }); + +``` + +## post hooks + +#### It runs without any hooks specified + +```javascript + + hooks.execPost('cook', null, [1], function(error, eggs) { + assert.ifError(error); + assert.equal(1, eggs); + done(); + }); + +``` + +#### It executes with parameters passed in + +```javascript + + hooks.post('cook', function(eggs, bacon, callback) { + assert.equal(1, eggs); + assert.equal(2, bacon); + callback(); + }); + + hooks.execPost('cook', null, [1, 2], function(error, eggs, bacon) { + assert.ifError(error); + assert.equal(1, eggs); + assert.equal(2, bacon); + done(); + }); + +``` + +#### It can use synchronous post hooks + +```javascript + + var execed = {}; + + hooks.post('cook', function(eggs, bacon) { + execed.first = true; + assert.equal(1, eggs); + assert.equal(2, bacon); + }); + + hooks.post('cook', function(eggs, bacon, callback) { + execed.second = true; + assert.equal(1, eggs); + assert.equal(2, bacon); + callback(); + }); + + hooks.execPost('cook', null, [1, 2], function(error, eggs, bacon) { + assert.ifError(error); + assert.equal(2, Object.keys(execed).length); + assert.ok(execed.first); + assert.ok(execed.second); + assert.equal(1, eggs); + assert.equal(2, bacon); + done(); + }); + +``` + +## wrap() + +#### It wraps pre and post calls into one call + +```javascript + + hooks.pre('cook', true, function(next, done) { + this.bacon = 3; + next(); + setTimeout(function() { + done(); + }, 5); + }); + + hooks.pre('cook', true, function(next, done) { + next(); + var _this = this; + setTimeout(function() { + _this.eggs = 4; + done(); + }, 10); + }); + + hooks.pre('cook', function(next) { + this.waffles = false; + next(); + }); + + hooks.post('cook', function(obj) { + obj.tofu = 'no'; + }); + + var obj = { bacon: 0, eggs: 0 }; + + var args = [obj]; + args.push(function(error, result) { + assert.ifError(error); + assert.equal(null, error); + assert.equal(3, obj.bacon); + assert.equal(4, obj.eggs); + assert.equal(false, obj.waffles); + assert.equal('no', obj.tofu); + + assert.equal(obj, result); + done(); + }); + + hooks.wrap( + 'cook', + function(o, callback) { + assert.equal(3, obj.bacon); + assert.equal(4, obj.eggs); + assert.equal(false, obj.waffles); + assert.equal(undefined, obj.tofu); + callback(null, o); + }, + obj, + args); + +``` + +## createWrapper() + +#### It wraps wrap() into a callable function + +```javascript + + hooks.pre('cook', true, function(next, done) { + this.bacon = 3; + next(); + setTimeout(function() { + done(); + }, 5); + }); + + hooks.pre('cook', true, function(next, done) { + next(); + var _this = this; + setTimeout(function() { + _this.eggs = 4; + done(); + }, 10); + }); + + hooks.pre('cook', function(next) { + this.waffles = false; + next(); + }); + + hooks.post('cook', function(obj) { + obj.tofu = 'no'; + }); + + var obj = { bacon: 0, eggs: 0 }; + + var cook = hooks.createWrapper( + 'cook', + function(o, callback) { + assert.equal(3, obj.bacon); + assert.equal(4, obj.eggs); + assert.equal(false, obj.waffles); + assert.equal(undefined, obj.tofu); + callback(null, o); + }, + obj); + + cook(obj, function(error, result) { + assert.ifError(error); + assert.equal(3, obj.bacon); + assert.equal(4, obj.eggs); + assert.equal(false, obj.waffles); + assert.equal('no', obj.tofu); + + assert.equal(obj, result); + done(); + }); + +``` + +## clone() + +#### It clones a Kareem object + +```javascript + + var k1 = new Kareem(); + k1.pre('cook', function() {}); + k1.post('cook', function() {}); + + var k2 = k1.clone(); + assert.deepEqual(['cook'], Object.keys(k2._pres)); + assert.deepEqual(['cook'], Object.keys(k2._posts)); + +``` + +## merge() + +#### It pulls hooks from another Kareem object + +```javascript + + var k1 = new Kareem(); + var test1 = function() {}; + k1.pre('cook', test1); + k1.post('cook', function() {}); + + var k2 = new Kareem(); + var test2 = function() {}; + k2.pre('cook', test2); + var k3 = k2.merge(k1); + assert.equal(k3._pres['cook'].length, 2); + assert.equal(k3._pres['cook'][0].fn, test2); + assert.equal(k3._pres['cook'][1].fn, test1); + assert.equal(k3._posts['cook'].length, 1); + +``` + diff --git a/node_modules/kareem/docs.js b/node_modules/kareem/docs.js new file mode 100644 index 0000000..4a8d4c8 --- /dev/null +++ b/node_modules/kareem/docs.js @@ -0,0 +1,37 @@ +var acquit = require('acquit'); + +var content = require('fs').readFileSync('./test/examples.test.js').toString(); +var blocks = acquit.parse(content); + +var mdOutput = + '# kareem\n\n' + + ' [](https://travis-ci.org/vkarpov15/kareem)\n' + + ' [](https://coveralls.io/r/vkarpov15/kareem)\n\n' + + 'Re-imagined take on the [hooks](http://npmjs.org/package/hooks) module, ' + + 'meant to offer additional flexibility in allowing you to execute hooks ' + + 'whenever necessary, as opposed to simply wrapping a single function.\n\n' + + 'Named for the NBA\'s all-time leading scorer Kareem Abdul-Jabbar, known ' + + 'for his mastery of the [hook shot](http://en.wikipedia.org/wiki/Kareem_Abdul-Jabbar#Skyhook)\n\n' + + '<img src="http://upload.wikimedia.org/wikipedia/commons/0/00/Kareem-Abdul-Jabbar_Lipofsky.jpg" width="220">\n\n' + + '# API\n\n'; + +for (var i = 0; i < blocks.length; ++i) { + var describe = blocks[i]; + mdOutput += '## ' + describe.contents + '\n\n'; + mdOutput += describe.comments[0] ? + acquit.trimEachLine(describe.comments[0]) + '\n\n' : + ''; + + for (var j = 0; j < describe.blocks.length; ++j) { + var it = describe.blocks[j]; + mdOutput += '#### It ' + it.contents + '\n\n'; + mdOutput += it.comments[0] ? + acquit.trimEachLine(it.comments[0]) + '\n\n' : + ''; + mdOutput += '```javascript\n'; + mdOutput += ' ' + it.code + '\n'; + mdOutput += '```\n\n'; + } +} + +require('fs').writeFileSync('README.md', mdOutput); diff --git a/node_modules/kareem/gulpfile.js b/node_modules/kareem/gulpfile.js new file mode 100644 index 0000000..635bfc7 --- /dev/null +++ b/node_modules/kareem/gulpfile.js @@ -0,0 +1,18 @@ +var gulp = require('gulp'); +var mocha = require('gulp-mocha'); +var config = require('./package.json'); +var jscs = require('gulp-jscs'); + +gulp.task('mocha', function() { + return gulp.src('./test/*'). + pipe(mocha({ reporter: 'dot' })); +}); + +gulp.task('jscs', function() { + return gulp.src('./index.js'). + pipe(jscs(config.jscsConfig)); +}); + +gulp.task('watch', function() { + gulp.watch('./index.js', ['jscs', 'mocha']); +}); diff --git a/node_modules/kareem/index.js b/node_modules/kareem/index.js new file mode 100644 index 0000000..31ccb41 --- /dev/null +++ b/node_modules/kareem/index.js @@ -0,0 +1,511 @@ +'use strict'; + +function Kareem() { + this._pres = new Map(); + this._posts = new Map(); +} + +Kareem.prototype.execPre = function(name, context, args, callback) { + if (arguments.length === 3) { + callback = args; + args = []; + } + var pres = get(this._pres, name, []); + var numPres = pres.length; + var numAsyncPres = pres.numAsync || 0; + var currentPre = 0; + var asyncPresLeft = numAsyncPres; + var done = false; + var $args = args; + + if (!numPres) { + return process.nextTick(function() { + callback(null); + }); + } + + var next = function() { + if (currentPre >= numPres) { + return; + } + var pre = pres[currentPre]; + + if (pre.isAsync) { + var args = [ + decorateNextFn(_next), + decorateNextFn(function(error) { + if (error) { + if (done) { + return; + } + done = true; + return callback(error); + } + if (--asyncPresLeft === 0 && currentPre >= numPres) { + return callback(null); + } + }) + ]; + + callMiddlewareFunction(pre.fn, context, args, args[0]); + } else if (pre.fn.length > 0) { + var args = [decorateNextFn(_next)]; + var _args = arguments.length >= 2 ? arguments : [null].concat($args); + for (var i = 1; i < _args.length; ++i) { + args.push(_args[i]); + } + + callMiddlewareFunction(pre.fn, context, args, args[0]); + } else { + let error = null; + let maybePromise = null; + try { + maybePromise = pre.fn.call(context); + } catch (err) { + error = err; + } + + if (isPromise(maybePromise)) { + maybePromise.then(() => _next(), err => _next(err)); + } else { + if (++currentPre >= numPres) { + if (asyncPresLeft > 0) { + // Leave parallel hooks to run + return; + } else { + return process.nextTick(function() { + callback(error); + }); + } + } + next(error); + } + } + }; + + next.apply(null, [null].concat(args)); + + function _next(error) { + if (error) { + if (done) { + return; + } + done = true; + return callback(error); + } + + if (++currentPre >= numPres) { + if (asyncPresLeft > 0) { + // Leave parallel hooks to run + return; + } else { + return callback(null); + } + } + + next.apply(context, arguments); + } +}; + +Kareem.prototype.execPreSync = function(name, context, args) { + var pres = get(this._pres, name, []); + var numPres = pres.length; + + for (var i = 0; i < numPres; ++i) { + pres[i].fn.apply(context, args || []); + } +}; + +Kareem.prototype.execPost = function(name, context, args, options, callback) { + if (arguments.length < 5) { + callback = options; + options = null; + } + var posts = get(this._posts, name, []); + var numPosts = posts.length; + var currentPost = 0; + + var firstError = null; + if (options && options.error) { + firstError = options.error; + } + + if (!numPosts) { + return process.nextTick(function() { + callback.apply(null, [firstError].concat(args)); + }); + } + + var next = function() { + var post = posts[currentPost].fn; + var numArgs = 0; + var argLength = args.length; + var newArgs = []; + for (var i = 0; i < argLength; ++i) { + numArgs += args[i] && args[i]._kareemIgnore ? 0 : 1; + if (!args[i] || !args[i]._kareemIgnore) { + newArgs.push(args[i]); + } + } + + if (firstError) { + if (post.length === numArgs + 2) { + var _cb = decorateNextFn(function(error) { + if (error) { + firstError = error; + } + if (++currentPost >= numPosts) { + return callback.call(null, firstError); + } + next(); + }); + + callMiddlewareFunction(post, context, + [firstError].concat(newArgs).concat([_cb]), _cb); + } else { + if (++currentPost >= numPosts) { + return callback.call(null, firstError); + } + next(); + } + } else { + const _cb = decorateNextFn(function(error) { + if (error) { + firstError = error; + return next(); + } + + if (++currentPost >= numPosts) { + return callback.apply(null, [null].concat(args)); + } + + next(); + }); + + if (post.length === numArgs + 2) { + // Skip error handlers if no error + if (++currentPost >= numPosts) { + return callback.apply(null, [null].concat(args)); + } + return next(); + } + if (post.length === numArgs + 1) { + callMiddlewareFunction(post, context, newArgs.concat([_cb]), _cb); + } else { + let error; + let maybePromise; + try { + maybePromise = post.apply(context, newArgs); + } catch (err) { + error = err; + firstError = err; + } + + if (isPromise(maybePromise)) { + return maybePromise.then(() => _cb(), err => _cb(err)); + } + + if (++currentPost >= numPosts) { + return callback.apply(null, [error].concat(args)); + } + + next(error); + } + } + }; + + next(); +}; + +Kareem.prototype.execPostSync = function(name, context, args) { + const posts = get(this._posts, name, []); + const numPosts = posts.length; + + for (let i = 0; i < numPosts; ++i) { + posts[i].fn.apply(context, args || []); + } +}; + +Kareem.prototype.createWrapperSync = function(name, fn) { + var kareem = this; + return function syncWrapper() { + kareem.execPreSync(name, this, arguments); + + var toReturn = fn.apply(this, arguments); + + kareem.execPostSync(name, this, [toReturn]); + + return toReturn; + }; +} + +function _handleWrapError(instance, error, name, context, args, options, callback) { + if (options.useErrorHandlers) { + var _options = { error: error }; + return instance.execPost(name, context, args, _options, function(error) { + return typeof callback === 'function' && callback(error); + }); + } else { + return typeof callback === 'function' ? + callback(error) : + undefined; + } +} + +Kareem.prototype.wrap = function(name, fn, context, args, options) { + const lastArg = (args.length > 0 ? args[args.length - 1] : null); + const argsWithoutCb = typeof lastArg === 'function' ? + args.slice(0, args.length - 1) : + args; + const _this = this; + + options = options || {}; + const checkForPromise = options.checkForPromise; + + this.execPre(name, context, args, function(error) { + if (error) { + const numCallbackParams = options.numCallbackParams || 0; + const errorArgs = options.contextParameter ? [context] : []; + for (var i = errorArgs.length; i < numCallbackParams; ++i) { + errorArgs.push(null); + } + return _handleWrapError(_this, error, name, context, errorArgs, + options, lastArg); + } + + const end = (typeof lastArg === 'function' ? args.length - 1 : args.length); + const numParameters = fn.length; + const ret = fn.apply(context, args.slice(0, end).concat(_cb)); + + if (checkForPromise) { + if (ret != null && typeof ret.then === 'function') { + // Thenable, use it + return ret.then( + res => _cb(null, res), + err => _cb(err) + ); + } + + // If `fn()` doesn't have a callback argument and doesn't return a + // promise, assume it is sync + if (numParameters < end + 1) { + return _cb(null, ret); + } + } + + function _cb() { + const args = arguments; + const argsWithoutError = Array.prototype.slice.call(arguments, 1); + if (options.nullResultByDefault && argsWithoutError.length === 0) { + argsWithoutError.push(null); + } + if (arguments[0]) { + // Assume error + return _handleWrapError(_this, arguments[0], name, context, + argsWithoutError, options, lastArg); + } else { + _this.execPost(name, context, argsWithoutError, function() { + if (arguments[0]) { + return typeof lastArg === 'function' ? + lastArg(arguments[0]) : + undefined; + } + + return typeof lastArg === 'function' ? + lastArg.apply(context, arguments) : + undefined; + }); + } + } + }); +}; + +Kareem.prototype.filter = function(fn) { + const clone = this.clone(); + + const pres = Array.from(clone._pres.keys()); + for (const name of pres) { + const hooks = this._pres.get(name). + map(h => Object.assign({}, h, { name: name })). + filter(fn); + + if (hooks.length === 0) { + clone._pres.delete(name); + continue; + } + + hooks.numAsync = hooks.filter(h => h.isAsync).length; + + clone._pres.set(name, hooks); + } + + const posts = Array.from(clone._posts.keys()); + for (const name of posts) { + const hooks = this._posts.get(name). + map(h => Object.assign({}, h, { name: name })). + filter(fn); + + if (hooks.length === 0) { + clone._posts.delete(name); + continue; + } + + clone._posts.set(name, hooks); + } + + return clone; +}; + +Kareem.prototype.hasHooks = function(name) { + return this._pres.has(name) || this._posts.has(name); +}; + +Kareem.prototype.createWrapper = function(name, fn, context, options) { + var _this = this; + if (!this.hasHooks(name)) { + // Fast path: if there's no hooks for this function, just return the + // function wrapped in a nextTick() + return function() { + process.nextTick(() => fn.apply(this, arguments)); + }; + } + return function() { + var _context = context || this; + var args = Array.prototype.slice.call(arguments); + _this.wrap(name, fn, _context, args, options); + }; +}; + +Kareem.prototype.pre = function(name, isAsync, fn, error, unshift) { + let options = {}; + if (typeof isAsync === 'object' && isAsync != null) { + options = isAsync; + isAsync = options.isAsync; + } else if (typeof arguments[1] !== 'boolean') { + error = fn; + fn = isAsync; + isAsync = false; + } + + const pres = get(this._pres, name, []); + this._pres.set(name, pres); + + if (isAsync) { + pres.numAsync = pres.numAsync || 0; + ++pres.numAsync; + } + + if (typeof fn !== 'function') { + throw new Error('pre() requires a function, got "' + typeof fn + '"'); + } + + if (unshift) { + pres.unshift(Object.assign({}, options, { fn: fn, isAsync: isAsync })); + } else { + pres.push(Object.assign({}, options, { fn: fn, isAsync: isAsync })); + } + + return this; +}; + +Kareem.prototype.post = function(name, options, fn, unshift) { + const hooks = get(this._posts, name, []); + + if (typeof options === 'function') { + unshift = !!fn; + fn = options; + options = {}; + } + + if (typeof fn !== 'function') { + throw new Error('post() requires a function, got "' + typeof fn + '"'); + } + + if (unshift) { + hooks.unshift(Object.assign({}, options, { fn: fn })); + } else { + hooks.push(Object.assign({}, options, { fn: fn })); + } + this._posts.set(name, hooks); + return this; +}; + +Kareem.prototype.clone = function() { + const n = new Kareem(); + + for (let key of this._pres.keys()) { + const clone = this._pres.get(key).slice(); + clone.numAsync = this._pres.get(key).numAsync; + n._pres.set(key, clone); + } + for (let key of this._posts.keys()) { + n._posts.set(key, this._posts.get(key).slice()); + } + + return n; +}; + +Kareem.prototype.merge = function(other, clone) { + clone = arguments.length === 1 ? true : clone; + var ret = clone ? this.clone() : this; + + for (let key of other._pres.keys()) { + const sourcePres = get(ret._pres, key, []); + const deduplicated = other._pres.get(key). + // Deduplicate based on `fn` + filter(p => sourcePres.map(_p => _p.fn).indexOf(p.fn) === -1); + const combined = sourcePres.concat(deduplicated); + combined.numAsync = sourcePres.numAsync || 0; + combined.numAsync += deduplicated.filter(p => p.isAsync).length; + ret._pres.set(key, combined); + } + for (let key of other._posts.keys()) { + const sourcePosts = get(ret._posts, key, []); + const deduplicated = other._posts.get(key). + filter(p => sourcePosts.indexOf(p) === -1); + ret._posts.set(key, sourcePosts.concat(deduplicated)); + } + + return ret; +}; + +function get(map, key, def) { + if (map.has(key)) { + return map.get(key); + } + return def; +} + +function callMiddlewareFunction(fn, context, args, next) { + let maybePromise; + try { + maybePromise = fn.apply(context, args); + } catch (error) { + return next(error); + } + + if (isPromise(maybePromise)) { + maybePromise.then(() => next(), err => next(err)); + } +} + +function isPromise(v) { + return v != null && typeof v.then === 'function'; +} + +function decorateNextFn(fn) { + var called = false; + var _this = this; + return function() { + // Ensure this function can only be called once + if (called) { + return; + } + called = true; + // Make sure to clear the stack so try/catch doesn't catch errors + // in subsequent middleware + return process.nextTick(() => fn.apply(_this, arguments)); + }; +} + +module.exports = Kareem; diff --git a/node_modules/kareem/package.json b/node_modules/kareem/package.json new file mode 100644 index 0000000..8909749 --- /dev/null +++ b/node_modules/kareem/package.json @@ -0,0 +1,53 @@ +{ + "_from": "kareem@2.3.1", + "_id": "kareem@2.3.1", + "_inBundle": false, + "_integrity": "sha512-l3hLhffs9zqoDe8zjmb/mAN4B8VT3L56EUvKNqLFVs9YlFA+zx7ke1DO8STAdDyYNkeSo1nKmjuvQeI12So8Xw==", + "_location": "/kareem", + "_phantomChildren": {}, + "_requested": { + "type": "version", + "registry": true, + "raw": "kareem@2.3.1", + "name": "kareem", + "escapedName": "kareem", + "rawSpec": "2.3.1", + "saveSpec": null, + "fetchSpec": "2.3.1" + }, + "_requiredBy": [ + "/mongoose" + ], + "_resolved": "https://registry.npmjs.org/kareem/-/kareem-2.3.1.tgz", + "_shasum": "def12d9c941017fabfb00f873af95e9c99e1be87", + "_spec": "kareem@2.3.1", + "_where": "/home/pruss/Dev/3-minute-website/node_modules/mongoose", + "author": { + "name": "Valeri Karpov", + "email": "val@karpov.io" + }, + "bugs": { + "url": "https://github.com/vkarpov15/kareem/issues" + }, + "bundleDependencies": false, + "deprecated": false, + "description": "Next-generation take on pre/post function hooks", + "devDependencies": { + "mocha": "5.x", + "nyc": "11.x", + "standard-version": "4.4.0" + }, + "homepage": "https://github.com/vkarpov15/kareem#readme", + "license": "Apache-2.0", + "main": "index.js", + "name": "kareem", + "repository": { + "type": "git", + "url": "git://github.com/vkarpov15/kareem.git" + }, + "scripts": { + "test": "mocha ./test/*", + "test-travis": "nyc mocha ./test/*" + }, + "version": "2.3.1" +} diff --git a/node_modules/kareem/test/examples.test.js b/node_modules/kareem/test/examples.test.js new file mode 100644 index 0000000..f120723 --- /dev/null +++ b/node_modules/kareem/test/examples.test.js @@ -0,0 +1,379 @@ +var assert = require('assert'); +var Kareem = require('../'); + +/* Much like [hooks](https://npmjs.org/package/hooks), kareem lets you define + * pre and post hooks: pre hooks are called before a given function executes. + * Unlike hooks, kareem stores hooks and other internal state in a separate + * object, rather than relying on inheritance. Furthermore, kareem exposes + * an `execPre()` function that allows you to execute your pre hooks when + * appropriate, giving you more fine-grained control over your function hooks. + */ +describe('pre hooks', function() { + var hooks; + + beforeEach(function() { + hooks = new Kareem(); + }); + + it('runs without any hooks specified', function(done) { + hooks.execPre('cook', null, function() { + done(); + }); + }); + + /* pre hook functions take one parameter, a "done" function that you execute + * when your pre hook is finished. + */ + it('runs basic serial pre hooks', function(done) { + var count = 0; + + hooks.pre('cook', function(done) { + ++count; + done(); + }); + + hooks.execPre('cook', null, function() { + assert.equal(1, count); + done(); + }); + }); + + it('can run multipe pre hooks', function(done) { + var count1 = 0; + var count2 = 0; + + hooks.pre('cook', function(done) { + ++count1; + done(); + }); + + hooks.pre('cook', function(done) { + ++count2; + done(); + }); + + hooks.execPre('cook', null, function() { + assert.equal(1, count1); + assert.equal(1, count2); + done(); + }); + }); + + /* If your pre hook function takes no parameters, its assumed to be + * fully synchronous. + */ + it('can run fully synchronous pre hooks', function(done) { + var count1 = 0; + var count2 = 0; + + hooks.pre('cook', function() { + ++count1; + }); + + hooks.pre('cook', function() { + ++count2; + }); + + hooks.execPre('cook', null, function(error) { + assert.equal(null, error); + assert.equal(1, count1); + assert.equal(1, count2); + done(); + }); + }); + + /* Pre save hook functions are bound to the second parameter to `execPre()` + */ + it('properly attaches context to pre hooks', function(done) { + hooks.pre('cook', function(done) { + this.bacon = 3; + done(); + }); + + hooks.pre('cook', function(done) { + this.eggs = 4; + done(); + }); + + var obj = { bacon: 0, eggs: 0 }; + + // In the pre hooks, `this` will refer to `obj` + hooks.execPre('cook', obj, function(error) { + assert.equal(null, error); + assert.equal(3, obj.bacon); + assert.equal(4, obj.eggs); + done(); + }); + }); + + /* Like the hooks module, you can declare "async" pre hooks - these take two + * parameters, the functions `next()` and `done()`. `next()` passes control to + * the next pre hook, but the underlying function won't be called until all + * async pre hooks have called `done()`. + */ + it('can execute parallel (async) pre hooks', function(done) { + hooks.pre('cook', true, function(next, done) { + this.bacon = 3; + next(); + setTimeout(function() { + done(); + }, 5); + }); + + hooks.pre('cook', true, function(next, done) { + next(); + var _this = this; + setTimeout(function() { + _this.eggs = 4; + done(); + }, 10); + }); + + hooks.pre('cook', function(next) { + this.waffles = false; + next(); + }); + + var obj = { bacon: 0, eggs: 0 }; + + hooks.execPre('cook', obj, function() { + assert.equal(3, obj.bacon); + assert.equal(4, obj.eggs); + assert.equal(false, obj.waffles); + done(); + }); + }); + + /* You can also return a promise from your pre hooks instead of calling + * `next()`. When the returned promise resolves, kareem will kick off the + * next middleware. + */ + it('supports returning a promise', function(done) { + hooks.pre('cook', function() { + return new Promise(resolve => { + setTimeout(() => { + this.bacon = 3; + resolve(); + }, 100); + }); + }); + + var obj = { bacon: 0 }; + + hooks.execPre('cook', obj, function() { + assert.equal(3, obj.bacon); + done(); + }); + }); +}); + +describe('post hooks', function() { + var hooks; + + beforeEach(function() { + hooks = new Kareem(); + }); + + it('runs without any hooks specified', function(done) { + hooks.execPost('cook', null, [1], function(error, eggs) { + assert.ifError(error); + assert.equal(1, eggs); + done(); + }); + }); + + it('executes with parameters passed in', function(done) { + hooks.post('cook', function(eggs, bacon, callback) { + assert.equal(1, eggs); + assert.equal(2, bacon); + callback(); + }); + + hooks.execPost('cook', null, [1, 2], function(error, eggs, bacon) { + assert.ifError(error); + assert.equal(1, eggs); + assert.equal(2, bacon); + done(); + }); + }); + + it('can use synchronous post hooks', function(done) { + var execed = {}; + + hooks.post('cook', function(eggs, bacon) { + execed.first = true; + assert.equal(1, eggs); + assert.equal(2, bacon); + }); + + hooks.post('cook', function(eggs, bacon, callback) { + execed.second = true; + assert.equal(1, eggs); + assert.equal(2, bacon); + callback(); + }); + + hooks.execPost('cook', null, [1, 2], function(error, eggs, bacon) { + assert.ifError(error); + assert.equal(2, Object.keys(execed).length); + assert.ok(execed.first); + assert.ok(execed.second); + assert.equal(1, eggs); + assert.equal(2, bacon); + done(); + }); + }); +}); + +describe('wrap()', function() { + var hooks; + + beforeEach(function() { + hooks = new Kareem(); + }); + + it('wraps pre and post calls into one call', function(done) { + hooks.pre('cook', true, function(next, done) { + this.bacon = 3; + next(); + setTimeout(function() { + done(); + }, 5); + }); + + hooks.pre('cook', true, function(next, done) { + next(); + var _this = this; + setTimeout(function() { + _this.eggs = 4; + done(); + }, 10); + }); + + hooks.pre('cook', function(next) { + this.waffles = false; + next(); + }); + + hooks.post('cook', function(obj) { + obj.tofu = 'no'; + }); + + var obj = { bacon: 0, eggs: 0 }; + + var args = [obj]; + args.push(function(error, result) { + assert.ifError(error); + assert.equal(null, error); + assert.equal(3, obj.bacon); + assert.equal(4, obj.eggs); + assert.equal(false, obj.waffles); + assert.equal('no', obj.tofu); + + assert.equal(obj, result); + done(); + }); + + hooks.wrap( + 'cook', + function(o, callback) { + assert.equal(3, obj.bacon); + assert.equal(4, obj.eggs); + assert.equal(false, obj.waffles); + assert.equal(undefined, obj.tofu); + callback(null, o); + }, + obj, + args); + }); +}); + +describe('createWrapper()', function() { + var hooks; + + beforeEach(function() { + hooks = new Kareem(); + }); + + it('wraps wrap() into a callable function', function(done) { + hooks.pre('cook', true, function(next, done) { + this.bacon = 3; + next(); + setTimeout(function() { + done(); + }, 5); + }); + + hooks.pre('cook', true, function(next, done) { + next(); + var _this = this; + setTimeout(function() { + _this.eggs = 4; + done(); + }, 10); + }); + + hooks.pre('cook', function(next) { + this.waffles = false; + next(); + }); + + hooks.post('cook', function(obj) { + obj.tofu = 'no'; + }); + + var obj = { bacon: 0, eggs: 0 }; + + var cook = hooks.createWrapper( + 'cook', + function(o, callback) { + assert.equal(3, obj.bacon); + assert.equal(4, obj.eggs); + assert.equal(false, obj.waffles); + assert.equal(undefined, obj.tofu); + callback(null, o); + }, + obj); + + cook(obj, function(error, result) { + assert.ifError(error); + assert.equal(3, obj.bacon); + assert.equal(4, obj.eggs); + assert.equal(false, obj.waffles); + assert.equal('no', obj.tofu); + + assert.equal(obj, result); + done(); + }); + }); +}); + +describe('clone()', function() { + it('clones a Kareem object', function() { + var k1 = new Kareem(); + k1.pre('cook', function() {}); + k1.post('cook', function() {}); + + var k2 = k1.clone(); + assert.deepEqual(Array.from(k2._pres.keys()), ['cook']); + assert.deepEqual(Array.from(k2._posts.keys()), ['cook']); + }); +}); + +describe('merge()', function() { + it('pulls hooks from another Kareem object', function() { + var k1 = new Kareem(); + var test1 = function() {}; + k1.pre('cook', test1); + k1.post('cook', function() {}); + + var k2 = new Kareem(); + var test2 = function() {}; + k2.pre('cook', test2); + var k3 = k2.merge(k1); + assert.equal(k3._pres.get('cook').length, 2); + assert.equal(k3._pres.get('cook')[0].fn, test2); + assert.equal(k3._pres.get('cook')[1].fn, test1); + assert.equal(k3._posts.get('cook').length, 1); + }); +}); diff --git a/node_modules/kareem/test/misc.test.js b/node_modules/kareem/test/misc.test.js new file mode 100644 index 0000000..531b1d4 --- /dev/null +++ b/node_modules/kareem/test/misc.test.js @@ -0,0 +1,71 @@ +'use strict'; + +const assert = require('assert'); +const Kareem = require('../'); + +describe('hasHooks', function() { + it('returns false for toString (Automattic/mongoose#6538)', function() { + const k = new Kareem(); + assert.ok(!k.hasHooks('toString')); + }); +}); + +describe('merge', function() { + it('handles async pres if source doesnt have them', function() { + const k1 = new Kareem(); + k1.pre('cook', true, function(next, done) { + execed.first = true; + setTimeout( + function() { + done('error!'); + }, + 5); + + next(); + }); + + assert.equal(k1._pres.get('cook').numAsync, 1); + + const k2 = new Kareem(); + const k3 = k2.merge(k1); + assert.equal(k3._pres.get('cook').numAsync, 1); + }); +}); + +describe('filter', function() { + it('returns clone with only hooks that match `fn()`', function() { + const k1 = new Kareem(); + + k1.pre('update', { document: true }, f1); + k1.pre('update', { query: true }, f2); + k1.pre('remove', { document: true }, f3); + + k1.post('update', { document: true }, f1); + k1.post('update', { query: true }, f2); + k1.post('remove', { document: true }, f3); + + const k2 = k1.filter(hook => hook.document); + assert.equal(k2._pres.get('update').length, 1); + assert.equal(k2._pres.get('update')[0].fn, f1); + assert.equal(k2._pres.get('remove').length, 1); + assert.equal(k2._pres.get('remove')[0].fn, f3); + + assert.equal(k2._posts.get('update').length, 1); + assert.equal(k2._posts.get('update')[0].fn, f1); + assert.equal(k2._posts.get('remove').length, 1); + assert.equal(k2._posts.get('remove')[0].fn, f3); + + const k3 = k1.filter(hook => hook.query); + assert.equal(k3._pres.get('update').length, 1); + assert.equal(k3._pres.get('update')[0].fn, f2); + assert.ok(!k3._pres.has('remove')); + + assert.equal(k3._posts.get('update').length, 1); + assert.equal(k3._posts.get('update')[0].fn, f2); + assert.ok(!k3._posts.has('remove')); + + function f1() {} + function f2() {} + function f3() {} + }); +}); diff --git a/node_modules/kareem/test/post.test.js b/node_modules/kareem/test/post.test.js new file mode 100644 index 0000000..b9a776d --- /dev/null +++ b/node_modules/kareem/test/post.test.js @@ -0,0 +1,198 @@ +'use strict'; + +const assert = require('assert'); +const Kareem = require('../'); + +describe('execPost', function() { + var hooks; + + beforeEach(function() { + hooks = new Kareem(); + }); + + it('handles errors', function(done) { + hooks.post('cook', function(eggs, callback) { + callback('error!'); + }); + + hooks.execPost('cook', null, [4], function(error, eggs) { + assert.equal('error!', error); + assert.ok(!eggs); + done(); + }); + }); + + it('unshift', function() { + var f1 = function() {}; + var f2 = function() {}; + hooks.post('cook', f1); + hooks.post('cook', f2, true); + assert.strictEqual(hooks._posts.get('cook')[0].fn, f2); + assert.strictEqual(hooks._posts.get('cook')[1].fn, f1); + }); + + it('arbitrary options', function() { + const f1 = function() {}; + const f2 = function() {}; + hooks.post('cook', { foo: 'bar' }, f1); + hooks.post('cook', { bar: 'baz' }, f2, true); + assert.equal(hooks._posts.get('cook')[1].foo, 'bar'); + assert.equal(hooks._posts.get('cook')[0].bar, 'baz'); + }); + + it('throws error if no function', function() { + assert.throws(() => hooks.post('test'), /got "undefined"/); + }); + + it('multiple posts', function(done) { + hooks.post('cook', function(eggs, callback) { + setTimeout( + function() { + callback(); + }, + 5); + }); + + hooks.post('cook', function(eggs, callback) { + setTimeout( + function() { + callback(); + }, + 5); + }); + + hooks.execPost('cook', null, [4], function(error, eggs) { + assert.ifError(error); + assert.equal(4, eggs); + done(); + }); + }); + + it('error posts', function(done) { + var called = {}; + hooks.post('cook', function(eggs, callback) { + called.first = true; + callback(); + }); + + hooks.post('cook', function(eggs, callback) { + called.second = true; + callback(new Error('fail')); + }); + + hooks.post('cook', function(eggs, callback) { + assert.ok(false); + }); + + hooks.post('cook', function(error, eggs, callback) { + called.fourth = true; + assert.equal(error.message, 'fail'); + callback(new Error('fourth')); + }); + + hooks.post('cook', function(error, eggs, callback) { + called.fifth = true; + assert.equal(error.message, 'fourth'); + callback(new Error('fifth')); + }); + + hooks.execPost('cook', null, [4], function(error, eggs) { + assert.ok(error); + assert.equal(error.message, 'fifth'); + assert.deepEqual(called, { + first: true, + second: true, + fourth: true, + fifth: true + }); + done(); + }); + }); + + it('error posts with initial error', function(done) { + var called = {}; + + hooks.post('cook', function(eggs, callback) { + assert.ok(false); + }); + + hooks.post('cook', function(error, eggs, callback) { + called.second = true; + assert.equal(error.message, 'fail'); + callback(new Error('second')); + }); + + hooks.post('cook', function(error, eggs, callback) { + called.third = true; + assert.equal(error.message, 'second'); + callback(new Error('third')); + }); + + hooks.post('cook', function(error, eggs, callback) { + called.fourth = true; + assert.equal(error.message, 'third'); + callback(); + }); + + var options = { error: new Error('fail') }; + hooks.execPost('cook', null, [4], options, function(error, eggs) { + assert.ok(error); + assert.equal(error.message, 'third'); + assert.deepEqual(called, { + second: true, + third: true, + fourth: true + }); + done(); + }); + }); + + it('supports returning a promise', function(done) { + var calledPost = 0; + + hooks.post('cook', function() { + return new Promise(resolve => { + setTimeout(() => { + ++calledPost; + resolve(); + }, 100); + }); + }); + + hooks.execPost('cook', null, [], {}, function(error) { + assert.ifError(error); + assert.equal(calledPost, 1); + done(); + }); + }); +}); + +describe('execPostSync', function() { + var hooks; + + beforeEach(function() { + hooks = new Kareem(); + }); + + it('executes hooks synchronously', function() { + var execed = {}; + + hooks.post('cook', function() { + execed.first = true; + }); + + hooks.post('cook', function() { + execed.second = true; + }); + + hooks.execPostSync('cook', null); + assert.ok(execed.first); + assert.ok(execed.second); + }); + + it('works with no hooks specified', function() { + assert.doesNotThrow(function() { + hooks.execPostSync('cook', null); + }); + }); +}); diff --git a/node_modules/kareem/test/pre.test.js b/node_modules/kareem/test/pre.test.js new file mode 100644 index 0000000..d908d67 --- /dev/null +++ b/node_modules/kareem/test/pre.test.js @@ -0,0 +1,320 @@ +'use strict'; + +const assert = require('assert'); +const Kareem = require('../'); + +describe('execPre', function() { + var hooks; + + beforeEach(function() { + hooks = new Kareem(); + }); + + it('handles errors with multiple pres', function(done) { + var execed = {}; + + hooks.pre('cook', function(done) { + execed.first = true; + done(); + }); + + hooks.pre('cook', function(done) { + execed.second = true; + done('error!'); + }); + + hooks.pre('cook', function(done) { + execed.third = true; + done(); + }); + + hooks.execPre('cook', null, function(err) { + assert.equal('error!', err); + assert.equal(2, Object.keys(execed).length); + assert.ok(execed.first); + assert.ok(execed.second); + done(); + }); + }); + + it('sync errors', function(done) { + var called = 0; + + hooks.pre('cook', function(next) { + throw new Error('woops!'); + }); + + hooks.pre('cook', function(next) { + ++called; + next(); + }); + + hooks.execPre('cook', null, function(err) { + assert.equal(err.message, 'woops!'); + assert.equal(called, 0); + done(); + }); + }); + + it('unshift', function() { + var f1 = function() {}; + var f2 = function() {}; + hooks.pre('cook', false, f1); + hooks.pre('cook', false, f2, null, true); + assert.strictEqual(hooks._pres.get('cook')[0].fn, f2); + assert.strictEqual(hooks._pres.get('cook')[1].fn, f1); + }); + + it('throws error if no function', function() { + assert.throws(() => hooks.pre('test'), /got "undefined"/); + }); + + it('arbitrary options', function() { + const f1 = function() {}; + const f2 = function() {}; + hooks.pre('cook', { foo: 'bar' }, f1); + hooks.pre('cook', { bar: 'baz' }, f2, null, true); + assert.equal(hooks._pres.get('cook')[1].foo, 'bar'); + assert.equal(hooks._pres.get('cook')[0].bar, 'baz'); + }); + + it('handles async errors', function(done) { + var execed = {}; + + hooks.pre('cook', true, function(next, done) { + execed.first = true; + setTimeout( + function() { + done('error!'); + }, + 5); + + next(); + }); + + hooks.pre('cook', true, function(next, done) { + execed.second = true; + setTimeout( + function() { + done('other error!'); + }, + 10); + + next(); + }); + + hooks.execPre('cook', null, function(err) { + assert.equal('error!', err); + assert.equal(2, Object.keys(execed).length); + assert.ok(execed.first); + assert.ok(execed.second); + done(); + }); + }); + + it('handles async errors in next()', function(done) { + var execed = {}; + + hooks.pre('cook', true, function(next, done) { + execed.first = true; + setTimeout( + function() { + done('other error!'); + }, + 15); + + next(); + }); + + hooks.pre('cook', true, function(next, done) { + execed.second = true; + setTimeout( + function() { + next('error!'); + done('another error!'); + }, + 5); + }); + + hooks.execPre('cook', null, function(err) { + assert.equal('error!', err); + assert.equal(2, Object.keys(execed).length); + assert.ok(execed.first); + assert.ok(execed.second); + done(); + }); + }); + + it('handles async errors in next() when already done', function(done) { + var execed = {}; + + hooks.pre('cook', true, function(next, done) { + execed.first = true; + setTimeout( + function() { + done('other error!'); + }, + 5); + + next(); + }); + + hooks.pre('cook', true, function(next, done) { + execed.second = true; + setTimeout( + function() { + next('error!'); + done('another error!'); + }, + 25); + }); + + hooks.execPre('cook', null, function(err) { + assert.equal('other error!', err); + assert.equal(2, Object.keys(execed).length); + assert.ok(execed.first); + assert.ok(execed.second); + done(); + }); + }); + + it('async pres with clone()', function(done) { + var execed = false; + + hooks.pre('cook', true, function(next, done) { + execed = true; + setTimeout( + function() { + done(); + }, + 5); + + next(); + }); + + hooks.clone().execPre('cook', null, function(err) { + assert.ifError(err); + assert.ok(execed); + done(); + }); + }); + + it('returns correct error when async pre errors', function(done) { + var execed = {}; + + hooks.pre('cook', true, function(next, done) { + execed.first = true; + setTimeout( + function() { + done('other error!'); + }, + 5); + + next(); + }); + + hooks.pre('cook', function(next) { + execed.second = true; + setTimeout( + function() { + next('error!'); + }, + 15); + }); + + hooks.execPre('cook', null, function(err) { + assert.equal('other error!', err); + assert.equal(2, Object.keys(execed).length); + assert.ok(execed.first); + assert.ok(execed.second); + done(); + }); + }); + + it('lets async pres run when fully sync pres are done', function(done) { + var execed = {}; + + hooks.pre('cook', true, function(next, done) { + execed.first = true; + setTimeout( + function() { + done(); + }, + 5); + + next(); + }); + + hooks.pre('cook', function() { + execed.second = true; + }); + + hooks.execPre('cook', null, function(err) { + assert.ifError(err); + assert.equal(2, Object.keys(execed).length); + assert.ok(execed.first); + assert.ok(execed.second); + done(); + }); + }); + + it('allows passing arguments to the next pre', function(done) { + var execed = {}; + + hooks.pre('cook', function(next) { + execed.first = true; + next(null, 'test'); + }); + + hooks.pre('cook', function(next, p) { + execed.second = true; + assert.equal(p, 'test'); + next(); + }); + + hooks.pre('cook', function(next, p) { + execed.third = true; + assert.ok(!p); + next(); + }); + + hooks.execPre('cook', null, function(err) { + assert.ifError(err); + assert.equal(3, Object.keys(execed).length); + assert.ok(execed.first); + assert.ok(execed.second); + assert.ok(execed.third); + done(); + }); + }); +}); + +describe('execPreSync', function() { + var hooks; + + beforeEach(function() { + hooks = new Kareem(); + }); + + it('executes hooks synchronously', function() { + var execed = {}; + + hooks.pre('cook', function() { + execed.first = true; + }); + + hooks.pre('cook', function() { + execed.second = true; + }); + + hooks.execPreSync('cook', null); + assert.ok(execed.first); + assert.ok(execed.second); + }); + + it('works with no hooks specified', function() { + assert.doesNotThrow(function() { + hooks.execPreSync('cook', null); + }); + }); +}); diff --git a/node_modules/kareem/test/wrap.test.js b/node_modules/kareem/test/wrap.test.js new file mode 100644 index 0000000..dd9196e --- /dev/null +++ b/node_modules/kareem/test/wrap.test.js @@ -0,0 +1,342 @@ +var assert = require('assert'); +var Kareem = require('../'); + +describe('wrap()', function() { + var hooks; + + beforeEach(function() { + hooks = new Kareem(); + }); + + it('handles pre errors', function(done) { + hooks.pre('cook', function(done) { + done('error!'); + }); + + hooks.post('cook', function(obj) { + obj.tofu = 'no'; + }); + + var obj = { bacon: 0, eggs: 0 }; + + var args = [obj]; + args.push(function(error, result) { + assert.equal('error!', error); + assert.ok(!result); + assert.equal(undefined, obj.tofu); + done(); + }); + + hooks.wrap( + 'cook', + function(o, callback) { + // Should never get called + assert.ok(false); + callback(null, o); + }, + obj, + args); + }); + + it('handles pre errors when no callback defined', function(done) { + hooks.pre('cook', function(done) { + done('error!'); + }); + + hooks.post('cook', function(obj) { + obj.tofu = 'no'; + }); + + var obj = { bacon: 0, eggs: 0 }; + + var args = [obj]; + + hooks.wrap( + 'cook', + function(o, callback) { + // Should never get called + assert.ok(false); + callback(null, o); + }, + obj, + args); + + setTimeout( + function() { + done(); + }, + 25); + }); + + it('handles errors in wrapped function', function(done) { + hooks.pre('cook', function(done) { + done(); + }); + + hooks.post('cook', function(obj) { + obj.tofu = 'no'; + }); + + var obj = { bacon: 0, eggs: 0 }; + + var args = [obj]; + args.push(function(error, result) { + assert.equal('error!', error); + assert.ok(!result); + assert.equal(undefined, obj.tofu); + done(); + }); + + hooks.wrap( + 'cook', + function(o, callback) { + callback('error!'); + }, + obj, + args); + }); + + it('handles errors in post', function(done) { + hooks.pre('cook', function(done) { + done(); + }); + + hooks.post('cook', function(obj, callback) { + obj.tofu = 'no'; + callback('error!'); + }); + + var obj = { bacon: 0, eggs: 0 }; + + var args = [obj]; + args.push(function(error, result) { + assert.equal('error!', error); + assert.ok(!result); + assert.equal('no', obj.tofu); + done(); + }); + + hooks.wrap( + 'cook', + function(o, callback) { + callback(null, o); + }, + obj, + args); + }); + + it('defers errors to post hooks if enabled', function(done) { + hooks.pre('cook', function(done) { + done(new Error('fail')); + }); + + hooks.post('cook', function(error, res, callback) { + callback(new Error('another error occurred')); + }); + + var args = []; + args.push(function(error) { + assert.equal(error.message, 'another error occurred'); + done(); + }); + + hooks.wrap( + 'cook', + function(callback) { + assert.ok(false); + callback(); + }, + null, + args, + { useErrorHandlers: true, numCallbackParams: 1 }); + }); + + it('error handlers with no callback', function(done) { + hooks.pre('cook', function(done) { + done(new Error('fail')); + }); + + hooks.post('cook', function(error, callback) { + assert.equal(error.message, 'fail'); + done(); + }); + + var args = []; + + hooks.wrap( + 'cook', + function(callback) { + assert.ok(false); + callback(); + }, + null, + args, + { useErrorHandlers: true }); + }); + + it('error handlers with no error', function(done) { + hooks.post('cook', function(error, callback) { + callback(new Error('another error occurred')); + }); + + var args = []; + args.push(function(error) { + assert.ifError(error); + done(); + }); + + hooks.wrap( + 'cook', + function(callback) { + callback(); + }, + null, + args, + { useErrorHandlers: true }); + }); + + it('works with no args', function(done) { + hooks.pre('cook', function(done) { + done(); + }); + + hooks.post('cook', function(callback) { + obj.tofu = 'no'; + callback(); + }); + + var obj = { bacon: 0, eggs: 0 }; + + var args = []; + + hooks.wrap( + 'cook', + function(callback) { + callback(null); + }, + obj, + args); + + setTimeout( + function() { + assert.equal('no', obj.tofu); + done(); + }, + 25); + }); + + it('handles pre errors with no args', function(done) { + hooks.pre('cook', function(done) { + done('error!'); + }); + + hooks.post('cook', function(callback) { + obj.tofu = 'no'; + callback(); + }); + + var obj = { bacon: 0, eggs: 0 }; + + var args = []; + + hooks.wrap( + 'cook', + function(callback) { + callback(null); + }, + obj, + args); + + setTimeout( + function() { + assert.equal(undefined, obj.tofu); + done(); + }, + 25); + }); + + it('handles wrapped function errors with no args', function(done) { + hooks.pre('cook', function(done) { + obj.waffles = false; + done(); + }); + + hooks.post('cook', function(callback) { + obj.tofu = 'no'; + callback(); + }); + + var obj = { bacon: 0, eggs: 0 }; + + var args = []; + + hooks.wrap( + 'cook', + function(callback) { + callback('error!'); + }, + obj, + args); + + setTimeout( + function() { + assert.equal(false, obj.waffles); + assert.equal(undefined, obj.tofu); + done(); + }, + 25); + }); + + it('handles post errors with no args', function(done) { + hooks.pre('cook', function(done) { + obj.waffles = false; + done(); + }); + + hooks.post('cook', function(callback) { + obj.tofu = 'no'; + callback('error!'); + }); + + var obj = { bacon: 0, eggs: 0 }; + + var args = []; + + hooks.wrap( + 'cook', + function(callback) { + callback(); + }, + obj, + args); + + setTimeout( + function() { + assert.equal(false, obj.waffles); + assert.equal('no', obj.tofu); + done(); + }, + 25); + }); + + it('sync wrappers', function() { + var calledPre = 0; + var calledFn = 0; + var calledPost = 0; + hooks.pre('cook', function() { + ++calledPre; + }); + + hooks.post('cook', function() { + ++calledPost; + }); + + var wrapper = hooks.createWrapperSync('cook', function() { ++calledFn; }); + + wrapper(); + + assert.equal(calledPre, 1); + assert.equal(calledFn, 1); + assert.equal(calledPost, 1); + }); +}); |