@logosdx/hooks 1.0.0-beta.2 → 1.0.0-beta.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/dist/cjs/index.js CHANGED
@@ -9,12 +9,21 @@ function _export(target, all) {
9
9
  });
10
10
  }
11
11
  _export(exports, {
12
+ get HookContext () {
13
+ return HookContext;
14
+ },
12
15
  get HookEngine () {
13
16
  return HookEngine;
14
17
  },
15
18
  get HookError () {
16
19
  return HookError;
17
20
  },
21
+ get HookScope () {
22
+ return HookScope;
23
+ },
24
+ get PipeContext () {
25
+ return PipeContext;
26
+ },
18
27
  get isHookError () {
19
28
  return isHookError;
20
29
  }
@@ -231,21 +240,6 @@ function _non_iterable_rest() {
231
240
  function _non_iterable_spread() {
232
241
  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
242
  }
234
- function _object_spread(target) {
235
- for(var i = 1; i < arguments.length; i++){
236
- var source = arguments[i] != null ? arguments[i] : {};
237
- var ownKeys = Object.keys(source);
238
- if (typeof Object.getOwnPropertySymbols === "function") {
239
- ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
240
- return Object.getOwnPropertyDescriptor(source, sym).enumerable;
241
- }));
242
- }
243
- ownKeys.forEach(function(key) {
244
- _define_property(target, key, source[key]);
245
- });
246
- }
247
- return target;
248
- }
249
243
  function _possible_constructor_return(self, call) {
250
244
  if (call && (_type_of(call) === "object" || typeof call === "function")) {
251
245
  return call;
@@ -433,24 +427,326 @@ var isHookError = function(error) {
433
427
  var _error_constructor;
434
428
  return (error === null || error === void 0 ? void 0 : (_error_constructor = error.constructor) === null || _error_constructor === void 0 ? void 0 : _error_constructor.name) === HookError.name;
435
429
  };
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();
430
+ var _data = /*#__PURE__*/ new WeakMap();
431
+ var HookScope = /*#__PURE__*/ function() {
432
+ "use strict";
433
+ function HookScope() {
434
+ _class_call_check(this, HookScope);
435
+ _class_private_field_init(this, _data, {
436
+ writable: true,
437
+ value: new Map()
438
+ });
439
+ }
440
+ _create_class(HookScope, [
441
+ {
442
+ /**
443
+ * Get a value from the scope.
444
+ *
445
+ * @example
446
+ * const state = ctx.scope.get<CacheState>(CACHE_STATE);
447
+ */ key: "get",
448
+ value: function get(key) {
449
+ return _class_private_field_get(this, _data).get(key);
450
+ }
451
+ },
452
+ {
453
+ /**
454
+ * Set a value in the scope.
455
+ *
456
+ * @example
457
+ * ctx.scope.set(CACHE_STATE, { key: 'abc', rule });
458
+ */ key: "set",
459
+ value: function set(key, value) {
460
+ _class_private_field_get(this, _data).set(key, value);
461
+ }
462
+ },
463
+ {
464
+ /**
465
+ * Check if a key exists in the scope.
466
+ */ key: "has",
467
+ value: function has(key) {
468
+ return _class_private_field_get(this, _data).has(key);
469
+ }
470
+ },
471
+ {
472
+ /**
473
+ * Delete a key from the scope.
474
+ */ key: "delete",
475
+ value: function _delete(key) {
476
+ return _class_private_field_get(this, _data).delete(key);
477
+ }
478
+ }
479
+ ]);
480
+ return HookScope;
481
+ }();
482
+ var EARLY_RETURN = Symbol('early-return');
483
+ var _args = /*#__PURE__*/ new WeakMap(), _argsChanged = /*#__PURE__*/ new WeakMap(), _result = /*#__PURE__*/ new WeakMap(), _earlyReturn = /*#__PURE__*/ new WeakMap(), _handleFail = /*#__PURE__*/ new WeakMap(), _hookName = /*#__PURE__*/ new WeakMap(), _removeFn = /*#__PURE__*/ new WeakMap();
484
+ var HookContext = /*#__PURE__*/ function() {
485
+ "use strict";
486
+ function HookContext(handleFail, hookName, removeFn, scope) {
487
+ _class_call_check(this, HookContext);
488
+ _class_private_field_init(this, _args, {
489
+ writable: true,
490
+ value: void 0
491
+ });
492
+ _class_private_field_init(this, _argsChanged, {
493
+ writable: true,
494
+ value: false
495
+ });
496
+ _class_private_field_init(this, _result, {
497
+ writable: true,
498
+ value: void 0
499
+ });
500
+ _class_private_field_init(this, _earlyReturn, {
501
+ writable: true,
502
+ value: false
503
+ });
504
+ _class_private_field_init(this, _handleFail, {
505
+ writable: true,
506
+ value: void 0
507
+ });
508
+ _class_private_field_init(this, _hookName, {
509
+ writable: true,
510
+ value: void 0
511
+ });
512
+ _class_private_field_init(this, _removeFn, {
513
+ writable: true,
514
+ value: void 0
515
+ });
516
+ /**
517
+ * Request-scoped state bag shared across hook runs and engine instances.
518
+ *
519
+ * @example
520
+ * // In beforeRequest hook
521
+ * ctx.scope.set(CACHE_KEY, serializedKey);
522
+ *
523
+ * // In afterRequest hook (same scope)
524
+ * const key = ctx.scope.get<string>(CACHE_KEY);
525
+ */ _define_property(this, "scope", void 0);
526
+ _class_private_field_set(this, _handleFail, handleFail);
527
+ _class_private_field_set(this, _hookName, hookName);
528
+ _class_private_field_set(this, _removeFn, removeFn);
529
+ this.scope = scope;
530
+ }
531
+ _create_class(HookContext, [
532
+ {
533
+ /**
534
+ * Replace args for downstream callbacks.
535
+ * When used with `return`, also stops the chain.
536
+ *
537
+ * @example
538
+ * // Just replace args, continue chain
539
+ * ctx.args(newUrl, newOpts);
540
+ *
541
+ * // Replace args AND stop the chain
542
+ * return ctx.args(newUrl, newOpts);
543
+ */ key: "args",
544
+ value: function args() {
545
+ for(var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++){
546
+ args[_key] = arguments[_key];
547
+ }
548
+ _class_private_field_set(this, _args, args);
549
+ _class_private_field_set(this, _argsChanged, true);
550
+ return EARLY_RETURN;
551
+ }
552
+ },
553
+ {
554
+ /**
555
+ * Set a result value and stop the chain.
556
+ * Always used with `return`.
557
+ *
558
+ * @example
559
+ * return ctx.returns(cachedResponse);
560
+ */ key: "returns",
561
+ value: function returns(value) {
562
+ _class_private_field_set(this, _result, value);
563
+ _class_private_field_set(this, _earlyReturn, true);
564
+ return EARLY_RETURN;
565
+ }
566
+ },
567
+ {
568
+ /**
569
+ * Abort hook execution with an error.
570
+ * Uses the engine's `handleFail` to create the error.
571
+ *
572
+ * @example
573
+ * ctx.fail('Validation failed');
574
+ */ key: "fail",
575
+ value: function fail() {
576
+ for(var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++){
577
+ args[_key] = arguments[_key];
578
+ }
579
+ var _handler_prototype;
580
+ var handler = _class_private_field_get(this, _handleFail);
581
+ var isConstructor = typeof handler === 'function' && ((_handler_prototype = handler.prototype) === null || _handler_prototype === void 0 ? void 0 : _handler_prototype.constructor) === handler;
582
+ var _attemptSync = _sliced_to_array((0, _utils.attemptSync)(function() {
583
+ if (isConstructor) {
584
+ throw _construct(handler, _to_consumable_array(args));
585
+ }
586
+ handler.apply(void 0, _to_consumable_array(args));
587
+ }), 2), error = _attemptSync[1];
588
+ if (error) {
589
+ if (_instanceof(error, HookError)) {
590
+ error.hookName = _class_private_field_get(this, _hookName);
591
+ }
592
+ throw error;
593
+ }
594
+ throw new HookError('ctx.fail() handler did not throw');
595
+ }
596
+ },
597
+ {
598
+ /**
599
+ * Remove this callback from future runs.
600
+ *
601
+ * @example
602
+ * hooks.add('init', (config, ctx) => {
603
+ * bootstrap(config);
604
+ * ctx.removeHook();
605
+ * });
606
+ */ key: "removeHook",
607
+ value: function removeHook() {
608
+ _class_private_field_get(this, _removeFn).call(this);
609
+ }
610
+ },
611
+ {
612
+ key: "_argsChanged",
613
+ get: /** @internal */ function get() {
614
+ return _class_private_field_get(this, _argsChanged);
615
+ }
616
+ },
617
+ {
618
+ key: "_newArgs",
619
+ get: /** @internal */ function get() {
620
+ return _class_private_field_get(this, _args);
621
+ }
622
+ },
623
+ {
624
+ key: "_result",
625
+ get: /** @internal */ function get() {
626
+ return _class_private_field_get(this, _result);
627
+ }
628
+ },
629
+ {
630
+ key: "_earlyReturn",
631
+ get: /** @internal */ function get() {
632
+ return _class_private_field_get(this, _earlyReturn);
633
+ }
634
+ }
635
+ ]);
636
+ return HookContext;
637
+ }();
638
+ var _handleFail1 = /*#__PURE__*/ new WeakMap(), _hookName1 = /*#__PURE__*/ new WeakMap(), _removeFn1 = /*#__PURE__*/ new WeakMap(), _setArgs = /*#__PURE__*/ new WeakMap();
639
+ var PipeContext = /*#__PURE__*/ function() {
640
+ "use strict";
641
+ function PipeContext(handleFail, hookName, removeFn, scope, setArgs) {
642
+ _class_call_check(this, PipeContext);
643
+ _class_private_field_init(this, _handleFail1, {
644
+ writable: true,
645
+ value: void 0
646
+ });
647
+ _class_private_field_init(this, _hookName1, {
648
+ writable: true,
649
+ value: void 0
650
+ });
651
+ _class_private_field_init(this, _removeFn1, {
652
+ writable: true,
653
+ value: void 0
654
+ });
655
+ _class_private_field_init(this, _setArgs, {
656
+ writable: true,
657
+ value: void 0
658
+ });
659
+ /**
660
+ * Request-scoped state bag shared across hook runs and engine instances.
661
+ */ _define_property(this, "scope", void 0);
662
+ _class_private_field_set(this, _handleFail1, handleFail);
663
+ _class_private_field_set(this, _hookName1, hookName);
664
+ _class_private_field_set(this, _removeFn1, removeFn);
665
+ this.scope = scope;
666
+ _class_private_field_set(this, _setArgs, setArgs);
667
+ }
668
+ _create_class(PipeContext, [
669
+ {
670
+ /**
671
+ * Replace args for `next()` and downstream middleware.
672
+ *
673
+ * @example
674
+ * ctx.args({ ...opts, timeout: 5000 });
675
+ * return next(); // next receives modified opts
676
+ */ key: "args",
677
+ value: function args() {
678
+ for(var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++){
679
+ args[_key] = arguments[_key];
680
+ }
681
+ _class_private_field_get(this, _setArgs).call(this, args);
682
+ }
683
+ },
684
+ {
685
+ /**
686
+ * Abort execution with an error.
687
+ *
688
+ * @example
689
+ * ctx.fail('Rate limit exceeded');
690
+ */ key: "fail",
691
+ value: function fail() {
692
+ for(var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++){
693
+ args[_key] = arguments[_key];
694
+ }
695
+ var _handler_prototype;
696
+ var handler = _class_private_field_get(this, _handleFail1);
697
+ var isConstructor = typeof handler === 'function' && ((_handler_prototype = handler.prototype) === null || _handler_prototype === void 0 ? void 0 : _handler_prototype.constructor) === handler;
698
+ var _attemptSync = _sliced_to_array((0, _utils.attemptSync)(function() {
699
+ if (isConstructor) {
700
+ throw _construct(handler, _to_consumable_array(args));
701
+ }
702
+ handler.apply(void 0, _to_consumable_array(args));
703
+ }), 2), error = _attemptSync[1];
704
+ if (error) {
705
+ if (_instanceof(error, HookError)) {
706
+ error.hookName = _class_private_field_get(this, _hookName1);
707
+ }
708
+ throw error;
709
+ }
710
+ throw new HookError('ctx.fail() handler did not throw');
711
+ }
712
+ },
713
+ {
714
+ /**
715
+ * Remove this middleware from future runs.
716
+ */ key: "removeHook",
717
+ value: function removeHook() {
718
+ _class_private_field_get(this, _removeFn1).call(this);
719
+ }
720
+ }
721
+ ]);
722
+ return PipeContext;
723
+ }();
724
+ var _hooks = /*#__PURE__*/ new WeakMap(), _handleFail2 = /*#__PURE__*/ new WeakMap(), _registered = /*#__PURE__*/ new WeakMap(), _callCounts = /*#__PURE__*/ new WeakMap(), /**
725
+ * Validate that a hook name is registered (when strict mode is active).
726
+ */ _assertRegistered = /*#__PURE__*/ new WeakSet(), /**
727
+ * Process a HookContext after a callback has run.
728
+ */ _processCtx = /*#__PURE__*/ new WeakSet(), /**
729
+ * Check times limit and increment counter. Returns true if exceeded.
730
+ */ _checkTimes = /*#__PURE__*/ new WeakSet(), /**
731
+ * Remove an entry from the hooks array.
732
+ */ _removeEntry = /*#__PURE__*/ new WeakSet(), /**
733
+ * Extract RunOptions from the args array if present.
734
+ */ _extractRunOptions = /*#__PURE__*/ new WeakSet();
439
735
  var HookEngine = /*#__PURE__*/ function() {
440
736
  "use strict";
441
737
  function HookEngine() {
442
738
  var options = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
443
739
  _class_call_check(this, HookEngine);
444
740
  _class_private_method_init(this, _assertRegistered);
741
+ _class_private_method_init(this, _processCtx);
742
+ _class_private_method_init(this, _checkTimes);
743
+ _class_private_method_init(this, _removeEntry);
744
+ _class_private_method_init(this, _extractRunOptions);
445
745
  _class_private_field_init(this, _hooks, {
446
746
  writable: true,
447
747
  value: new Map()
448
748
  });
449
- _class_private_field_init(this, _hookOpts, {
450
- writable: true,
451
- value: new WeakMap()
452
- });
453
- _class_private_field_init(this, _handleFail, {
749
+ _class_private_field_init(this, _handleFail2, {
454
750
  writable: true,
455
751
  value: void 0
456
752
  });
@@ -458,8 +754,12 @@ var HookEngine = /*#__PURE__*/ function() {
458
754
  writable: true,
459
755
  value: null
460
756
  });
757
+ _class_private_field_init(this, _callCounts, {
758
+ writable: true,
759
+ value: new WeakMap()
760
+ });
461
761
  var _options_handleFail;
462
- _class_private_field_set(this, _handleFail, (_options_handleFail = options.handleFail) !== null && _options_handleFail !== void 0 ? _options_handleFail : function(message) {
762
+ _class_private_field_set(this, _handleFail2, (_options_handleFail = options.handleFail) !== null && _options_handleFail !== void 0 ? _options_handleFail : function(message) {
463
763
  throw new HookError(message);
464
764
  });
465
765
  }
@@ -474,10 +774,10 @@ var HookEngine = /*#__PURE__*/ function() {
474
774
  *
475
775
  * @example
476
776
  * const hooks = new HookEngine<FetchLifecycle>()
477
- * .register('preRequest', 'postRequest', 'rateLimit');
777
+ * .register('beforeRequest', 'afterRequest');
478
778
  *
479
- * hooks.on('preRequest', cb); // OK
480
- * hooks.on('preRequset', cb); // Error: not registered (typo caught!)
779
+ * hooks.add('beforeRequest', cb); // OK
780
+ * hooks.add('beforeRequset', cb); // Error: not registered (typo caught!)
481
781
  */ key: "register",
482
782
  value: function register() {
483
783
  for(var _len = arguments.length, names = new Array(_len), _key = 0; _key < _len; _key++){
@@ -516,142 +816,102 @@ var HookEngine = /*#__PURE__*/ function() {
516
816
  * Subscribe to a lifecycle hook.
517
817
  *
518
818
  * @param name - Name of the lifecycle hook
519
- * @param cbOrOpts - Callback function or options object
819
+ * @param callback - Callback function receiving spread args + ctx
820
+ * @param options - Options for this subscription
520
821
  * @returns Cleanup function to remove the subscription
521
822
  *
522
823
  * @example
523
824
  * // Simple callback
524
- * const cleanup = hooks.on('preRequest', async (ctx) => {
525
- * console.log('Request:', ctx.args[0]);
825
+ * const cleanup = hooks.add('beforeRequest', (url, opts, ctx) => {
826
+ * console.log('Request:', url);
526
827
  * });
527
828
  *
528
829
  * // With options
529
- * hooks.on('analytics', {
530
- * callback: async (ctx) => { track(ctx.args); },
531
- * once: true, // Remove after first run
532
- * ignoreOnFail: true // Don't throw if callback fails
533
- * });
830
+ * hooks.add('analytics', (event, ctx) => {
831
+ * track(event);
832
+ * }, { once: true, ignoreOnFail: true });
833
+ *
834
+ * // With priority (lower runs first)
835
+ * hooks.add('beforeRequest', cb, { priority: -10 });
534
836
  *
535
837
  * // Remove subscription
536
838
  * cleanup();
537
- */ key: "on",
538
- value: function on(name, cbOrOpts) {
539
- var callback = typeof cbOrOpts === 'function' ? cbOrOpts : cbOrOpts === null || cbOrOpts === void 0 ? void 0 : cbOrOpts.callback;
540
- var opts = typeof cbOrOpts === 'function' ? {} : cbOrOpts;
839
+ */ key: "add",
840
+ value: function add(name, callback) {
841
+ var _this = this;
842
+ var options = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : {};
541
843
  (0, _utils.assert)(typeof name === 'string', '"name" must be a string');
542
- (0, _utils.assert)((0, _utils.isFunction)(callback) || (0, _utils.isObject)(cbOrOpts), '"cbOrOpts" must be a callback or options');
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');
844
+ (0, _utils.assert)((0, _utils.isFunction)(callback), '"callback" must be a function');
845
+ _class_private_method_get(this, _assertRegistered, assertRegistered).call(this, name, 'add');
846
+ var _options_priority;
847
+ var priority = (_options_priority = options.priority) !== null && _options_priority !== void 0 ? _options_priority : 0;
848
+ var entry = {
849
+ callback: callback,
850
+ options: options,
851
+ priority: priority
852
+ };
545
853
  var _class_private_field_get_get;
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);
854
+ 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 : [];
855
+ var inserted = false;
856
+ for(var i = 0; i < hooks.length; i++){
857
+ if (hooks[i].priority > priority) {
858
+ hooks.splice(i, 0, entry);
859
+ inserted = true;
860
+ break;
861
+ }
862
+ }
863
+ if (!inserted) {
864
+ hooks.push(entry);
865
+ }
548
866
  _class_private_field_get(this, _hooks).set(name, hooks);
549
- _class_private_field_get(this, _hookOpts).set(callback, opts);
550
867
  return function() {
551
- hooks.delete(callback);
868
+ var arr = _class_private_field_get(_this, _hooks).get(name);
869
+ if (arr) {
870
+ var idx = arr.indexOf(entry);
871
+ if (idx !== -1) {
872
+ arr.splice(idx, 1);
873
+ }
874
+ }
552
875
  };
553
876
  }
554
877
  },
555
878
  {
556
- /**
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
563
- *
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",
879
+ key: "run",
579
880
  value: /**
580
- * Emit a lifecycle hook, running all subscribed callbacks.
881
+ * Run all callbacks for a hook asynchronously.
581
882
  *
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
883
+ * @param name - Name of the lifecycle hook to run
884
+ * @param args - Arguments to pass to callbacks (spread + ctx)
885
+ * @returns RunResult with final args, result, and returned flag
585
886
  *
586
887
  * @example
587
- * const result = await hooks.emit('cacheCheck', url);
588
- *
589
- * if (result.earlyReturn && result.result) {
590
- * return result.result; // Use cached value
591
- * }
592
- *
593
- * // Continue with modified args
594
- * const [modifiedUrl] = result.args;
595
- */ function emit(name) {
888
+ * const pre = await hooks.run('beforeRequest', url, options);
889
+ * if (pre.returned) return pre.result;
890
+ * const response = await fetch(...pre.args);
891
+ */ function run(name) {
596
892
  for(var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++){
597
893
  args[_key - 1] = arguments[_key];
598
894
  }
599
895
  return _async_to_generator(function() {
600
- var _this, earlyReturn, hooks, context, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _this1, _loop, _iterator, _step, _ret, err;
896
+ var _this, _class_private_method_get_call, realArgs, runOptions, currentArgs, _runOptions_scope, scope, hooks, entries, result, returned, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _this1, _loop, _iterator, _step, _ret, err;
601
897
  return _ts_generator(this, function(_state) {
602
898
  switch(_state.label){
603
899
  case 0:
604
900
  _this = this;
605
- _class_private_method_get(this, _assertRegistered, assertRegistered).call(this, name, 'emit');
606
- earlyReturn = false;
901
+ _class_private_method_get(this, _assertRegistered, assertRegistered).call(this, name, 'run');
902
+ _class_private_method_get_call = _class_private_method_get(this, _extractRunOptions, extractRunOptions).call(this, args), realArgs = _class_private_method_get_call.realArgs, runOptions = _class_private_method_get_call.runOptions;
903
+ currentArgs = realArgs;
904
+ scope = (_runOptions_scope = runOptions === null || runOptions === void 0 ? void 0 : runOptions.scope) !== null && _runOptions_scope !== void 0 ? _runOptions_scope : new HookScope();
607
905
  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
- ];
906
+ entries = hooks ? _to_consumable_array(hooks) : [];
907
+ if (runOptions === null || runOptions === void 0 ? void 0 : runOptions.append) {
908
+ entries.push({
909
+ callback: runOptions.append,
910
+ options: {},
911
+ priority: Infinity
912
+ });
654
913
  }
914
+ returned = false;
655
915
  _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
656
916
  _state.label = 1;
657
917
  case 1:
@@ -662,21 +922,57 @@ var HookEngine = /*#__PURE__*/ function() {
662
922
  8
663
923
  ]);
664
924
  _loop = function() {
665
- var fn, _class_private_field_get_get, opts, _ref, _$err;
925
+ var entry, callback, opts, timesExceeded, removeFn, ctx, _ref, _$err, signal;
666
926
  return _ts_generator(this, function(_state) {
667
927
  switch(_state.label){
668
928
  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
929
+ entry = _step.value;
930
+ callback = entry.callback, opts = entry.options;
931
+ timesExceeded = _class_private_method_get(_this1, _checkTimes, checkTimes).call(_this1, callback, opts);
932
+ if (timesExceeded) {
933
+ _class_private_method_get(_this1, _removeEntry, removeEntry).call(_this1, name, entry);
934
+ return [
935
+ 2,
936
+ "continue"
937
+ ];
938
+ }
939
+ removeFn = function() {
940
+ return _class_private_method_get(_this, _removeEntry, removeEntry).call(_this, name, entry);
675
941
  };
942
+ ctx = new HookContext(_class_private_field_get(_this1, _handleFail2), String(name), removeFn, scope);
943
+ if (!opts.ignoreOnFail) return [
944
+ 3,
945
+ 2
946
+ ];
676
947
  return [
677
948
  4,
678
949
  (0, _utils.attempt)(function() {
679
- return fn(_object_spread({}, context));
950
+ return _async_to_generator(function() {
951
+ var signal;
952
+ return _ts_generator(this, function(_state) {
953
+ switch(_state.label){
954
+ case 0:
955
+ return [
956
+ 4,
957
+ callback.apply(void 0, _to_consumable_array(currentArgs).concat([
958
+ ctx
959
+ ]))
960
+ ];
961
+ case 1:
962
+ signal = _state.sent();
963
+ _class_private_method_get(this, _processCtx, processCtx).call(this, ctx, signal, function(a) {
964
+ currentArgs = a;
965
+ }, function(r) {
966
+ result = r;
967
+ }, function() {
968
+ returned = true;
969
+ });
970
+ return [
971
+ 2
972
+ ];
973
+ }
974
+ });
975
+ }).call(_this);
680
976
  })
681
977
  ];
682
978
  case 1:
@@ -684,11 +980,33 @@ var HookEngine = /*#__PURE__*/ function() {
684
980
  _state.sent(),
685
981
  2
686
982
  ]), _$err = _ref[1];
687
- if (opts.once) context.removeHook();
688
- if (_$err && opts.ignoreOnFail !== true) {
689
- throw _$err;
690
- }
691
- if (earlyReturn) return [
983
+ if (!_$err && opts.once) removeFn();
984
+ if (returned) return [
985
+ 2,
986
+ "break"
987
+ ];
988
+ return [
989
+ 2,
990
+ "continue"
991
+ ];
992
+ case 2:
993
+ return [
994
+ 4,
995
+ callback.apply(void 0, _to_consumable_array(currentArgs).concat([
996
+ ctx
997
+ ]))
998
+ ];
999
+ case 3:
1000
+ signal = _state.sent();
1001
+ _class_private_method_get(_this1, _processCtx, processCtx).call(_this1, ctx, signal, function(a) {
1002
+ currentArgs = a;
1003
+ }, function(r) {
1004
+ result = r;
1005
+ }, function() {
1006
+ returned = true;
1007
+ });
1008
+ if (opts.once) removeFn();
1009
+ if (returned) return [
692
1010
  2,
693
1011
  "break"
694
1012
  ];
@@ -698,7 +1016,7 @@ var HookEngine = /*#__PURE__*/ function() {
698
1016
  }
699
1017
  });
700
1018
  };
701
- _iterator = hooks[Symbol.iterator]();
1019
+ _iterator = entries[Symbol.iterator]();
702
1020
  _state.label = 2;
703
1021
  case 2:
704
1022
  if (!!(_iteratorNormalCompletion = (_step = _iterator.next()).done)) return [
@@ -753,9 +1071,10 @@ var HookEngine = /*#__PURE__*/ function() {
753
1071
  return [
754
1072
  2,
755
1073
  {
756
- args: context.args,
757
- result: context.result,
758
- earlyReturn: earlyReturn
1074
+ args: currentArgs,
1075
+ result: result,
1076
+ returned: returned,
1077
+ scope: scope
759
1078
  }
760
1079
  ];
761
1080
  }
@@ -765,59 +1084,122 @@ var HookEngine = /*#__PURE__*/ function() {
765
1084
  },
766
1085
  {
767
1086
  /**
768
- * Clear all registered hooks.
1087
+ * Run all callbacks for a hook synchronously.
769
1088
  *
770
- * @example
771
- * hooks.on('preRequest', validator);
772
- * hooks.on('postRequest', logger);
1089
+ * @param name - Name of the lifecycle hook to run
1090
+ * @param args - Arguments to pass to callbacks (spread + ctx)
1091
+ * @returns RunResult with final args, result, and returned flag
773
1092
  *
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);
1093
+ * @example
1094
+ * const pre = hooks.runSync('beforeValidation', data);
1095
+ * if (pre.returned) return pre.result;
1096
+ */ key: "runSync",
1097
+ value: function runSync(name) {
1098
+ var _this = this;
1099
+ for(var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++){
1100
+ args[_key - 1] = arguments[_key];
1101
+ }
1102
+ _class_private_method_get(this, _assertRegistered, assertRegistered).call(this, name, 'runSync');
1103
+ var _class_private_method_get_call = _class_private_method_get(this, _extractRunOptions, extractRunOptions).call(this, args), realArgs = _class_private_method_get_call.realArgs, runOptions = _class_private_method_get_call.runOptions;
1104
+ var currentArgs = realArgs;
1105
+ var _runOptions_scope;
1106
+ var scope = (_runOptions_scope = runOptions === null || runOptions === void 0 ? void 0 : runOptions.scope) !== null && _runOptions_scope !== void 0 ? _runOptions_scope : new HookScope();
1107
+ var hooks = _class_private_field_get(this, _hooks).get(name);
1108
+ var entries = hooks ? _to_consumable_array(hooks) : [];
1109
+ if (runOptions === null || runOptions === void 0 ? void 0 : runOptions.append) {
1110
+ entries.push({
1111
+ callback: runOptions.append,
1112
+ options: {},
1113
+ priority: Infinity
1114
+ });
1115
+ }
1116
+ var result;
1117
+ var returned = false;
1118
+ var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
1119
+ try {
1120
+ var _this1, _loop = function() {
1121
+ var entry = _step.value;
1122
+ var callback = entry.callback, opts = entry.options;
1123
+ var timesExceeded = _class_private_method_get(_this1, _checkTimes, checkTimes).call(_this1, callback, opts);
1124
+ if (timesExceeded) {
1125
+ _class_private_method_get(_this1, _removeEntry, removeEntry).call(_this1, name, entry);
1126
+ return "continue";
1127
+ }
1128
+ var removeFn = function() {
1129
+ return _class_private_method_get(_this, _removeEntry, removeEntry).call(_this, name, entry);
1130
+ };
1131
+ var ctx = new HookContext(_class_private_field_get(_this1, _handleFail2), String(name), removeFn, scope);
1132
+ if (opts.ignoreOnFail) {
1133
+ var _attemptSync = _sliced_to_array((0, _utils.attemptSync)(function() {
1134
+ var signal = callback.apply(void 0, _to_consumable_array(currentArgs).concat([
1135
+ ctx
1136
+ ]));
1137
+ _class_private_method_get(_this, _processCtx, processCtx).call(_this, ctx, signal, function(a) {
1138
+ currentArgs = a;
1139
+ }, function(r) {
1140
+ result = r;
1141
+ }, function() {
1142
+ returned = true;
1143
+ });
1144
+ }), 2), _$err = _attemptSync[1];
1145
+ if (!_$err && opts.once) removeFn();
1146
+ if (returned) return "break";
1147
+ return "continue";
1148
+ }
1149
+ var signal = callback.apply(void 0, _to_consumable_array(currentArgs).concat([
1150
+ ctx
1151
+ ]));
1152
+ _class_private_method_get(_this1, _processCtx, processCtx).call(_this1, ctx, signal, function(a) {
1153
+ currentArgs = a;
1154
+ }, function(r) {
1155
+ result = r;
1156
+ }, function() {
1157
+ returned = true;
1158
+ });
1159
+ if (opts.once) removeFn();
1160
+ if (returned) return "break";
1161
+ };
1162
+ for(var _iterator = entries[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
1163
+ var _ret = (_this1 = this, _loop());
1164
+ if (_ret === "break") break;
1165
+ }
1166
+ } catch (err) {
1167
+ _didIteratorError = true;
1168
+ _iteratorError = err;
1169
+ } finally{
1170
+ try {
1171
+ if (!_iteratorNormalCompletion && _iterator.return != null) {
1172
+ _iterator.return();
1173
+ }
1174
+ } finally{
1175
+ if (_didIteratorError) {
1176
+ throw _iteratorError;
1177
+ }
1178
+ }
1179
+ }
1180
+ return {
1181
+ args: currentArgs,
1182
+ result: result,
1183
+ returned: returned,
1184
+ scope: scope
1185
+ };
781
1186
  }
782
1187
  },
783
1188
  {
784
1189
  /**
785
- * Wrap a function with pre/post lifecycle hooks.
1190
+ * Wrap an async function with pre/post lifecycle hooks.
786
1191
  *
787
- * - Pre hook: emitted with function args, can modify args or returnEarly with result
788
- * - Post hook: emitted with [result, ...args], can modify result
1192
+ * - Pre hook: called with function args, can modify args or return early
1193
+ * - Post hook: called with `(result, ...originalArgs)`, can transform result
789
1194
  *
790
1195
  * @param fn - The async function to wrap
791
1196
  * @param hooks - Object with optional pre and post hook names
792
1197
  * @returns Wrapped function with same signature
793
1198
  *
794
1199
  * @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);
815
- * });
816
- *
817
- * // Wrap the fetch function
818
1200
  * const wrappedFetch = hooks.wrap(
819
1201
  * async (url: string, opts: RequestInit) => fetch(url, opts),
820
- * { pre: 'preRequest', post: 'postRequest' }
1202
+ * { pre: 'beforeRequest', post: 'afterRequest' }
821
1203
  * );
822
1204
  */ key: "wrap",
823
1205
  value: function wrap(fn, hooks) {
@@ -830,7 +1212,7 @@ var HookEngine = /*#__PURE__*/ function() {
830
1212
  args[_key] = arguments[_key];
831
1213
  }
832
1214
  return _async_to_generator(function() {
833
- var currentArgs, result, preResult, postResult;
1215
+ var currentArgs, preResult, result, postResult;
834
1216
  return _ts_generator(this, function(_state) {
835
1217
  switch(_state.label){
836
1218
  case 0:
@@ -841,14 +1223,14 @@ var HookEngine = /*#__PURE__*/ function() {
841
1223
  ];
842
1224
  return [
843
1225
  4,
844
- this.emit.apply(this, [
1226
+ this.run.apply(this, [
845
1227
  hooks.pre
846
1228
  ].concat(_to_consumable_array(currentArgs)))
847
1229
  ];
848
1230
  case 1:
849
1231
  preResult = _state.sent();
850
1232
  currentArgs = preResult.args;
851
- if (preResult.earlyReturn && preResult.result !== undefined) {
1233
+ if (preResult.returned && preResult.result !== undefined) {
852
1234
  return [
853
1235
  2,
854
1236
  preResult.result
@@ -861,7 +1243,6 @@ var HookEngine = /*#__PURE__*/ function() {
861
1243
  fn.apply(void 0, _to_consumable_array(currentArgs))
862
1244
  ];
863
1245
  case 3:
864
- // Execute function
865
1246
  result = _state.sent();
866
1247
  if (!hooks.post) return [
867
1248
  3,
@@ -869,7 +1250,7 @@ var HookEngine = /*#__PURE__*/ function() {
869
1250
  ];
870
1251
  return [
871
1252
  4,
872
- this.emit.apply(this, [
1253
+ this.run.apply(this, [
873
1254
  hooks.post
874
1255
  ].concat(_to_consumable_array([
875
1256
  result
@@ -877,7 +1258,7 @@ var HookEngine = /*#__PURE__*/ function() {
877
1258
  ];
878
1259
  case 4:
879
1260
  postResult = _state.sent();
880
- if (postResult.result !== undefined) {
1261
+ if (postResult.returned) {
881
1262
  return [
882
1263
  2,
883
1264
  postResult.result
@@ -894,6 +1275,294 @@ var HookEngine = /*#__PURE__*/ function() {
894
1275
  }).call(_this);
895
1276
  };
896
1277
  }
1278
+ },
1279
+ {
1280
+ /**
1281
+ * Wrap a synchronous function with pre/post lifecycle hooks.
1282
+ *
1283
+ * @param fn - The sync function to wrap
1284
+ * @param hooks - Object with optional pre and post hook names
1285
+ * @returns Wrapped function with same signature
1286
+ *
1287
+ * @example
1288
+ * const wrappedValidate = hooks.wrapSync(
1289
+ * (data: UserData) => validate(data),
1290
+ * { pre: 'beforeValidate' }
1291
+ * );
1292
+ */ key: "wrapSync",
1293
+ value: function wrapSync(fn, hooks) {
1294
+ var _this = this;
1295
+ (0, _utils.assert)(hooks.pre || hooks.post, 'wrapSync() requires at least one of "pre" or "post" hooks');
1296
+ if (hooks.pre) _class_private_method_get(this, _assertRegistered, assertRegistered).call(this, hooks.pre, 'wrapSync');
1297
+ if (hooks.post) _class_private_method_get(this, _assertRegistered, assertRegistered).call(this, hooks.post, 'wrapSync');
1298
+ return function() {
1299
+ for(var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++){
1300
+ args[_key] = arguments[_key];
1301
+ }
1302
+ var currentArgs = args;
1303
+ if (hooks.pre) {
1304
+ var preResult = _this.runSync.apply(_this, [
1305
+ hooks.pre
1306
+ ].concat(_to_consumable_array(currentArgs)));
1307
+ currentArgs = preResult.args;
1308
+ if (preResult.returned && preResult.result !== undefined) {
1309
+ return preResult.result;
1310
+ }
1311
+ }
1312
+ var result = fn.apply(void 0, _to_consumable_array(currentArgs));
1313
+ if (hooks.post) {
1314
+ var postResult = _this.runSync.apply(_this, [
1315
+ hooks.post
1316
+ ].concat(_to_consumable_array([
1317
+ result
1318
+ ].concat(_to_consumable_array(currentArgs)))));
1319
+ if (postResult.returned) {
1320
+ return postResult.result;
1321
+ }
1322
+ }
1323
+ return result;
1324
+ };
1325
+ }
1326
+ },
1327
+ {
1328
+ key: "pipe",
1329
+ value: /**
1330
+ * Execute middleware hooks as an onion (nested) composition.
1331
+ *
1332
+ * Unlike `run()` which executes hooks linearly, `pipe()` composes hooks
1333
+ * as nested middleware. Each hook receives a `next` function that calls
1334
+ * the next layer. The innermost layer is `coreFn`. Control flow is
1335
+ * managed by calling or not calling `next()` — no `ctx.returns()` needed.
1336
+ *
1337
+ * Hooks execute in priority order (lower first = outermost layer).
1338
+ *
1339
+ * @param name - Name of the lifecycle hook
1340
+ * @param coreFn - The innermost function to wrap
1341
+ * @param args - Arguments passed to each middleware
1342
+ * @returns The result from the middleware chain
1343
+ *
1344
+ * @example
1345
+ * // Retry plugin wraps the fetch call
1346
+ * hooks.add('execute', async (next, opts, ctx) => {
1347
+ * for (let i = 0; i < 3; i++) {
1348
+ * const [result, err] = await attempt(next);
1349
+ * if (!err) return result;
1350
+ * await wait(1000 * i);
1351
+ * }
1352
+ * throw lastError;
1353
+ * }, { priority: -20 });
1354
+ *
1355
+ * // Dedupe plugin wraps retry
1356
+ * hooks.add('execute', async (next, opts, ctx) => {
1357
+ * const inflight = getInflight(key);
1358
+ * if (inflight) return inflight;
1359
+ * const result = await next();
1360
+ * share(result);
1361
+ * return result;
1362
+ * }, { priority: -30 });
1363
+ *
1364
+ * // Execute: dedupe( retry( makeCall() ) )
1365
+ * const response = await hooks.pipe(
1366
+ * 'execute',
1367
+ * () => makeCall(opts),
1368
+ * opts
1369
+ * );
1370
+ */ function pipe(name, coreFn) {
1371
+ for(var _len = arguments.length, args = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++){
1372
+ args[_key - 2] = arguments[_key];
1373
+ }
1374
+ return _async_to_generator(function() {
1375
+ var _this, _class_private_method_get_call, realArgs, runOptions, _runOptions_scope, scope, hooks, entries, currentArgs, buildChain;
1376
+ return _ts_generator(this, function(_state) {
1377
+ _this = this;
1378
+ _class_private_method_get(this, _assertRegistered, assertRegistered).call(this, name, 'pipe');
1379
+ _class_private_method_get_call = _class_private_method_get(this, _extractRunOptions, extractRunOptions).call(this, args), realArgs = _class_private_method_get_call.realArgs, runOptions = _class_private_method_get_call.runOptions;
1380
+ scope = (_runOptions_scope = runOptions === null || runOptions === void 0 ? void 0 : runOptions.scope) !== null && _runOptions_scope !== void 0 ? _runOptions_scope : new HookScope();
1381
+ hooks = _class_private_field_get(this, _hooks).get(name);
1382
+ entries = hooks ? _to_consumable_array(hooks) : [];
1383
+ if (runOptions === null || runOptions === void 0 ? void 0 : runOptions.append) {
1384
+ entries.push({
1385
+ callback: runOptions.append,
1386
+ options: {},
1387
+ priority: Infinity
1388
+ });
1389
+ }
1390
+ currentArgs = realArgs;
1391
+ buildChain = function(index) {
1392
+ if (index >= entries.length) return coreFn;
1393
+ return function() {
1394
+ return _async_to_generator(function() {
1395
+ var _this, entry, callback, opts, timesExceeded, removeFn, ctx, next, cb, _ref, result, err, result1;
1396
+ return _ts_generator(this, function(_state) {
1397
+ switch(_state.label){
1398
+ case 0:
1399
+ _this = this;
1400
+ entry = entries[index];
1401
+ callback = entry.callback, opts = entry.options;
1402
+ timesExceeded = _class_private_method_get(this, _checkTimes, checkTimes).call(this, callback, opts);
1403
+ if (timesExceeded) {
1404
+ _class_private_method_get(this, _removeEntry, removeEntry).call(this, name, entry);
1405
+ return [
1406
+ 2,
1407
+ buildChain(index + 1)()
1408
+ ];
1409
+ }
1410
+ removeFn = function() {
1411
+ return _class_private_method_get(_this, _removeEntry, removeEntry).call(_this, name, entry);
1412
+ };
1413
+ ctx = new PipeContext(_class_private_field_get(this, _handleFail2), String(name), removeFn, scope, function(newArgs) {
1414
+ currentArgs = newArgs;
1415
+ });
1416
+ next = buildChain(index + 1);
1417
+ cb = callback;
1418
+ if (!opts.ignoreOnFail) return [
1419
+ 3,
1420
+ 2
1421
+ ];
1422
+ return [
1423
+ 4,
1424
+ (0, _utils.attempt)(function() {
1425
+ return _async_to_generator(function() {
1426
+ return _ts_generator(this, function(_state) {
1427
+ return [
1428
+ 2,
1429
+ cb.apply(void 0, [
1430
+ next
1431
+ ].concat(_to_consumable_array(currentArgs), [
1432
+ ctx
1433
+ ]))
1434
+ ];
1435
+ });
1436
+ })();
1437
+ })
1438
+ ];
1439
+ case 1:
1440
+ _ref = _sliced_to_array.apply(void 0, [
1441
+ _state.sent(),
1442
+ 2
1443
+ ]), result = _ref[0], err = _ref[1];
1444
+ if (opts.once) removeFn();
1445
+ if (err) return [
1446
+ 2,
1447
+ next()
1448
+ ];
1449
+ return [
1450
+ 2,
1451
+ result
1452
+ ];
1453
+ case 2:
1454
+ return [
1455
+ 4,
1456
+ cb.apply(void 0, [
1457
+ next
1458
+ ].concat(_to_consumable_array(currentArgs), [
1459
+ ctx
1460
+ ]))
1461
+ ];
1462
+ case 3:
1463
+ result1 = _state.sent();
1464
+ if (opts.once) removeFn();
1465
+ return [
1466
+ 2,
1467
+ result1
1468
+ ];
1469
+ }
1470
+ });
1471
+ }).call(_this);
1472
+ };
1473
+ };
1474
+ return [
1475
+ 2,
1476
+ buildChain(0)()
1477
+ ];
1478
+ });
1479
+ }).call(this);
1480
+ }
1481
+ },
1482
+ {
1483
+ /**
1484
+ * Synchronous version of `pipe()`.
1485
+ *
1486
+ * @param name - Name of the lifecycle hook
1487
+ * @param coreFn - The innermost function to wrap
1488
+ * @param args - Arguments passed to each middleware
1489
+ * @returns The result from the middleware chain
1490
+ */ key: "pipeSync",
1491
+ value: function pipeSync(name, coreFn) {
1492
+ var _this = this;
1493
+ for(var _len = arguments.length, args = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++){
1494
+ args[_key - 2] = arguments[_key];
1495
+ }
1496
+ _class_private_method_get(this, _assertRegistered, assertRegistered).call(this, name, 'pipeSync');
1497
+ var _class_private_method_get_call = _class_private_method_get(this, _extractRunOptions, extractRunOptions).call(this, args), realArgs = _class_private_method_get_call.realArgs, runOptions = _class_private_method_get_call.runOptions;
1498
+ var _runOptions_scope;
1499
+ var scope = (_runOptions_scope = runOptions === null || runOptions === void 0 ? void 0 : runOptions.scope) !== null && _runOptions_scope !== void 0 ? _runOptions_scope : new HookScope();
1500
+ var hooks = _class_private_field_get(this, _hooks).get(name);
1501
+ var entries = hooks ? _to_consumable_array(hooks) : [];
1502
+ if (runOptions === null || runOptions === void 0 ? void 0 : runOptions.append) {
1503
+ entries.push({
1504
+ callback: runOptions.append,
1505
+ options: {},
1506
+ priority: Infinity
1507
+ });
1508
+ }
1509
+ var currentArgs = realArgs;
1510
+ var buildChain = function(index) {
1511
+ if (index >= entries.length) return coreFn;
1512
+ return function() {
1513
+ var entry = entries[index];
1514
+ var callback = entry.callback, opts = entry.options;
1515
+ var timesExceeded = _class_private_method_get(_this, _checkTimes, checkTimes).call(_this, callback, opts);
1516
+ if (timesExceeded) {
1517
+ _class_private_method_get(_this, _removeEntry, removeEntry).call(_this, name, entry);
1518
+ return buildChain(index + 1)();
1519
+ }
1520
+ var removeFn = function() {
1521
+ return _class_private_method_get(_this, _removeEntry, removeEntry).call(_this, name, entry);
1522
+ };
1523
+ var ctx = new PipeContext(_class_private_field_get(_this, _handleFail2), String(name), removeFn, scope, function(newArgs) {
1524
+ currentArgs = newArgs;
1525
+ });
1526
+ var next = buildChain(index + 1);
1527
+ var cb = callback;
1528
+ if (opts.ignoreOnFail) {
1529
+ var _attemptSync = _sliced_to_array((0, _utils.attemptSync)(function() {
1530
+ return cb.apply(void 0, [
1531
+ next
1532
+ ].concat(_to_consumable_array(currentArgs), [
1533
+ ctx
1534
+ ]));
1535
+ }), 2), result = _attemptSync[0], err = _attemptSync[1];
1536
+ if (opts.once) removeFn();
1537
+ if (err) return next();
1538
+ return result;
1539
+ }
1540
+ var result1 = cb.apply(void 0, [
1541
+ next
1542
+ ].concat(_to_consumable_array(currentArgs), [
1543
+ ctx
1544
+ ]));
1545
+ if (opts.once) removeFn();
1546
+ return result1;
1547
+ };
1548
+ };
1549
+ return buildChain(0)();
1550
+ }
1551
+ },
1552
+ {
1553
+ /**
1554
+ * Clear all hooks and reset registration state.
1555
+ *
1556
+ * @example
1557
+ * hooks.add('beforeRequest', validator);
1558
+ * hooks.clear();
1559
+ * // All hooks removed, back to permissive mode
1560
+ */ key: "clear",
1561
+ value: function clear() {
1562
+ _class_private_field_get(this, _hooks).clear();
1563
+ _class_private_field_set(this, _registered, null);
1564
+ _class_private_field_set(this, _callCounts, new WeakMap());
1565
+ }
897
1566
  }
898
1567
  ]);
899
1568
  return HookEngine;
@@ -904,3 +1573,46 @@ function assertRegistered(name, method) {
904
1573
  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
1574
  }
906
1575
  }
1576
+ function processCtx(ctx, signal, setArgs, setResult, setReturned) {
1577
+ if (ctx._earlyReturn) {
1578
+ setResult(ctx._result);
1579
+ setReturned();
1580
+ return;
1581
+ }
1582
+ if (ctx._argsChanged) {
1583
+ setArgs(ctx._newArgs);
1584
+ if (signal === EARLY_RETURN) {
1585
+ setReturned();
1586
+ }
1587
+ }
1588
+ }
1589
+ function checkTimes(callback, opts) {
1590
+ if (opts.times === undefined) return false;
1591
+ var _class_private_field_get_get;
1592
+ var count = (_class_private_field_get_get = _class_private_field_get(this, _callCounts).get(callback)) !== null && _class_private_field_get_get !== void 0 ? _class_private_field_get_get : 0;
1593
+ if (count >= opts.times) return true;
1594
+ _class_private_field_get(this, _callCounts).set(callback, count + 1);
1595
+ return false;
1596
+ }
1597
+ function removeEntry(name, entry) {
1598
+ var arr = _class_private_field_get(this, _hooks).get(name);
1599
+ if (arr) {
1600
+ var idx = arr.indexOf(entry);
1601
+ if (idx !== -1) {
1602
+ arr.splice(idx, 1);
1603
+ }
1604
+ }
1605
+ }
1606
+ function extractRunOptions(args) {
1607
+ var last = args[args.length - 1];
1608
+ if ((0, _utils.isObject)(last) && ('append' in last && (0, _utils.isFunction)(last.append) || 'scope' in last && _instanceof(last.scope, HookScope))) {
1609
+ return {
1610
+ realArgs: args.slice(0, -1),
1611
+ runOptions: last
1612
+ };
1613
+ }
1614
+ return {
1615
+ realArgs: args,
1616
+ runOptions: undefined
1617
+ };
1618
+ }