moost 0.6.46 → 0.6.48
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 +211 -97
- package/dist/index.d.ts +56 -41
- package/dist/index.mjs +212 -98
- package/package.json +8 -8
package/dist/index.cjs
CHANGED
|
@@ -48,7 +48,7 @@ let stamped = false;
|
|
|
48
48
|
if (stamped) return;
|
|
49
49
|
stamped = true;
|
|
50
50
|
stampModuleIdentity({
|
|
51
|
-
version: "0.6.
|
|
51
|
+
version: "0.6.48",
|
|
52
52
|
path: typeof __filename === "string" ? __filename : require("url").pathToFileURL(__filename).href
|
|
53
53
|
});
|
|
54
54
|
}
|
|
@@ -124,7 +124,7 @@ function getDefaultLogger(topic) {
|
|
|
124
124
|
|
|
125
125
|
//#endregion
|
|
126
126
|
//#region packages/moost/src/event-scope.ts
|
|
127
|
-
function _define_property$
|
|
127
|
+
function _define_property$1(obj, key, value) {
|
|
128
128
|
if (key in obj) Object.defineProperty(obj, key, {
|
|
129
129
|
value,
|
|
130
130
|
enumerable: true,
|
|
@@ -143,13 +143,64 @@ function nextScopeId() {
|
|
|
143
143
|
}
|
|
144
144
|
return `__moost_${_scopeChar}_${++_scopeNum}`;
|
|
145
145
|
}
|
|
146
|
-
const
|
|
146
|
+
const eventScopeSlot = (0, _wooksjs_event_core.cached)(() => ({
|
|
147
|
+
id: nextScopeId(),
|
|
148
|
+
held: false,
|
|
149
|
+
registered: false
|
|
150
|
+
}));
|
|
151
|
+
/**
|
|
152
|
+
* The DI scope of an event (see {@link useScopeId}) — cached on the event context itself.
|
|
153
|
+
* @internal
|
|
154
|
+
*/ const getEventScope = (ctx) => (ctx ?? (0, _wooksjs_event_core.current)()).getOwn(eventScopeSlot);
|
|
147
155
|
/**
|
|
148
156
|
* Composable returning the moost DI scope ID of the current event. Generated on first call
|
|
149
157
|
* and cached on the event context itself — never inherited from a parent context, so a child
|
|
150
158
|
* event (a workflow run started with `eventContext`, a WebSocket message) owns its scope
|
|
151
159
|
* instead of sharing, and later releasing, its parent's.
|
|
152
|
-
*/ const useScopeId = (ctx) => (ctx
|
|
160
|
+
*/ const useScopeId = (ctx) => getEventScope(ctx).id;
|
|
161
|
+
/**
|
|
162
|
+
* Holds the event scope for a handler lifecycle — registering it, deferred to the first
|
|
163
|
+
* `FOR_EVENT` resolution (see {@link resolveEventScopeId}). Returns the release, which drops
|
|
164
|
+
* the scope like the release of an eager registration.
|
|
165
|
+
* @internal
|
|
166
|
+
*/ function holdEventScopeLazily(scope) {
|
|
167
|
+
scope.held = true;
|
|
168
|
+
return () => {
|
|
169
|
+
scope.held = false;
|
|
170
|
+
if (scope.registered) {
|
|
171
|
+
scope.registered = false;
|
|
172
|
+
getMoostInfact().unregisterScope(scope.id);
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* The scope id a `FOR_EVENT` resolution in the current event uses: a held scope is registered
|
|
178
|
+
* in the DI container now, on first use.
|
|
179
|
+
* @internal
|
|
180
|
+
*/ function resolveEventScopeId() {
|
|
181
|
+
const scope = getEventScope();
|
|
182
|
+
if (scope.held && !scope.registered) {
|
|
183
|
+
scope.registered = true;
|
|
184
|
+
getMoostInfact().registerScope(scope.id);
|
|
185
|
+
}
|
|
186
|
+
return scope.id;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Keeps the current event's scope state in step with a direct `registerScope` /
|
|
190
|
+
* `unregisterScope` of its id on the moost DI container — `registerEventScope(useScopeId())`,
|
|
191
|
+
* or an adapter's `cleanup: () => getMoostInfact().unregisterScope(useScopeId())`. As with an
|
|
192
|
+
* eager registration: a registered scope is dropped with the handler lifecycle, and an
|
|
193
|
+
* unregistered one stays gone for the rest of the lifecycle (a later `FOR_EVENT` resolution
|
|
194
|
+
* fails instead of registering it again — and leaking it, when nothing releases it after).
|
|
195
|
+
* @internal
|
|
196
|
+
*/ function syncEventScope(scopeId, registered) {
|
|
197
|
+
const ctx = (0, _wooksjs_event_core.tryGetCurrent)();
|
|
198
|
+
const scope = ctx?.hasOwn(eventScopeSlot) ? ctx.getOwn(eventScopeSlot) : void 0;
|
|
199
|
+
if (scope?.id === scopeId) {
|
|
200
|
+
scope.registered = registered;
|
|
201
|
+
if (!registered) scope.held = false;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
153
204
|
/** Registers a DI scope for the given ID and returns an unscope function. */ function registerEventScope(scopeId) {
|
|
154
205
|
const infact = getMoostInfact();
|
|
155
206
|
infact.registerScope(scopeId);
|
|
@@ -169,7 +220,7 @@ const NO_ISOLATION = /* @__PURE__ */ new Set();
|
|
|
169
220
|
super({
|
|
170
221
|
logger: parent.logger,
|
|
171
222
|
parent
|
|
172
|
-
}), _define_property$
|
|
223
|
+
}), _define_property$1(this, "isolated", void 0), this.isolated = isolated;
|
|
173
224
|
}
|
|
174
225
|
};
|
|
175
226
|
/**
|
|
@@ -222,7 +273,7 @@ const NO_ISOLATION = /* @__PURE__ */ new Set();
|
|
|
222
273
|
ctx: child
|
|
223
274
|
});
|
|
224
275
|
if (opts?.shareScope !== false) {
|
|
225
|
-
child.setOwn(
|
|
276
|
+
child.setOwn(eventScopeSlot, getEventScope(parent));
|
|
226
277
|
return (0, _wooksjs_event_core.run)(child, fn);
|
|
227
278
|
}
|
|
228
279
|
const release = registerEventScope(useScopeId(child));
|
|
@@ -347,6 +398,22 @@ const moostMate = new _prostojs_mate.Mate(METADATA_WORKSPACE, {
|
|
|
347
398
|
return moostMate;
|
|
348
399
|
}
|
|
349
400
|
|
|
401
|
+
//#endregion
|
|
402
|
+
//#region packages/moost/src/metadata/moost-infact.ts
|
|
403
|
+
/**
|
|
404
|
+
* The moost DI container. A direct scope (un)registration of the current event's own scope
|
|
405
|
+
* keeps its on-demand registration state in step (see `syncEventScope`).
|
|
406
|
+
*/ var MoostInfact = class extends _prostojs_infact.Infact {
|
|
407
|
+
registerScope(scopeId) {
|
|
408
|
+
super.registerScope(scopeId);
|
|
409
|
+
syncEventScope(scopeId, true);
|
|
410
|
+
}
|
|
411
|
+
unregisterScope(scopeId) {
|
|
412
|
+
super.unregisterScope(scopeId);
|
|
413
|
+
syncEventScope(scopeId, false);
|
|
414
|
+
}
|
|
415
|
+
};
|
|
416
|
+
|
|
350
417
|
//#endregion
|
|
351
418
|
//#region packages/moost/src/metadata/infact.ts
|
|
352
419
|
const sharedMoostInfact = getNewMoostInfact();
|
|
@@ -458,7 +525,7 @@ function formatNewInstanceArg(a) {
|
|
|
458
525
|
/**
|
|
459
526
|
* Get Infact instance (used for Dependency Injections)
|
|
460
527
|
*/ function getNewMoostInfact() {
|
|
461
|
-
return new
|
|
528
|
+
return new MoostInfact({
|
|
462
529
|
describeClass(classConstructor) {
|
|
463
530
|
const meta = getMoostMate().read(classConstructor);
|
|
464
531
|
return {
|
|
@@ -467,7 +534,7 @@ function formatNewInstanceArg(a) {
|
|
|
467
534
|
constructorParams: meta?.params || [],
|
|
468
535
|
provide: meta?.provide,
|
|
469
536
|
properties: meta?.properties || [],
|
|
470
|
-
scopeId: meta?.injectable === "FOR_EVENT" ?
|
|
537
|
+
scopeId: meta?.injectable === "FOR_EVENT" ? resolveEventScopeId() : void 0
|
|
471
538
|
};
|
|
472
539
|
},
|
|
473
540
|
resolveParam({ paramMeta, customData, classConstructor, index, scopeId, instantiate }) {
|
|
@@ -519,19 +586,27 @@ const registry = (_g = globalThis).__moost_keys ?? (_g.__moost_keys = /* @__PURE
|
|
|
519
586
|
|
|
520
587
|
//#endregion
|
|
521
588
|
//#region packages/moost/src/composables/controller.composable.ts
|
|
522
|
-
const
|
|
523
|
-
const controllerMethodKey = globalKey("controller.method");
|
|
524
|
-
const controllerRouteKey = globalKey("controller.route");
|
|
525
|
-
const controllerPrefixKey = globalKey("controller.prefix");
|
|
589
|
+
const controllerContextKey = globalKey("controller.context");
|
|
526
590
|
/**
|
|
527
591
|
* Sets the controller context for the current event scope.
|
|
528
592
|
* Called internally by adapters when dispatching events to handlers.
|
|
529
593
|
*/ function setControllerContext(controller, method, route, opts) {
|
|
530
594
|
const _ctx = opts?.ctx || (0, _wooksjs_event_core.current)();
|
|
531
|
-
|
|
532
|
-
_ctx.
|
|
533
|
-
_ctx.set(
|
|
534
|
-
|
|
595
|
+
let prefix = opts?.prefix;
|
|
596
|
+
if (prefix === void 0 && _ctx.has(controllerContextKey)) prefix = _ctx.get(controllerContextKey).prefix;
|
|
597
|
+
_ctx.set(controllerContextKey, {
|
|
598
|
+
instance: controller,
|
|
599
|
+
method,
|
|
600
|
+
route,
|
|
601
|
+
prefix
|
|
602
|
+
});
|
|
603
|
+
}
|
|
604
|
+
/** Reads the controller context; throws the per-field "not set" error when there is none. */ function readControllerContext(ctx, field) {
|
|
605
|
+
try {
|
|
606
|
+
return ctx.get(controllerContextKey);
|
|
607
|
+
} catch {
|
|
608
|
+
throw new Error(`Key "controller.${field}" is not set`);
|
|
609
|
+
}
|
|
535
610
|
}
|
|
536
611
|
/** Brands already warned about by {@link brandedAdapterFor} (one warning per process). */ const reportedAdapterCopies = /* @__PURE__ */ new Set();
|
|
537
612
|
/**
|
|
@@ -555,10 +630,14 @@ const controllerPrefixKey = globalKey("controller.prefix");
|
|
|
555
630
|
* Returns utilities for accessing the controller instance, method metadata, and DI.
|
|
556
631
|
*/ function useControllerContext(ctx) {
|
|
557
632
|
const _ctx = ctx || (0, _wooksjs_event_core.current)();
|
|
558
|
-
const getController = () => _ctx.
|
|
559
|
-
const getMethod = () => _ctx.
|
|
560
|
-
const getRoute = () => _ctx.
|
|
561
|
-
const getPrefix = () =>
|
|
633
|
+
const getController = () => readControllerContext(_ctx, "instance").instance;
|
|
634
|
+
const getMethod = () => readControllerContext(_ctx, "method").method;
|
|
635
|
+
const getRoute = () => readControllerContext(_ctx, "route").route;
|
|
636
|
+
const getPrefix = () => {
|
|
637
|
+
const { prefix } = readControllerContext(_ctx, "prefix");
|
|
638
|
+
if (prefix === void 0) throw new Error("Key \"controller.prefix\" is not set");
|
|
639
|
+
return prefix;
|
|
640
|
+
};
|
|
562
641
|
const getControllerMeta = () => getMoostMate().read(getController());
|
|
563
642
|
const getMethodMeta = (name) => getMoostMate().read(getController(), name || getMethod());
|
|
564
643
|
function instantiate(c) {
|
|
@@ -602,13 +681,30 @@ const interceptResultKey = globalKey("interceptor.result");
|
|
|
602
681
|
//#region packages/moost/src/adapter-utils.ts
|
|
603
682
|
const noop = () => {};
|
|
604
683
|
/**
|
|
605
|
-
*
|
|
606
|
-
*
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
684
|
+
* The hook options of one event. `logger` is a prototype getter: the topic logger is only
|
|
685
|
+
* derived when a hook reads it (an own accessor property would deopt the object instead).
|
|
686
|
+
*/ let EventHookOptions = class EventHookOptions {
|
|
687
|
+
get logger() {
|
|
688
|
+
return this._getLogger();
|
|
689
|
+
}
|
|
690
|
+
constructor(scopeId, unscope, method, getResponse, reply, getLogger) {
|
|
691
|
+
this.scopeId = scopeId;
|
|
692
|
+
this.unscope = unscope;
|
|
693
|
+
this.method = method;
|
|
694
|
+
this.getResponse = getResponse;
|
|
695
|
+
this.reply = reply;
|
|
696
|
+
this._getLogger = getLogger;
|
|
697
|
+
}
|
|
698
|
+
};
|
|
699
|
+
/**
|
|
700
|
+
* Holds an event's DI scope (registered on demand, see `holdEventScopeLazily`) by its handler
|
|
701
|
+
* lifecycle and, with `adapterHolds`, by the adapter too. Each release is idempotent; the
|
|
702
|
+
* scope is dropped once every holder let go, so an adapter signal that fires early (a client
|
|
703
|
+
* disconnect mid-handler) cannot pull the scope from under a running handler. Built outside
|
|
704
|
+
* the handler closure so a long-lived adapter listener (the response 'close' of a streamed
|
|
705
|
+
* body) retains only the scope.
|
|
706
|
+
*/ function holdEventScope(scope, adapterHolds) {
|
|
707
|
+
const drop = holdEventScopeLazily(scope);
|
|
612
708
|
let holders = adapterHolds ? 2 : 1;
|
|
613
709
|
const hold = () => {
|
|
614
710
|
let held = true;
|
|
@@ -634,7 +730,6 @@ const noop = () => {};
|
|
|
634
730
|
* Handles scope registration, controller resolution, interceptors, argument resolution,
|
|
635
731
|
* handler invocation, and cleanup — optimised for sync-first execution.
|
|
636
732
|
*/ function defineMoostEventHandler(options) {
|
|
637
|
-
const ci = (0, _wooksjs_event_core.getContextInjector)();
|
|
638
733
|
const manualUnscope = !!options.manualUnscope;
|
|
639
734
|
const handlerSpanName = `Handler:${options.targetPath}`;
|
|
640
735
|
const handlerAttrs = {
|
|
@@ -642,21 +737,17 @@ const noop = () => {};
|
|
|
642
737
|
"moost.controller": options.controllerName || ""
|
|
643
738
|
};
|
|
644
739
|
return () => {
|
|
740
|
+
const ci = (0, _wooksjs_event_core.getContextInjector)();
|
|
645
741
|
const ctx = (0, _wooksjs_event_core.current)();
|
|
646
|
-
const
|
|
647
|
-
const
|
|
648
|
-
const { unscope, releaseLifecycle, failLifecycle } = holdEventScope(
|
|
742
|
+
const scope = getEventScope(ctx);
|
|
743
|
+
const scopeId = scope.id;
|
|
744
|
+
const { unscope, releaseLifecycle, failLifecycle } = holdEventScope(scope, manualUnscope);
|
|
649
745
|
let response;
|
|
746
|
+
let logger;
|
|
747
|
+
const getLogger = () => logger ?? (logger = (0, _wooksjs_event_core.useLogger)(options.loggerTitle, ctx));
|
|
650
748
|
let hookOptions;
|
|
651
749
|
function getHookOptions() {
|
|
652
|
-
return hookOptions ?? (hookOptions =
|
|
653
|
-
scopeId,
|
|
654
|
-
logger,
|
|
655
|
-
unscope,
|
|
656
|
-
method: options.controllerMethod,
|
|
657
|
-
getResponse: () => response,
|
|
658
|
-
reply: (r) => response = r
|
|
659
|
-
});
|
|
750
|
+
return hookOptions ?? (hookOptions = new EventHookOptions(scopeId, unscope, options.controllerMethod, () => response, (r) => response = r, getLogger));
|
|
660
751
|
}
|
|
661
752
|
let interceptorHandler;
|
|
662
753
|
let raise = false;
|
|
@@ -694,7 +785,7 @@ const noop = () => {};
|
|
|
694
785
|
response = initResult;
|
|
695
786
|
if (response !== void 0) return cleanup();
|
|
696
787
|
} catch (error) {
|
|
697
|
-
if (options.logErrors)
|
|
788
|
+
if (options.logErrors) getLogger().error(String(error));
|
|
698
789
|
response = error;
|
|
699
790
|
raise = true;
|
|
700
791
|
return cleanup();
|
|
@@ -711,7 +802,7 @@ const noop = () => {};
|
|
|
711
802
|
}, handleError);
|
|
712
803
|
args = argsResult;
|
|
713
804
|
} catch (error) {
|
|
714
|
-
if (options.logErrors)
|
|
805
|
+
if (options.logErrors) getLogger().error(String(error));
|
|
715
806
|
response = error;
|
|
716
807
|
raise = true;
|
|
717
808
|
return cleanup();
|
|
@@ -726,21 +817,21 @@ const noop = () => {};
|
|
|
726
817
|
response = r;
|
|
727
818
|
return cleanup();
|
|
728
819
|
}, (error) => {
|
|
729
|
-
if (options.logErrors)
|
|
820
|
+
if (options.logErrors) getLogger().error(error);
|
|
730
821
|
response = error;
|
|
731
822
|
raise = true;
|
|
732
823
|
return cleanup();
|
|
733
824
|
});
|
|
734
825
|
response = handlerResult;
|
|
735
826
|
} catch (error) {
|
|
736
|
-
if (options.logErrors)
|
|
827
|
+
if (options.logErrors) getLogger().error(error);
|
|
737
828
|
response = error;
|
|
738
829
|
raise = true;
|
|
739
830
|
}
|
|
740
831
|
return cleanup();
|
|
741
832
|
}
|
|
742
833
|
function handleError(error) {
|
|
743
|
-
if (options.logErrors)
|
|
834
|
+
if (options.logErrors) getLogger().error(String(error));
|
|
744
835
|
response = error;
|
|
745
836
|
raise = true;
|
|
746
837
|
return cleanup();
|
|
@@ -754,7 +845,7 @@ const noop = () => {};
|
|
|
754
845
|
if (raise && response !== raisedResponse) raise = false;
|
|
755
846
|
return finalize();
|
|
756
847
|
}, (error) => {
|
|
757
|
-
if (options.logErrors)
|
|
848
|
+
if (options.logErrors) getLogger().error(String(error));
|
|
758
849
|
throw error;
|
|
759
850
|
});
|
|
760
851
|
response = afterResult;
|
|
@@ -1134,10 +1225,14 @@ function ImportController(prefix, controller, provide) {
|
|
|
1134
1225
|
*/ function Resolve(resolver, label) {
|
|
1135
1226
|
return (target, key, index) => {
|
|
1136
1227
|
const i = typeof index === "number" ? index : void 0;
|
|
1228
|
+
let labelFilled = false;
|
|
1137
1229
|
getMoostMate().decorate("resolver", (metas, level) => {
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1230
|
+
if (!labelFilled) {
|
|
1231
|
+
labelFilled = true;
|
|
1232
|
+
let newLabel = label;
|
|
1233
|
+
if (!newLabel && level === "PROP" && typeof metas.key === "string") newLabel = metas.key;
|
|
1234
|
+
fillLabel(target, key || "", i, newLabel);
|
|
1235
|
+
}
|
|
1141
1236
|
return resolver(metas, level);
|
|
1142
1237
|
})(target, key, i);
|
|
1143
1238
|
};
|
|
@@ -1608,6 +1703,7 @@ const sharedPipes = [{
|
|
|
1608
1703
|
|
|
1609
1704
|
//#endregion
|
|
1610
1705
|
//#region packages/moost/src/resolve-arguments.ts
|
|
1706
|
+
/** `metas.instantiate` of a handler argument: resolves through the current controller's DI. */ const instantiateFromController = (t) => useControllerContext().instantiate(t);
|
|
1611
1707
|
/**
|
|
1612
1708
|
* Builds an argument-resolver function from pre-computed per-parameter pipe lists.
|
|
1613
1709
|
*
|
|
@@ -1616,21 +1712,25 @@ const sharedPipes = [{
|
|
|
1616
1712
|
* `unknown[]` synchronously when possible, or `Promise<unknown[]>` otherwise.
|
|
1617
1713
|
*/ function resolveArguments(argsPipes, context) {
|
|
1618
1714
|
if (argsPipes.length === 0) return;
|
|
1715
|
+
const params = argsPipes.map(({ meta: paramMeta, pipes }, index) => ({
|
|
1716
|
+
pipes,
|
|
1717
|
+
metas: {
|
|
1718
|
+
classMeta: context.classMeta,
|
|
1719
|
+
methodMeta: context.methodMeta,
|
|
1720
|
+
paramMeta,
|
|
1721
|
+
type: context.type,
|
|
1722
|
+
key: context.key,
|
|
1723
|
+
index,
|
|
1724
|
+
targetMeta: paramMeta,
|
|
1725
|
+
instantiate: instantiateFromController
|
|
1726
|
+
}
|
|
1727
|
+
}));
|
|
1619
1728
|
return () => {
|
|
1620
1729
|
const args = [];
|
|
1621
1730
|
let hasAsync = false;
|
|
1622
|
-
for (let i = 0; i <
|
|
1623
|
-
const { pipes,
|
|
1624
|
-
const result = runPipes(pipes, void 0,
|
|
1625
|
-
classMeta: context.classMeta,
|
|
1626
|
-
methodMeta: context.methodMeta,
|
|
1627
|
-
paramMeta,
|
|
1628
|
-
type: context.type,
|
|
1629
|
-
key: context.key,
|
|
1630
|
-
index: i,
|
|
1631
|
-
targetMeta: paramMeta,
|
|
1632
|
-
instantiate: (t) => useControllerContext().instantiate(t)
|
|
1633
|
-
}, "PARAM");
|
|
1731
|
+
for (let i = 0; i < params.length; i++) {
|
|
1732
|
+
const { pipes, metas } = params[i];
|
|
1733
|
+
const result = runPipes(pipes, void 0, metas, "PARAM");
|
|
1634
1734
|
if (!hasAsync && isThenable(result)) hasAsync = true;
|
|
1635
1735
|
args[i] = result;
|
|
1636
1736
|
}
|
|
@@ -1640,16 +1740,9 @@ const sharedPipes = [{
|
|
|
1640
1740
|
|
|
1641
1741
|
//#endregion
|
|
1642
1742
|
//#region packages/moost/src/interceptor-handler.ts
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
enumerable: true,
|
|
1647
|
-
configurable: true,
|
|
1648
|
-
writable: true
|
|
1649
|
-
});
|
|
1650
|
-
else obj[key] = value;
|
|
1651
|
-
return obj;
|
|
1652
|
-
}
|
|
1743
|
+
/** Span attributes of the interceptor stages — shared, never mutated. */ const BEFORE_STAGE = { "moost.interceptor.stage": "before" };
|
|
1744
|
+
const AFTER_STAGE = { "moost.interceptor.stage": "after" };
|
|
1745
|
+
const ON_ERROR_STAGE = { "moost.interceptor.stage": "onError" };
|
|
1653
1746
|
/**
|
|
1654
1747
|
* Manages the before/after/error interceptor lifecycle for a single event.
|
|
1655
1748
|
* Optimised for the common sync path — only allocates promises when an interceptor goes async.
|
|
@@ -1674,16 +1767,15 @@ function _define_property$1(obj, key, value) {
|
|
|
1674
1767
|
* Returns a pending PromiseLike if `before` went async, or undefined.
|
|
1675
1768
|
*/ registerDef(def, entry, ci) {
|
|
1676
1769
|
if (def.after) (this.after ?? (this.after = [])).unshift({
|
|
1677
|
-
|
|
1770
|
+
spanName: entry.spanName,
|
|
1678
1771
|
fn: def.after
|
|
1679
1772
|
});
|
|
1680
1773
|
if (def.error) (this.onError ?? (this.onError = [])).unshift({
|
|
1681
|
-
|
|
1774
|
+
spanName: entry.spanName,
|
|
1682
1775
|
fn: def.error
|
|
1683
1776
|
});
|
|
1684
1777
|
if (def.before) {
|
|
1685
|
-
const
|
|
1686
|
-
const result = ci ? ci.with(spanName, { "moost.interceptor.stage": "before" }, () => def.before?.(this.getReplyFn())) : def.before(this.getReplyFn());
|
|
1778
|
+
const result = ci ? ci.with(entry.spanName, BEFORE_STAGE, () => def.before?.(this.getReplyFn())) : def.before(this.getReplyFn());
|
|
1687
1779
|
if (isThenable(result)) return result;
|
|
1688
1780
|
}
|
|
1689
1781
|
}
|
|
@@ -1736,10 +1828,10 @@ function _define_property$1(obj, key, value) {
|
|
|
1736
1828
|
const handlers = isError ? this.onError : this.after;
|
|
1737
1829
|
if (!handlers) return this.response;
|
|
1738
1830
|
const ci = (0, _wooksjs_event_core.getContextInjector)();
|
|
1739
|
-
const stage = isError ?
|
|
1831
|
+
const stage = isError ? ON_ERROR_STAGE : AFTER_STAGE;
|
|
1740
1832
|
for (let i = 0; i < handlers.length; i++) {
|
|
1741
|
-
const {
|
|
1742
|
-
const result = ci ? ci.with(
|
|
1833
|
+
const { spanName, fn } = handlers[i];
|
|
1834
|
+
const result = ci ? ci.with(spanName, stage, () => fn(response, this.getReplyFn())) : fn(response, this.getReplyFn());
|
|
1743
1835
|
if (isThenable(result)) return this._fireAfterAsync({
|
|
1744
1836
|
ci,
|
|
1745
1837
|
handlers,
|
|
@@ -1752,21 +1844,19 @@ function _define_property$1(obj, key, value) {
|
|
|
1752
1844
|
async _fireAfterAsync(ctx, pending, startIndex) {
|
|
1753
1845
|
await pending;
|
|
1754
1846
|
for (let i = startIndex + 1; i < ctx.handlers.length; i++) {
|
|
1755
|
-
const {
|
|
1756
|
-
if (ctx.ci) await ctx.ci.with(
|
|
1847
|
+
const { spanName, fn } = ctx.handlers[i];
|
|
1848
|
+
if (ctx.ci) await ctx.ci.with(spanName, ctx.stage, () => fn(ctx.response, this.getReplyFn()));
|
|
1757
1849
|
else await fn(ctx.response, this.getReplyFn());
|
|
1758
1850
|
}
|
|
1759
1851
|
return this.response;
|
|
1760
1852
|
}
|
|
1761
1853
|
constructor(handlers) {
|
|
1762
|
-
_define_property$1(this, "handlers", void 0);
|
|
1763
|
-
_define_property$1(this, "after", void 0);
|
|
1764
|
-
_define_property$1(this, "onError", void 0);
|
|
1765
|
-
_define_property$1(this, "response", void 0);
|
|
1766
|
-
_define_property$1(this, "responseOverwritten", void 0);
|
|
1767
|
-
_define_property$1(this, "_boundReplyFn", void 0);
|
|
1768
1854
|
this.handlers = handlers;
|
|
1855
|
+
this.after = void 0;
|
|
1856
|
+
this.onError = void 0;
|
|
1857
|
+
this.response = void 0;
|
|
1769
1858
|
this.responseOverwritten = false;
|
|
1859
|
+
this._boundReplyFn = void 0;
|
|
1770
1860
|
}
|
|
1771
1861
|
};
|
|
1772
1862
|
|
|
@@ -1774,6 +1864,7 @@ function _define_property$1(obj, key, value) {
|
|
|
1774
1864
|
//#region packages/moost/src/utils.ts
|
|
1775
1865
|
const mate = getMoostMate();
|
|
1776
1866
|
const noInterceptors = () => void 0;
|
|
1867
|
+
const isForEvent = (instance) => mate.read(instance)?.injectable === "FOR_EVENT";
|
|
1777
1868
|
function findInterceptorMethods(handler) {
|
|
1778
1869
|
const fakeInstance = Object.create(handler.prototype);
|
|
1779
1870
|
const methods = getInstanceOwnMethods(fakeInstance);
|
|
@@ -1812,6 +1903,8 @@ function callMethod(instance, methodName, resolveArgs) {
|
|
|
1812
1903
|
}
|
|
1813
1904
|
function createClassInterceptorFactory(opts) {
|
|
1814
1905
|
const infact = getMoostInfact();
|
|
1906
|
+
const customData = { pipes: opts.pipes };
|
|
1907
|
+
const defs = opts.cacheable ? /* @__PURE__ */ new WeakMap() : void 0;
|
|
1815
1908
|
function buildDef(instance) {
|
|
1816
1909
|
const def = {};
|
|
1817
1910
|
if (opts.methods.before) {
|
|
@@ -1844,9 +1937,21 @@ function createClassInterceptorFactory(opts) {
|
|
|
1844
1937
|
return def;
|
|
1845
1938
|
}
|
|
1846
1939
|
function fromTarget(targetInstance) {
|
|
1847
|
-
const
|
|
1848
|
-
if (
|
|
1849
|
-
|
|
1940
|
+
const cached = defs?.get(targetInstance);
|
|
1941
|
+
if (cached) return cached;
|
|
1942
|
+
const registries = infact.getInstanceRegistries(targetInstance);
|
|
1943
|
+
const result = infact.get(opts.handler, {
|
|
1944
|
+
provide: registries.provide || {},
|
|
1945
|
+
replace: registries.replace,
|
|
1946
|
+
customData
|
|
1947
|
+
});
|
|
1948
|
+
const remember = (instance) => {
|
|
1949
|
+
const def = buildDef(instance);
|
|
1950
|
+
if (defs && !isForEvent(instance) && !isForEvent(targetInstance)) defs.set(targetInstance, def);
|
|
1951
|
+
return def;
|
|
1952
|
+
};
|
|
1953
|
+
if (isThenable(result)) return result.then(remember);
|
|
1954
|
+
return remember(result);
|
|
1850
1955
|
}
|
|
1851
1956
|
return () => {
|
|
1852
1957
|
const result = opts.getTargetInstance();
|
|
@@ -1888,7 +1993,8 @@ function getIterceptorHandlerFactory(interceptors, getTargetInstance, pipes) {
|
|
|
1888
1993
|
methods,
|
|
1889
1994
|
resolvers,
|
|
1890
1995
|
getTargetInstance,
|
|
1891
|
-
pipes: mergedPipes
|
|
1996
|
+
pipes: mergedPipes,
|
|
1997
|
+
cacheable: classMeta.injectable !== "FOR_EVENT"
|
|
1892
1998
|
}),
|
|
1893
1999
|
name,
|
|
1894
2000
|
spanName
|
|
@@ -2387,12 +2493,17 @@ function _define_property(obj, key, value) {
|
|
|
2387
2493
|
* - before the hook pass starts (including from a controller constructor
|
|
2388
2494
|
* during binding) — queued;
|
|
2389
2495
|
* - while the pass runs (from another hook) — runs later in the same pass;
|
|
2390
|
-
* - after the pass finished — runs immediately (asynchronously, in its
|
|
2391
|
-
* init context)
|
|
2496
|
+
* - after the pass finished — runs once, immediately (asynchronously, in its
|
|
2497
|
+
* own init context) and is NOT stored, so it does not run again on
|
|
2498
|
+
* re-init and per-request callers (`FOR_EVENT` constructors) do not grow
|
|
2499
|
+
* the hook list. A failure is logged, since there is no `init()` left to
|
|
2392
2500
|
* reject.
|
|
2393
2501
|
*
|
|
2394
|
-
* No de-duplication: registering the same function twice runs it twice
|
|
2395
|
-
*
|
|
2502
|
+
* No de-duplication: registering the same function twice runs it twice
|
|
2503
|
+
* (per-request callers should guard non-idempotent work themselves). Hooks
|
|
2504
|
+
* registered before or during a pass re-run on re-init exactly like
|
|
2505
|
+
* `@MoostInit` hooks; to get a hook on every future init, register it
|
|
2506
|
+
* before `init()`.
|
|
2396
2507
|
* @since 0.6.46
|
|
2397
2508
|
*/ addInitHook(fn, opts) {
|
|
2398
2509
|
const hook = {
|
|
@@ -2400,10 +2511,13 @@ function _define_property(obj, key, value) {
|
|
|
2400
2511
|
priority: opts?.priority ?? 0,
|
|
2401
2512
|
fn
|
|
2402
2513
|
};
|
|
2514
|
+
if (this.initHookPhase === "done") {
|
|
2515
|
+
this.runInitHook(hook).catch((error) => {
|
|
2516
|
+
this.logger.error(`Late init hook failed: ${errorMessage(error)}`);
|
|
2517
|
+
});
|
|
2518
|
+
return;
|
|
2519
|
+
}
|
|
2403
2520
|
this.initHooks.push(hook);
|
|
2404
|
-
if (this.initHookPhase === "done") this.runInitHook(hook).catch((error) => {
|
|
2405
|
-
this.logger.error(`Late init hook failed: ${errorMessage(error)}`);
|
|
2406
|
-
});
|
|
2407
2521
|
}
|
|
2408
2522
|
/**
|
|
2409
2523
|
* ### dispose
|
|
@@ -2536,7 +2650,7 @@ function _define_property(obj, key, value) {
|
|
|
2536
2650
|
infact.setInstanceRegistries(instance, provide, replace, { pipes });
|
|
2537
2651
|
}
|
|
2538
2652
|
if (instance) this.singletonInstances.add(instance);
|
|
2539
|
-
const getInstance = instance ? () => instance :
|
|
2653
|
+
const getInstance = instance ? () => instance : () => infact.get(controller, infactOpts);
|
|
2540
2654
|
const classConstructor = (0, _prostojs_mate.isConstructor)(controller) ? controller : (0, _prostojs_mate.getConstructor)(controller);
|
|
2541
2655
|
const controllerOverview = await bindControllerMethods({
|
|
2542
2656
|
getInstance,
|
package/dist/index.d.ts
CHANGED
|
@@ -216,6 +216,28 @@ declare function MoostDispose(opts?: {
|
|
|
216
216
|
priority?: number;
|
|
217
217
|
}): MethodDecorator;
|
|
218
218
|
|
|
219
|
+
/** Summary of a registered controller, its metadata, prefix, and handlers. */
|
|
220
|
+
interface TControllerOverview {
|
|
221
|
+
meta: TMoostMetadata;
|
|
222
|
+
computedPrefix: string;
|
|
223
|
+
type: TFunction;
|
|
224
|
+
handlers: THandlerOverview[];
|
|
225
|
+
}
|
|
226
|
+
/** Summary of a registered handler method within a controller. */
|
|
227
|
+
interface THandlerOverview {
|
|
228
|
+
meta: TMoostMetadata;
|
|
229
|
+
path?: string;
|
|
230
|
+
type: string;
|
|
231
|
+
method: string;
|
|
232
|
+
handler: TMoostHandler<TEmpty>;
|
|
233
|
+
registeredAs: {
|
|
234
|
+
path: string;
|
|
235
|
+
args: string[];
|
|
236
|
+
}[];
|
|
237
|
+
}
|
|
238
|
+
/** Hook points in the event handler lifecycle where context injectors are invoked. */
|
|
239
|
+
type TContextInjectorHook = 'Event:start' | 'Interceptors:init' | 'Arguments:resolve' | 'Interceptors:before' | 'Handler' | 'Interceptors:after';
|
|
240
|
+
|
|
219
241
|
type TDecoratorLevel = 'CLASS' | 'METHOD' | 'PROP' | 'PARAM';
|
|
220
242
|
|
|
221
243
|
/** Metadata context passed to pipe functions during argument/property resolution. */
|
|
@@ -257,28 +279,6 @@ interface TPipeData {
|
|
|
257
279
|
|
|
258
280
|
declare const resolvePipe: TPipeFn<TEmpty>;
|
|
259
281
|
|
|
260
|
-
/** Summary of a registered controller, its metadata, prefix, and handlers. */
|
|
261
|
-
interface TControllerOverview {
|
|
262
|
-
meta: TMoostMetadata;
|
|
263
|
-
computedPrefix: string;
|
|
264
|
-
type: TFunction;
|
|
265
|
-
handlers: THandlerOverview[];
|
|
266
|
-
}
|
|
267
|
-
/** Summary of a registered handler method within a controller. */
|
|
268
|
-
interface THandlerOverview {
|
|
269
|
-
meta: TMoostMetadata;
|
|
270
|
-
path?: string;
|
|
271
|
-
type: string;
|
|
272
|
-
method: string;
|
|
273
|
-
handler: TMoostHandler<TEmpty>;
|
|
274
|
-
registeredAs: {
|
|
275
|
-
path: string;
|
|
276
|
-
args: string[];
|
|
277
|
-
}[];
|
|
278
|
-
}
|
|
279
|
-
/** Hook points in the event handler lifecycle where context injectors are invoked. */
|
|
280
|
-
type TContextInjectorHook = 'Event:start' | 'Interceptors:init' | 'Arguments:resolve' | 'Interceptors:before' | 'Handler' | 'Interceptors:after';
|
|
281
|
-
|
|
282
282
|
type TInterceptorBeforeFn = (reply: (response: TAny) => void) => void | Promise<void>;
|
|
283
283
|
type TInterceptorAfterFn = (response: TAny, reply: (response: TAny) => void) => void | Promise<void>;
|
|
284
284
|
type TInterceptorErrorFn = (error: Error, reply: (response: TAny) => void) => void | Promise<void>;
|
|
@@ -412,6 +412,19 @@ interface TCommonMoostMeta {
|
|
|
412
412
|
type?: TFunction;
|
|
413
413
|
}
|
|
414
414
|
|
|
415
|
+
/** Infact `customData` of a moost resolution: the pipes its params and props resolve through. */
|
|
416
|
+
interface TMoostInfactCustom {
|
|
417
|
+
pipes?: TPipeData[];
|
|
418
|
+
}
|
|
419
|
+
/**
|
|
420
|
+
* The moost DI container. A direct scope (un)registration of the current event's own scope
|
|
421
|
+
* keeps its on-demand registration state in step (see `syncEventScope`).
|
|
422
|
+
*/
|
|
423
|
+
declare class MoostInfact extends Infact<TMoostMetadata, TMoostMetadata, TMoostParamsMetadata, TMoostInfactCustom> {
|
|
424
|
+
registerScope(scopeId: string | symbol): void;
|
|
425
|
+
unregisterScope(scopeId: string | symbol): void;
|
|
426
|
+
}
|
|
427
|
+
|
|
415
428
|
interface TInfactLoggingOptions {
|
|
416
429
|
newInstance?: true | false | 'FOR_EVENT' | 'SINGLETON';
|
|
417
430
|
warn?: true | false;
|
|
@@ -420,7 +433,7 @@ interface TInfactLoggingOptions {
|
|
|
420
433
|
/** Configures which Infact DI events are logged (instance creation, warnings, errors). */
|
|
421
434
|
declare function setInfactLoggingOptions(options: TInfactLoggingOptions): void;
|
|
422
435
|
/** Returns the shared Infact DI container used by Moost for dependency injection. */
|
|
423
|
-
declare function getMoostInfact():
|
|
436
|
+
declare function getMoostInfact(): MoostInfact;
|
|
424
437
|
/**
|
|
425
438
|
* Every SINGLETON instance currently held by an Infact container's **global**
|
|
426
439
|
* registry (per-event `scopes` registries are excluded — those instances are
|
|
@@ -431,9 +444,6 @@ declare function getMoostInfact(): Infact<TMoostMetadata<TEmpty>, TMoostMetadata
|
|
|
431
444
|
* (`Moost.dispose()`, the `@moostjs/vite` dev plugin) do not each re-derive it.
|
|
432
445
|
*/
|
|
433
446
|
declare function getInfactSingletonInstances(infact?: ReturnType<typeof getMoostInfact>): object[];
|
|
434
|
-
interface TCustom {
|
|
435
|
-
pipes?: TPipeData[];
|
|
436
|
-
}
|
|
437
447
|
/**
|
|
438
448
|
* Define global scope name to be used with `@InjectFromScope` and `@InjectScopeVars` decorators
|
|
439
449
|
*
|
|
@@ -451,7 +461,7 @@ declare function getInfactScopeVars<T extends object>(name: string | symbol): T
|
|
|
451
461
|
/**
|
|
452
462
|
* Get Infact instance (used for Dependency Injections)
|
|
453
463
|
*/
|
|
454
|
-
declare function getNewMoostInfact():
|
|
464
|
+
declare function getNewMoostInfact(): MoostInfact;
|
|
455
465
|
|
|
456
466
|
/**
|
|
457
467
|
* `fatal-capable` findings may reject `init()` (only non-optional constructor
|
|
@@ -777,12 +787,17 @@ declare class Moost extends Hookable {
|
|
|
777
787
|
* - before the hook pass starts (including from a controller constructor
|
|
778
788
|
* during binding) — queued;
|
|
779
789
|
* - while the pass runs (from another hook) — runs later in the same pass;
|
|
780
|
-
* - after the pass finished — runs immediately (asynchronously, in its
|
|
781
|
-
* init context)
|
|
790
|
+
* - after the pass finished — runs once, immediately (asynchronously, in its
|
|
791
|
+
* own init context) and is NOT stored, so it does not run again on
|
|
792
|
+
* re-init and per-request callers (`FOR_EVENT` constructors) do not grow
|
|
793
|
+
* the hook list. A failure is logged, since there is no `init()` left to
|
|
782
794
|
* reject.
|
|
783
795
|
*
|
|
784
|
-
* No de-duplication: registering the same function twice runs it twice
|
|
785
|
-
*
|
|
796
|
+
* No de-duplication: registering the same function twice runs it twice
|
|
797
|
+
* (per-request callers should guard non-idempotent work themselves). Hooks
|
|
798
|
+
* registered before or during a pass re-run on re-init exactly like
|
|
799
|
+
* `@MoostInit` hooks; to get a hook on every future init, register it
|
|
800
|
+
* before `init()`.
|
|
786
801
|
* @since 0.6.46
|
|
787
802
|
*/
|
|
788
803
|
addInitHook(fn: (app: this) => unknown, opts?: {
|
|
@@ -1301,24 +1316,24 @@ interface TInterceptorEntry {
|
|
|
1301
1316
|
/** Pre-computed span name for ci.with(). */
|
|
1302
1317
|
spanName: string;
|
|
1303
1318
|
}
|
|
1319
|
+
/** A registered after/onError hook of one event. */
|
|
1320
|
+
interface TRegisteredHook<F> {
|
|
1321
|
+
/** Pre-computed span name for ci.with(). */
|
|
1322
|
+
spanName: string;
|
|
1323
|
+
fn: F;
|
|
1324
|
+
}
|
|
1304
1325
|
/**
|
|
1305
1326
|
* Manages the before/after/error interceptor lifecycle for a single event.
|
|
1306
1327
|
* Optimised for the common sync path — only allocates promises when an interceptor goes async.
|
|
1307
1328
|
*/
|
|
1308
1329
|
declare class InterceptorHandler {
|
|
1309
|
-
protected
|
|
1310
|
-
|
|
1311
|
-
protected after: {
|
|
1312
|
-
name: string;
|
|
1313
|
-
fn: TInterceptorAfterFn;
|
|
1314
|
-
}[] | undefined;
|
|
1315
|
-
protected onError: {
|
|
1316
|
-
name: string;
|
|
1317
|
-
fn: TInterceptorErrorFn;
|
|
1318
|
-
}[] | undefined;
|
|
1330
|
+
protected after: TRegisteredHook<TInterceptorAfterFn>[] | undefined;
|
|
1331
|
+
protected onError: TRegisteredHook<TInterceptorErrorFn>[] | undefined;
|
|
1319
1332
|
response?: unknown;
|
|
1320
1333
|
responseOverwritten: boolean;
|
|
1321
1334
|
protected _boundReplyFn?: (reply: unknown) => void;
|
|
1335
|
+
protected handlers: TInterceptorEntry[];
|
|
1336
|
+
constructor(handlers: TInterceptorEntry[]);
|
|
1322
1337
|
protected getReplyFn(): (reply: unknown) => void;
|
|
1323
1338
|
get count(): number;
|
|
1324
1339
|
get countAfter(): number;
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ContextInjector, EventContext, cached, cached as cached$1, createEventContext, createEventContext as createEventContext$1, current, current as current$1, eventTypeKey, getContextInjector, getContextInjector as getContextInjector$1, key, key as key$1, replaceContextInjector, resetContextInjector, run, run as run$1, useLogger, useLogger as useLogger$1, useRouteParams } from "@wooksjs/event-core";
|
|
1
|
+
import { ContextInjector, EventContext, cached, cached as cached$1, createEventContext, createEventContext as createEventContext$1, current, current as current$1, eventTypeKey, getContextInjector, getContextInjector as getContextInjector$1, key, key as key$1, replaceContextInjector, resetContextInjector, run, run as run$1, tryGetCurrent, useLogger, useLogger as useLogger$1, useRouteParams } from "@wooksjs/event-core";
|
|
2
2
|
import { Mate, getConstructor, getConstructor as getConstructor$1, isConstructor, isConstructor as isConstructor$1 } from "@prostojs/mate";
|
|
3
3
|
import { ProstoLogger, ProstoLogger as ProstoLogger$1, coloredConsole, createConsoleTransort } from "@prostojs/logger";
|
|
4
4
|
import { Infact, createProvideRegistry, createProvideRegistry as createProvideRegistry$1, createReplaceRegistry, createReplaceRegistry as createReplaceRegistry$1, getClassKey, getClassKey as getClassKey$1 } from "@prostojs/infact";
|
|
@@ -47,7 +47,7 @@ let stamped = false;
|
|
|
47
47
|
if (stamped) return;
|
|
48
48
|
stamped = true;
|
|
49
49
|
stampModuleIdentity({
|
|
50
|
-
version: "0.6.
|
|
50
|
+
version: "0.6.48",
|
|
51
51
|
path: typeof __filename === "string" ? __filename : import.meta.url
|
|
52
52
|
});
|
|
53
53
|
}
|
|
@@ -123,7 +123,7 @@ function getDefaultLogger(topic) {
|
|
|
123
123
|
|
|
124
124
|
//#endregion
|
|
125
125
|
//#region packages/moost/src/event-scope.ts
|
|
126
|
-
function _define_property$
|
|
126
|
+
function _define_property$1(obj, key, value) {
|
|
127
127
|
if (key in obj) Object.defineProperty(obj, key, {
|
|
128
128
|
value,
|
|
129
129
|
enumerable: true,
|
|
@@ -142,13 +142,64 @@ function nextScopeId() {
|
|
|
142
142
|
}
|
|
143
143
|
return `__moost_${_scopeChar}_${++_scopeNum}`;
|
|
144
144
|
}
|
|
145
|
-
const
|
|
145
|
+
const eventScopeSlot = cached$1(() => ({
|
|
146
|
+
id: nextScopeId(),
|
|
147
|
+
held: false,
|
|
148
|
+
registered: false
|
|
149
|
+
}));
|
|
150
|
+
/**
|
|
151
|
+
* The DI scope of an event (see {@link useScopeId}) — cached on the event context itself.
|
|
152
|
+
* @internal
|
|
153
|
+
*/ const getEventScope = (ctx) => (ctx ?? current$1()).getOwn(eventScopeSlot);
|
|
146
154
|
/**
|
|
147
155
|
* Composable returning the moost DI scope ID of the current event. Generated on first call
|
|
148
156
|
* and cached on the event context itself — never inherited from a parent context, so a child
|
|
149
157
|
* event (a workflow run started with `eventContext`, a WebSocket message) owns its scope
|
|
150
158
|
* instead of sharing, and later releasing, its parent's.
|
|
151
|
-
*/ const useScopeId = (ctx) => (ctx
|
|
159
|
+
*/ const useScopeId = (ctx) => getEventScope(ctx).id;
|
|
160
|
+
/**
|
|
161
|
+
* Holds the event scope for a handler lifecycle — registering it, deferred to the first
|
|
162
|
+
* `FOR_EVENT` resolution (see {@link resolveEventScopeId}). Returns the release, which drops
|
|
163
|
+
* the scope like the release of an eager registration.
|
|
164
|
+
* @internal
|
|
165
|
+
*/ function holdEventScopeLazily(scope) {
|
|
166
|
+
scope.held = true;
|
|
167
|
+
return () => {
|
|
168
|
+
scope.held = false;
|
|
169
|
+
if (scope.registered) {
|
|
170
|
+
scope.registered = false;
|
|
171
|
+
getMoostInfact().unregisterScope(scope.id);
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* The scope id a `FOR_EVENT` resolution in the current event uses: a held scope is registered
|
|
177
|
+
* in the DI container now, on first use.
|
|
178
|
+
* @internal
|
|
179
|
+
*/ function resolveEventScopeId() {
|
|
180
|
+
const scope = getEventScope();
|
|
181
|
+
if (scope.held && !scope.registered) {
|
|
182
|
+
scope.registered = true;
|
|
183
|
+
getMoostInfact().registerScope(scope.id);
|
|
184
|
+
}
|
|
185
|
+
return scope.id;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Keeps the current event's scope state in step with a direct `registerScope` /
|
|
189
|
+
* `unregisterScope` of its id on the moost DI container — `registerEventScope(useScopeId())`,
|
|
190
|
+
* or an adapter's `cleanup: () => getMoostInfact().unregisterScope(useScopeId())`. As with an
|
|
191
|
+
* eager registration: a registered scope is dropped with the handler lifecycle, and an
|
|
192
|
+
* unregistered one stays gone for the rest of the lifecycle (a later `FOR_EVENT` resolution
|
|
193
|
+
* fails instead of registering it again — and leaking it, when nothing releases it after).
|
|
194
|
+
* @internal
|
|
195
|
+
*/ function syncEventScope(scopeId, registered) {
|
|
196
|
+
const ctx = tryGetCurrent();
|
|
197
|
+
const scope = ctx?.hasOwn(eventScopeSlot) ? ctx.getOwn(eventScopeSlot) : void 0;
|
|
198
|
+
if (scope?.id === scopeId) {
|
|
199
|
+
scope.registered = registered;
|
|
200
|
+
if (!registered) scope.held = false;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
152
203
|
/** Registers a DI scope for the given ID and returns an unscope function. */ function registerEventScope(scopeId) {
|
|
153
204
|
const infact = getMoostInfact();
|
|
154
205
|
infact.registerScope(scopeId);
|
|
@@ -168,7 +219,7 @@ const NO_ISOLATION = /* @__PURE__ */ new Set();
|
|
|
168
219
|
super({
|
|
169
220
|
logger: parent.logger,
|
|
170
221
|
parent
|
|
171
|
-
}), _define_property$
|
|
222
|
+
}), _define_property$1(this, "isolated", void 0), this.isolated = isolated;
|
|
172
223
|
}
|
|
173
224
|
};
|
|
174
225
|
/**
|
|
@@ -221,7 +272,7 @@ const NO_ISOLATION = /* @__PURE__ */ new Set();
|
|
|
221
272
|
ctx: child
|
|
222
273
|
});
|
|
223
274
|
if (opts?.shareScope !== false) {
|
|
224
|
-
child.setOwn(
|
|
275
|
+
child.setOwn(eventScopeSlot, getEventScope(parent));
|
|
225
276
|
return run$1(child, fn);
|
|
226
277
|
}
|
|
227
278
|
const release = registerEventScope(useScopeId(child));
|
|
@@ -346,6 +397,22 @@ const moostMate = new Mate(METADATA_WORKSPACE, {
|
|
|
346
397
|
return moostMate;
|
|
347
398
|
}
|
|
348
399
|
|
|
400
|
+
//#endregion
|
|
401
|
+
//#region packages/moost/src/metadata/moost-infact.ts
|
|
402
|
+
/**
|
|
403
|
+
* The moost DI container. A direct scope (un)registration of the current event's own scope
|
|
404
|
+
* keeps its on-demand registration state in step (see `syncEventScope`).
|
|
405
|
+
*/ var MoostInfact = class extends Infact {
|
|
406
|
+
registerScope(scopeId) {
|
|
407
|
+
super.registerScope(scopeId);
|
|
408
|
+
syncEventScope(scopeId, true);
|
|
409
|
+
}
|
|
410
|
+
unregisterScope(scopeId) {
|
|
411
|
+
super.unregisterScope(scopeId);
|
|
412
|
+
syncEventScope(scopeId, false);
|
|
413
|
+
}
|
|
414
|
+
};
|
|
415
|
+
|
|
349
416
|
//#endregion
|
|
350
417
|
//#region packages/moost/src/metadata/infact.ts
|
|
351
418
|
const sharedMoostInfact = getNewMoostInfact();
|
|
@@ -457,7 +524,7 @@ function formatNewInstanceArg(a) {
|
|
|
457
524
|
/**
|
|
458
525
|
* Get Infact instance (used for Dependency Injections)
|
|
459
526
|
*/ function getNewMoostInfact() {
|
|
460
|
-
return new
|
|
527
|
+
return new MoostInfact({
|
|
461
528
|
describeClass(classConstructor) {
|
|
462
529
|
const meta = getMoostMate().read(classConstructor);
|
|
463
530
|
return {
|
|
@@ -466,7 +533,7 @@ function formatNewInstanceArg(a) {
|
|
|
466
533
|
constructorParams: meta?.params || [],
|
|
467
534
|
provide: meta?.provide,
|
|
468
535
|
properties: meta?.properties || [],
|
|
469
|
-
scopeId: meta?.injectable === "FOR_EVENT" ?
|
|
536
|
+
scopeId: meta?.injectable === "FOR_EVENT" ? resolveEventScopeId() : void 0
|
|
470
537
|
};
|
|
471
538
|
},
|
|
472
539
|
resolveParam({ paramMeta, customData, classConstructor, index, scopeId, instantiate }) {
|
|
@@ -518,19 +585,27 @@ const registry = (_g = globalThis).__moost_keys ?? (_g.__moost_keys = /* @__PURE
|
|
|
518
585
|
|
|
519
586
|
//#endregion
|
|
520
587
|
//#region packages/moost/src/composables/controller.composable.ts
|
|
521
|
-
const
|
|
522
|
-
const controllerMethodKey = globalKey("controller.method");
|
|
523
|
-
const controllerRouteKey = globalKey("controller.route");
|
|
524
|
-
const controllerPrefixKey = globalKey("controller.prefix");
|
|
588
|
+
const controllerContextKey = globalKey("controller.context");
|
|
525
589
|
/**
|
|
526
590
|
* Sets the controller context for the current event scope.
|
|
527
591
|
* Called internally by adapters when dispatching events to handlers.
|
|
528
592
|
*/ function setControllerContext(controller, method, route, opts) {
|
|
529
593
|
const _ctx = opts?.ctx || current$1();
|
|
530
|
-
|
|
531
|
-
_ctx.
|
|
532
|
-
_ctx.set(
|
|
533
|
-
|
|
594
|
+
let prefix = opts?.prefix;
|
|
595
|
+
if (prefix === void 0 && _ctx.has(controllerContextKey)) prefix = _ctx.get(controllerContextKey).prefix;
|
|
596
|
+
_ctx.set(controllerContextKey, {
|
|
597
|
+
instance: controller,
|
|
598
|
+
method,
|
|
599
|
+
route,
|
|
600
|
+
prefix
|
|
601
|
+
});
|
|
602
|
+
}
|
|
603
|
+
/** Reads the controller context; throws the per-field "not set" error when there is none. */ function readControllerContext(ctx, field) {
|
|
604
|
+
try {
|
|
605
|
+
return ctx.get(controllerContextKey);
|
|
606
|
+
} catch {
|
|
607
|
+
throw new Error(`Key "controller.${field}" is not set`);
|
|
608
|
+
}
|
|
534
609
|
}
|
|
535
610
|
/** Brands already warned about by {@link brandedAdapterFor} (one warning per process). */ const reportedAdapterCopies = /* @__PURE__ */ new Set();
|
|
536
611
|
/**
|
|
@@ -554,10 +629,14 @@ const controllerPrefixKey = globalKey("controller.prefix");
|
|
|
554
629
|
* Returns utilities for accessing the controller instance, method metadata, and DI.
|
|
555
630
|
*/ function useControllerContext(ctx) {
|
|
556
631
|
const _ctx = ctx || current$1();
|
|
557
|
-
const getController = () => _ctx.
|
|
558
|
-
const getMethod = () => _ctx.
|
|
559
|
-
const getRoute = () => _ctx.
|
|
560
|
-
const getPrefix = () =>
|
|
632
|
+
const getController = () => readControllerContext(_ctx, "instance").instance;
|
|
633
|
+
const getMethod = () => readControllerContext(_ctx, "method").method;
|
|
634
|
+
const getRoute = () => readControllerContext(_ctx, "route").route;
|
|
635
|
+
const getPrefix = () => {
|
|
636
|
+
const { prefix } = readControllerContext(_ctx, "prefix");
|
|
637
|
+
if (prefix === void 0) throw new Error("Key \"controller.prefix\" is not set");
|
|
638
|
+
return prefix;
|
|
639
|
+
};
|
|
561
640
|
const getControllerMeta = () => getMoostMate().read(getController());
|
|
562
641
|
const getMethodMeta = (name) => getMoostMate().read(getController(), name || getMethod());
|
|
563
642
|
function instantiate(c) {
|
|
@@ -601,13 +680,30 @@ const interceptResultKey = globalKey("interceptor.result");
|
|
|
601
680
|
//#region packages/moost/src/adapter-utils.ts
|
|
602
681
|
const noop = () => {};
|
|
603
682
|
/**
|
|
604
|
-
*
|
|
605
|
-
*
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
683
|
+
* The hook options of one event. `logger` is a prototype getter: the topic logger is only
|
|
684
|
+
* derived when a hook reads it (an own accessor property would deopt the object instead).
|
|
685
|
+
*/ let EventHookOptions = class EventHookOptions {
|
|
686
|
+
get logger() {
|
|
687
|
+
return this._getLogger();
|
|
688
|
+
}
|
|
689
|
+
constructor(scopeId, unscope, method, getResponse, reply, getLogger) {
|
|
690
|
+
this.scopeId = scopeId;
|
|
691
|
+
this.unscope = unscope;
|
|
692
|
+
this.method = method;
|
|
693
|
+
this.getResponse = getResponse;
|
|
694
|
+
this.reply = reply;
|
|
695
|
+
this._getLogger = getLogger;
|
|
696
|
+
}
|
|
697
|
+
};
|
|
698
|
+
/**
|
|
699
|
+
* Holds an event's DI scope (registered on demand, see `holdEventScopeLazily`) by its handler
|
|
700
|
+
* lifecycle and, with `adapterHolds`, by the adapter too. Each release is idempotent; the
|
|
701
|
+
* scope is dropped once every holder let go, so an adapter signal that fires early (a client
|
|
702
|
+
* disconnect mid-handler) cannot pull the scope from under a running handler. Built outside
|
|
703
|
+
* the handler closure so a long-lived adapter listener (the response 'close' of a streamed
|
|
704
|
+
* body) retains only the scope.
|
|
705
|
+
*/ function holdEventScope(scope, adapterHolds) {
|
|
706
|
+
const drop = holdEventScopeLazily(scope);
|
|
611
707
|
let holders = adapterHolds ? 2 : 1;
|
|
612
708
|
const hold = () => {
|
|
613
709
|
let held = true;
|
|
@@ -633,7 +729,6 @@ const noop = () => {};
|
|
|
633
729
|
* Handles scope registration, controller resolution, interceptors, argument resolution,
|
|
634
730
|
* handler invocation, and cleanup — optimised for sync-first execution.
|
|
635
731
|
*/ function defineMoostEventHandler(options) {
|
|
636
|
-
const ci = getContextInjector$1();
|
|
637
732
|
const manualUnscope = !!options.manualUnscope;
|
|
638
733
|
const handlerSpanName = `Handler:${options.targetPath}`;
|
|
639
734
|
const handlerAttrs = {
|
|
@@ -641,21 +736,17 @@ const noop = () => {};
|
|
|
641
736
|
"moost.controller": options.controllerName || ""
|
|
642
737
|
};
|
|
643
738
|
return () => {
|
|
739
|
+
const ci = getContextInjector$1();
|
|
644
740
|
const ctx = current$1();
|
|
645
|
-
const
|
|
646
|
-
const
|
|
647
|
-
const { unscope, releaseLifecycle, failLifecycle } = holdEventScope(
|
|
741
|
+
const scope = getEventScope(ctx);
|
|
742
|
+
const scopeId = scope.id;
|
|
743
|
+
const { unscope, releaseLifecycle, failLifecycle } = holdEventScope(scope, manualUnscope);
|
|
648
744
|
let response;
|
|
745
|
+
let logger;
|
|
746
|
+
const getLogger = () => logger ?? (logger = useLogger$1(options.loggerTitle, ctx));
|
|
649
747
|
let hookOptions;
|
|
650
748
|
function getHookOptions() {
|
|
651
|
-
return hookOptions ?? (hookOptions =
|
|
652
|
-
scopeId,
|
|
653
|
-
logger,
|
|
654
|
-
unscope,
|
|
655
|
-
method: options.controllerMethod,
|
|
656
|
-
getResponse: () => response,
|
|
657
|
-
reply: (r) => response = r
|
|
658
|
-
});
|
|
749
|
+
return hookOptions ?? (hookOptions = new EventHookOptions(scopeId, unscope, options.controllerMethod, () => response, (r) => response = r, getLogger));
|
|
659
750
|
}
|
|
660
751
|
let interceptorHandler;
|
|
661
752
|
let raise = false;
|
|
@@ -693,7 +784,7 @@ const noop = () => {};
|
|
|
693
784
|
response = initResult;
|
|
694
785
|
if (response !== void 0) return cleanup();
|
|
695
786
|
} catch (error) {
|
|
696
|
-
if (options.logErrors)
|
|
787
|
+
if (options.logErrors) getLogger().error(String(error));
|
|
697
788
|
response = error;
|
|
698
789
|
raise = true;
|
|
699
790
|
return cleanup();
|
|
@@ -710,7 +801,7 @@ const noop = () => {};
|
|
|
710
801
|
}, handleError);
|
|
711
802
|
args = argsResult;
|
|
712
803
|
} catch (error) {
|
|
713
|
-
if (options.logErrors)
|
|
804
|
+
if (options.logErrors) getLogger().error(String(error));
|
|
714
805
|
response = error;
|
|
715
806
|
raise = true;
|
|
716
807
|
return cleanup();
|
|
@@ -725,21 +816,21 @@ const noop = () => {};
|
|
|
725
816
|
response = r;
|
|
726
817
|
return cleanup();
|
|
727
818
|
}, (error) => {
|
|
728
|
-
if (options.logErrors)
|
|
819
|
+
if (options.logErrors) getLogger().error(error);
|
|
729
820
|
response = error;
|
|
730
821
|
raise = true;
|
|
731
822
|
return cleanup();
|
|
732
823
|
});
|
|
733
824
|
response = handlerResult;
|
|
734
825
|
} catch (error) {
|
|
735
|
-
if (options.logErrors)
|
|
826
|
+
if (options.logErrors) getLogger().error(error);
|
|
736
827
|
response = error;
|
|
737
828
|
raise = true;
|
|
738
829
|
}
|
|
739
830
|
return cleanup();
|
|
740
831
|
}
|
|
741
832
|
function handleError(error) {
|
|
742
|
-
if (options.logErrors)
|
|
833
|
+
if (options.logErrors) getLogger().error(String(error));
|
|
743
834
|
response = error;
|
|
744
835
|
raise = true;
|
|
745
836
|
return cleanup();
|
|
@@ -753,7 +844,7 @@ const noop = () => {};
|
|
|
753
844
|
if (raise && response !== raisedResponse) raise = false;
|
|
754
845
|
return finalize();
|
|
755
846
|
}, (error) => {
|
|
756
|
-
if (options.logErrors)
|
|
847
|
+
if (options.logErrors) getLogger().error(String(error));
|
|
757
848
|
throw error;
|
|
758
849
|
});
|
|
759
850
|
response = afterResult;
|
|
@@ -1133,10 +1224,14 @@ function ImportController(prefix, controller, provide) {
|
|
|
1133
1224
|
*/ function Resolve(resolver, label) {
|
|
1134
1225
|
return (target, key, index) => {
|
|
1135
1226
|
const i = typeof index === "number" ? index : void 0;
|
|
1227
|
+
let labelFilled = false;
|
|
1136
1228
|
getMoostMate().decorate("resolver", (metas, level) => {
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1229
|
+
if (!labelFilled) {
|
|
1230
|
+
labelFilled = true;
|
|
1231
|
+
let newLabel = label;
|
|
1232
|
+
if (!newLabel && level === "PROP" && typeof metas.key === "string") newLabel = metas.key;
|
|
1233
|
+
fillLabel(target, key || "", i, newLabel);
|
|
1234
|
+
}
|
|
1140
1235
|
return resolver(metas, level);
|
|
1141
1236
|
})(target, key, i);
|
|
1142
1237
|
};
|
|
@@ -1607,6 +1702,7 @@ const sharedPipes = [{
|
|
|
1607
1702
|
|
|
1608
1703
|
//#endregion
|
|
1609
1704
|
//#region packages/moost/src/resolve-arguments.ts
|
|
1705
|
+
/** `metas.instantiate` of a handler argument: resolves through the current controller's DI. */ const instantiateFromController = (t) => useControllerContext().instantiate(t);
|
|
1610
1706
|
/**
|
|
1611
1707
|
* Builds an argument-resolver function from pre-computed per-parameter pipe lists.
|
|
1612
1708
|
*
|
|
@@ -1615,21 +1711,25 @@ const sharedPipes = [{
|
|
|
1615
1711
|
* `unknown[]` synchronously when possible, or `Promise<unknown[]>` otherwise.
|
|
1616
1712
|
*/ function resolveArguments(argsPipes, context) {
|
|
1617
1713
|
if (argsPipes.length === 0) return;
|
|
1714
|
+
const params = argsPipes.map(({ meta: paramMeta, pipes }, index) => ({
|
|
1715
|
+
pipes,
|
|
1716
|
+
metas: {
|
|
1717
|
+
classMeta: context.classMeta,
|
|
1718
|
+
methodMeta: context.methodMeta,
|
|
1719
|
+
paramMeta,
|
|
1720
|
+
type: context.type,
|
|
1721
|
+
key: context.key,
|
|
1722
|
+
index,
|
|
1723
|
+
targetMeta: paramMeta,
|
|
1724
|
+
instantiate: instantiateFromController
|
|
1725
|
+
}
|
|
1726
|
+
}));
|
|
1618
1727
|
return () => {
|
|
1619
1728
|
const args = [];
|
|
1620
1729
|
let hasAsync = false;
|
|
1621
|
-
for (let i = 0; i <
|
|
1622
|
-
const { pipes,
|
|
1623
|
-
const result = runPipes(pipes, void 0,
|
|
1624
|
-
classMeta: context.classMeta,
|
|
1625
|
-
methodMeta: context.methodMeta,
|
|
1626
|
-
paramMeta,
|
|
1627
|
-
type: context.type,
|
|
1628
|
-
key: context.key,
|
|
1629
|
-
index: i,
|
|
1630
|
-
targetMeta: paramMeta,
|
|
1631
|
-
instantiate: (t) => useControllerContext().instantiate(t)
|
|
1632
|
-
}, "PARAM");
|
|
1730
|
+
for (let i = 0; i < params.length; i++) {
|
|
1731
|
+
const { pipes, metas } = params[i];
|
|
1732
|
+
const result = runPipes(pipes, void 0, metas, "PARAM");
|
|
1633
1733
|
if (!hasAsync && isThenable(result)) hasAsync = true;
|
|
1634
1734
|
args[i] = result;
|
|
1635
1735
|
}
|
|
@@ -1639,16 +1739,9 @@ const sharedPipes = [{
|
|
|
1639
1739
|
|
|
1640
1740
|
//#endregion
|
|
1641
1741
|
//#region packages/moost/src/interceptor-handler.ts
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
enumerable: true,
|
|
1646
|
-
configurable: true,
|
|
1647
|
-
writable: true
|
|
1648
|
-
});
|
|
1649
|
-
else obj[key] = value;
|
|
1650
|
-
return obj;
|
|
1651
|
-
}
|
|
1742
|
+
/** Span attributes of the interceptor stages — shared, never mutated. */ const BEFORE_STAGE = { "moost.interceptor.stage": "before" };
|
|
1743
|
+
const AFTER_STAGE = { "moost.interceptor.stage": "after" };
|
|
1744
|
+
const ON_ERROR_STAGE = { "moost.interceptor.stage": "onError" };
|
|
1652
1745
|
/**
|
|
1653
1746
|
* Manages the before/after/error interceptor lifecycle for a single event.
|
|
1654
1747
|
* Optimised for the common sync path — only allocates promises when an interceptor goes async.
|
|
@@ -1673,16 +1766,15 @@ function _define_property$1(obj, key, value) {
|
|
|
1673
1766
|
* Returns a pending PromiseLike if `before` went async, or undefined.
|
|
1674
1767
|
*/ registerDef(def, entry, ci) {
|
|
1675
1768
|
if (def.after) (this.after ?? (this.after = [])).unshift({
|
|
1676
|
-
|
|
1769
|
+
spanName: entry.spanName,
|
|
1677
1770
|
fn: def.after
|
|
1678
1771
|
});
|
|
1679
1772
|
if (def.error) (this.onError ?? (this.onError = [])).unshift({
|
|
1680
|
-
|
|
1773
|
+
spanName: entry.spanName,
|
|
1681
1774
|
fn: def.error
|
|
1682
1775
|
});
|
|
1683
1776
|
if (def.before) {
|
|
1684
|
-
const
|
|
1685
|
-
const result = ci ? ci.with(spanName, { "moost.interceptor.stage": "before" }, () => def.before?.(this.getReplyFn())) : def.before(this.getReplyFn());
|
|
1777
|
+
const result = ci ? ci.with(entry.spanName, BEFORE_STAGE, () => def.before?.(this.getReplyFn())) : def.before(this.getReplyFn());
|
|
1686
1778
|
if (isThenable(result)) return result;
|
|
1687
1779
|
}
|
|
1688
1780
|
}
|
|
@@ -1735,10 +1827,10 @@ function _define_property$1(obj, key, value) {
|
|
|
1735
1827
|
const handlers = isError ? this.onError : this.after;
|
|
1736
1828
|
if (!handlers) return this.response;
|
|
1737
1829
|
const ci = getContextInjector$1();
|
|
1738
|
-
const stage = isError ?
|
|
1830
|
+
const stage = isError ? ON_ERROR_STAGE : AFTER_STAGE;
|
|
1739
1831
|
for (let i = 0; i < handlers.length; i++) {
|
|
1740
|
-
const {
|
|
1741
|
-
const result = ci ? ci.with(
|
|
1832
|
+
const { spanName, fn } = handlers[i];
|
|
1833
|
+
const result = ci ? ci.with(spanName, stage, () => fn(response, this.getReplyFn())) : fn(response, this.getReplyFn());
|
|
1742
1834
|
if (isThenable(result)) return this._fireAfterAsync({
|
|
1743
1835
|
ci,
|
|
1744
1836
|
handlers,
|
|
@@ -1751,21 +1843,19 @@ function _define_property$1(obj, key, value) {
|
|
|
1751
1843
|
async _fireAfterAsync(ctx, pending, startIndex) {
|
|
1752
1844
|
await pending;
|
|
1753
1845
|
for (let i = startIndex + 1; i < ctx.handlers.length; i++) {
|
|
1754
|
-
const {
|
|
1755
|
-
if (ctx.ci) await ctx.ci.with(
|
|
1846
|
+
const { spanName, fn } = ctx.handlers[i];
|
|
1847
|
+
if (ctx.ci) await ctx.ci.with(spanName, ctx.stage, () => fn(ctx.response, this.getReplyFn()));
|
|
1756
1848
|
else await fn(ctx.response, this.getReplyFn());
|
|
1757
1849
|
}
|
|
1758
1850
|
return this.response;
|
|
1759
1851
|
}
|
|
1760
1852
|
constructor(handlers) {
|
|
1761
|
-
_define_property$1(this, "handlers", void 0);
|
|
1762
|
-
_define_property$1(this, "after", void 0);
|
|
1763
|
-
_define_property$1(this, "onError", void 0);
|
|
1764
|
-
_define_property$1(this, "response", void 0);
|
|
1765
|
-
_define_property$1(this, "responseOverwritten", void 0);
|
|
1766
|
-
_define_property$1(this, "_boundReplyFn", void 0);
|
|
1767
1853
|
this.handlers = handlers;
|
|
1854
|
+
this.after = void 0;
|
|
1855
|
+
this.onError = void 0;
|
|
1856
|
+
this.response = void 0;
|
|
1768
1857
|
this.responseOverwritten = false;
|
|
1858
|
+
this._boundReplyFn = void 0;
|
|
1769
1859
|
}
|
|
1770
1860
|
};
|
|
1771
1861
|
|
|
@@ -1773,6 +1863,7 @@ function _define_property$1(obj, key, value) {
|
|
|
1773
1863
|
//#region packages/moost/src/utils.ts
|
|
1774
1864
|
const mate = getMoostMate();
|
|
1775
1865
|
const noInterceptors = () => void 0;
|
|
1866
|
+
const isForEvent = (instance) => mate.read(instance)?.injectable === "FOR_EVENT";
|
|
1776
1867
|
function findInterceptorMethods(handler) {
|
|
1777
1868
|
const fakeInstance = Object.create(handler.prototype);
|
|
1778
1869
|
const methods = getInstanceOwnMethods(fakeInstance);
|
|
@@ -1811,6 +1902,8 @@ function callMethod(instance, methodName, resolveArgs) {
|
|
|
1811
1902
|
}
|
|
1812
1903
|
function createClassInterceptorFactory(opts) {
|
|
1813
1904
|
const infact = getMoostInfact();
|
|
1905
|
+
const customData = { pipes: opts.pipes };
|
|
1906
|
+
const defs = opts.cacheable ? /* @__PURE__ */ new WeakMap() : void 0;
|
|
1814
1907
|
function buildDef(instance) {
|
|
1815
1908
|
const def = {};
|
|
1816
1909
|
if (opts.methods.before) {
|
|
@@ -1843,9 +1936,21 @@ function createClassInterceptorFactory(opts) {
|
|
|
1843
1936
|
return def;
|
|
1844
1937
|
}
|
|
1845
1938
|
function fromTarget(targetInstance) {
|
|
1846
|
-
const
|
|
1847
|
-
if (
|
|
1848
|
-
|
|
1939
|
+
const cached = defs?.get(targetInstance);
|
|
1940
|
+
if (cached) return cached;
|
|
1941
|
+
const registries = infact.getInstanceRegistries(targetInstance);
|
|
1942
|
+
const result = infact.get(opts.handler, {
|
|
1943
|
+
provide: registries.provide || {},
|
|
1944
|
+
replace: registries.replace,
|
|
1945
|
+
customData
|
|
1946
|
+
});
|
|
1947
|
+
const remember = (instance) => {
|
|
1948
|
+
const def = buildDef(instance);
|
|
1949
|
+
if (defs && !isForEvent(instance) && !isForEvent(targetInstance)) defs.set(targetInstance, def);
|
|
1950
|
+
return def;
|
|
1951
|
+
};
|
|
1952
|
+
if (isThenable(result)) return result.then(remember);
|
|
1953
|
+
return remember(result);
|
|
1849
1954
|
}
|
|
1850
1955
|
return () => {
|
|
1851
1956
|
const result = opts.getTargetInstance();
|
|
@@ -1887,7 +1992,8 @@ function getIterceptorHandlerFactory(interceptors, getTargetInstance, pipes) {
|
|
|
1887
1992
|
methods,
|
|
1888
1993
|
resolvers,
|
|
1889
1994
|
getTargetInstance,
|
|
1890
|
-
pipes: mergedPipes
|
|
1995
|
+
pipes: mergedPipes,
|
|
1996
|
+
cacheable: classMeta.injectable !== "FOR_EVENT"
|
|
1891
1997
|
}),
|
|
1892
1998
|
name,
|
|
1893
1999
|
spanName
|
|
@@ -2386,12 +2492,17 @@ function _define_property(obj, key, value) {
|
|
|
2386
2492
|
* - before the hook pass starts (including from a controller constructor
|
|
2387
2493
|
* during binding) — queued;
|
|
2388
2494
|
* - while the pass runs (from another hook) — runs later in the same pass;
|
|
2389
|
-
* - after the pass finished — runs immediately (asynchronously, in its
|
|
2390
|
-
* init context)
|
|
2495
|
+
* - after the pass finished — runs once, immediately (asynchronously, in its
|
|
2496
|
+
* own init context) and is NOT stored, so it does not run again on
|
|
2497
|
+
* re-init and per-request callers (`FOR_EVENT` constructors) do not grow
|
|
2498
|
+
* the hook list. A failure is logged, since there is no `init()` left to
|
|
2391
2499
|
* reject.
|
|
2392
2500
|
*
|
|
2393
|
-
* No de-duplication: registering the same function twice runs it twice
|
|
2394
|
-
*
|
|
2501
|
+
* No de-duplication: registering the same function twice runs it twice
|
|
2502
|
+
* (per-request callers should guard non-idempotent work themselves). Hooks
|
|
2503
|
+
* registered before or during a pass re-run on re-init exactly like
|
|
2504
|
+
* `@MoostInit` hooks; to get a hook on every future init, register it
|
|
2505
|
+
* before `init()`.
|
|
2395
2506
|
* @since 0.6.46
|
|
2396
2507
|
*/ addInitHook(fn, opts) {
|
|
2397
2508
|
const hook = {
|
|
@@ -2399,10 +2510,13 @@ function _define_property(obj, key, value) {
|
|
|
2399
2510
|
priority: opts?.priority ?? 0,
|
|
2400
2511
|
fn
|
|
2401
2512
|
};
|
|
2513
|
+
if (this.initHookPhase === "done") {
|
|
2514
|
+
this.runInitHook(hook).catch((error) => {
|
|
2515
|
+
this.logger.error(`Late init hook failed: ${errorMessage(error)}`);
|
|
2516
|
+
});
|
|
2517
|
+
return;
|
|
2518
|
+
}
|
|
2402
2519
|
this.initHooks.push(hook);
|
|
2403
|
-
if (this.initHookPhase === "done") this.runInitHook(hook).catch((error) => {
|
|
2404
|
-
this.logger.error(`Late init hook failed: ${errorMessage(error)}`);
|
|
2405
|
-
});
|
|
2406
2520
|
}
|
|
2407
2521
|
/**
|
|
2408
2522
|
* ### dispose
|
|
@@ -2535,7 +2649,7 @@ function _define_property(obj, key, value) {
|
|
|
2535
2649
|
infact.setInstanceRegistries(instance, provide, replace, { pipes });
|
|
2536
2650
|
}
|
|
2537
2651
|
if (instance) this.singletonInstances.add(instance);
|
|
2538
|
-
const getInstance = instance ? () => instance :
|
|
2652
|
+
const getInstance = instance ? () => instance : () => infact.get(controller, infactOpts);
|
|
2539
2653
|
const classConstructor = isConstructor$1(controller) ? controller : getConstructor$1(controller);
|
|
2540
2654
|
const controllerOverview = await bindControllerMethods({
|
|
2541
2655
|
getInstance,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "moost",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.48",
|
|
4
4
|
"description": "moost",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"composables",
|
|
@@ -38,18 +38,18 @@
|
|
|
38
38
|
}
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@prostojs/infact": "^0.6.
|
|
41
|
+
"@prostojs/infact": "^0.6.1",
|
|
42
42
|
"@prostojs/logger": "^0.4.3",
|
|
43
|
-
"@prostojs/mate": "^0.5.
|
|
44
|
-
"@wooksjs/event-core": "^0.7.
|
|
43
|
+
"@prostojs/mate": "^0.5.1",
|
|
44
|
+
"@wooksjs/event-core": "^0.7.27",
|
|
45
45
|
"hookable": "^5.5.3",
|
|
46
|
-
"wooks": "^0.7.
|
|
46
|
+
"wooks": "^0.7.27"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
|
-
"@wooksjs/event-http": "^0.7.
|
|
50
|
-
"@wooksjs/http-body": "^0.7.
|
|
49
|
+
"@wooksjs/event-http": "^0.7.27",
|
|
50
|
+
"@wooksjs/http-body": "^0.7.27",
|
|
51
51
|
"vitest": "3.2.7",
|
|
52
|
-
"@moostjs/event-http": "^0.6.
|
|
52
|
+
"@moostjs/event-http": "^0.6.48"
|
|
53
53
|
},
|
|
54
54
|
"scripts": {
|
|
55
55
|
"pub": "pnpm publish --access public",
|