@bluelibs/runner 4.8.2 → 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.
@@ -37,8 +37,7 @@ __export(defs_exports, {
37
37
  symbolTagConfigured: () => symbolTagConfigured,
38
38
  symbolTask: () => symbolTask,
39
39
  symbolTaskMiddleware: () => symbolTaskMiddleware,
40
- symbolTunneledBy: () => symbolTunneledBy,
41
- symbolTunneledTask: () => symbolTunneledTask
40
+ symbolTunneledBy: () => symbolTunneledBy
42
41
  });
43
42
 
44
43
  // src/types/symbols.ts
@@ -62,9 +61,6 @@ var symbolResourceMiddleware = Symbol.for(
62
61
  var symbolMiddlewareConfigured = Symbol.for(
63
62
  "runner.middlewareConfigured"
64
63
  );
65
- var symbolTunneledTask = Symbol.for(
66
- "runner.tunneledTask"
67
- );
68
64
  var symbolTunneledBy = Symbol.for(
69
65
  "runner.tunneledBy"
70
66
  );
@@ -2072,39 +2068,33 @@ var TaskRunner = class {
2072
2068
  }
2073
2069
  };
2074
2070
 
2075
- // src/models/MiddlewareManager.ts
2076
- var MiddlewareManager = class {
2077
- constructor(store2, eventManager, logger) {
2078
- this.store = store2;
2079
- this.eventManager = eventManager;
2080
- this.logger = logger;
2081
- // Interceptor storage
2082
- this.taskMiddlewareInterceptors = [];
2083
- this.resourceMiddlewareInterceptors = [];
2084
- // Per-middleware interceptor storage
2085
- this.perMiddlewareInterceptors = /* @__PURE__ */ new Map();
2086
- this.perResourceMiddlewareInterceptors = /* @__PURE__ */ new Map();
2087
- // Locking mechanism to prevent modifications after initialization
2071
+ // src/models/middleware/InterceptorRegistry.ts
2072
+ var InterceptorRegistry = class {
2073
+ constructor() {
2074
+ this.taskInterceptors = [];
2075
+ this.resourceInterceptors = [];
2076
+ this.perTaskMiddleware = /* @__PURE__ */ new Map();
2077
+ this.perResourceMiddleware = /* @__PURE__ */ new Map();
2088
2078
  this.#isLocked = false;
2089
2079
  }
2090
2080
  static {
2091
- __name(this, "MiddlewareManager");
2081
+ __name(this, "InterceptorRegistry");
2092
2082
  }
2093
2083
  #isLocked;
2094
2084
  /**
2095
- * Gets the current lock status of the MiddlewareManager
2085
+ * Gets the current lock status
2096
2086
  */
2097
2087
  get isLocked() {
2098
2088
  return this.#isLocked;
2099
2089
  }
2100
2090
  /**
2101
- * Locks the MiddlewareManager, preventing any further modifications to interceptors
2091
+ * Locks the registry, preventing any further modifications
2102
2092
  */
2103
2093
  lock() {
2104
2094
  this.#isLocked = true;
2105
2095
  }
2106
2096
  /**
2107
- * Throws an error if the MiddlewareManager is locked
2097
+ * Throws an error if the registry is locked
2108
2098
  */
2109
2099
  checkLock() {
2110
2100
  if (this.#isLocked) {
@@ -2112,193 +2102,288 @@ var MiddlewareManager = class {
2112
2102
  }
2113
2103
  }
2114
2104
  /**
2115
- * Adds an interceptor for task or resource middleware execution
2116
- * Interceptors are executed in the order they are added, with the ability to
2117
- * modify, log, or prevent middleware execution
2118
- *
2119
- * @param kind - The type of middleware to intercept ("task" or "resource")
2120
- * @param interceptor - The interceptor function to add
2105
+ * Adds a global task interceptor
2121
2106
  */
2122
- intercept(kind, interceptor) {
2107
+ addGlobalTaskInterceptor(interceptor) {
2123
2108
  this.checkLock();
2124
- if (kind === "task") {
2125
- this.taskMiddlewareInterceptors.push(
2126
- interceptor
2127
- );
2128
- } else {
2129
- this.resourceMiddlewareInterceptors.push(
2130
- interceptor
2131
- );
2109
+ this.taskInterceptors.push(interceptor);
2110
+ }
2111
+ /**
2112
+ * Adds a global resource interceptor
2113
+ */
2114
+ addGlobalResourceInterceptor(interceptor) {
2115
+ this.checkLock();
2116
+ this.resourceInterceptors.push(interceptor);
2117
+ }
2118
+ /**
2119
+ * Adds an interceptor for a specific task middleware instance
2120
+ */
2121
+ addTaskMiddlewareInterceptor(middlewareId, interceptor) {
2122
+ this.checkLock();
2123
+ if (!this.perTaskMiddleware.has(middlewareId)) {
2124
+ this.perTaskMiddleware.set(middlewareId, []);
2132
2125
  }
2126
+ this.perTaskMiddleware.get(middlewareId).push(interceptor);
2133
2127
  }
2134
2128
  /**
2135
- * Adds an interceptor for a specific middleware instance with better type safety
2136
- * This method automatically determines the type and provides type-safe access
2137
- *
2138
- * @param middleware - The middleware instance to intercept
2139
- * @param interceptor - The interceptor function with proper typing
2129
+ * Adds an interceptor for a specific resource middleware instance
2140
2130
  */
2141
- interceptMiddleware(middleware, interceptor) {
2131
+ addResourceMiddlewareInterceptor(middlewareId, interceptor) {
2142
2132
  this.checkLock();
2143
- if (isTaskMiddleware(middleware)) {
2144
- if (!this.perMiddlewareInterceptors.has(middleware.id)) {
2145
- this.perMiddlewareInterceptors.set(middleware.id, []);
2133
+ if (!this.perResourceMiddleware.has(middlewareId)) {
2134
+ this.perResourceMiddleware.set(middlewareId, []);
2135
+ }
2136
+ this.perResourceMiddleware.get(middlewareId).push(interceptor);
2137
+ }
2138
+ /**
2139
+ * Gets all global task interceptors
2140
+ */
2141
+ getGlobalTaskInterceptors() {
2142
+ return this.taskInterceptors;
2143
+ }
2144
+ /**
2145
+ * Gets all global resource interceptors
2146
+ */
2147
+ getGlobalResourceInterceptors() {
2148
+ return this.resourceInterceptors;
2149
+ }
2150
+ /**
2151
+ * Gets interceptors for a specific task middleware
2152
+ */
2153
+ getTaskMiddlewareInterceptors(middlewareId) {
2154
+ return this.perTaskMiddleware.get(middlewareId) || [];
2155
+ }
2156
+ /**
2157
+ * Gets interceptors for a specific resource middleware
2158
+ */
2159
+ getResourceMiddlewareInterceptors(middlewareId) {
2160
+ return this.perResourceMiddleware.get(middlewareId) || [];
2161
+ }
2162
+ };
2163
+
2164
+ // src/models/middleware/MiddlewareResolver.ts
2165
+ var MiddlewareResolver = class {
2166
+ constructor(store2) {
2167
+ this.store = store2;
2168
+ }
2169
+ static {
2170
+ __name(this, "MiddlewareResolver");
2171
+ }
2172
+ /**
2173
+ * Gets all applicable middlewares for a task (global + local, deduplicated)
2174
+ */
2175
+ getApplicableTaskMiddlewares(task2) {
2176
+ const local = task2.middleware;
2177
+ const localIds = new Set(local.map((m) => m.id));
2178
+ const global = this.getEverywhereTaskMiddlewares(task2).filter(
2179
+ (m) => !localIds.has(m.id)
2180
+ );
2181
+ return [...global, ...local];
2182
+ }
2183
+ /**
2184
+ * Gets all applicable middlewares for a resource (global + local, deduplicated)
2185
+ */
2186
+ getApplicableResourceMiddlewares(resource2) {
2187
+ const local = resource2.middleware;
2188
+ const localIds = new Set(local.map((m) => m.id));
2189
+ const global = this.getEverywhereResourceMiddlewares(resource2).filter(
2190
+ (m) => !localIds.has(m.id)
2191
+ );
2192
+ return [...global, ...local];
2193
+ }
2194
+ /**
2195
+ * Applies tunnel policy filter to middlewares if task is tunneled
2196
+ * Only allows whitelisted middlewares when tunnel policy is set
2197
+ */
2198
+ applyTunnelPolicyFilter(task2, middlewares) {
2199
+ const tDef = this.store.tasks.get(task2.id).task;
2200
+ const isLocallyTunneled = tDef.isTunneled;
2201
+ if (!isLocallyTunneled || !globalTags.tunnelPolicy.exists(tDef)) {
2202
+ return middlewares;
2203
+ }
2204
+ const cfg = globalTags.tunnelPolicy.extract(task2);
2205
+ const allowList = cfg?.client;
2206
+ if (!Array.isArray(allowList)) {
2207
+ return middlewares;
2208
+ }
2209
+ const toId = /* @__PURE__ */ __name((x) => typeof x === "string" ? x : x?.id, "toId");
2210
+ const allowed = new Set(allowList.map(toId).filter(Boolean));
2211
+ return middlewares.filter((m) => allowed.has(m.id));
2212
+ }
2213
+ /**
2214
+ * Gets all "everywhere" middlewares that apply to the given task
2215
+ */
2216
+ getEverywhereTaskMiddlewares(task2) {
2217
+ return Array.from(this.store.taskMiddlewares.values()).filter((x) => Boolean(x.middleware.everywhere)).filter((x) => {
2218
+ if (typeof x.middleware.everywhere === "function") {
2219
+ return x.middleware.everywhere(task2);
2146
2220
  }
2147
- this.perMiddlewareInterceptors.get(middleware.id).push(interceptor);
2148
- } else if (isResourceMiddleware(middleware)) {
2149
- if (!this.perResourceMiddlewareInterceptors.has(middleware.id)) {
2150
- this.perResourceMiddlewareInterceptors.set(middleware.id, []);
2221
+ return true;
2222
+ }).map((x) => x.middleware);
2223
+ }
2224
+ /**
2225
+ * Gets all "everywhere" middlewares that apply to the given resource
2226
+ */
2227
+ getEverywhereResourceMiddlewares(resource2) {
2228
+ return Array.from(this.store.resourceMiddlewares.values()).filter((x) => Boolean(x.middleware.everywhere)).filter((x) => {
2229
+ if (typeof x.middleware.everywhere === "function") {
2230
+ return x.middleware.everywhere(resource2);
2151
2231
  }
2152
- this.perResourceMiddlewareInterceptors.get(middleware.id).push(interceptor);
2153
- } else {
2154
- throw new Error("Unknown middleware type");
2232
+ return true;
2233
+ }).map((x) => x.middleware);
2234
+ }
2235
+ };
2236
+
2237
+ // src/models/middleware/ValidationHelper.ts
2238
+ var ValidationHelper = class {
2239
+ static {
2240
+ __name(this, "ValidationHelper");
2241
+ }
2242
+ /**
2243
+ * Validates input using the provided schema
2244
+ * @throws ValidationError if validation fails
2245
+ */
2246
+ static validateInput(value, schema, id2, type) {
2247
+ if (!schema) return value;
2248
+ try {
2249
+ return schema.parse(value);
2250
+ } catch (error2) {
2251
+ return validationError.throw({
2252
+ subject: `${type} input`,
2253
+ id: id2,
2254
+ originalError: error2 instanceof Error ? error2 : new Error(String(error2))
2255
+ });
2155
2256
  }
2156
2257
  }
2157
2258
  /**
2158
- * Wrap a middleware with its specific interceptors in onion style
2259
+ * Validates result using the provided schema
2260
+ * @throws ValidationError if validation fails
2159
2261
  */
2160
- wrapMiddlewareWithInterceptors(middleware, middlewareRunner, interceptors) {
2161
- if (!interceptors.length) {
2162
- return middlewareRunner;
2262
+ static validateResult(value, schema, id2, type) {
2263
+ if (!schema) return value;
2264
+ try {
2265
+ return schema.parse(value);
2266
+ } catch (error2) {
2267
+ return validationError.throw({
2268
+ subject: `${type} result`,
2269
+ id: id2,
2270
+ originalError: error2 instanceof Error ? error2 : new Error(String(error2))
2271
+ });
2163
2272
  }
2164
- const reversedInterceptors = [...interceptors].reverse();
2165
- let wrapped = middlewareRunner;
2166
- for (let i = reversedInterceptors.length - 1; i >= 0; i--) {
2167
- const interceptor = reversedInterceptors[i];
2273
+ }
2274
+ };
2275
+
2276
+ // src/models/middleware/TaskMiddlewareComposer.ts
2277
+ var TaskMiddlewareComposer = class {
2278
+ constructor(store2, interceptorRegistry, middlewareResolver) {
2279
+ this.store = store2;
2280
+ this.interceptorRegistry = interceptorRegistry;
2281
+ this.middlewareResolver = middlewareResolver;
2282
+ }
2283
+ static {
2284
+ __name(this, "TaskMiddlewareComposer");
2285
+ }
2286
+ /**
2287
+ * Composes a complete task runner with all middleware and interceptors applied
2288
+ */
2289
+ compose(task2) {
2290
+ const storeTask = this.store.tasks.get(task2.id);
2291
+ let runner = this.createBaseRunner(task2, storeTask);
2292
+ runner = this.applyLocalInterceptors(runner, storeTask);
2293
+ runner = this.applyGlobalInterceptors(runner, task2);
2294
+ runner = this.applyMiddlewares(runner, task2, storeTask);
2295
+ return runner;
2296
+ }
2297
+ /**
2298
+ * Creates the base task runner with input/result validation
2299
+ */
2300
+ createBaseRunner(task2, storeTask) {
2301
+ return async (input) => {
2302
+ const runnerTask = this.resolveTaskDefinition(task2, storeTask.task);
2303
+ const validatedInput = ValidationHelper.validateInput(
2304
+ input,
2305
+ runnerTask.inputSchema,
2306
+ runnerTask.id,
2307
+ "Task"
2308
+ );
2309
+ const rawResult = await runnerTask.run(
2310
+ validatedInput,
2311
+ storeTask.computedDependencies
2312
+ );
2313
+ return ValidationHelper.validateResult(
2314
+ rawResult,
2315
+ runnerTask.resultSchema,
2316
+ runnerTask.id,
2317
+ "Task"
2318
+ );
2319
+ };
2320
+ }
2321
+ /**
2322
+ * Determines which task definition to use for execution
2323
+ * Prefers store definition when task is tunneled (tunnel overrides apply)
2324
+ */
2325
+ resolveTaskDefinition(task2, storeTask) {
2326
+ const isLocallyTunneled = task2.isTunneled || storeTask.isTunneled;
2327
+ return isLocallyTunneled ? storeTask : task2;
2328
+ }
2329
+ /**
2330
+ * Applies local per-task interceptors (closest to the task)
2331
+ */
2332
+ applyLocalInterceptors(runner, storeTask) {
2333
+ if (!storeTask.interceptors || storeTask.interceptors.length === 0) {
2334
+ return runner;
2335
+ }
2336
+ let wrapped = runner;
2337
+ for (let i = storeTask.interceptors.length - 1; i >= 0; i--) {
2338
+ const interceptor = storeTask.interceptors[i];
2168
2339
  const nextFunction = wrapped;
2169
- wrapped = /* @__PURE__ */ __name(async (input) => {
2170
- const executionInput = {
2171
- task: {
2172
- definition: null,
2173
- // Will be filled by middleware.run
2174
- input
2175
- },
2176
- next: nextFunction
2177
- };
2178
- const wrappedNext = /* @__PURE__ */ __name((i2) => {
2179
- return nextFunction(i2.task.input);
2180
- }, "wrappedNext");
2181
- return interceptor(wrappedNext, executionInput);
2182
- }, "wrapped");
2340
+ wrapped = /* @__PURE__ */ __name(async (input) => interceptor(nextFunction, input), "wrapped");
2183
2341
  }
2184
2342
  return wrapped;
2185
2343
  }
2186
2344
  /**
2187
- * Wrap a resource middleware with its specific interceptors in onion style
2345
+ * Applies global task middleware interceptors
2188
2346
  */
2189
- wrapResourceMiddlewareWithInterceptors(middleware, middlewareRunner, interceptors) {
2190
- if (!interceptors.length) {
2191
- return middlewareRunner;
2347
+ applyGlobalInterceptors(runner, task2) {
2348
+ const interceptors = this.interceptorRegistry.getGlobalTaskInterceptors();
2349
+ if (interceptors.length === 0) {
2350
+ return runner;
2192
2351
  }
2193
2352
  const reversedInterceptors = [...interceptors].reverse();
2194
- let wrapped = middlewareRunner;
2353
+ const createExecutionInput = /* @__PURE__ */ __name((input, nextFunc) => ({
2354
+ task: {
2355
+ definition: task2,
2356
+ input
2357
+ },
2358
+ next: nextFunc
2359
+ }), "createExecutionInput");
2360
+ let currentNext = runner;
2195
2361
  for (let i = reversedInterceptors.length - 1; i >= 0; i--) {
2196
2362
  const interceptor = reversedInterceptors[i];
2197
- const nextFunction = wrapped;
2198
- wrapped = /* @__PURE__ */ __name(async (config) => {
2199
- const executionInput = {
2200
- resource: {
2201
- definition: null,
2202
- // Will be filled by middleware.run
2203
- config
2204
- },
2205
- next: nextFunction
2206
- };
2207
- const wrappedNext = /* @__PURE__ */ __name((input) => {
2208
- return nextFunction(input.resource.config);
2363
+ const nextFunction = currentNext;
2364
+ currentNext = /* @__PURE__ */ __name(async (input) => {
2365
+ const executionInput = createExecutionInput(input, nextFunction);
2366
+ const wrappedNext = /* @__PURE__ */ __name((i2) => {
2367
+ return nextFunction(i2.task.input);
2209
2368
  }, "wrappedNext");
2210
2369
  return interceptor(wrappedNext, executionInput);
2211
- }, "wrapped");
2370
+ }, "currentNext");
2212
2371
  }
2213
- return wrapped;
2372
+ return currentNext;
2214
2373
  }
2215
2374
  /**
2216
- * Compose a runner for a task with its local interceptors and applicable middlewares.
2217
- * Returns a function that accepts the task input and resolves to the task output.
2375
+ * Applies task middleware layers (global first, then local)
2218
2376
  */
2219
- composeTaskRunner(task2) {
2220
- const storeTask = this.store.tasks.get(task2.id);
2221
- const tDef = storeTask.task;
2222
- let next = /* @__PURE__ */ __name(async (input) => {
2223
- let rawInput = input;
2224
- const isLocallyTunneled = task2[symbolTunneledTask] === "client" || tDef[symbolTunneledTask] === "client";
2225
- const runnerTask = isLocallyTunneled ? tDef : task2;
2226
- if (runnerTask.inputSchema) {
2227
- try {
2228
- rawInput = runnerTask.inputSchema.parse(rawInput);
2229
- } catch (error2) {
2230
- validationError.throw({
2231
- subject: "Task input",
2232
- id: runnerTask.id,
2233
- originalError: error2 instanceof Error ? error2 : new Error(String(error2))
2234
- });
2235
- }
2236
- }
2237
- const deps = storeTask.computedDependencies;
2238
- const rawResult = await runnerTask.run.call(null, rawInput, deps);
2239
- if (runnerTask.resultSchema) {
2240
- try {
2241
- return runnerTask.resultSchema.parse(rawResult);
2242
- } catch (error2) {
2243
- validationError.throw({
2244
- subject: "Task result",
2245
- id: runnerTask.id,
2246
- originalError: error2
2247
- });
2248
- }
2249
- }
2250
- return rawResult;
2251
- }, "next");
2252
- if (storeTask.interceptors && storeTask.interceptors.length > 0) {
2253
- for (let i = storeTask.interceptors.length - 1; i >= 0; i--) {
2254
- const interceptor = storeTask.interceptors[i];
2255
- const nextFunction = next;
2256
- next = /* @__PURE__ */ __name(async (input) => interceptor(nextFunction, input), "next");
2257
- }
2258
- }
2259
- if (this.taskMiddlewareInterceptors.length > 0) {
2260
- const reversedInterceptors = [
2261
- ...this.taskMiddlewareInterceptors
2262
- ].reverse();
2263
- const createExecutionInput = /* @__PURE__ */ __name((input, nextFunc) => ({
2264
- task: {
2265
- definition: task2,
2266
- input
2267
- },
2268
- next: nextFunc
2269
- }), "createExecutionInput");
2270
- let currentNext = next;
2271
- for (let i = reversedInterceptors.length - 1; i >= 0; i--) {
2272
- const interceptor = reversedInterceptors[i];
2273
- const nextFunction = currentNext;
2274
- currentNext = /* @__PURE__ */ __name(async (input) => {
2275
- const executionInput = createExecutionInput(input, nextFunction);
2276
- const wrappedNext = /* @__PURE__ */ __name((i2) => {
2277
- return nextFunction(i2.task.input);
2278
- }, "wrappedNext");
2279
- return interceptor(wrappedNext, executionInput);
2280
- }, "currentNext");
2281
- }
2282
- next = currentNext;
2283
- }
2284
- let createdMiddlewares = this.getApplicableTaskMiddlewares(task2);
2285
- const isLocallyTunneledPolicy = task2[symbolTunneledTask] === "client" || tDef[symbolTunneledTask] === "client";
2286
- if (isLocallyTunneledPolicy && globalTags.tunnelPolicy.exists(tDef)) {
2287
- const cfg = globalTags.tunnelPolicy.extract(task2);
2288
- const allowList = cfg?.client || void 0;
2289
- if (Array.isArray(allowList)) {
2290
- const toId = /* @__PURE__ */ __name((x) => typeof x === "string" ? x : x?.id, "toId");
2291
- const allowed = new Set(allowList.map(toId).filter(Boolean));
2292
- createdMiddlewares = createdMiddlewares.filter(
2293
- (m) => allowed.has(m.id)
2294
- );
2295
- }
2296
- }
2297
- if (createdMiddlewares.length === 0) {
2298
- return next;
2299
- }
2300
- for (let i = createdMiddlewares.length - 1; i >= 0; i--) {
2301
- const middleware = createdMiddlewares[i];
2377
+ applyMiddlewares(runner, task2, storeTask) {
2378
+ storeTask.task;
2379
+ let middlewares = this.middlewareResolver.getApplicableTaskMiddlewares(task2);
2380
+ middlewares = this.middlewareResolver.applyTunnelPolicyFilter(task2, middlewares);
2381
+ if (middlewares.length === 0) {
2382
+ return runner;
2383
+ }
2384
+ let next = runner;
2385
+ for (let i = middlewares.length - 1; i >= 0; i--) {
2386
+ const middleware = middlewares[i];
2302
2387
  const storeMiddleware = this.store.taskMiddlewares.get(middleware.id);
2303
2388
  const nextFunction = next;
2304
2389
  const baseMiddlewareRunner = /* @__PURE__ */ __name(async (input) => {
@@ -2314,51 +2399,96 @@ var MiddlewareManager = class {
2314
2399
  middleware.config
2315
2400
  );
2316
2401
  }, "baseMiddlewareRunner");
2317
- const middlewareInterceptors = this.perMiddlewareInterceptors.get(middleware.id) || [];
2318
- const wrappedMiddleware = this.wrapMiddlewareWithInterceptors(
2319
- middleware,
2402
+ const middlewareInterceptors = this.interceptorRegistry.getTaskMiddlewareInterceptors(middleware.id);
2403
+ next = this.wrapWithInterceptors(
2320
2404
  baseMiddlewareRunner,
2321
2405
  middlewareInterceptors
2322
2406
  );
2323
- next = wrappedMiddleware;
2324
2407
  }
2325
2408
  return next;
2326
2409
  }
2327
2410
  /**
2328
- * Run a resource init wrapped with its applicable middlewares.
2411
+ * Wraps a middleware runner with its specific interceptors in onion style
2329
2412
  */
2330
- async runResourceInit(resource2, config, dependencies, context) {
2331
- let next = /* @__PURE__ */ __name(async (cfg) => {
2332
- if (!resource2.init) return void 0;
2333
- const rawValue = await resource2.init.call(
2334
- null,
2335
- cfg,
2336
- dependencies,
2337
- context
2338
- );
2339
- if (resource2.resultSchema) {
2340
- try {
2341
- return resource2.resultSchema.parse(rawValue);
2342
- } catch (error2) {
2343
- validationError.throw({
2344
- subject: "Resource result",
2345
- id: resource2.id,
2346
- originalError: error2
2347
- });
2348
- }
2413
+ wrapWithInterceptors(middlewareRunner, interceptors) {
2414
+ if (interceptors.length === 0) {
2415
+ return middlewareRunner;
2416
+ }
2417
+ const reversedInterceptors = [...interceptors].reverse();
2418
+ let wrapped = middlewareRunner;
2419
+ for (let i = reversedInterceptors.length - 1; i >= 0; i--) {
2420
+ const interceptor = reversedInterceptors[i];
2421
+ const nextFunction = wrapped;
2422
+ wrapped = /* @__PURE__ */ __name(async (input) => {
2423
+ const executionInput = {
2424
+ task: {
2425
+ definition: null,
2426
+ input
2427
+ },
2428
+ next: nextFunction
2429
+ };
2430
+ const wrappedNext = /* @__PURE__ */ __name((i2) => {
2431
+ return nextFunction(i2.task.input);
2432
+ }, "wrappedNext");
2433
+ return interceptor(wrappedNext, executionInput);
2434
+ }, "wrapped");
2435
+ }
2436
+ return wrapped;
2437
+ }
2438
+ };
2439
+
2440
+ // src/models/middleware/ResourceMiddlewareComposer.ts
2441
+ var ResourceMiddlewareComposer = class {
2442
+ constructor(store2, interceptorRegistry, middlewareResolver) {
2443
+ this.store = store2;
2444
+ this.interceptorRegistry = interceptorRegistry;
2445
+ this.middlewareResolver = middlewareResolver;
2446
+ }
2447
+ static {
2448
+ __name(this, "ResourceMiddlewareComposer");
2449
+ }
2450
+ /**
2451
+ * Runs resource initialization with all middleware and interceptors applied
2452
+ */
2453
+ async runInit(resource2, config, dependencies, context) {
2454
+ let runner = this.createBaseInitRunner(resource2, dependencies, context);
2455
+ runner = this.applyMiddlewares(runner, resource2);
2456
+ runner = this.applyGlobalInterceptors(runner, resource2);
2457
+ return runner(config);
2458
+ }
2459
+ /**
2460
+ * Creates the base resource init runner with result validation
2461
+ */
2462
+ createBaseInitRunner(resource2, dependencies, context) {
2463
+ return async (config) => {
2464
+ if (!resource2.init) {
2465
+ return void 0;
2349
2466
  }
2350
- return rawValue;
2351
- }, "next");
2352
- const createdMiddlewares = this.getApplicableResourceMiddlewares(resource2);
2353
- for (let i = createdMiddlewares.length - 1; i >= 0; i--) {
2354
- const middleware = createdMiddlewares[i];
2355
- const storeMiddleware = this.store.resourceMiddlewares.get(
2356
- middleware.id
2467
+ const rawValue = await resource2.init(config, dependencies, context);
2468
+ return ValidationHelper.validateResult(
2469
+ rawValue,
2470
+ resource2.resultSchema,
2471
+ resource2.id,
2472
+ "Resource"
2357
2473
  );
2474
+ };
2475
+ }
2476
+ /**
2477
+ * Applies resource middleware layers
2478
+ */
2479
+ applyMiddlewares(runner, resource2) {
2480
+ const middlewares = this.middlewareResolver.getApplicableResourceMiddlewares(resource2);
2481
+ if (middlewares.length === 0) {
2482
+ return runner;
2483
+ }
2484
+ let next = runner;
2485
+ for (let i = middlewares.length - 1; i >= 0; i--) {
2486
+ const middleware = middlewares[i];
2487
+ const storeMiddleware = this.store.resourceMiddlewares.get(middleware.id);
2358
2488
  const nextFunction = next;
2359
2489
  const baseMiddlewareRunner = /* @__PURE__ */ __name(async (cfg) => {
2360
2490
  try {
2361
- const result = await storeMiddleware.middleware.run(
2491
+ return await storeMiddleware.middleware.run(
2362
2492
  {
2363
2493
  resource: {
2364
2494
  definition: resource2,
@@ -2369,7 +2499,6 @@ var MiddlewareManager = class {
2369
2499
  storeMiddleware.computedDependencies,
2370
2500
  middleware.config
2371
2501
  );
2372
- return result;
2373
2502
  } catch (error2) {
2374
2503
  try {
2375
2504
  await this.store.onUnhandledError({
@@ -2382,79 +2511,192 @@ var MiddlewareManager = class {
2382
2511
  throw error2;
2383
2512
  }
2384
2513
  }, "baseMiddlewareRunner");
2385
- const middlewareInterceptors = this.perResourceMiddlewareInterceptors.get(middleware.id) || [];
2386
- const wrappedMiddleware = this.wrapResourceMiddlewareWithInterceptors(
2387
- middleware,
2514
+ const middlewareInterceptors = this.interceptorRegistry.getResourceMiddlewareInterceptors(middleware.id);
2515
+ next = this.wrapWithInterceptors(
2388
2516
  baseMiddlewareRunner,
2389
2517
  middlewareInterceptors
2390
2518
  );
2391
- next = wrappedMiddleware;
2392
- }
2393
- if (this.resourceMiddlewareInterceptors.length > 0) {
2394
- const reversedInterceptors = [
2395
- ...this.resourceMiddlewareInterceptors
2396
- ].reverse();
2397
- const createExecutionInput = /* @__PURE__ */ __name((config2, nextFunc) => ({
2398
- resource: {
2399
- definition: resource2,
2400
- config: config2
2401
- },
2402
- next: nextFunc
2403
- }), "createExecutionInput");
2404
- let currentNext = next;
2405
- for (let i = reversedInterceptors.length - 1; i >= 0; i--) {
2406
- const interceptor = reversedInterceptors[i];
2407
- const nextFunction = currentNext;
2408
- currentNext = /* @__PURE__ */ __name(async (cfg) => {
2409
- const executionInput = createExecutionInput(cfg, nextFunction);
2410
- const wrappedNext = /* @__PURE__ */ __name((input) => {
2411
- return nextFunction(input.resource.config);
2412
- }, "wrappedNext");
2413
- return interceptor(wrappedNext, executionInput);
2414
- }, "currentNext");
2415
- }
2416
- next = currentNext;
2417
2519
  }
2418
- return next(config);
2520
+ return next;
2419
2521
  }
2420
- getApplicableTaskMiddlewares(task2) {
2421
- const existingMiddlewares = task2.middleware;
2422
- const existingMiddlewareIds = existingMiddlewares.map((x) => x.id);
2423
- const globalMiddlewares2 = this.getEverywhereMiddlewareForTasks(task2).filter(
2424
- (x) => !existingMiddlewareIds.includes(x.id)
2522
+ /**
2523
+ * Applies global resource middleware interceptors
2524
+ */
2525
+ applyGlobalInterceptors(runner, resource2) {
2526
+ const interceptors = this.interceptorRegistry.getGlobalResourceInterceptors();
2527
+ if (interceptors.length === 0) {
2528
+ return runner;
2529
+ }
2530
+ const reversedInterceptors = [...interceptors].reverse();
2531
+ const createExecutionInput = /* @__PURE__ */ __name((config, nextFunc) => ({
2532
+ resource: {
2533
+ definition: resource2,
2534
+ config
2535
+ },
2536
+ next: nextFunc
2537
+ }), "createExecutionInput");
2538
+ let currentNext = runner;
2539
+ for (let i = reversedInterceptors.length - 1; i >= 0; i--) {
2540
+ const interceptor = reversedInterceptors[i];
2541
+ const nextFunction = currentNext;
2542
+ currentNext = /* @__PURE__ */ __name(async (cfg) => {
2543
+ const executionInput = createExecutionInput(cfg, nextFunction);
2544
+ const wrappedNext = /* @__PURE__ */ __name((input) => {
2545
+ return nextFunction(input.resource.config);
2546
+ }, "wrappedNext");
2547
+ return interceptor(wrappedNext, executionInput);
2548
+ }, "currentNext");
2549
+ }
2550
+ return currentNext;
2551
+ }
2552
+ /**
2553
+ * Wraps a middleware runner with its specific interceptors in onion style
2554
+ */
2555
+ wrapWithInterceptors(middlewareRunner, interceptors) {
2556
+ if (interceptors.length === 0) {
2557
+ return middlewareRunner;
2558
+ }
2559
+ const reversedInterceptors = [...interceptors].reverse();
2560
+ let wrapped = middlewareRunner;
2561
+ for (let i = reversedInterceptors.length - 1; i >= 0; i--) {
2562
+ const interceptor = reversedInterceptors[i];
2563
+ const nextFunction = wrapped;
2564
+ wrapped = /* @__PURE__ */ __name(async (config) => {
2565
+ const executionInput = {
2566
+ resource: {
2567
+ definition: null,
2568
+ config
2569
+ },
2570
+ next: nextFunction
2571
+ };
2572
+ const wrappedNext = /* @__PURE__ */ __name((input) => {
2573
+ return nextFunction(input.resource.config);
2574
+ }, "wrappedNext");
2575
+ return interceptor(wrappedNext, executionInput);
2576
+ }, "wrapped");
2577
+ }
2578
+ return wrapped;
2579
+ }
2580
+ };
2581
+
2582
+ // src/models/MiddlewareManager.ts
2583
+ var MiddlewareManager = class {
2584
+ constructor(store2, eventManager, logger) {
2585
+ this.store = store2;
2586
+ this.eventManager = eventManager;
2587
+ this.logger = logger;
2588
+ this.interceptorRegistry = new InterceptorRegistry();
2589
+ this.middlewareResolver = new MiddlewareResolver(store2);
2590
+ this.taskComposer = new TaskMiddlewareComposer(
2591
+ store2,
2592
+ this.interceptorRegistry,
2593
+ this.middlewareResolver
2594
+ );
2595
+ this.resourceComposer = new ResourceMiddlewareComposer(
2596
+ store2,
2597
+ this.interceptorRegistry,
2598
+ this.middlewareResolver
2425
2599
  );
2426
- return [...globalMiddlewares2, ...existingMiddlewares];
2427
2600
  }
2428
- getApplicableResourceMiddlewares(resource2) {
2429
- const existingMiddlewares = resource2.middleware;
2430
- const existingMiddlewareIds = existingMiddlewares.map((x) => x.id);
2431
- const globalMiddlewares2 = this.getEverywhereMiddlewareForResources(
2432
- resource2
2433
- ).filter((x) => !existingMiddlewareIds.includes(x.id));
2434
- return [...globalMiddlewares2, ...existingMiddlewares];
2601
+ static {
2602
+ __name(this, "MiddlewareManager");
2435
2603
  }
2436
2604
  /**
2437
- * @param task
2438
- * @returns
2605
+ * @internal
2606
+ */
2607
+ get taskMiddlewareInterceptors() {
2608
+ return this.interceptorRegistry.getGlobalTaskInterceptors();
2609
+ }
2610
+ /**
2611
+ * @internal
2612
+ */
2613
+ get resourceMiddlewareInterceptors() {
2614
+ return this.interceptorRegistry.getGlobalResourceInterceptors();
2615
+ }
2616
+ /**
2617
+ * Gets the current lock status of the MiddlewareManager
2618
+ */
2619
+ get isLocked() {
2620
+ return this.interceptorRegistry.isLocked;
2621
+ }
2622
+ /**
2623
+ * Locks the MiddlewareManager, preventing any further modifications to interceptors
2624
+ */
2625
+ lock() {
2626
+ this.interceptorRegistry.lock();
2627
+ }
2628
+ /**
2629
+ * Adds an interceptor for task or resource middleware execution
2630
+ * Interceptors are executed in the order they are added, with the ability to
2631
+ * modify, log, or prevent middleware execution
2632
+ *
2633
+ * @param kind - The type of middleware to intercept ("task" or "resource")
2634
+ * @param interceptor - The interceptor function to add
2635
+ */
2636
+ intercept(kind, interceptor) {
2637
+ if (kind === "task") {
2638
+ this.interceptorRegistry.addGlobalTaskInterceptor(
2639
+ interceptor
2640
+ );
2641
+ } else {
2642
+ this.interceptorRegistry.addGlobalResourceInterceptor(
2643
+ interceptor
2644
+ );
2645
+ }
2646
+ }
2647
+ /**
2648
+ * Adds an interceptor for a specific middleware instance with better type safety
2649
+ * This method automatically determines the type and provides type-safe access
2650
+ *
2651
+ * @param middleware - The middleware instance to intercept
2652
+ * @param interceptor - The interceptor function with proper typing
2653
+ */
2654
+ interceptMiddleware(middleware, interceptor) {
2655
+ if (isTaskMiddleware(middleware)) {
2656
+ this.interceptorRegistry.addTaskMiddlewareInterceptor(
2657
+ middleware.id,
2658
+ interceptor
2659
+ );
2660
+ } else if (isResourceMiddleware(middleware)) {
2661
+ this.interceptorRegistry.addResourceMiddlewareInterceptor(
2662
+ middleware.id,
2663
+ interceptor
2664
+ );
2665
+ } else {
2666
+ throw new Error("Unknown middleware type");
2667
+ }
2668
+ }
2669
+ /**
2670
+ * Compose a runner for a task with its local interceptors and applicable middlewares.
2671
+ * Returns a function that accepts the task input and resolves to the task output.
2672
+ */
2673
+ composeTaskRunner(task2) {
2674
+ return this.taskComposer.compose(task2);
2675
+ }
2676
+ /**
2677
+ * Run a resource init wrapped with its applicable middlewares.
2678
+ */
2679
+ async runResourceInit(resource2, config, dependencies, context) {
2680
+ return this.resourceComposer.runInit(
2681
+ resource2,
2682
+ config,
2683
+ dependencies,
2684
+ context
2685
+ );
2686
+ }
2687
+ /**
2688
+ * Gets all "everywhere" middlewares that apply to the given task
2689
+ * @deprecated Internal method exposed for testing - may be removed in future versions
2439
2690
  */
2440
2691
  getEverywhereMiddlewareForTasks(task2) {
2441
- return Array.from(this.store.taskMiddlewares.values()).filter((x) => Boolean(x.middleware.everywhere)).filter((x) => {
2442
- if (typeof x.middleware.everywhere === "function") {
2443
- return x.middleware.everywhere(task2);
2444
- }
2445
- return true;
2446
- }).map((x) => x.middleware);
2692
+ return this.middlewareResolver.getEverywhereTaskMiddlewares(task2);
2447
2693
  }
2448
2694
  /**
2449
- * Returns all global middleware for resource, which do not depend on the target resource.
2695
+ * Gets all "everywhere" middlewares that apply to the given resource
2696
+ * @deprecated Internal method exposed for testing - may be removed in future versions
2450
2697
  */
2451
- getEverywhereMiddlewareForResources(target) {
2452
- return Array.from(this.store.resourceMiddlewares.values()).filter((x) => Boolean(x.middleware.everywhere)).filter((x) => {
2453
- if (typeof x.middleware.everywhere === "function") {
2454
- return x.middleware.everywhere(target);
2455
- }
2456
- return true;
2457
- }).map((x) => x.middleware);
2698
+ getEverywhereMiddlewareForResources(resource2) {
2699
+ return this.middlewareResolver.getEverywhereResourceMiddlewares(resource2);
2458
2700
  }
2459
2701
  };
2460
2702
 
@@ -4203,7 +4445,7 @@ var tunnelResourceMiddleware = defineResourceMiddleware({
4203
4445
  t.run = (async (input) => {
4204
4446
  return value.run(t, input);
4205
4447
  });
4206
- t[symbolTunneledTask] = "client";
4448
+ t.isTunneled = true;
4207
4449
  t[symbolTunneledBy] = resourceId;
4208
4450
  }
4209
4451
  if (events.length > 0) {