moost 0.5.33 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -6,11 +6,11 @@ var __getOwnPropNames = Object.getOwnPropertyNames;
6
6
  var __getProtoOf = Object.getPrototypeOf;
7
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
8
  var __copyProps = (to, from, except, desc) => {
9
- if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
10
- key = keys[i];
11
- if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
12
- get: ((k) => from[k]).bind(null, key),
13
- enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
9
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key$3; i < n; i++) {
10
+ key$3 = keys[i];
11
+ if (!__hasOwnProp.call(to, key$3) && key$3 !== except) __defProp(to, key$3, {
12
+ get: ((k) => from[k]).bind(null, key$3),
13
+ enumerable: !(desc = __getOwnPropDesc(from, key$3)) || desc.enumerable
14
14
  });
15
15
  }
16
16
  return to;
@@ -21,9 +21,9 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
21
21
  }) : target, mod));
22
22
 
23
23
  //#endregion
24
- const __prostojs_mate = __toESM(require("@prostojs/mate"));
25
24
  const __wooksjs_event_core = __toESM(require("@wooksjs/event-core"));
26
25
  const __prostojs_infact = __toESM(require("@prostojs/infact"));
26
+ const __prostojs_mate = __toESM(require("@prostojs/mate"));
27
27
  const __prostojs_logger = __toESM(require("@prostojs/logger"));
28
28
  const hookable = __toESM(require("hookable"));
29
29
  const wooks = __toESM(require("wooks"));
@@ -40,20 +40,48 @@ function getDefaultLogger(topic) {
40
40
  });
41
41
  return topic && defaultLogger instanceof __prostojs_logger.ProstoLogger ? defaultLogger.createTopic(topic) : defaultLogger;
42
42
  }
43
- function createLogger(opts) {
43
+ /** Creates a new `ProstoLogger` instance with sensible defaults (level 4, colored console). */ function createLogger(opts) {
44
44
  return new __prostojs_logger.ProstoLogger({
45
45
  ...opts,
46
46
  level: opts?.level ?? 4,
47
47
  transports: opts?.transports ?? [loggerConsoleTransport]
48
48
  });
49
49
  }
50
- const loggerConsoleTransport = (0, __prostojs_logger.createConsoleTransort)({ format: __prostojs_logger.coloredConsole });
50
+ /** Default colored console transport used by Moost loggers. */ const loggerConsoleTransport = (0, __prostojs_logger.createConsoleTransort)({ format: __prostojs_logger.coloredConsole });
51
+
52
+ //#endregion
53
+ //#region packages/moost/src/shared-utils.ts
54
+ /**
55
+ * Checks whether a value is a PromiseLike (thenable).
56
+ * Single source of truth — import from here instead of duplicating.
57
+ */ function isThenable(value) {
58
+ return value !== null && value !== void 0 && typeof value.then === "function";
59
+ }
60
+ /**
61
+ * Merges multiple arrays of items with a `priority` field, returning a
62
+ * single sorted-by-priority array. Accepts `undefined` entries for convenience.
63
+ */ function mergeSorted(...lists) {
64
+ let total = 0;
65
+ for (const l of lists) if (l) total += l.length;
66
+ if (total === 0) return [];
67
+ const merged = [];
68
+ for (const l of lists) if (l) for (const item of l) merged.push(item);
69
+ return merged.toSorted((a, b) => a.priority - b.priority);
70
+ }
51
71
 
52
72
  //#endregion
53
73
  //#region packages/moost/src/pipes/run-pipes.ts
54
- async function runPipes(pipes, initialValue, metas, level) {
74
+ function runPipes(pipes, initialValue, metas, level) {
55
75
  let v = initialValue;
56
- for (const pipe of pipes) v = await pipe.handler(v, metas, level);
76
+ for (let i = 0; i < pipes.length; i++) {
77
+ const result = pipes[i].handler(v, metas, level);
78
+ if (isThenable(result)) return (async () => {
79
+ v = await result;
80
+ for (let j = i + 1; j < pipes.length; j++) v = await pipes[j].handler(v, metas, level);
81
+ return v;
82
+ })();
83
+ v = result;
84
+ }
57
85
  return v;
58
86
  }
59
87
 
@@ -70,7 +98,7 @@ const moostMate = new __prostojs_mate.Mate(METADATA_WORKSPACE, {
70
98
  return !!targetMeta?.inherit;
71
99
  }
72
100
  });
73
- function getMoostMate() {
101
+ /** Returns the shared `Mate` instance operating in the `'moost'` metadata workspace. */ function getMoostMate() {
74
102
  return moostMate;
75
103
  }
76
104
 
@@ -83,13 +111,13 @@ let loggingOptions = {
83
111
  warn: true,
84
112
  error: true
85
113
  };
86
- function setInfactLoggingOptions(options) {
114
+ /** Configures which Infact DI events are logged (instance creation, warnings, errors). */ function setInfactLoggingOptions(options) {
87
115
  loggingOptions = {
88
116
  ...loggingOptions,
89
117
  ...options
90
118
  };
91
119
  }
92
- function getMoostInfact() {
120
+ /** Returns the shared Infact DI container used by Moost for dependency injection. */ function getMoostInfact() {
93
121
  return sharedMoostInfact;
94
122
  }
95
123
  const scopeVarsMap = /* @__PURE__ */ new Map();
@@ -122,7 +150,7 @@ const scopeVarsMap = /* @__PURE__ */ new Map();
122
150
  constructorParams: meta?.params || [],
123
151
  provide: meta?.provide,
124
152
  properties: meta?.properties || [],
125
- scopeId: meta?.injectable === "FOR_EVENT" ? (0, __wooksjs_event_core.useEventId)().getId() : void 0
153
+ scopeId: meta?.injectable === "FOR_EVENT" ? useScopeId() : void 0
126
154
  };
127
155
  },
128
156
  resolveParam({ paramMeta, customData, classConstructor, index, scopeId, instantiate }) {
@@ -137,15 +165,15 @@ const scopeVarsMap = /* @__PURE__ */ new Map();
137
165
  instantiate
138
166
  }, "PARAM");
139
167
  },
140
- describeProp(classConstructor, key) {
141
- const meta = getMoostMate().read(classConstructor, key);
168
+ describeProp(classConstructor, key$3) {
169
+ const meta = getMoostMate().read(classConstructor, key$3);
142
170
  return meta;
143
171
  },
144
- resolveProp({ instance, key, initialValue, propMeta, scopeId, classMeta, customData, classConstructor, instantiate }) {
172
+ resolveProp({ instance, key: key$3, initialValue, propMeta, scopeId, classMeta, customData, classConstructor, instantiate }) {
145
173
  if (propMeta && customData?.pipes) return runPipes(customData.pipes, initialValue, {
146
174
  instance,
147
175
  type: classConstructor,
148
- key,
176
+ key: key$3,
149
177
  scopeId,
150
178
  propMeta,
151
179
  targetMeta: propMeta,
@@ -173,7 +201,8 @@ const scopeVarsMap = /* @__PURE__ */ new Map();
173
201
  }
174
202
  let logger;
175
203
  try {
176
- logger = event === "error" ? getDefaultLogger(INFACT_BANNER) : (0, __wooksjs_event_core.useEventLogger)(INFACT_BANNER);
204
+ const ctxLogger = event === "error" ? getDefaultLogger(INFACT_BANNER) : (0, __wooksjs_event_core.useLogger)();
205
+ logger = typeof ctxLogger.topic === "function" ? ctxLogger.topic(INFACT_BANNER) : ctxLogger;
177
206
  } catch (error) {
178
207
  logger = getDefaultLogger(INFACT_BANNER);
179
208
  }
@@ -215,19 +244,26 @@ const scopeVarsMap = /* @__PURE__ */ new Map();
215
244
 
216
245
  //#endregion
217
246
  //#region packages/moost/src/composables/controller.composable.ts
218
- function setControllerContext(controller, method, route) {
219
- const { store } = (0, __wooksjs_event_core.useAsyncEventContext)();
220
- const { set } = store("controller");
221
- set("instance", controller);
222
- set("method", method);
223
- set("route", route);
224
- }
225
- function useControllerContext() {
226
- const { store } = (0, __wooksjs_event_core.useAsyncEventContext)();
227
- const { get } = store("controller");
228
- const getController = () => get("instance");
229
- const getMethod = () => get("method");
230
- const getRoute = () => get("route");
247
+ const controllerInstanceKey = (0, __wooksjs_event_core.key)("controller.instance");
248
+ const controllerMethodKey = (0, __wooksjs_event_core.key)("controller.method");
249
+ const controllerRouteKey = (0, __wooksjs_event_core.key)("controller.route");
250
+ /**
251
+ * Sets the controller context for the current event scope.
252
+ * Called internally by adapters when dispatching events to handlers.
253
+ */ function setControllerContext(controller, method, route, ctx) {
254
+ const _ctx = ctx || (0, __wooksjs_event_core.current)();
255
+ _ctx.set(controllerInstanceKey, controller);
256
+ _ctx.set(controllerMethodKey, method);
257
+ _ctx.set(controllerRouteKey, route);
258
+ }
259
+ /**
260
+ * Provides access to the current controller context within an event handler.
261
+ * Returns utilities for accessing the controller instance, method metadata, and DI.
262
+ */ function useControllerContext(ctx) {
263
+ const _ctx = ctx || (0, __wooksjs_event_core.current)();
264
+ const getController = () => _ctx.get(controllerInstanceKey);
265
+ const getMethod = () => _ctx.get(controllerMethodKey);
266
+ const getRoute = () => _ctx.get(controllerRouteKey);
231
267
  const getControllerMeta = () => getMoostMate().read(getController());
232
268
  const getMethodMeta = (name) => getMoostMate().read(getController(), name || getMethod());
233
269
  function instantiate(c) {
@@ -247,105 +283,204 @@ function useControllerContext() {
247
283
  };
248
284
  }
249
285
 
286
+ //#endregion
287
+ //#region packages/moost/src/composables/interceptor.composable.ts
288
+ var _g, _g1;
289
+ const g = globalThis;
290
+ const overtakeKey = (_g = g).__moost_overtakeKey ?? (_g.__moost_overtakeKey = (0, __wooksjs_event_core.key)("interceptor.overtake"));
291
+ const interceptResultKey = (_g1 = g).__moost_interceptResultKey ?? (_g1.__moost_interceptResultKey = (0, __wooksjs_event_core.key)("interceptor.result"));
292
+ /** Stores the overtake (reply) function in the current event context. */ function setOvertake(fn, ctx) {
293
+ (ctx || (0, __wooksjs_event_core.current)()).set(overtakeKey, fn);
294
+ }
295
+ /** Retrieves the overtake (reply) function from the current event context. */ function useOvertake(ctx) {
296
+ return (ctx || (0, __wooksjs_event_core.current)()).get(overtakeKey);
297
+ }
298
+ /** Stores the interceptor result value in the current event context. */ function setInterceptResult(value, ctx) {
299
+ (ctx || (0, __wooksjs_event_core.current)()).set(interceptResultKey, value);
300
+ }
301
+ /** Retrieves the interceptor result value from the current event context. */ function useInterceptResult(ctx) {
302
+ return (ctx || (0, __wooksjs_event_core.current)()).get(interceptResultKey);
303
+ }
304
+
250
305
  //#endregion
251
306
  //#region packages/moost/src/adapter-utils.ts
252
- const infact = getMoostInfact();
253
- function registerEventScope(scopeId) {
307
+ let _scopeChar = "a";
308
+ let _scopeNum = 0;
309
+ function nextScopeId() {
310
+ if (_scopeNum >= Number.MAX_SAFE_INTEGER) {
311
+ _scopeNum = 0;
312
+ _scopeChar = _scopeChar === "z" ? "a" : String.fromCodePoint((_scopeChar.codePointAt(0) ?? 97) + 1);
313
+ }
314
+ return `__moost_${_scopeChar}_${++_scopeNum}`;
315
+ }
316
+ /** Composable returning the moost scope ID for the current event. Generates on first call, caches for subsequent calls. */ const useScopeId = (0, __wooksjs_event_core.defineWook)(() => nextScopeId());
317
+ /** Registers a DI scope for the given ID and returns an unscope function. */ function registerEventScope(scopeId) {
318
+ const infact = getMoostInfact();
254
319
  infact.registerScope(scopeId);
255
320
  return () => {
256
321
  infact.unregisterScope(scopeId);
257
322
  };
258
323
  }
259
- function defineMoostEventHandler(options) {
324
+ /**
325
+ * Creates the complete event handler lifecycle processor used by adapters.
326
+ * Handles scope registration, controller resolution, interceptors, argument resolution,
327
+ * handler invocation, and cleanup — optimised for sync-first execution.
328
+ */ function defineMoostEventHandler(options) {
260
329
  const ci = (0, __wooksjs_event_core.getContextInjector)();
261
- return async () => {
262
- const scopeId = (0, __wooksjs_event_core.useEventId)().getId();
263
- const logger = (0, __wooksjs_event_core.useEventLogger)(options.loggerTitle);
330
+ const handlerSpanName = `Handler:${options.targetPath}`;
331
+ const handlerAttrs = {
332
+ "moost.handler": options.controllerMethod || "",
333
+ "moost.controller": options.controllerName || ""
334
+ };
335
+ return () => {
336
+ const ctx = (0, __wooksjs_event_core.current)();
337
+ const scopeId = useScopeId(ctx);
338
+ const ctxLogger = (0, __wooksjs_event_core.useLogger)(ctx);
339
+ const logger = typeof ctxLogger.topic === "function" ? ctxLogger.topic(options.loggerTitle) : ctxLogger;
264
340
  const unscope = registerEventScope(scopeId);
265
341
  let response;
266
- const hookOptions = {
267
- scopeId,
268
- logger,
269
- unscope,
270
- method: options.controllerMethod,
271
- getResponse: () => response,
272
- reply: (r) => response = r
273
- };
274
- if (options.hooks?.init) await options.hooks.init(hookOptions);
275
- const instance = await options.getControllerInstance();
276
- if (instance) {
277
- setControllerContext(instance, options.controllerMethod || "", options.targetPath);
278
- ci.hook(options.handlerType, "Controller:registered");
342
+ let hookOptions;
343
+ function getHookOptions() {
344
+ return hookOptions ?? (hookOptions = {
345
+ scopeId,
346
+ logger,
347
+ unscope,
348
+ method: options.controllerMethod,
349
+ getResponse: () => response,
350
+ reply: (r) => response = r
351
+ });
279
352
  }
280
- const interceptorHandler = await options.getIterceptorHandler();
281
- if (interceptorHandler?.count) try {
282
- response = await ci.with("Interceptors:init", () => interceptorHandler.init());
283
- if (response !== void 0) return await endWithResponse();
353
+ let interceptorHandler;
354
+ let raise = false;
355
+ try {
356
+ if (options.hooks?.init) {
357
+ const hookResult = options.hooks.init(getHookOptions());
358
+ if (isThenable(hookResult)) return hookResult.then(afterInit);
359
+ }
360
+ return afterInit();
284
361
  } catch (error) {
285
- options.logErrors && logger.error(error);
286
- response = error;
287
- return endWithResponse(true);
362
+ if (!options.manualUnscope) unscope();
363
+ throw error;
288
364
  }
289
- let args = [];
290
- if (options.resolveArgs) try {
291
- args = await ci.with("Arguments:resolve", () => options.resolveArgs());
292
- } catch (error) {
293
- options.logErrors && logger.error(error);
294
- response = error;
295
- return endWithResponse(true);
365
+ function afterInit() {
366
+ const instanceResult = options.getControllerInstance();
367
+ if (isThenable(instanceResult)) return instanceResult.then((inst) => afterInstance(inst));
368
+ return afterInstance(instanceResult);
296
369
  }
297
- if (interceptorHandler?.countBefore) {
298
- response = await ci.with("Interceptors:before", () => interceptorHandler.fireBefore(response));
299
- if (response !== void 0) return endWithResponse();
370
+ function afterInstance(instance) {
371
+ if (instance) {
372
+ setControllerContext(instance, options.controllerMethod || "", options.targetPath);
373
+ ci?.hook(options.handlerType, "Controller:registered");
374
+ }
375
+ interceptorHandler = options.getIterceptorHandler();
376
+ if (interceptorHandler?.count) try {
377
+ const initResult = ci ? ci.with("Interceptors:before", () => interceptorHandler?.before()) : interceptorHandler?.before();
378
+ if (isThenable(initResult)) return initResult.then((r) => {
379
+ response = r;
380
+ if (response !== void 0) return cleanup();
381
+ return afterInterceptors(instance);
382
+ }, handleError);
383
+ response = initResult;
384
+ if (response !== void 0) return cleanup();
385
+ } catch (error) {
386
+ if (options.logErrors) logger.error(String(error));
387
+ response = error;
388
+ raise = true;
389
+ return cleanup();
390
+ }
391
+ return afterInterceptors(instance);
300
392
  }
301
- const callControllerMethod = () => {
302
- if (options.callControllerMethod) return options.callControllerMethod(args);
303
- else if (instance && options.controllerMethod && typeof instance[options.controllerMethod] === "function") return instance[options.controllerMethod](...args);
304
- };
305
- try {
306
- response = await ci.with(`Handler:${options.targetPath}`, {
307
- "moost.handler": options.controllerMethod || "",
308
- "moost.controller": (0, __prostojs_mate.getConstructor)(instance).name
309
- }, () => callControllerMethod());
310
- } catch (error) {
311
- options.logErrors && logger.error(error);
312
- response = error;
313
- return endWithResponse(true);
393
+ function afterInterceptors(instance) {
394
+ let args = [];
395
+ if (options.resolveArgs) try {
396
+ const argsResult = ci ? ci.with("Arguments:resolve", () => options.resolveArgs?.()) : options.resolveArgs?.();
397
+ if (isThenable(argsResult)) return argsResult.then((a) => {
398
+ args = a;
399
+ return callHandler(instance, args);
400
+ }, handleError);
401
+ args = argsResult;
402
+ } catch (error) {
403
+ if (options.logErrors) logger.error(String(error));
404
+ response = error;
405
+ raise = true;
406
+ return cleanup();
407
+ }
408
+ return callHandler(instance, args);
314
409
  }
315
- async function endWithResponse(raise = false) {
316
- if (interceptorHandler?.countAfter || interceptorHandler?.countOnError) try {
317
- response = await ci.with("Interceptors:after", () => interceptorHandler.fireAfter(response));
410
+ function callHandler(instance, args) {
411
+ const invoke = options.callControllerMethod ? () => options.callControllerMethod?.(args) : instance && options.controllerMethod && typeof instance[options.controllerMethod] === "function" ? () => instance[options.controllerMethod](...args) : void 0;
412
+ try {
413
+ const handlerResult = ci ? ci.with(handlerSpanName, handlerAttrs, () => invoke?.()) : invoke?.();
414
+ if (isThenable(handlerResult)) return handlerResult.then((r) => {
415
+ response = r;
416
+ return cleanup();
417
+ }, (error) => {
418
+ if (options.logErrors) logger.error(error);
419
+ response = error;
420
+ raise = true;
421
+ return cleanup();
422
+ });
423
+ response = handlerResult;
318
424
  } catch (error) {
319
- options.logErrors && logger.error(error);
320
- if (!options.manualUnscope) unscope();
321
- throw error;
425
+ if (options.logErrors) logger.error(error);
426
+ response = error;
427
+ raise = true;
428
+ }
429
+ return cleanup();
430
+ }
431
+ function handleError(error) {
432
+ if (options.logErrors) logger.error(String(error));
433
+ response = error;
434
+ raise = true;
435
+ return cleanup();
436
+ }
437
+ function cleanup() {
438
+ if (interceptorHandler?.countAfter || interceptorHandler?.countOnError) {
439
+ const afterResult = ci ? ci.with("Interceptors:after", () => interceptorHandler?.fireAfter(response)) : interceptorHandler?.fireAfter(response);
440
+ if (isThenable(afterResult)) return afterResult.then((r) => {
441
+ response = r;
442
+ return finalize();
443
+ }, (error) => {
444
+ if (options.logErrors) logger.error(String(error));
445
+ if (!options.manualUnscope) unscope();
446
+ throw error;
447
+ });
448
+ response = afterResult;
322
449
  }
450
+ return finalize();
451
+ }
452
+ function finalize() {
323
453
  if (!options.manualUnscope) unscope();
324
- if (options.hooks?.end) await options.hooks.end(hookOptions);
454
+ if (options.hooks?.end) {
455
+ const endResult = options.hooks.end(getHookOptions());
456
+ if (isThenable(endResult)) return endResult.then(() => {
457
+ if (raise) throw response;
458
+ return response;
459
+ });
460
+ }
325
461
  if (raise) throw response;
326
462
  return response;
327
463
  }
328
- return endWithResponse();
329
464
  };
330
465
  }
331
466
 
332
467
  //#endregion
333
468
  //#region packages/moost/src/binding/utils.ts
334
- function getInstanceOwnMethods(instance) {
469
+ /** Returns the own method names of an instance, including inherited methods from parent classes. */ function getInstanceOwnMethods(instance) {
335
470
  const proto = Object.getPrototypeOf(instance);
336
- return [
471
+ return [...new Set([
337
472
  ...getParentProps((0, __prostojs_mate.getConstructor)(instance)),
338
473
  ...Object.getOwnPropertyNames(proto),
339
474
  ...Object.getOwnPropertyNames(instance)
340
- ].filter((m) => typeof instance[m] === "function");
475
+ ])].filter((m) => typeof instance[m] === "function");
341
476
  }
342
- function getInstanceOwnProps(instance) {
477
+ /** Returns the own non-method property names of an instance, including inherited properties. */ function getInstanceOwnProps(instance) {
343
478
  const proto = Object.getPrototypeOf(instance);
344
- return [
479
+ return [...new Set([
345
480
  ...getParentProps((0, __prostojs_mate.getConstructor)(instance)),
346
481
  ...Object.getOwnPropertyNames(proto),
347
482
  ...Object.getOwnPropertyNames(instance)
348
- ].filter((m) => typeof instance[m] !== "function");
483
+ ])].filter((m) => typeof instance[m] !== "function");
349
484
  }
350
485
  const fnProto = Object.getPrototypeOf(Function);
351
486
  function getParentProps(constructor) {
@@ -355,99 +490,166 @@ function getParentProps(constructor) {
355
490
  }
356
491
 
357
492
  //#endregion
358
- //#region packages/moost/src/class-function/class-function.ts
359
- async function getCallableFn(targetInstance, fn, pipes, logger) {
360
- const mate$1 = getMoostMate();
361
- const meta = mate$1.read(fn);
362
- if (meta?.injectable) {
363
- const infact$1 = getMoostInfact();
364
- const instance = await infact$1.getForInstance(targetInstance, fn, { customData: { pipes: [...pipes || [], ...meta.pipes || []].sort((a, b) => a.priority - b.priority) } });
365
- return (...args) => instance.handler(...args);
366
- }
367
- if (typeof fn === "function") return fn;
368
- const e = /* @__PURE__ */ new Error(`getCallableFn failed for "${(0, __prostojs_mate.getConstructor)(targetInstance).name}" because the passed arg is not a Function nor TClassFunction`);
369
- logger.error(e);
370
- throw e;
493
+ //#region packages/moost/src/resolve-arguments.ts
494
+ /**
495
+ * Builds an argument-resolver function from pre-computed per-parameter pipe lists.
496
+ *
497
+ * Returns `undefined` when there are no parameters to resolve.
498
+ * The returned function runs pipes for each parameter and returns
499
+ * `unknown[]` synchronously when possible, or `Promise<unknown[]>` otherwise.
500
+ */ function resolveArguments(argsPipes, context) {
501
+ if (argsPipes.length === 0) return void 0;
502
+ return () => {
503
+ const args = [];
504
+ let hasAsync = false;
505
+ for (let i = 0; i < argsPipes.length; i++) {
506
+ const { pipes, meta: paramMeta } = argsPipes[i];
507
+ const result = runPipes(pipes, void 0, {
508
+ classMeta: context.classMeta,
509
+ methodMeta: context.methodMeta,
510
+ paramMeta,
511
+ type: context.type,
512
+ key: context.key,
513
+ index: i,
514
+ targetMeta: paramMeta,
515
+ instantiate: (t) => useControllerContext().instantiate(t)
516
+ }, "PARAM");
517
+ if (!hasAsync && isThenable(result)) hasAsync = true;
518
+ args[i] = result;
519
+ }
520
+ return hasAsync ? Promise.all(args) : args;
521
+ };
371
522
  }
372
523
 
373
524
  //#endregion
374
525
  //#region packages/moost/src/interceptor-handler.ts
375
- function _define_property$1(obj, key, value) {
376
- if (key in obj) Object.defineProperty(obj, key, {
526
+ function _define_property$1(obj, key$3, value) {
527
+ if (key$3 in obj) Object.defineProperty(obj, key$3, {
377
528
  value,
378
529
  enumerable: true,
379
530
  configurable: true,
380
531
  writable: true
381
532
  });
382
- else obj[key] = value;
533
+ else obj[key$3] = value;
383
534
  return obj;
384
535
  }
385
- var InterceptorHandler = class {
536
+ /**
537
+ * Manages the before/after/error interceptor lifecycle for a single event.
538
+ * Optimised for the common sync path — only allocates promises when an interceptor goes async.
539
+ */ var InterceptorHandler = class {
540
+ getReplyFn() {
541
+ return this._boundReplyFn ?? (this._boundReplyFn = (reply) => {
542
+ this.response = reply;
543
+ this.responseOverwritten = true;
544
+ });
545
+ }
386
546
  get count() {
387
547
  return this.handlers.length;
388
548
  }
389
- get countBefore() {
390
- return this.before.length;
391
- }
392
549
  get countAfter() {
393
- return this.after.length;
550
+ return this.after?.length ?? 0;
394
551
  }
395
552
  get countOnError() {
396
- return this.onError.length;
553
+ return this.onError?.length ?? 0;
397
554
  }
398
- replyFn(reply) {
399
- this.response = reply;
400
- this.responseOverwritten = true;
555
+ /**
556
+ * Register hooks from a TInterceptorDef.
557
+ * Returns a pending PromiseLike if `before` went async, or undefined.
558
+ */ registerDef(def, entry, ci) {
559
+ if (def.after) (this.after ?? (this.after = [])).unshift({
560
+ name: entry.name,
561
+ fn: def.after
562
+ });
563
+ if (def.error) (this.onError ?? (this.onError = [])).unshift({
564
+ name: entry.name,
565
+ fn: def.error
566
+ });
567
+ if (def.before) {
568
+ const spanName = entry.spanName;
569
+ const result = ci ? ci.with(spanName, { "moost.interceptor.stage": "before" }, () => def.before?.(this.getReplyFn())) : def.before(this.getReplyFn());
570
+ if (isThenable(result)) return result;
571
+ }
572
+ return void 0;
401
573
  }
402
- async init() {
574
+ before() {
403
575
  const ci = (0, __wooksjs_event_core.getContextInjector)();
404
- for (const { handler, name } of this.handlers) {
405
- const response = await ci.with(`Interceptor:${name}`, { "moost.interceptor.stage": "init" }, () => handler((fn) => {
406
- this.before.push({
407
- name,
408
- fn
409
- });
410
- }, (fn) => {
411
- this.after.unshift({
412
- name,
413
- fn
414
- });
415
- }, (fn) => {
416
- this.onError.unshift({
417
- name,
418
- fn
419
- });
420
- }));
421
- if (response !== void 0) return response;
576
+ for (let i = 0; i < this.handlers.length; i++) {
577
+ const entry = this.handlers[i];
578
+ const { handler } = entry;
579
+ if (typeof handler === "function") {
580
+ const factoryResult = handler();
581
+ if (isThenable(factoryResult)) return this._beforeAsyncFactory(ci, factoryResult, i);
582
+ const pending = this.registerDef(factoryResult, entry, ci);
583
+ if (pending) return this._beforeAsyncPending(ci, pending, i);
584
+ if (this.responseOverwritten) return this.response;
585
+ } else {
586
+ const pending = this.registerDef(handler, entry, ci);
587
+ if (pending) return this._beforeAsyncPending(ci, pending, i);
588
+ if (this.responseOverwritten) return this.response;
589
+ }
422
590
  }
423
591
  }
424
- async fireBefore(response) {
425
- const ci = (0, __wooksjs_event_core.getContextInjector)();
592
+ async _beforeAsyncFactory(ci, factoryPromise, startIndex) {
593
+ const def = await factoryPromise;
594
+ const entry = this.handlers[startIndex];
595
+ const pending = this.registerDef(def, entry, ci);
596
+ if (pending) await pending;
597
+ if (this.responseOverwritten) return this.response;
598
+ return this._beforeFrom(ci, startIndex + 1);
599
+ }
600
+ async _beforeAsyncPending(ci, pending, startIndex) {
601
+ await pending;
602
+ if (this.responseOverwritten) return this.response;
603
+ return this._beforeFrom(ci, startIndex + 1);
604
+ }
605
+ async _beforeFrom(ci, startIndex) {
606
+ for (let i = startIndex; i < this.handlers.length; i++) {
607
+ const entry = this.handlers[i];
608
+ const { handler } = entry;
609
+ let def;
610
+ if (typeof handler === "function") def = await handler();
611
+ else def = handler;
612
+ const pending = this.registerDef(def, entry, ci);
613
+ if (pending) await pending;
614
+ if (this.responseOverwritten) return this.response;
615
+ }
616
+ }
617
+ fireAfter(response) {
426
618
  this.response = response;
427
- for (const { name, fn } of this.before) {
428
- await ci.with(`Interceptor:${name}`, { "moost.interceptor.stage": "before" }, () => fn(this.replyFn.bind(this)));
429
- if (this.responseOverwritten) break;
619
+ const isError = response instanceof Error;
620
+ const handlers = isError ? this.onError : this.after;
621
+ if (!handlers) return this.response;
622
+ const ci = (0, __wooksjs_event_core.getContextInjector)();
623
+ const stage = isError ? "onError" : "after";
624
+ for (let i = 0; i < handlers.length; i++) {
625
+ const { name, fn } = handlers[i];
626
+ const result = ci ? ci.with(`Interceptor:${name}`, { "moost.interceptor.stage": stage }, () => fn(response, this.getReplyFn())) : fn(response, this.getReplyFn());
627
+ if (isThenable(result)) return this._fireAfterAsync({
628
+ ci,
629
+ handlers,
630
+ stage,
631
+ response
632
+ }, result, i);
430
633
  }
431
634
  return this.response;
432
635
  }
433
- async fireAfter(response) {
434
- const ci = (0, __wooksjs_event_core.getContextInjector)();
435
- this.response = response;
436
- if (response instanceof Error) for (const { name, fn } of this.onError) await ci.with(`Interceptor:${name}`, { "moost.interceptor.stage": "after" }, () => fn(response, this.replyFn.bind(this)));
437
- else for (const { name, fn } of this.after) await ci.with(`Interceptor:${name}`, { "moost.interceptor.stage": "onError" }, () => fn(response, this.replyFn.bind(this)));
636
+ async _fireAfterAsync(ctx, pending, startIndex) {
637
+ await pending;
638
+ for (let i = startIndex + 1; i < ctx.handlers.length; i++) {
639
+ const { name, fn } = ctx.handlers[i];
640
+ if (ctx.ci) await ctx.ci.with(`Interceptor:${name}`, { "moost.interceptor.stage": ctx.stage }, () => fn(ctx.response, this.getReplyFn()));
641
+ else await fn(ctx.response, this.getReplyFn());
642
+ }
438
643
  return this.response;
439
644
  }
440
645
  constructor(handlers) {
441
646
  _define_property$1(this, "handlers", void 0);
442
- _define_property$1(this, "before", void 0);
443
647
  _define_property$1(this, "after", void 0);
444
648
  _define_property$1(this, "onError", void 0);
445
649
  _define_property$1(this, "response", void 0);
446
650
  _define_property$1(this, "responseOverwritten", void 0);
651
+ _define_property$1(this, "_boundReplyFn", void 0);
447
652
  this.handlers = handlers;
448
- this.before = [];
449
- this.after = [];
450
- this.onError = [];
451
653
  this.responseOverwritten = false;
452
654
  }
453
655
  };
@@ -455,25 +657,129 @@ var InterceptorHandler = class {
455
657
  //#endregion
456
658
  //#region packages/moost/src/utils.ts
457
659
  const mate = getMoostMate();
458
- function getIterceptorHandlerFactory(interceptors, getTargetInstance, pipes, logger) {
660
+ const noInterceptors = () => void 0;
661
+ function findInterceptorMethods(handler) {
662
+ const fakeInstance = Object.create(handler.prototype);
663
+ const methods = getInstanceOwnMethods(fakeInstance);
664
+ const result = {};
665
+ for (const method of methods) {
666
+ const methodMeta = mate.read(fakeInstance, method);
667
+ const hook = methodMeta?.interceptorHook;
668
+ if (hook === "before" || hook === "after" || hook === "error") result[hook] = method;
669
+ }
670
+ return result;
671
+ }
672
+ function buildMethodResolver(opts) {
673
+ const fakeInstance = Object.create(opts.handler.prototype);
674
+ const methodMeta = mate.read(fakeInstance, opts.methodName) || {};
675
+ const argsPipes = [];
676
+ for (const p of methodMeta.params || []) argsPipes.push({
677
+ meta: p,
678
+ pipes: mergeSorted(opts.pipes, p.pipes)
679
+ });
680
+ if (argsPipes.length === 0) return void 0;
681
+ return resolveArguments(argsPipes, {
682
+ classMeta: opts.classMeta,
683
+ methodMeta,
684
+ type: opts.handler,
685
+ key: opts.methodName
686
+ });
687
+ }
688
+ function callWithArgs(instance, methodName, resolveArgs) {
689
+ const ci = (0, __wooksjs_event_core.getContextInjector)();
690
+ const args = ci ? ci.with("Arguments:resolve", resolveArgs) : resolveArgs();
691
+ if (isThenable(args)) return args.then((a) => instance[methodName](...a));
692
+ return instance[methodName](...args);
693
+ }
694
+ function callMethod(instance, methodName, resolveArgs) {
695
+ if (resolveArgs) return callWithArgs(instance, methodName, resolveArgs);
696
+ return instance[methodName]();
697
+ }
698
+ function createClassInterceptorFactory(opts) {
699
+ const infact = getMoostInfact();
700
+ function buildDef(instance) {
701
+ const def = {};
702
+ if (opts.methods.before) {
703
+ const methodName = opts.methods.before;
704
+ const resolveArgs = opts.resolvers[methodName];
705
+ if (resolveArgs) def.before = (reply) => {
706
+ setOvertake(reply);
707
+ return callWithArgs(instance, methodName, resolveArgs);
708
+ };
709
+ else def.before = () => instance[methodName]();
710
+ }
711
+ if (opts.methods.after) {
712
+ const methodName = opts.methods.after;
713
+ const resolveArgs = opts.resolvers[methodName];
714
+ def.after = (response, reply) => {
715
+ setOvertake(reply);
716
+ setInterceptResult(response);
717
+ return callMethod(instance, methodName, resolveArgs);
718
+ };
719
+ }
720
+ if (opts.methods.error) {
721
+ const methodName = opts.methods.error;
722
+ const resolveArgs = opts.resolvers[methodName];
723
+ def.error = (error, reply) => {
724
+ setOvertake(reply);
725
+ setInterceptResult(error);
726
+ return callMethod(instance, methodName, resolveArgs);
727
+ };
728
+ }
729
+ return def;
730
+ }
731
+ function fromTarget(targetInstance) {
732
+ const result = infact.getForInstance(targetInstance, opts.handler, { customData: { pipes: opts.pipes } });
733
+ if (isThenable(result)) return result.then(buildDef);
734
+ return buildDef(result);
735
+ }
459
736
  return () => {
460
- const interceptorHandlers = [];
461
- for (const { handler, name } of interceptors) {
462
- const interceptorMeta = mate.read(handler);
463
- if (interceptorMeta?.injectable) interceptorHandlers.push({
464
- handler: async (...args) => {
465
- const targetInstance = await getTargetInstance();
466
- return (await getCallableFn(targetInstance, handler, pipes, logger))(...args);
467
- },
468
- name
469
- });
470
- else interceptorHandlers.push({
737
+ const result = opts.getTargetInstance();
738
+ if (isThenable(result)) return result.then(fromTarget);
739
+ return fromTarget(result);
740
+ };
741
+ }
742
+ function getIterceptorHandlerFactory(interceptors, getTargetInstance, pipes) {
743
+ if (interceptors.length === 0) return noInterceptors;
744
+ const precomputedHandlers = interceptors.map(({ handler, name }) => {
745
+ const spanName = `Interceptor:${name}`;
746
+ if (typeof handler !== "function") return {
747
+ handler,
748
+ name,
749
+ spanName
750
+ };
751
+ const interceptorMeta = mate.read(handler);
752
+ if (!interceptorMeta?.interceptor) throw new Error(`Invalid interceptor "${name}": must be TInterceptorDef or @Interceptor class`);
753
+ const classMeta = interceptorMeta;
754
+ const methods = findInterceptorMethods(handler);
755
+ const mergedPipes = mergeSorted(pipes, classMeta.pipes);
756
+ const resolvers = {};
757
+ for (const hook of [
758
+ "before",
759
+ "after",
760
+ "error"
761
+ ]) {
762
+ const methodName = methods[hook];
763
+ if (methodName) resolvers[methodName] = buildMethodResolver({
471
764
  handler,
472
- name
765
+ methodName,
766
+ pipes: mergedPipes,
767
+ classMeta
473
768
  });
474
769
  }
475
- return Promise.resolve(new InterceptorHandler(interceptorHandlers));
476
- };
770
+ return {
771
+ handler: createClassInterceptorFactory({
772
+ handler,
773
+ methods,
774
+ resolvers,
775
+ getTargetInstance,
776
+ pipes: mergedPipes
777
+ }),
778
+ name,
779
+ spanName
780
+ };
781
+ });
782
+ return () => new InterceptorHandler(precomputedHandlers);
477
783
  }
478
784
 
479
785
  //#endregion
@@ -500,32 +806,20 @@ async function bindControllerMethods(options) {
500
806
  for (const method of methods) {
501
807
  const methodMeta = getMoostMate().read(fakeInstance, method) || {};
502
808
  if (!methodMeta.handlers?.length) continue;
503
- const pipes = [...opts.pipes || [], ...methodMeta.pipes || []].sort((a, b) => a.priority - b.priority);
504
- const interceptors = [
505
- ...opts.interceptors || [],
506
- ...meta.interceptors || [],
507
- ...methodMeta.interceptors || []
508
- ].sort((a, b) => a.priority - b.priority);
509
- const getIterceptorHandler = getIterceptorHandlerFactory(interceptors, getInstance, pipes, options.logger);
809
+ const pipes = mergeSorted(opts.pipes, methodMeta.pipes);
810
+ const interceptors = mergeSorted(opts.interceptors, meta.interceptors, methodMeta.interceptors);
811
+ const getIterceptorHandler = getIterceptorHandlerFactory(interceptors, getInstance, pipes);
510
812
  const argsPipes = [];
511
813
  for (const p of methodMeta.params || []) argsPipes.push({
512
814
  meta: p,
513
- pipes: [...pipes, ...p.pipes || []].sort((a, b) => a.priority - b.priority)
815
+ pipes: mergeSorted(pipes, p.pipes)
816
+ });
817
+ const resolveArgs = resolveArguments(argsPipes, {
818
+ classMeta: meta,
819
+ methodMeta,
820
+ type: classConstructor,
821
+ key: method
514
822
  });
515
- const resolveArgs = async () => {
516
- const args = [];
517
- for (const [i, { pipes: pipes$1, meta: paramMeta }] of argsPipes.entries()) args[i] = await runPipes(pipes$1, void 0, {
518
- classMeta: meta,
519
- methodMeta,
520
- paramMeta,
521
- type: classConstructor,
522
- key: method,
523
- index: i,
524
- targetMeta: paramMeta,
525
- instantiate: (t) => useControllerContext().instantiate(t)
526
- }, "PARAM");
527
- return args;
528
- };
529
823
  const wm = /* @__PURE__ */ new WeakMap();
530
824
  controllerOverview.handlers.push(...methodMeta.handlers.map((h) => {
531
825
  const data = {
@@ -547,6 +841,7 @@ async function bindControllerMethods(options) {
547
841
  handlers: methodMeta.handlers,
548
842
  getIterceptorHandler,
549
843
  resolveArgs,
844
+ controllerName: classConstructor.name,
550
845
  logHandler: (eventName) => {
551
846
  options.moostInstance.logMappedHandler(eventName, classConstructor, method);
552
847
  },
@@ -564,7 +859,19 @@ async function bindControllerMethods(options) {
564
859
 
565
860
  //#endregion
566
861
  //#region packages/moost/src/decorators/circular.decorator.ts
567
- function Circular(resolver) {
862
+ /**
863
+ * Marks a constructor parameter dependency as circular.
864
+ * The resolver function is called lazily to break the circular reference.
865
+ *
866
+ * @param resolver - Factory that returns the class constructor (e.g. `() => MyService`).
867
+ *
868
+ * @example
869
+ * ```ts
870
+ * class ServiceA {
871
+ * constructor(@Circular(() => ServiceB) private b: ServiceB) {}
872
+ * }
873
+ * ```
874
+ */ function Circular(resolver) {
568
875
  return getMoostMate().decorate("circular", resolver);
569
876
  }
570
877
 
@@ -632,10 +939,10 @@ function Circular(resolver) {
632
939
  * Stores Required metadata
633
940
  */ function Required() {
634
941
  const mate$1 = getMoostMate();
635
- return mate$1.apply(mate$1.decorate("required", true), mate$1.decorateClass((meta, level, key, index) => {
636
- if (typeof index !== "number" && meta && ["string", "symbol"].includes(typeof key)) {
942
+ return mate$1.apply(mate$1.decorate("required", true), mate$1.decorateClass((meta, level, key$3, index) => {
943
+ if (typeof index !== "number" && meta && ["string", "symbol"].includes(typeof key$3)) {
637
944
  meta.requiredProps = meta.requiredProps || [];
638
- meta.requiredProps.push(key);
945
+ meta.requiredProps.push(key$3);
639
946
  }
640
947
  return meta;
641
948
  }));
@@ -702,15 +1009,24 @@ var TInterceptorPriority = /* @__PURE__ */ function(TInterceptorPriority$1) {
702
1009
  /**
703
1010
  * ## Intercept
704
1011
  * ### @Decorator
705
- * Set interceptor
706
- * @param handler interceptor fn (use defineInterceptorFn)
707
- * @param priority interceptor priority
708
- * @returns
1012
+ * Attach an interceptor to a class or method.
1013
+ * @param handler @Interceptor class constructor or TInterceptorDef object
1014
+ * @param priority interceptor priority (overrides handler's own priority)
1015
+ * @param name — interceptor name for tracing
709
1016
  */ function Intercept(handler, priority, name) {
710
- return getMoostMate().decorate("interceptors", {
1017
+ const mate$1 = getMoostMate();
1018
+ if (typeof handler === "function") {
1019
+ const interceptorMeta = mate$1.read(handler);
1020
+ return mate$1.decorate("interceptors", {
1021
+ handler,
1022
+ priority: priority ?? interceptorMeta?.interceptor?.priority ?? 4,
1023
+ name: name || handler.name || "<anonymous>"
1024
+ }, true);
1025
+ }
1026
+ return mate$1.decorate("interceptors", {
711
1027
  handler,
712
- priority: priority || handler.priority || 4,
713
- name: name || handler._name || handler.name
1028
+ priority: priority ?? handler.priority ?? 4,
1029
+ name: name || handler._name || "<anonymous>"
714
1030
  }, true);
715
1031
  }
716
1032
 
@@ -723,14 +1039,14 @@ var TInterceptorPriority = /* @__PURE__ */ function(TInterceptorPriority$1) {
723
1039
  * @param label - field label
724
1040
  * @paramType unknown
725
1041
  */ function Resolve(resolver, label) {
726
- return (target, key, index) => {
1042
+ return (target, key$3, index) => {
727
1043
  const i = typeof index === "number" ? index : void 0;
728
1044
  getMoostMate().decorate("resolver", (metas, level) => {
729
1045
  let newLabel = label;
730
1046
  if (!newLabel && level === "PROP" && typeof metas.key === "string") newLabel = metas.key;
731
- fillLabel(target, key || "", i, newLabel);
1047
+ fillLabel(target, key$3 || "", i, newLabel);
732
1048
  return resolver(metas, level);
733
- })(target, key, i);
1049
+ })(target, key$3, i);
734
1050
  };
735
1051
  }
736
1052
  /**
@@ -766,23 +1082,90 @@ var TInterceptorPriority = /* @__PURE__ */ function(TInterceptorPriority$1) {
766
1082
  */ function ConstFactory(factory, label) {
767
1083
  return Resolve(async () => factory(), label);
768
1084
  }
769
- function fillLabel(target, key, index, name) {
1085
+ function fillLabel(target, key$3, index, name) {
770
1086
  if (name) {
771
- const meta = getMoostMate().read(target, key);
1087
+ const meta = getMoostMate().read(target, key$3);
772
1088
  if (typeof index === "number") {
773
- if (!meta?.params?.[index]?.label) Label(name)(target, key, index);
774
- } else if (!meta?.label) Label(name)(target, key);
1089
+ if (!meta?.params?.[index]?.label) Label(name)(target, key$3, index);
1090
+ } else if (!meta?.label) Label(name)(target, key$3);
775
1091
  }
776
1092
  }
777
1093
 
1094
+ //#endregion
1095
+ //#region packages/moost/src/decorators/interceptor.decorator.ts
1096
+ /**
1097
+ * ## @Interceptor
1098
+ * ### Class Decorator
1099
+ * Marks a class as a decorator-based interceptor.
1100
+ * Auto-adds @Injectable() if not already present.
1101
+ *
1102
+ * Use @Before(), @After(), and @OnError() method decorators
1103
+ * to register lifecycle hooks.
1104
+ *
1105
+ * @param priority — interceptor priority (default: INTERCEPTOR)
1106
+ * @param scope — DI scope ('FOR_EVENT' | 'SINGLETON' | true)
1107
+ */ function Interceptor(priority, scope) {
1108
+ const mate$1 = getMoostMate();
1109
+ const decorators = [insureInjectable, mate$1.decorate("interceptor", { priority: priority ?? TInterceptorPriority.INTERCEPTOR })];
1110
+ if (scope) decorators.push(mate$1.decorate("injectable", scope));
1111
+ return mate$1.apply(...decorators);
1112
+ }
1113
+ /**
1114
+ * ## @Before
1115
+ * ### Method Decorator
1116
+ * Marks a method as a before-phase interceptor hook.
1117
+ * Runs before argument resolution and handler execution.
1118
+ * Use @Overtake() param to get the reply fn for short-circuiting.
1119
+ */ function Before() {
1120
+ return getMoostMate().decorate("interceptorHook", "before");
1121
+ }
1122
+ /**
1123
+ * ## @After
1124
+ * ### Method Decorator
1125
+ * Marks a method as an after-phase interceptor hook.
1126
+ * Runs after successful handler execution.
1127
+ * Use @Response() param for the handler result, @Overtake() for the reply fn.
1128
+ */ function After() {
1129
+ return getMoostMate().decorate("interceptorHook", "after");
1130
+ }
1131
+ /**
1132
+ * ## @OnError
1133
+ * ### Method Decorator
1134
+ * Marks a method as an error-phase interceptor hook.
1135
+ * Runs when the handler throws or returns an Error.
1136
+ * Use @Response() param for the error, @Overtake() for the reply fn.
1137
+ */ function OnError() {
1138
+ return getMoostMate().decorate("interceptorHook", "error");
1139
+ }
1140
+ /**
1141
+ * ## @Overtake
1142
+ * ### Parameter Decorator
1143
+ * Injects the reply function into an interceptor method parameter.
1144
+ * Call the reply fn to short-circuit the handler or replace the response.
1145
+ */ function Overtake() {
1146
+ return Resolve(() => useOvertake(), "overtake");
1147
+ }
1148
+ /**
1149
+ * ## @Response
1150
+ * ### Parameter Decorator
1151
+ * Injects the handler result into an interceptor method parameter.
1152
+ * In @After methods, this is the successful response.
1153
+ * In @OnError methods, this is the Error that was thrown.
1154
+ */ function Response() {
1155
+ return Resolve(() => useInterceptResult(), "response");
1156
+ }
1157
+
778
1158
  //#endregion
779
1159
  //#region packages/moost/src/decorators/logger.decorator.ts
780
1160
  /**
781
1161
  * Resolves event logger from event context
782
1162
  * @param topic
783
- * @returns Resolver to '@wooksjs/event-core' (EventLogger)
1163
+ * @returns Resolver to '@wooksjs/event-core' (Logger)
784
1164
  */ function InjectEventLogger(topic) {
785
- return Resolve(() => (0, __wooksjs_event_core.useEventLogger)(topic));
1165
+ return Resolve(() => {
1166
+ const l = (0, __wooksjs_event_core.useLogger)();
1167
+ return topic && typeof l.topic === "function" ? l.topic(topic) : l;
1168
+ });
786
1169
  }
787
1170
  /**
788
1171
  * Resolves app-level logger
@@ -807,7 +1190,7 @@ function fillLabel(target, key, index, name) {
807
1190
 
808
1191
  //#endregion
809
1192
  //#region packages/moost/src/pipes/types.ts
810
- var TPipePriority = /* @__PURE__ */ function(TPipePriority$1) {
1193
+ /** Execution priority for pipes. Lower values run first. */ var TPipePriority = /* @__PURE__ */ function(TPipePriority$1) {
811
1194
  TPipePriority$1[TPipePriority$1["BEFORE_RESOLVE"] = 0] = "BEFORE_RESOLVE";
812
1195
  TPipePriority$1[TPipePriority$1["RESOLVE"] = 1] = "RESOLVE";
813
1196
  TPipePriority$1[TPipePriority$1["AFTER_RESOLVE"] = 2] = "AFTER_RESOLVE";
@@ -895,31 +1278,73 @@ var TPipePriority = /* @__PURE__ */ function(TPipePriority$1) {
895
1278
  //#endregion
896
1279
  //#region packages/moost/src/define.ts
897
1280
  /**
898
- * ### Define Interceptor Function
1281
+ * Define a before-phase interceptor.
899
1282
  *
1283
+ * Runs before argument resolution and handler execution.
1284
+ * Call `reply(value)` to short-circuit the handler and respond early.
1285
+ *
1286
+ * @example
900
1287
  * ```ts
901
- * defineInterceptorFn((before, after, onError) => {
902
- * //init
903
- * before(() => {
904
- * // before handler
905
- * })
906
- * after((response, reply) => {
907
- * // after handler
908
- * })
909
- * onError((error, reply) => {
910
- * // when error occured
911
- * })
912
- * },
913
- * TInterceptorPriority.INTERCEPTOR,
914
- * )
1288
+ * const authGuard = defineBeforeInterceptor((reply) => {
1289
+ * if (!isAuthenticated()) reply(new HttpError(401))
1290
+ * }, TInterceptorPriority.GUARD)
915
1291
  * ```
1292
+ */ function defineBeforeInterceptor(fn, priority = TInterceptorPriority.INTERCEPTOR) {
1293
+ return {
1294
+ before: fn,
1295
+ priority
1296
+ };
1297
+ }
1298
+ /**
1299
+ * Define an after-phase interceptor.
916
1300
  *
917
- * @param fn interceptor function
918
- * @param priority priority of the interceptor where BEFORE_ALL = 0, BEFORE_GUARD = 1, GUARD = 2, AFTER_GUARD = 3, INTERCEPTOR = 4, CATCH_ERROR = 5, AFTER_ALL = 6
919
- * @returns
920
- */ function defineInterceptorFn(fn, priority = TInterceptorPriority.INTERCEPTOR) {
921
- fn.priority = priority;
922
- return fn;
1301
+ * Runs after successful handler execution.
1302
+ * Call `reply(value)` to transform/replace the response.
1303
+ *
1304
+ * @example
1305
+ * ```ts
1306
+ * const setHeader = defineAfterInterceptor(() => {
1307
+ * useResponse().setHeader('x-server', 'my-server')
1308
+ * }, TInterceptorPriority.AFTER_ALL)
1309
+ * ```
1310
+ */ function defineAfterInterceptor(fn, priority = TInterceptorPriority.AFTER_ALL) {
1311
+ return {
1312
+ after: fn,
1313
+ priority
1314
+ };
1315
+ }
1316
+ /**
1317
+ * Define an error-phase interceptor.
1318
+ *
1319
+ * Runs when the handler throws or returns an Error.
1320
+ * Call `reply(value)` to recover from the error with a replacement response.
1321
+ *
1322
+ * @example
1323
+ * ```ts
1324
+ * const errorFormatter = defineErrorInterceptor((error, reply) => {
1325
+ * reply({ message: error.message, status: 500 })
1326
+ * }, TInterceptorPriority.CATCH_ERROR)
1327
+ * ```
1328
+ */ function defineErrorInterceptor(fn, priority = TInterceptorPriority.CATCH_ERROR) {
1329
+ return {
1330
+ error: fn,
1331
+ priority
1332
+ };
1333
+ }
1334
+ /**
1335
+ * Define a full interceptor with multiple lifecycle hooks.
1336
+ *
1337
+ * @example
1338
+ * ```ts
1339
+ * const myInterceptor = defineInterceptor({
1340
+ * before(reply) { ... },
1341
+ * after(response, reply) { ... },
1342
+ * error(error, reply) { ... },
1343
+ * }, TInterceptorPriority.INTERCEPTOR)
1344
+ * ```
1345
+ */ function defineInterceptor(def, priority = TInterceptorPriority.INTERCEPTOR) {
1346
+ def.priority = priority;
1347
+ return def;
923
1348
  }
924
1349
  /**
925
1350
  * ### Define Pipe Function
@@ -933,8 +1358,8 @@ var TPipePriority = /* @__PURE__ */ function(TPipePriority$1) {
933
1358
  * )
934
1359
  * ```
935
1360
  *
936
- * @param fn interceptor function
937
- * @param priority priority of the pipe where BEFORE_RESOLVE = 0, RESOLVE = 1, AFTER_RESOLVE = 2, BEFORE_TRANSFORM = 3, TRANSFORM = 4, AFTER_TRANSFORM = 5, BEFORE_VALIDATE = 6, VALIDATE = 7, AFTER_VALIDATE = 8
1361
+ * @param fn pipe function
1362
+ * @param priority priority of the pipe
938
1363
  * @returns
939
1364
  */ function definePipeFn(fn, priority = TPipePriority.TRANSFORM) {
940
1365
  fn.priority = priority;
@@ -958,14 +1383,14 @@ const sharedPipes = [{
958
1383
 
959
1384
  //#endregion
960
1385
  //#region packages/moost/src/moost.ts
961
- function _define_property(obj, key, value) {
962
- if (key in obj) Object.defineProperty(obj, key, {
1386
+ function _define_property(obj, key$3, value) {
1387
+ if (key$3 in obj) Object.defineProperty(obj, key$3, {
963
1388
  value,
964
1389
  enumerable: true,
965
1390
  configurable: true,
966
1391
  writable: true
967
1392
  });
968
- else obj[key] = value;
1393
+ else obj[key$3] = value;
969
1394
  return obj;
970
1395
  }
971
1396
  /**
@@ -1084,27 +1509,24 @@ function _define_property(obj, key, value) {
1084
1509
  async bindController(controller, provide, replace, globalPrefix, replaceOwnPrefix) {
1085
1510
  const mate$1 = getMoostMate();
1086
1511
  const classMeta = mate$1.read(controller);
1087
- const infact$1 = getMoostInfact();
1512
+ const infact = getMoostInfact();
1088
1513
  const isControllerConsructor = (0, __prostojs_mate.isConstructor)(controller);
1089
- const pipes = [...this.pipes, ...classMeta?.pipes || []].sort((a, b) => a.priority - b.priority);
1514
+ const pipes = mergeSorted(this.pipes, classMeta?.pipes);
1090
1515
  let instance;
1091
1516
  const infactOpts = {
1092
1517
  provide,
1093
1518
  replace,
1094
1519
  customData: { pipes }
1095
1520
  };
1096
- if (isControllerConsructor && (classMeta?.injectable === "SINGLETON" || classMeta?.injectable === true)) await (0, __wooksjs_event_core.createAsyncEventContext)({
1097
- event: { type: "init" },
1098
- options: {}
1099
- })(async () => {
1521
+ if (isControllerConsructor && (classMeta?.injectable === "SINGLETON" || classMeta?.injectable === true)) await (0, __wooksjs_event_core.createEventContext)({ logger: this.logger }, async () => {
1100
1522
  setControllerContext(this, "bindController", "");
1101
- instance = await infact$1.get(controller, infactOpts);
1523
+ instance = await infact.get(controller, infactOpts);
1102
1524
  });
1103
1525
  else if (!isControllerConsructor) {
1104
1526
  instance = controller;
1105
- infact$1.setInstanceRegistries(instance, provide, replace, { pipes });
1527
+ infact.setInstanceRegistries(instance, provide, replace, { pipes });
1106
1528
  }
1107
- const getInstance = instance ? () => Promise.resolve(instance) : async () => await infact$1.get(controller, { ...infactOpts });
1529
+ const getInstance = instance ? () => instance : async () => await infact.get(controller, { ...infactOpts });
1108
1530
  const classConstructor = (0, __prostojs_mate.isConstructor)(controller) ? controller : (0, __prostojs_mate.getConstructor)(controller);
1109
1531
  this.controllersOverview.push(await bindControllerMethods({
1110
1532
  getInstance,
@@ -1160,22 +1582,26 @@ function _define_property(obj, key, value) {
1160
1582
  if (!this.globalInterceptorHandler) {
1161
1583
  const mate$1 = getMoostMate();
1162
1584
  const thisMeta = mate$1.read(this);
1163
- const pipes = [...this.pipes || [], ...thisMeta?.pipes || []].sort((a, b) => a.priority - b.priority);
1164
- const interceptors = [...this.interceptors, ...thisMeta?.interceptors || []].sort((a, b) => a.priority - b.priority);
1165
- this.globalInterceptorHandler = getIterceptorHandlerFactory(interceptors, () => Promise.resolve(this), pipes, this.logger);
1585
+ const pipes = mergeSorted(this.pipes, thisMeta?.pipes);
1586
+ const interceptors = mergeSorted(this.interceptors, thisMeta?.interceptors);
1587
+ this.globalInterceptorHandler = getIterceptorHandlerFactory(interceptors, () => this, pipes);
1166
1588
  }
1167
1589
  return this.globalInterceptorHandler();
1168
1590
  }
1169
1591
  applyGlobalInterceptors(...items) {
1170
- for (const item of items) if (typeof item === "function") this.interceptors.push({
1171
- handler: item,
1172
- priority: typeof item.priority === "number" ? item.priority : TInterceptorPriority.INTERCEPTOR,
1173
- name: item._name || item.name || "<anonymous>"
1174
- });
1592
+ const mate$1 = getMoostMate();
1593
+ for (const item of items) if (typeof item === "function") {
1594
+ const meta = mate$1.read(item);
1595
+ this.interceptors.push({
1596
+ handler: item,
1597
+ priority: meta?.interceptor?.priority ?? TInterceptorPriority.INTERCEPTOR,
1598
+ name: item.name || "<anonymous>"
1599
+ });
1600
+ } else if ("handler" in item) this.interceptors.push(item);
1175
1601
  else this.interceptors.push({
1176
- handler: item.handler,
1177
- priority: item.priority,
1178
- name: item.name || item.handler._name || item.handler.name || "<anonymous>"
1602
+ handler: item,
1603
+ priority: item.priority ?? TInterceptorPriority.INTERCEPTOR,
1604
+ name: item._name || "<anonymous>"
1179
1605
  });
1180
1606
  this.globalInterceptorHandler = void 0;
1181
1607
  return this;
@@ -1225,7 +1651,9 @@ function _define_property(obj, key, value) {
1225
1651
  };
1226
1652
 
1227
1653
  //#endregion
1654
+ exports.After = After;
1228
1655
  exports.ApplyDecorators = ApplyDecorators;
1656
+ exports.Before = Before;
1229
1657
  exports.Circular = Circular;
1230
1658
  exports.Const = Const;
1231
1659
  exports.ConstFactory = ConstFactory;
@@ -1237,12 +1665,6 @@ Object.defineProperty(exports, 'ContextInjector', {
1237
1665
  });
1238
1666
  exports.Controller = Controller;
1239
1667
  exports.Description = Description;
1240
- Object.defineProperty(exports, 'EventLogger', {
1241
- enumerable: true,
1242
- get: function () {
1243
- return __wooksjs_event_core.EventLogger;
1244
- }
1245
- });
1246
1668
  exports.Id = Id;
1247
1669
  exports.ImportController = ImportController;
1248
1670
  exports.Inherit = Inherit;
@@ -1253,11 +1675,14 @@ exports.InjectMoostLogger = InjectMoostLogger;
1253
1675
  exports.InjectScopeVars = InjectScopeVars;
1254
1676
  exports.Injectable = Injectable;
1255
1677
  exports.Intercept = Intercept;
1678
+ exports.Interceptor = Interceptor;
1256
1679
  exports.InterceptorHandler = InterceptorHandler;
1257
1680
  exports.Label = Label;
1258
1681
  exports.LoggerTopic = LoggerTopic;
1259
1682
  exports.Moost = Moost;
1683
+ exports.OnError = OnError;
1260
1684
  exports.Optional = Optional;
1685
+ exports.Overtake = Overtake;
1261
1686
  exports.Param = Param;
1262
1687
  exports.Params = Params;
1263
1688
  exports.Pipe = Pipe;
@@ -1271,15 +1696,28 @@ exports.Provide = Provide;
1271
1696
  exports.Replace = Replace;
1272
1697
  exports.Required = Required;
1273
1698
  exports.Resolve = Resolve;
1699
+ exports.Response = Response;
1274
1700
  exports.TInterceptorPriority = TInterceptorPriority;
1275
1701
  exports.TPipePriority = TPipePriority;
1276
1702
  exports.Value = Value;
1703
+ Object.defineProperty(exports, 'cached', {
1704
+ enumerable: true,
1705
+ get: function () {
1706
+ return __wooksjs_event_core.cached;
1707
+ }
1708
+ });
1277
1709
  Object.defineProperty(exports, 'clearGlobalWooks', {
1278
1710
  enumerable: true,
1279
1711
  get: function () {
1280
1712
  return wooks.clearGlobalWooks;
1281
1713
  }
1282
1714
  });
1715
+ Object.defineProperty(exports, 'createEventContext', {
1716
+ enumerable: true,
1717
+ get: function () {
1718
+ return __wooksjs_event_core.createEventContext;
1719
+ }
1720
+ });
1283
1721
  exports.createLogger = createLogger;
1284
1722
  Object.defineProperty(exports, 'createProvideRegistry', {
1285
1723
  enumerable: true,
@@ -1293,10 +1731,25 @@ Object.defineProperty(exports, 'createReplaceRegistry', {
1293
1731
  return __prostojs_infact.createReplaceRegistry;
1294
1732
  }
1295
1733
  });
1734
+ Object.defineProperty(exports, 'current', {
1735
+ enumerable: true,
1736
+ get: function () {
1737
+ return __wooksjs_event_core.current;
1738
+ }
1739
+ });
1740
+ exports.defineAfterInterceptor = defineAfterInterceptor;
1741
+ exports.defineBeforeInterceptor = defineBeforeInterceptor;
1742
+ exports.defineErrorInterceptor = defineErrorInterceptor;
1296
1743
  exports.defineInfactScope = defineInfactScope;
1297
- exports.defineInterceptorFn = defineInterceptorFn;
1744
+ exports.defineInterceptor = defineInterceptor;
1298
1745
  exports.defineMoostEventHandler = defineMoostEventHandler;
1299
1746
  exports.definePipeFn = definePipeFn;
1747
+ Object.defineProperty(exports, 'eventTypeKey', {
1748
+ enumerable: true,
1749
+ get: function () {
1750
+ return __wooksjs_event_core.eventTypeKey;
1751
+ }
1752
+ });
1300
1753
  Object.defineProperty(exports, 'getConstructor', {
1301
1754
  enumerable: true,
1302
1755
  get: function () {
@@ -1327,7 +1780,15 @@ Object.defineProperty(exports, 'isConstructor', {
1327
1780
  return __prostojs_mate.isConstructor;
1328
1781
  }
1329
1782
  });
1783
+ exports.isThenable = isThenable;
1784
+ Object.defineProperty(exports, 'key', {
1785
+ enumerable: true,
1786
+ get: function () {
1787
+ return __wooksjs_event_core.key;
1788
+ }
1789
+ });
1330
1790
  exports.loggerConsoleTransport = loggerConsoleTransport;
1791
+ exports.mergeSorted = mergeSorted;
1331
1792
  exports.registerEventScope = registerEventScope;
1332
1793
  Object.defineProperty(exports, 'replaceContextInjector', {
1333
1794
  enumerable: true,
@@ -1335,19 +1796,30 @@ Object.defineProperty(exports, 'replaceContextInjector', {
1335
1796
  return __wooksjs_event_core.replaceContextInjector;
1336
1797
  }
1337
1798
  });
1799
+ Object.defineProperty(exports, 'resetContextInjector', {
1800
+ enumerable: true,
1801
+ get: function () {
1802
+ return __wooksjs_event_core.resetContextInjector;
1803
+ }
1804
+ });
1338
1805
  exports.resolvePipe = resolvePipe;
1339
- exports.setControllerContext = setControllerContext;
1340
- exports.setInfactLoggingOptions = setInfactLoggingOptions;
1341
- Object.defineProperty(exports, 'useAsyncEventContext', {
1806
+ Object.defineProperty(exports, 'run', {
1342
1807
  enumerable: true,
1343
1808
  get: function () {
1344
- return __wooksjs_event_core.useAsyncEventContext;
1809
+ return __wooksjs_event_core.run;
1345
1810
  }
1346
1811
  });
1812
+ exports.setControllerContext = setControllerContext;
1813
+ exports.setInfactLoggingOptions = setInfactLoggingOptions;
1814
+ exports.setInterceptResult = setInterceptResult;
1815
+ exports.setOvertake = setOvertake;
1347
1816
  exports.useControllerContext = useControllerContext;
1348
- Object.defineProperty(exports, 'useEventLogger', {
1817
+ exports.useInterceptResult = useInterceptResult;
1818
+ Object.defineProperty(exports, 'useLogger', {
1349
1819
  enumerable: true,
1350
1820
  get: function () {
1351
- return __wooksjs_event_core.useEventLogger;
1821
+ return __wooksjs_event_core.useLogger;
1352
1822
  }
1353
- });
1823
+ });
1824
+ exports.useOvertake = useOvertake;
1825
+ exports.useScopeId = useScopeId;