@logosdx/hooks 1.0.0-beta.0 → 1.0.0-beta.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/dist/cjs/index.js CHANGED
@@ -28,6 +28,9 @@ function _array_like_to_array(arr, len) {
28
28
  function _array_with_holes(arr) {
29
29
  if (Array.isArray(arr)) return arr;
30
30
  }
31
+ function _array_without_holes(arr) {
32
+ if (Array.isArray(arr)) return _array_like_to_array(arr);
33
+ }
31
34
  function _assert_this_initialized(self) {
32
35
  if (self === void 0) {
33
36
  throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
@@ -112,6 +115,16 @@ function _class_private_field_set(receiver, privateMap, value) {
112
115
  _class_apply_descriptor_set(receiver, descriptor, value);
113
116
  return value;
114
117
  }
118
+ function _class_private_method_get(receiver, privateSet, fn) {
119
+ if (!privateSet.has(receiver)) {
120
+ throw new TypeError("attempted to get private field on non-instance");
121
+ }
122
+ return fn;
123
+ }
124
+ function _class_private_method_init(obj, privateSet) {
125
+ _check_private_redeclaration(obj, privateSet);
126
+ privateSet.add(obj);
127
+ }
115
128
  function _construct(Parent, args, Class) {
116
129
  if (_is_native_reflect_construct()) {
117
130
  _construct = Reflect.construct;
@@ -185,6 +198,9 @@ function _instanceof(left, right) {
185
198
  function _is_native_function(fn) {
186
199
  return Function.toString.call(fn).indexOf("[native code]") !== -1;
187
200
  }
201
+ function _iterable_to_array(iter) {
202
+ if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
203
+ }
188
204
  function _iterable_to_array_limit(arr, i) {
189
205
  var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
190
206
  if (_i == null) return;
@@ -212,6 +228,9 @@ function _iterable_to_array_limit(arr, i) {
212
228
  function _non_iterable_rest() {
213
229
  throw new TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
214
230
  }
231
+ function _non_iterable_spread() {
232
+ throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
233
+ }
215
234
  function _object_spread(target) {
216
235
  for(var i = 1; i < arguments.length; i++){
217
236
  var source = arguments[i] != null ? arguments[i] : {};
@@ -243,6 +262,9 @@ function _set_prototype_of(o, p) {
243
262
  function _sliced_to_array(arr, i) {
244
263
  return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest();
245
264
  }
265
+ function _to_consumable_array(arr) {
266
+ return _array_without_holes(arr) || _iterable_to_array(arr) || _unsupported_iterable_to_array(arr) || _non_iterable_spread();
267
+ }
246
268
  function _type_of(obj) {
247
269
  "@swc/helpers - typeof";
248
270
  return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj;
@@ -402,7 +424,7 @@ var HookError = /*#__PURE__*/ function(Error1) {
402
424
  var _this;
403
425
  _this = _call_super(this, HookError, [
404
426
  message
405
- ]), /** Name of the hook where the error occurred */ _define_property(_this, "hookName", void 0), /** Extension point where the error occurred: 'before', 'after', or 'error' */ _define_property(_this, "extPoint", void 0), /** Original error if `fail()` was called with an Error instance */ _define_property(_this, "originalError", void 0), /** Whether the hook was explicitly aborted via `fail()` */ _define_property(_this, "aborted", false);
427
+ ]), /** Name of the hook where the error occurred */ _define_property(_this, "hookName", void 0), /** Original error if `fail()` was called with an Error instance */ _define_property(_this, "originalError", void 0);
406
428
  return _this;
407
429
  }
408
430
  return HookError;
@@ -411,386 +433,474 @@ var isHookError = function(error) {
411
433
  var _error_constructor;
412
434
  return (error === null || error === void 0 ? void 0 : (_error_constructor = error.constructor) === null || _error_constructor === void 0 ? void 0 : _error_constructor.name) === HookError.name;
413
435
  };
414
- var Hook = function Hook() {
415
- "use strict";
416
- _class_call_check(this, Hook);
417
- _define_property(this, "before", new Set());
418
- _define_property(this, "after", new Set());
419
- _define_property(this, "error", new Set());
420
- };
421
- var allowedExtPoints = new Set([
422
- 'before',
423
- 'after',
424
- 'error'
425
- ]);
426
- var _registered = /*#__PURE__*/ new WeakMap(), _hooks = /*#__PURE__*/ new WeakMap(), _hookFnOpts = /*#__PURE__*/ new WeakMap(), _wrapped = /*#__PURE__*/ new WeakMap();
436
+ var _hooks = /*#__PURE__*/ new WeakMap(), _hookOpts = /*#__PURE__*/ new WeakMap(), _handleFail = /*#__PURE__*/ new WeakMap(), _registered = /*#__PURE__*/ new WeakMap(), /**
437
+ * Validate that a hook is registered (if registration is enabled).
438
+ */ _assertRegistered = /*#__PURE__*/ new WeakSet();
427
439
  var HookEngine = /*#__PURE__*/ function() {
428
440
  "use strict";
429
441
  function HookEngine() {
442
+ var options = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
430
443
  _class_call_check(this, HookEngine);
431
- _class_private_field_init(this, _registered, {
432
- writable: true,
433
- value: new Set()
434
- });
444
+ _class_private_method_init(this, _assertRegistered);
435
445
  _class_private_field_init(this, _hooks, {
436
446
  writable: true,
437
447
  value: new Map()
438
448
  });
439
- _class_private_field_init(this, _hookFnOpts, {
449
+ _class_private_field_init(this, _hookOpts, {
440
450
  writable: true,
441
451
  value: new WeakMap()
442
452
  });
443
- _class_private_field_init(this, _wrapped, {
453
+ _class_private_field_init(this, _handleFail, {
444
454
  writable: true,
445
- value: new WeakMap()
455
+ value: void 0
456
+ });
457
+ _class_private_field_init(this, _registered, {
458
+ writable: true,
459
+ value: null
460
+ });
461
+ var _options_handleFail;
462
+ _class_private_field_set(this, _handleFail, (_options_handleFail = options.handleFail) !== null && _options_handleFail !== void 0 ? _options_handleFail : function(message) {
463
+ throw new HookError(message);
446
464
  });
447
465
  }
448
466
  _create_class(HookEngine, [
449
467
  {
450
468
  /**
451
- * Add an extension to a registered hook.
469
+ * Register hook names for runtime validation.
470
+ * Once any hooks are registered, all hooks must be registered before use.
452
471
  *
453
- * Extensions run at specific points in the hook lifecycle:
454
- * - `before`: Runs before the original function. Can modify args or return early.
455
- * - `after`: Runs after successful execution. Can modify the result.
456
- * - `error`: Runs when the original function throws. Can handle or transform errors.
472
+ * @param names - Hook names to register
473
+ * @returns this (for chaining)
457
474
  *
458
- * @param name - Name of the registered hook to extend
459
- * @param extensionPoint - When to run: 'before', 'after', or 'error'
460
- * @param cbOrOpts - Extension callback or options object
461
- * @returns Cleanup function to remove the extension
475
+ * @example
476
+ * const hooks = new HookEngine<FetchLifecycle>()
477
+ * .register('preRequest', 'postRequest', 'rateLimit');
478
+ *
479
+ * hooks.on('preRequest', cb); // OK
480
+ * hooks.on('preRequset', cb); // Error: not registered (typo caught!)
481
+ */ key: "register",
482
+ value: function register() {
483
+ for(var _len = arguments.length, names = new Array(_len), _key = 0; _key < _len; _key++){
484
+ names[_key] = arguments[_key];
485
+ }
486
+ (0, _utils.assert)(names.length > 0, 'register() requires at least one hook name');
487
+ if (_class_private_field_get(this, _registered) === null) {
488
+ _class_private_field_set(this, _registered, new Set());
489
+ }
490
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
491
+ try {
492
+ for(var _iterator = names[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
493
+ var name = _step.value;
494
+ (0, _utils.assert)(typeof name === 'string', "Hook name must be a string, got ".concat(typeof name === "undefined" ? "undefined" : _type_of(name)));
495
+ _class_private_field_get(this, _registered).add(name);
496
+ }
497
+ } catch (err) {
498
+ _didIteratorError = true;
499
+ _iteratorError = err;
500
+ } finally{
501
+ try {
502
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
503
+ _iterator.return();
504
+ }
505
+ } finally{
506
+ if (_didIteratorError) {
507
+ throw _iteratorError;
508
+ }
509
+ }
510
+ }
511
+ return this;
512
+ }
513
+ },
514
+ {
515
+ /**
516
+ * Subscribe to a lifecycle hook.
517
+ *
518
+ * @param name - Name of the lifecycle hook
519
+ * @param cbOrOpts - Callback function or options object
520
+ * @returns Cleanup function to remove the subscription
462
521
  *
463
522
  * @example
464
523
  * // Simple callback
465
- * const cleanup = hooks.extend('save', 'before', async (ctx) => {
466
- * console.log('About to save:', ctx.args);
524
+ * const cleanup = hooks.on('preRequest', async (ctx) => {
525
+ * console.log('Request:', ctx.args[0]);
467
526
  * });
468
527
  *
469
528
  * // With options
470
- * hooks.extend('save', 'after', {
471
- * callback: async (ctx) => { console.log('Saved!'); },
529
+ * hooks.on('analytics', {
530
+ * callback: async (ctx) => { track(ctx.args); },
472
531
  * once: true, // Remove after first run
473
- * ignoreOnFail: true // Don't throw if this extension fails
532
+ * ignoreOnFail: true // Don't throw if callback fails
474
533
  * });
475
534
  *
476
- * // Later: remove the extension
535
+ * // Remove subscription
477
536
  * cleanup();
478
- */ key: "extend",
479
- value: function extend(name, extensionPoint, cbOrOpts) {
537
+ */ key: "on",
538
+ value: function on(name, cbOrOpts) {
480
539
  var callback = typeof cbOrOpts === 'function' ? cbOrOpts : cbOrOpts === null || cbOrOpts === void 0 ? void 0 : cbOrOpts.callback;
481
540
  var opts = typeof cbOrOpts === 'function' ? {} : cbOrOpts;
482
541
  (0, _utils.assert)(typeof name === 'string', '"name" must be a string');
483
- (0, _utils.assert)(_class_private_field_get(this, _registered).has(name), "'".concat(name.toString(), "' is not a registered hook"));
484
- (0, _utils.assert)(typeof extensionPoint === 'string', '"extensionPoint" must be a string');
485
- (0, _utils.assert)(allowedExtPoints.has(extensionPoint), "'".concat(extensionPoint, "' is not a valid extension point"));
486
- (0, _utils.assert)((0, _utils.isFunction)(callback) || (0, _utils.isObject)(cbOrOpts), '"cbOrOpts" must be a extension callback or options');
542
+ (0, _utils.assert)((0, _utils.isFunction)(callback) || (0, _utils.isObject)(cbOrOpts), '"cbOrOpts" must be a callback or options');
487
543
  (0, _utils.assert)((0, _utils.isFunction)(callback), 'callback must be a function');
544
+ _class_private_method_get(this, _assertRegistered, assertRegistered).call(this, name, 'on');
488
545
  var _class_private_field_get_get;
489
- var hook = (_class_private_field_get_get = _class_private_field_get(this, _hooks).get(name)) !== null && _class_private_field_get_get !== void 0 ? _class_private_field_get_get : new Hook();
490
- hook[extensionPoint].add(callback);
491
- _class_private_field_get(this, _hooks).set(name, hook);
492
- _class_private_field_get(this, _hookFnOpts).set(callback, opts);
493
- /**
494
- * Removes the registered hook extension
495
- */ return function() {
496
- hook[extensionPoint].delete(callback);
546
+ var hooks = (_class_private_field_get_get = _class_private_field_get(this, _hooks).get(name)) !== null && _class_private_field_get_get !== void 0 ? _class_private_field_get_get : new Set();
547
+ hooks.add(callback);
548
+ _class_private_field_get(this, _hooks).set(name, hooks);
549
+ _class_private_field_get(this, _hookOpts).set(callback, opts);
550
+ return function() {
551
+ hooks.delete(callback);
497
552
  };
498
553
  }
499
554
  },
500
555
  {
501
556
  /**
502
- * Register a function as a hookable and return the wrapped version.
557
+ * Subscribe to a lifecycle hook that fires only once.
558
+ * Sugar for `on(name, { callback, once: true })`.
559
+ *
560
+ * @param name - Name of the lifecycle hook
561
+ * @param callback - Callback function
562
+ * @returns Cleanup function to remove the subscription
503
563
  *
504
- * The wrapped function behaves identically to the original but allows
505
- * extensions to be added via `extend()`. Use `wrap()` for a simpler API
506
- * when working with object methods.
564
+ * @example
565
+ * // Log only the first request
566
+ * hooks.once('preRequest', async (ctx) => {
567
+ * console.log('First request:', ctx.args[0]);
568
+ * });
569
+ */ key: "once",
570
+ value: function once(name, callback) {
571
+ return this.on(name, {
572
+ callback: callback,
573
+ once: true
574
+ });
575
+ }
576
+ },
577
+ {
578
+ key: "emit",
579
+ value: /**
580
+ * Emit a lifecycle hook, running all subscribed callbacks.
507
581
  *
508
- * @param name - Unique name for this hook (must match a key in Shape)
509
- * @param cb - The original function to wrap
510
- * @param opts - Options for the wrapped function
511
- * @returns Wrapped function with hook support
582
+ * @param name - Name of the lifecycle hook to emit
583
+ * @param args - Arguments to pass to callbacks
584
+ * @returns EmitResult with final args, result, and earlyReturn flag
512
585
  *
513
586
  * @example
514
- * const hooks = new HookEngine<{ fetch: typeof fetch }>();
587
+ * const result = await hooks.emit('cacheCheck', url);
515
588
  *
516
- * const hookedFetch = hooks.make('fetch', fetch);
589
+ * if (result.earlyReturn && result.result) {
590
+ * return result.result; // Use cached value
591
+ * }
517
592
  *
518
- * hooks.extend('fetch', 'before', async (ctx) => {
519
- * console.log('Fetching:', ctx.args[0]);
593
+ * // Continue with modified args
594
+ * const [modifiedUrl] = result.args;
595
+ */ function emit(name) {
596
+ for(var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++){
597
+ args[_key - 1] = arguments[_key];
598
+ }
599
+ return _async_to_generator(function() {
600
+ var _this, earlyReturn, hooks, context, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _this1, _loop, _iterator, _step, _ret, err;
601
+ return _ts_generator(this, function(_state) {
602
+ switch(_state.label){
603
+ case 0:
604
+ _this = this;
605
+ _class_private_method_get(this, _assertRegistered, assertRegistered).call(this, name, 'emit');
606
+ earlyReturn = false;
607
+ hooks = _class_private_field_get(this, _hooks).get(name);
608
+ context = {
609
+ args: args,
610
+ removeHook: function removeHook() {},
611
+ returnEarly: function returnEarly() {
612
+ earlyReturn = true;
613
+ },
614
+ setArgs: function(next) {
615
+ (0, _utils.assert)(Array.isArray(next), "setArgs: args for '".concat(String(name), "' must be an array"));
616
+ context.args = next;
617
+ },
618
+ setResult: function(next) {
619
+ context.result = next;
620
+ },
621
+ fail: function() {
622
+ for(var _len = arguments.length, failArgs = new Array(_len), _key = 0; _key < _len; _key++){
623
+ failArgs[_key] = arguments[_key];
624
+ }
625
+ var _handler_prototype;
626
+ var handler = _class_private_field_get(_this, _handleFail);
627
+ // Check if handler is a constructor (class or function with prototype)
628
+ var isConstructor = typeof handler === 'function' && ((_handler_prototype = handler.prototype) === null || _handler_prototype === void 0 ? void 0 : _handler_prototype.constructor) === handler;
629
+ var _attemptSync = _sliced_to_array((0, _utils.attemptSync)(function() {
630
+ if (isConstructor) {
631
+ throw _construct(handler, _to_consumable_array(failArgs));
632
+ }
633
+ handler.apply(void 0, _to_consumable_array(failArgs));
634
+ }), 2), error = _attemptSync[1];
635
+ if (error) {
636
+ if (_instanceof(error, HookError)) {
637
+ error.hookName = String(name);
638
+ }
639
+ throw error;
640
+ }
641
+ // If handler didn't throw, we need to throw something
642
+ throw new HookError('ctx.fail() handler did not throw');
643
+ }
644
+ };
645
+ if (!hooks || hooks.size === 0) {
646
+ return [
647
+ 2,
648
+ {
649
+ args: context.args,
650
+ result: context.result,
651
+ earlyReturn: false
652
+ }
653
+ ];
654
+ }
655
+ _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
656
+ _state.label = 1;
657
+ case 1:
658
+ _state.trys.push([
659
+ 1,
660
+ 6,
661
+ 7,
662
+ 8
663
+ ]);
664
+ _loop = function() {
665
+ var fn, _class_private_field_get_get, opts, _ref, _$err;
666
+ return _ts_generator(this, function(_state) {
667
+ switch(_state.label){
668
+ case 0:
669
+ fn = _step.value;
670
+ context.removeHook = function() {
671
+ return hooks.delete(fn);
672
+ };
673
+ opts = (_class_private_field_get_get = _class_private_field_get(_this1, _hookOpts).get(fn)) !== null && _class_private_field_get_get !== void 0 ? _class_private_field_get_get : {
674
+ callback: fn
675
+ };
676
+ return [
677
+ 4,
678
+ (0, _utils.attempt)(function() {
679
+ return fn(_object_spread({}, context));
680
+ })
681
+ ];
682
+ case 1:
683
+ _ref = _sliced_to_array.apply(void 0, [
684
+ _state.sent(),
685
+ 2
686
+ ]), _$err = _ref[1];
687
+ if (opts.once) context.removeHook();
688
+ if (_$err && opts.ignoreOnFail !== true) {
689
+ throw _$err;
690
+ }
691
+ if (earlyReturn) return [
692
+ 2,
693
+ "break"
694
+ ];
695
+ return [
696
+ 2
697
+ ];
698
+ }
699
+ });
700
+ };
701
+ _iterator = hooks[Symbol.iterator]();
702
+ _state.label = 2;
703
+ case 2:
704
+ if (!!(_iteratorNormalCompletion = (_step = _iterator.next()).done)) return [
705
+ 3,
706
+ 5
707
+ ];
708
+ _this1 = this;
709
+ return [
710
+ 5,
711
+ _ts_values(_loop())
712
+ ];
713
+ case 3:
714
+ _ret = _state.sent();
715
+ if (_ret === "break") return [
716
+ 3,
717
+ 5
718
+ ];
719
+ _state.label = 4;
720
+ case 4:
721
+ _iteratorNormalCompletion = true;
722
+ return [
723
+ 3,
724
+ 2
725
+ ];
726
+ case 5:
727
+ return [
728
+ 3,
729
+ 8
730
+ ];
731
+ case 6:
732
+ err = _state.sent();
733
+ _didIteratorError = true;
734
+ _iteratorError = err;
735
+ return [
736
+ 3,
737
+ 8
738
+ ];
739
+ case 7:
740
+ try {
741
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
742
+ _iterator.return();
743
+ }
744
+ } finally{
745
+ if (_didIteratorError) {
746
+ throw _iteratorError;
747
+ }
748
+ }
749
+ return [
750
+ 7
751
+ ];
752
+ case 8:
753
+ return [
754
+ 2,
755
+ {
756
+ args: context.args,
757
+ result: context.result,
758
+ earlyReturn: earlyReturn
759
+ }
760
+ ];
761
+ }
762
+ });
763
+ }).call(this);
764
+ }
765
+ },
766
+ {
767
+ /**
768
+ * Clear all registered hooks.
769
+ *
770
+ * @example
771
+ * hooks.on('preRequest', validator);
772
+ * hooks.on('postRequest', logger);
773
+ *
774
+ * // Reset for testing
775
+ * hooks.clear();
776
+ */ key: "clear",
777
+ value: function clear() {
778
+ _class_private_field_get(this, _hooks).clear();
779
+ _class_private_field_set(this, _hookOpts, new WeakMap());
780
+ _class_private_field_set(this, _registered, null);
781
+ }
782
+ },
783
+ {
784
+ /**
785
+ * Wrap a function with pre/post lifecycle hooks.
786
+ *
787
+ * - Pre hook: emitted with function args, can modify args or returnEarly with result
788
+ * - Post hook: emitted with [result, ...args], can modify result
789
+ *
790
+ * @param fn - The async function to wrap
791
+ * @param hooks - Object with optional pre and post hook names
792
+ * @returns Wrapped function with same signature
793
+ *
794
+ * @example
795
+ * interface Lifecycle {
796
+ * preRequest(url: string, opts: RequestInit): Promise<Response>;
797
+ * postRequest(result: Response, url: string, opts: RequestInit): Promise<Response>;
798
+ * }
799
+ *
800
+ * const hooks = new HookEngine<Lifecycle>();
801
+ *
802
+ * // Add cache check in pre hook
803
+ * hooks.on('preRequest', async (ctx) => {
804
+ * const cached = cache.get(ctx.args[0]);
805
+ * if (cached) {
806
+ * ctx.setResult(cached);
807
+ * ctx.returnEarly();
808
+ * }
809
+ * });
810
+ *
811
+ * // Log result in post hook
812
+ * hooks.on('postRequest', async (ctx) => {
813
+ * const [result, url] = ctx.args;
814
+ * console.log(`Fetched ${url}:`, result.status);
520
815
  * });
521
816
  *
522
- * await hookedFetch('/api/data');
523
- */ key: "make",
524
- value: function make(name, cb) {
525
- var opts = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : {};
817
+ * // Wrap the fetch function
818
+ * const wrappedFetch = hooks.wrap(
819
+ * async (url: string, opts: RequestInit) => fetch(url, opts),
820
+ * { pre: 'preRequest', post: 'postRequest' }
821
+ * );
822
+ */ key: "wrap",
823
+ value: function wrap(fn, hooks) {
526
824
  var _this = this;
527
- (0, _utils.assert)(typeof name === 'string', '"name" must be a string');
528
- (0, _utils.assert)(!_class_private_field_get(this, _registered).has(name), "'".concat(name.toString(), "' hook is already registered"));
529
- (0, _utils.assert)((0, _utils.isFunction)(cb), '"cb" must be a function');
530
- (0, _utils.assert)((0, _utils.isObject)(opts), '"opts" must be an object');
531
- _class_private_field_get(this, _registered).add(name);
532
- if (_class_private_field_get(this, _wrapped).has(cb)) {
533
- return _class_private_field_get(this, _wrapped).get(cb);
534
- }
535
- var callback = function() {
536
- for(var _len = arguments.length, origArgs = new Array(_len), _key = 0; _key < _len; _key++){
537
- origArgs[_key] = arguments[_key];
825
+ (0, _utils.assert)(hooks.pre || hooks.post, 'wrap() requires at least one of "pre" or "post" hooks');
826
+ if (hooks.pre) _class_private_method_get(this, _assertRegistered, assertRegistered).call(this, hooks.pre, 'wrap');
827
+ if (hooks.post) _class_private_method_get(this, _assertRegistered, assertRegistered).call(this, hooks.post, 'wrap');
828
+ return function() {
829
+ for(var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++){
830
+ args[_key] = arguments[_key];
538
831
  }
539
832
  return _async_to_generator(function() {
540
- var _this, returnEarly, hook, context, _ref, before, after, errorFns, handleSet, _ref1, res, err;
833
+ var currentArgs, result, preResult, postResult;
541
834
  return _ts_generator(this, function(_state) {
542
835
  switch(_state.label){
543
836
  case 0:
544
- _this = this;
545
- returnEarly = false;
546
- hook = _class_private_field_get(this, _hooks).get(name);
547
- context = {
548
- args: origArgs,
549
- point: 'before',
550
- removeHook: function removeHook() {},
551
- returnEarly: function returnEarly1() {
552
- returnEarly = true;
553
- },
554
- setArgs: function setArgs(next) {
555
- (0, _utils.assert)(Array.isArray(next), "setArgs: next args for '".concat(context.point, "' '").concat(name.toString(), "' must be an array of arguments"));
556
- context.args = next;
557
- },
558
- setResult: function setResult(next) {
559
- context.results = next;
560
- },
561
- fail: function fail(reason) {
562
- var error = new HookError("Hook Aborted: ".concat(reason !== null && reason !== void 0 ? reason : 'unknown'));
563
- if (_instanceof(reason, Error)) {
564
- error.originalError = reason;
565
- }
566
- error.extPoint = context.point;
567
- error.hookName = name;
568
- throw error;
569
- }
570
- };
571
- _ref = hook !== null && hook !== void 0 ? hook : new Hook(), before = _ref.before, after = _ref.after, errorFns = _ref.error;
572
- handleSet = function(which, point) {
573
- return _async_to_generator(function() {
574
- var _iteratorNormalCompletion, _didIteratorError, _iteratorError, _this, _loop, _iterator, _step, _ret, err;
575
- return _ts_generator(this, function(_state) {
576
- switch(_state.label){
577
- case 0:
578
- context.point = point;
579
- _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
580
- _state.label = 1;
581
- case 1:
582
- _state.trys.push([
583
- 1,
584
- 6,
585
- 7,
586
- 8
587
- ]);
588
- _loop = function() {
589
- var fn, opts, _ref, _$err;
590
- return _ts_generator(this, function(_state) {
591
- switch(_state.label){
592
- case 0:
593
- fn = _step.value;
594
- context.removeHook = function() {
595
- return which.delete(fn);
596
- };
597
- opts = _class_private_field_get(_this, _hookFnOpts).get(fn);
598
- return [
599
- 4,
600
- (0, _utils.attempt)(function() {
601
- return fn(_object_spread({}, context));
602
- })
603
- ];
604
- case 1:
605
- _ref = _sliced_to_array.apply(void 0, [
606
- _state.sent(),
607
- 2
608
- ]), _$err = _ref[1];
609
- if (opts.once) context.removeHook();
610
- if (_$err && opts.ignoreOnFail !== true) {
611
- throw _$err;
612
- }
613
- if (returnEarly) return [
614
- 2,
615
- "break"
616
- ];
617
- return [
618
- 2
619
- ];
620
- }
621
- });
622
- };
623
- _iterator = which[Symbol.iterator]();
624
- _state.label = 2;
625
- case 2:
626
- if (!!(_iteratorNormalCompletion = (_step = _iterator.next()).done)) return [
627
- 3,
628
- 5
629
- ];
630
- _this = this;
631
- return [
632
- 5,
633
- _ts_values(_loop())
634
- ];
635
- case 3:
636
- _ret = _state.sent();
637
- if (_ret === "break") return [
638
- 3,
639
- 5
640
- ];
641
- _state.label = 4;
642
- case 4:
643
- _iteratorNormalCompletion = true;
644
- return [
645
- 3,
646
- 2
647
- ];
648
- case 5:
649
- return [
650
- 3,
651
- 8
652
- ];
653
- case 6:
654
- err = _state.sent();
655
- _didIteratorError = true;
656
- _iteratorError = err;
657
- return [
658
- 3,
659
- 8
660
- ];
661
- case 7:
662
- try {
663
- if (!_iteratorNormalCompletion && _iterator.return != null) {
664
- _iterator.return();
665
- }
666
- } finally{
667
- if (_didIteratorError) {
668
- throw _iteratorError;
669
- }
670
- }
671
- return [
672
- 7
673
- ];
674
- case 8:
675
- return [
676
- 2
677
- ];
678
- }
679
- });
680
- }).call(_this);
681
- };
837
+ currentArgs = args;
838
+ if (!hooks.pre) return [
839
+ 3,
840
+ 2
841
+ ];
682
842
  return [
683
843
  4,
684
- handleSet(before, 'before')
844
+ this.emit.apply(this, [
845
+ hooks.pre
846
+ ].concat(_to_consumable_array(currentArgs)))
685
847
  ];
686
848
  case 1:
687
- _state.sent();
688
- if (returnEarly) return [
689
- 2,
690
- context.results
691
- ];
849
+ preResult = _state.sent();
850
+ currentArgs = preResult.args;
851
+ if (preResult.earlyReturn && preResult.result !== undefined) {
852
+ return [
853
+ 2,
854
+ preResult.result
855
+ ];
856
+ }
857
+ _state.label = 2;
858
+ case 2:
692
859
  return [
693
860
  4,
694
- (0, _utils.attempt)(function() {
695
- return cb.apply((opts === null || opts === void 0 ? void 0 : opts.bindTo) || cb, context.args);
696
- })
861
+ fn.apply(void 0, _to_consumable_array(currentArgs))
697
862
  ];
698
- case 2:
699
- _ref1 = _sliced_to_array.apply(void 0, [
700
- _state.sent(),
701
- 2
702
- ]), res = _ref1[0], err = _ref1[1];
703
- context.results = res;
704
- context.error = err;
705
- if (!err) return [
863
+ case 3:
864
+ // Execute function
865
+ result = _state.sent();
866
+ if (!hooks.post) return [
706
867
  3,
707
- 4
868
+ 5
708
869
  ];
709
- context.point = 'error';
710
870
  return [
711
871
  4,
712
- handleSet(errorFns, 'error')
872
+ this.emit.apply(this, [
873
+ hooks.post
874
+ ].concat(_to_consumable_array([
875
+ result
876
+ ].concat(_to_consumable_array(currentArgs)))))
713
877
  ];
714
- case 3:
715
- _state.sent();
716
- throw err;
717
878
  case 4:
718
- return [
719
- 4,
720
- handleSet(after, 'after')
721
- ];
879
+ postResult = _state.sent();
880
+ if (postResult.result !== undefined) {
881
+ return [
882
+ 2,
883
+ postResult.result
884
+ ];
885
+ }
886
+ _state.label = 5;
722
887
  case 5:
723
- _state.sent();
724
888
  return [
725
889
  2,
726
- context.results
890
+ result
727
891
  ];
728
892
  }
729
893
  });
730
894
  }).call(_this);
731
895
  };
732
- return callback;
733
- }
734
- },
735
- {
736
- /**
737
- * Wrap an object method in-place to make it hookable.
738
- *
739
- * This is a convenience method that combines `make()` with automatic
740
- * binding and reassignment. The method is replaced on the instance
741
- * with the wrapped version.
742
- *
743
- * @param instance - Object containing the method to wrap
744
- * @param name - Name of the method to wrap
745
- * @param opts - Additional options
746
- *
747
- * @example
748
- * class UserService {
749
- * async save(user: User) { ... }
750
- * }
751
- *
752
- * const service = new UserService();
753
- * const hooks = new HookEngine<UserService>();
754
- *
755
- * hooks.wrap(service, 'save');
756
- *
757
- * // Now service.save() is hookable
758
- * hooks.extend('save', 'before', async (ctx) => {
759
- * console.log('Saving user:', ctx.args[0]);
760
- * });
761
- */ key: "wrap",
762
- value: function wrap(instance, name, opts) {
763
- (0, _utils.assert)((0, _utils.isObject)(instance), '"instance" must be an object');
764
- var wrapped = this.make(name, instance[name], _object_spread({
765
- bindTo: instance
766
- }, opts));
767
- _class_private_field_get(this, _wrapped).set(wrapped, instance[name]);
768
- instance[name] = wrapped;
769
- }
770
- },
771
- {
772
- /**
773
- * Clear all registered hooks and extensions.
774
- *
775
- * After calling this method, all hooks are unregistered and all
776
- * extensions are removed. Previously wrapped functions will continue
777
- * to work but without any extensions.
778
- *
779
- * @example
780
- * hooks.wrap(app, 'save');
781
- * hooks.extend('save', 'before', validator);
782
- *
783
- * // Reset for testing
784
- * hooks.clear();
785
- *
786
- * // app.save() still works, but validator no longer runs
787
- */ key: "clear",
788
- value: function clear() {
789
- _class_private_field_get(this, _registered).clear();
790
- _class_private_field_get(this, _hooks).clear();
791
- _class_private_field_set(this, _hookFnOpts, new WeakMap());
792
896
  }
793
897
  }
794
898
  ]);
795
899
  return HookEngine;
796
900
  }();
901
+ function assertRegistered(name, method) {
902
+ if (_class_private_field_get(this, _registered) !== null && !_class_private_field_get(this, _registered).has(name)) {
903
+ var registered = _to_consumable_array(_class_private_field_get(this, _registered)).map(String).join(', ');
904
+ throw new Error('Hook "'.concat(String(name), '" is not registered. ') + 'Call register("'.concat(String(name), '") before using ').concat(method, "(). ") + "Registered hooks: ".concat(registered || '(none)'));
905
+ }
906
+ }