kareem 2.3.5 → 2.4.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.
@@ -0,0 +1,30 @@
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
+ include:
17
+ - os: ubuntu-20.04
18
+ mongo-os: ubuntu2004
19
+ name: Node ${{ matrix.node }}
20
+ steps:
21
+ - uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846 # v3
22
+
23
+ - name: Setup node
24
+ uses: actions/setup-node@5b52f097d36d4b0b2f94ed6de710023fbb8b2236 # v3.1.0
25
+ with:
26
+ node-version: ${{ matrix.node }}
27
+
28
+ - run: npm install
29
+
30
+ - run: npm test
package/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ <a name="2.4.0"></a>
4
+ ## 2.4.0 (2022-06-13)
5
+
6
+ * feat: add `overwriteResult()` and `skipWrappedFunction()` for more advanced control flow
7
+
3
8
  <a name="2.3.4"></a>
4
9
  ## 2.3.4 (2022-02-10)
5
10
 
package/index.js CHANGED
@@ -5,6 +5,22 @@ function Kareem() {
5
5
  this._posts = new Map();
6
6
  }
7
7
 
8
+ Kareem.skipWrappedFunction = function skipWrappedFunction() {
9
+ if (!(this instanceof Kareem.skipWrappedFunction)) {
10
+ return new Kareem.skipWrappedFunction(...arguments);
11
+ }
12
+
13
+ this.args = [...arguments];
14
+ };
15
+
16
+ Kareem.overwriteResult = function overwriteResult() {
17
+ if (!(this instanceof Kareem.overwriteResult)) {
18
+ return new Kareem.overwriteResult(...arguments);
19
+ }
20
+
21
+ this.args = [...arguments];
22
+ };
23
+
8
24
  Kareem.prototype.execPre = function(name, context, args, callback) {
9
25
  if (arguments.length === 3) {
10
26
  callback = args;
@@ -17,6 +33,7 @@ Kareem.prototype.execPre = function(name, context, args, callback) {
17
33
  var asyncPresLeft = numAsyncPres;
18
34
  var done = false;
19
35
  var $args = args;
36
+ var shouldSkipWrappedFunction = null;
20
37
 
21
38
  if (!numPres) {
22
39
  return nextTick(function() {
@@ -38,11 +55,15 @@ Kareem.prototype.execPre = function(name, context, args, callback) {
38
55
  if (done) {
39
56
  return;
40
57
  }
41
- done = true;
42
- return callback(error);
58
+ if (error instanceof Kareem.skipWrappedFunction) {
59
+ shouldSkipWrappedFunction = error;
60
+ } else {
61
+ done = true;
62
+ return callback(error);
63
+ }
43
64
  }
44
65
  if (--asyncPresLeft === 0 && currentPre >= numPres) {
45
- return callback(null);
66
+ return callback(shouldSkipWrappedFunction);
46
67
  }
47
68
  })
48
69
  ];
@@ -75,7 +96,7 @@ Kareem.prototype.execPre = function(name, context, args, callback) {
75
96
  return;
76
97
  } else {
77
98
  return nextTick(function() {
78
- callback(null);
99
+ callback(shouldSkipWrappedFunction);
79
100
  });
80
101
  }
81
102
  }
@@ -91,8 +112,12 @@ Kareem.prototype.execPre = function(name, context, args, callback) {
91
112
  if (done) {
92
113
  return;
93
114
  }
94
- done = true;
95
- return callback(error);
115
+ if (error instanceof Kareem.skipWrappedFunction) {
116
+ shouldSkipWrappedFunction = error;
117
+ } else {
118
+ done = true;
119
+ return callback(error);
120
+ }
96
121
  }
97
122
 
98
123
  if (++currentPre >= numPres) {
@@ -100,7 +125,7 @@ Kareem.prototype.execPre = function(name, context, args, callback) {
100
125
  // Leave parallel hooks to run
101
126
  return;
102
127
  } else {
103
- return callback(null);
128
+ return callback(shouldSkipWrappedFunction);
104
129
  }
105
130
  }
106
131
 
@@ -153,6 +178,13 @@ Kareem.prototype.execPost = function(name, context, args, options, callback) {
153
178
  if (post.length === numArgs + 2) {
154
179
  const _cb = decorateNextFn(function(error) {
155
180
  if (error) {
181
+ if (error instanceof Kareem.overwriteResult) {
182
+ args = error.args;
183
+ if (++currentPost >= numPosts) {
184
+ return callback.call(null, firstError);
185
+ }
186
+ return next();
187
+ }
156
188
  firstError = error;
157
189
  }
158
190
  if (++currentPost >= numPosts) {
@@ -172,6 +204,13 @@ Kareem.prototype.execPost = function(name, context, args, options, callback) {
172
204
  } else {
173
205
  const _cb = decorateNextFn(function(error) {
174
206
  if (error) {
207
+ if (error instanceof Kareem.overwriteResult) {
208
+ args = error.args;
209
+ if (++currentPost >= numPosts) {
210
+ return callback.apply(null, [null].concat(args));
211
+ }
212
+ return next();
213
+ }
175
214
  firstError = error;
176
215
  return next();
177
216
  }
@@ -203,7 +242,11 @@ Kareem.prototype.execPost = function(name, context, args, options, callback) {
203
242
  }
204
243
 
205
244
  if (isPromiseLike(maybePromiseLike)) {
206
- return maybePromiseLike.then(() => _cb(), err => _cb(err));
245
+ return maybePromiseLike.then((res) => _cb(res), err => _cb(err));
246
+ }
247
+
248
+ if (maybePromiseLike instanceof Kareem.overwriteResult) {
249
+ args = maybePromiseLike.args;
207
250
  }
208
251
 
209
252
  if (++currentPost >= numPosts) {
@@ -223,8 +266,13 @@ Kareem.prototype.execPostSync = function(name, context, args) {
223
266
  const numPosts = posts.length;
224
267
 
225
268
  for (let i = 0; i < numPosts; ++i) {
226
- posts[i].fn.apply(context, args || []);
269
+ const res = posts[i].fn.apply(context, args || []);
270
+ if (res instanceof Kareem.overwriteResult) {
271
+ args = res.args;
272
+ }
227
273
  }
274
+
275
+ return args;
228
276
  };
229
277
 
230
278
  Kareem.prototype.createWrapperSync = function(name, fn) {
@@ -234,9 +282,9 @@ Kareem.prototype.createWrapperSync = function(name, fn) {
234
282
 
235
283
  var toReturn = fn.apply(this, arguments);
236
284
 
237
- kareem.execPostSync(name, this, [toReturn]);
285
+ const result = kareem.execPostSync(name, this, [toReturn]);
238
286
 
239
- return toReturn;
287
+ return result[0];
240
288
  };
241
289
  }
242
290
 
@@ -252,7 +300,7 @@ function _handleWrapError(instance, error, name, context, args, options, callbac
252
300
 
253
301
  Kareem.prototype.wrap = function(name, fn, context, args, options) {
254
302
  const lastArg = (args.length > 0 ? args[args.length - 1] : null);
255
- const argsWithoutCb = Array.from(args);
303
+ let argsWithoutCb = Array.from(args);
256
304
  typeof lastArg === 'function' && argsWithoutCb.pop();
257
305
  const _this = this;
258
306
 
@@ -260,7 +308,7 @@ Kareem.prototype.wrap = function(name, fn, context, args, options) {
260
308
  const checkForPromise = options.checkForPromise;
261
309
 
262
310
  this.execPre(name, context, args, function(error) {
263
- if (error) {
311
+ if (error && !(error instanceof Kareem.skipWrappedFunction)) {
264
312
  const numCallbackParams = options.numCallbackParams || 0;
265
313
  const errorArgs = options.contextParameter ? [context] : [];
266
314
  for (var i = errorArgs.length; i < numCallbackParams; ++i) {
@@ -272,10 +320,16 @@ Kareem.prototype.wrap = function(name, fn, context, args, options) {
272
320
 
273
321
  const numParameters = fn.length;
274
322
  let ret;
275
- try {
276
- ret = fn.apply(context, argsWithoutCb.concat(_cb));
277
- } catch (err) {
278
- return _cb(err);
323
+
324
+ if (error instanceof Kareem.skipWrappedFunction) {
325
+ ret = error.args[0];
326
+ return _cb(null, ...error.args);
327
+ } else {
328
+ try {
329
+ ret = fn.apply(context, argsWithoutCb.concat(_cb));
330
+ } catch (err) {
331
+ return _cb(err);
332
+ }
279
333
  }
280
334
 
281
335
  if (checkForPromise) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kareem",
3
- "version": "2.3.5",
3
+ "version": "2.4.0",
4
4
  "description": "Next-generation take on pre/post function hooks",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/test/post.test.js CHANGED
@@ -165,6 +165,71 @@ describe('execPost', function() {
165
165
  done();
166
166
  });
167
167
  });
168
+
169
+ it('supports overwriteResult', function(done) {
170
+ hooks.post('cook', function(eggs, callback) {
171
+ callback(Kareem.overwriteResult(5));
172
+ });
173
+
174
+ hooks.post('cook', function(eggs, callback) {
175
+ assert.equal(eggs, 5);
176
+ callback();
177
+ });
178
+
179
+ var options = {};
180
+ hooks.execPost('cook', null, [4], options, function(error, eggs) {
181
+ assert.equal(eggs, 5);
182
+ done();
183
+ });
184
+ });
185
+
186
+ it('supports sync returning overwriteResult', function(done) {
187
+ hooks.post('cook', function() {
188
+ return Kareem.overwriteResult(5);
189
+ });
190
+
191
+ hooks.post('cook', function(eggs, callback) {
192
+ assert.equal(eggs, 5);
193
+ callback();
194
+ });
195
+
196
+ var options = {};
197
+ hooks.execPost('cook', null, [4], options, function(error, eggs) {
198
+ assert.ifError(error);
199
+ assert.equal(eggs, 5);
200
+ done();
201
+ });
202
+ });
203
+
204
+ it('supports sync overwriteResult', function() {
205
+ hooks.post('cook', function(eggs) {
206
+ return Kareem.overwriteResult(5);
207
+ });
208
+
209
+ hooks.post('cook', function(eggs) {
210
+ assert.equal(eggs, 5);
211
+ });
212
+
213
+ var options = {};
214
+ const res = hooks.execPostSync('cook', null, [4], options);
215
+ assert.deepEqual(res, [5]);
216
+ });
217
+
218
+ it('supports overwriteResult with promises', function(done) {
219
+ hooks.post('cook', function(eggs) {
220
+ return Promise.resolve(Kareem.overwriteResult(5));
221
+ });
222
+
223
+ hooks.post('cook', function(eggs) {
224
+ assert.equal(eggs, 5);
225
+ });
226
+
227
+ var options = {};
228
+ hooks.execPost('cook', null, [4], options, function(error, eggs) {
229
+ assert.equal(eggs, 5);
230
+ done();
231
+ });
232
+ });
168
233
  });
169
234
 
170
235
  describe('execPostSync', function() {
package/test/pre.test.js CHANGED
@@ -307,6 +307,24 @@ describe('execPre', function() {
307
307
  done();
308
308
  });
309
309
  });
310
+
311
+ it('supports skipWrappedFunction', function(done) {
312
+ var execed = {};
313
+
314
+ hooks.pre('cook', function(callback) {
315
+ callback(Kareem.skipWrappedFunction(42));
316
+ });
317
+
318
+ hooks.pre('cook', function() {
319
+ execed.second = true;
320
+ });
321
+
322
+ hooks.execPre('cook', null, function(err) {
323
+ assert.ok(execed.second);
324
+ assert.ok(err instanceof Kareem.skipWrappedFunction);
325
+ done();
326
+ });
327
+ });
310
328
  });
311
329
 
312
330
  describe('execPreSync', function() {
package/test/wrap.test.js CHANGED
@@ -287,6 +287,91 @@ describe('wrap()', function() {
287
287
  25);
288
288
  });
289
289
 
290
+ it('supports overwriteResult', function(done) {
291
+ hooks.post('cook', function(eggs, callback) {
292
+ callback(Kareem.overwriteResult(5));
293
+ });
294
+
295
+ const args = [(err, res) => {
296
+ assert.ifError(err);
297
+ assert.equal(res, 5);
298
+ done();
299
+ }];
300
+
301
+ hooks.wrap(
302
+ 'cook',
303
+ function(callback) {
304
+ callback(null, 4);
305
+ },
306
+ null,
307
+ args);
308
+ });
309
+
310
+ it('supports skipWrappedFunction', function(done) {
311
+ const execed = {};
312
+ hooks.pre('cook', function pre(callback) {
313
+ execed.pre = true;
314
+ callback(Kareem.skipWrappedFunction(3));
315
+ });
316
+
317
+ hooks.post('cook', function(res, callback) {
318
+ assert.equal(res, 3);
319
+ execed.post = true;
320
+ callback();
321
+ });
322
+
323
+ const args = [(err, res) => {
324
+ assert.ifError(err);
325
+ assert.equal(res, 3);
326
+ assert.ok(execed.pre);
327
+ assert.ok(execed.post);
328
+ assert.ok(!execed.wrapped);
329
+ done();
330
+ }];
331
+
332
+ hooks.wrap(
333
+ 'cook',
334
+ function wrapped(callback) {
335
+ execed.wrapped = true;
336
+ callback();
337
+ },
338
+ null,
339
+ args);
340
+ });
341
+
342
+ it('supports skipWrappedFunction with arguments', function(done) {
343
+ const execed = {};
344
+ hooks.pre('cook', function pre(callback, arg) {
345
+ execed.pre = true;
346
+ assert.strictEqual(arg, 4);
347
+ callback(Kareem.skipWrappedFunction(3));
348
+ });
349
+
350
+ hooks.post('cook', function(res, callback) {
351
+ assert.equal(res, 3);
352
+ execed.post = true;
353
+ callback();
354
+ });
355
+
356
+ const args = [4, (err, res) => {
357
+ assert.ifError(err);
358
+ assert.equal(res, 3);
359
+ assert.ok(execed.pre);
360
+ assert.ok(execed.post);
361
+ assert.ok(!execed.wrapped);
362
+ done();
363
+ }];
364
+
365
+ hooks.wrap(
366
+ 'cook',
367
+ function wrapped(arg, callback) {
368
+ execed.wrapped = true;
369
+ callback();
370
+ },
371
+ null,
372
+ args);
373
+ });
374
+
290
375
  it('handles post errors with no args', function(done) {
291
376
  hooks.pre('cook', function(done) {
292
377
  obj.waffles = false;
@@ -363,4 +448,17 @@ describe('wrap()', function() {
363
448
  assert.equal(calledFn, 1);
364
449
  assert.equal(calledPost, 1);
365
450
  });
451
+
452
+ it('sync wrappers with overwriteResult', function() {
453
+ hooks.pre('cook', function() {
454
+ });
455
+
456
+ hooks.post('cook', function() {
457
+ return Kareem.overwriteResult(5);
458
+ });
459
+
460
+ const wrapper = hooks.createWrapperSync('cook', function() { return 4; });
461
+
462
+ assert.strictEqual(wrapper(), 5);
463
+ });
366
464
  });