@bluelibs/runner 4.8.3 → 4.8.4

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.
@@ -661,8 +661,7 @@ __export(defs_exports, {
661
661
  symbolTagConfigured: () => symbolTagConfigured,
662
662
  symbolTask: () => symbolTask,
663
663
  symbolTaskMiddleware: () => symbolTaskMiddleware,
664
- symbolTunneledBy: () => symbolTunneledBy,
665
- symbolTunneledTask: () => symbolTunneledTask
664
+ symbolTunneledBy: () => symbolTunneledBy
666
665
  });
667
666
 
668
667
  // src/types/symbols.ts
@@ -686,9 +685,6 @@ var symbolResourceMiddleware = Symbol.for(
686
685
  var symbolMiddlewareConfigured = Symbol.for(
687
686
  "runner.middlewareConfigured"
688
687
  );
689
- var symbolTunneledTask = Symbol.for(
690
- "runner.tunneledTask"
691
- );
692
688
  var symbolTunneledBy = Symbol.for(
693
689
  "runner.tunneledBy"
694
690
  );
@@ -2538,39 +2534,33 @@ var TaskRunner = class {
2538
2534
  }
2539
2535
  };
2540
2536
 
2541
- // src/models/MiddlewareManager.ts
2542
- var MiddlewareManager = class {
2543
- constructor(store2, eventManager, logger) {
2544
- this.store = store2;
2545
- this.eventManager = eventManager;
2546
- this.logger = logger;
2547
- // Interceptor storage
2548
- this.taskMiddlewareInterceptors = [];
2549
- this.resourceMiddlewareInterceptors = [];
2550
- // Per-middleware interceptor storage
2551
- this.perMiddlewareInterceptors = /* @__PURE__ */ new Map();
2552
- this.perResourceMiddlewareInterceptors = /* @__PURE__ */ new Map();
2553
- // Locking mechanism to prevent modifications after initialization
2537
+ // src/models/middleware/InterceptorRegistry.ts
2538
+ var InterceptorRegistry = class {
2539
+ constructor() {
2540
+ this.taskInterceptors = [];
2541
+ this.resourceInterceptors = [];
2542
+ this.perTaskMiddleware = /* @__PURE__ */ new Map();
2543
+ this.perResourceMiddleware = /* @__PURE__ */ new Map();
2554
2544
  this.#isLocked = false;
2555
2545
  }
2556
2546
  static {
2557
- __name(this, "MiddlewareManager");
2547
+ __name(this, "InterceptorRegistry");
2558
2548
  }
2559
2549
  #isLocked;
2560
2550
  /**
2561
- * Gets the current lock status of the MiddlewareManager
2551
+ * Gets the current lock status
2562
2552
  */
2563
2553
  get isLocked() {
2564
2554
  return this.#isLocked;
2565
2555
  }
2566
2556
  /**
2567
- * Locks the MiddlewareManager, preventing any further modifications to interceptors
2557
+ * Locks the registry, preventing any further modifications
2568
2558
  */
2569
2559
  lock() {
2570
2560
  this.#isLocked = true;
2571
2561
  }
2572
2562
  /**
2573
- * Throws an error if the MiddlewareManager is locked
2563
+ * Throws an error if the registry is locked
2574
2564
  */
2575
2565
  checkLock() {
2576
2566
  if (this.#isLocked) {
@@ -2578,193 +2568,288 @@ var MiddlewareManager = class {
2578
2568
  }
2579
2569
  }
2580
2570
  /**
2581
- * Adds an interceptor for task or resource middleware execution
2582
- * Interceptors are executed in the order they are added, with the ability to
2583
- * modify, log, or prevent middleware execution
2584
- *
2585
- * @param kind - The type of middleware to intercept ("task" or "resource")
2586
- * @param interceptor - The interceptor function to add
2571
+ * Adds a global task interceptor
2587
2572
  */
2588
- intercept(kind, interceptor) {
2573
+ addGlobalTaskInterceptor(interceptor) {
2589
2574
  this.checkLock();
2590
- if (kind === "task") {
2591
- this.taskMiddlewareInterceptors.push(
2592
- interceptor
2593
- );
2594
- } else {
2595
- this.resourceMiddlewareInterceptors.push(
2596
- interceptor
2597
- );
2575
+ this.taskInterceptors.push(interceptor);
2576
+ }
2577
+ /**
2578
+ * Adds a global resource interceptor
2579
+ */
2580
+ addGlobalResourceInterceptor(interceptor) {
2581
+ this.checkLock();
2582
+ this.resourceInterceptors.push(interceptor);
2583
+ }
2584
+ /**
2585
+ * Adds an interceptor for a specific task middleware instance
2586
+ */
2587
+ addTaskMiddlewareInterceptor(middlewareId, interceptor) {
2588
+ this.checkLock();
2589
+ if (!this.perTaskMiddleware.has(middlewareId)) {
2590
+ this.perTaskMiddleware.set(middlewareId, []);
2598
2591
  }
2592
+ this.perTaskMiddleware.get(middlewareId).push(interceptor);
2599
2593
  }
2600
2594
  /**
2601
- * Adds an interceptor for a specific middleware instance with better type safety
2602
- * This method automatically determines the type and provides type-safe access
2603
- *
2604
- * @param middleware - The middleware instance to intercept
2605
- * @param interceptor - The interceptor function with proper typing
2595
+ * Adds an interceptor for a specific resource middleware instance
2606
2596
  */
2607
- interceptMiddleware(middleware, interceptor) {
2597
+ addResourceMiddlewareInterceptor(middlewareId, interceptor) {
2608
2598
  this.checkLock();
2609
- if (isTaskMiddleware(middleware)) {
2610
- if (!this.perMiddlewareInterceptors.has(middleware.id)) {
2611
- this.perMiddlewareInterceptors.set(middleware.id, []);
2599
+ if (!this.perResourceMiddleware.has(middlewareId)) {
2600
+ this.perResourceMiddleware.set(middlewareId, []);
2601
+ }
2602
+ this.perResourceMiddleware.get(middlewareId).push(interceptor);
2603
+ }
2604
+ /**
2605
+ * Gets all global task interceptors
2606
+ */
2607
+ getGlobalTaskInterceptors() {
2608
+ return this.taskInterceptors;
2609
+ }
2610
+ /**
2611
+ * Gets all global resource interceptors
2612
+ */
2613
+ getGlobalResourceInterceptors() {
2614
+ return this.resourceInterceptors;
2615
+ }
2616
+ /**
2617
+ * Gets interceptors for a specific task middleware
2618
+ */
2619
+ getTaskMiddlewareInterceptors(middlewareId) {
2620
+ return this.perTaskMiddleware.get(middlewareId) || [];
2621
+ }
2622
+ /**
2623
+ * Gets interceptors for a specific resource middleware
2624
+ */
2625
+ getResourceMiddlewareInterceptors(middlewareId) {
2626
+ return this.perResourceMiddleware.get(middlewareId) || [];
2627
+ }
2628
+ };
2629
+
2630
+ // src/models/middleware/MiddlewareResolver.ts
2631
+ var MiddlewareResolver = class {
2632
+ constructor(store2) {
2633
+ this.store = store2;
2634
+ }
2635
+ static {
2636
+ __name(this, "MiddlewareResolver");
2637
+ }
2638
+ /**
2639
+ * Gets all applicable middlewares for a task (global + local, deduplicated)
2640
+ */
2641
+ getApplicableTaskMiddlewares(task2) {
2642
+ const local = task2.middleware;
2643
+ const localIds = new Set(local.map((m) => m.id));
2644
+ const global = this.getEverywhereTaskMiddlewares(task2).filter(
2645
+ (m) => !localIds.has(m.id)
2646
+ );
2647
+ return [...global, ...local];
2648
+ }
2649
+ /**
2650
+ * Gets all applicable middlewares for a resource (global + local, deduplicated)
2651
+ */
2652
+ getApplicableResourceMiddlewares(resource2) {
2653
+ const local = resource2.middleware;
2654
+ const localIds = new Set(local.map((m) => m.id));
2655
+ const global = this.getEverywhereResourceMiddlewares(resource2).filter(
2656
+ (m) => !localIds.has(m.id)
2657
+ );
2658
+ return [...global, ...local];
2659
+ }
2660
+ /**
2661
+ * Applies tunnel policy filter to middlewares if task is tunneled
2662
+ * Only allows whitelisted middlewares when tunnel policy is set
2663
+ */
2664
+ applyTunnelPolicyFilter(task2, middlewares) {
2665
+ const tDef = this.store.tasks.get(task2.id).task;
2666
+ const isLocallyTunneled = tDef.isTunneled;
2667
+ if (!isLocallyTunneled || !globalTags.tunnelPolicy.exists(tDef)) {
2668
+ return middlewares;
2669
+ }
2670
+ const cfg = globalTags.tunnelPolicy.extract(task2);
2671
+ const allowList = cfg?.client;
2672
+ if (!Array.isArray(allowList)) {
2673
+ return middlewares;
2674
+ }
2675
+ const toId = /* @__PURE__ */ __name((x) => typeof x === "string" ? x : x?.id, "toId");
2676
+ const allowed = new Set(allowList.map(toId).filter(Boolean));
2677
+ return middlewares.filter((m) => allowed.has(m.id));
2678
+ }
2679
+ /**
2680
+ * Gets all "everywhere" middlewares that apply to the given task
2681
+ */
2682
+ getEverywhereTaskMiddlewares(task2) {
2683
+ return Array.from(this.store.taskMiddlewares.values()).filter((x) => Boolean(x.middleware.everywhere)).filter((x) => {
2684
+ if (typeof x.middleware.everywhere === "function") {
2685
+ return x.middleware.everywhere(task2);
2612
2686
  }
2613
- this.perMiddlewareInterceptors.get(middleware.id).push(interceptor);
2614
- } else if (isResourceMiddleware(middleware)) {
2615
- if (!this.perResourceMiddlewareInterceptors.has(middleware.id)) {
2616
- this.perResourceMiddlewareInterceptors.set(middleware.id, []);
2687
+ return true;
2688
+ }).map((x) => x.middleware);
2689
+ }
2690
+ /**
2691
+ * Gets all "everywhere" middlewares that apply to the given resource
2692
+ */
2693
+ getEverywhereResourceMiddlewares(resource2) {
2694
+ return Array.from(this.store.resourceMiddlewares.values()).filter((x) => Boolean(x.middleware.everywhere)).filter((x) => {
2695
+ if (typeof x.middleware.everywhere === "function") {
2696
+ return x.middleware.everywhere(resource2);
2617
2697
  }
2618
- this.perResourceMiddlewareInterceptors.get(middleware.id).push(interceptor);
2619
- } else {
2620
- throw new Error("Unknown middleware type");
2698
+ return true;
2699
+ }).map((x) => x.middleware);
2700
+ }
2701
+ };
2702
+
2703
+ // src/models/middleware/ValidationHelper.ts
2704
+ var ValidationHelper = class {
2705
+ static {
2706
+ __name(this, "ValidationHelper");
2707
+ }
2708
+ /**
2709
+ * Validates input using the provided schema
2710
+ * @throws ValidationError if validation fails
2711
+ */
2712
+ static validateInput(value, schema, id2, type) {
2713
+ if (!schema) return value;
2714
+ try {
2715
+ return schema.parse(value);
2716
+ } catch (error2) {
2717
+ return validationError.throw({
2718
+ subject: `${type} input`,
2719
+ id: id2,
2720
+ originalError: error2 instanceof Error ? error2 : new Error(String(error2))
2721
+ });
2621
2722
  }
2622
2723
  }
2623
2724
  /**
2624
- * Wrap a middleware with its specific interceptors in onion style
2725
+ * Validates result using the provided schema
2726
+ * @throws ValidationError if validation fails
2625
2727
  */
2626
- wrapMiddlewareWithInterceptors(middleware, middlewareRunner, interceptors) {
2627
- if (!interceptors.length) {
2628
- return middlewareRunner;
2728
+ static validateResult(value, schema, id2, type) {
2729
+ if (!schema) return value;
2730
+ try {
2731
+ return schema.parse(value);
2732
+ } catch (error2) {
2733
+ return validationError.throw({
2734
+ subject: `${type} result`,
2735
+ id: id2,
2736
+ originalError: error2 instanceof Error ? error2 : new Error(String(error2))
2737
+ });
2629
2738
  }
2630
- const reversedInterceptors = [...interceptors].reverse();
2631
- let wrapped = middlewareRunner;
2632
- for (let i = reversedInterceptors.length - 1; i >= 0; i--) {
2633
- const interceptor = reversedInterceptors[i];
2739
+ }
2740
+ };
2741
+
2742
+ // src/models/middleware/TaskMiddlewareComposer.ts
2743
+ var TaskMiddlewareComposer = class {
2744
+ constructor(store2, interceptorRegistry, middlewareResolver) {
2745
+ this.store = store2;
2746
+ this.interceptorRegistry = interceptorRegistry;
2747
+ this.middlewareResolver = middlewareResolver;
2748
+ }
2749
+ static {
2750
+ __name(this, "TaskMiddlewareComposer");
2751
+ }
2752
+ /**
2753
+ * Composes a complete task runner with all middleware and interceptors applied
2754
+ */
2755
+ compose(task2) {
2756
+ const storeTask = this.store.tasks.get(task2.id);
2757
+ let runner = this.createBaseRunner(task2, storeTask);
2758
+ runner = this.applyLocalInterceptors(runner, storeTask);
2759
+ runner = this.applyGlobalInterceptors(runner, task2);
2760
+ runner = this.applyMiddlewares(runner, task2, storeTask);
2761
+ return runner;
2762
+ }
2763
+ /**
2764
+ * Creates the base task runner with input/result validation
2765
+ */
2766
+ createBaseRunner(task2, storeTask) {
2767
+ return async (input) => {
2768
+ const runnerTask = this.resolveTaskDefinition(task2, storeTask.task);
2769
+ const validatedInput = ValidationHelper.validateInput(
2770
+ input,
2771
+ runnerTask.inputSchema,
2772
+ runnerTask.id,
2773
+ "Task"
2774
+ );
2775
+ const rawResult = await runnerTask.run(
2776
+ validatedInput,
2777
+ storeTask.computedDependencies
2778
+ );
2779
+ return ValidationHelper.validateResult(
2780
+ rawResult,
2781
+ runnerTask.resultSchema,
2782
+ runnerTask.id,
2783
+ "Task"
2784
+ );
2785
+ };
2786
+ }
2787
+ /**
2788
+ * Determines which task definition to use for execution
2789
+ * Prefers store definition when task is tunneled (tunnel overrides apply)
2790
+ */
2791
+ resolveTaskDefinition(task2, storeTask) {
2792
+ const isLocallyTunneled = task2.isTunneled || storeTask.isTunneled;
2793
+ return isLocallyTunneled ? storeTask : task2;
2794
+ }
2795
+ /**
2796
+ * Applies local per-task interceptors (closest to the task)
2797
+ */
2798
+ applyLocalInterceptors(runner, storeTask) {
2799
+ if (!storeTask.interceptors || storeTask.interceptors.length === 0) {
2800
+ return runner;
2801
+ }
2802
+ let wrapped = runner;
2803
+ for (let i = storeTask.interceptors.length - 1; i >= 0; i--) {
2804
+ const interceptor = storeTask.interceptors[i];
2634
2805
  const nextFunction = wrapped;
2635
- wrapped = /* @__PURE__ */ __name(async (input) => {
2636
- const executionInput = {
2637
- task: {
2638
- definition: null,
2639
- // Will be filled by middleware.run
2640
- input
2641
- },
2642
- next: nextFunction
2643
- };
2644
- const wrappedNext = /* @__PURE__ */ __name((i2) => {
2645
- return nextFunction(i2.task.input);
2646
- }, "wrappedNext");
2647
- return interceptor(wrappedNext, executionInput);
2648
- }, "wrapped");
2806
+ wrapped = /* @__PURE__ */ __name(async (input) => interceptor(nextFunction, input), "wrapped");
2649
2807
  }
2650
2808
  return wrapped;
2651
2809
  }
2652
2810
  /**
2653
- * Wrap a resource middleware with its specific interceptors in onion style
2811
+ * Applies global task middleware interceptors
2654
2812
  */
2655
- wrapResourceMiddlewareWithInterceptors(middleware, middlewareRunner, interceptors) {
2656
- if (!interceptors.length) {
2657
- return middlewareRunner;
2813
+ applyGlobalInterceptors(runner, task2) {
2814
+ const interceptors = this.interceptorRegistry.getGlobalTaskInterceptors();
2815
+ if (interceptors.length === 0) {
2816
+ return runner;
2658
2817
  }
2659
2818
  const reversedInterceptors = [...interceptors].reverse();
2660
- let wrapped = middlewareRunner;
2819
+ const createExecutionInput = /* @__PURE__ */ __name((input, nextFunc) => ({
2820
+ task: {
2821
+ definition: task2,
2822
+ input
2823
+ },
2824
+ next: nextFunc
2825
+ }), "createExecutionInput");
2826
+ let currentNext = runner;
2661
2827
  for (let i = reversedInterceptors.length - 1; i >= 0; i--) {
2662
2828
  const interceptor = reversedInterceptors[i];
2663
- const nextFunction = wrapped;
2664
- wrapped = /* @__PURE__ */ __name(async (config) => {
2665
- const executionInput = {
2666
- resource: {
2667
- definition: null,
2668
- // Will be filled by middleware.run
2669
- config
2670
- },
2671
- next: nextFunction
2672
- };
2673
- const wrappedNext = /* @__PURE__ */ __name((input) => {
2674
- return nextFunction(input.resource.config);
2829
+ const nextFunction = currentNext;
2830
+ currentNext = /* @__PURE__ */ __name(async (input) => {
2831
+ const executionInput = createExecutionInput(input, nextFunction);
2832
+ const wrappedNext = /* @__PURE__ */ __name((i2) => {
2833
+ return nextFunction(i2.task.input);
2675
2834
  }, "wrappedNext");
2676
2835
  return interceptor(wrappedNext, executionInput);
2677
- }, "wrapped");
2836
+ }, "currentNext");
2678
2837
  }
2679
- return wrapped;
2838
+ return currentNext;
2680
2839
  }
2681
2840
  /**
2682
- * Compose a runner for a task with its local interceptors and applicable middlewares.
2683
- * Returns a function that accepts the task input and resolves to the task output.
2841
+ * Applies task middleware layers (global first, then local)
2684
2842
  */
2685
- composeTaskRunner(task2) {
2686
- const storeTask = this.store.tasks.get(task2.id);
2687
- const tDef = storeTask.task;
2688
- let next = /* @__PURE__ */ __name(async (input) => {
2689
- let rawInput = input;
2690
- const isLocallyTunneled = task2[symbolTunneledTask] === "client" || tDef[symbolTunneledTask] === "client";
2691
- const runnerTask = isLocallyTunneled ? tDef : task2;
2692
- if (runnerTask.inputSchema) {
2693
- try {
2694
- rawInput = runnerTask.inputSchema.parse(rawInput);
2695
- } catch (error2) {
2696
- validationError.throw({
2697
- subject: "Task input",
2698
- id: runnerTask.id,
2699
- originalError: error2 instanceof Error ? error2 : new Error(String(error2))
2700
- });
2701
- }
2702
- }
2703
- const deps = storeTask.computedDependencies;
2704
- const rawResult = await runnerTask.run.call(null, rawInput, deps);
2705
- if (runnerTask.resultSchema) {
2706
- try {
2707
- return runnerTask.resultSchema.parse(rawResult);
2708
- } catch (error2) {
2709
- validationError.throw({
2710
- subject: "Task result",
2711
- id: runnerTask.id,
2712
- originalError: error2
2713
- });
2714
- }
2715
- }
2716
- return rawResult;
2717
- }, "next");
2718
- if (storeTask.interceptors && storeTask.interceptors.length > 0) {
2719
- for (let i = storeTask.interceptors.length - 1; i >= 0; i--) {
2720
- const interceptor = storeTask.interceptors[i];
2721
- const nextFunction = next;
2722
- next = /* @__PURE__ */ __name(async (input) => interceptor(nextFunction, input), "next");
2723
- }
2724
- }
2725
- if (this.taskMiddlewareInterceptors.length > 0) {
2726
- const reversedInterceptors = [
2727
- ...this.taskMiddlewareInterceptors
2728
- ].reverse();
2729
- const createExecutionInput = /* @__PURE__ */ __name((input, nextFunc) => ({
2730
- task: {
2731
- definition: task2,
2732
- input
2733
- },
2734
- next: nextFunc
2735
- }), "createExecutionInput");
2736
- let currentNext = next;
2737
- for (let i = reversedInterceptors.length - 1; i >= 0; i--) {
2738
- const interceptor = reversedInterceptors[i];
2739
- const nextFunction = currentNext;
2740
- currentNext = /* @__PURE__ */ __name(async (input) => {
2741
- const executionInput = createExecutionInput(input, nextFunction);
2742
- const wrappedNext = /* @__PURE__ */ __name((i2) => {
2743
- return nextFunction(i2.task.input);
2744
- }, "wrappedNext");
2745
- return interceptor(wrappedNext, executionInput);
2746
- }, "currentNext");
2747
- }
2748
- next = currentNext;
2749
- }
2750
- let createdMiddlewares = this.getApplicableTaskMiddlewares(task2);
2751
- const isLocallyTunneledPolicy = task2[symbolTunneledTask] === "client" || tDef[symbolTunneledTask] === "client";
2752
- if (isLocallyTunneledPolicy && globalTags.tunnelPolicy.exists(tDef)) {
2753
- const cfg = globalTags.tunnelPolicy.extract(task2);
2754
- const allowList = cfg?.client || void 0;
2755
- if (Array.isArray(allowList)) {
2756
- const toId = /* @__PURE__ */ __name((x) => typeof x === "string" ? x : x?.id, "toId");
2757
- const allowed = new Set(allowList.map(toId).filter(Boolean));
2758
- createdMiddlewares = createdMiddlewares.filter(
2759
- (m) => allowed.has(m.id)
2760
- );
2761
- }
2762
- }
2763
- if (createdMiddlewares.length === 0) {
2764
- return next;
2765
- }
2766
- for (let i = createdMiddlewares.length - 1; i >= 0; i--) {
2767
- const middleware = createdMiddlewares[i];
2843
+ applyMiddlewares(runner, task2, storeTask) {
2844
+ storeTask.task;
2845
+ let middlewares = this.middlewareResolver.getApplicableTaskMiddlewares(task2);
2846
+ middlewares = this.middlewareResolver.applyTunnelPolicyFilter(task2, middlewares);
2847
+ if (middlewares.length === 0) {
2848
+ return runner;
2849
+ }
2850
+ let next = runner;
2851
+ for (let i = middlewares.length - 1; i >= 0; i--) {
2852
+ const middleware = middlewares[i];
2768
2853
  const storeMiddleware = this.store.taskMiddlewares.get(middleware.id);
2769
2854
  const nextFunction = next;
2770
2855
  const baseMiddlewareRunner = /* @__PURE__ */ __name(async (input) => {
@@ -2780,51 +2865,96 @@ var MiddlewareManager = class {
2780
2865
  middleware.config
2781
2866
  );
2782
2867
  }, "baseMiddlewareRunner");
2783
- const middlewareInterceptors = this.perMiddlewareInterceptors.get(middleware.id) || [];
2784
- const wrappedMiddleware = this.wrapMiddlewareWithInterceptors(
2785
- middleware,
2868
+ const middlewareInterceptors = this.interceptorRegistry.getTaskMiddlewareInterceptors(middleware.id);
2869
+ next = this.wrapWithInterceptors(
2786
2870
  baseMiddlewareRunner,
2787
2871
  middlewareInterceptors
2788
2872
  );
2789
- next = wrappedMiddleware;
2790
2873
  }
2791
2874
  return next;
2792
2875
  }
2793
2876
  /**
2794
- * Run a resource init wrapped with its applicable middlewares.
2877
+ * Wraps a middleware runner with its specific interceptors in onion style
2795
2878
  */
2796
- async runResourceInit(resource2, config, dependencies, context) {
2797
- let next = /* @__PURE__ */ __name(async (cfg) => {
2798
- if (!resource2.init) return void 0;
2799
- const rawValue = await resource2.init.call(
2800
- null,
2801
- cfg,
2802
- dependencies,
2803
- context
2804
- );
2805
- if (resource2.resultSchema) {
2806
- try {
2807
- return resource2.resultSchema.parse(rawValue);
2808
- } catch (error2) {
2809
- validationError.throw({
2810
- subject: "Resource result",
2811
- id: resource2.id,
2812
- originalError: error2
2813
- });
2814
- }
2815
- }
2816
- return rawValue;
2817
- }, "next");
2818
- const createdMiddlewares = this.getApplicableResourceMiddlewares(resource2);
2819
- for (let i = createdMiddlewares.length - 1; i >= 0; i--) {
2820
- const middleware = createdMiddlewares[i];
2821
- const storeMiddleware = this.store.resourceMiddlewares.get(
2822
- middleware.id
2879
+ wrapWithInterceptors(middlewareRunner, interceptors) {
2880
+ if (interceptors.length === 0) {
2881
+ return middlewareRunner;
2882
+ }
2883
+ const reversedInterceptors = [...interceptors].reverse();
2884
+ let wrapped = middlewareRunner;
2885
+ for (let i = reversedInterceptors.length - 1; i >= 0; i--) {
2886
+ const interceptor = reversedInterceptors[i];
2887
+ const nextFunction = wrapped;
2888
+ wrapped = /* @__PURE__ */ __name(async (input) => {
2889
+ const executionInput = {
2890
+ task: {
2891
+ definition: null,
2892
+ input
2893
+ },
2894
+ next: nextFunction
2895
+ };
2896
+ const wrappedNext = /* @__PURE__ */ __name((i2) => {
2897
+ return nextFunction(i2.task.input);
2898
+ }, "wrappedNext");
2899
+ return interceptor(wrappedNext, executionInput);
2900
+ }, "wrapped");
2901
+ }
2902
+ return wrapped;
2903
+ }
2904
+ };
2905
+
2906
+ // src/models/middleware/ResourceMiddlewareComposer.ts
2907
+ var ResourceMiddlewareComposer = class {
2908
+ constructor(store2, interceptorRegistry, middlewareResolver) {
2909
+ this.store = store2;
2910
+ this.interceptorRegistry = interceptorRegistry;
2911
+ this.middlewareResolver = middlewareResolver;
2912
+ }
2913
+ static {
2914
+ __name(this, "ResourceMiddlewareComposer");
2915
+ }
2916
+ /**
2917
+ * Runs resource initialization with all middleware and interceptors applied
2918
+ */
2919
+ async runInit(resource2, config, dependencies, context) {
2920
+ let runner = this.createBaseInitRunner(resource2, dependencies, context);
2921
+ runner = this.applyMiddlewares(runner, resource2);
2922
+ runner = this.applyGlobalInterceptors(runner, resource2);
2923
+ return runner(config);
2924
+ }
2925
+ /**
2926
+ * Creates the base resource init runner with result validation
2927
+ */
2928
+ createBaseInitRunner(resource2, dependencies, context) {
2929
+ return async (config) => {
2930
+ if (!resource2.init) {
2931
+ return void 0;
2932
+ }
2933
+ const rawValue = await resource2.init(config, dependencies, context);
2934
+ return ValidationHelper.validateResult(
2935
+ rawValue,
2936
+ resource2.resultSchema,
2937
+ resource2.id,
2938
+ "Resource"
2823
2939
  );
2940
+ };
2941
+ }
2942
+ /**
2943
+ * Applies resource middleware layers
2944
+ */
2945
+ applyMiddlewares(runner, resource2) {
2946
+ const middlewares = this.middlewareResolver.getApplicableResourceMiddlewares(resource2);
2947
+ if (middlewares.length === 0) {
2948
+ return runner;
2949
+ }
2950
+ let next = runner;
2951
+ for (let i = middlewares.length - 1; i >= 0; i--) {
2952
+ const middleware = middlewares[i];
2953
+ const storeMiddleware = this.store.resourceMiddlewares.get(middleware.id);
2824
2954
  const nextFunction = next;
2825
2955
  const baseMiddlewareRunner = /* @__PURE__ */ __name(async (cfg) => {
2826
2956
  try {
2827
- const result = await storeMiddleware.middleware.run(
2957
+ return await storeMiddleware.middleware.run(
2828
2958
  {
2829
2959
  resource: {
2830
2960
  definition: resource2,
@@ -2835,7 +2965,6 @@ var MiddlewareManager = class {
2835
2965
  storeMiddleware.computedDependencies,
2836
2966
  middleware.config
2837
2967
  );
2838
- return result;
2839
2968
  } catch (error2) {
2840
2969
  try {
2841
2970
  await this.store.onUnhandledError({
@@ -2848,79 +2977,192 @@ var MiddlewareManager = class {
2848
2977
  throw error2;
2849
2978
  }
2850
2979
  }, "baseMiddlewareRunner");
2851
- const middlewareInterceptors = this.perResourceMiddlewareInterceptors.get(middleware.id) || [];
2852
- const wrappedMiddleware = this.wrapResourceMiddlewareWithInterceptors(
2853
- middleware,
2980
+ const middlewareInterceptors = this.interceptorRegistry.getResourceMiddlewareInterceptors(middleware.id);
2981
+ next = this.wrapWithInterceptors(
2854
2982
  baseMiddlewareRunner,
2855
2983
  middlewareInterceptors
2856
2984
  );
2857
- next = wrappedMiddleware;
2858
- }
2859
- if (this.resourceMiddlewareInterceptors.length > 0) {
2860
- const reversedInterceptors = [
2861
- ...this.resourceMiddlewareInterceptors
2862
- ].reverse();
2863
- const createExecutionInput = /* @__PURE__ */ __name((config2, nextFunc) => ({
2864
- resource: {
2865
- definition: resource2,
2866
- config: config2
2867
- },
2868
- next: nextFunc
2869
- }), "createExecutionInput");
2870
- let currentNext = next;
2871
- for (let i = reversedInterceptors.length - 1; i >= 0; i--) {
2872
- const interceptor = reversedInterceptors[i];
2873
- const nextFunction = currentNext;
2874
- currentNext = /* @__PURE__ */ __name(async (cfg) => {
2875
- const executionInput = createExecutionInput(cfg, nextFunction);
2876
- const wrappedNext = /* @__PURE__ */ __name((input) => {
2877
- return nextFunction(input.resource.config);
2878
- }, "wrappedNext");
2879
- return interceptor(wrappedNext, executionInput);
2880
- }, "currentNext");
2881
- }
2882
- next = currentNext;
2883
- }
2884
- return next(config);
2985
+ }
2986
+ return next;
2885
2987
  }
2886
- getApplicableTaskMiddlewares(task2) {
2887
- const existingMiddlewares = task2.middleware;
2888
- const existingMiddlewareIds = existingMiddlewares.map((x) => x.id);
2889
- const globalMiddlewares2 = this.getEverywhereMiddlewareForTasks(task2).filter(
2890
- (x) => !existingMiddlewareIds.includes(x.id)
2988
+ /**
2989
+ * Applies global resource middleware interceptors
2990
+ */
2991
+ applyGlobalInterceptors(runner, resource2) {
2992
+ const interceptors = this.interceptorRegistry.getGlobalResourceInterceptors();
2993
+ if (interceptors.length === 0) {
2994
+ return runner;
2995
+ }
2996
+ const reversedInterceptors = [...interceptors].reverse();
2997
+ const createExecutionInput = /* @__PURE__ */ __name((config, nextFunc) => ({
2998
+ resource: {
2999
+ definition: resource2,
3000
+ config
3001
+ },
3002
+ next: nextFunc
3003
+ }), "createExecutionInput");
3004
+ let currentNext = runner;
3005
+ for (let i = reversedInterceptors.length - 1; i >= 0; i--) {
3006
+ const interceptor = reversedInterceptors[i];
3007
+ const nextFunction = currentNext;
3008
+ currentNext = /* @__PURE__ */ __name(async (cfg) => {
3009
+ const executionInput = createExecutionInput(cfg, nextFunction);
3010
+ const wrappedNext = /* @__PURE__ */ __name((input) => {
3011
+ return nextFunction(input.resource.config);
3012
+ }, "wrappedNext");
3013
+ return interceptor(wrappedNext, executionInput);
3014
+ }, "currentNext");
3015
+ }
3016
+ return currentNext;
3017
+ }
3018
+ /**
3019
+ * Wraps a middleware runner with its specific interceptors in onion style
3020
+ */
3021
+ wrapWithInterceptors(middlewareRunner, interceptors) {
3022
+ if (interceptors.length === 0) {
3023
+ return middlewareRunner;
3024
+ }
3025
+ const reversedInterceptors = [...interceptors].reverse();
3026
+ let wrapped = middlewareRunner;
3027
+ for (let i = reversedInterceptors.length - 1; i >= 0; i--) {
3028
+ const interceptor = reversedInterceptors[i];
3029
+ const nextFunction = wrapped;
3030
+ wrapped = /* @__PURE__ */ __name(async (config) => {
3031
+ const executionInput = {
3032
+ resource: {
3033
+ definition: null,
3034
+ config
3035
+ },
3036
+ next: nextFunction
3037
+ };
3038
+ const wrappedNext = /* @__PURE__ */ __name((input) => {
3039
+ return nextFunction(input.resource.config);
3040
+ }, "wrappedNext");
3041
+ return interceptor(wrappedNext, executionInput);
3042
+ }, "wrapped");
3043
+ }
3044
+ return wrapped;
3045
+ }
3046
+ };
3047
+
3048
+ // src/models/MiddlewareManager.ts
3049
+ var MiddlewareManager = class {
3050
+ constructor(store2, eventManager, logger) {
3051
+ this.store = store2;
3052
+ this.eventManager = eventManager;
3053
+ this.logger = logger;
3054
+ this.interceptorRegistry = new InterceptorRegistry();
3055
+ this.middlewareResolver = new MiddlewareResolver(store2);
3056
+ this.taskComposer = new TaskMiddlewareComposer(
3057
+ store2,
3058
+ this.interceptorRegistry,
3059
+ this.middlewareResolver
3060
+ );
3061
+ this.resourceComposer = new ResourceMiddlewareComposer(
3062
+ store2,
3063
+ this.interceptorRegistry,
3064
+ this.middlewareResolver
2891
3065
  );
2892
- return [...globalMiddlewares2, ...existingMiddlewares];
2893
3066
  }
2894
- getApplicableResourceMiddlewares(resource2) {
2895
- const existingMiddlewares = resource2.middleware;
2896
- const existingMiddlewareIds = existingMiddlewares.map((x) => x.id);
2897
- const globalMiddlewares2 = this.getEverywhereMiddlewareForResources(
2898
- resource2
2899
- ).filter((x) => !existingMiddlewareIds.includes(x.id));
2900
- return [...globalMiddlewares2, ...existingMiddlewares];
3067
+ static {
3068
+ __name(this, "MiddlewareManager");
2901
3069
  }
2902
3070
  /**
2903
- * @param task
2904
- * @returns
3071
+ * @internal
3072
+ */
3073
+ get taskMiddlewareInterceptors() {
3074
+ return this.interceptorRegistry.getGlobalTaskInterceptors();
3075
+ }
3076
+ /**
3077
+ * @internal
3078
+ */
3079
+ get resourceMiddlewareInterceptors() {
3080
+ return this.interceptorRegistry.getGlobalResourceInterceptors();
3081
+ }
3082
+ /**
3083
+ * Gets the current lock status of the MiddlewareManager
3084
+ */
3085
+ get isLocked() {
3086
+ return this.interceptorRegistry.isLocked;
3087
+ }
3088
+ /**
3089
+ * Locks the MiddlewareManager, preventing any further modifications to interceptors
3090
+ */
3091
+ lock() {
3092
+ this.interceptorRegistry.lock();
3093
+ }
3094
+ /**
3095
+ * Adds an interceptor for task or resource middleware execution
3096
+ * Interceptors are executed in the order they are added, with the ability to
3097
+ * modify, log, or prevent middleware execution
3098
+ *
3099
+ * @param kind - The type of middleware to intercept ("task" or "resource")
3100
+ * @param interceptor - The interceptor function to add
3101
+ */
3102
+ intercept(kind, interceptor) {
3103
+ if (kind === "task") {
3104
+ this.interceptorRegistry.addGlobalTaskInterceptor(
3105
+ interceptor
3106
+ );
3107
+ } else {
3108
+ this.interceptorRegistry.addGlobalResourceInterceptor(
3109
+ interceptor
3110
+ );
3111
+ }
3112
+ }
3113
+ /**
3114
+ * Adds an interceptor for a specific middleware instance with better type safety
3115
+ * This method automatically determines the type and provides type-safe access
3116
+ *
3117
+ * @param middleware - The middleware instance to intercept
3118
+ * @param interceptor - The interceptor function with proper typing
3119
+ */
3120
+ interceptMiddleware(middleware, interceptor) {
3121
+ if (isTaskMiddleware(middleware)) {
3122
+ this.interceptorRegistry.addTaskMiddlewareInterceptor(
3123
+ middleware.id,
3124
+ interceptor
3125
+ );
3126
+ } else if (isResourceMiddleware(middleware)) {
3127
+ this.interceptorRegistry.addResourceMiddlewareInterceptor(
3128
+ middleware.id,
3129
+ interceptor
3130
+ );
3131
+ } else {
3132
+ throw new Error("Unknown middleware type");
3133
+ }
3134
+ }
3135
+ /**
3136
+ * Compose a runner for a task with its local interceptors and applicable middlewares.
3137
+ * Returns a function that accepts the task input and resolves to the task output.
3138
+ */
3139
+ composeTaskRunner(task2) {
3140
+ return this.taskComposer.compose(task2);
3141
+ }
3142
+ /**
3143
+ * Run a resource init wrapped with its applicable middlewares.
3144
+ */
3145
+ async runResourceInit(resource2, config, dependencies, context) {
3146
+ return this.resourceComposer.runInit(
3147
+ resource2,
3148
+ config,
3149
+ dependencies,
3150
+ context
3151
+ );
3152
+ }
3153
+ /**
3154
+ * Gets all "everywhere" middlewares that apply to the given task
3155
+ * @deprecated Internal method exposed for testing - may be removed in future versions
2905
3156
  */
2906
3157
  getEverywhereMiddlewareForTasks(task2) {
2907
- return Array.from(this.store.taskMiddlewares.values()).filter((x) => Boolean(x.middleware.everywhere)).filter((x) => {
2908
- if (typeof x.middleware.everywhere === "function") {
2909
- return x.middleware.everywhere(task2);
2910
- }
2911
- return true;
2912
- }).map((x) => x.middleware);
3158
+ return this.middlewareResolver.getEverywhereTaskMiddlewares(task2);
2913
3159
  }
2914
3160
  /**
2915
- * Returns all global middleware for resource, which do not depend on the target resource.
3161
+ * Gets all "everywhere" middlewares that apply to the given resource
3162
+ * @deprecated Internal method exposed for testing - may be removed in future versions
2916
3163
  */
2917
- getEverywhereMiddlewareForResources(target) {
2918
- return Array.from(this.store.resourceMiddlewares.values()).filter((x) => Boolean(x.middleware.everywhere)).filter((x) => {
2919
- if (typeof x.middleware.everywhere === "function") {
2920
- return x.middleware.everywhere(target);
2921
- }
2922
- return true;
2923
- }).map((x) => x.middleware);
3164
+ getEverywhereMiddlewareForResources(resource2) {
3165
+ return this.middlewareResolver.getEverywhereResourceMiddlewares(resource2);
2924
3166
  }
2925
3167
  };
2926
3168
 
@@ -4669,7 +4911,7 @@ var tunnelResourceMiddleware = defineResourceMiddleware({
4669
4911
  t.run = (async (input) => {
4670
4912
  return value.run(t, input);
4671
4913
  });
4672
- t[symbolTunneledTask] = "client";
4914
+ t.isTunneled = true;
4673
4915
  t[symbolTunneledBy] = resourceId;
4674
4916
  }
4675
4917
  if (events.length > 0) {