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