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/README.md CHANGED
@@ -5,80 +5,69 @@
5
5
 
6
6
  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.
7
7
 
8
- 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)
8
+ Named for the NBA's 2nd all-time leading scorer Kareem Abdul-Jabbar, known for his mastery of the [hook shot](http://en.wikipedia.org/wiki/Kareem_Abdul-Jabbar#Skyhook)
9
9
 
10
10
  <img src="http://upload.wikimedia.org/wikipedia/commons/0/00/Kareem-Abdul-Jabbar_Lipofsky.jpg" width="220">
11
11
 
12
+ <!--DOCS START-->
13
+
12
14
  # API
13
15
 
14
16
  ## pre hooks
15
17
 
16
- Much like [hooks](https://npmjs.org/package/hooks), kareem lets you define
17
- pre and post hooks: pre hooks are called before a given function executes.
18
- Unlike hooks, kareem stores hooks and other internal state in a separate
19
- object, rather than relying on inheritance. Furthermore, kareem exposes
20
- an `execPre()` function that allows you to execute your pre hooks when
21
- appropriate, giving you more fine-grained control over your function hooks.
22
-
18
+ NOTE: this file has some empty comment lines to workaround https://github.com/vkarpov15/acquit/issues/30
23
19
 
24
- #### It runs without any hooks specified
20
+ ### It runs without any hooks specified
25
21
 
26
22
  ```javascript
27
- hooks.execPre('cook', null, function() {
28
- // ...
29
- });
23
+ await hooks.execPre('cook', null);
30
24
  ```
31
25
 
32
- #### It runs basic serial pre hooks
33
-
34
- pre hook functions take one parameter, a "done" function that you execute
35
- when your pre hook is finished.
26
+ ### It runs basic serial pre hooks
36
27
 
28
+ pre hook functions can return a promise that resolves when finished.
37
29
 
38
30
  ```javascript
39
- var count = 0;
31
+ let count = 0;
40
32
 
41
- hooks.pre('cook', function(done) {
33
+ hooks.pre('cook', function() {
42
34
  ++count;
43
- done();
35
+ return Promise.resolve();
44
36
  });
45
37
 
46
- hooks.execPre('cook', null, function() {
47
- assert.equal(1, count);
48
- });
38
+ await hooks.execPre('cook', null);
39
+ assert.equal(1, count);
49
40
  ```
50
41
 
51
- #### It can run multipe pre hooks
42
+ ### It can run multiple pre hooks
52
43
 
53
44
  ```javascript
54
- var count1 = 0;
55
- var count2 = 0;
45
+ let count1 = 0;
46
+ let count2 = 0;
56
47
 
57
- hooks.pre('cook', function(done) {
48
+ hooks.pre('cook', function() {
58
49
  ++count1;
59
- done();
50
+ return Promise.resolve();
60
51
  });
61
52
 
62
- hooks.pre('cook', function(done) {
53
+ hooks.pre('cook', function() {
63
54
  ++count2;
64
- done();
55
+ return Promise.resolve();
65
56
  });
66
57
 
67
- hooks.execPre('cook', null, function() {
68
- assert.equal(1, count1);
69
- assert.equal(1, count2);
70
- });
58
+ await hooks.execPre('cook', null);
59
+ assert.equal(1, count1);
60
+ assert.equal(1, count2);
71
61
  ```
72
62
 
73
- #### It can run fully synchronous pre hooks
63
+ ### It can run fully synchronous pre hooks
74
64
 
75
65
  If your pre hook function takes no parameters, its assumed to be
76
66
  fully synchronous.
77
67
 
78
-
79
68
  ```javascript
80
- var count1 = 0;
81
- var count2 = 0;
69
+ let count1 = 0;
70
+ let count2 = 0;
82
71
 
83
72
  hooks.pre('cook', function() {
84
73
  ++count1;
@@ -88,86 +77,38 @@ hooks.pre('cook', function() {
88
77
  ++count2;
89
78
  });
90
79
 
91
- hooks.execPre('cook', null, function(error) {
92
- assert.equal(null, error);
93
- assert.equal(1, count1);
94
- assert.equal(1, count2);
95
- });
80
+ await hooks.execPre('cook', null);
81
+ assert.equal(1, count1);
82
+ assert.equal(1, count2);
96
83
  ```
97
84
 
98
- #### It properly attaches context to pre hooks
85
+ ### It properly attaches context to pre hooks
99
86
 
100
87
  Pre save hook functions are bound to the second parameter to `execPre()`
101
88
 
102
-
103
89
  ```javascript
104
- hooks.pre('cook', function(done) {
90
+ hooks.pre('cook', function() {
105
91
  this.bacon = 3;
106
- done();
107
92
  });
108
93
 
109
- hooks.pre('cook', function(done) {
94
+ hooks.pre('cook', function() {
110
95
  this.eggs = 4;
111
- done();
112
96
  });
113
97
 
114
- var obj = { bacon: 0, eggs: 0 };
98
+ const obj = { bacon: 0, eggs: 0 };
115
99
 
116
100
  // In the pre hooks, `this` will refer to `obj`
117
- hooks.execPre('cook', obj, function(error) {
118
- assert.equal(null, error);
119
- assert.equal(3, obj.bacon);
120
- assert.equal(4, obj.eggs);
121
- });
122
- ```
123
-
124
- #### It can execute parallel (async) pre hooks
125
-
126
- Like the hooks module, you can declare "async" pre hooks - these take two
127
- parameters, the functions `next()` and `done()`. `next()` passes control to
128
- the next pre hook, but the underlying function won't be called until all
129
- async pre hooks have called `done()`.
130
-
131
-
132
- ```javascript
133
- hooks.pre('cook', true, function(next, done) {
134
- this.bacon = 3;
135
- next();
136
- setTimeout(function() {
137
- done();
138
- }, 5);
139
- });
140
-
141
- hooks.pre('cook', true, function(next, done) {
142
- next();
143
- var _this = this;
144
- setTimeout(function() {
145
- _this.eggs = 4;
146
- done();
147
- }, 10);
148
- });
149
-
150
- hooks.pre('cook', function(next) {
151
- this.waffles = false;
152
- next();
153
- });
154
-
155
- var obj = { bacon: 0, eggs: 0 };
156
-
157
- hooks.execPre('cook', obj, function() {
158
- assert.equal(3, obj.bacon);
159
- assert.equal(4, obj.eggs);
160
- assert.equal(false, obj.waffles);
161
- });
101
+ await hooks.execPre('cook', obj);
102
+ assert.equal(3, obj.bacon);
103
+ assert.equal(4, obj.eggs);
162
104
  ```
163
105
 
164
- #### It supports returning a promise
106
+ ### It supports returning a promise
165
107
 
166
108
  You can also return a promise from your pre hooks instead of calling
167
109
  `next()`. When the returned promise resolves, kareem will kick off the
168
110
  next middleware.
169
111
 
170
-
171
112
  ```javascript
172
113
  hooks.pre('cook', function() {
173
114
  return new Promise(resolve => {
@@ -178,80 +119,93 @@ hooks.pre('cook', function() {
178
119
  });
179
120
  });
180
121
 
181
- var obj = { bacon: 0 };
122
+ const obj = { bacon: 0 };
123
+
124
+ await hooks.execPre('cook', obj);
125
+ assert.equal(3, obj.bacon);
126
+ ```
127
+
128
+ ### It supports filtering which hooks to run
129
+
130
+ You can pass a `filter` option to `execPre()` to select which hooks
131
+ to run. The filter function receives each hook object and should return
132
+ `true` to run the hook or `false` to skip it.
133
+
134
+ ```javascript
135
+ const execed = [];
136
+
137
+ const fn1 = function() { execed.push('first'); };
138
+ fn1.skipMe = true;
139
+ hooks.pre('cook', fn1);
140
+
141
+ const fn2 = function() { execed.push('second'); };
142
+ hooks.pre('cook', fn2);
182
143
 
183
- hooks.execPre('cook', obj, function() {
184
- assert.equal(3, obj.bacon);
144
+ // Only runs fn2, skips fn1 because fn1.skipMe is true
145
+ await hooks.execPre('cook', null, [], {
146
+ filter: hook => !hook.fn.skipMe
185
147
  });
148
+
149
+ assert.deepStrictEqual(execed, ['second']);
186
150
  ```
187
151
 
188
152
  ## post hooks
189
153
 
190
- acquit:ignore:end
191
-
192
- #### It runs without any hooks specified
154
+ ### It runs without any hooks specified
193
155
 
194
156
  ```javascript
195
- hooks.execPost('cook', null, [1], function(error, eggs) {
196
- assert.ifError(error);
197
- assert.equal(1, eggs);
198
- done();
199
- });
157
+ const [eggs] = await hooks.execPost('cook', null, [1]);
158
+ assert.equal(eggs, 1);
200
159
  ```
201
160
 
202
- #### It executes with parameters passed in
161
+ ### It executes with parameters passed in
203
162
 
204
163
  ```javascript
205
164
  hooks.post('cook', function(eggs, bacon, callback) {
206
- assert.equal(1, eggs);
207
- assert.equal(2, bacon);
165
+ assert.equal(eggs, 1);
166
+ assert.equal(bacon, 2);
208
167
  callback();
209
168
  });
210
169
 
211
- hooks.execPost('cook', null, [1, 2], function(error, eggs, bacon) {
212
- assert.ifError(error);
213
- assert.equal(1, eggs);
214
- assert.equal(2, bacon);
215
- });
170
+ const [eggs, bacon] = await hooks.execPost('cook', null, [1, 2]);
171
+ assert.equal(eggs, 1);
172
+ assert.equal(bacon, 2);
216
173
  ```
217
174
 
218
- #### It can use synchronous post hooks
175
+ ### It can use synchronous post hooks
219
176
 
220
177
  ```javascript
221
- var execed = {};
178
+ const execed = {};
222
179
 
223
180
  hooks.post('cook', function(eggs, bacon) {
224
181
  execed.first = true;
225
- assert.equal(1, eggs);
226
- assert.equal(2, bacon);
182
+ assert.equal(eggs, 1);
183
+ assert.equal(bacon, 2);
227
184
  });
228
185
 
229
186
  hooks.post('cook', function(eggs, bacon, callback) {
230
187
  execed.second = true;
231
- assert.equal(1, eggs);
232
- assert.equal(2, bacon);
188
+ assert.equal(eggs, 1);
189
+ assert.equal(bacon, 2);
233
190
  callback();
234
191
  });
235
192
 
236
- hooks.execPost('cook', null, [1, 2], function(error, eggs, bacon) {
237
- assert.ifError(error);
238
- assert.equal(2, Object.keys(execed).length);
239
- assert.ok(execed.first);
240
- assert.ok(execed.second);
241
- assert.equal(1, eggs);
242
- assert.equal(2, bacon);
243
- });
193
+ const [eggs, bacon] = await hooks.execPost('cook', null, [1, 2]);
194
+ assert.equal(Object.keys(execed).length, 2);
195
+ assert.ok(execed.first);
196
+ assert.ok(execed.second);
197
+ assert.equal(eggs, 1);
198
+ assert.equal(bacon, 2);
244
199
  ```
245
200
 
246
- #### It supports returning a promise
201
+ ### It supports returning a promise
247
202
 
248
203
  You can also return a promise from your post hooks instead of calling
249
204
  `next()`. When the returned promise resolves, kareem will kick off the
250
205
  next middleware.
251
206
 
252
-
253
207
  ```javascript
254
- hooks.post('cook', function(bacon) {
208
+ hooks.post('cook', function() {
255
209
  return new Promise(resolve => {
256
210
  setTimeout(() => {
257
211
  this.bacon = 3;
@@ -260,158 +214,165 @@ hooks.post('cook', function(bacon) {
260
214
  });
261
215
  });
262
216
 
263
- var obj = { bacon: 0 };
217
+ const obj = { bacon: 0 };
218
+
219
+ await hooks.execPost('cook', obj, [obj]);
220
+ assert.equal(obj.bacon, 3);
221
+ ```
222
+
223
+ ### It supports filtering which hooks to run
224
+
225
+ You can pass a `filter` option to `execPost()` to select which hooks
226
+ to run. The filter function receives each hook object and should return
227
+ `true` to run the hook or `false` to skip it.
264
228
 
265
- hooks.execPost('cook', obj, obj, function() {
266
- assert.equal(obj.bacon, 3);
229
+ ```javascript
230
+ const execed = [];
231
+
232
+ const fn1 = function() { execed.push('first'); };
233
+ fn1.skipMe = true;
234
+ hooks.post('cook', fn1);
235
+
236
+ const fn2 = function() { execed.push('second'); };
237
+ hooks.post('cook', fn2);
238
+
239
+ // Only runs fn2, skips fn1 because fn1.skipMe is true
240
+ await hooks.execPost('cook', null, [], {
241
+ filter: hook => !hook.fn.skipMe
267
242
  });
243
+
244
+ assert.deepStrictEqual(execed, ['second']);
268
245
  ```
269
246
 
270
247
  ## wrap()
271
248
 
272
- acquit:ignore:end
273
-
274
- #### It wraps pre and post calls into one call
249
+ ### It wraps pre and post calls into one call
275
250
 
276
251
  ```javascript
277
- hooks.pre('cook', true, function(next, done) {
278
- this.bacon = 3;
279
- next();
280
- setTimeout(function() {
281
- done();
282
- }, 5);
252
+ hooks.pre('cook', function() {
253
+ return new Promise(resolve => {
254
+ this.bacon = 3;
255
+ setTimeout(() => {
256
+ resolve();
257
+ }, 5);
258
+ });
283
259
  });
284
260
 
285
- hooks.pre('cook', true, function(next, done) {
286
- next();
287
- var _this = this;
288
- setTimeout(function() {
289
- _this.eggs = 4;
290
- done();
291
- }, 10);
261
+ hooks.pre('cook', function() {
262
+ this.eggs = 4;
263
+ return Promise.resolve();
292
264
  });
293
265
 
294
- hooks.pre('cook', function(next) {
266
+ hooks.pre('cook', function() {
295
267
  this.waffles = false;
296
- next();
268
+ return Promise.resolve();
297
269
  });
298
270
 
299
271
  hooks.post('cook', function(obj) {
300
272
  obj.tofu = 'no';
301
273
  });
302
274
 
303
- var obj = { bacon: 0, eggs: 0 };
275
+ const obj = { bacon: 0, eggs: 0 };
304
276
 
305
- var args = [obj];
306
- args.push(function(error, result) {
307
- assert.ifError(error);
308
- assert.equal(null, error);
309
- assert.equal(3, obj.bacon);
310
- assert.equal(4, obj.eggs);
311
- assert.equal(false, obj.waffles);
312
- assert.equal('no', obj.tofu);
277
+ const args = [obj];
313
278
 
314
- assert.equal(obj, result);
315
- });
316
-
317
- hooks.wrap(
279
+ const result = await hooks.wrap(
318
280
  'cook',
319
- function(o, callback) {
320
- assert.equal(3, obj.bacon);
321
- assert.equal(4, obj.eggs);
322
- assert.equal(false, obj.waffles);
323
- assert.equal(undefined, obj.tofu);
324
- callback(null, o);
281
+ function(o) {
282
+ assert.equal(obj.bacon, 3);
283
+ assert.equal(obj.eggs, 4);
284
+ assert.equal(obj.waffles, false);
285
+ assert.equal(obj.tofu, undefined);
286
+ return o;
325
287
  },
326
288
  obj,
327
289
  args);
290
+
291
+ assert.equal(obj.bacon, 3);
292
+ assert.equal(obj.eggs, 4);
293
+ assert.equal(obj.waffles, false);
294
+ assert.equal(obj.tofu, 'no');
295
+ assert.equal(result, obj);
328
296
  ```
329
297
 
330
298
  ## createWrapper()
331
299
 
332
- #### It wraps wrap() into a callable function
300
+ ### It wraps wrap() into a callable function
333
301
 
334
302
  ```javascript
335
- hooks.pre('cook', true, function(next, done) {
303
+ hooks.pre('cook', function() {
336
304
  this.bacon = 3;
337
- next();
338
- setTimeout(function() {
339
- done();
340
- }, 5);
305
+ return Promise.resolve();
341
306
  });
342
307
 
343
- hooks.pre('cook', true, function(next, done) {
344
- next();
345
- var _this = this;
346
- setTimeout(function() {
347
- _this.eggs = 4;
348
- done();
349
- }, 10);
308
+ hooks.pre('cook', function() {
309
+ return new Promise(resolve => {
310
+ this.eggs = 4;
311
+ setTimeout(function() {
312
+ resolve();
313
+ }, 10);
314
+ });
350
315
  });
351
316
 
352
- hooks.pre('cook', function(next) {
317
+ hooks.pre('cook', function() {
353
318
  this.waffles = false;
354
- next();
319
+ return Promise.resolve();
355
320
  });
356
321
 
357
322
  hooks.post('cook', function(obj) {
358
323
  obj.tofu = 'no';
359
324
  });
360
325
 
361
- var obj = { bacon: 0, eggs: 0 };
326
+ const obj = { bacon: 0, eggs: 0 };
362
327
 
363
- var cook = hooks.createWrapper(
328
+ const cook = hooks.createWrapper(
364
329
  'cook',
365
- function(o, callback) {
330
+ function(o) {
366
331
  assert.equal(3, obj.bacon);
367
332
  assert.equal(4, obj.eggs);
368
333
  assert.equal(false, obj.waffles);
369
334
  assert.equal(undefined, obj.tofu);
370
- callback(null, o);
335
+ return o;
371
336
  },
372
337
  obj);
373
338
 
374
- cook(obj, function(error, result) {
375
- assert.ifError(error);
376
- assert.equal(3, obj.bacon);
377
- assert.equal(4, obj.eggs);
378
- assert.equal(false, obj.waffles);
379
- assert.equal('no', obj.tofu);
339
+ const result = await cook(obj);
340
+ assert.equal(obj.bacon, 3);
341
+ assert.equal(obj.eggs, 4);
342
+ assert.equal(obj.waffles, false);
343
+ assert.equal(obj.tofu, 'no');
380
344
 
381
- assert.equal(obj, result);
382
- });
345
+ assert.equal(result, obj);
383
346
  ```
384
347
 
385
348
  ## clone()
386
349
 
387
- acquit:ignore:end
388
-
389
- #### It clones a Kareem object
350
+ ### It clones a Kareem object
390
351
 
391
352
  ```javascript
392
- var k1 = new Kareem();
353
+ const k1 = new Kareem();
393
354
  k1.pre('cook', function() {});
394
355
  k1.post('cook', function() {});
395
356
 
396
- var k2 = k1.clone();
357
+ const k2 = k1.clone();
397
358
  assert.deepEqual(Array.from(k2._pres.keys()), ['cook']);
398
359
  assert.deepEqual(Array.from(k2._posts.keys()), ['cook']);
399
360
  ```
400
361
 
401
362
  ## merge()
402
363
 
403
- #### It pulls hooks from another Kareem object
364
+ ### It pulls hooks from another Kareem object
404
365
 
405
366
  ```javascript
406
- var k1 = new Kareem();
407
- var test1 = function() {};
367
+ const k1 = new Kareem();
368
+ const test1 = function() {};
408
369
  k1.pre('cook', test1);
409
370
  k1.post('cook', function() {});
410
371
 
411
- var k2 = new Kareem();
412
- var test2 = function() {};
372
+ const k2 = new Kareem();
373
+ const test2 = function() {};
413
374
  k2.pre('cook', test2);
414
- var k3 = k2.merge(k1);
375
+ const k3 = k2.merge(k1);
415
376
  assert.equal(k3._pres.get('cook').length, 2);
416
377
  assert.equal(k3._pres.get('cook')[0].fn, test2);
417
378
  assert.equal(k3._pres.get('cook')[1].fn, test1);