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/README.md +21 -0
- package/dist/index.cjs +743 -271
- package/dist/index.d.ts +298 -116
- package/dist/index.mjs +680 -254
- package/package.json +39 -33
- package/scripts/setup-skills.js +76 -0
- package/skills/moost/SKILL.md +34 -0
- package/skills/moost/core.md +174 -0
- package/skills/moost/custom-adapters.md +744 -0
- package/skills/moost/decorators.md +185 -0
- package/skills/moost/di.md +161 -0
- package/skills/moost/interceptors.md +199 -0
- package/skills/moost/pipes.md +213 -0
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { ContextInjector, EventLogger, createAsyncEventContext, getContextInjector, getContextInjector as getContextInjector$1, replaceContextInjector, useAsyncEventContext, useAsyncEventContext as useAsyncEventContext$1, useEventId, useEventLogger, useEventLogger as useEventLogger$1, useRouteParams } from "@wooksjs/event-core";
|
|
1
|
+
import { ContextInjector, cached, createEventContext, createEventContext as createEventContext$1, current, current as current$1, defineWook, eventTypeKey, getContextInjector, getContextInjector as getContextInjector$1, key, key as key$1, replaceContextInjector, resetContextInjector, run, useLogger, useLogger as useLogger$1, useRouteParams } from "@wooksjs/event-core";
|
|
3
2
|
import { Infact, createProvideRegistry, createProvideRegistry as createProvideRegistry$1, createReplaceRegistry, createReplaceRegistry as createReplaceRegistry$1 } from "@prostojs/infact";
|
|
3
|
+
import { Mate, getConstructor, getConstructor as getConstructor$1, isConstructor, isConstructor as isConstructor$1 } from "@prostojs/mate";
|
|
4
4
|
import { ProstoLogger, ProstoLogger as ProstoLogger$1, coloredConsole, createConsoleTransort } from "@prostojs/logger";
|
|
5
5
|
import { Hookable } from "hookable";
|
|
6
6
|
import { clearGlobalWooks, getGlobalWooks } from "wooks";
|
|
@@ -17,20 +17,48 @@ function getDefaultLogger(topic) {
|
|
|
17
17
|
});
|
|
18
18
|
return topic && defaultLogger instanceof ProstoLogger$1 ? defaultLogger.createTopic(topic) : defaultLogger;
|
|
19
19
|
}
|
|
20
|
-
function createLogger(opts) {
|
|
20
|
+
/** Creates a new `ProstoLogger` instance with sensible defaults (level 4, colored console). */ function createLogger(opts) {
|
|
21
21
|
return new ProstoLogger$1({
|
|
22
22
|
...opts,
|
|
23
23
|
level: opts?.level ?? 4,
|
|
24
24
|
transports: opts?.transports ?? [loggerConsoleTransport]
|
|
25
25
|
});
|
|
26
26
|
}
|
|
27
|
-
const loggerConsoleTransport = createConsoleTransort({ format: coloredConsole });
|
|
27
|
+
/** Default colored console transport used by Moost loggers. */ const loggerConsoleTransport = createConsoleTransort({ format: coloredConsole });
|
|
28
|
+
|
|
29
|
+
//#endregion
|
|
30
|
+
//#region packages/moost/src/shared-utils.ts
|
|
31
|
+
/**
|
|
32
|
+
* Checks whether a value is a PromiseLike (thenable).
|
|
33
|
+
* Single source of truth — import from here instead of duplicating.
|
|
34
|
+
*/ function isThenable(value) {
|
|
35
|
+
return value !== null && value !== void 0 && typeof value.then === "function";
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Merges multiple arrays of items with a `priority` field, returning a
|
|
39
|
+
* single sorted-by-priority array. Accepts `undefined` entries for convenience.
|
|
40
|
+
*/ function mergeSorted(...lists) {
|
|
41
|
+
let total = 0;
|
|
42
|
+
for (const l of lists) if (l) total += l.length;
|
|
43
|
+
if (total === 0) return [];
|
|
44
|
+
const merged = [];
|
|
45
|
+
for (const l of lists) if (l) for (const item of l) merged.push(item);
|
|
46
|
+
return merged.toSorted((a, b) => a.priority - b.priority);
|
|
47
|
+
}
|
|
28
48
|
|
|
29
49
|
//#endregion
|
|
30
50
|
//#region packages/moost/src/pipes/run-pipes.ts
|
|
31
|
-
|
|
51
|
+
function runPipes(pipes, initialValue, metas, level) {
|
|
32
52
|
let v = initialValue;
|
|
33
|
-
for (
|
|
53
|
+
for (let i = 0; i < pipes.length; i++) {
|
|
54
|
+
const result = pipes[i].handler(v, metas, level);
|
|
55
|
+
if (isThenable(result)) return (async () => {
|
|
56
|
+
v = await result;
|
|
57
|
+
for (let j = i + 1; j < pipes.length; j++) v = await pipes[j].handler(v, metas, level);
|
|
58
|
+
return v;
|
|
59
|
+
})();
|
|
60
|
+
v = result;
|
|
61
|
+
}
|
|
34
62
|
return v;
|
|
35
63
|
}
|
|
36
64
|
|
|
@@ -47,7 +75,7 @@ const moostMate = new Mate(METADATA_WORKSPACE, {
|
|
|
47
75
|
return !!targetMeta?.inherit;
|
|
48
76
|
}
|
|
49
77
|
});
|
|
50
|
-
function getMoostMate() {
|
|
78
|
+
/** Returns the shared `Mate` instance operating in the `'moost'` metadata workspace. */ function getMoostMate() {
|
|
51
79
|
return moostMate;
|
|
52
80
|
}
|
|
53
81
|
|
|
@@ -60,13 +88,13 @@ let loggingOptions = {
|
|
|
60
88
|
warn: true,
|
|
61
89
|
error: true
|
|
62
90
|
};
|
|
63
|
-
function setInfactLoggingOptions(options) {
|
|
91
|
+
/** Configures which Infact DI events are logged (instance creation, warnings, errors). */ function setInfactLoggingOptions(options) {
|
|
64
92
|
loggingOptions = {
|
|
65
93
|
...loggingOptions,
|
|
66
94
|
...options
|
|
67
95
|
};
|
|
68
96
|
}
|
|
69
|
-
function getMoostInfact() {
|
|
97
|
+
/** Returns the shared Infact DI container used by Moost for dependency injection. */ function getMoostInfact() {
|
|
70
98
|
return sharedMoostInfact;
|
|
71
99
|
}
|
|
72
100
|
const scopeVarsMap = /* @__PURE__ */ new Map();
|
|
@@ -99,7 +127,7 @@ const scopeVarsMap = /* @__PURE__ */ new Map();
|
|
|
99
127
|
constructorParams: meta?.params || [],
|
|
100
128
|
provide: meta?.provide,
|
|
101
129
|
properties: meta?.properties || [],
|
|
102
|
-
scopeId: meta?.injectable === "FOR_EVENT" ?
|
|
130
|
+
scopeId: meta?.injectable === "FOR_EVENT" ? useScopeId() : void 0
|
|
103
131
|
};
|
|
104
132
|
},
|
|
105
133
|
resolveParam({ paramMeta, customData, classConstructor, index, scopeId, instantiate }) {
|
|
@@ -114,15 +142,15 @@ const scopeVarsMap = /* @__PURE__ */ new Map();
|
|
|
114
142
|
instantiate
|
|
115
143
|
}, "PARAM");
|
|
116
144
|
},
|
|
117
|
-
describeProp(classConstructor, key) {
|
|
118
|
-
const meta = getMoostMate().read(classConstructor, key);
|
|
145
|
+
describeProp(classConstructor, key$2) {
|
|
146
|
+
const meta = getMoostMate().read(classConstructor, key$2);
|
|
119
147
|
return meta;
|
|
120
148
|
},
|
|
121
|
-
resolveProp({ instance, key, initialValue, propMeta, scopeId, classMeta, customData, classConstructor, instantiate }) {
|
|
149
|
+
resolveProp({ instance, key: key$2, initialValue, propMeta, scopeId, classMeta, customData, classConstructor, instantiate }) {
|
|
122
150
|
if (propMeta && customData?.pipes) return runPipes(customData.pipes, initialValue, {
|
|
123
151
|
instance,
|
|
124
152
|
type: classConstructor,
|
|
125
|
-
key,
|
|
153
|
+
key: key$2,
|
|
126
154
|
scopeId,
|
|
127
155
|
propMeta,
|
|
128
156
|
targetMeta: propMeta,
|
|
@@ -150,7 +178,8 @@ const scopeVarsMap = /* @__PURE__ */ new Map();
|
|
|
150
178
|
}
|
|
151
179
|
let logger;
|
|
152
180
|
try {
|
|
153
|
-
|
|
181
|
+
const ctxLogger = event === "error" ? getDefaultLogger(INFACT_BANNER) : useLogger$1();
|
|
182
|
+
logger = typeof ctxLogger.topic === "function" ? ctxLogger.topic(INFACT_BANNER) : ctxLogger;
|
|
154
183
|
} catch (error) {
|
|
155
184
|
logger = getDefaultLogger(INFACT_BANNER);
|
|
156
185
|
}
|
|
@@ -192,19 +221,26 @@ const scopeVarsMap = /* @__PURE__ */ new Map();
|
|
|
192
221
|
|
|
193
222
|
//#endregion
|
|
194
223
|
//#region packages/moost/src/composables/controller.composable.ts
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
224
|
+
const controllerInstanceKey = key$1("controller.instance");
|
|
225
|
+
const controllerMethodKey = key$1("controller.method");
|
|
226
|
+
const controllerRouteKey = key$1("controller.route");
|
|
227
|
+
/**
|
|
228
|
+
* Sets the controller context for the current event scope.
|
|
229
|
+
* Called internally by adapters when dispatching events to handlers.
|
|
230
|
+
*/ function setControllerContext(controller, method, route, ctx) {
|
|
231
|
+
const _ctx = ctx || current$1();
|
|
232
|
+
_ctx.set(controllerInstanceKey, controller);
|
|
233
|
+
_ctx.set(controllerMethodKey, method);
|
|
234
|
+
_ctx.set(controllerRouteKey, route);
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Provides access to the current controller context within an event handler.
|
|
238
|
+
* Returns utilities for accessing the controller instance, method metadata, and DI.
|
|
239
|
+
*/ function useControllerContext(ctx) {
|
|
240
|
+
const _ctx = ctx || current$1();
|
|
241
|
+
const getController = () => _ctx.get(controllerInstanceKey);
|
|
242
|
+
const getMethod = () => _ctx.get(controllerMethodKey);
|
|
243
|
+
const getRoute = () => _ctx.get(controllerRouteKey);
|
|
208
244
|
const getControllerMeta = () => getMoostMate().read(getController());
|
|
209
245
|
const getMethodMeta = (name) => getMoostMate().read(getController(), name || getMethod());
|
|
210
246
|
function instantiate(c) {
|
|
@@ -224,105 +260,204 @@ function useControllerContext() {
|
|
|
224
260
|
};
|
|
225
261
|
}
|
|
226
262
|
|
|
263
|
+
//#endregion
|
|
264
|
+
//#region packages/moost/src/composables/interceptor.composable.ts
|
|
265
|
+
var _g, _g1;
|
|
266
|
+
const g = globalThis;
|
|
267
|
+
const overtakeKey = (_g = g).__moost_overtakeKey ?? (_g.__moost_overtakeKey = key$1("interceptor.overtake"));
|
|
268
|
+
const interceptResultKey = (_g1 = g).__moost_interceptResultKey ?? (_g1.__moost_interceptResultKey = key$1("interceptor.result"));
|
|
269
|
+
/** Stores the overtake (reply) function in the current event context. */ function setOvertake(fn, ctx) {
|
|
270
|
+
(ctx || current$1()).set(overtakeKey, fn);
|
|
271
|
+
}
|
|
272
|
+
/** Retrieves the overtake (reply) function from the current event context. */ function useOvertake(ctx) {
|
|
273
|
+
return (ctx || current$1()).get(overtakeKey);
|
|
274
|
+
}
|
|
275
|
+
/** Stores the interceptor result value in the current event context. */ function setInterceptResult(value, ctx) {
|
|
276
|
+
(ctx || current$1()).set(interceptResultKey, value);
|
|
277
|
+
}
|
|
278
|
+
/** Retrieves the interceptor result value from the current event context. */ function useInterceptResult(ctx) {
|
|
279
|
+
return (ctx || current$1()).get(interceptResultKey);
|
|
280
|
+
}
|
|
281
|
+
|
|
227
282
|
//#endregion
|
|
228
283
|
//#region packages/moost/src/adapter-utils.ts
|
|
229
|
-
|
|
230
|
-
|
|
284
|
+
let _scopeChar = "a";
|
|
285
|
+
let _scopeNum = 0;
|
|
286
|
+
function nextScopeId() {
|
|
287
|
+
if (_scopeNum >= Number.MAX_SAFE_INTEGER) {
|
|
288
|
+
_scopeNum = 0;
|
|
289
|
+
_scopeChar = _scopeChar === "z" ? "a" : String.fromCodePoint((_scopeChar.codePointAt(0) ?? 97) + 1);
|
|
290
|
+
}
|
|
291
|
+
return `__moost_${_scopeChar}_${++_scopeNum}`;
|
|
292
|
+
}
|
|
293
|
+
/** Composable returning the moost scope ID for the current event. Generates on first call, caches for subsequent calls. */ const useScopeId = defineWook(() => nextScopeId());
|
|
294
|
+
/** Registers a DI scope for the given ID and returns an unscope function. */ function registerEventScope(scopeId) {
|
|
295
|
+
const infact = getMoostInfact();
|
|
231
296
|
infact.registerScope(scopeId);
|
|
232
297
|
return () => {
|
|
233
298
|
infact.unregisterScope(scopeId);
|
|
234
299
|
};
|
|
235
300
|
}
|
|
236
|
-
|
|
301
|
+
/**
|
|
302
|
+
* Creates the complete event handler lifecycle processor used by adapters.
|
|
303
|
+
* Handles scope registration, controller resolution, interceptors, argument resolution,
|
|
304
|
+
* handler invocation, and cleanup — optimised for sync-first execution.
|
|
305
|
+
*/ function defineMoostEventHandler(options) {
|
|
237
306
|
const ci = getContextInjector$1();
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
307
|
+
const handlerSpanName = `Handler:${options.targetPath}`;
|
|
308
|
+
const handlerAttrs = {
|
|
309
|
+
"moost.handler": options.controllerMethod || "",
|
|
310
|
+
"moost.controller": options.controllerName || ""
|
|
311
|
+
};
|
|
312
|
+
return () => {
|
|
313
|
+
const ctx = current$1();
|
|
314
|
+
const scopeId = useScopeId(ctx);
|
|
315
|
+
const ctxLogger = useLogger$1(ctx);
|
|
316
|
+
const logger = typeof ctxLogger.topic === "function" ? ctxLogger.topic(options.loggerTitle) : ctxLogger;
|
|
241
317
|
const unscope = registerEventScope(scopeId);
|
|
242
318
|
let response;
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
if (instance) {
|
|
254
|
-
setControllerContext(instance, options.controllerMethod || "", options.targetPath);
|
|
255
|
-
ci.hook(options.handlerType, "Controller:registered");
|
|
319
|
+
let hookOptions;
|
|
320
|
+
function getHookOptions() {
|
|
321
|
+
return hookOptions ?? (hookOptions = {
|
|
322
|
+
scopeId,
|
|
323
|
+
logger,
|
|
324
|
+
unscope,
|
|
325
|
+
method: options.controllerMethod,
|
|
326
|
+
getResponse: () => response,
|
|
327
|
+
reply: (r) => response = r
|
|
328
|
+
});
|
|
256
329
|
}
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
if (
|
|
330
|
+
let interceptorHandler;
|
|
331
|
+
let raise = false;
|
|
332
|
+
try {
|
|
333
|
+
if (options.hooks?.init) {
|
|
334
|
+
const hookResult = options.hooks.init(getHookOptions());
|
|
335
|
+
if (isThenable(hookResult)) return hookResult.then(afterInit);
|
|
336
|
+
}
|
|
337
|
+
return afterInit();
|
|
261
338
|
} catch (error) {
|
|
262
|
-
options.
|
|
263
|
-
|
|
264
|
-
return endWithResponse(true);
|
|
339
|
+
if (!options.manualUnscope) unscope();
|
|
340
|
+
throw error;
|
|
265
341
|
}
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
options.logErrors && logger.error(error);
|
|
271
|
-
response = error;
|
|
272
|
-
return endWithResponse(true);
|
|
342
|
+
function afterInit() {
|
|
343
|
+
const instanceResult = options.getControllerInstance();
|
|
344
|
+
if (isThenable(instanceResult)) return instanceResult.then((inst) => afterInstance(inst));
|
|
345
|
+
return afterInstance(instanceResult);
|
|
273
346
|
}
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
347
|
+
function afterInstance(instance) {
|
|
348
|
+
if (instance) {
|
|
349
|
+
setControllerContext(instance, options.controllerMethod || "", options.targetPath);
|
|
350
|
+
ci?.hook(options.handlerType, "Controller:registered");
|
|
351
|
+
}
|
|
352
|
+
interceptorHandler = options.getIterceptorHandler();
|
|
353
|
+
if (interceptorHandler?.count) try {
|
|
354
|
+
const initResult = ci ? ci.with("Interceptors:before", () => interceptorHandler?.before()) : interceptorHandler?.before();
|
|
355
|
+
if (isThenable(initResult)) return initResult.then((r) => {
|
|
356
|
+
response = r;
|
|
357
|
+
if (response !== void 0) return cleanup();
|
|
358
|
+
return afterInterceptors(instance);
|
|
359
|
+
}, handleError);
|
|
360
|
+
response = initResult;
|
|
361
|
+
if (response !== void 0) return cleanup();
|
|
362
|
+
} catch (error) {
|
|
363
|
+
if (options.logErrors) logger.error(String(error));
|
|
364
|
+
response = error;
|
|
365
|
+
raise = true;
|
|
366
|
+
return cleanup();
|
|
367
|
+
}
|
|
368
|
+
return afterInterceptors(instance);
|
|
277
369
|
}
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
370
|
+
function afterInterceptors(instance) {
|
|
371
|
+
let args = [];
|
|
372
|
+
if (options.resolveArgs) try {
|
|
373
|
+
const argsResult = ci ? ci.with("Arguments:resolve", () => options.resolveArgs?.()) : options.resolveArgs?.();
|
|
374
|
+
if (isThenable(argsResult)) return argsResult.then((a) => {
|
|
375
|
+
args = a;
|
|
376
|
+
return callHandler(instance, args);
|
|
377
|
+
}, handleError);
|
|
378
|
+
args = argsResult;
|
|
379
|
+
} catch (error) {
|
|
380
|
+
if (options.logErrors) logger.error(String(error));
|
|
381
|
+
response = error;
|
|
382
|
+
raise = true;
|
|
383
|
+
return cleanup();
|
|
384
|
+
}
|
|
385
|
+
return callHandler(instance, args);
|
|
291
386
|
}
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
387
|
+
function callHandler(instance, args) {
|
|
388
|
+
const invoke = options.callControllerMethod ? () => options.callControllerMethod?.(args) : instance && options.controllerMethod && typeof instance[options.controllerMethod] === "function" ? () => instance[options.controllerMethod](...args) : void 0;
|
|
389
|
+
try {
|
|
390
|
+
const handlerResult = ci ? ci.with(handlerSpanName, handlerAttrs, () => invoke?.()) : invoke?.();
|
|
391
|
+
if (isThenable(handlerResult)) return handlerResult.then((r) => {
|
|
392
|
+
response = r;
|
|
393
|
+
return cleanup();
|
|
394
|
+
}, (error) => {
|
|
395
|
+
if (options.logErrors) logger.error(error);
|
|
396
|
+
response = error;
|
|
397
|
+
raise = true;
|
|
398
|
+
return cleanup();
|
|
399
|
+
});
|
|
400
|
+
response = handlerResult;
|
|
295
401
|
} catch (error) {
|
|
296
|
-
options.logErrors
|
|
297
|
-
|
|
298
|
-
|
|
402
|
+
if (options.logErrors) logger.error(error);
|
|
403
|
+
response = error;
|
|
404
|
+
raise = true;
|
|
405
|
+
}
|
|
406
|
+
return cleanup();
|
|
407
|
+
}
|
|
408
|
+
function handleError(error) {
|
|
409
|
+
if (options.logErrors) logger.error(String(error));
|
|
410
|
+
response = error;
|
|
411
|
+
raise = true;
|
|
412
|
+
return cleanup();
|
|
413
|
+
}
|
|
414
|
+
function cleanup() {
|
|
415
|
+
if (interceptorHandler?.countAfter || interceptorHandler?.countOnError) {
|
|
416
|
+
const afterResult = ci ? ci.with("Interceptors:after", () => interceptorHandler?.fireAfter(response)) : interceptorHandler?.fireAfter(response);
|
|
417
|
+
if (isThenable(afterResult)) return afterResult.then((r) => {
|
|
418
|
+
response = r;
|
|
419
|
+
return finalize();
|
|
420
|
+
}, (error) => {
|
|
421
|
+
if (options.logErrors) logger.error(String(error));
|
|
422
|
+
if (!options.manualUnscope) unscope();
|
|
423
|
+
throw error;
|
|
424
|
+
});
|
|
425
|
+
response = afterResult;
|
|
299
426
|
}
|
|
427
|
+
return finalize();
|
|
428
|
+
}
|
|
429
|
+
function finalize() {
|
|
300
430
|
if (!options.manualUnscope) unscope();
|
|
301
|
-
if (options.hooks?.end)
|
|
431
|
+
if (options.hooks?.end) {
|
|
432
|
+
const endResult = options.hooks.end(getHookOptions());
|
|
433
|
+
if (isThenable(endResult)) return endResult.then(() => {
|
|
434
|
+
if (raise) throw response;
|
|
435
|
+
return response;
|
|
436
|
+
});
|
|
437
|
+
}
|
|
302
438
|
if (raise) throw response;
|
|
303
439
|
return response;
|
|
304
440
|
}
|
|
305
|
-
return endWithResponse();
|
|
306
441
|
};
|
|
307
442
|
}
|
|
308
443
|
|
|
309
444
|
//#endregion
|
|
310
445
|
//#region packages/moost/src/binding/utils.ts
|
|
311
|
-
function getInstanceOwnMethods(instance) {
|
|
446
|
+
/** Returns the own method names of an instance, including inherited methods from parent classes. */ function getInstanceOwnMethods(instance) {
|
|
312
447
|
const proto = Object.getPrototypeOf(instance);
|
|
313
|
-
return [
|
|
448
|
+
return [...new Set([
|
|
314
449
|
...getParentProps(getConstructor$1(instance)),
|
|
315
450
|
...Object.getOwnPropertyNames(proto),
|
|
316
451
|
...Object.getOwnPropertyNames(instance)
|
|
317
|
-
].filter((m) => typeof instance[m] === "function");
|
|
452
|
+
])].filter((m) => typeof instance[m] === "function");
|
|
318
453
|
}
|
|
319
|
-
function getInstanceOwnProps(instance) {
|
|
454
|
+
/** Returns the own non-method property names of an instance, including inherited properties. */ function getInstanceOwnProps(instance) {
|
|
320
455
|
const proto = Object.getPrototypeOf(instance);
|
|
321
|
-
return [
|
|
456
|
+
return [...new Set([
|
|
322
457
|
...getParentProps(getConstructor$1(instance)),
|
|
323
458
|
...Object.getOwnPropertyNames(proto),
|
|
324
459
|
...Object.getOwnPropertyNames(instance)
|
|
325
|
-
].filter((m) => typeof instance[m] !== "function");
|
|
460
|
+
])].filter((m) => typeof instance[m] !== "function");
|
|
326
461
|
}
|
|
327
462
|
const fnProto = Object.getPrototypeOf(Function);
|
|
328
463
|
function getParentProps(constructor) {
|
|
@@ -332,99 +467,166 @@ function getParentProps(constructor) {
|
|
|
332
467
|
}
|
|
333
468
|
|
|
334
469
|
//#endregion
|
|
335
|
-
//#region packages/moost/src/
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
470
|
+
//#region packages/moost/src/resolve-arguments.ts
|
|
471
|
+
/**
|
|
472
|
+
* Builds an argument-resolver function from pre-computed per-parameter pipe lists.
|
|
473
|
+
*
|
|
474
|
+
* Returns `undefined` when there are no parameters to resolve.
|
|
475
|
+
* The returned function runs pipes for each parameter and returns
|
|
476
|
+
* `unknown[]` synchronously when possible, or `Promise<unknown[]>` otherwise.
|
|
477
|
+
*/ function resolveArguments(argsPipes, context) {
|
|
478
|
+
if (argsPipes.length === 0) return void 0;
|
|
479
|
+
return () => {
|
|
480
|
+
const args = [];
|
|
481
|
+
let hasAsync = false;
|
|
482
|
+
for (let i = 0; i < argsPipes.length; i++) {
|
|
483
|
+
const { pipes, meta: paramMeta } = argsPipes[i];
|
|
484
|
+
const result = runPipes(pipes, void 0, {
|
|
485
|
+
classMeta: context.classMeta,
|
|
486
|
+
methodMeta: context.methodMeta,
|
|
487
|
+
paramMeta,
|
|
488
|
+
type: context.type,
|
|
489
|
+
key: context.key,
|
|
490
|
+
index: i,
|
|
491
|
+
targetMeta: paramMeta,
|
|
492
|
+
instantiate: (t) => useControllerContext().instantiate(t)
|
|
493
|
+
}, "PARAM");
|
|
494
|
+
if (!hasAsync && isThenable(result)) hasAsync = true;
|
|
495
|
+
args[i] = result;
|
|
496
|
+
}
|
|
497
|
+
return hasAsync ? Promise.all(args) : args;
|
|
498
|
+
};
|
|
348
499
|
}
|
|
349
500
|
|
|
350
501
|
//#endregion
|
|
351
502
|
//#region packages/moost/src/interceptor-handler.ts
|
|
352
|
-
function _define_property$1(obj, key, value) {
|
|
353
|
-
if (key in obj) Object.defineProperty(obj, key, {
|
|
503
|
+
function _define_property$1(obj, key$2, value) {
|
|
504
|
+
if (key$2 in obj) Object.defineProperty(obj, key$2, {
|
|
354
505
|
value,
|
|
355
506
|
enumerable: true,
|
|
356
507
|
configurable: true,
|
|
357
508
|
writable: true
|
|
358
509
|
});
|
|
359
|
-
else obj[key] = value;
|
|
510
|
+
else obj[key$2] = value;
|
|
360
511
|
return obj;
|
|
361
512
|
}
|
|
362
|
-
|
|
513
|
+
/**
|
|
514
|
+
* Manages the before/after/error interceptor lifecycle for a single event.
|
|
515
|
+
* Optimised for the common sync path — only allocates promises when an interceptor goes async.
|
|
516
|
+
*/ var InterceptorHandler = class {
|
|
517
|
+
getReplyFn() {
|
|
518
|
+
return this._boundReplyFn ?? (this._boundReplyFn = (reply) => {
|
|
519
|
+
this.response = reply;
|
|
520
|
+
this.responseOverwritten = true;
|
|
521
|
+
});
|
|
522
|
+
}
|
|
363
523
|
get count() {
|
|
364
524
|
return this.handlers.length;
|
|
365
525
|
}
|
|
366
|
-
get countBefore() {
|
|
367
|
-
return this.before.length;
|
|
368
|
-
}
|
|
369
526
|
get countAfter() {
|
|
370
|
-
return this.after
|
|
527
|
+
return this.after?.length ?? 0;
|
|
371
528
|
}
|
|
372
529
|
get countOnError() {
|
|
373
|
-
return this.onError
|
|
530
|
+
return this.onError?.length ?? 0;
|
|
374
531
|
}
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
532
|
+
/**
|
|
533
|
+
* Register hooks from a TInterceptorDef.
|
|
534
|
+
* Returns a pending PromiseLike if `before` went async, or undefined.
|
|
535
|
+
*/ registerDef(def, entry, ci) {
|
|
536
|
+
if (def.after) (this.after ?? (this.after = [])).unshift({
|
|
537
|
+
name: entry.name,
|
|
538
|
+
fn: def.after
|
|
539
|
+
});
|
|
540
|
+
if (def.error) (this.onError ?? (this.onError = [])).unshift({
|
|
541
|
+
name: entry.name,
|
|
542
|
+
fn: def.error
|
|
543
|
+
});
|
|
544
|
+
if (def.before) {
|
|
545
|
+
const spanName = entry.spanName;
|
|
546
|
+
const result = ci ? ci.with(spanName, { "moost.interceptor.stage": "before" }, () => def.before?.(this.getReplyFn())) : def.before(this.getReplyFn());
|
|
547
|
+
if (isThenable(result)) return result;
|
|
548
|
+
}
|
|
549
|
+
return void 0;
|
|
378
550
|
}
|
|
379
|
-
|
|
551
|
+
before() {
|
|
380
552
|
const ci = getContextInjector$1();
|
|
381
|
-
for (
|
|
382
|
-
const
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
this.
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
this.
|
|
394
|
-
|
|
395
|
-
fn
|
|
396
|
-
});
|
|
397
|
-
}));
|
|
398
|
-
if (response !== void 0) return response;
|
|
553
|
+
for (let i = 0; i < this.handlers.length; i++) {
|
|
554
|
+
const entry = this.handlers[i];
|
|
555
|
+
const { handler } = entry;
|
|
556
|
+
if (typeof handler === "function") {
|
|
557
|
+
const factoryResult = handler();
|
|
558
|
+
if (isThenable(factoryResult)) return this._beforeAsyncFactory(ci, factoryResult, i);
|
|
559
|
+
const pending = this.registerDef(factoryResult, entry, ci);
|
|
560
|
+
if (pending) return this._beforeAsyncPending(ci, pending, i);
|
|
561
|
+
if (this.responseOverwritten) return this.response;
|
|
562
|
+
} else {
|
|
563
|
+
const pending = this.registerDef(handler, entry, ci);
|
|
564
|
+
if (pending) return this._beforeAsyncPending(ci, pending, i);
|
|
565
|
+
if (this.responseOverwritten) return this.response;
|
|
566
|
+
}
|
|
399
567
|
}
|
|
400
568
|
}
|
|
401
|
-
async
|
|
402
|
-
const
|
|
569
|
+
async _beforeAsyncFactory(ci, factoryPromise, startIndex) {
|
|
570
|
+
const def = await factoryPromise;
|
|
571
|
+
const entry = this.handlers[startIndex];
|
|
572
|
+
const pending = this.registerDef(def, entry, ci);
|
|
573
|
+
if (pending) await pending;
|
|
574
|
+
if (this.responseOverwritten) return this.response;
|
|
575
|
+
return this._beforeFrom(ci, startIndex + 1);
|
|
576
|
+
}
|
|
577
|
+
async _beforeAsyncPending(ci, pending, startIndex) {
|
|
578
|
+
await pending;
|
|
579
|
+
if (this.responseOverwritten) return this.response;
|
|
580
|
+
return this._beforeFrom(ci, startIndex + 1);
|
|
581
|
+
}
|
|
582
|
+
async _beforeFrom(ci, startIndex) {
|
|
583
|
+
for (let i = startIndex; i < this.handlers.length; i++) {
|
|
584
|
+
const entry = this.handlers[i];
|
|
585
|
+
const { handler } = entry;
|
|
586
|
+
let def;
|
|
587
|
+
if (typeof handler === "function") def = await handler();
|
|
588
|
+
else def = handler;
|
|
589
|
+
const pending = this.registerDef(def, entry, ci);
|
|
590
|
+
if (pending) await pending;
|
|
591
|
+
if (this.responseOverwritten) return this.response;
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
fireAfter(response) {
|
|
403
595
|
this.response = response;
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
596
|
+
const isError = response instanceof Error;
|
|
597
|
+
const handlers = isError ? this.onError : this.after;
|
|
598
|
+
if (!handlers) return this.response;
|
|
599
|
+
const ci = getContextInjector$1();
|
|
600
|
+
const stage = isError ? "onError" : "after";
|
|
601
|
+
for (let i = 0; i < handlers.length; i++) {
|
|
602
|
+
const { name, fn } = handlers[i];
|
|
603
|
+
const result = ci ? ci.with(`Interceptor:${name}`, { "moost.interceptor.stage": stage }, () => fn(response, this.getReplyFn())) : fn(response, this.getReplyFn());
|
|
604
|
+
if (isThenable(result)) return this._fireAfterAsync({
|
|
605
|
+
ci,
|
|
606
|
+
handlers,
|
|
607
|
+
stage,
|
|
608
|
+
response
|
|
609
|
+
}, result, i);
|
|
407
610
|
}
|
|
408
611
|
return this.response;
|
|
409
612
|
}
|
|
410
|
-
async
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
613
|
+
async _fireAfterAsync(ctx, pending, startIndex) {
|
|
614
|
+
await pending;
|
|
615
|
+
for (let i = startIndex + 1; i < ctx.handlers.length; i++) {
|
|
616
|
+
const { name, fn } = ctx.handlers[i];
|
|
617
|
+
if (ctx.ci) await ctx.ci.with(`Interceptor:${name}`, { "moost.interceptor.stage": ctx.stage }, () => fn(ctx.response, this.getReplyFn()));
|
|
618
|
+
else await fn(ctx.response, this.getReplyFn());
|
|
619
|
+
}
|
|
415
620
|
return this.response;
|
|
416
621
|
}
|
|
417
622
|
constructor(handlers) {
|
|
418
623
|
_define_property$1(this, "handlers", void 0);
|
|
419
|
-
_define_property$1(this, "before", void 0);
|
|
420
624
|
_define_property$1(this, "after", void 0);
|
|
421
625
|
_define_property$1(this, "onError", void 0);
|
|
422
626
|
_define_property$1(this, "response", void 0);
|
|
423
627
|
_define_property$1(this, "responseOverwritten", void 0);
|
|
628
|
+
_define_property$1(this, "_boundReplyFn", void 0);
|
|
424
629
|
this.handlers = handlers;
|
|
425
|
-
this.before = [];
|
|
426
|
-
this.after = [];
|
|
427
|
-
this.onError = [];
|
|
428
630
|
this.responseOverwritten = false;
|
|
429
631
|
}
|
|
430
632
|
};
|
|
@@ -432,25 +634,129 @@ var InterceptorHandler = class {
|
|
|
432
634
|
//#endregion
|
|
433
635
|
//#region packages/moost/src/utils.ts
|
|
434
636
|
const mate = getMoostMate();
|
|
435
|
-
|
|
637
|
+
const noInterceptors = () => void 0;
|
|
638
|
+
function findInterceptorMethods(handler) {
|
|
639
|
+
const fakeInstance = Object.create(handler.prototype);
|
|
640
|
+
const methods = getInstanceOwnMethods(fakeInstance);
|
|
641
|
+
const result = {};
|
|
642
|
+
for (const method of methods) {
|
|
643
|
+
const methodMeta = mate.read(fakeInstance, method);
|
|
644
|
+
const hook = methodMeta?.interceptorHook;
|
|
645
|
+
if (hook === "before" || hook === "after" || hook === "error") result[hook] = method;
|
|
646
|
+
}
|
|
647
|
+
return result;
|
|
648
|
+
}
|
|
649
|
+
function buildMethodResolver(opts) {
|
|
650
|
+
const fakeInstance = Object.create(opts.handler.prototype);
|
|
651
|
+
const methodMeta = mate.read(fakeInstance, opts.methodName) || {};
|
|
652
|
+
const argsPipes = [];
|
|
653
|
+
for (const p of methodMeta.params || []) argsPipes.push({
|
|
654
|
+
meta: p,
|
|
655
|
+
pipes: mergeSorted(opts.pipes, p.pipes)
|
|
656
|
+
});
|
|
657
|
+
if (argsPipes.length === 0) return void 0;
|
|
658
|
+
return resolveArguments(argsPipes, {
|
|
659
|
+
classMeta: opts.classMeta,
|
|
660
|
+
methodMeta,
|
|
661
|
+
type: opts.handler,
|
|
662
|
+
key: opts.methodName
|
|
663
|
+
});
|
|
664
|
+
}
|
|
665
|
+
function callWithArgs(instance, methodName, resolveArgs) {
|
|
666
|
+
const ci = getContextInjector$1();
|
|
667
|
+
const args = ci ? ci.with("Arguments:resolve", resolveArgs) : resolveArgs();
|
|
668
|
+
if (isThenable(args)) return args.then((a) => instance[methodName](...a));
|
|
669
|
+
return instance[methodName](...args);
|
|
670
|
+
}
|
|
671
|
+
function callMethod(instance, methodName, resolveArgs) {
|
|
672
|
+
if (resolveArgs) return callWithArgs(instance, methodName, resolveArgs);
|
|
673
|
+
return instance[methodName]();
|
|
674
|
+
}
|
|
675
|
+
function createClassInterceptorFactory(opts) {
|
|
676
|
+
const infact = getMoostInfact();
|
|
677
|
+
function buildDef(instance) {
|
|
678
|
+
const def = {};
|
|
679
|
+
if (opts.methods.before) {
|
|
680
|
+
const methodName = opts.methods.before;
|
|
681
|
+
const resolveArgs = opts.resolvers[methodName];
|
|
682
|
+
if (resolveArgs) def.before = (reply) => {
|
|
683
|
+
setOvertake(reply);
|
|
684
|
+
return callWithArgs(instance, methodName, resolveArgs);
|
|
685
|
+
};
|
|
686
|
+
else def.before = () => instance[methodName]();
|
|
687
|
+
}
|
|
688
|
+
if (opts.methods.after) {
|
|
689
|
+
const methodName = opts.methods.after;
|
|
690
|
+
const resolveArgs = opts.resolvers[methodName];
|
|
691
|
+
def.after = (response, reply) => {
|
|
692
|
+
setOvertake(reply);
|
|
693
|
+
setInterceptResult(response);
|
|
694
|
+
return callMethod(instance, methodName, resolveArgs);
|
|
695
|
+
};
|
|
696
|
+
}
|
|
697
|
+
if (opts.methods.error) {
|
|
698
|
+
const methodName = opts.methods.error;
|
|
699
|
+
const resolveArgs = opts.resolvers[methodName];
|
|
700
|
+
def.error = (error, reply) => {
|
|
701
|
+
setOvertake(reply);
|
|
702
|
+
setInterceptResult(error);
|
|
703
|
+
return callMethod(instance, methodName, resolveArgs);
|
|
704
|
+
};
|
|
705
|
+
}
|
|
706
|
+
return def;
|
|
707
|
+
}
|
|
708
|
+
function fromTarget(targetInstance) {
|
|
709
|
+
const result = infact.getForInstance(targetInstance, opts.handler, { customData: { pipes: opts.pipes } });
|
|
710
|
+
if (isThenable(result)) return result.then(buildDef);
|
|
711
|
+
return buildDef(result);
|
|
712
|
+
}
|
|
436
713
|
return () => {
|
|
437
|
-
const
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
714
|
+
const result = opts.getTargetInstance();
|
|
715
|
+
if (isThenable(result)) return result.then(fromTarget);
|
|
716
|
+
return fromTarget(result);
|
|
717
|
+
};
|
|
718
|
+
}
|
|
719
|
+
function getIterceptorHandlerFactory(interceptors, getTargetInstance, pipes) {
|
|
720
|
+
if (interceptors.length === 0) return noInterceptors;
|
|
721
|
+
const precomputedHandlers = interceptors.map(({ handler, name }) => {
|
|
722
|
+
const spanName = `Interceptor:${name}`;
|
|
723
|
+
if (typeof handler !== "function") return {
|
|
724
|
+
handler,
|
|
725
|
+
name,
|
|
726
|
+
spanName
|
|
727
|
+
};
|
|
728
|
+
const interceptorMeta = mate.read(handler);
|
|
729
|
+
if (!interceptorMeta?.interceptor) throw new Error(`Invalid interceptor "${name}": must be TInterceptorDef or @Interceptor class`);
|
|
730
|
+
const classMeta = interceptorMeta;
|
|
731
|
+
const methods = findInterceptorMethods(handler);
|
|
732
|
+
const mergedPipes = mergeSorted(pipes, classMeta.pipes);
|
|
733
|
+
const resolvers = {};
|
|
734
|
+
for (const hook of [
|
|
735
|
+
"before",
|
|
736
|
+
"after",
|
|
737
|
+
"error"
|
|
738
|
+
]) {
|
|
739
|
+
const methodName = methods[hook];
|
|
740
|
+
if (methodName) resolvers[methodName] = buildMethodResolver({
|
|
448
741
|
handler,
|
|
449
|
-
|
|
742
|
+
methodName,
|
|
743
|
+
pipes: mergedPipes,
|
|
744
|
+
classMeta
|
|
450
745
|
});
|
|
451
746
|
}
|
|
452
|
-
return
|
|
453
|
-
|
|
747
|
+
return {
|
|
748
|
+
handler: createClassInterceptorFactory({
|
|
749
|
+
handler,
|
|
750
|
+
methods,
|
|
751
|
+
resolvers,
|
|
752
|
+
getTargetInstance,
|
|
753
|
+
pipes: mergedPipes
|
|
754
|
+
}),
|
|
755
|
+
name,
|
|
756
|
+
spanName
|
|
757
|
+
};
|
|
758
|
+
});
|
|
759
|
+
return () => new InterceptorHandler(precomputedHandlers);
|
|
454
760
|
}
|
|
455
761
|
|
|
456
762
|
//#endregion
|
|
@@ -477,32 +783,20 @@ async function bindControllerMethods(options) {
|
|
|
477
783
|
for (const method of methods) {
|
|
478
784
|
const methodMeta = getMoostMate().read(fakeInstance, method) || {};
|
|
479
785
|
if (!methodMeta.handlers?.length) continue;
|
|
480
|
-
const pipes =
|
|
481
|
-
const interceptors =
|
|
482
|
-
|
|
483
|
-
...meta.interceptors || [],
|
|
484
|
-
...methodMeta.interceptors || []
|
|
485
|
-
].sort((a, b) => a.priority - b.priority);
|
|
486
|
-
const getIterceptorHandler = getIterceptorHandlerFactory(interceptors, getInstance, pipes, options.logger);
|
|
786
|
+
const pipes = mergeSorted(opts.pipes, methodMeta.pipes);
|
|
787
|
+
const interceptors = mergeSorted(opts.interceptors, meta.interceptors, methodMeta.interceptors);
|
|
788
|
+
const getIterceptorHandler = getIterceptorHandlerFactory(interceptors, getInstance, pipes);
|
|
487
789
|
const argsPipes = [];
|
|
488
790
|
for (const p of methodMeta.params || []) argsPipes.push({
|
|
489
791
|
meta: p,
|
|
490
|
-
pipes:
|
|
792
|
+
pipes: mergeSorted(pipes, p.pipes)
|
|
793
|
+
});
|
|
794
|
+
const resolveArgs = resolveArguments(argsPipes, {
|
|
795
|
+
classMeta: meta,
|
|
796
|
+
methodMeta,
|
|
797
|
+
type: classConstructor,
|
|
798
|
+
key: method
|
|
491
799
|
});
|
|
492
|
-
const resolveArgs = async () => {
|
|
493
|
-
const args = [];
|
|
494
|
-
for (const [i, { pipes: pipes$1, meta: paramMeta }] of argsPipes.entries()) args[i] = await runPipes(pipes$1, void 0, {
|
|
495
|
-
classMeta: meta,
|
|
496
|
-
methodMeta,
|
|
497
|
-
paramMeta,
|
|
498
|
-
type: classConstructor,
|
|
499
|
-
key: method,
|
|
500
|
-
index: i,
|
|
501
|
-
targetMeta: paramMeta,
|
|
502
|
-
instantiate: (t) => useControllerContext().instantiate(t)
|
|
503
|
-
}, "PARAM");
|
|
504
|
-
return args;
|
|
505
|
-
};
|
|
506
800
|
const wm = /* @__PURE__ */ new WeakMap();
|
|
507
801
|
controllerOverview.handlers.push(...methodMeta.handlers.map((h) => {
|
|
508
802
|
const data = {
|
|
@@ -524,6 +818,7 @@ async function bindControllerMethods(options) {
|
|
|
524
818
|
handlers: methodMeta.handlers,
|
|
525
819
|
getIterceptorHandler,
|
|
526
820
|
resolveArgs,
|
|
821
|
+
controllerName: classConstructor.name,
|
|
527
822
|
logHandler: (eventName) => {
|
|
528
823
|
options.moostInstance.logMappedHandler(eventName, classConstructor, method);
|
|
529
824
|
},
|
|
@@ -541,7 +836,19 @@ async function bindControllerMethods(options) {
|
|
|
541
836
|
|
|
542
837
|
//#endregion
|
|
543
838
|
//#region packages/moost/src/decorators/circular.decorator.ts
|
|
544
|
-
|
|
839
|
+
/**
|
|
840
|
+
* Marks a constructor parameter dependency as circular.
|
|
841
|
+
* The resolver function is called lazily to break the circular reference.
|
|
842
|
+
*
|
|
843
|
+
* @param resolver - Factory that returns the class constructor (e.g. `() => MyService`).
|
|
844
|
+
*
|
|
845
|
+
* @example
|
|
846
|
+
* ```ts
|
|
847
|
+
* class ServiceA {
|
|
848
|
+
* constructor(@Circular(() => ServiceB) private b: ServiceB) {}
|
|
849
|
+
* }
|
|
850
|
+
* ```
|
|
851
|
+
*/ function Circular(resolver) {
|
|
545
852
|
return getMoostMate().decorate("circular", resolver);
|
|
546
853
|
}
|
|
547
854
|
|
|
@@ -609,10 +916,10 @@ function Circular(resolver) {
|
|
|
609
916
|
* Stores Required metadata
|
|
610
917
|
*/ function Required() {
|
|
611
918
|
const mate$1 = getMoostMate();
|
|
612
|
-
return mate$1.apply(mate$1.decorate("required", true), mate$1.decorateClass((meta, level, key, index) => {
|
|
613
|
-
if (typeof index !== "number" && meta && ["string", "symbol"].includes(typeof key)) {
|
|
919
|
+
return mate$1.apply(mate$1.decorate("required", true), mate$1.decorateClass((meta, level, key$2, index) => {
|
|
920
|
+
if (typeof index !== "number" && meta && ["string", "symbol"].includes(typeof key$2)) {
|
|
614
921
|
meta.requiredProps = meta.requiredProps || [];
|
|
615
|
-
meta.requiredProps.push(key);
|
|
922
|
+
meta.requiredProps.push(key$2);
|
|
616
923
|
}
|
|
617
924
|
return meta;
|
|
618
925
|
}));
|
|
@@ -679,15 +986,24 @@ var TInterceptorPriority = /* @__PURE__ */ function(TInterceptorPriority$1) {
|
|
|
679
986
|
/**
|
|
680
987
|
* ## Intercept
|
|
681
988
|
* ### @Decorator
|
|
682
|
-
*
|
|
683
|
-
* @param handler
|
|
684
|
-
* @param priority interceptor priority
|
|
685
|
-
* @
|
|
989
|
+
* Attach an interceptor to a class or method.
|
|
990
|
+
* @param handler — @Interceptor class constructor or TInterceptorDef object
|
|
991
|
+
* @param priority — interceptor priority (overrides handler's own priority)
|
|
992
|
+
* @param name — interceptor name for tracing
|
|
686
993
|
*/ function Intercept(handler, priority, name) {
|
|
687
|
-
|
|
994
|
+
const mate$1 = getMoostMate();
|
|
995
|
+
if (typeof handler === "function") {
|
|
996
|
+
const interceptorMeta = mate$1.read(handler);
|
|
997
|
+
return mate$1.decorate("interceptors", {
|
|
998
|
+
handler,
|
|
999
|
+
priority: priority ?? interceptorMeta?.interceptor?.priority ?? 4,
|
|
1000
|
+
name: name || handler.name || "<anonymous>"
|
|
1001
|
+
}, true);
|
|
1002
|
+
}
|
|
1003
|
+
return mate$1.decorate("interceptors", {
|
|
688
1004
|
handler,
|
|
689
|
-
priority: priority
|
|
690
|
-
name: name || handler._name ||
|
|
1005
|
+
priority: priority ?? handler.priority ?? 4,
|
|
1006
|
+
name: name || handler._name || "<anonymous>"
|
|
691
1007
|
}, true);
|
|
692
1008
|
}
|
|
693
1009
|
|
|
@@ -700,14 +1016,14 @@ var TInterceptorPriority = /* @__PURE__ */ function(TInterceptorPriority$1) {
|
|
|
700
1016
|
* @param label - field label
|
|
701
1017
|
* @paramType unknown
|
|
702
1018
|
*/ function Resolve(resolver, label) {
|
|
703
|
-
return (target, key, index) => {
|
|
1019
|
+
return (target, key$2, index) => {
|
|
704
1020
|
const i = typeof index === "number" ? index : void 0;
|
|
705
1021
|
getMoostMate().decorate("resolver", (metas, level) => {
|
|
706
1022
|
let newLabel = label;
|
|
707
1023
|
if (!newLabel && level === "PROP" && typeof metas.key === "string") newLabel = metas.key;
|
|
708
|
-
fillLabel(target, key || "", i, newLabel);
|
|
1024
|
+
fillLabel(target, key$2 || "", i, newLabel);
|
|
709
1025
|
return resolver(metas, level);
|
|
710
|
-
})(target, key, i);
|
|
1026
|
+
})(target, key$2, i);
|
|
711
1027
|
};
|
|
712
1028
|
}
|
|
713
1029
|
/**
|
|
@@ -743,23 +1059,90 @@ var TInterceptorPriority = /* @__PURE__ */ function(TInterceptorPriority$1) {
|
|
|
743
1059
|
*/ function ConstFactory(factory, label) {
|
|
744
1060
|
return Resolve(async () => factory(), label);
|
|
745
1061
|
}
|
|
746
|
-
function fillLabel(target, key, index, name) {
|
|
1062
|
+
function fillLabel(target, key$2, index, name) {
|
|
747
1063
|
if (name) {
|
|
748
|
-
const meta = getMoostMate().read(target, key);
|
|
1064
|
+
const meta = getMoostMate().read(target, key$2);
|
|
749
1065
|
if (typeof index === "number") {
|
|
750
|
-
if (!meta?.params?.[index]?.label) Label(name)(target, key, index);
|
|
751
|
-
} else if (!meta?.label) Label(name)(target, key);
|
|
1066
|
+
if (!meta?.params?.[index]?.label) Label(name)(target, key$2, index);
|
|
1067
|
+
} else if (!meta?.label) Label(name)(target, key$2);
|
|
752
1068
|
}
|
|
753
1069
|
}
|
|
754
1070
|
|
|
1071
|
+
//#endregion
|
|
1072
|
+
//#region packages/moost/src/decorators/interceptor.decorator.ts
|
|
1073
|
+
/**
|
|
1074
|
+
* ## @Interceptor
|
|
1075
|
+
* ### Class Decorator
|
|
1076
|
+
* Marks a class as a decorator-based interceptor.
|
|
1077
|
+
* Auto-adds @Injectable() if not already present.
|
|
1078
|
+
*
|
|
1079
|
+
* Use @Before(), @After(), and @OnError() method decorators
|
|
1080
|
+
* to register lifecycle hooks.
|
|
1081
|
+
*
|
|
1082
|
+
* @param priority — interceptor priority (default: INTERCEPTOR)
|
|
1083
|
+
* @param scope — DI scope ('FOR_EVENT' | 'SINGLETON' | true)
|
|
1084
|
+
*/ function Interceptor(priority, scope) {
|
|
1085
|
+
const mate$1 = getMoostMate();
|
|
1086
|
+
const decorators = [insureInjectable, mate$1.decorate("interceptor", { priority: priority ?? TInterceptorPriority.INTERCEPTOR })];
|
|
1087
|
+
if (scope) decorators.push(mate$1.decorate("injectable", scope));
|
|
1088
|
+
return mate$1.apply(...decorators);
|
|
1089
|
+
}
|
|
1090
|
+
/**
|
|
1091
|
+
* ## @Before
|
|
1092
|
+
* ### Method Decorator
|
|
1093
|
+
* Marks a method as a before-phase interceptor hook.
|
|
1094
|
+
* Runs before argument resolution and handler execution.
|
|
1095
|
+
* Use @Overtake() param to get the reply fn for short-circuiting.
|
|
1096
|
+
*/ function Before() {
|
|
1097
|
+
return getMoostMate().decorate("interceptorHook", "before");
|
|
1098
|
+
}
|
|
1099
|
+
/**
|
|
1100
|
+
* ## @After
|
|
1101
|
+
* ### Method Decorator
|
|
1102
|
+
* Marks a method as an after-phase interceptor hook.
|
|
1103
|
+
* Runs after successful handler execution.
|
|
1104
|
+
* Use @Response() param for the handler result, @Overtake() for the reply fn.
|
|
1105
|
+
*/ function After() {
|
|
1106
|
+
return getMoostMate().decorate("interceptorHook", "after");
|
|
1107
|
+
}
|
|
1108
|
+
/**
|
|
1109
|
+
* ## @OnError
|
|
1110
|
+
* ### Method Decorator
|
|
1111
|
+
* Marks a method as an error-phase interceptor hook.
|
|
1112
|
+
* Runs when the handler throws or returns an Error.
|
|
1113
|
+
* Use @Response() param for the error, @Overtake() for the reply fn.
|
|
1114
|
+
*/ function OnError() {
|
|
1115
|
+
return getMoostMate().decorate("interceptorHook", "error");
|
|
1116
|
+
}
|
|
1117
|
+
/**
|
|
1118
|
+
* ## @Overtake
|
|
1119
|
+
* ### Parameter Decorator
|
|
1120
|
+
* Injects the reply function into an interceptor method parameter.
|
|
1121
|
+
* Call the reply fn to short-circuit the handler or replace the response.
|
|
1122
|
+
*/ function Overtake() {
|
|
1123
|
+
return Resolve(() => useOvertake(), "overtake");
|
|
1124
|
+
}
|
|
1125
|
+
/**
|
|
1126
|
+
* ## @Response
|
|
1127
|
+
* ### Parameter Decorator
|
|
1128
|
+
* Injects the handler result into an interceptor method parameter.
|
|
1129
|
+
* In @After methods, this is the successful response.
|
|
1130
|
+
* In @OnError methods, this is the Error that was thrown.
|
|
1131
|
+
*/ function Response() {
|
|
1132
|
+
return Resolve(() => useInterceptResult(), "response");
|
|
1133
|
+
}
|
|
1134
|
+
|
|
755
1135
|
//#endregion
|
|
756
1136
|
//#region packages/moost/src/decorators/logger.decorator.ts
|
|
757
1137
|
/**
|
|
758
1138
|
* Resolves event logger from event context
|
|
759
1139
|
* @param topic
|
|
760
|
-
* @returns Resolver to '@wooksjs/event-core' (
|
|
1140
|
+
* @returns Resolver to '@wooksjs/event-core' (Logger)
|
|
761
1141
|
*/ function InjectEventLogger(topic) {
|
|
762
|
-
return Resolve(() =>
|
|
1142
|
+
return Resolve(() => {
|
|
1143
|
+
const l = useLogger$1();
|
|
1144
|
+
return topic && typeof l.topic === "function" ? l.topic(topic) : l;
|
|
1145
|
+
});
|
|
763
1146
|
}
|
|
764
1147
|
/**
|
|
765
1148
|
* Resolves app-level logger
|
|
@@ -784,7 +1167,7 @@ function fillLabel(target, key, index, name) {
|
|
|
784
1167
|
|
|
785
1168
|
//#endregion
|
|
786
1169
|
//#region packages/moost/src/pipes/types.ts
|
|
787
|
-
var TPipePriority = /* @__PURE__ */ function(TPipePriority$1) {
|
|
1170
|
+
/** Execution priority for pipes. Lower values run first. */ var TPipePriority = /* @__PURE__ */ function(TPipePriority$1) {
|
|
788
1171
|
TPipePriority$1[TPipePriority$1["BEFORE_RESOLVE"] = 0] = "BEFORE_RESOLVE";
|
|
789
1172
|
TPipePriority$1[TPipePriority$1["RESOLVE"] = 1] = "RESOLVE";
|
|
790
1173
|
TPipePriority$1[TPipePriority$1["AFTER_RESOLVE"] = 2] = "AFTER_RESOLVE";
|
|
@@ -872,31 +1255,73 @@ var TPipePriority = /* @__PURE__ */ function(TPipePriority$1) {
|
|
|
872
1255
|
//#endregion
|
|
873
1256
|
//#region packages/moost/src/define.ts
|
|
874
1257
|
/**
|
|
875
|
-
*
|
|
1258
|
+
* Define a before-phase interceptor.
|
|
1259
|
+
*
|
|
1260
|
+
* Runs before argument resolution and handler execution.
|
|
1261
|
+
* Call `reply(value)` to short-circuit the handler and respond early.
|
|
876
1262
|
*
|
|
1263
|
+
* @example
|
|
877
1264
|
* ```ts
|
|
878
|
-
*
|
|
879
|
-
*
|
|
880
|
-
*
|
|
881
|
-
* // before handler
|
|
882
|
-
* })
|
|
883
|
-
* after((response, reply) => {
|
|
884
|
-
* // after handler
|
|
885
|
-
* })
|
|
886
|
-
* onError((error, reply) => {
|
|
887
|
-
* // when error occured
|
|
888
|
-
* })
|
|
889
|
-
* },
|
|
890
|
-
* TInterceptorPriority.INTERCEPTOR,
|
|
891
|
-
* )
|
|
1265
|
+
* const authGuard = defineBeforeInterceptor((reply) => {
|
|
1266
|
+
* if (!isAuthenticated()) reply(new HttpError(401))
|
|
1267
|
+
* }, TInterceptorPriority.GUARD)
|
|
892
1268
|
* ```
|
|
1269
|
+
*/ function defineBeforeInterceptor(fn, priority = TInterceptorPriority.INTERCEPTOR) {
|
|
1270
|
+
return {
|
|
1271
|
+
before: fn,
|
|
1272
|
+
priority
|
|
1273
|
+
};
|
|
1274
|
+
}
|
|
1275
|
+
/**
|
|
1276
|
+
* Define an after-phase interceptor.
|
|
893
1277
|
*
|
|
894
|
-
*
|
|
895
|
-
*
|
|
896
|
-
*
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
1278
|
+
* Runs after successful handler execution.
|
|
1279
|
+
* Call `reply(value)` to transform/replace the response.
|
|
1280
|
+
*
|
|
1281
|
+
* @example
|
|
1282
|
+
* ```ts
|
|
1283
|
+
* const setHeader = defineAfterInterceptor(() => {
|
|
1284
|
+
* useResponse().setHeader('x-server', 'my-server')
|
|
1285
|
+
* }, TInterceptorPriority.AFTER_ALL)
|
|
1286
|
+
* ```
|
|
1287
|
+
*/ function defineAfterInterceptor(fn, priority = TInterceptorPriority.AFTER_ALL) {
|
|
1288
|
+
return {
|
|
1289
|
+
after: fn,
|
|
1290
|
+
priority
|
|
1291
|
+
};
|
|
1292
|
+
}
|
|
1293
|
+
/**
|
|
1294
|
+
* Define an error-phase interceptor.
|
|
1295
|
+
*
|
|
1296
|
+
* Runs when the handler throws or returns an Error.
|
|
1297
|
+
* Call `reply(value)` to recover from the error with a replacement response.
|
|
1298
|
+
*
|
|
1299
|
+
* @example
|
|
1300
|
+
* ```ts
|
|
1301
|
+
* const errorFormatter = defineErrorInterceptor((error, reply) => {
|
|
1302
|
+
* reply({ message: error.message, status: 500 })
|
|
1303
|
+
* }, TInterceptorPriority.CATCH_ERROR)
|
|
1304
|
+
* ```
|
|
1305
|
+
*/ function defineErrorInterceptor(fn, priority = TInterceptorPriority.CATCH_ERROR) {
|
|
1306
|
+
return {
|
|
1307
|
+
error: fn,
|
|
1308
|
+
priority
|
|
1309
|
+
};
|
|
1310
|
+
}
|
|
1311
|
+
/**
|
|
1312
|
+
* Define a full interceptor with multiple lifecycle hooks.
|
|
1313
|
+
*
|
|
1314
|
+
* @example
|
|
1315
|
+
* ```ts
|
|
1316
|
+
* const myInterceptor = defineInterceptor({
|
|
1317
|
+
* before(reply) { ... },
|
|
1318
|
+
* after(response, reply) { ... },
|
|
1319
|
+
* error(error, reply) { ... },
|
|
1320
|
+
* }, TInterceptorPriority.INTERCEPTOR)
|
|
1321
|
+
* ```
|
|
1322
|
+
*/ function defineInterceptor(def, priority = TInterceptorPriority.INTERCEPTOR) {
|
|
1323
|
+
def.priority = priority;
|
|
1324
|
+
return def;
|
|
900
1325
|
}
|
|
901
1326
|
/**
|
|
902
1327
|
* ### Define Pipe Function
|
|
@@ -910,8 +1335,8 @@ var TPipePriority = /* @__PURE__ */ function(TPipePriority$1) {
|
|
|
910
1335
|
* )
|
|
911
1336
|
* ```
|
|
912
1337
|
*
|
|
913
|
-
* @param fn
|
|
914
|
-
* @param priority priority of the pipe
|
|
1338
|
+
* @param fn pipe function
|
|
1339
|
+
* @param priority priority of the pipe
|
|
915
1340
|
* @returns
|
|
916
1341
|
*/ function definePipeFn(fn, priority = TPipePriority.TRANSFORM) {
|
|
917
1342
|
fn.priority = priority;
|
|
@@ -935,14 +1360,14 @@ const sharedPipes = [{
|
|
|
935
1360
|
|
|
936
1361
|
//#endregion
|
|
937
1362
|
//#region packages/moost/src/moost.ts
|
|
938
|
-
function _define_property(obj, key, value) {
|
|
939
|
-
if (key in obj) Object.defineProperty(obj, key, {
|
|
1363
|
+
function _define_property(obj, key$2, value) {
|
|
1364
|
+
if (key$2 in obj) Object.defineProperty(obj, key$2, {
|
|
940
1365
|
value,
|
|
941
1366
|
enumerable: true,
|
|
942
1367
|
configurable: true,
|
|
943
1368
|
writable: true
|
|
944
1369
|
});
|
|
945
|
-
else obj[key] = value;
|
|
1370
|
+
else obj[key$2] = value;
|
|
946
1371
|
return obj;
|
|
947
1372
|
}
|
|
948
1373
|
/**
|
|
@@ -1061,27 +1486,24 @@ function _define_property(obj, key, value) {
|
|
|
1061
1486
|
async bindController(controller, provide, replace, globalPrefix, replaceOwnPrefix) {
|
|
1062
1487
|
const mate$1 = getMoostMate();
|
|
1063
1488
|
const classMeta = mate$1.read(controller);
|
|
1064
|
-
const infact
|
|
1489
|
+
const infact = getMoostInfact();
|
|
1065
1490
|
const isControllerConsructor = isConstructor$1(controller);
|
|
1066
|
-
const pipes =
|
|
1491
|
+
const pipes = mergeSorted(this.pipes, classMeta?.pipes);
|
|
1067
1492
|
let instance;
|
|
1068
1493
|
const infactOpts = {
|
|
1069
1494
|
provide,
|
|
1070
1495
|
replace,
|
|
1071
1496
|
customData: { pipes }
|
|
1072
1497
|
};
|
|
1073
|
-
if (isControllerConsructor && (classMeta?.injectable === "SINGLETON" || classMeta?.injectable === true)) await
|
|
1074
|
-
event: { type: "init" },
|
|
1075
|
-
options: {}
|
|
1076
|
-
})(async () => {
|
|
1498
|
+
if (isControllerConsructor && (classMeta?.injectable === "SINGLETON" || classMeta?.injectable === true)) await createEventContext$1({ logger: this.logger }, async () => {
|
|
1077
1499
|
setControllerContext(this, "bindController", "");
|
|
1078
|
-
instance = await infact
|
|
1500
|
+
instance = await infact.get(controller, infactOpts);
|
|
1079
1501
|
});
|
|
1080
1502
|
else if (!isControllerConsructor) {
|
|
1081
1503
|
instance = controller;
|
|
1082
|
-
infact
|
|
1504
|
+
infact.setInstanceRegistries(instance, provide, replace, { pipes });
|
|
1083
1505
|
}
|
|
1084
|
-
const getInstance = instance ? () =>
|
|
1506
|
+
const getInstance = instance ? () => instance : async () => await infact.get(controller, { ...infactOpts });
|
|
1085
1507
|
const classConstructor = isConstructor$1(controller) ? controller : getConstructor$1(controller);
|
|
1086
1508
|
this.controllersOverview.push(await bindControllerMethods({
|
|
1087
1509
|
getInstance,
|
|
@@ -1137,22 +1559,26 @@ function _define_property(obj, key, value) {
|
|
|
1137
1559
|
if (!this.globalInterceptorHandler) {
|
|
1138
1560
|
const mate$1 = getMoostMate();
|
|
1139
1561
|
const thisMeta = mate$1.read(this);
|
|
1140
|
-
const pipes =
|
|
1141
|
-
const interceptors =
|
|
1142
|
-
this.globalInterceptorHandler = getIterceptorHandlerFactory(interceptors, () =>
|
|
1562
|
+
const pipes = mergeSorted(this.pipes, thisMeta?.pipes);
|
|
1563
|
+
const interceptors = mergeSorted(this.interceptors, thisMeta?.interceptors);
|
|
1564
|
+
this.globalInterceptorHandler = getIterceptorHandlerFactory(interceptors, () => this, pipes);
|
|
1143
1565
|
}
|
|
1144
1566
|
return this.globalInterceptorHandler();
|
|
1145
1567
|
}
|
|
1146
1568
|
applyGlobalInterceptors(...items) {
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1569
|
+
const mate$1 = getMoostMate();
|
|
1570
|
+
for (const item of items) if (typeof item === "function") {
|
|
1571
|
+
const meta = mate$1.read(item);
|
|
1572
|
+
this.interceptors.push({
|
|
1573
|
+
handler: item,
|
|
1574
|
+
priority: meta?.interceptor?.priority ?? TInterceptorPriority.INTERCEPTOR,
|
|
1575
|
+
name: item.name || "<anonymous>"
|
|
1576
|
+
});
|
|
1577
|
+
} else if ("handler" in item) this.interceptors.push(item);
|
|
1152
1578
|
else this.interceptors.push({
|
|
1153
|
-
handler: item
|
|
1154
|
-
priority: item.priority,
|
|
1155
|
-
name: item.
|
|
1579
|
+
handler: item,
|
|
1580
|
+
priority: item.priority ?? TInterceptorPriority.INTERCEPTOR,
|
|
1581
|
+
name: item._name || "<anonymous>"
|
|
1156
1582
|
});
|
|
1157
1583
|
this.globalInterceptorHandler = void 0;
|
|
1158
1584
|
return this;
|
|
@@ -1202,4 +1628,4 @@ function _define_property(obj, key, value) {
|
|
|
1202
1628
|
};
|
|
1203
1629
|
|
|
1204
1630
|
//#endregion
|
|
1205
|
-
export { ApplyDecorators, Circular, Const, ConstFactory, ContextInjector, Controller, Description,
|
|
1631
|
+
export { After, ApplyDecorators, Before, Circular, Const, ConstFactory, ContextInjector, Controller, Description, Id, ImportController, Inherit, Inject, InjectEventLogger, InjectFromScope, InjectMoostLogger, InjectScopeVars, Injectable, Intercept, Interceptor, InterceptorHandler, Label, LoggerTopic, Moost, OnError, Optional, Overtake, Param, Params, Pipe, ProstoLogger, Provide, Replace, Required, Resolve, Response, TInterceptorPriority, TPipePriority, Value, cached, clearGlobalWooks, createEventContext, createLogger, createProvideRegistry, createReplaceRegistry, current, defineAfterInterceptor, defineBeforeInterceptor, defineErrorInterceptor, defineInfactScope, defineInterceptor, defineMoostEventHandler, definePipeFn, eventTypeKey, getConstructor, getContextInjector, getGlobalWooks, getInfactScopeVars, getInstanceOwnMethods, getInstanceOwnProps, getMoostInfact, getMoostMate, getNewMoostInfact, isConstructor, isThenable, key, loggerConsoleTransport, mergeSorted, registerEventScope, replaceContextInjector, resetContextInjector, resolvePipe, run, setControllerContext, setInfactLoggingOptions, setInterceptResult, setOvertake, useControllerContext, useInterceptResult, useLogger, useOvertake, useScopeId };
|