1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93 | 1x
1x
1x
1x
1x
1x
1x
51x
5x
1x
4x
2x
2x
2x
4x
3x
1x
2x
1x
1x
5x
5x
4x
4x
4x
124x
11x
| import { randomStringGenerator } from '@nestjs/common/utils/random-string-generator.util';
import { isNil, isString } from '@nestjs/common/utils/shared.utils';
import {
defer,
fromEvent,
merge,
Observable,
Observer,
throwError as _throw,
} from 'rxjs';
import { map, mergeMap, take } from 'rxjs/operators';
import { CONNECT_EVENT, ERROR_EVENT } from '../constants';
import { InvalidMessageException } from '../exceptions/errors/invalid-message.exception';
import {
ClientOptions,
PacketId,
ReadPacket,
WritePacket,
} from '../interfaces';
export abstract class ClientProxy {
public abstract connect(): Promise<any>;
public abstract close(): any;
protected routingMap = new Map<string, Function>();
public send<TResult = any, TInput = any>(
pattern: any,
data: TInput,
): Observable<TResult> {
if (isNil(pattern) || isNil(data)) {
return _throw(new InvalidMessageException());
}
return defer(async () => this.connect()).pipe(
mergeMap(
() =>
new Observable((observer: Observer<TResult>) => {
const callback = this.createObserver(observer);
return this.publish({ pattern, data }, callback);
}),
),
);
}
protected abstract publish(
packet: ReadPacket,
callback: (packet: WritePacket) => void,
): Function | void;
protected createObserver<T>(
observer: Observer<T>,
): (packet: WritePacket) => void {
return ({ err, response, isDisposed }: WritePacket) => {
if (err) {
return observer.error(err);
} else if (isDisposed) {
return observer.complete();
}
observer.next(response);
};
}
protected assignPacketId(packet: ReadPacket): ReadPacket & PacketId {
const id = randomStringGenerator();
return Object.assign(packet, { id });
}
protected connect$(
instance: any,
errorEvent = ERROR_EVENT,
connectEvent = CONNECT_EVENT,
): Observable<any> {
const error$ = fromEvent(instance, errorEvent).pipe(
map(err => {
throw err;
}),
);
const connect$ = fromEvent(instance, connectEvent);
return merge(error$, connect$).pipe(take(1));
}
protected getOptionsProp<T extends { options? }>(
obj: ClientOptions['options'],
prop: keyof T['options'],
defaultValue = undefined,
) {
return obj ? obj[prop as string] : defaultValue;
}
protected normalizePattern<T = any>(pattern: T): string {
return isString(pattern) ? pattern : JSON.stringify(pattern);
}
}
|