@riaskov/nevo-messaging 1.0.1 → 1.1.2

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 (64) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +202 -67
  3. package/dist/common/access-control.d.ts +15 -0
  4. package/dist/common/access-control.js +94 -0
  5. package/dist/common/base.client.d.ts +7 -2
  6. package/dist/common/base.client.js +16 -2
  7. package/dist/common/base.controller.d.ts +6 -1
  8. package/dist/common/base.controller.js +68 -4
  9. package/dist/common/constants.d.ts +4 -0
  10. package/dist/common/constants.js +7 -0
  11. package/dist/common/discovery.d.ts +8 -0
  12. package/dist/common/discovery.js +35 -0
  13. package/dist/common/error-code.d.ts +2 -1
  14. package/dist/common/error-code.js +1 -0
  15. package/dist/common/error-messages.js +2 -1
  16. package/dist/common/index.d.ts +3 -0
  17. package/dist/common/index.js +3 -0
  18. package/dist/common/service-utils.d.ts +2 -0
  19. package/dist/common/service-utils.js +8 -0
  20. package/dist/common/types.d.ts +62 -0
  21. package/dist/signal-router.utils.d.ts +3 -1
  22. package/dist/signal-router.utils.js +70 -6
  23. package/dist/transports/http/http.client-base.d.ts +13 -0
  24. package/dist/transports/http/http.client-base.js +33 -0
  25. package/dist/transports/http/http.config.d.ts +8 -0
  26. package/dist/transports/http/http.config.js +16 -0
  27. package/dist/transports/http/http.signal-router.decorator.d.ts +3 -0
  28. package/dist/transports/http/http.signal-router.decorator.js +18 -0
  29. package/dist/transports/http/http.transport.controller.d.ts +21 -0
  30. package/dist/transports/http/http.transport.controller.js +114 -0
  31. package/dist/transports/http/index.d.ts +5 -0
  32. package/dist/transports/http/index.js +21 -0
  33. package/dist/transports/http/nevo-http.client.d.ts +54 -0
  34. package/dist/transports/http/nevo-http.client.js +280 -0
  35. package/dist/transports/index.d.ts +3 -0
  36. package/dist/transports/index.js +3 -0
  37. package/dist/transports/kafka/kafka.client-base.d.ts +5 -0
  38. package/dist/transports/kafka/kafka.client-base.js +15 -0
  39. package/dist/transports/kafka/kafka.config.d.ts +7 -0
  40. package/dist/transports/kafka/kafka.config.js +48 -2
  41. package/dist/transports/kafka/kafka.signal-router.decorator.js +2 -1
  42. package/dist/transports/kafka/nevo-kafka.client.d.ts +42 -0
  43. package/dist/transports/kafka/nevo-kafka.client.js +210 -4
  44. package/dist/transports/nats/index.d.ts +4 -0
  45. package/dist/transports/nats/index.js +20 -0
  46. package/dist/transports/nats/nats.client-base.d.ts +13 -0
  47. package/dist/transports/nats/nats.client-base.js +33 -0
  48. package/dist/transports/nats/nats.config.d.ts +8 -0
  49. package/dist/transports/nats/nats.config.js +16 -0
  50. package/dist/transports/nats/nats.signal-router.decorator.d.ts +6 -0
  51. package/dist/transports/nats/nats.signal-router.decorator.js +49 -0
  52. package/dist/transports/nats/nevo-nats.client.d.ts +55 -0
  53. package/dist/transports/nats/nevo-nats.client.js +210 -0
  54. package/dist/transports/socket-io/index.d.ts +4 -0
  55. package/dist/transports/socket-io/index.js +20 -0
  56. package/dist/transports/socket-io/nevo-socket.client.d.ts +50 -0
  57. package/dist/transports/socket-io/nevo-socket.client.js +202 -0
  58. package/dist/transports/socket-io/socket.client-base.d.ts +13 -0
  59. package/dist/transports/socket-io/socket.client-base.js +33 -0
  60. package/dist/transports/socket-io/socket.config.d.ts +8 -0
  61. package/dist/transports/socket-io/socket.config.js +16 -0
  62. package/dist/transports/socket-io/socket.signal-router.decorator.d.ts +13 -0
  63. package/dist/transports/socket-io/socket.signal-router.decorator.js +109 -0
  64. package/package.json +11 -5
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.BaseMessageController = void 0;
4
4
  const _1 = require("./");
5
+ const access_control_1 = require("./access-control");
5
6
  class BaseMessageController {
6
7
  constructor(serviceName, serviceInstances, methodHandlers, options) {
7
8
  this.methodRegistry = {};
@@ -11,6 +12,7 @@ class BaseMessageController {
11
12
  this.beforeHook = options?.onBefore;
12
13
  this.afterHook = options?.onAfter;
13
14
  this.debug = options?.debug || false;
15
+ this.accessControl = options?.accessControl;
14
16
  this.systemBeforeHook = (context) => {
15
17
  if (this.debug) {
16
18
  console.log(`[${this.constructor.name}] Received:`, {
@@ -67,6 +69,50 @@ class BaseMessageController {
67
69
  throw error;
68
70
  }
69
71
  }
72
+ suggestClosestMethod(method) {
73
+ const candidates = Object.keys(this.methodRegistry || {});
74
+ if (!candidates.length) {
75
+ return null;
76
+ }
77
+ const normalized = method.toLowerCase();
78
+ let best = null;
79
+ for (const candidate of candidates) {
80
+ const score = this.levenshteinDistance(normalized, candidate.toLowerCase());
81
+ if (!best || score < best.score) {
82
+ best = { name: candidate, score };
83
+ }
84
+ }
85
+ if (!best) {
86
+ return null;
87
+ }
88
+ const threshold = Math.max(2, Math.floor(method.length * 0.4));
89
+ return best.score <= threshold ? best.name : null;
90
+ }
91
+ levenshteinDistance(a, b) {
92
+ if (a === b) {
93
+ return 0;
94
+ }
95
+ if (!a.length) {
96
+ return b.length;
97
+ }
98
+ if (!b.length) {
99
+ return a.length;
100
+ }
101
+ const matrix = Array.from({ length: a.length + 1 }, () => []);
102
+ for (let i = 0; i <= a.length; i++) {
103
+ matrix[i][0] = i;
104
+ }
105
+ for (let j = 0; j <= b.length; j++) {
106
+ matrix[0][j] = j;
107
+ }
108
+ for (let i = 1; i <= a.length; i++) {
109
+ for (let j = 1; j <= b.length; j++) {
110
+ const cost = a[i - 1] === b[j - 1] ? 0 : 1;
111
+ matrix[i][j] = Math.min(matrix[i - 1][j] + 1, matrix[i][j - 1] + 1, matrix[i - 1][j - 1] + cost);
112
+ }
113
+ }
114
+ return matrix[a.length][b.length];
115
+ }
70
116
  async formatResult(result) {
71
117
  if (result instanceof Promise) {
72
118
  result = await result;
@@ -100,12 +146,13 @@ class BaseMessageController {
100
146
  };
101
147
  }
102
148
  async processMessage(data) {
103
- const { method, uuid, params } = this.extractMessageData(data);
149
+ const { method, uuid, params, meta } = this.extractMessageData(data);
104
150
  const baseContext = {
105
151
  method,
106
152
  serviceName: this.serviceName,
107
153
  uuid,
108
- rawData: data
154
+ rawData: data,
155
+ meta
109
156
  };
110
157
  const requestContext = {
111
158
  ...baseContext,
@@ -120,10 +167,26 @@ class BaseMessageController {
120
167
  processedParams = hookResult;
121
168
  }
122
169
  }
170
+ const callerService = (0, access_control_1.extractCallerService)(meta);
171
+ const topic = this.serviceName;
172
+ if (!(0, access_control_1.isAccessAllowed)(this.accessControl, topic, method, callerService)) {
173
+ (0, access_control_1.logAccessDenied)(this.accessControl, { topic, method, serviceName: this.serviceName, callerService });
174
+ return {
175
+ uuid,
176
+ method,
177
+ params: {
178
+ result: "error",
179
+ error: (0, access_control_1.createAccessDeniedError)(method, this.serviceName, callerService)
180
+ },
181
+ meta
182
+ };
183
+ }
123
184
  const handler = this.methodRegistry[method];
124
185
  if (!handler) {
186
+ const suggestion = this.suggestClosestMethod(method);
187
+ const message = suggestion ? `Invalid method name '${method}', did you mean '${suggestion}'?` : `Method handler not found: ${method}`;
125
188
  throw new _1.MessagingError(_1.ErrorCode.UNKNOWN, {
126
- message: `Method handler not found: ${method}`
189
+ message
127
190
  });
128
191
  }
129
192
  const result = await this.executeHandler(handler, processedParams);
@@ -131,7 +194,8 @@ class BaseMessageController {
131
194
  let response = {
132
195
  uuid,
133
196
  method,
134
- params: { result: formattedResult }
197
+ params: { result: formattedResult },
198
+ meta
135
199
  };
136
200
  const responseContext = {
137
201
  ...baseContext,
@@ -0,0 +1,4 @@
1
+ export declare const DEFAULT_SUBSCRIPTION_SUFFIX = "-events.sub";
2
+ export declare const DEFAULT_EVENTS_SUFFIX = "-events";
3
+ export declare const DEFAULT_BROADCAST_TOPIC = "__broadcast";
4
+ export declare const DEFAULT_DISCOVERY_TOPIC = "__nevo.discovery";
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DEFAULT_DISCOVERY_TOPIC = exports.DEFAULT_BROADCAST_TOPIC = exports.DEFAULT_EVENTS_SUFFIX = exports.DEFAULT_SUBSCRIPTION_SUFFIX = void 0;
4
+ exports.DEFAULT_SUBSCRIPTION_SUFFIX = "-events.sub";
5
+ exports.DEFAULT_EVENTS_SUFFIX = "-events";
6
+ exports.DEFAULT_BROADCAST_TOPIC = "__broadcast";
7
+ exports.DEFAULT_DISCOVERY_TOPIC = "__nevo.discovery";
@@ -0,0 +1,8 @@
1
+ import { DiscoveryAnnouncement, DiscoveryEntry } from "./types";
2
+ export declare class DiscoveryRegistry {
3
+ private readonly services;
4
+ update(announcement: DiscoveryAnnouncement): void;
5
+ prune(ttlMs: number): void;
6
+ list(): DiscoveryEntry[];
7
+ isAvailable(serviceName: string, ttlMs: number): boolean;
8
+ }
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DiscoveryRegistry = void 0;
4
+ class DiscoveryRegistry {
5
+ constructor() {
6
+ this.services = new Map();
7
+ }
8
+ update(announcement) {
9
+ const now = Date.now();
10
+ const entry = {
11
+ ...announcement,
12
+ lastSeen: now
13
+ };
14
+ this.services.set(announcement.serviceName, entry);
15
+ }
16
+ prune(ttlMs) {
17
+ const now = Date.now();
18
+ for (const [serviceName, entry] of this.services.entries()) {
19
+ if (now - entry.lastSeen > ttlMs) {
20
+ this.services.delete(serviceName);
21
+ }
22
+ }
23
+ }
24
+ list() {
25
+ return [...this.services.values()];
26
+ }
27
+ isAvailable(serviceName, ttlMs) {
28
+ const entry = this.services.get(serviceName);
29
+ if (!entry) {
30
+ return false;
31
+ }
32
+ return Date.now() - entry.lastSeen <= ttlMs;
33
+ }
34
+ }
35
+ exports.DiscoveryRegistry = DiscoveryRegistry;
@@ -1,3 +1,4 @@
1
1
  export declare enum ErrorCode {
2
- UNKNOWN = 0
2
+ UNKNOWN = 0,
3
+ UNAUTHORIZED = 1
3
4
  }
@@ -4,4 +4,5 @@ exports.ErrorCode = void 0;
4
4
  var ErrorCode;
5
5
  (function (ErrorCode) {
6
6
  ErrorCode[ErrorCode["UNKNOWN"] = 0] = "UNKNOWN";
7
+ ErrorCode[ErrorCode["UNAUTHORIZED"] = 1] = "UNAUTHORIZED";
7
8
  })(ErrorCode || (exports.ErrorCode = ErrorCode = {}));
@@ -3,5 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ErrorMessages = void 0;
4
4
  const _1 = require("./");
5
5
  exports.ErrorMessages = {
6
- [_1.ErrorCode.UNKNOWN]: "An unknown error occurred"
6
+ [_1.ErrorCode.UNKNOWN]: "An unknown error occurred",
7
+ [_1.ErrorCode.UNAUTHORIZED]: "Access denied"
7
8
  };
@@ -6,3 +6,6 @@ export * from "./service-utils";
6
6
  export * from "./error-code";
7
7
  export * from "./error-messages";
8
8
  export * from "./bigint.utils";
9
+ export * from "./constants";
10
+ export * from "./access-control";
11
+ export * from "./discovery";
@@ -22,3 +22,6 @@ __exportStar(require("./service-utils"), exports);
22
22
  __exportStar(require("./error-code"), exports);
23
23
  __exportStar(require("./error-messages"), exports);
24
24
  __exportStar(require("./bigint.utils"), exports);
25
+ __exportStar(require("./constants"), exports);
26
+ __exportStar(require("./access-control"), exports);
27
+ __exportStar(require("./discovery"), exports);
@@ -17,5 +17,7 @@ export declare function mapServiceMethods<T>(service: T, customMappings?: Record
17
17
  export declare const createServiceClient: <T extends ServiceMethodMap>(serviceName: string) => {
18
18
  query: <M extends keyof T & string>(method: M, params: T[M]["params"]) => Promise<T[M]["result"]>;
19
19
  emit: <M extends keyof T & string>(method: M, params: T[M]["params"]) => Promise<void>;
20
+ publish: <M extends keyof T & string>(method: M, params: T[M]["params"]) => Promise<void>;
21
+ subscribe: <M extends keyof T & string>(method: M, handler: (data: T[M]["result"]) => void) => Promise<void>;
20
22
  };
21
23
  export declare function createMethodHandlers(mappings: Record<string, [string, ((params: unknown) => unknown[])?, ((result: unknown) => unknown)?]>): ServiceMethodMapping;
@@ -38,6 +38,14 @@ const createServiceClient = (serviceName) => ({
38
38
  // @ts-ignore
39
39
  emit: (method, params) => {
40
40
  throw new Error("Implementation required in subclass");
41
+ },
42
+ // @ts-ignore
43
+ publish: (method, params) => {
44
+ throw new Error("Implementation required in subclass");
45
+ },
46
+ // @ts-ignore
47
+ subscribe: (method, handler) => {
48
+ throw new Error("Implementation required in subclass");
41
49
  }
42
50
  });
43
51
  exports.createServiceClient = createServiceClient;
@@ -6,10 +6,20 @@ export interface MessagePayload {
6
6
  key: string;
7
7
  value: string;
8
8
  }
9
+ export type MessageType = "query" | "emit" | "sub" | "broadcast" | "discovery";
10
+ export interface MessageMeta {
11
+ type?: MessageType;
12
+ service?: string;
13
+ ts?: number;
14
+ auth?: {
15
+ token?: string;
16
+ };
17
+ }
9
18
  export interface MessageRequest<T = unknown> {
10
19
  uuid: string;
11
20
  method: string;
12
21
  params: T;
22
+ meta?: MessageMeta;
13
23
  }
14
24
  export interface MessageResponse<T = unknown> {
15
25
  uuid: string;
@@ -18,6 +28,7 @@ export interface MessageResponse<T = unknown> {
18
28
  result: T | "error";
19
29
  error?: ErrorDetails;
20
30
  };
31
+ meta?: MessageMeta;
21
32
  }
22
33
  export interface ErrorDetails {
23
34
  code: number;
@@ -31,6 +42,7 @@ export interface HookContext {
31
42
  serviceName: string;
32
43
  uuid: string;
33
44
  rawData: unknown;
45
+ meta?: MessageMeta;
34
46
  }
35
47
  export interface BeforeHookContext extends HookContext {
36
48
  params: unknown;
@@ -57,16 +69,66 @@ export interface ServiceMethodMapping {
57
69
  }
58
70
  export interface TransportClientOptions {
59
71
  clientId?: string;
72
+ serviceName?: string;
73
+ authToken?: string;
60
74
  timeout?: number;
61
75
  debug?: boolean;
76
+ backoff?: {
77
+ enabled?: boolean;
78
+ baseMs?: number;
79
+ maxMs?: number;
80
+ maxAttempts?: number;
81
+ jitter?: boolean;
82
+ };
83
+ discovery?: {
84
+ enabled?: boolean;
85
+ heartbeatIntervalMs?: number;
86
+ ttlMs?: number;
87
+ };
62
88
  [key: string]: any;
63
89
  }
64
90
  export interface TransportServerOptions {
65
91
  serviceName: string;
66
92
  debug?: boolean;
93
+ authToken?: string;
67
94
  [key: string]: any;
68
95
  }
69
96
  export interface MicroserviceConfig {
70
97
  serviceName: string;
71
98
  clientName: string;
72
99
  }
100
+ export interface SubscriptionOptions {
101
+ ack?: boolean;
102
+ durableKey?: string;
103
+ groupId?: string;
104
+ fromBeginning?: boolean;
105
+ }
106
+ export interface SubscriptionContext {
107
+ ack(): Promise<void>;
108
+ nack?(reason?: string): Promise<void>;
109
+ meta: MessageMeta;
110
+ }
111
+ export interface Subscription {
112
+ unsubscribe(): Promise<void>;
113
+ }
114
+ export interface AccessRule {
115
+ topic?: string;
116
+ method?: string;
117
+ allow?: string[];
118
+ deny?: string[];
119
+ }
120
+ export interface AccessControlConfig {
121
+ rules?: AccessRule[];
122
+ allowAllByDefault?: boolean;
123
+ logDenied?: boolean;
124
+ }
125
+ export interface DiscoveryAnnouncement {
126
+ serviceName: string;
127
+ clientId?: string;
128
+ transport: string;
129
+ ts: number;
130
+ meta?: Record<string, unknown>;
131
+ }
132
+ export interface DiscoveryEntry extends DiscoveryAnnouncement {
133
+ lastSeen: number;
134
+ }
@@ -1,15 +1,17 @@
1
1
  import { Type } from "@nestjs/common";
2
- import { BeforeHook, AfterHook } from "./common";
2
+ import { BeforeHook, AfterHook, AccessControlConfig, MessageMeta } from "./common";
3
3
  export interface SignalRouterOptions {
4
4
  before?: BeforeHook;
5
5
  after?: AfterHook;
6
6
  debug?: boolean;
7
7
  eventPattern?: string;
8
+ accessControl?: AccessControlConfig;
8
9
  }
9
10
  export interface MessageData {
10
11
  method: string;
11
12
  params: any;
12
13
  uuid: string;
14
+ meta?: MessageMeta;
13
15
  }
14
16
  export type MessageExtractor = (data: any) => MessageData;
15
17
  export declare function findPropertyByType(obj: any, type: Type<any>): string | null;
@@ -5,6 +5,8 @@ exports.findServiceInstances = findServiceInstances;
5
5
  exports.createErrorResponse = createErrorResponse;
6
6
  exports.createSignalRouterDecorator = createSignalRouterDecorator;
7
7
  const common_1 = require("./common");
8
+ const access_control_1 = require("./common/access-control");
9
+ const common_2 = require("./common");
8
10
  const signal_decorator_1 = require("./signal.decorator");
9
11
  function findPropertyByType(obj, type) {
10
12
  for (const prop in obj) {
@@ -34,6 +36,49 @@ function createErrorResponse(message, uuid, method, code = 0) {
34
36
  }
35
37
  };
36
38
  }
39
+ function levenshteinDistance(a, b) {
40
+ if (a === b) {
41
+ return 0;
42
+ }
43
+ if (!a.length) {
44
+ return b.length;
45
+ }
46
+ if (!b.length) {
47
+ return a.length;
48
+ }
49
+ const matrix = Array.from({ length: a.length + 1 }, () => []);
50
+ for (let i = 0; i <= a.length; i++) {
51
+ matrix[i][0] = i;
52
+ }
53
+ for (let j = 0; j <= b.length; j++) {
54
+ matrix[0][j] = j;
55
+ }
56
+ for (let i = 1; i <= a.length; i++) {
57
+ for (let j = 1; j <= b.length; j++) {
58
+ const cost = a[i - 1] === b[j - 1] ? 0 : 1;
59
+ matrix[i][j] = Math.min(matrix[i - 1][j] + 1, matrix[i][j - 1] + 1, matrix[i - 1][j - 1] + cost);
60
+ }
61
+ }
62
+ return matrix[a.length][b.length];
63
+ }
64
+ function suggestClosestMethod(method, candidates) {
65
+ if (!candidates.length) {
66
+ return null;
67
+ }
68
+ const normalized = method.toLowerCase();
69
+ let best = null;
70
+ for (const candidate of candidates) {
71
+ const score = levenshteinDistance(normalized, candidate.toLowerCase());
72
+ if (!best || score < best.score) {
73
+ best = { name: candidate, score };
74
+ }
75
+ }
76
+ if (!best) {
77
+ return null;
78
+ }
79
+ const threshold = Math.max(2, Math.floor(method.length * 0.4));
80
+ return best.score <= threshold ? best.name : null;
81
+ }
37
82
  function createSignalRouterDecorator(serviceType, options = {}, messageExtractor, registerHandler) {
38
83
  const debug = options?.debug || process.env["NODE_ENV"] !== "production";
39
84
  return function (target) {
@@ -45,7 +90,7 @@ function createSignalRouterDecorator(serviceType, options = {}, messageExtractor
45
90
  console.log(`[${eventPattern}] Received message:`, (0, common_1.stringifyWithBigInt)(data));
46
91
  }
47
92
  const messageData = messageExtractor(data);
48
- const { method, params, uuid } = messageData;
93
+ const { method, params, uuid, meta } = messageData;
49
94
  if (!method) {
50
95
  console.error("Missing 'method' field in message");
51
96
  return createErrorResponse("Invalid message format");
@@ -58,6 +103,20 @@ function createSignalRouterDecorator(serviceType, options = {}, messageExtractor
58
103
  console.error(`No service instances found for:`, serviceType);
59
104
  return createErrorResponse("Service not found", uuid, method);
60
105
  }
106
+ const callerService = (0, access_control_1.extractCallerService)(meta);
107
+ const topic = eventPattern;
108
+ if (!(0, access_control_1.isAccessAllowed)(options.accessControl, topic, method, callerService)) {
109
+ (0, access_control_1.logAccessDenied)(options.accessControl, { topic, method, serviceName: eventPattern, callerService });
110
+ return {
111
+ uuid,
112
+ method,
113
+ params: {
114
+ result: "error",
115
+ error: (0, access_control_1.createAccessDeniedError)(method, eventPattern, callerService)
116
+ },
117
+ meta
118
+ };
119
+ }
61
120
  let processedParams = params;
62
121
  if (options.before) {
63
122
  const hookResult = await options.before({
@@ -65,7 +124,8 @@ function createSignalRouterDecorator(serviceType, options = {}, messageExtractor
65
124
  serviceName: eventPattern,
66
125
  uuid,
67
126
  rawData: data,
68
- params
127
+ params,
128
+ meta
69
129
  });
70
130
  if (hookResult !== undefined) {
71
131
  processedParams = hookResult;
@@ -75,7 +135,9 @@ function createSignalRouterDecorator(serviceType, options = {}, messageExtractor
75
135
  const signalHandler = signals.find((s) => s.signalName === method);
76
136
  if (!signalHandler) {
77
137
  console.error(`No handler found for method:`, method);
78
- return createErrorResponse(`Method ${method} not found`, uuid, method);
138
+ const suggestion = suggestClosestMethod(method, signals.map((s) => s.signalName));
139
+ const message = suggestion ? `Invalid method name '${method}', did you mean '${suggestion}'?` : `Method ${method} not found`;
140
+ return createErrorResponse(message, uuid, method);
79
141
  }
80
142
  let serviceInstance = null;
81
143
  const serviceMethod = signalHandler.methodName;
@@ -101,7 +163,8 @@ function createSignalRouterDecorator(serviceType, options = {}, messageExtractor
101
163
  let response = {
102
164
  uuid,
103
165
  method,
104
- params: { result: serializedResult }
166
+ params: { result: serializedResult },
167
+ meta
105
168
  };
106
169
  if (options.after) {
107
170
  const hookResponse = await options.after({
@@ -111,7 +174,8 @@ function createSignalRouterDecorator(serviceType, options = {}, messageExtractor
111
174
  rawData: data,
112
175
  params: processedParams,
113
176
  result: serializedResult,
114
- response
177
+ response,
178
+ meta
115
179
  });
116
180
  if (hookResponse !== undefined) {
117
181
  response = hookResponse;
@@ -122,7 +186,7 @@ function createSignalRouterDecorator(serviceType, options = {}, messageExtractor
122
186
  catch (error) {
123
187
  const errorMessage = error instanceof Error ? error.message : "Unknown error";
124
188
  console.error(`[${eventPattern}] Processing error:`, error);
125
- return createErrorResponse(errorMessage, data.uuid, data.method, error.code);
189
+ return createErrorResponse(errorMessage, data.uuid, data.method, error.code || common_2.ErrorCode.UNKNOWN);
126
190
  }
127
191
  };
128
192
  registerHandler(target, eventPattern, handlerName);
@@ -0,0 +1,13 @@
1
+ import { NevoHttpClient } from "./nevo-http.client";
2
+ export declare abstract class HttpClientBase {
3
+ protected readonly universalClient: NevoHttpClient;
4
+ protected constructor(universalClient: NevoHttpClient);
5
+ protected query<T = any>(serviceName: string, method: string, params: any): Promise<T>;
6
+ protected emit(serviceName: string, method: string, params: any): Promise<void>;
7
+ protected publish(serviceName: string, method: string, params: any): Promise<void>;
8
+ protected broadcast(method: string, params: any): Promise<void>;
9
+ protected subscribe<T = any>(serviceName: string, method: string, options: Parameters<NevoHttpClient["subscribe"]>[2], handler: Parameters<NevoHttpClient["subscribe"]>[3]): Promise<import("../..").Subscription>;
10
+ protected getAvailableServices(): string[];
11
+ protected getDiscoveredServices(): import("../..").DiscoveryEntry[];
12
+ protected isServiceAvailable(serviceName: string): boolean;
13
+ }
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.HttpClientBase = void 0;
4
+ class HttpClientBase {
5
+ constructor(universalClient) {
6
+ this.universalClient = universalClient;
7
+ }
8
+ async query(serviceName, method, params) {
9
+ return this.universalClient.query(serviceName, method, params);
10
+ }
11
+ async emit(serviceName, method, params) {
12
+ return this.universalClient.emit(serviceName, method, params);
13
+ }
14
+ async publish(serviceName, method, params) {
15
+ return this.universalClient.publish(serviceName, method, params);
16
+ }
17
+ async broadcast(method, params) {
18
+ return this.universalClient.broadcast(method, params);
19
+ }
20
+ async subscribe(serviceName, method, options, handler) {
21
+ return this.universalClient.subscribe(serviceName, method, options, handler);
22
+ }
23
+ getAvailableServices() {
24
+ return this.universalClient.getAvailableServices();
25
+ }
26
+ getDiscoveredServices() {
27
+ return this.universalClient.getDiscoveredServices();
28
+ }
29
+ isServiceAvailable(serviceName) {
30
+ return this.universalClient.isServiceAvailable(serviceName);
31
+ }
32
+ }
33
+ exports.HttpClientBase = HttpClientBase;
@@ -0,0 +1,8 @@
1
+ import { NevoHttpClient, NevoHttpClientOptions } from "./nevo-http.client";
2
+ export interface HttpClientFactoryOptions extends NevoHttpClientOptions {
3
+ clientIdPrefix: string;
4
+ }
5
+ export declare const createNevoHttpClient: (serviceUrls: Record<string, string>, options: HttpClientFactoryOptions) => {
6
+ provide: string;
7
+ useFactory: () => Promise<NevoHttpClient>;
8
+ };
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createNevoHttpClient = void 0;
4
+ const nevo_http_client_1 = require("./nevo-http.client");
5
+ const createNevoHttpClient = (serviceUrls, options) => {
6
+ return {
7
+ provide: "NEVO_HTTP_CLIENT",
8
+ useFactory: async () => {
9
+ return new nevo_http_client_1.NevoHttpClient(serviceUrls, {
10
+ ...options,
11
+ serviceName: options.serviceName || options.clientIdPrefix
12
+ });
13
+ }
14
+ };
15
+ };
16
+ exports.createNevoHttpClient = createNevoHttpClient;
@@ -0,0 +1,3 @@
1
+ import { Type } from "@nestjs/common";
2
+ import { SignalRouterOptions } from "../../signal-router.utils";
3
+ export declare function HttpSignalRouter(serviceType: Type<any> | Type<any>[], options?: SignalRouterOptions): (target: any) => any;
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.HttpSignalRouter = HttpSignalRouter;
4
+ const common_1 = require("@nestjs/common");
5
+ const signal_router_utils_1 = require("../../signal-router.utils");
6
+ function HttpSignalRouter(serviceType, options) {
7
+ return (0, signal_router_utils_1.createSignalRouterDecorator)(serviceType, options, (data) => {
8
+ const messageData = data || {};
9
+ return {
10
+ method: messageData.method,
11
+ params: messageData.params,
12
+ uuid: messageData.uuid,
13
+ meta: messageData.meta
14
+ };
15
+ }, (target, eventPattern, handlerName) => {
16
+ (0, common_1.Post)(`/${eventPattern}`)(target.prototype, handlerName, Object.getOwnPropertyDescriptor(target.prototype, handlerName));
17
+ });
18
+ }
@@ -0,0 +1,21 @@
1
+ import { Observable } from "rxjs";
2
+ export declare class HttpTransportController {
3
+ streamDiscovery(): Observable<{
4
+ data: string;
5
+ }>;
6
+ publishDiscovery(payload: any): {
7
+ ok: boolean;
8
+ };
9
+ streamSubscription(service: string): Observable<{
10
+ data: string;
11
+ }>;
12
+ publishSubscription(payload: any): {
13
+ ok: boolean;
14
+ };
15
+ streamBroadcast(): Observable<{
16
+ data: string;
17
+ }>;
18
+ publishBroadcast(payload: any): {
19
+ ok: boolean;
20
+ };
21
+ }