kareem 2.4.1 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE CHANGED
@@ -186,7 +186,7 @@ Apache License
186
186
  same "printed page" as the copyright notice for easier
187
187
  identification within third-party archives.
188
188
 
189
- Copyright {yyyy} {name of copyright owner}
189
+ Copyright 2014-2022 mongoosejs
190
190
 
191
191
  Licensed under the Apache License, Version 2.0 (the "License");
192
192
  you may not use this file except in compliance with the License.
package/index.js CHANGED
@@ -1,5 +1,8 @@
1
1
  'use strict';
2
2
 
3
+ /**
4
+ * Create a new instance
5
+ */
3
6
  function Kareem() {
4
7
  this._pres = new Map();
5
8
  this._posts = new Map();
@@ -21,19 +24,27 @@ Kareem.overwriteResult = function overwriteResult() {
21
24
  this.args = [...arguments];
22
25
  };
23
26
 
27
+ /**
28
+ * Execute all "pre" hooks for "name"
29
+ * @param {String} name The hook name to execute
30
+ * @param {*} context Overwrite the "this" for the hook
31
+ * @param {Array|Function} args Optional arguments or directly the callback
32
+ * @param {Function} [callback] The callback to call when executing all hooks are finished
33
+ * @returns {void}
34
+ */
24
35
  Kareem.prototype.execPre = function(name, context, args, callback) {
25
36
  if (arguments.length === 3) {
26
37
  callback = args;
27
38
  args = [];
28
39
  }
29
- var pres = this._pres.get(name) || [];
30
- var numPres = pres.length;
31
- var numAsyncPres = pres.numAsync || 0;
32
- var currentPre = 0;
33
- var asyncPresLeft = numAsyncPres;
34
- var done = false;
35
- var $args = args;
36
- var shouldSkipWrappedFunction = null;
40
+ const pres = this._pres.get(name) || [];
41
+ const numPres = pres.length;
42
+ const numAsyncPres = pres.numAsync || 0;
43
+ let currentPre = 0;
44
+ let asyncPresLeft = numAsyncPres;
45
+ let done = false;
46
+ const $args = args;
47
+ let shouldSkipWrappedFunction = null;
37
48
 
38
49
  if (!numPres) {
39
50
  return nextTick(function() {
@@ -41,14 +52,14 @@ Kareem.prototype.execPre = function(name, context, args, callback) {
41
52
  });
42
53
  }
43
54
 
44
- var next = function() {
55
+ function next() {
45
56
  if (currentPre >= numPres) {
46
57
  return;
47
58
  }
48
- var pre = pres[currentPre];
59
+ const pre = pres[currentPre];
49
60
 
50
61
  if (pre.isAsync) {
51
- var args = [
62
+ const args = [
52
63
  decorateNextFn(_next),
53
64
  decorateNextFn(function(error) {
54
65
  if (error) {
@@ -70,9 +81,9 @@ Kareem.prototype.execPre = function(name, context, args, callback) {
70
81
 
71
82
  callMiddlewareFunction(pre.fn, context, args, args[0]);
72
83
  } else if (pre.fn.length > 0) {
73
- var args = [decorateNextFn(_next)];
74
- var _args = arguments.length >= 2 ? arguments : [null].concat($args);
75
- for (var i = 1; i < _args.length; ++i) {
84
+ const args = [decorateNextFn(_next)];
85
+ const _args = arguments.length >= 2 ? arguments : [null].concat($args);
86
+ for (let i = 1; i < _args.length; ++i) {
76
87
  args.push(_args[i]);
77
88
  }
78
89
 
@@ -103,7 +114,7 @@ Kareem.prototype.execPre = function(name, context, args, callback) {
103
114
  next();
104
115
  }
105
116
  }
106
- };
117
+ }
107
118
 
108
119
  next.apply(null, [null].concat(args));
109
120
 
@@ -133,25 +144,41 @@ Kareem.prototype.execPre = function(name, context, args, callback) {
133
144
  }
134
145
  };
135
146
 
147
+ /**
148
+ * Execute all "pre" hooks for "name" synchronously
149
+ * @param {String} name The hook name to execute
150
+ * @param {*} context Overwrite the "this" for the hook
151
+ * @param {Array} [args] Apply custom arguments to the hook
152
+ * @returns {void}
153
+ */
136
154
  Kareem.prototype.execPreSync = function(name, context, args) {
137
- var pres = this._pres.get(name) || [];
138
- var numPres = pres.length;
155
+ const pres = this._pres.get(name) || [];
156
+ const numPres = pres.length;
139
157
 
140
- for (var i = 0; i < numPres; ++i) {
158
+ for (let i = 0; i < numPres; ++i) {
141
159
  pres[i].fn.apply(context, args || []);
142
160
  }
143
161
  };
144
162
 
163
+ /**
164
+ * Execute all "post" hooks for "name"
165
+ * @param {String} name The hook name to execute
166
+ * @param {*} context Overwrite the "this" for the hook
167
+ * @param {Array|Function} args Apply custom arguments to the hook
168
+ * @param {*} options Optional options or directly the callback
169
+ * @param {Function} [callback] The callback to call when executing all hooks are finished
170
+ * @returns {void}
171
+ */
145
172
  Kareem.prototype.execPost = function(name, context, args, options, callback) {
146
173
  if (arguments.length < 5) {
147
174
  callback = options;
148
175
  options = null;
149
176
  }
150
- var posts = this._posts.get(name) || [];
151
- var numPosts = posts.length;
152
- var currentPost = 0;
177
+ const posts = this._posts.get(name) || [];
178
+ const numPosts = posts.length;
179
+ let currentPost = 0;
153
180
 
154
- var firstError = null;
181
+ let firstError = null;
155
182
  if (options && options.error) {
156
183
  firstError = options.error;
157
184
  }
@@ -162,12 +189,12 @@ Kareem.prototype.execPost = function(name, context, args, options, callback) {
162
189
  });
163
190
  }
164
191
 
165
- var next = function() {
166
- var post = posts[currentPost].fn;
167
- var numArgs = 0;
168
- var argLength = args.length;
169
- var newArgs = [];
170
- for (var i = 0; i < argLength; ++i) {
192
+ function next() {
193
+ const post = posts[currentPost].fn;
194
+ let numArgs = 0;
195
+ const argLength = args.length;
196
+ const newArgs = [];
197
+ for (let i = 0; i < argLength; ++i) {
171
198
  numArgs += args[i] && args[i]._kareemIgnore ? 0 : 1;
172
199
  if (!args[i] || !args[i]._kareemIgnore) {
173
200
  newArgs.push(args[i]);
@@ -175,7 +202,7 @@ Kareem.prototype.execPost = function(name, context, args, options, callback) {
175
202
  }
176
203
 
177
204
  if (firstError) {
178
- if (post.length === numArgs + 2) {
205
+ if (isErrorHandlingMiddleware(posts[currentPost], numArgs)) {
179
206
  const _cb = decorateNextFn(function(error) {
180
207
  if (error) {
181
208
  if (error instanceof Kareem.overwriteResult) {
@@ -222,7 +249,7 @@ Kareem.prototype.execPost = function(name, context, args, options, callback) {
222
249
  next();
223
250
  });
224
251
 
225
- if (post.length === numArgs + 2) {
252
+ if (isErrorHandlingMiddleware(posts[currentPost], numArgs)) {
226
253
  // Skip error handlers if no error
227
254
  if (++currentPost >= numPosts) {
228
255
  return callback.apply(null, [null].concat(args));
@@ -261,11 +288,18 @@ Kareem.prototype.execPost = function(name, context, args, options, callback) {
261
288
  next();
262
289
  }
263
290
  }
264
- };
291
+ }
265
292
 
266
293
  next();
267
294
  };
268
295
 
296
+ /**
297
+ * Execute all "post" hooks for "name" synchronously
298
+ * @param {String} name The hook name to execute
299
+ * @param {*} context Overwrite the "this" for the hook
300
+ * @param {Array|Function} args Apply custom arguments to the hook
301
+ * @returns {Array} The used arguments
302
+ */
269
303
  Kareem.prototype.execPostSync = function(name, context, args) {
270
304
  const posts = this._posts.get(name) || [];
271
305
  const numPosts = posts.length;
@@ -280,14 +314,20 @@ Kareem.prototype.execPostSync = function(name, context, args) {
280
314
  return args;
281
315
  };
282
316
 
317
+ /**
318
+ * Create a synchronous wrapper for "fn"
319
+ * @param {String} name The name of the hook
320
+ * @param {Function} fn The function to wrap
321
+ * @returns {Function} The wrapped function
322
+ */
283
323
  Kareem.prototype.createWrapperSync = function(name, fn) {
284
- var kareem = this;
324
+ const _this = this;
285
325
  return function syncWrapper() {
286
- kareem.execPreSync(name, this, arguments);
326
+ _this.execPreSync(name, this, arguments);
287
327
 
288
- var toReturn = fn.apply(this, arguments);
328
+ const toReturn = fn.apply(this, arguments);
289
329
 
290
- const result = kareem.execPostSync(name, this, [toReturn]);
330
+ const result = _this.execPostSync(name, this, [toReturn]);
291
331
 
292
332
  return result[0];
293
333
  };
@@ -303,9 +343,19 @@ function _handleWrapError(instance, error, name, context, args, options, callbac
303
343
  }
304
344
  }
305
345
 
346
+ /**
347
+ * Executes pre hooks, followed by the wrapped function, followed by post hooks.
348
+ * @param {String} name The name of the hook
349
+ * @param {Function} fn The function for the hook
350
+ * @param {*} context Overwrite the "this" for the hook
351
+ * @param {Array} args Apply custom arguments to the hook
352
+ * @param {Object} [options]
353
+ * @param {Boolean} [options.checkForPromise]
354
+ * @returns {void}
355
+ */
306
356
  Kareem.prototype.wrap = function(name, fn, context, args, options) {
307
357
  const lastArg = (args.length > 0 ? args[args.length - 1] : null);
308
- let argsWithoutCb = Array.from(args);
358
+ const argsWithoutCb = Array.from(args);
309
359
  typeof lastArg === 'function' && argsWithoutCb.pop();
310
360
  const _this = this;
311
361
 
@@ -316,7 +366,7 @@ Kareem.prototype.wrap = function(name, fn, context, args, options) {
316
366
  if (error && !(error instanceof Kareem.skipWrappedFunction)) {
317
367
  const numCallbackParams = options.numCallbackParams || 0;
318
368
  const errorArgs = options.contextParameter ? [context] : [];
319
- for (var i = errorArgs.length; i < numCallbackParams; ++i) {
369
+ for (let i = errorArgs.length; i < numCallbackParams; ++i) {
320
370
  errorArgs.push(null);
321
371
  }
322
372
  return _handleWrapError(_this, error, name, context, errorArgs,
@@ -377,6 +427,11 @@ Kareem.prototype.wrap = function(name, fn, context, args, options) {
377
427
  });
378
428
  };
379
429
 
430
+ /**
431
+ * Filter current instance for something specific and return the filtered clone
432
+ * @param {Function} fn The filter function
433
+ * @returns {Kareem} The cloned and filtered instance
434
+ */
380
435
  Kareem.prototype.filter = function(fn) {
381
436
  const clone = this.clone();
382
437
 
@@ -413,12 +468,25 @@ Kareem.prototype.filter = function(fn) {
413
468
  return clone;
414
469
  };
415
470
 
471
+ /**
472
+ * Check for a "name" to exist either in pre or post hooks
473
+ * @param {String} name The name of the hook
474
+ * @returns {Boolean} "true" if found, "false" otherwise
475
+ */
416
476
  Kareem.prototype.hasHooks = function(name) {
417
477
  return this._pres.has(name) || this._posts.has(name);
418
478
  };
419
479
 
480
+ /**
481
+ * Create a Wrapper for "fn" on "name" and return the wrapped function
482
+ * @param {String} name The name of the hook
483
+ * @param {Function} fn The function to wrap
484
+ * @param {*} context Overwrite the "this" for the hook
485
+ * @param {Object} [options]
486
+ * @returns {Function} The wrapped function
487
+ */
420
488
  Kareem.prototype.createWrapper = function(name, fn, context, options) {
421
- var _this = this;
489
+ const _this = this;
422
490
  if (!this.hasHooks(name)) {
423
491
  // Fast path: if there's no hooks for this function, just return the
424
492
  // function wrapped in a nextTick()
@@ -427,11 +495,20 @@ Kareem.prototype.createWrapper = function(name, fn, context, options) {
427
495
  };
428
496
  }
429
497
  return function() {
430
- var _context = context || this;
498
+ const _context = context || this;
431
499
  _this.wrap(name, fn, _context, Array.from(arguments), options);
432
500
  };
433
501
  };
434
502
 
503
+ /**
504
+ * Register a new hook for "pre"
505
+ * @param {String} name The name of the hook
506
+ * @param {Boolean} [isAsync]
507
+ * @param {Function} fn The function to register for "name"
508
+ * @param {never} error Unused
509
+ * @param {Boolean} [unshift] Wheter to "push" or to "unshift" the new hook
510
+ * @returns {Kareem}
511
+ */
435
512
  Kareem.prototype.pre = function(name, isAsync, fn, error, unshift) {
436
513
  let options = {};
437
514
  if (typeof isAsync === 'object' && isAsync !== null) {
@@ -463,8 +540,16 @@ Kareem.prototype.pre = function(name, isAsync, fn, error, unshift) {
463
540
  return this;
464
541
  };
465
542
 
543
+ /**
544
+ * Register a new hook for "post"
545
+ * @param {String} name The name of the hook
546
+ * @param {Object} [options]
547
+ * @param {Function} fn The function to register for "name"
548
+ * @param {Boolean} [unshift] Wheter to "push" or to "unshift" the new hook
549
+ * @returns {Kareem}
550
+ */
466
551
  Kareem.prototype.post = function(name, options, fn, unshift) {
467
- const hooks = this._posts.get(name) || [];
552
+ const posts = this._posts.get(name) || [];
468
553
 
469
554
  if (typeof options === 'function') {
470
555
  unshift = !!fn;
@@ -477,34 +562,44 @@ Kareem.prototype.post = function(name, options, fn, unshift) {
477
562
  }
478
563
 
479
564
  if (unshift) {
480
- hooks.unshift(Object.assign({}, options, { fn: fn }));
565
+ posts.unshift(Object.assign({}, options, { fn: fn }));
481
566
  } else {
482
- hooks.push(Object.assign({}, options, { fn: fn }));
567
+ posts.push(Object.assign({}, options, { fn: fn }));
483
568
  }
484
- this._posts.set(name, hooks);
569
+ this._posts.set(name, posts);
485
570
  return this;
486
571
  };
487
572
 
573
+ /**
574
+ * Clone the current instance
575
+ * @returns {Kareem} The cloned instance
576
+ */
488
577
  Kareem.prototype.clone = function() {
489
578
  const n = new Kareem();
490
579
 
491
- for (let key of this._pres.keys()) {
580
+ for (const key of this._pres.keys()) {
492
581
  const clone = this._pres.get(key).slice();
493
582
  clone.numAsync = this._pres.get(key).numAsync;
494
583
  n._pres.set(key, clone);
495
584
  }
496
- for (let key of this._posts.keys()) {
585
+ for (const key of this._posts.keys()) {
497
586
  n._posts.set(key, this._posts.get(key).slice());
498
587
  }
499
588
 
500
589
  return n;
501
590
  };
502
591
 
592
+ /**
593
+ * Merge "other" into self or "clone"
594
+ * @param {Kareem} other The instance to merge with
595
+ * @param {Kareem} [clone] The instance to merge onto (if not defined, using "this")
596
+ * @returns {Kareem} The merged instance
597
+ */
503
598
  Kareem.prototype.merge = function(other, clone) {
504
599
  clone = arguments.length === 1 ? true : clone;
505
- var ret = clone ? this.clone() : this;
600
+ const ret = clone ? this.clone() : this;
506
601
 
507
- for (let key of other._pres.keys()) {
602
+ for (const key of other._pres.keys()) {
508
603
  const sourcePres = ret._pres.get(key) || [];
509
604
  const deduplicated = other._pres.get(key).
510
605
  // Deduplicate based on `fn`
@@ -514,7 +609,7 @@ Kareem.prototype.merge = function(other, clone) {
514
609
  combined.numAsync += deduplicated.filter(p => p.isAsync).length;
515
610
  ret._pres.set(key, combined);
516
611
  }
517
- for (let key of other._posts.keys()) {
612
+ for (const key of other._posts.keys()) {
518
613
  const sourcePosts = ret._posts.get(key) || [];
519
614
  const deduplicated = other._posts.get(key).
520
615
  filter(p => sourcePosts.indexOf(p) === -1);
@@ -542,8 +637,8 @@ function isPromiseLike(v) {
542
637
  }
543
638
 
544
639
  function decorateNextFn(fn) {
545
- var called = false;
546
- var _this = this;
640
+ let called = false;
641
+ const _this = this;
547
642
  return function() {
548
643
  // Ensure this function can only be called once
549
644
  if (called) {
@@ -556,8 +651,15 @@ function decorateNextFn(fn) {
556
651
  };
557
652
  }
558
653
 
559
- const nextTick = typeof process === 'object' && process !== null && process.nextTick || function nextTick(cb) {
560
- setTimeout(cb, 0);
654
+ const nextTick = typeof process === 'object' && process !== null && process.nextTick || function nextTick(cb) {
655
+ setTimeout(cb, 0);
561
656
  };
562
657
 
658
+ function isErrorHandlingMiddleware(post, numArgs) {
659
+ if (post.errorHandler) {
660
+ return true;
661
+ }
662
+ return post.fn.length === numArgs + 2;
663
+ }
664
+
563
665
  module.exports = Kareem;
package/package.json CHANGED
@@ -1,25 +1,31 @@
1
1
  {
2
2
  "name": "kareem",
3
- "version": "2.4.1",
3
+ "version": "2.5.0",
4
4
  "description": "Next-generation take on pre/post function hooks",
5
5
  "main": "index.js",
6
6
  "scripts": {
7
7
  "lint": "eslint .",
8
8
  "test": "mocha ./test/*",
9
- "test-travis": "nyc mocha ./test/*"
9
+ "test-coverage": "nyc --reporter lcov mocha ./test/*",
10
+ "docs": "node ./docs.js"
10
11
  },
11
12
  "repository": {
12
13
  "type": "git",
13
14
  "url": "git://github.com/vkarpov15/kareem.git"
14
15
  },
15
16
  "devDependencies": {
16
- "@masteringjs/eslint-config": "0.0.1",
17
17
  "acquit": "1.x",
18
- "acquit-ignore": "0.1.x",
19
- "eslint": "8.15.0",
18
+ "acquit-ignore": "0.2.x",
19
+ "eslint": "8.20.0",
20
20
  "mocha": "9.2.0",
21
21
  "nyc": "15.1.0"
22
22
  },
23
23
  "author": "Valeri Karpov <val@karpov.io>",
24
- "license": "Apache-2.0"
24
+ "license": "Apache-2.0",
25
+ "files": [
26
+ "index.js"
27
+ ],
28
+ "engines": {
29
+ "node": ">=12.0.0"
30
+ }
25
31
  }
package/.eslintrc.json DELETED
@@ -1,16 +0,0 @@
1
- {
2
- "extends": [
3
- "@masteringjs"
4
- ],
5
- "parserOptions": {
6
- "ecmaVersion": 2020
7
- },
8
- "env": {
9
- "node": true,
10
- "es6": true
11
- },
12
- "rules": {
13
- "no-var": "off",
14
- "prefer-const": "off"
15
- }
16
- }
@@ -1,47 +0,0 @@
1
- name: Test
2
- on:
3
- pull_request:
4
- push:
5
- permissions:
6
- contents: read
7
-
8
- jobs:
9
- test:
10
- runs-on: ${{ matrix.os }}
11
- strategy:
12
- fail-fast: false
13
- matrix:
14
- node: [12, 14, 16, 18]
15
- os: [ubuntu-20.04]
16
- name: Node ${{ matrix.node }}
17
- steps:
18
- - uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 # v3
19
-
20
- - name: Setup node
21
- uses: actions/setup-node@5b52f097d36d4b0b2f94ed6de710023fbb8b2236 # v3.1.0
22
- with:
23
- node-version: ${{ matrix.node }}
24
-
25
- - run: npm install
26
-
27
- - run: npm test
28
-
29
- lint:
30
- runs-on: ${{ matrix.os }}
31
- strategy:
32
- fail-fast: false
33
- matrix:
34
- node: [18]
35
- os: [ubuntu-20.04]
36
- name: Lint
37
- steps:
38
- - uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 # v3
39
-
40
- - name: Setup node
41
- uses: actions/setup-node@5b52f097d36d4b0b2f94ed6de710023fbb8b2236 # v3.1.0
42
- with:
43
- node-version: ${{ matrix.node }}
44
-
45
- - run: npm install
46
-
47
- - run: npm run lint
package/.travis.yml DELETED
@@ -1,12 +0,0 @@
1
- language: node_js
2
- node_js:
3
- - "12"
4
- - "10"
5
- - "9"
6
- - "8"
7
- - "7"
8
- - "6"
9
- - "5"
10
- - "4"
11
- script: "npm run-script test-travis"
12
- after_script: "npm install coveralls@2.10.0 && cat ./coverage/lcov.info | coveralls"