kareem 2.2.2 → 2.3.2

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
 
@@ -320,6 +321,42 @@ Kareem.prototype.wrap = function(name, fn, context, args, options) {
320
321
  });
321
322
  };
322
323
 
324
+ Kareem.prototype.filter = function(fn) {
325
+ const clone = this.clone();
326
+
327
+ const pres = Array.from(clone._pres.keys());
328
+ for (const name of pres) {
329
+ const hooks = this._pres.get(name).
330
+ map(h => Object.assign({}, h, { name: name })).
331
+ filter(fn);
332
+
333
+ if (hooks.length === 0) {
334
+ clone._pres.delete(name);
335
+ continue;
336
+ }
337
+
338
+ hooks.numAsync = hooks.filter(h => h.isAsync).length;
339
+
340
+ clone._pres.set(name, hooks);
341
+ }
342
+
343
+ const posts = Array.from(clone._posts.keys());
344
+ for (const name of posts) {
345
+ const hooks = this._posts.get(name).
346
+ map(h => Object.assign({}, h, { name: name })).
347
+ filter(fn);
348
+
349
+ if (hooks.length === 0) {
350
+ clone._posts.delete(name);
351
+ continue;
352
+ }
353
+
354
+ clone._posts.set(name, hooks);
355
+ }
356
+
357
+ return clone;
358
+ };
359
+
323
360
  Kareem.prototype.hasHooks = function(name) {
324
361
  return this._pres.has(name) || this._posts.has(name);
325
362
  };
@@ -341,7 +378,11 @@ Kareem.prototype.createWrapper = function(name, fn, context, options) {
341
378
  };
342
379
 
343
380
  Kareem.prototype.pre = function(name, isAsync, fn, error, unshift) {
344
- if (typeof arguments[1] !== 'boolean') {
381
+ let options = {};
382
+ if (typeof isAsync === 'object' && isAsync != null) {
383
+ options = isAsync;
384
+ isAsync = options.isAsync;
385
+ } else if (typeof arguments[1] !== 'boolean') {
345
386
  error = fn;
346
387
  fn = isAsync;
347
388
  isAsync = false;
@@ -355,22 +396,36 @@ Kareem.prototype.pre = function(name, isAsync, fn, error, unshift) {
355
396
  ++pres.numAsync;
356
397
  }
357
398
 
399
+ if (typeof fn !== 'function') {
400
+ throw new Error('pre() requires a function, got "' + typeof fn + '"');
401
+ }
402
+
358
403
  if (unshift) {
359
- pres.unshift({ fn: fn, isAsync: isAsync });
404
+ pres.unshift(Object.assign({}, options, { fn: fn, isAsync: isAsync }));
360
405
  } else {
361
- pres.push({ fn: fn, isAsync: isAsync });
406
+ pres.push(Object.assign({}, options, { fn: fn, isAsync: isAsync }));
362
407
  }
363
408
 
364
409
  return this;
365
410
  };
366
411
 
367
- Kareem.prototype.post = function(name, fn, unshift) {
412
+ Kareem.prototype.post = function(name, options, fn, unshift) {
368
413
  const hooks = get(this._posts, name, []);
369
414
 
415
+ if (typeof options === 'function') {
416
+ unshift = !!fn;
417
+ fn = options;
418
+ options = {};
419
+ }
420
+
421
+ if (typeof fn !== 'function') {
422
+ throw new Error('post() requires a function, got "' + typeof fn + '"');
423
+ }
424
+
370
425
  if (unshift) {
371
- hooks.unshift(fn);
426
+ hooks.unshift(Object.assign({}, options, { fn: fn }));
372
427
  } else {
373
- hooks.push(fn);
428
+ hooks.push(Object.assign({}, options, { fn: fn }));
374
429
  }
375
430
  this._posts.set(name, hooks);
376
431
  return this;
@@ -393,7 +448,7 @@ Kareem.prototype.clone = function() {
393
448
 
394
449
  Kareem.prototype.merge = function(other, clone) {
395
450
  clone = arguments.length === 1 ? true : clone;
396
- var ret = clone ? this.clone() : ret;
451
+ var ret = clone ? this.clone() : this;
397
452
 
398
453
  for (let key of other._pres.keys()) {
399
454
  const sourcePres = get(ret._pres, key, []);
package/package.json CHANGED
@@ -1,29 +1,21 @@
1
1
  {
2
2
  "name": "kareem",
3
- "version": "2.2.2",
3
+ "version": "2.3.2",
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() {