kareem 2.2.3 → 2.3.3

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/docs.js CHANGED
@@ -1,5 +1,7 @@
1
1
  var acquit = require('acquit');
2
2
 
3
+ require('acquit-ignore')();
4
+
3
5
  var content = require('fs').readFileSync('./test/examples.test.js').toString();
4
6
  var blocks = acquit.parse(content);
5
7
 
@@ -29,7 +31,7 @@ for (var i = 0; i < blocks.length; ++i) {
29
31
  acquit.trimEachLine(it.comments[0]) + '\n\n' :
30
32
  '';
31
33
  mdOutput += '```javascript\n';
32
- mdOutput += ' ' + it.code + '\n';
34
+ mdOutput += it.code + '\n';
33
35
  mdOutput += '```\n\n';
34
36
  }
35
37
  }
package/index.js CHANGED
@@ -57,12 +57,13 @@ Kareem.prototype.execPre = function(name, context, args, callback) {
57
57
 
58
58
  callMiddlewareFunction(pre.fn, context, args, args[0]);
59
59
  } else {
60
- let error = null;
61
60
  let maybePromise = null;
62
61
  try {
63
62
  maybePromise = pre.fn.call(context);
64
63
  } catch (err) {
65
- error = err;
64
+ if (err != null) {
65
+ return callback(err);
66
+ }
66
67
  }
67
68
 
68
69
  if (isPromise(maybePromise)) {
@@ -74,11 +75,11 @@ Kareem.prototype.execPre = function(name, context, args, callback) {
74
75
  return;
75
76
  } else {
76
77
  return process.nextTick(function() {
77
- callback(error);
78
+ callback(null);
78
79
  });
79
80
  }
80
81
  }
81
- next(error);
82
+ next();
82
83
  }
83
84
  }
84
85
  };
@@ -137,7 +138,7 @@ Kareem.prototype.execPost = function(name, context, args, options, callback) {
137
138
  }
138
139
 
139
140
  var next = function() {
140
- var post = posts[currentPost];
141
+ var post = posts[currentPost].fn;
141
142
  var numArgs = 0;
142
143
  var argLength = args.length;
143
144
  var newArgs = [];
@@ -222,7 +223,7 @@ Kareem.prototype.execPostSync = function(name, context, args) {
222
223
  const numPosts = posts.length;
223
224
 
224
225
  for (let i = 0; i < numPosts; ++i) {
225
- posts[i].apply(context, args || []);
226
+ posts[i].fn.apply(context, args || []);
226
227
  }
227
228
  };
228
229
 
@@ -275,7 +276,12 @@ Kareem.prototype.wrap = function(name, fn, context, args, options) {
275
276
 
276
277
  const end = (typeof lastArg === 'function' ? args.length - 1 : args.length);
277
278
  const numParameters = fn.length;
278
- const ret = fn.apply(context, args.slice(0, end).concat(_cb));
279
+ let ret;
280
+ try {
281
+ ret = fn.apply(context, args.slice(0, end).concat(_cb));
282
+ } catch (err) {
283
+ return _cb(err);
284
+ }
279
285
 
280
286
  if (checkForPromise) {
281
287
  if (ret != null && typeof ret.then === 'function') {
@@ -320,6 +326,42 @@ Kareem.prototype.wrap = function(name, fn, context, args, options) {
320
326
  });
321
327
  };
322
328
 
329
+ Kareem.prototype.filter = function(fn) {
330
+ const clone = this.clone();
331
+
332
+ const pres = Array.from(clone._pres.keys());
333
+ for (const name of pres) {
334
+ const hooks = this._pres.get(name).
335
+ map(h => Object.assign({}, h, { name: name })).
336
+ filter(fn);
337
+
338
+ if (hooks.length === 0) {
339
+ clone._pres.delete(name);
340
+ continue;
341
+ }
342
+
343
+ hooks.numAsync = hooks.filter(h => h.isAsync).length;
344
+
345
+ clone._pres.set(name, hooks);
346
+ }
347
+
348
+ const posts = Array.from(clone._posts.keys());
349
+ for (const name of posts) {
350
+ const hooks = this._posts.get(name).
351
+ map(h => Object.assign({}, h, { name: name })).
352
+ filter(fn);
353
+
354
+ if (hooks.length === 0) {
355
+ clone._posts.delete(name);
356
+ continue;
357
+ }
358
+
359
+ clone._posts.set(name, hooks);
360
+ }
361
+
362
+ return clone;
363
+ };
364
+
323
365
  Kareem.prototype.hasHooks = function(name) {
324
366
  return this._pres.has(name) || this._posts.has(name);
325
367
  };
@@ -341,7 +383,11 @@ Kareem.prototype.createWrapper = function(name, fn, context, options) {
341
383
  };
342
384
 
343
385
  Kareem.prototype.pre = function(name, isAsync, fn, error, unshift) {
344
- if (typeof arguments[1] !== 'boolean') {
386
+ let options = {};
387
+ if (typeof isAsync === 'object' && isAsync != null) {
388
+ options = isAsync;
389
+ isAsync = options.isAsync;
390
+ } else if (typeof arguments[1] !== 'boolean') {
345
391
  error = fn;
346
392
  fn = isAsync;
347
393
  isAsync = false;
@@ -355,22 +401,36 @@ Kareem.prototype.pre = function(name, isAsync, fn, error, unshift) {
355
401
  ++pres.numAsync;
356
402
  }
357
403
 
404
+ if (typeof fn !== 'function') {
405
+ throw new Error('pre() requires a function, got "' + typeof fn + '"');
406
+ }
407
+
358
408
  if (unshift) {
359
- pres.unshift({ fn: fn, isAsync: isAsync });
409
+ pres.unshift(Object.assign({}, options, { fn: fn, isAsync: isAsync }));
360
410
  } else {
361
- pres.push({ fn: fn, isAsync: isAsync });
411
+ pres.push(Object.assign({}, options, { fn: fn, isAsync: isAsync }));
362
412
  }
363
413
 
364
414
  return this;
365
415
  };
366
416
 
367
- Kareem.prototype.post = function(name, fn, unshift) {
417
+ Kareem.prototype.post = function(name, options, fn, unshift) {
368
418
  const hooks = get(this._posts, name, []);
369
419
 
420
+ if (typeof options === 'function') {
421
+ unshift = !!fn;
422
+ fn = options;
423
+ options = {};
424
+ }
425
+
426
+ if (typeof fn !== 'function') {
427
+ throw new Error('post() requires a function, got "' + typeof fn + '"');
428
+ }
429
+
370
430
  if (unshift) {
371
- hooks.unshift(fn);
431
+ hooks.unshift(Object.assign({}, options, { fn: fn }));
372
432
  } else {
373
- hooks.push(fn);
433
+ hooks.push(Object.assign({}, options, { fn: fn }));
374
434
  }
375
435
  this._posts.set(name, hooks);
376
436
  return this;
package/package.json CHANGED
@@ -1,29 +1,21 @@
1
1
  {
2
2
  "name": "kareem",
3
- "version": "2.2.3",
3
+ "version": "2.3.3",
4
4
  "description": "Next-generation take on pre/post function hooks",
5
5
  "main": "index.js",
6
6
  "scripts": {
7
- "test": "./node_modules/mocha/bin/mocha ./test/*",
8
- "test-travis": "./node_modules/istanbul/lib/cli.js cover ./node_modules/mocha/bin/_mocha -- -R spec ./test/*"
7
+ "test": "mocha ./test/*",
8
+ "test-travis": "nyc mocha ./test/*"
9
9
  },
10
10
  "repository": {
11
11
  "type": "git",
12
12
  "url": "git://github.com/vkarpov15/kareem.git"
13
13
  },
14
14
  "devDependencies": {
15
- "acquit": "0.5.1",
16
- "gulp": "3.8.10",
17
- "gulp-mocha": "2.0.0",
18
- "gulp-jscs": "1.4.0",
19
- "istanbul": "0.4.5",
20
- "jscs": "1.9.0",
21
- "mocha": "3.2.0"
22
- },
23
- "jscsConfig": {
24
- "preset": "airbnb",
25
- "requireMultipleVarDecl": null,
26
- "disallowMultipleVarDecl": true
15
+ "acquit": "1.x",
16
+ "acquit-ignore": "0.1.x",
17
+ "nyc": "11.x",
18
+ "mocha": "5.x"
27
19
  },
28
20
  "author": "Valeri Karpov <val@karpov.io>",
29
21
  "license": "Apache-2.0"
@@ -17,7 +17,10 @@ describe('pre hooks', function() {
17
17
 
18
18
  it('runs without any hooks specified', function(done) {
19
19
  hooks.execPre('cook', null, function() {
20
+ // ...
21
+ // acquit:ignore:start
20
22
  done();
23
+ // acquit:ignore:end
21
24
  });
22
25
  });
23
26
 
@@ -34,7 +37,9 @@ describe('pre hooks', function() {
34
37
 
35
38
  hooks.execPre('cook', null, function() {
36
39
  assert.equal(1, count);
40
+ // acquit:ignore:start
37
41
  done();
42
+ // acquit:ignore:end
38
43
  });
39
44
  });
40
45
 
@@ -55,7 +60,9 @@ describe('pre hooks', function() {
55
60
  hooks.execPre('cook', null, function() {
56
61
  assert.equal(1, count1);
57
62
  assert.equal(1, count2);
63
+ // acquit:ignore:start
58
64
  done();
65
+ // acquit:ignore:end
59
66
  });
60
67
  });
61
68
 
@@ -78,7 +85,9 @@ describe('pre hooks', function() {
78
85
  assert.equal(null, error);
79
86
  assert.equal(1, count1);
80
87
  assert.equal(1, count2);
88
+ // acquit:ignore:start
81
89
  done();
90
+ // acquit:ignore:end
82
91
  });
83
92
  });
84
93
 
@@ -102,7 +111,9 @@ describe('pre hooks', function() {
102
111
  assert.equal(null, error);
103
112
  assert.equal(3, obj.bacon);
104
113
  assert.equal(4, obj.eggs);
114
+ // acquit:ignore:start
105
115
  done();
116
+ // acquit:ignore:end
106
117
  });
107
118
  });
108
119
 
@@ -140,7 +151,9 @@ describe('pre hooks', function() {
140
151
  assert.equal(3, obj.bacon);
141
152
  assert.equal(4, obj.eggs);
142
153
  assert.equal(false, obj.waffles);
154
+ // acquit:ignore:start
143
155
  done();
156
+ // acquit:ignore:end
144
157
  });
145
158
  });
146
159
 
@@ -162,7 +175,9 @@ describe('pre hooks', function() {
162
175
 
163
176
  hooks.execPre('cook', obj, function() {
164
177
  assert.equal(3, obj.bacon);
178
+ // acquit:ignore:start
165
179
  done();
180
+ // acquit:ignore:end
166
181
  });
167
182
  });
168
183
  });
@@ -193,7 +208,9 @@ describe('post hooks', function() {
193
208
  assert.ifError(error);
194
209
  assert.equal(1, eggs);
195
210
  assert.equal(2, bacon);
211
+ // acquit:ignore:start
196
212
  done();
213
+ // acquit:ignore:end
197
214
  });
198
215
  });
199
216
 
@@ -220,7 +237,33 @@ describe('post hooks', function() {
220
237
  assert.ok(execed.second);
221
238
  assert.equal(1, eggs);
222
239
  assert.equal(2, bacon);
240
+ // acquit:ignore:start
223
241
  done();
242
+ // acquit:ignore:end
243
+ });
244
+ });
245
+
246
+ /* You can also return a promise from your post hooks instead of calling
247
+ * `next()`. When the returned promise resolves, kareem will kick off the
248
+ * next middleware.
249
+ */
250
+ it('supports returning a promise', function(done) {
251
+ hooks.post('cook', function(bacon) {
252
+ return new Promise(resolve => {
253
+ setTimeout(() => {
254
+ this.bacon = 3;
255
+ resolve();
256
+ }, 100);
257
+ });
258
+ });
259
+
260
+ var obj = { bacon: 0 };
261
+
262
+ hooks.execPost('cook', obj, obj, function() {
263
+ assert.equal(obj.bacon, 3);
264
+ // acquit:ignore:start
265
+ done();
266
+ // acquit:ignore:end
224
267
  });
225
268
  });
226
269
  });
@@ -271,7 +314,9 @@ describe('wrap()', function() {
271
314
  assert.equal('no', obj.tofu);
272
315
 
273
316
  assert.equal(obj, result);
317
+ // acquit:ignore:start
274
318
  done();
319
+ // acquit:ignore:end
275
320
  });
276
321
 
277
322
  hooks.wrap(
@@ -343,7 +388,9 @@ describe('createWrapper()', function() {
343
388
  assert.equal('no', obj.tofu);
344
389
 
345
390
  assert.equal(obj, result);
391
+ // acquit:ignore:start
346
392
  done();
393
+ // acquit:ignore:end
347
394
  });
348
395
  });
349
396
  });
package/test/misc.test.js CHANGED
@@ -31,3 +31,41 @@ describe('merge', function() {
31
31
  assert.equal(k3._pres.get('cook').numAsync, 1);
32
32
  });
33
33
  });
34
+
35
+ describe('filter', function() {
36
+ it('returns clone with only hooks that match `fn()`', function() {
37
+ const k1 = new Kareem();
38
+
39
+ k1.pre('update', { document: true }, f1);
40
+ k1.pre('update', { query: true }, f2);
41
+ k1.pre('remove', { document: true }, f3);
42
+
43
+ k1.post('update', { document: true }, f1);
44
+ k1.post('update', { query: true }, f2);
45
+ k1.post('remove', { document: true }, f3);
46
+
47
+ const k2 = k1.filter(hook => hook.document);
48
+ assert.equal(k2._pres.get('update').length, 1);
49
+ assert.equal(k2._pres.get('update')[0].fn, f1);
50
+ assert.equal(k2._pres.get('remove').length, 1);
51
+ assert.equal(k2._pres.get('remove')[0].fn, f3);
52
+
53
+ assert.equal(k2._posts.get('update').length, 1);
54
+ assert.equal(k2._posts.get('update')[0].fn, f1);
55
+ assert.equal(k2._posts.get('remove').length, 1);
56
+ assert.equal(k2._posts.get('remove')[0].fn, f3);
57
+
58
+ const k3 = k1.filter(hook => hook.query);
59
+ assert.equal(k3._pres.get('update').length, 1);
60
+ assert.equal(k3._pres.get('update')[0].fn, f2);
61
+ assert.ok(!k3._pres.has('remove'));
62
+
63
+ assert.equal(k3._posts.get('update').length, 1);
64
+ assert.equal(k3._posts.get('update')[0].fn, f2);
65
+ assert.ok(!k3._posts.has('remove'));
66
+
67
+ function f1() {}
68
+ function f2() {}
69
+ function f3() {}
70
+ });
71
+ });
package/test/post.test.js CHANGED
@@ -27,10 +27,23 @@ describe('execPost', function() {
27
27
  var f2 = function() {};
28
28
  hooks.post('cook', f1);
29
29
  hooks.post('cook', f2, true);
30
- assert.strictEqual(hooks._posts.get('cook')[0], f2);
31
- assert.strictEqual(hooks._posts.get('cook')[1], f1);
30
+ assert.strictEqual(hooks._posts.get('cook')[0].fn, f2);
31
+ assert.strictEqual(hooks._posts.get('cook')[1].fn, f1);
32
32
  });
33
33
 
34
+ it('arbitrary options', function() {
35
+ const f1 = function() {};
36
+ const f2 = function() {};
37
+ hooks.post('cook', { foo: 'bar' }, f1);
38
+ hooks.post('cook', { bar: 'baz' }, f2, true);
39
+ assert.equal(hooks._posts.get('cook')[1].foo, 'bar');
40
+ assert.equal(hooks._posts.get('cook')[0].bar, 'baz');
41
+ });
42
+
43
+ it('throws error if no function', function() {
44
+ assert.throws(() => hooks.post('test'), /got "undefined"/);
45
+ });
46
+
34
47
  it('multiple posts', function(done) {
35
48
  hooks.post('cook', function(eggs, callback) {
36
49
  setTimeout(
package/test/pre.test.js CHANGED
@@ -65,6 +65,19 @@ describe('execPre', function() {
65
65
  assert.strictEqual(hooks._pres.get('cook')[1].fn, f1);
66
66
  });
67
67
 
68
+ it('throws error if no function', function() {
69
+ assert.throws(() => hooks.pre('test'), /got "undefined"/);
70
+ });
71
+
72
+ it('arbitrary options', function() {
73
+ const f1 = function() {};
74
+ const f2 = function() {};
75
+ hooks.pre('cook', { foo: 'bar' }, f1);
76
+ hooks.pre('cook', { bar: 'baz' }, f2, null, true);
77
+ assert.equal(hooks._pres.get('cook')[1].foo, 'bar');
78
+ assert.equal(hooks._pres.get('cook')[0].bar, 'baz');
79
+ });
80
+
68
81
  it('handles async errors', function(done) {
69
82
  var execed = {};
70
83
 
@@ -274,6 +287,26 @@ describe('execPre', function() {
274
287
  done();
275
288
  });
276
289
  });
290
+
291
+ it('handles sync errors in pre if there are more hooks', function(done) {
292
+ var execed = {};
293
+
294
+ hooks.pre('cook', function() {
295
+ execed.first = true;
296
+ throw new Error('Oops!');
297
+ });
298
+
299
+ hooks.pre('cook', function() {
300
+ execed.second = true;
301
+ });
302
+
303
+ hooks.execPre('cook', null, function(err) {
304
+ assert.ok(err);
305
+ assert.ok(execed.first);
306
+ assert.equal(err.message, 'Oops!');
307
+ done();
308
+ });
309
+ });
277
310
  });
278
311
 
279
312
  describe('execPreSync', function() {
package/test/wrap.test.js CHANGED
@@ -319,6 +319,30 @@ describe('wrap()', function() {
319
319
  25);
320
320
  });
321
321
 
322
+ it('catches sync errors', function(done) {
323
+ hooks.pre('cook', function(done) {
324
+ done();
325
+ });
326
+
327
+ hooks.post('cook', function(callback) {
328
+ callback();
329
+ });
330
+
331
+ var args = [];
332
+ args.push(function(error) {
333
+ assert.equal(error.message, 'oops!');
334
+ done();
335
+ });
336
+
337
+ hooks.wrap(
338
+ 'cook',
339
+ function() {
340
+ throw new Error('oops!');
341
+ },
342
+ null,
343
+ args);
344
+ });
345
+
322
346
  it('sync wrappers', function() {
323
347
  var calledPre = 0;
324
348
  var calledFn = 0;