@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.
Files changed (81) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +297 -0
  3. package/dist/client/client-proxy.d.ts +147 -0
  4. package/dist/client/client-proxy.js +225 -0
  5. package/dist/client/client-proxy.js.map +1 -0
  6. package/dist/client/index.d.ts +1 -0
  7. package/dist/client/index.js +18 -0
  8. package/dist/client/index.js.map +1 -0
  9. package/dist/context/execution-context.d.ts +102 -0
  10. package/dist/context/execution-context.js +110 -0
  11. package/dist/context/execution-context.js.map +1 -0
  12. package/dist/context/index.d.ts +1 -0
  13. package/dist/context/index.js +18 -0
  14. package/dist/context/index.js.map +1 -0
  15. package/dist/decorators/constants.d.ts +41 -0
  16. package/dist/decorators/constants.js +13 -0
  17. package/dist/decorators/constants.js.map +1 -0
  18. package/dist/decorators/event-handler.decorator.d.ts +28 -0
  19. package/dist/decorators/event-handler.decorator.js +42 -0
  20. package/dist/decorators/event-handler.decorator.js.map +1 -0
  21. package/dist/decorators/index.d.ts +4 -0
  22. package/dist/decorators/index.js +21 -0
  23. package/dist/decorators/index.js.map +1 -0
  24. package/dist/decorators/message-handler.decorator.d.ts +26 -0
  25. package/dist/decorators/message-handler.decorator.js +40 -0
  26. package/dist/decorators/message-handler.decorator.js.map +1 -0
  27. package/dist/decorators/payload.decorator.d.ts +30 -0
  28. package/dist/decorators/payload.decorator.js +42 -0
  29. package/dist/decorators/payload.decorator.js.map +1 -0
  30. package/dist/index.d.ts +11 -0
  31. package/dist/index.js +42 -0
  32. package/dist/index.js.map +1 -0
  33. package/dist/interfaces/index.d.ts +4 -0
  34. package/dist/interfaces/index.js +21 -0
  35. package/dist/interfaces/index.js.map +1 -0
  36. package/dist/interfaces/message-handler.interface.d.ts +21 -0
  37. package/dist/interfaces/message-handler.interface.js +3 -0
  38. package/dist/interfaces/message-handler.interface.js.map +1 -0
  39. package/dist/interfaces/packet.interface.d.ts +42 -0
  40. package/dist/interfaces/packet.interface.js +3 -0
  41. package/dist/interfaces/packet.interface.js.map +1 -0
  42. package/dist/interfaces/transport-client.interface.d.ts +41 -0
  43. package/dist/interfaces/transport-client.interface.js +3 -0
  44. package/dist/interfaces/transport-client.interface.js.map +1 -0
  45. package/dist/interfaces/transport-server.interface.d.ts +44 -0
  46. package/dist/interfaces/transport-server.interface.js +3 -0
  47. package/dist/interfaces/transport-server.interface.js.map +1 -0
  48. package/dist/keys.d.ts +88 -0
  49. package/dist/keys.js +123 -0
  50. package/dist/keys.js.map +1 -0
  51. package/dist/registry/handler-registry.d.ts +77 -0
  52. package/dist/registry/handler-registry.js +265 -0
  53. package/dist/registry/handler-registry.js.map +1 -0
  54. package/dist/registry/index.d.ts +1 -0
  55. package/dist/registry/index.js +18 -0
  56. package/dist/registry/index.js.map +1 -0
  57. package/dist/serializers/index.d.ts +1 -0
  58. package/dist/serializers/index.js +18 -0
  59. package/dist/serializers/index.js.map +1 -0
  60. package/dist/serializers/serializer.interface.d.ts +62 -0
  61. package/dist/serializers/serializer.interface.js +52 -0
  62. package/dist/serializers/serializer.interface.js.map +1 -0
  63. package/dist/server/index.d.ts +1 -0
  64. package/dist/server/index.js +18 -0
  65. package/dist/server/index.js.map +1 -0
  66. package/dist/server/server-base.d.ts +154 -0
  67. package/dist/server/server-base.js +287 -0
  68. package/dist/server/server-base.js.map +1 -0
  69. package/dist/transport-booter.d.ts +31 -0
  70. package/dist/transport-booter.js +117 -0
  71. package/dist/transport-booter.js.map +1 -0
  72. package/dist/transport.component.d.ts +26 -0
  73. package/dist/transport.component.js +42 -0
  74. package/dist/transport.component.js.map +1 -0
  75. package/dist/utils/index.d.ts +1 -0
  76. package/dist/utils/index.js +6 -0
  77. package/dist/utils/index.js.map +1 -0
  78. package/dist/utils/normalize-pattern.d.ts +18 -0
  79. package/dist/utils/normalize-pattern.js +75 -0
  80. package/dist/utils/normalize-pattern.js.map +1 -0
  81. 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":"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"}
@@ -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
+ }