@riaskov/nevo-messaging 1.0.1 → 1.1.1
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 +1 -1
- package/README.md +241 -56
- package/dist/common/access-control.d.ts +15 -0
- package/dist/common/access-control.js +94 -0
- package/dist/common/base.client.d.ts +7 -2
- package/dist/common/base.client.js +16 -2
- package/dist/common/base.controller.d.ts +6 -1
- package/dist/common/base.controller.js +68 -4
- package/dist/common/constants.d.ts +4 -0
- package/dist/common/constants.js +7 -0
- package/dist/common/discovery.d.ts +8 -0
- package/dist/common/discovery.js +35 -0
- package/dist/common/error-code.d.ts +2 -1
- package/dist/common/error-code.js +1 -0
- package/dist/common/error-messages.js +2 -1
- package/dist/common/index.d.ts +3 -0
- package/dist/common/index.js +3 -0
- package/dist/common/service-utils.d.ts +2 -0
- package/dist/common/service-utils.js +8 -0
- package/dist/common/types.d.ts +62 -0
- package/dist/signal-router.utils.d.ts +3 -1
- package/dist/signal-router.utils.js +70 -6
- package/dist/transports/http/http.client-base.d.ts +13 -0
- package/dist/transports/http/http.client-base.js +33 -0
- package/dist/transports/http/http.config.d.ts +8 -0
- package/dist/transports/http/http.config.js +16 -0
- package/dist/transports/http/http.signal-router.decorator.d.ts +3 -0
- package/dist/transports/http/http.signal-router.decorator.js +18 -0
- package/dist/transports/http/http.transport.controller.d.ts +21 -0
- package/dist/transports/http/http.transport.controller.js +114 -0
- package/dist/transports/http/index.d.ts +5 -0
- package/dist/transports/http/index.js +21 -0
- package/dist/transports/http/nevo-http.client.d.ts +54 -0
- package/dist/transports/http/nevo-http.client.js +280 -0
- package/dist/transports/index.d.ts +3 -0
- package/dist/transports/index.js +3 -0
- package/dist/transports/kafka/kafka.client-base.d.ts +5 -0
- package/dist/transports/kafka/kafka.client-base.js +15 -0
- package/dist/transports/kafka/kafka.config.d.ts +7 -0
- package/dist/transports/kafka/kafka.config.js +48 -2
- package/dist/transports/kafka/kafka.signal-router.decorator.js +2 -1
- package/dist/transports/kafka/nevo-kafka.client.d.ts +42 -0
- package/dist/transports/kafka/nevo-kafka.client.js +210 -4
- package/dist/transports/nats/index.d.ts +4 -0
- package/dist/transports/nats/index.js +20 -0
- package/dist/transports/nats/nats.client-base.d.ts +13 -0
- package/dist/transports/nats/nats.client-base.js +33 -0
- package/dist/transports/nats/nats.config.d.ts +8 -0
- package/dist/transports/nats/nats.config.js +16 -0
- package/dist/transports/nats/nats.signal-router.decorator.d.ts +6 -0
- package/dist/transports/nats/nats.signal-router.decorator.js +49 -0
- package/dist/transports/nats/nevo-nats.client.d.ts +55 -0
- package/dist/transports/nats/nevo-nats.client.js +210 -0
- package/dist/transports/socket-io/index.d.ts +4 -0
- package/dist/transports/socket-io/index.js +20 -0
- package/dist/transports/socket-io/nevo-socket.client.d.ts +50 -0
- package/dist/transports/socket-io/nevo-socket.client.js +202 -0
- package/dist/transports/socket-io/socket.client-base.d.ts +13 -0
- package/dist/transports/socket-io/socket.client-base.js +33 -0
- package/dist/transports/socket-io/socket.config.d.ts +8 -0
- package/dist/transports/socket-io/socket.config.js +16 -0
- package/dist/transports/socket-io/socket.signal-router.decorator.d.ts +13 -0
- package/dist/transports/socket-io/socket.signal-router.decorator.js +109 -0
- package/package.json +11 -5
|
@@ -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;
|
|
@@ -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
|
};
|
package/dist/common/index.d.ts
CHANGED
package/dist/common/index.js
CHANGED
|
@@ -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;
|
package/dist/common/types.d.ts
CHANGED
|
@@ -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
|
-
|
|
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,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
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
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
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.HttpTransportController = void 0;
|
|
16
|
+
const common_1 = require("@nestjs/common");
|
|
17
|
+
const rxjs_1 = require("rxjs");
|
|
18
|
+
const operators_1 = require("rxjs/operators");
|
|
19
|
+
const common_2 = require("../../common");
|
|
20
|
+
class HttpSseBroker {
|
|
21
|
+
constructor() {
|
|
22
|
+
this.channels = new Map();
|
|
23
|
+
}
|
|
24
|
+
stream(channel) {
|
|
25
|
+
const subject = this.getChannel(channel);
|
|
26
|
+
return subject.asObservable().pipe((0, operators_1.map)((data) => ({ data })));
|
|
27
|
+
}
|
|
28
|
+
publish(channel, payload) {
|
|
29
|
+
const subject = this.getChannel(channel);
|
|
30
|
+
subject.next((0, common_2.stringifyWithBigInt)(payload));
|
|
31
|
+
}
|
|
32
|
+
getChannel(channel) {
|
|
33
|
+
let subject = this.channels.get(channel);
|
|
34
|
+
if (!subject) {
|
|
35
|
+
subject = new rxjs_1.Subject();
|
|
36
|
+
this.channels.set(channel, subject);
|
|
37
|
+
}
|
|
38
|
+
return subject;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
const broker = new HttpSseBroker();
|
|
42
|
+
let HttpTransportController = class HttpTransportController {
|
|
43
|
+
streamDiscovery() {
|
|
44
|
+
return broker.stream(common_2.DEFAULT_DISCOVERY_TOPIC);
|
|
45
|
+
}
|
|
46
|
+
publishDiscovery(payload) {
|
|
47
|
+
broker.publish(common_2.DEFAULT_DISCOVERY_TOPIC, payload);
|
|
48
|
+
return { ok: true };
|
|
49
|
+
}
|
|
50
|
+
streamSubscription(service) {
|
|
51
|
+
const channel = `${service.toLowerCase()}${common_2.DEFAULT_SUBSCRIPTION_SUFFIX}`;
|
|
52
|
+
return broker.stream(channel);
|
|
53
|
+
}
|
|
54
|
+
publishSubscription(payload) {
|
|
55
|
+
const serviceName = payload?.serviceName;
|
|
56
|
+
if (!serviceName) {
|
|
57
|
+
return { ok: false };
|
|
58
|
+
}
|
|
59
|
+
const channel = `${serviceName.toLowerCase()}${common_2.DEFAULT_SUBSCRIPTION_SUFFIX}`;
|
|
60
|
+
broker.publish(channel, payload);
|
|
61
|
+
return { ok: true };
|
|
62
|
+
}
|
|
63
|
+
streamBroadcast() {
|
|
64
|
+
return broker.stream(common_2.DEFAULT_BROADCAST_TOPIC);
|
|
65
|
+
}
|
|
66
|
+
publishBroadcast(payload) {
|
|
67
|
+
broker.publish(common_2.DEFAULT_BROADCAST_TOPIC, payload);
|
|
68
|
+
return { ok: true };
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
exports.HttpTransportController = HttpTransportController;
|
|
72
|
+
__decorate([
|
|
73
|
+
(0, common_1.Sse)(`/${common_2.DEFAULT_DISCOVERY_TOPIC}`),
|
|
74
|
+
__metadata("design:type", Function),
|
|
75
|
+
__metadata("design:paramtypes", []),
|
|
76
|
+
__metadata("design:returntype", rxjs_1.Observable)
|
|
77
|
+
], HttpTransportController.prototype, "streamDiscovery", null);
|
|
78
|
+
__decorate([
|
|
79
|
+
(0, common_1.Post)(`/${common_2.DEFAULT_DISCOVERY_TOPIC}`),
|
|
80
|
+
__param(0, (0, common_1.Body)()),
|
|
81
|
+
__metadata("design:type", Function),
|
|
82
|
+
__metadata("design:paramtypes", [Object]),
|
|
83
|
+
__metadata("design:returntype", void 0)
|
|
84
|
+
], HttpTransportController.prototype, "publishDiscovery", null);
|
|
85
|
+
__decorate([
|
|
86
|
+
(0, common_1.Sse)(`/__nevo/subscribe`),
|
|
87
|
+
__param(0, (0, common_1.Query)("service")),
|
|
88
|
+
__metadata("design:type", Function),
|
|
89
|
+
__metadata("design:paramtypes", [String]),
|
|
90
|
+
__metadata("design:returntype", rxjs_1.Observable)
|
|
91
|
+
], HttpTransportController.prototype, "streamSubscription", null);
|
|
92
|
+
__decorate([
|
|
93
|
+
(0, common_1.Post)(`/__nevo/publish`),
|
|
94
|
+
__param(0, (0, common_1.Body)()),
|
|
95
|
+
__metadata("design:type", Function),
|
|
96
|
+
__metadata("design:paramtypes", [Object]),
|
|
97
|
+
__metadata("design:returntype", void 0)
|
|
98
|
+
], HttpTransportController.prototype, "publishSubscription", null);
|
|
99
|
+
__decorate([
|
|
100
|
+
(0, common_1.Sse)(`/${common_2.DEFAULT_BROADCAST_TOPIC}`),
|
|
101
|
+
__metadata("design:type", Function),
|
|
102
|
+
__metadata("design:paramtypes", []),
|
|
103
|
+
__metadata("design:returntype", rxjs_1.Observable)
|
|
104
|
+
], HttpTransportController.prototype, "streamBroadcast", null);
|
|
105
|
+
__decorate([
|
|
106
|
+
(0, common_1.Post)(`/${common_2.DEFAULT_BROADCAST_TOPIC}`),
|
|
107
|
+
__param(0, (0, common_1.Body)()),
|
|
108
|
+
__metadata("design:type", Function),
|
|
109
|
+
__metadata("design:paramtypes", [Object]),
|
|
110
|
+
__metadata("design:returntype", void 0)
|
|
111
|
+
], HttpTransportController.prototype, "publishBroadcast", null);
|
|
112
|
+
exports.HttpTransportController = HttpTransportController = __decorate([
|
|
113
|
+
(0, common_1.Controller)()
|
|
114
|
+
], HttpTransportController);
|
|
@@ -0,0 +1,21 @@
|
|
|
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("./nevo-http.client"), exports);
|
|
18
|
+
__exportStar(require("./http.client-base"), exports);
|
|
19
|
+
__exportStar(require("./http.signal-router.decorator"), exports);
|
|
20
|
+
__exportStar(require("./http.transport.controller"), exports);
|
|
21
|
+
__exportStar(require("./http.config"), exports);
|