@ebarahona/loopback-transport-core 1.0.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/LICENSE +21 -0
- package/README.md +297 -0
- package/dist/client/client-proxy.d.ts +147 -0
- package/dist/client/client-proxy.js +225 -0
- package/dist/client/client-proxy.js.map +1 -0
- package/dist/client/index.d.ts +1 -0
- package/dist/client/index.js +18 -0
- package/dist/client/index.js.map +1 -0
- package/dist/context/execution-context.d.ts +102 -0
- package/dist/context/execution-context.js +110 -0
- package/dist/context/execution-context.js.map +1 -0
- package/dist/context/index.d.ts +1 -0
- package/dist/context/index.js +18 -0
- package/dist/context/index.js.map +1 -0
- package/dist/decorators/constants.d.ts +41 -0
- package/dist/decorators/constants.js +13 -0
- package/dist/decorators/constants.js.map +1 -0
- package/dist/decorators/event-handler.decorator.d.ts +28 -0
- package/dist/decorators/event-handler.decorator.js +42 -0
- package/dist/decorators/event-handler.decorator.js.map +1 -0
- package/dist/decorators/index.d.ts +4 -0
- package/dist/decorators/index.js +21 -0
- package/dist/decorators/index.js.map +1 -0
- package/dist/decorators/message-handler.decorator.d.ts +26 -0
- package/dist/decorators/message-handler.decorator.js +40 -0
- package/dist/decorators/message-handler.decorator.js.map +1 -0
- package/dist/decorators/payload.decorator.d.ts +30 -0
- package/dist/decorators/payload.decorator.js +42 -0
- package/dist/decorators/payload.decorator.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +42 -0
- package/dist/index.js.map +1 -0
- package/dist/interfaces/index.d.ts +4 -0
- package/dist/interfaces/index.js +21 -0
- package/dist/interfaces/index.js.map +1 -0
- package/dist/interfaces/message-handler.interface.d.ts +21 -0
- package/dist/interfaces/message-handler.interface.js +3 -0
- package/dist/interfaces/message-handler.interface.js.map +1 -0
- package/dist/interfaces/packet.interface.d.ts +42 -0
- package/dist/interfaces/packet.interface.js +3 -0
- package/dist/interfaces/packet.interface.js.map +1 -0
- package/dist/interfaces/transport-client.interface.d.ts +41 -0
- package/dist/interfaces/transport-client.interface.js +3 -0
- package/dist/interfaces/transport-client.interface.js.map +1 -0
- package/dist/interfaces/transport-server.interface.d.ts +44 -0
- package/dist/interfaces/transport-server.interface.js +3 -0
- package/dist/interfaces/transport-server.interface.js.map +1 -0
- package/dist/keys.d.ts +88 -0
- package/dist/keys.js +123 -0
- package/dist/keys.js.map +1 -0
- package/dist/registry/handler-registry.d.ts +77 -0
- package/dist/registry/handler-registry.js +265 -0
- package/dist/registry/handler-registry.js.map +1 -0
- package/dist/registry/index.d.ts +1 -0
- package/dist/registry/index.js +18 -0
- package/dist/registry/index.js.map +1 -0
- package/dist/serializers/index.d.ts +1 -0
- package/dist/serializers/index.js +18 -0
- package/dist/serializers/index.js.map +1 -0
- package/dist/serializers/serializer.interface.d.ts +62 -0
- package/dist/serializers/serializer.interface.js +52 -0
- package/dist/serializers/serializer.interface.js.map +1 -0
- package/dist/server/index.d.ts +1 -0
- package/dist/server/index.js +18 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/server-base.d.ts +154 -0
- package/dist/server/server-base.js +287 -0
- package/dist/server/server-base.js.map +1 -0
- package/dist/transport-booter.d.ts +31 -0
- package/dist/transport-booter.js +117 -0
- package/dist/transport-booter.js.map +1 -0
- package/dist/transport.component.d.ts +26 -0
- package/dist/transport.component.js +42 -0
- package/dist/transport.component.js.map +1 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +6 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/normalize-pattern.d.ts +18 -0
- package/dist/utils/normalize-pattern.js +75 -0
- package/dist/utils/normalize-pattern.js.map +1 -0
- package/package.json +73 -0
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.HandlerRegistry = void 0;
|
|
10
|
+
const core_1 = require("@loopback/core");
|
|
11
|
+
const crypto_1 = require("crypto");
|
|
12
|
+
const debug_1 = require("debug");
|
|
13
|
+
const rxjs_1 = require("rxjs");
|
|
14
|
+
const decorators_1 = require("../decorators");
|
|
15
|
+
const keys_1 = require("../keys");
|
|
16
|
+
const utils_1 = require("../utils");
|
|
17
|
+
const debug = (0, debug_1.default)('loopback:transport:registry');
|
|
18
|
+
/**
|
|
19
|
+
* Separator for registry keys. Uses double colon to avoid collision
|
|
20
|
+
* with colons that may appear inside JSON-stringified object patterns.
|
|
21
|
+
*/
|
|
22
|
+
const KEY_SEPARATOR = '::';
|
|
23
|
+
/**
|
|
24
|
+
* Discovers @messageHandler and @eventHandler decorated methods
|
|
25
|
+
* from controllers and registers them with the appropriate transport server.
|
|
26
|
+
*
|
|
27
|
+
* This class does NOT run in the constructor. It is invoked by
|
|
28
|
+
* TransportBooter after all controllers are registered.
|
|
29
|
+
*
|
|
30
|
+
* Handler invocations use per-message child contexts for concurrency
|
|
31
|
+
* safety. The application context is never mutated per-message.
|
|
32
|
+
*
|
|
33
|
+
* Context lifetime extends until the handler result (including Observable
|
|
34
|
+
* streams) fully completes, errors, or times out.
|
|
35
|
+
*/
|
|
36
|
+
let HandlerRegistry = class HandlerRegistry {
|
|
37
|
+
constructor() {
|
|
38
|
+
/**
|
|
39
|
+
* Registry keyed by `transport::pattern` to support the same pattern
|
|
40
|
+
* on different transports without collision.
|
|
41
|
+
*/
|
|
42
|
+
this.handlers = new Map();
|
|
43
|
+
this.discovered = false;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Scan all controllers in the application for transport decorators
|
|
47
|
+
* and register the handlers.
|
|
48
|
+
*
|
|
49
|
+
* Idempotent: clears previously discovered handlers before scanning.
|
|
50
|
+
*/
|
|
51
|
+
async discoverHandlers(app) {
|
|
52
|
+
this.handlers.clear();
|
|
53
|
+
this.discovered = false;
|
|
54
|
+
const controllerBindings = app.findByTag('controller');
|
|
55
|
+
debug('scanning %d controllers for transport handlers', controllerBindings.length);
|
|
56
|
+
for (const binding of controllerBindings) {
|
|
57
|
+
const controllerClass = binding.valueConstructor;
|
|
58
|
+
if (!controllerClass)
|
|
59
|
+
continue;
|
|
60
|
+
const bindingKey = binding.key;
|
|
61
|
+
this.scanMessageHandlers(controllerClass, bindingKey, app);
|
|
62
|
+
this.scanEventHandlers(controllerClass, bindingKey, app);
|
|
63
|
+
}
|
|
64
|
+
this.discovered = true;
|
|
65
|
+
debug('discovered %d transport handlers', this.handlers.size);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Bind discovered handlers to the registered transport servers.
|
|
69
|
+
* Throws if discovery has not been run.
|
|
70
|
+
*
|
|
71
|
+
* Handles precedence: transport-specific handlers override wildcard
|
|
72
|
+
* handlers for the same pattern on that transport's server.
|
|
73
|
+
*/
|
|
74
|
+
async bindToServers(app) {
|
|
75
|
+
if (!this.discovered) {
|
|
76
|
+
throw new Error('Cannot bind handlers to servers: discoverHandlers() has not been called.');
|
|
77
|
+
}
|
|
78
|
+
const serverBindings = app.findByTag(keys_1.TRANSPORT_SERVER_TAG);
|
|
79
|
+
for (const serverBinding of serverBindings) {
|
|
80
|
+
const server = await app.get(serverBinding.key);
|
|
81
|
+
const transportName = serverBinding.tagMap?.[keys_1.TRANSPORT_NAME_TAG];
|
|
82
|
+
// Collect handlers for this server.
|
|
83
|
+
// Precedence rules differ by handler type:
|
|
84
|
+
// - Request handlers: specific overrides wildcard (only one per pattern)
|
|
85
|
+
// - Event handlers: both specific and wildcard run (fan-out)
|
|
86
|
+
const boundRequestPatterns = new Set();
|
|
87
|
+
// First pass: transport-specific handlers
|
|
88
|
+
for (const [registryKey, handlers] of this.handlers) {
|
|
89
|
+
if (handlers[0].transport && handlers[0].transport === transportName) {
|
|
90
|
+
const pattern = this.extractPattern(registryKey);
|
|
91
|
+
for (const handler of handlers) {
|
|
92
|
+
server.addHandler(pattern, handler);
|
|
93
|
+
}
|
|
94
|
+
if (!handlers[0].isEventHandler) {
|
|
95
|
+
boundRequestPatterns.add(pattern);
|
|
96
|
+
}
|
|
97
|
+
debug('bound handler [%s] to transport [%s] (specific)', pattern, transportName);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
// Second pass: wildcard handlers
|
|
101
|
+
// - Request handlers: skip if transport-specific already bound
|
|
102
|
+
// - Event handlers: always bind (fan-out semantics)
|
|
103
|
+
for (const [registryKey, handlers] of this.handlers) {
|
|
104
|
+
if (!handlers[0].transport) {
|
|
105
|
+
const pattern = this.extractPattern(registryKey);
|
|
106
|
+
if (handlers[0].isEventHandler || !boundRequestPatterns.has(pattern)) {
|
|
107
|
+
for (const handler of handlers) {
|
|
108
|
+
server.addHandler(pattern, handler);
|
|
109
|
+
}
|
|
110
|
+
debug('bound handler [%s] to transport [%s] (wildcard)', pattern, transportName ?? 'default');
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Get all discovered handlers.
|
|
118
|
+
*/
|
|
119
|
+
getHandlers() {
|
|
120
|
+
const copy = new Map();
|
|
121
|
+
for (const [key, handlers] of this.handlers) {
|
|
122
|
+
copy.set(key, [...handlers]);
|
|
123
|
+
}
|
|
124
|
+
return copy;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Whether discovery has been run.
|
|
128
|
+
*/
|
|
129
|
+
isDiscovered() {
|
|
130
|
+
return this.discovered;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Build the registry key from transport and raw pattern.
|
|
134
|
+
* Normalizes the pattern (sorts object keys) before keying.
|
|
135
|
+
* Format: `transport::normalizedPattern` or `*::normalizedPattern`.
|
|
136
|
+
*/
|
|
137
|
+
buildKey(transport, pattern) {
|
|
138
|
+
return `${transport ?? '*'}${KEY_SEPARATOR}${(0, utils_1.normalizePattern)(pattern)}`;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Extract the pattern portion from a registry key.
|
|
142
|
+
*/
|
|
143
|
+
extractPattern(key) {
|
|
144
|
+
const separatorIndex = key.indexOf(KEY_SEPARATOR);
|
|
145
|
+
return separatorIndex >= 0
|
|
146
|
+
? key.slice(separatorIndex + KEY_SEPARATOR.length)
|
|
147
|
+
: key;
|
|
148
|
+
}
|
|
149
|
+
scanMessageHandlers(controllerClass, controllerBindingKey, app) {
|
|
150
|
+
this.scanHandlers(controllerClass, controllerBindingKey, app, decorators_1.MESSAGE_HANDLER_METADATA.key, false);
|
|
151
|
+
}
|
|
152
|
+
scanEventHandlers(controllerClass, controllerBindingKey, app) {
|
|
153
|
+
this.scanHandlers(controllerClass, controllerBindingKey, app, decorators_1.EVENT_HANDLER_METADATA.key, true);
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Shared scanner for both @messageHandler and @eventHandler metadata.
|
|
157
|
+
* The isEvent flag controls duplicate/chaining rules.
|
|
158
|
+
*/
|
|
159
|
+
scanHandlers(controllerClass, controllerBindingKey, app, metadataKey, isEvent) {
|
|
160
|
+
const methods = core_1.MetadataInspector.getAllMethodMetadata(metadataKey, controllerClass.prototype);
|
|
161
|
+
if (!methods)
|
|
162
|
+
return;
|
|
163
|
+
const decoratorName = isEvent ? '@eventHandler' : '@messageHandler';
|
|
164
|
+
for (const [methodName, metadata] of Object.entries(methods)) {
|
|
165
|
+
const key = this.buildKey(metadata.transport, metadata.pattern);
|
|
166
|
+
const existing = this.handlers.get(key);
|
|
167
|
+
// Reject mixed handler types on the same pattern
|
|
168
|
+
if (existing && existing[0].isEventHandler !== isEvent) {
|
|
169
|
+
throw new Error(`Cannot mix @messageHandler and @eventHandler for pattern: ${(0, utils_1.normalizePattern)(metadata.pattern)}. ` +
|
|
170
|
+
'A pattern must be exclusively request/response or event.');
|
|
171
|
+
}
|
|
172
|
+
// Reject duplicate request/response handlers
|
|
173
|
+
if (existing && !isEvent) {
|
|
174
|
+
throw new Error(`Duplicate @messageHandler for pattern: ${(0, utils_1.normalizePattern)(metadata.pattern)}. ` +
|
|
175
|
+
'Only one request/response handler per pattern is allowed.');
|
|
176
|
+
}
|
|
177
|
+
const handler = this.createHandler(controllerBindingKey, methodName, app);
|
|
178
|
+
handler.isEventHandler = isEvent;
|
|
179
|
+
handler.transport = metadata.transport;
|
|
180
|
+
handler.extras = metadata.extras;
|
|
181
|
+
if (existing) {
|
|
182
|
+
existing.push(handler);
|
|
183
|
+
debug('chained %s [%s] on %s.%s', decoratorName, (0, utils_1.normalizePattern)(metadata.pattern), controllerClass.name, methodName);
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
this.handlers.set(key, [handler]);
|
|
187
|
+
debug('discovered %s [%s] on %s.%s', decoratorName, (0, utils_1.normalizePattern)(metadata.pattern), controllerClass.name, methodName);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Create a handler function that invokes the controller method through
|
|
193
|
+
* LoopBack's native invocation pipeline.
|
|
194
|
+
*
|
|
195
|
+
* Each invocation creates a uniquely named child Context from the
|
|
196
|
+
* application context. Per-message bindings (payload, transport context)
|
|
197
|
+
* are scoped to the child context and cannot collide with concurrent
|
|
198
|
+
* messages.
|
|
199
|
+
*
|
|
200
|
+
* The child context lifetime extends until the handler result fully
|
|
201
|
+
* resolves. For Observable results, the context stays open until the
|
|
202
|
+
* Observable completes, errors, or times out.
|
|
203
|
+
*/
|
|
204
|
+
createHandler(controllerBindingKey, methodName, app) {
|
|
205
|
+
const handler = async (data, context) => {
|
|
206
|
+
const invocationCtx = new core_1.Context(app, `transport-invocation-${(0, crypto_1.randomUUID)()}`);
|
|
207
|
+
// Idempotent cleanup guard: Context.close() is synchronous but
|
|
208
|
+
// may be reached from multiple paths (error + teardown) for Observables
|
|
209
|
+
let closed = false;
|
|
210
|
+
const cleanup = () => {
|
|
211
|
+
if (!closed) {
|
|
212
|
+
closed = true;
|
|
213
|
+
invocationCtx.close();
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
try {
|
|
217
|
+
invocationCtx.bind(keys_1.TransportBindings.CURRENT_PAYLOAD).to(data);
|
|
218
|
+
invocationCtx.bind(keys_1.TransportBindings.CURRENT_CONTEXT).to(context);
|
|
219
|
+
const controller = await invocationCtx.get(controllerBindingKey);
|
|
220
|
+
const method = controller[methodName];
|
|
221
|
+
if (typeof method !== 'function') {
|
|
222
|
+
throw new Error(`Transport handler method "${methodName}" not found on controller "${controllerBindingKey}"`);
|
|
223
|
+
}
|
|
224
|
+
// Invoke through LoopBack's method invocation pipeline
|
|
225
|
+
// This honors parameter injection, interceptors, and other
|
|
226
|
+
// framework invocation semantics
|
|
227
|
+
const result = await (0, core_1.invokeMethod)(controller, methodName, invocationCtx, [data, context]);
|
|
228
|
+
// For Observable results, defer context cleanup until stream completes
|
|
229
|
+
if ((0, rxjs_1.isObservable)(result)) {
|
|
230
|
+
const obs = result;
|
|
231
|
+
return new rxjs_1.Observable(subscriber => {
|
|
232
|
+
const subscription = obs.subscribe({
|
|
233
|
+
next: value => subscriber.next(value),
|
|
234
|
+
error: err => {
|
|
235
|
+
subscriber.error(err);
|
|
236
|
+
cleanup();
|
|
237
|
+
},
|
|
238
|
+
complete: () => {
|
|
239
|
+
subscriber.complete();
|
|
240
|
+
cleanup();
|
|
241
|
+
},
|
|
242
|
+
});
|
|
243
|
+
return () => {
|
|
244
|
+
subscription.unsubscribe();
|
|
245
|
+
cleanup();
|
|
246
|
+
};
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
// For non-Observable results, close context immediately
|
|
250
|
+
cleanup();
|
|
251
|
+
return result;
|
|
252
|
+
}
|
|
253
|
+
catch (err) {
|
|
254
|
+
cleanup();
|
|
255
|
+
throw err;
|
|
256
|
+
}
|
|
257
|
+
};
|
|
258
|
+
return handler;
|
|
259
|
+
}
|
|
260
|
+
};
|
|
261
|
+
exports.HandlerRegistry = HandlerRegistry;
|
|
262
|
+
exports.HandlerRegistry = HandlerRegistry = __decorate([
|
|
263
|
+
(0, core_1.injectable)({ scope: core_1.BindingScope.SINGLETON })
|
|
264
|
+
], HandlerRegistry);
|
|
265
|
+
//# sourceMappingURL=handler-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handler-registry.js","sourceRoot":"","sources":["../../src/registry/handler-registry.ts"],"names":[],"mappings":";;;;;;;;;AAAA,yCAOwB;AACxB,mCAAkC;AAClC,iCAAiC;AACjC,+BAA8C;AAC9C,8CAIuB;AAEvB,kCAAoF;AACpF,oCAA0C;AAE1C,MAAM,KAAK,GAAG,IAAA,eAAY,EAAC,6BAA6B,CAAC,CAAC;AAE1D;;;GAGG;AACH,MAAM,aAAa,GAAG,IAAI,CAAC;AAQ3B;;;;;;;;;;;;GAYG;AAEI,IAAM,eAAe,GAArB,MAAM,eAAe;IAArB;QACL;;;WAGG;QACc,aAAQ,GAAG,IAAI,GAAG,EAA4B,CAAC;QACxD,eAAU,GAAG,KAAK,CAAC;IA0U7B,CAAC;IAxUC;;;;;OAKG;IACH,KAAK,CAAC,gBAAgB,CAAC,GAAgB;QACrC,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;QACtB,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;QAExB,MAAM,kBAAkB,GAAG,GAAG,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;QACvD,KAAK,CACH,gDAAgD,EAChD,kBAAkB,CAAC,MAAM,CAC1B,CAAC;QAEF,KAAK,MAAM,OAAO,IAAI,kBAAkB,EAAE;YACxC,MAAM,eAAe,GAAG,OAAO,CAAC,gBAAgB,CAAC;YACjD,IAAI,CAAC,eAAe;gBAAE,SAAS;YAE/B,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC;YAC/B,IAAI,CAAC,mBAAmB,CAAC,eAAe,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC;YAC3D,IAAI,CAAC,iBAAiB,CAAC,eAAe,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC;SAC1D;QAED,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACvB,KAAK,CAAC,kCAAkC,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAChE,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,aAAa,CAAC,GAAgB;QAClC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE;YACpB,MAAM,IAAI,KAAK,CACb,0EAA0E,CAC3E,CAAC;SACH;QAED,MAAM,cAAc,GAAG,GAAG,CAAC,SAAS,CAAC,2BAAoB,CAAC,CAAC;QAE3D,KAAK,MAAM,aAAa,IAAI,cAAc,EAAE;YAC1C,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,GAAG,CAAkB,aAAa,CAAC,GAAG,CAAC,CAAC;YACjE,MAAM,aAAa,GAAG,aAAa,CAAC,MAAM,EAAE,CAAC,yBAAkB,CAElD,CAAC;YAEd,oCAAoC;YACpC,2CAA2C;YAC3C,yEAAyE;YACzE,6DAA6D;YAC7D,MAAM,oBAAoB,GAAG,IAAI,GAAG,EAAU,CAAC;YAE/C,0CAA0C;YAC1C,KAAK,MAAM,CAAC,WAAW,EAAE,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,EAAE;gBACnD,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,KAAK,aAAa,EAAE;oBACpE,MAAM,OAAO,GAAG,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC;oBACjD,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE;wBAC9B,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;qBACrC;oBACD,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,cAAc,EAAE;wBAC/B,oBAAoB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;qBACnC;oBACD,KAAK,CACH,iDAAiD,EACjD,OAAO,EACP,aAAa,CACd,CAAC;iBACH;aACF;YAED,iCAAiC;YACjC,+DAA+D;YAC/D,oDAAoD;YACpD,KAAK,MAAM,CAAC,WAAW,EAAE,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,EAAE;gBACnD,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE;oBAC1B,MAAM,OAAO,GAAG,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC;oBACjD,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC,cAAc,IAAI,CAAC,oBAAoB,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE;wBACpE,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE;4BAC9B,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;yBACrC;wBACD,KAAK,CACH,iDAAiD,EACjD,OAAO,EACP,aAAa,IAAI,SAAS,CAC3B,CAAC;qBACH;iBACF;aACF;SACF;IACH,CAAC;IAED;;OAEG;IACH,WAAW;QACT,MAAM,IAAI,GAAG,IAAI,GAAG,EAAqC,CAAC;QAC1D,KAAK,MAAM,CAAC,GAAG,EAAE,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,EAAE;YAC3C,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC;SAC9B;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;OAEG;IACH,YAAY;QACV,OAAO,IAAI,CAAC,UAAU,CAAC;IACzB,CAAC;IAED;;;;OAIG;IACK,QAAQ,CACd,SAA6B,EAC7B,OAAyC;QAEzC,OAAO,GAAG,SAAS,IAAI,GAAG,GAAG,aAAa,GAAG,IAAA,wBAAgB,EAAC,OAAO,CAAC,EAAE,CAAC;IAC3E,CAAC;IAED;;OAEG;IACK,cAAc,CAAC,GAAW;QAChC,MAAM,cAAc,GAAG,GAAG,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;QAClD,OAAO,cAAc,IAAI,CAAC;YACxB,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,cAAc,GAAG,aAAa,CAAC,MAAM,CAAC;YAClD,CAAC,CAAC,GAAG,CAAC;IACV,CAAC;IAEO,mBAAmB,CACzB,eAAsC,EACtC,oBAA4B,EAC5B,GAAgB;QAEhB,IAAI,CAAC,YAAY,CACf,eAAe,EACf,oBAAoB,EACpB,GAAG,EACH,qCAAwB,CAAC,GAAG,EAC5B,KAAK,CACN,CAAC;IACJ,CAAC;IAEO,iBAAiB,CACvB,eAAsC,EACtC,oBAA4B,EAC5B,GAAgB;QAEhB,IAAI,CAAC,YAAY,CACf,eAAe,EACf,oBAAoB,EACpB,GAAG,EACH,mCAAsB,CAAC,GAAG,EAC1B,IAAI,CACL,CAAC;IACJ,CAAC;IAED;;;OAGG;IACK,YAAY,CAClB,eAAsC,EACtC,oBAA4B,EAC5B,GAAgB,EAChB,WAAmB,EACnB,OAAgB;QAEhB,MAAM,OAAO,GACX,wBAAiB,CAAC,oBAAoB,CACpC,WAAW,EACX,eAAe,CAAC,SAAS,CAC1B,CAAC;QACJ,IAAI,CAAC,OAAO;YAAE,OAAO;QAErB,MAAM,aAAa,GAAG,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,iBAAiB,CAAC;QAEpE,KAAK,MAAM,CAAC,UAAU,EAAE,QAAQ,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE;YAC5D,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC;YAChE,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAExC,iDAAiD;YACjD,IAAI,QAAQ,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC,cAAc,KAAK,OAAO,EAAE;gBACtD,MAAM,IAAI,KAAK,CACb,6DAA6D,IAAA,wBAAgB,EAAC,QAAQ,CAAC,OAAO,CAAC,IAAI;oBACjG,0DAA0D,CAC7D,CAAC;aACH;YAED,6CAA6C;YAC7C,IAAI,QAAQ,IAAI,CAAC,OAAO,EAAE;gBACxB,MAAM,IAAI,KAAK,CACb,0CAA0C,IAAA,wBAAgB,EAAC,QAAQ,CAAC,OAAO,CAAC,IAAI;oBAC9E,2DAA2D,CAC9D,CAAC;aACH;YAED,MAAM,OAAO,GAAmB,IAAI,CAAC,aAAa,CAChD,oBAAoB,EACpB,UAAU,EACV,GAAG,CACJ,CAAC;YACF,OAAO,CAAC,cAAc,GAAG,OAAO,CAAC;YACjC,OAAO,CAAC,SAAS,GAAG,QAAQ,CAAC,SAAS,CAAC;YACvC,OAAO,CAAC,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC;YAEjC,IAAI,QAAQ,EAAE;gBACZ,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBACvB,KAAK,CACH,0BAA0B,EAC1B,aAAa,EACb,IAAA,wBAAgB,EAAC,QAAQ,CAAC,OAAO,CAAC,EAClC,eAAe,CAAC,IAAI,EACpB,UAAU,CACX,CAAC;aACH;iBAAM;gBACL,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;gBAClC,KAAK,CACH,6BAA6B,EAC7B,aAAa,EACb,IAAA,wBAAgB,EAAC,QAAQ,CAAC,OAAO,CAAC,EAClC,eAAe,CAAC,IAAI,EACpB,UAAU,CACX,CAAC;aACH;SACF;IACH,CAAC;IAED;;;;;;;;;;;;OAYG;IACK,aAAa,CACnB,oBAA4B,EAC5B,UAAkB,EAClB,GAAgB;QAEhB,MAAM,OAAO,GAAmB,KAAK,EACnC,IAAa,EACb,OAAiB,EACjB,EAAE;YACF,MAAM,aAAa,GAAG,IAAI,cAAO,CAC/B,GAAG,EACH,wBAAwB,IAAA,mBAAU,GAAE,EAAE,CACvC,CAAC;YAEF,+DAA+D;YAC/D,wEAAwE;YACxE,IAAI,MAAM,GAAG,KAAK,CAAC;YACnB,MAAM,OAAO,GAAG,GAAG,EAAE;gBACnB,IAAI,CAAC,MAAM,EAAE;oBACX,MAAM,GAAG,IAAI,CAAC;oBACd,aAAa,CAAC,KAAK,EAAE,CAAC;iBACvB;YACH,CAAC,CAAC;YAEF,IAAI;gBACF,aAAa,CAAC,IAAI,CAAC,wBAAiB,CAAC,eAAe,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;gBAC/D,aAAa,CAAC,IAAI,CAAC,wBAAiB,CAAC,eAAe,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC;gBAElE,MAAM,UAAU,GACd,MAAM,aAAa,CAAC,GAAG,CAAqB,oBAAoB,CAAC,CAAC;gBAEpE,MAAM,MAAM,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC;gBACtC,IAAI,OAAO,MAAM,KAAK,UAAU,EAAE;oBAChC,MAAM,IAAI,KAAK,CACb,6BAA6B,UAAU,8BAA8B,oBAAoB,GAAG,CAC7F,CAAC;iBACH;gBAED,uDAAuD;gBACvD,2DAA2D;gBAC3D,iCAAiC;gBACjC,MAAM,MAAM,GAAG,MAAM,IAAA,mBAAY,EAC/B,UAAU,EACV,UAAU,EACV,aAAa,EACb,CAAC,IAAI,EAAE,OAAO,CAAC,CAChB,CAAC;gBAEF,uEAAuE;gBACvE,IAAI,IAAA,mBAAY,EAAC,MAAM,CAAC,EAAE;oBACxB,MAAM,GAAG,GAAG,MAA6B,CAAC;oBAC1C,OAAO,IAAI,iBAAU,CAAC,UAAU,CAAC,EAAE;wBACjC,MAAM,YAAY,GAAG,GAAG,CAAC,SAAS,CAAC;4BACjC,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC;4BACrC,KAAK,EAAE,GAAG,CAAC,EAAE;gCACX,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gCACtB,OAAO,EAAE,CAAC;4BACZ,CAAC;4BACD,QAAQ,EAAE,GAAG,EAAE;gCACb,UAAU,CAAC,QAAQ,EAAE,CAAC;gCACtB,OAAO,EAAE,CAAC;4BACZ,CAAC;yBACF,CAAC,CAAC;wBACH,OAAO,GAAG,EAAE;4BACV,YAAY,CAAC,WAAW,EAAE,CAAC;4BAC3B,OAAO,EAAE,CAAC;wBACZ,CAAC,CAAC;oBACJ,CAAC,CAAC,CAAC;iBACJ;gBAED,wDAAwD;gBACxD,OAAO,EAAE,CAAC;gBACV,OAAO,MAAM,CAAC;aACf;YAAC,OAAO,GAAG,EAAE;gBACZ,OAAO,EAAE,CAAC;gBACV,MAAM,GAAG,CAAC;aACX;QACH,CAAC,CAAC;QACF,OAAO,OAAO,CAAC;IACjB,CAAC;CACF,CAAA;AAhVY,0CAAe;0BAAf,eAAe;IAD3B,IAAA,iBAAU,EAAC,EAAC,KAAK,EAAE,mBAAY,CAAC,SAAS,EAAC,CAAC;GAC/B,eAAe,CAgV3B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './handler-registry';
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./handler-registry"), exports);
|
|
18
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/registry/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,qDAAmC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './serializer.interface';
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./serializer.interface"), exports);
|
|
18
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/serializers/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,yDAAuC"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
/// <reference types="node" />
|
|
3
|
+
/**
|
|
4
|
+
* Serializes outgoing messages before sending to the broker.
|
|
5
|
+
*
|
|
6
|
+
* Supports both sync and async implementations to allow for
|
|
7
|
+
* compression, encryption, schema registry lookup, protobuf/avro
|
|
8
|
+
* encoding, and streaming codecs.
|
|
9
|
+
*/
|
|
10
|
+
export interface Serializer<TInput = unknown, TOutput = unknown> {
|
|
11
|
+
serialize(value: TInput): TOutput | Promise<TOutput>;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Deserializes incoming messages received from the broker.
|
|
15
|
+
*
|
|
16
|
+
* Supports async implementations for decompression, decryption,
|
|
17
|
+
* schema registry lookup, and streaming codecs.
|
|
18
|
+
*/
|
|
19
|
+
export interface Deserializer<TInput = unknown, TOutput = unknown> {
|
|
20
|
+
deserialize(value: TInput): TOutput | Promise<TOutput>;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Transport message envelope with metadata for tracing,
|
|
24
|
+
* correlation, retries, and distributed context propagation.
|
|
25
|
+
*
|
|
26
|
+
* Transport adapters should serialize/deserialize this envelope
|
|
27
|
+
* rather than raw payloads when full transport metadata is needed.
|
|
28
|
+
*/
|
|
29
|
+
export interface TransportPacket<T = unknown> {
|
|
30
|
+
readonly pattern: string | Record<string, unknown>;
|
|
31
|
+
readonly data: T;
|
|
32
|
+
readonly headers?: Readonly<Record<string, string | Buffer | number | boolean>>;
|
|
33
|
+
readonly correlationId?: string;
|
|
34
|
+
readonly traceId?: string;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Default JSON serializer. Converts objects to JSON strings.
|
|
38
|
+
*
|
|
39
|
+
* Wraps JSON.stringify errors into deterministic transport errors
|
|
40
|
+
* instead of exposing raw runtime exceptions (circular refs, BigInt, etc.).
|
|
41
|
+
*
|
|
42
|
+
* Input: any JSON-serializable value.
|
|
43
|
+
* Output: JSON string (compatible with all text-based transports).
|
|
44
|
+
*
|
|
45
|
+
* Note: Buffer/Uint8Array output for binary transports requires
|
|
46
|
+
* a custom serializer implementation.
|
|
47
|
+
*/
|
|
48
|
+
export declare class JsonSerializer implements Serializer<unknown, string> {
|
|
49
|
+
serialize(value: unknown): string;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Default JSON deserializer. Parses JSON strings or Buffers to objects.
|
|
53
|
+
*
|
|
54
|
+
* Wraps JSON.parse errors into deterministic transport errors
|
|
55
|
+
* instead of exposing raw SyntaxError from corrupted broker payloads.
|
|
56
|
+
*
|
|
57
|
+
* Input: string or Buffer (Node.js). For browser/WebSocket transports,
|
|
58
|
+
* use string or Uint8Array with a custom deserializer.
|
|
59
|
+
*/
|
|
60
|
+
export declare class JsonDeserializer implements Deserializer<string | Buffer, unknown> {
|
|
61
|
+
deserialize(value: string | Buffer): unknown;
|
|
62
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.JsonDeserializer = exports.JsonSerializer = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Default JSON serializer. Converts objects to JSON strings.
|
|
6
|
+
*
|
|
7
|
+
* Wraps JSON.stringify errors into deterministic transport errors
|
|
8
|
+
* instead of exposing raw runtime exceptions (circular refs, BigInt, etc.).
|
|
9
|
+
*
|
|
10
|
+
* Input: any JSON-serializable value.
|
|
11
|
+
* Output: JSON string (compatible with all text-based transports).
|
|
12
|
+
*
|
|
13
|
+
* Note: Buffer/Uint8Array output for binary transports requires
|
|
14
|
+
* a custom serializer implementation.
|
|
15
|
+
*/
|
|
16
|
+
class JsonSerializer {
|
|
17
|
+
serialize(value) {
|
|
18
|
+
try {
|
|
19
|
+
const serialized = JSON.stringify(value);
|
|
20
|
+
if (serialized === undefined) {
|
|
21
|
+
throw new Error('value is not JSON-serializable');
|
|
22
|
+
}
|
|
23
|
+
return serialized;
|
|
24
|
+
}
|
|
25
|
+
catch (err) {
|
|
26
|
+
throw new Error(`Failed to serialize outgoing message: ${err instanceof Error ? err.message : String(err)}`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
exports.JsonSerializer = JsonSerializer;
|
|
31
|
+
/**
|
|
32
|
+
* Default JSON deserializer. Parses JSON strings or Buffers to objects.
|
|
33
|
+
*
|
|
34
|
+
* Wraps JSON.parse errors into deterministic transport errors
|
|
35
|
+
* instead of exposing raw SyntaxError from corrupted broker payloads.
|
|
36
|
+
*
|
|
37
|
+
* Input: string or Buffer (Node.js). For browser/WebSocket transports,
|
|
38
|
+
* use string or Uint8Array with a custom deserializer.
|
|
39
|
+
*/
|
|
40
|
+
class JsonDeserializer {
|
|
41
|
+
deserialize(value) {
|
|
42
|
+
try {
|
|
43
|
+
const str = typeof value === 'string' ? value : value.toString('utf-8');
|
|
44
|
+
return JSON.parse(str);
|
|
45
|
+
}
|
|
46
|
+
catch (err) {
|
|
47
|
+
throw new Error(`Failed to deserialize incoming message: ${err instanceof Error ? err.message : String(err)}`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
exports.JsonDeserializer = JsonDeserializer;
|
|
52
|
+
//# sourceMappingURL=serializer.interface.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serializer.interface.js","sourceRoot":"","sources":["../../src/serializers/serializer.interface.ts"],"names":[],"mappings":";;;AAoCA;;;;;;;;;;;GAWG;AACH,MAAa,cAAc;IACzB,SAAS,CAAC,KAAc;QACtB,IAAI;YACF,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;YACzC,IAAI,UAAU,KAAK,SAAS,EAAE;gBAC5B,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;aACnD;YACD,OAAO,UAAU,CAAC;SACnB;QAAC,OAAO,GAAG,EAAE;YACZ,MAAM,IAAI,KAAK,CACb,yCACE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CACjD,EAAE,CACH,CAAC;SACH;IACH,CAAC;CACF;AAhBD,wCAgBC;AAED;;;;;;;;GAQG;AACH,MAAa,gBAAgB;IAG3B,WAAW,CAAC,KAAsB;QAChC,IAAI;YACF,MAAM,GAAG,GACP,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;YAC9D,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;SACxB;QAAC,OAAO,GAAG,EAAE;YACZ,MAAM,IAAI,KAAK,CACb,2CACE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CACjD,EAAE,CACH,CAAC;SACH;IACH,CAAC;CACF;AAhBD,4CAgBC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './server-base';
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./server-base"), exports);
|
|
18
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,gDAA8B"}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { Observable } from 'rxjs';
|
|
2
|
+
import { TransportServer, TransportStatus, MessageHandler, WritePacket, IncomingRequest, IncomingEvent } from '../interfaces';
|
|
3
|
+
import { Serializer, Deserializer } from '../serializers';
|
|
4
|
+
/**
|
|
5
|
+
* Result of handling a message. Separates "what was sent to the caller"
|
|
6
|
+
* from "should the broker ack or nack this message."
|
|
7
|
+
*
|
|
8
|
+
* - `success`: Handler completed. Response was sent. Adapter should ack.
|
|
9
|
+
* - `handler-error`: Handler threw or Observable errored. Error response
|
|
10
|
+
* was sent to the caller. Adapter should ack (the error was handled).
|
|
11
|
+
* - `infrastructure-error`: No handler found, serialization failure, or
|
|
12
|
+
* other framework-level failure. Adapter should nack/dead-letter.
|
|
13
|
+
*/
|
|
14
|
+
export interface HandlerResult {
|
|
15
|
+
readonly outcome: 'success' | 'handler-error' | 'infrastructure-error';
|
|
16
|
+
readonly error?: unknown;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Abstract base class for transport servers.
|
|
20
|
+
*
|
|
21
|
+
* Manages the handler registry, message dispatching, and serialization.
|
|
22
|
+
* Each transport (Kafka, RabbitMQ, gRPC, MQTT, NATS) extends this
|
|
23
|
+
* class and implements listen/close/unwrap.
|
|
24
|
+
*
|
|
25
|
+
* Subclasses should:
|
|
26
|
+
* - Call deserializer.deserialize() on raw broker messages before
|
|
27
|
+
* passing them to handleMessage()/handleEvent()
|
|
28
|
+
* - Call serializer.serialize() on outbound responses
|
|
29
|
+
* - Call setStatus('connected') in listen() when ready
|
|
30
|
+
* - Call setStatus('disconnected') in close() when stopped
|
|
31
|
+
* - Call dispose() only when the server will never be restarted
|
|
32
|
+
*/
|
|
33
|
+
export declare abstract class ServerBase implements TransportServer {
|
|
34
|
+
protected readonly messageHandlers: Map<string, MessageHandler<unknown, unknown, unknown>[]>;
|
|
35
|
+
private readonly statusSubject;
|
|
36
|
+
protected serializer: Serializer;
|
|
37
|
+
protected deserializer: Deserializer;
|
|
38
|
+
protected handlerTimeoutMs: number;
|
|
39
|
+
readonly status$: Observable<TransportStatus>;
|
|
40
|
+
constructor(options?: {
|
|
41
|
+
serializer?: Serializer;
|
|
42
|
+
deserializer?: Deserializer;
|
|
43
|
+
handlerTimeoutMs?: number;
|
|
44
|
+
});
|
|
45
|
+
/**
|
|
46
|
+
* Start listening for messages from the broker.
|
|
47
|
+
* Subclasses should call setStatus('connected') when ready.
|
|
48
|
+
*/
|
|
49
|
+
abstract listen(): Promise<void>;
|
|
50
|
+
/**
|
|
51
|
+
* Stop listening and close connections.
|
|
52
|
+
* Subclasses should call setStatus('disconnected') when stopped.
|
|
53
|
+
* Call dispose() only when the server will never be restarted.
|
|
54
|
+
*/
|
|
55
|
+
abstract close(): Promise<void>;
|
|
56
|
+
/**
|
|
57
|
+
* Access the underlying native server/consumer.
|
|
58
|
+
*/
|
|
59
|
+
abstract unwrap<T>(): T;
|
|
60
|
+
/**
|
|
61
|
+
* Emit a status change. Called by transport adapters in listen() and close().
|
|
62
|
+
*/
|
|
63
|
+
protected setStatus(status: TransportStatus): void;
|
|
64
|
+
/**
|
|
65
|
+
* Permanently complete the status stream. After this call, no further
|
|
66
|
+
* status emissions are possible and the server instance cannot restart.
|
|
67
|
+
* Existing subscribers receive the complete notification.
|
|
68
|
+
*
|
|
69
|
+
* Call only when the server is being permanently disposed.
|
|
70
|
+
* Normal close() should call setStatus('disconnected'), NOT dispose().
|
|
71
|
+
*/
|
|
72
|
+
protected dispose(): void;
|
|
73
|
+
/**
|
|
74
|
+
* Register a handler for a message pattern.
|
|
75
|
+
*
|
|
76
|
+
* For request/response handlers (@messageHandler): duplicate patterns
|
|
77
|
+
* throw an error. Only one handler per pattern is allowed.
|
|
78
|
+
*
|
|
79
|
+
* For event handlers (@eventHandler): multiple handlers on the same
|
|
80
|
+
* pattern are stored in an array and all execute.
|
|
81
|
+
*
|
|
82
|
+
* Mixing @messageHandler and @eventHandler on the same pattern throws.
|
|
83
|
+
*
|
|
84
|
+
* Handlers are never mutated. Each server owns its own handler array,
|
|
85
|
+
* so the same handler object can be safely shared across servers.
|
|
86
|
+
*/
|
|
87
|
+
addHandler(pattern: string, handler: MessageHandler): void;
|
|
88
|
+
/**
|
|
89
|
+
* Get all registered handlers. Returns a defensive copy.
|
|
90
|
+
*/
|
|
91
|
+
getHandlers(): ReadonlyMap<string, readonly MessageHandler[]>;
|
|
92
|
+
/**
|
|
93
|
+
* Remove all registered handlers.
|
|
94
|
+
* Called before rebinding on restart to prevent duplicate registration.
|
|
95
|
+
*/
|
|
96
|
+
clearHandlers(): void;
|
|
97
|
+
/**
|
|
98
|
+
* Get handlers by pattern. Normalizes the pattern before lookup.
|
|
99
|
+
* Returns a defensive copy for external consumers.
|
|
100
|
+
*/
|
|
101
|
+
getHandlersByPattern(pattern: string | Record<string, unknown>): readonly MessageHandler[] | undefined;
|
|
102
|
+
/**
|
|
103
|
+
* Internal handler lookup. Returns the live array for dispatch performance.
|
|
104
|
+
*/
|
|
105
|
+
private lookupHandlers;
|
|
106
|
+
/**
|
|
107
|
+
* Handle a request/response message.
|
|
108
|
+
*
|
|
109
|
+
* Invokes the handler and calls respond() with each result value.
|
|
110
|
+
* Observable subscriptions are tracked and cleaned up on completion,
|
|
111
|
+
* error, or timeout.
|
|
112
|
+
*
|
|
113
|
+
* Returns a HandlerResult that separates response semantics from
|
|
114
|
+
* broker settlement semantics:
|
|
115
|
+
*
|
|
116
|
+
* - `success`: Handler completed normally. Ack the message.
|
|
117
|
+
* - `handler-error`: Handler threw or Observable errored. The error
|
|
118
|
+
* response was already sent to the caller. Ack the message --
|
|
119
|
+
* the error was handled as an application-level response.
|
|
120
|
+
* - `infrastructure-error`: No handler found or framework failure.
|
|
121
|
+
* Nack/dead-letter the message.
|
|
122
|
+
*
|
|
123
|
+
* Observable handlers that do not complete within handlerTimeoutMs
|
|
124
|
+
* are terminated with a timeout error (handler-error).
|
|
125
|
+
*
|
|
126
|
+
* If respond() throws (adapter publication failure), the error is
|
|
127
|
+
* caught and returned as infrastructure-error.
|
|
128
|
+
*/
|
|
129
|
+
protected handleMessage(request: IncomingRequest, respond: (packet: WritePacket) => void, context?: unknown): Promise<HandlerResult>;
|
|
130
|
+
/**
|
|
131
|
+
* Core handler execution. Separated from handleMessage so that
|
|
132
|
+
* respond() failures bubble up and are caught by the outer wrapper.
|
|
133
|
+
*/
|
|
134
|
+
private executeHandler;
|
|
135
|
+
/**
|
|
136
|
+
* Handle a fire-and-forget event.
|
|
137
|
+
*
|
|
138
|
+
* Invokes all chained handlers for the pattern.
|
|
139
|
+
* Errors are logged but not propagated (fire-and-forget semantics).
|
|
140
|
+
*
|
|
141
|
+
* Observable event handlers that do not complete within handlerTimeoutMs
|
|
142
|
+
* are terminated and logged.
|
|
143
|
+
*/
|
|
144
|
+
protected handleEvent(event: IncomingEvent, context?: unknown): Promise<void>;
|
|
145
|
+
/**
|
|
146
|
+
* Normalize a pattern to a consistent string key.
|
|
147
|
+
* Delegates to the shared normalizePattern utility.
|
|
148
|
+
*/
|
|
149
|
+
protected normalizePattern(pattern: string | Record<string, unknown>): string;
|
|
150
|
+
/**
|
|
151
|
+
* Serialize an error to a string for transport.
|
|
152
|
+
*/
|
|
153
|
+
private serializeError;
|
|
154
|
+
}
|