kareem 2.6.3 → 3.1.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/index.js CHANGED
@@ -24,127 +24,74 @@ Kareem.overwriteResult = function overwriteResult() {
24
24
  this.args = [...arguments];
25
25
  };
26
26
 
27
+ Kareem.overwriteArguments = function overwriteArguments() {
28
+ if (!(this instanceof Kareem.overwriteArguments)) {
29
+ return new Kareem.overwriteArguments(...arguments);
30
+ }
31
+
32
+ this.args = [...arguments];
33
+ };
34
+
27
35
  /**
28
36
  * Execute all "pre" hooks for "name"
29
37
  * @param {String} name The hook name to execute
30
38
  * @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}
39
+ * @param {Array} args arguments passed to the pre hooks
40
+ * @param {Object} [options] Optional options
41
+ * @param {Function} [options.filter] Filter function to select which hooks to run
42
+ * @returns {Array} The potentially modified arguments
34
43
  */
35
- Kareem.prototype.execPre = function(name, context, args, callback) {
36
- if (arguments.length === 3) {
37
- callback = args;
38
- args = [];
44
+ Kareem.prototype.execPre = async function execPre(name, context, args, options) {
45
+ let pres = this._pres.get(name) || [];
46
+ if (options?.filter) {
47
+ pres = pres.filter(options.filter);
39
48
  }
40
- const pres = this._pres.get(name) || [];
41
49
  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;
50
+ let $args = args;
51
+ let skipWrappedFunction = null;
48
52
 
49
53
  if (!numPres) {
50
- return nextTick(function() {
51
- callback(null);
52
- });
54
+ return $args;
53
55
  }
54
56
 
55
- function next() {
56
- if (currentPre >= numPres) {
57
- return;
58
- }
59
- const pre = pres[currentPre];
60
-
61
- if (pre.isAsync) {
62
- const args = [
63
- decorateNextFn(_next),
64
- decorateNextFn(function(error) {
65
- if (error) {
66
- if (done) {
67
- return;
68
- }
69
- if (error instanceof Kareem.skipWrappedFunction) {
70
- shouldSkipWrappedFunction = error;
71
- } else {
72
- done = true;
73
- return callback(error);
74
- }
75
- }
76
- if (--asyncPresLeft === 0 && currentPre >= numPres) {
77
- return callback(shouldSkipWrappedFunction);
78
- }
79
- })
80
- ];
81
-
82
- callMiddlewareFunction(pre.fn, context, args, args[0]);
83
- } else if (pre.fn.length > 0) {
84
- const args = [decorateNextFn(_next)];
85
- const _args = arguments.length >= 2 ? arguments : [null].concat($args);
86
- for (let i = 1; i < _args.length; ++i) {
87
- if (i === _args.length - 1 && typeof _args[i] === 'function') {
88
- continue; // skip callbacks to avoid accidentally calling the callback from a hook
89
- }
90
- args.push(_args[i]);
91
- }
92
-
93
- callMiddlewareFunction(pre.fn, context, args, args[0]);
94
- } else {
95
- let maybePromiseLike = null;
96
- try {
97
- maybePromiseLike = pre.fn.call(context);
98
- } catch (err) {
99
- if (err != null) {
100
- return callback(err);
101
- }
57
+ for (const pre of pres) {
58
+ const args = [];
59
+ const _args = [null].concat($args);
60
+ for (let i = 1; i < _args.length; ++i) {
61
+ if (i === _args.length - 1 && typeof _args[i] === 'function') {
62
+ continue; // skip callbacks to avoid accidentally calling the callback from a hook
102
63
  }
64
+ args.push(_args[i]);
65
+ }
103
66
 
67
+ try {
68
+ const maybePromiseLike = pre.fn.apply(context, args);
104
69
  if (isPromiseLike(maybePromiseLike)) {
105
- maybePromiseLike.then(() => _next(), err => _next(err));
106
- } else {
107
- if (++currentPre >= numPres) {
108
- if (asyncPresLeft > 0) {
109
- // Leave parallel hooks to run
110
- return;
111
- } else {
112
- return nextTick(function() {
113
- callback(shouldSkipWrappedFunction);
114
- });
115
- }
70
+ const result = await maybePromiseLike;
71
+ if (result instanceof Kareem.overwriteArguments) {
72
+ $args = result.args;
116
73
  }
117
- next();
118
- }
119
- }
120
- }
121
-
122
- next.apply(null, [null].concat(args));
123
-
124
- function _next(error) {
125
- if (error) {
126
- if (done) {
127
- return;
74
+ } else if (maybePromiseLike instanceof Kareem.overwriteArguments) {
75
+ $args = maybePromiseLike.args;
128
76
  }
77
+ } catch (error) {
129
78
  if (error instanceof Kareem.skipWrappedFunction) {
130
- shouldSkipWrappedFunction = error;
131
- } else {
132
- done = true;
133
- return callback(error);
79
+ skipWrappedFunction = error;
80
+ continue;
134
81
  }
135
- }
136
-
137
- if (++currentPre >= numPres) {
138
- if (asyncPresLeft > 0) {
139
- // Leave parallel hooks to run
140
- return;
141
- } else {
142
- return callback(shouldSkipWrappedFunction);
82
+ if (error instanceof Kareem.overwriteArguments) {
83
+ $args = error.args;
84
+ continue;
143
85
  }
86
+ throw error;
144
87
  }
88
+ }
145
89
 
146
- next.apply(context, arguments);
90
+ if (skipWrappedFunction) {
91
+ throw skipWrappedFunction;
147
92
  }
93
+
94
+ return $args;
148
95
  };
149
96
 
150
97
  /**
@@ -152,34 +99,39 @@ Kareem.prototype.execPre = function(name, context, args, callback) {
152
99
  * @param {String} name The hook name to execute
153
100
  * @param {*} context Overwrite the "this" for the hook
154
101
  * @param {Array} [args] Apply custom arguments to the hook
155
- * @returns {void}
102
+ * @returns {Array} The potentially modified arguments
156
103
  */
157
104
  Kareem.prototype.execPreSync = function(name, context, args) {
158
105
  const pres = this._pres.get(name) || [];
159
106
  const numPres = pres.length;
107
+ let $args = args || [];
160
108
 
161
109
  for (let i = 0; i < numPres; ++i) {
162
- pres[i].fn.apply(context, args || []);
110
+ const result = pres[i].fn.apply(context, $args);
111
+ if (result instanceof Kareem.overwriteArguments) {
112
+ $args = result.args;
113
+ }
163
114
  }
115
+
116
+ return $args;
164
117
  };
165
118
 
166
119
  /**
167
120
  * Execute all "post" hooks for "name"
168
121
  * @param {String} name The hook name to execute
169
122
  * @param {*} context Overwrite the "this" for the hook
170
- * @param {Array|Function} args Apply custom arguments to the hook
171
- * @param {*} options Optional options or directly the callback
172
- * @param {Function} [callback] The callback to call when executing all hooks are finished
123
+ * @param {Array} args Apply custom arguments to the hook
124
+ * @param {Object} [options] Optional options
125
+ * @param {Error} [options.error] Error to pass to error-handling middleware
126
+ * @param {Function} [options.filter] Filter function to select which hooks to run
173
127
  * @returns {void}
174
128
  */
175
- Kareem.prototype.execPost = function(name, context, args, options, callback) {
176
- if (arguments.length < 5) {
177
- callback = options;
178
- options = null;
129
+ Kareem.prototype.execPost = async function execPost(name, context, args, options) {
130
+ let posts = this._posts.get(name) || [];
131
+ if (options?.filter) {
132
+ posts = posts.filter(options.filter);
179
133
  }
180
- const posts = this._posts.get(name) || [];
181
134
  const numPosts = posts.length;
182
- let currentPost = 0;
183
135
 
184
136
  let firstError = null;
185
137
  if (options && options.error) {
@@ -187,120 +139,108 @@ Kareem.prototype.execPost = function(name, context, args, options, callback) {
187
139
  }
188
140
 
189
141
  if (!numPosts) {
190
- return nextTick(function() {
191
- callback.apply(null, [firstError].concat(args));
192
- });
142
+ if (firstError != null) {
143
+ throw firstError;
144
+ }
145
+ return args;
193
146
  }
194
147
 
195
- function next() {
196
- const post = posts[currentPost].fn;
148
+ for (const currentPost of posts) {
149
+ const post = currentPost.fn;
197
150
  let numArgs = 0;
198
- const argLength = args.length;
199
151
  const newArgs = [];
152
+ const argLength = args.length;
200
153
  for (let i = 0; i < argLength; ++i) {
201
- numArgs += args[i] && args[i]._kareemIgnore ? 0 : 1;
202
154
  if (!args[i] || !args[i]._kareemIgnore) {
155
+ numArgs += 1;
203
156
  newArgs.push(args[i]);
204
157
  }
205
158
  }
159
+ // If numCallbackParams set, fill in the rest with null to enforce consistent number of args
160
+ if (options?.numCallbackParams != null) {
161
+ numArgs = options.numCallbackParams;
162
+ for (let i = newArgs.length; i < numArgs; ++i) {
163
+ newArgs.push(null);
164
+ }
165
+ }
206
166
 
207
- if (firstError) {
208
- if (isErrorHandlingMiddleware(posts[currentPost], numArgs)) {
209
- const _cb = decorateNextFn(function(error) {
210
- if (error) {
211
- if (error instanceof Kareem.overwriteResult) {
212
- args = error.args;
213
- if (++currentPost >= numPosts) {
214
- return callback.call(null, firstError);
215
- }
216
- return next();
217
- }
218
- firstError = error;
219
- }
220
- if (++currentPost >= numPosts) {
221
- return callback.call(null, firstError);
222
- }
223
- next();
224
- });
225
-
226
- callMiddlewareFunction(post, context,
227
- [firstError].concat(newArgs).concat([_cb]), _cb);
167
+ let resolve;
168
+ let reject;
169
+ const cbPromise = new Promise((_resolve, _reject) => {
170
+ resolve = _resolve;
171
+ reject = _reject;
172
+ });
173
+ newArgs.push(function nextCallback(err) {
174
+ if (err) {
175
+ reject(err);
228
176
  } else {
229
- if (++currentPost >= numPosts) {
230
- return callback.call(null, firstError);
231
- }
232
- next();
177
+ resolve();
233
178
  }
234
- } else {
235
- const _cb = decorateNextFn(function(error) {
236
- if (error) {
179
+ });
180
+
181
+ if (firstError) {
182
+ if (isErrorHandlingMiddleware(currentPost, numArgs)) {
183
+ try {
184
+ const res = post.apply(context, [firstError].concat(newArgs));
185
+ if (isPromiseLike(res)) {
186
+ await res;
187
+ } else if (post.length === numArgs + 2) {
188
+ // `numArgs + 2` because we added the error and the callback
189
+ await cbPromise;
190
+ }
191
+ } catch (error) {
237
192
  if (error instanceof Kareem.overwriteResult) {
238
193
  args = error.args;
239
- if (++currentPost >= numPosts) {
240
- return callback.apply(null, [null].concat(args));
241
- }
242
- return next();
194
+ continue;
243
195
  }
244
196
  firstError = error;
245
- return next();
246
197
  }
247
-
248
- if (++currentPost >= numPosts) {
249
- return callback.apply(null, [null].concat(args));
250
- }
251
-
252
- next();
253
- });
254
-
255
- if (isErrorHandlingMiddleware(posts[currentPost], numArgs)) {
256
- // Skip error handlers if no error
257
- if (++currentPost >= numPosts) {
258
- return callback.apply(null, [null].concat(args));
259
- }
260
- return next();
198
+ } else {
199
+ continue;
261
200
  }
262
- if (post.length === numArgs + 1) {
263
- callMiddlewareFunction(post, context, newArgs.concat([_cb]), _cb);
201
+ } else {
202
+ if (isErrorHandlingMiddleware(currentPost, numArgs)) {
203
+ // Skip error handlers if no error
204
+ continue;
264
205
  } else {
265
- let error;
266
- let maybePromiseLike;
206
+ let res = null;
267
207
  try {
268
- maybePromiseLike = post.apply(context, newArgs);
269
- } catch (err) {
270
- error = err;
271
- firstError = err;
272
- }
273
-
274
- if (isPromiseLike(maybePromiseLike)) {
275
- return maybePromiseLike.then(
276
- (res) => {
277
- _cb(res instanceof Kareem.overwriteResult ? res : null);
278
- },
279
- err => _cb(err)
280
- );
281
- }
282
-
283
- if (maybePromiseLike instanceof Kareem.overwriteResult) {
284
- args = maybePromiseLike.args;
208
+ res = post.apply(context, newArgs);
209
+ if (isPromiseLike(res)) {
210
+ res = await res;
211
+ } else if (post.length === numArgs + 1) {
212
+ // If post function takes a callback, wait for the post function to call the callback
213
+ res = await cbPromise;
214
+ }
215
+ } catch (error) {
216
+ if (error instanceof Kareem.overwriteResult) {
217
+ args = error.args;
218
+ continue;
219
+ }
220
+ firstError = error;
221
+ continue;
285
222
  }
286
223
 
287
- if (++currentPost >= numPosts) {
288
- return callback.apply(null, [error].concat(args));
224
+ if (res instanceof Kareem.overwriteResult) {
225
+ args = res.args;
226
+ continue;
289
227
  }
290
-
291
- next();
292
228
  }
293
229
  }
294
230
  }
295
231
 
296
- next();
232
+ if (firstError != null) {
233
+ throw firstError;
234
+ }
235
+
236
+ return args;
297
237
  };
298
238
 
299
239
  /**
300
240
  * Execute all "post" hooks for "name" synchronously
301
241
  * @param {String} name The hook name to execute
302
242
  * @param {*} context Overwrite the "this" for the hook
303
- * @param {Array|Function} args Apply custom arguments to the hook
243
+ * @param {Array} args Apply custom arguments to the hook
304
244
  * @returns {Array} The used arguments
305
245
  */
306
246
  Kareem.prototype.execPostSync = function(name, context, args) {
@@ -326,9 +266,9 @@ Kareem.prototype.execPostSync = function(name, context, args) {
326
266
  Kareem.prototype.createWrapperSync = function(name, fn) {
327
267
  const _this = this;
328
268
  return function syncWrapper() {
329
- _this.execPreSync(name, this, arguments);
269
+ const modifiedArgs = _this.execPreSync(name, this, Array.from(arguments));
330
270
 
331
- const toReturn = fn.apply(this, arguments);
271
+ const toReturn = fn.apply(this, modifiedArgs);
332
272
 
333
273
  const result = _this.execPostSync(name, this, [toReturn]);
334
274
 
@@ -336,98 +276,37 @@ Kareem.prototype.createWrapperSync = function(name, fn) {
336
276
  };
337
277
  };
338
278
 
339
- function _handleWrapError(instance, error, name, context, args, options, callback) {
340
- if (options.useErrorHandlers) {
341
- return instance.execPost(name, context, args, { error: error }, function(error) {
342
- return typeof callback === 'function' && callback(error);
343
- });
344
- } else {
345
- return typeof callback === 'function' && callback(error);
346
- }
347
- }
348
-
349
279
  /**
350
280
  * Executes pre hooks, followed by the wrapped function, followed by post hooks.
351
281
  * @param {String} name The name of the hook
352
282
  * @param {Function} fn The function for the hook
353
283
  * @param {*} context Overwrite the "this" for the hook
354
284
  * @param {Array} args Apply custom arguments to the hook
355
- * @param {Object} [options]
356
- * @param {Boolean} [options.checkForPromise]
285
+ * @param {Object} options Additional options for the hook
357
286
  * @returns {void}
358
287
  */
359
- Kareem.prototype.wrap = function(name, fn, context, args, options) {
360
- const lastArg = (args.length > 0 ? args[args.length - 1] : null);
361
- const argsWithoutCb = Array.from(args);
362
- typeof lastArg === 'function' && argsWithoutCb.pop();
363
- const _this = this;
364
-
365
- options = options || {};
366
- const checkForPromise = options.checkForPromise;
367
-
368
- this.execPre(name, context, args, function(error) {
369
- if (error && !(error instanceof Kareem.skipWrappedFunction)) {
370
- const numCallbackParams = options.numCallbackParams || 0;
371
- const errorArgs = options.contextParameter ? [context] : [];
372
- for (let i = errorArgs.length; i < numCallbackParams; ++i) {
373
- errorArgs.push(null);
374
- }
375
- return _handleWrapError(_this, error, name, context, errorArgs,
376
- options, lastArg);
377
- }
378
-
379
- const numParameters = fn.length;
380
- let ret;
381
-
288
+ Kareem.prototype.wrap = async function wrap(name, fn, context, args, options) {
289
+ let ret;
290
+ let skipWrappedFunction = false;
291
+ let modifiedArgs = args;
292
+ try {
293
+ modifiedArgs = await this.execPre(name, context, args);
294
+ } catch (error) {
382
295
  if (error instanceof Kareem.skipWrappedFunction) {
383
- ret = error.args[0];
384
- return _cb(null, ...error.args);
296
+ ret = error.args;
297
+ skipWrappedFunction = true;
385
298
  } else {
386
- try {
387
- ret = fn.apply(context, argsWithoutCb.concat(_cb));
388
- } catch (err) {
389
- return _cb(err);
390
- }
299
+ await this.execPost(name, context, args, { ...options, error });
391
300
  }
301
+ }
392
302
 
393
- if (checkForPromise) {
394
- if (isPromiseLike(ret)) {
395
- // Thenable, use it
396
- return ret.then(
397
- res => _cb(null, res),
398
- err => _cb(err)
399
- );
400
- }
303
+ if (!skipWrappedFunction) {
304
+ ret = await fn.apply(context, modifiedArgs);
305
+ }
401
306
 
402
- // If `fn()` doesn't have a callback argument and doesn't return a
403
- // promise, assume it is sync
404
- if (numParameters < argsWithoutCb.length + 1) {
405
- return _cb(null, ret);
406
- }
407
- }
307
+ ret = await this.execPost(name, context, [ret], options);
408
308
 
409
- function _cb() {
410
- const argsWithoutError = Array.from(arguments);
411
- argsWithoutError.shift();
412
- if (options.nullResultByDefault && argsWithoutError.length === 0) {
413
- argsWithoutError.push(null);
414
- }
415
- if (arguments[0]) {
416
- // Assume error
417
- return _handleWrapError(_this, arguments[0], name, context,
418
- argsWithoutError, options, lastArg);
419
- } else {
420
- _this.execPost(name, context, argsWithoutError, function() {
421
- if (lastArg === null) {
422
- return;
423
- }
424
- arguments[0]
425
- ? lastArg(arguments[0])
426
- : lastArg.apply(context, arguments);
427
- });
428
- }
429
- }
430
- });
309
+ return ret[0];
431
310
  };
432
311
 
433
312
  /**
@@ -449,8 +328,6 @@ Kareem.prototype.filter = function(fn) {
449
328
  continue;
450
329
  }
451
330
 
452
- hooks.numAsync = hooks.filter(h => h.isAsync).length;
453
-
454
331
  clone._pres.set(name, hooks);
455
332
  }
456
333
 
@@ -491,53 +368,43 @@ Kareem.prototype.hasHooks = function(name) {
491
368
  Kareem.prototype.createWrapper = function(name, fn, context, options) {
492
369
  const _this = this;
493
370
  if (!this.hasHooks(name)) {
494
- // Fast path: if there's no hooks for this function, just return the
495
- // function wrapped in a nextTick()
496
- return function() {
497
- nextTick(() => fn.apply(this, arguments));
498
- };
371
+ // Fast path: if there's no hooks for this function, just return the function
372
+ return fn;
499
373
  }
500
- return function() {
374
+ return function kareemWrappedFunction() {
501
375
  const _context = context || this;
502
- _this.wrap(name, fn, _context, Array.from(arguments), options);
376
+ return _this.wrap(name, fn, _context, Array.from(arguments), options);
503
377
  };
504
378
  };
505
379
 
506
380
  /**
507
381
  * Register a new hook for "pre"
508
382
  * @param {String} name The name of the hook
509
- * @param {Boolean} [isAsync]
383
+ * @param {Object} [options]
510
384
  * @param {Function} fn The function to register for "name"
511
385
  * @param {never} error Unused
512
386
  * @param {Boolean} [unshift] Wheter to "push" or to "unshift" the new hook
513
387
  * @returns {Kareem}
514
388
  */
515
- Kareem.prototype.pre = function(name, isAsync, fn, error, unshift) {
516
- let options = {};
517
- if (typeof isAsync === 'object' && isAsync !== null) {
518
- options = isAsync;
519
- isAsync = options.isAsync;
520
- } else if (typeof arguments[1] !== 'boolean') {
521
- fn = isAsync;
522
- isAsync = false;
389
+ Kareem.prototype.pre = function(name, options, fn, error, unshift) {
390
+ if (typeof options === 'function') {
391
+ fn = options;
392
+ options = {};
393
+ } else if (options == null) {
394
+ options = {};
523
395
  }
524
396
 
525
397
  const pres = this._pres.get(name) || [];
526
398
  this._pres.set(name, pres);
527
399
 
528
- if (isAsync) {
529
- pres.numAsync = pres.numAsync || 0;
530
- ++pres.numAsync;
531
- }
532
-
533
400
  if (typeof fn !== 'function') {
534
401
  throw new Error('pre() requires a function, got "' + typeof fn + '"');
535
402
  }
536
403
 
537
404
  if (unshift) {
538
- pres.unshift(Object.assign({}, options, { fn: fn, isAsync: isAsync }));
405
+ pres.unshift(Object.assign({}, options, { fn: fn }));
539
406
  } else {
540
- pres.push(Object.assign({}, options, { fn: fn, isAsync: isAsync }));
407
+ pres.push(Object.assign({}, options, { fn: fn }));
541
408
  }
542
409
 
543
410
  return this;
@@ -547,6 +414,7 @@ Kareem.prototype.pre = function(name, isAsync, fn, error, unshift) {
547
414
  * Register a new hook for "post"
548
415
  * @param {String} name The name of the hook
549
416
  * @param {Object} [options]
417
+ * @param {Boolean} [options.errorHandler] Whether this is an error handler
550
418
  * @param {Function} fn The function to register for "name"
551
419
  * @param {Boolean} [unshift] Wheter to "push" or to "unshift" the new hook
552
420
  * @returns {Kareem}
@@ -573,6 +441,24 @@ Kareem.prototype.post = function(name, options, fn, unshift) {
573
441
  return this;
574
442
  };
575
443
 
444
+ /**
445
+ * Register a new error handler for "name"
446
+ * @param {String} name The name of the hook
447
+ * @param {Object} [options]
448
+ * @param {Function} fn The function to register for "name"
449
+ * @param {Boolean} [unshift] Wheter to "push" or to "unshift" the new hook
450
+ * @returns {Kareem}
451
+ */
452
+
453
+ Kareem.prototype.postError = function postError(name, options, fn, unshift) {
454
+ if (typeof options === 'function') {
455
+ unshift = !!fn;
456
+ fn = options;
457
+ options = {};
458
+ }
459
+ return this.post(name, { ...options, errorHandler: true }, fn, unshift);
460
+ };
461
+
576
462
  /**
577
463
  * Clone the current instance
578
464
  * @returns {Kareem} The cloned instance
@@ -582,7 +468,6 @@ Kareem.prototype.clone = function() {
582
468
 
583
469
  for (const key of this._pres.keys()) {
584
470
  const clone = this._pres.get(key).slice();
585
- clone.numAsync = this._pres.get(key).numAsync;
586
471
  n._pres.set(key, clone);
587
472
  }
588
473
  for (const key of this._posts.keys()) {
@@ -608,8 +493,6 @@ Kareem.prototype.merge = function(other, clone) {
608
493
  // Deduplicate based on `fn`
609
494
  filter(p => sourcePres.map(_p => _p.fn).indexOf(p.fn) === -1);
610
495
  const combined = sourcePres.concat(deduplicated);
611
- combined.numAsync = sourcePres.numAsync || 0;
612
- combined.numAsync += deduplicated.filter(p => p.isAsync).length;
613
496
  ret._pres.set(key, combined);
614
497
  }
615
498
  for (const key of other._posts.keys()) {
@@ -622,42 +505,10 @@ Kareem.prototype.merge = function(other, clone) {
622
505
  return ret;
623
506
  };
624
507
 
625
- function callMiddlewareFunction(fn, context, args, next) {
626
- let maybePromiseLike;
627
- try {
628
- maybePromiseLike = fn.apply(context, args);
629
- } catch (error) {
630
- return next(error);
631
- }
632
-
633
- if (isPromiseLike(maybePromiseLike)) {
634
- maybePromiseLike.then(() => next(), err => next(err));
635
- }
636
- }
637
-
638
508
  function isPromiseLike(v) {
639
509
  return (typeof v === 'object' && v !== null && typeof v.then === 'function');
640
510
  }
641
511
 
642
- function decorateNextFn(fn) {
643
- let called = false;
644
- const _this = this;
645
- return function() {
646
- // Ensure this function can only be called once
647
- if (called) {
648
- return;
649
- }
650
- called = true;
651
- // Make sure to clear the stack so try/catch doesn't catch errors
652
- // in subsequent middleware
653
- return nextTick(() => fn.apply(_this, arguments));
654
- };
655
- }
656
-
657
- const nextTick = typeof process === 'object' && process !== null && process.nextTick || function nextTick(cb) {
658
- setTimeout(cb, 0);
659
- };
660
-
661
512
  function isErrorHandlingMiddleware(post, numArgs) {
662
513
  if (post.errorHandler) {
663
514
  return true;