hl7v2-net 1.4.4 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cjs/helpers/frame-stream.js +9 -2
- package/cjs/helpers/hl7-exchange-error.js +2 -0
- package/cjs/hl7-client.js +108 -41
- package/cjs/hl7-request.js +2 -0
- package/cjs/hl7-response.js +4 -2
- package/cjs/hl7-router.js +3 -5
- package/cjs/hl7-server.js +10 -4
- package/cjs/hl7-socket.js +66 -25
- package/esm/helpers/frame-stream.js +9 -2
- package/esm/helpers/hl7-exchange-error.js +2 -0
- package/esm/hl7-client.js +108 -41
- package/esm/hl7-request.js +2 -0
- package/esm/hl7-response.js +4 -2
- package/esm/hl7-router.js +3 -5
- package/esm/hl7-server.js +10 -4
- package/esm/hl7-socket.js +66 -25
- package/package.json +7 -5
- package/types/hl7-client.d.ts +21 -3
- package/types/hl7-server.d.ts +2 -1
- package/types/hl7-socket.d.ts +10 -6
|
@@ -4,14 +4,21 @@ exports.FrameStream = void 0;
|
|
|
4
4
|
const node_buffer_1 = require("node:buffer");
|
|
5
5
|
const node_stream_1 = require("node:stream");
|
|
6
6
|
class FrameStream extends node_stream_1.Transform {
|
|
7
|
+
_chunks = [];
|
|
8
|
+
_chunkBuffer;
|
|
9
|
+
_flushTimeout;
|
|
10
|
+
_frameDelayMs;
|
|
11
|
+
_frameStart;
|
|
12
|
+
_frameEnd;
|
|
13
|
+
_bufferSize = 0;
|
|
14
|
+
_customTransform;
|
|
15
|
+
maxBufferSize;
|
|
7
16
|
constructor(opts) {
|
|
8
17
|
super({
|
|
9
18
|
...opts,
|
|
10
19
|
objectMode: true,
|
|
11
20
|
transform: undefined,
|
|
12
21
|
});
|
|
13
|
-
this._chunks = [];
|
|
14
|
-
this._bufferSize = 0;
|
|
15
22
|
this._customTransform = opts?.transform;
|
|
16
23
|
this._frameDelayMs = opts?.frameDelayMs || (opts?.frameEnd ? 0 : 500);
|
|
17
24
|
this.maxBufferSize = opts?.maxBufferSize;
|
|
@@ -3,6 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.HL7ExchangeError = void 0;
|
|
4
4
|
const hl7v2_1 = require("hl7v2");
|
|
5
5
|
class HL7ExchangeError extends hl7v2_1.HL7Error {
|
|
6
|
+
request;
|
|
7
|
+
response;
|
|
6
8
|
constructor(message, args) {
|
|
7
9
|
super(message, args);
|
|
8
10
|
if (args?.request)
|
package/cjs/hl7-client.js
CHANGED
|
@@ -5,11 +5,17 @@ const tslib_1 = require("tslib");
|
|
|
5
5
|
const node_net_1 = tslib_1.__importDefault(require("node:net"));
|
|
6
6
|
const node_tls_1 = tslib_1.__importDefault(require("node:tls"));
|
|
7
7
|
const node_events_async_1 = require("node-events-async");
|
|
8
|
+
const reconnect_core_1 = tslib_1.__importDefault(require("reconnect-core"));
|
|
8
9
|
const hl7_request_js_1 = require("./hl7-request.js");
|
|
9
10
|
const hl7_response_js_1 = require("./hl7-response.js");
|
|
10
11
|
const hl7_router_js_1 = require("./hl7-router.js");
|
|
11
12
|
const hl7_socket_js_1 = require("./hl7-socket.js");
|
|
12
13
|
class Hl7Client extends node_events_async_1.AsyncEventEmitter {
|
|
14
|
+
_connectionManager;
|
|
15
|
+
_router = new hl7_router_js_1.HL7Router();
|
|
16
|
+
_socket;
|
|
17
|
+
_tls;
|
|
18
|
+
_options;
|
|
13
19
|
/**
|
|
14
20
|
* Creates an HL7 TCP client
|
|
15
21
|
* @static
|
|
@@ -35,8 +41,60 @@ class Hl7Client extends node_events_async_1.AsyncEventEmitter {
|
|
|
35
41
|
*/
|
|
36
42
|
constructor(options) {
|
|
37
43
|
super();
|
|
38
|
-
this._router = new hl7_router_js_1.HL7Router();
|
|
39
44
|
this._options = options;
|
|
45
|
+
let reconnecting = false;
|
|
46
|
+
const connectionManager = (this._connectionManager = socketReconnect({
|
|
47
|
+
...this._options.reconnect,
|
|
48
|
+
timeout: this._options.connectTimeout,
|
|
49
|
+
})
|
|
50
|
+
.on('error', err => {
|
|
51
|
+
if (!connectionManager.reconnect)
|
|
52
|
+
return;
|
|
53
|
+
this.emit('error', err);
|
|
54
|
+
})
|
|
55
|
+
.on('connect', (tcpSocket) => {
|
|
56
|
+
if (!this._socket) {
|
|
57
|
+
const socket = (this._socket = new hl7_socket_js_1.HL7Socket(tcpSocket, this._options));
|
|
58
|
+
socket.on('connect', () => this.emit('connect'));
|
|
59
|
+
socket.on('ready', () => this.emit('ready'));
|
|
60
|
+
socket.on('lookup', (err, address, family, host) => this.emit('lookup', err, address, family, host));
|
|
61
|
+
socket.on('close', () => {
|
|
62
|
+
this._socket = undefined;
|
|
63
|
+
this.emit('close');
|
|
64
|
+
});
|
|
65
|
+
socket.on('error', err => this.emit('error', err));
|
|
66
|
+
socket.on('message', message => {
|
|
67
|
+
this.emit('message', message);
|
|
68
|
+
this._onMessage(message);
|
|
69
|
+
});
|
|
70
|
+
socket.on('send', message => this.emit('send', message));
|
|
71
|
+
socket.on('data', data => this.emit('data', data));
|
|
72
|
+
}
|
|
73
|
+
else
|
|
74
|
+
this._socket._bindSocket(tcpSocket);
|
|
75
|
+
if (reconnecting)
|
|
76
|
+
this.emit('reconnect', tcpSocket);
|
|
77
|
+
reconnecting = false;
|
|
78
|
+
this.emit('connect');
|
|
79
|
+
})
|
|
80
|
+
.on('reconnect', (n, delay) => {
|
|
81
|
+
if (n === 0 && delay === 0)
|
|
82
|
+
return;
|
|
83
|
+
reconnecting = true;
|
|
84
|
+
this.emit('reconnecting', n, delay);
|
|
85
|
+
})
|
|
86
|
+
.on('disconnect', err => {
|
|
87
|
+
this._socket = undefined;
|
|
88
|
+
if (connectionManager.reconnect) {
|
|
89
|
+
if (err)
|
|
90
|
+
err.message = `TCP socket connection lost: ${err.message}`;
|
|
91
|
+
else
|
|
92
|
+
err = new Error('TCP socket connection lost');
|
|
93
|
+
this.emit('disconnect', err);
|
|
94
|
+
}
|
|
95
|
+
else
|
|
96
|
+
this.emit('disconnect');
|
|
97
|
+
}));
|
|
40
98
|
}
|
|
41
99
|
get connected() {
|
|
42
100
|
return this._socket?.connected ?? false;
|
|
@@ -81,57 +139,32 @@ class Hl7Client extends node_events_async_1.AsyncEventEmitter {
|
|
|
81
139
|
if (this._socket)
|
|
82
140
|
this._socket.maxBufferSize = value;
|
|
83
141
|
}
|
|
84
|
-
connect() {
|
|
142
|
+
async connect() {
|
|
143
|
+
if (this.connected)
|
|
144
|
+
return;
|
|
85
145
|
return new Promise((resolve, reject) => {
|
|
86
|
-
if (this.connected) {
|
|
87
|
-
resolve();
|
|
88
|
-
return;
|
|
89
|
-
}
|
|
90
|
-
let timeoutTimer;
|
|
91
|
-
const tcpSocket = this._tls
|
|
92
|
-
? node_tls_1.default.connect(this._options)
|
|
93
|
-
: node_net_1.default.connect(this._options);
|
|
94
|
-
const socket = (this._socket = new hl7_socket_js_1.HL7Socket(tcpSocket, this._options));
|
|
95
|
-
socket.on('connect', () => this.emit('connect'));
|
|
96
|
-
socket.on('ready', () => this.emit('ready'));
|
|
97
|
-
socket.on('lookup', (err, address, family, host) => this.emit('lookup', err, address, family, host));
|
|
98
|
-
socket.on('close', () => {
|
|
99
|
-
this._socket = undefined;
|
|
100
|
-
this.emit('close');
|
|
101
|
-
});
|
|
102
|
-
socket.on('error', err => this.emit('error', err));
|
|
103
|
-
socket.on('message', message => {
|
|
104
|
-
this.emit('message', message);
|
|
105
|
-
this._onMessage(message);
|
|
106
|
-
});
|
|
107
|
-
socket.on('send', message => this.emit('send', message));
|
|
108
|
-
socket.on('data', data => this.emit('data', data));
|
|
109
146
|
const onReady = () => {
|
|
110
|
-
|
|
111
|
-
tcpSocket.removeListener('error', onError);
|
|
112
|
-
if (this._options.keepAlive) {
|
|
113
|
-
tcpSocket.setKeepAlive(this._options.keepAlive, this._options.keepAliveInitialDelay);
|
|
114
|
-
}
|
|
147
|
+
this.removeListener('error', onError);
|
|
115
148
|
resolve();
|
|
116
149
|
};
|
|
117
150
|
const onError = (error) => {
|
|
118
|
-
|
|
119
|
-
tcpSocket.removeListener('ready', onReady);
|
|
120
|
-
tcpSocket.destroy();
|
|
151
|
+
this.removeListener('ready', onReady);
|
|
121
152
|
reject(error);
|
|
122
153
|
};
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
}
|
|
154
|
+
this.once('ready', onReady);
|
|
155
|
+
this.once('error', onError);
|
|
156
|
+
this._connectionManager.reconnect = true;
|
|
157
|
+
this._connectionManager.connect({
|
|
158
|
+
tls: this._tls,
|
|
159
|
+
options: this._options,
|
|
160
|
+
});
|
|
131
161
|
});
|
|
132
162
|
}
|
|
133
163
|
async close(waitRunningHandlers) {
|
|
164
|
+
this._connectionManager.reconnect = false;
|
|
134
165
|
await this._socket?.close(waitRunningHandlers);
|
|
166
|
+
this._connectionManager.disconnect();
|
|
167
|
+
this._connectionManager.reset();
|
|
135
168
|
}
|
|
136
169
|
async sendMessage(message) {
|
|
137
170
|
if (!this.connected)
|
|
@@ -161,3 +194,37 @@ class Hl7Client extends node_events_async_1.AsyncEventEmitter {
|
|
|
161
194
|
}
|
|
162
195
|
}
|
|
163
196
|
exports.Hl7Client = Hl7Client;
|
|
197
|
+
const socketReconnect = (0, reconnect_core_1.default)((args) => {
|
|
198
|
+
const tcpSocket = args.tls
|
|
199
|
+
? node_tls_1.default.connect({
|
|
200
|
+
...args.options,
|
|
201
|
+
timeout: undefined,
|
|
202
|
+
})
|
|
203
|
+
: node_net_1.default.connect({
|
|
204
|
+
...args.options,
|
|
205
|
+
timeout: undefined,
|
|
206
|
+
});
|
|
207
|
+
if (args.options.timeout) {
|
|
208
|
+
const timer = setTimeout(() => {
|
|
209
|
+
tcpSocket.destroy(new Error('Connection timed out'));
|
|
210
|
+
}, args.options.timeout).unref();
|
|
211
|
+
const onConnect = () => {
|
|
212
|
+
clearTimeout(timer);
|
|
213
|
+
tcpSocket.removeListener('error', onError);
|
|
214
|
+
};
|
|
215
|
+
const onError = () => {
|
|
216
|
+
clearTimeout(timer);
|
|
217
|
+
tcpSocket.removeListener('connect', onConnect);
|
|
218
|
+
tcpSocket.removeListener('ready', onReady);
|
|
219
|
+
};
|
|
220
|
+
const onReady = () => {
|
|
221
|
+
if (args.options.keepAlive) {
|
|
222
|
+
tcpSocket.setKeepAlive(args.options.keepAlive, args.options.keepAliveInitialDelay);
|
|
223
|
+
}
|
|
224
|
+
};
|
|
225
|
+
tcpSocket.once('connect', onConnect);
|
|
226
|
+
tcpSocket.once('error', onError);
|
|
227
|
+
tcpSocket.once('ready', onReady);
|
|
228
|
+
}
|
|
229
|
+
return tcpSocket;
|
|
230
|
+
});
|
package/cjs/hl7-request.js
CHANGED
package/cjs/hl7-response.js
CHANGED
|
@@ -3,9 +3,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.HL7Response = void 0;
|
|
4
4
|
const hl7v2_1 = require("hl7v2");
|
|
5
5
|
class HL7Response {
|
|
6
|
+
_finished = false;
|
|
7
|
+
request;
|
|
8
|
+
errors = [];
|
|
9
|
+
message;
|
|
6
10
|
constructor(request) {
|
|
7
|
-
this._finished = false;
|
|
8
|
-
this.errors = [];
|
|
9
11
|
this.request = request;
|
|
10
12
|
this.message = request.message.createAck();
|
|
11
13
|
request.socket.once('send', () => {
|
package/cjs/hl7-router.js
CHANGED
|
@@ -2,11 +2,9 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.HL7Router = void 0;
|
|
4
4
|
class HL7Router {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
this._handlers = [];
|
|
9
|
-
}
|
|
5
|
+
_handlerStack = new Map();
|
|
6
|
+
_needPrepare = true;
|
|
7
|
+
_handlers = [];
|
|
10
8
|
use(handler, priority = 0) {
|
|
11
9
|
let list = this._handlerStack[priority];
|
|
12
10
|
if (!list) {
|
package/cjs/hl7-server.js
CHANGED
|
@@ -13,6 +13,14 @@ const hl7_response_js_1 = require("./hl7-response.js");
|
|
|
13
13
|
const hl7_router_js_1 = require("./hl7-router.js");
|
|
14
14
|
const hl7_socket_js_1 = require("./hl7-socket.js");
|
|
15
15
|
class HL7Server extends node_events_async_1.AsyncEventEmitter {
|
|
16
|
+
_server;
|
|
17
|
+
_sockets = new Set();
|
|
18
|
+
_router = new hl7_router_js_1.HL7Router();
|
|
19
|
+
_runningHandlers = new Set();
|
|
20
|
+
_closing;
|
|
21
|
+
parseStrict;
|
|
22
|
+
maxBufferPerSocket;
|
|
23
|
+
responseTimeout;
|
|
16
24
|
/**
|
|
17
25
|
* Creates a HL7 TCP server
|
|
18
26
|
* @static
|
|
@@ -34,9 +42,6 @@ class HL7Server extends node_events_async_1.AsyncEventEmitter {
|
|
|
34
42
|
*/
|
|
35
43
|
constructor(server, options) {
|
|
36
44
|
super();
|
|
37
|
-
this._sockets = new Set();
|
|
38
|
-
this._router = new hl7_router_js_1.HL7Router();
|
|
39
|
-
this._runningHandlers = new Set();
|
|
40
45
|
this.maxBufferPerSocket = options?.maxBufferPerSocket;
|
|
41
46
|
this.responseTimeout = options?.responseTimeout;
|
|
42
47
|
this.parseStrict = options?.parseStrict;
|
|
@@ -197,7 +202,8 @@ class HL7Server extends node_events_async_1.AsyncEventEmitter {
|
|
|
197
202
|
this._onMessage(message, socket);
|
|
198
203
|
});
|
|
199
204
|
socket.on('send', message => this.emit('send', message, socket));
|
|
200
|
-
socket.on('data', data => this.emit('data', data));
|
|
205
|
+
socket.on('data', data => this.emit('data', data, socket));
|
|
206
|
+
socket.on('write', data => this.emit('write', data, socket));
|
|
201
207
|
this.emit('connection', socket);
|
|
202
208
|
}
|
|
203
209
|
_onMessage(message, socket) {
|
package/cjs/hl7-socket.js
CHANGED
|
@@ -2,41 +2,39 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.HL7Socket = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
|
+
const node_buffer_1 = require("node:buffer");
|
|
5
6
|
const hl7v2_1 = require("hl7v2");
|
|
6
7
|
const iconv_lite_1 = tslib_1.__importDefault(require("iconv-lite"));
|
|
7
8
|
const node_events_async_1 = require("node-events-async");
|
|
8
9
|
const frame_stream_js_1 = require("./helpers/frame-stream.js");
|
|
9
10
|
class HL7Socket extends node_events_async_1.AsyncEventEmitter {
|
|
11
|
+
_messageHooks = new Set();
|
|
12
|
+
_frameStream;
|
|
13
|
+
_waitPromises = new Set();
|
|
14
|
+
_options;
|
|
15
|
+
responseTimeout;
|
|
16
|
+
/**
|
|
17
|
+
* User defined property
|
|
18
|
+
* @protected
|
|
19
|
+
*/
|
|
20
|
+
user;
|
|
10
21
|
constructor(socket, options) {
|
|
11
22
|
super();
|
|
12
|
-
this._messageHooks = new Set();
|
|
13
|
-
this._waitPromises = new Set();
|
|
14
|
-
this.socket = socket;
|
|
15
23
|
this._options = options;
|
|
16
24
|
const frameStream = new frame_stream_js_1.FrameStream({
|
|
17
25
|
frameStart: hl7v2_1.VT,
|
|
18
26
|
frameEnd: hl7v2_1.FS + hl7v2_1.CR,
|
|
19
27
|
maxBufferSize: options?.maxBufferSize,
|
|
20
28
|
});
|
|
21
|
-
this._frameStream = frameStream;
|
|
22
|
-
socket.on('error', (err) => {
|
|
23
|
-
if (err.code === 'ECONNRESET') {
|
|
24
|
-
err.message = `Connection reset by peer`;
|
|
25
|
-
}
|
|
26
|
-
this.emit('error', err);
|
|
27
|
-
});
|
|
28
|
-
socket.pipe(frameStream);
|
|
29
|
-
socket.on('connect', () => this.emit('connect'));
|
|
30
|
-
socket.on('ready', () => this.emit('ready'));
|
|
31
|
-
socket.on('lookup', (err, address, family, host) => this.emit('lookup', err, address, family, host));
|
|
32
|
-
socket.on('timeout', () => socket.destroy());
|
|
33
|
-
socket.on('close', () => {
|
|
34
|
-
this.emit('close');
|
|
35
|
-
});
|
|
36
29
|
frameStream.on('data', data => {
|
|
37
30
|
this.emit('data', data);
|
|
38
31
|
this._onData(data);
|
|
39
32
|
});
|
|
33
|
+
this._frameStream = frameStream;
|
|
34
|
+
this._bindSocket(socket);
|
|
35
|
+
}
|
|
36
|
+
get socket() {
|
|
37
|
+
return this._socket;
|
|
40
38
|
}
|
|
41
39
|
get connected() {
|
|
42
40
|
return !this.socket.closed;
|
|
@@ -45,7 +43,7 @@ class HL7Socket extends node_events_async_1.AsyncEventEmitter {
|
|
|
45
43
|
return this.socket.closed;
|
|
46
44
|
}
|
|
47
45
|
get readyState() {
|
|
48
|
-
return this.socket
|
|
46
|
+
return this.socket?.readyState || 'closed';
|
|
49
47
|
}
|
|
50
48
|
get maxBufferSize() {
|
|
51
49
|
return this._frameStream.maxBufferSize || 0;
|
|
@@ -54,14 +52,14 @@ class HL7Socket extends node_events_async_1.AsyncEventEmitter {
|
|
|
54
52
|
this._frameStream.maxBufferSize = value;
|
|
55
53
|
}
|
|
56
54
|
address() {
|
|
57
|
-
return this.socket
|
|
55
|
+
return this.socket?.address() || {};
|
|
58
56
|
}
|
|
59
57
|
remoteAddress() {
|
|
60
|
-
const addr = this.socket
|
|
58
|
+
const addr = this.socket?.remoteAddress;
|
|
61
59
|
return addr?.startsWith('::ffff:') ? addr.slice(7) : addr;
|
|
62
60
|
}
|
|
63
61
|
get writable() {
|
|
64
|
-
return this.connected && this.socket
|
|
62
|
+
return this.connected && this.socket?.writable;
|
|
65
63
|
}
|
|
66
64
|
async close(waitRunningHandlers) {
|
|
67
65
|
if (this.closed)
|
|
@@ -106,10 +104,14 @@ class HL7Socket extends node_events_async_1.AsyncEventEmitter {
|
|
|
106
104
|
}
|
|
107
105
|
const str = message.toHL7String();
|
|
108
106
|
const buf = iconv_lite_1.default.encode(str, encoding);
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
107
|
+
const outBuffer = node_buffer_1.Buffer.concat([
|
|
108
|
+
node_buffer_1.Buffer.from(hl7v2_1.VT),
|
|
109
|
+
buf,
|
|
110
|
+
node_buffer_1.Buffer.from(hl7v2_1.FS + hl7v2_1.CR),
|
|
111
|
+
]);
|
|
112
|
+
this.socket.write(outBuffer);
|
|
112
113
|
this.emit('send', message);
|
|
114
|
+
this.emit('write', outBuffer);
|
|
113
115
|
}
|
|
114
116
|
catch (err) {
|
|
115
117
|
this.emit('error', err);
|
|
@@ -189,5 +191,44 @@ class HL7Socket extends node_events_async_1.AsyncEventEmitter {
|
|
|
189
191
|
this.sendMessage(nak);
|
|
190
192
|
}
|
|
191
193
|
}
|
|
194
|
+
_bindSocket(socket) {
|
|
195
|
+
if (socket === this._socket)
|
|
196
|
+
return;
|
|
197
|
+
this._unBindSocket();
|
|
198
|
+
this._socket = socket;
|
|
199
|
+
const hl7EventListeners = (socket.__hl7EventListeners = {});
|
|
200
|
+
hl7EventListeners.onConnect = () => this.emit('connect');
|
|
201
|
+
hl7EventListeners.onReady = () => this.emit('ready');
|
|
202
|
+
hl7EventListeners.onLookup = (err, address, family, host) => this.emit('lookup', err, address, family, host);
|
|
203
|
+
hl7EventListeners.onTimeout = () => socket.destroy();
|
|
204
|
+
hl7EventListeners.onClose = () => this.emit('close');
|
|
205
|
+
hl7EventListeners.onError = (err) => {
|
|
206
|
+
if (err.code === 'ECONNRESET') {
|
|
207
|
+
err.message = `Connection reset by peer`;
|
|
208
|
+
}
|
|
209
|
+
this.emit('error', err);
|
|
210
|
+
};
|
|
211
|
+
socket.on('connect', hl7EventListeners.onConnect);
|
|
212
|
+
socket.on('ready', hl7EventListeners.onReady);
|
|
213
|
+
socket.on('lookup', hl7EventListeners.onLookup);
|
|
214
|
+
socket.on('timeout', hl7EventListeners.onTimeout);
|
|
215
|
+
socket.on('close', hl7EventListeners.onClose);
|
|
216
|
+
socket.on('error', hl7EventListeners.onError);
|
|
217
|
+
socket.pipe(this._frameStream);
|
|
218
|
+
}
|
|
219
|
+
_unBindSocket() {
|
|
220
|
+
if (!this.socket)
|
|
221
|
+
return;
|
|
222
|
+
this.socket.unpipe(this._frameStream);
|
|
223
|
+
const hl7EventListeners = this.socket.__hl7EventListeners;
|
|
224
|
+
if (hl7EventListeners) {
|
|
225
|
+
this.socket.removeListener('connect', hl7EventListeners.onConnect);
|
|
226
|
+
this.socket.removeListener('ready', hl7EventListeners.onReady);
|
|
227
|
+
this.socket.removeListener('lookup', hl7EventListeners.onLookup);
|
|
228
|
+
this.socket.removeListener('timeout', hl7EventListeners.onTimeout);
|
|
229
|
+
this.socket.removeListener('close', hl7EventListeners.onClose);
|
|
230
|
+
this.socket.removeListener('error', hl7EventListeners.onError);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
192
233
|
}
|
|
193
234
|
exports.HL7Socket = HL7Socket;
|
|
@@ -1,14 +1,21 @@
|
|
|
1
1
|
import { Buffer } from 'node:buffer';
|
|
2
2
|
import { Transform } from 'node:stream';
|
|
3
3
|
export class FrameStream extends Transform {
|
|
4
|
+
_chunks = [];
|
|
5
|
+
_chunkBuffer;
|
|
6
|
+
_flushTimeout;
|
|
7
|
+
_frameDelayMs;
|
|
8
|
+
_frameStart;
|
|
9
|
+
_frameEnd;
|
|
10
|
+
_bufferSize = 0;
|
|
11
|
+
_customTransform;
|
|
12
|
+
maxBufferSize;
|
|
4
13
|
constructor(opts) {
|
|
5
14
|
super({
|
|
6
15
|
...opts,
|
|
7
16
|
objectMode: true,
|
|
8
17
|
transform: undefined,
|
|
9
18
|
});
|
|
10
|
-
this._chunks = [];
|
|
11
|
-
this._bufferSize = 0;
|
|
12
19
|
this._customTransform = opts?.transform;
|
|
13
20
|
this._frameDelayMs = opts?.frameDelayMs || (opts?.frameEnd ? 0 : 500);
|
|
14
21
|
this.maxBufferSize = opts?.maxBufferSize;
|
package/esm/hl7-client.js
CHANGED
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
import net from 'node:net';
|
|
2
2
|
import tls from 'node:tls';
|
|
3
3
|
import { AsyncEventEmitter } from 'node-events-async';
|
|
4
|
+
import reconnectCore from 'reconnect-core';
|
|
4
5
|
import { HL7Request } from './hl7-request.js';
|
|
5
6
|
import { HL7Response } from './hl7-response.js';
|
|
6
7
|
import { HL7Router } from './hl7-router.js';
|
|
7
8
|
import { HL7Socket } from './hl7-socket.js';
|
|
8
9
|
export class Hl7Client extends AsyncEventEmitter {
|
|
10
|
+
_connectionManager;
|
|
11
|
+
_router = new HL7Router();
|
|
12
|
+
_socket;
|
|
13
|
+
_tls;
|
|
14
|
+
_options;
|
|
9
15
|
/**
|
|
10
16
|
* Creates an HL7 TCP client
|
|
11
17
|
* @static
|
|
@@ -31,8 +37,60 @@ export class Hl7Client extends AsyncEventEmitter {
|
|
|
31
37
|
*/
|
|
32
38
|
constructor(options) {
|
|
33
39
|
super();
|
|
34
|
-
this._router = new HL7Router();
|
|
35
40
|
this._options = options;
|
|
41
|
+
let reconnecting = false;
|
|
42
|
+
const connectionManager = (this._connectionManager = socketReconnect({
|
|
43
|
+
...this._options.reconnect,
|
|
44
|
+
timeout: this._options.connectTimeout,
|
|
45
|
+
})
|
|
46
|
+
.on('error', err => {
|
|
47
|
+
if (!connectionManager.reconnect)
|
|
48
|
+
return;
|
|
49
|
+
this.emit('error', err);
|
|
50
|
+
})
|
|
51
|
+
.on('connect', (tcpSocket) => {
|
|
52
|
+
if (!this._socket) {
|
|
53
|
+
const socket = (this._socket = new HL7Socket(tcpSocket, this._options));
|
|
54
|
+
socket.on('connect', () => this.emit('connect'));
|
|
55
|
+
socket.on('ready', () => this.emit('ready'));
|
|
56
|
+
socket.on('lookup', (err, address, family, host) => this.emit('lookup', err, address, family, host));
|
|
57
|
+
socket.on('close', () => {
|
|
58
|
+
this._socket = undefined;
|
|
59
|
+
this.emit('close');
|
|
60
|
+
});
|
|
61
|
+
socket.on('error', err => this.emit('error', err));
|
|
62
|
+
socket.on('message', message => {
|
|
63
|
+
this.emit('message', message);
|
|
64
|
+
this._onMessage(message);
|
|
65
|
+
});
|
|
66
|
+
socket.on('send', message => this.emit('send', message));
|
|
67
|
+
socket.on('data', data => this.emit('data', data));
|
|
68
|
+
}
|
|
69
|
+
else
|
|
70
|
+
this._socket._bindSocket(tcpSocket);
|
|
71
|
+
if (reconnecting)
|
|
72
|
+
this.emit('reconnect', tcpSocket);
|
|
73
|
+
reconnecting = false;
|
|
74
|
+
this.emit('connect');
|
|
75
|
+
})
|
|
76
|
+
.on('reconnect', (n, delay) => {
|
|
77
|
+
if (n === 0 && delay === 0)
|
|
78
|
+
return;
|
|
79
|
+
reconnecting = true;
|
|
80
|
+
this.emit('reconnecting', n, delay);
|
|
81
|
+
})
|
|
82
|
+
.on('disconnect', err => {
|
|
83
|
+
this._socket = undefined;
|
|
84
|
+
if (connectionManager.reconnect) {
|
|
85
|
+
if (err)
|
|
86
|
+
err.message = `TCP socket connection lost: ${err.message}`;
|
|
87
|
+
else
|
|
88
|
+
err = new Error('TCP socket connection lost');
|
|
89
|
+
this.emit('disconnect', err);
|
|
90
|
+
}
|
|
91
|
+
else
|
|
92
|
+
this.emit('disconnect');
|
|
93
|
+
}));
|
|
36
94
|
}
|
|
37
95
|
get connected() {
|
|
38
96
|
return this._socket?.connected ?? false;
|
|
@@ -77,57 +135,32 @@ export class Hl7Client extends AsyncEventEmitter {
|
|
|
77
135
|
if (this._socket)
|
|
78
136
|
this._socket.maxBufferSize = value;
|
|
79
137
|
}
|
|
80
|
-
connect() {
|
|
138
|
+
async connect() {
|
|
139
|
+
if (this.connected)
|
|
140
|
+
return;
|
|
81
141
|
return new Promise((resolve, reject) => {
|
|
82
|
-
if (this.connected) {
|
|
83
|
-
resolve();
|
|
84
|
-
return;
|
|
85
|
-
}
|
|
86
|
-
let timeoutTimer;
|
|
87
|
-
const tcpSocket = this._tls
|
|
88
|
-
? tls.connect(this._options)
|
|
89
|
-
: net.connect(this._options);
|
|
90
|
-
const socket = (this._socket = new HL7Socket(tcpSocket, this._options));
|
|
91
|
-
socket.on('connect', () => this.emit('connect'));
|
|
92
|
-
socket.on('ready', () => this.emit('ready'));
|
|
93
|
-
socket.on('lookup', (err, address, family, host) => this.emit('lookup', err, address, family, host));
|
|
94
|
-
socket.on('close', () => {
|
|
95
|
-
this._socket = undefined;
|
|
96
|
-
this.emit('close');
|
|
97
|
-
});
|
|
98
|
-
socket.on('error', err => this.emit('error', err));
|
|
99
|
-
socket.on('message', message => {
|
|
100
|
-
this.emit('message', message);
|
|
101
|
-
this._onMessage(message);
|
|
102
|
-
});
|
|
103
|
-
socket.on('send', message => this.emit('send', message));
|
|
104
|
-
socket.on('data', data => this.emit('data', data));
|
|
105
142
|
const onReady = () => {
|
|
106
|
-
|
|
107
|
-
tcpSocket.removeListener('error', onError);
|
|
108
|
-
if (this._options.keepAlive) {
|
|
109
|
-
tcpSocket.setKeepAlive(this._options.keepAlive, this._options.keepAliveInitialDelay);
|
|
110
|
-
}
|
|
143
|
+
this.removeListener('error', onError);
|
|
111
144
|
resolve();
|
|
112
145
|
};
|
|
113
146
|
const onError = (error) => {
|
|
114
|
-
|
|
115
|
-
tcpSocket.removeListener('ready', onReady);
|
|
116
|
-
tcpSocket.destroy();
|
|
147
|
+
this.removeListener('ready', onReady);
|
|
117
148
|
reject(error);
|
|
118
149
|
};
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
}
|
|
150
|
+
this.once('ready', onReady);
|
|
151
|
+
this.once('error', onError);
|
|
152
|
+
this._connectionManager.reconnect = true;
|
|
153
|
+
this._connectionManager.connect({
|
|
154
|
+
tls: this._tls,
|
|
155
|
+
options: this._options,
|
|
156
|
+
});
|
|
127
157
|
});
|
|
128
158
|
}
|
|
129
159
|
async close(waitRunningHandlers) {
|
|
160
|
+
this._connectionManager.reconnect = false;
|
|
130
161
|
await this._socket?.close(waitRunningHandlers);
|
|
162
|
+
this._connectionManager.disconnect();
|
|
163
|
+
this._connectionManager.reset();
|
|
131
164
|
}
|
|
132
165
|
async sendMessage(message) {
|
|
133
166
|
if (!this.connected)
|
|
@@ -156,3 +189,37 @@ export class Hl7Client extends AsyncEventEmitter {
|
|
|
156
189
|
});
|
|
157
190
|
}
|
|
158
191
|
}
|
|
192
|
+
const socketReconnect = reconnectCore((args) => {
|
|
193
|
+
const tcpSocket = args.tls
|
|
194
|
+
? tls.connect({
|
|
195
|
+
...args.options,
|
|
196
|
+
timeout: undefined,
|
|
197
|
+
})
|
|
198
|
+
: net.connect({
|
|
199
|
+
...args.options,
|
|
200
|
+
timeout: undefined,
|
|
201
|
+
});
|
|
202
|
+
if (args.options.timeout) {
|
|
203
|
+
const timer = setTimeout(() => {
|
|
204
|
+
tcpSocket.destroy(new Error('Connection timed out'));
|
|
205
|
+
}, args.options.timeout).unref();
|
|
206
|
+
const onConnect = () => {
|
|
207
|
+
clearTimeout(timer);
|
|
208
|
+
tcpSocket.removeListener('error', onError);
|
|
209
|
+
};
|
|
210
|
+
const onError = () => {
|
|
211
|
+
clearTimeout(timer);
|
|
212
|
+
tcpSocket.removeListener('connect', onConnect);
|
|
213
|
+
tcpSocket.removeListener('ready', onReady);
|
|
214
|
+
};
|
|
215
|
+
const onReady = () => {
|
|
216
|
+
if (args.options.keepAlive) {
|
|
217
|
+
tcpSocket.setKeepAlive(args.options.keepAlive, args.options.keepAliveInitialDelay);
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
tcpSocket.once('connect', onConnect);
|
|
221
|
+
tcpSocket.once('error', onError);
|
|
222
|
+
tcpSocket.once('ready', onReady);
|
|
223
|
+
}
|
|
224
|
+
return tcpSocket;
|
|
225
|
+
});
|
package/esm/hl7-request.js
CHANGED
package/esm/hl7-response.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { MSASegment } from 'hl7v2';
|
|
2
2
|
export class HL7Response {
|
|
3
|
+
_finished = false;
|
|
4
|
+
request;
|
|
5
|
+
errors = [];
|
|
6
|
+
message;
|
|
3
7
|
constructor(request) {
|
|
4
|
-
this._finished = false;
|
|
5
|
-
this.errors = [];
|
|
6
8
|
this.request = request;
|
|
7
9
|
this.message = request.message.createAck();
|
|
8
10
|
request.socket.once('send', () => {
|
package/esm/hl7-router.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
export class HL7Router {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
this._handlers = [];
|
|
6
|
-
}
|
|
2
|
+
_handlerStack = new Map();
|
|
3
|
+
_needPrepare = true;
|
|
4
|
+
_handlers = [];
|
|
7
5
|
use(handler, priority = 0) {
|
|
8
6
|
let list = this._handlerStack[priority];
|
|
9
7
|
if (!list) {
|
package/esm/hl7-server.js
CHANGED
|
@@ -9,6 +9,14 @@ import { HL7Response } from './hl7-response.js';
|
|
|
9
9
|
import { HL7Router } from './hl7-router.js';
|
|
10
10
|
import { HL7Socket } from './hl7-socket.js';
|
|
11
11
|
export class HL7Server extends AsyncEventEmitter {
|
|
12
|
+
_server;
|
|
13
|
+
_sockets = new Set();
|
|
14
|
+
_router = new HL7Router();
|
|
15
|
+
_runningHandlers = new Set();
|
|
16
|
+
_closing;
|
|
17
|
+
parseStrict;
|
|
18
|
+
maxBufferPerSocket;
|
|
19
|
+
responseTimeout;
|
|
12
20
|
/**
|
|
13
21
|
* Creates a HL7 TCP server
|
|
14
22
|
* @static
|
|
@@ -30,9 +38,6 @@ export class HL7Server extends AsyncEventEmitter {
|
|
|
30
38
|
*/
|
|
31
39
|
constructor(server, options) {
|
|
32
40
|
super();
|
|
33
|
-
this._sockets = new Set();
|
|
34
|
-
this._router = new HL7Router();
|
|
35
|
-
this._runningHandlers = new Set();
|
|
36
41
|
this.maxBufferPerSocket = options?.maxBufferPerSocket;
|
|
37
42
|
this.responseTimeout = options?.responseTimeout;
|
|
38
43
|
this.parseStrict = options?.parseStrict;
|
|
@@ -193,7 +198,8 @@ export class HL7Server extends AsyncEventEmitter {
|
|
|
193
198
|
this._onMessage(message, socket);
|
|
194
199
|
});
|
|
195
200
|
socket.on('send', message => this.emit('send', message, socket));
|
|
196
|
-
socket.on('data', data => this.emit('data', data));
|
|
201
|
+
socket.on('data', data => this.emit('data', data, socket));
|
|
202
|
+
socket.on('write', data => this.emit('write', data, socket));
|
|
197
203
|
this.emit('connection', socket);
|
|
198
204
|
}
|
|
199
205
|
_onMessage(message, socket) {
|
package/esm/hl7-socket.js
CHANGED
|
@@ -1,38 +1,36 @@
|
|
|
1
|
+
import { Buffer } from 'node:buffer';
|
|
1
2
|
import { CR, FS, HL7Message, MSASegment, MSHSegment, VT, } from 'hl7v2';
|
|
2
3
|
import iconv from 'iconv-lite';
|
|
3
4
|
import { AsyncEventEmitter } from 'node-events-async';
|
|
4
5
|
import { FrameStream } from './helpers/frame-stream.js';
|
|
5
6
|
export class HL7Socket extends AsyncEventEmitter {
|
|
7
|
+
_messageHooks = new Set();
|
|
8
|
+
_frameStream;
|
|
9
|
+
_waitPromises = new Set();
|
|
10
|
+
_options;
|
|
11
|
+
responseTimeout;
|
|
12
|
+
/**
|
|
13
|
+
* User defined property
|
|
14
|
+
* @protected
|
|
15
|
+
*/
|
|
16
|
+
user;
|
|
6
17
|
constructor(socket, options) {
|
|
7
18
|
super();
|
|
8
|
-
this._messageHooks = new Set();
|
|
9
|
-
this._waitPromises = new Set();
|
|
10
|
-
this.socket = socket;
|
|
11
19
|
this._options = options;
|
|
12
20
|
const frameStream = new FrameStream({
|
|
13
21
|
frameStart: VT,
|
|
14
22
|
frameEnd: FS + CR,
|
|
15
23
|
maxBufferSize: options?.maxBufferSize,
|
|
16
24
|
});
|
|
17
|
-
this._frameStream = frameStream;
|
|
18
|
-
socket.on('error', (err) => {
|
|
19
|
-
if (err.code === 'ECONNRESET') {
|
|
20
|
-
err.message = `Connection reset by peer`;
|
|
21
|
-
}
|
|
22
|
-
this.emit('error', err);
|
|
23
|
-
});
|
|
24
|
-
socket.pipe(frameStream);
|
|
25
|
-
socket.on('connect', () => this.emit('connect'));
|
|
26
|
-
socket.on('ready', () => this.emit('ready'));
|
|
27
|
-
socket.on('lookup', (err, address, family, host) => this.emit('lookup', err, address, family, host));
|
|
28
|
-
socket.on('timeout', () => socket.destroy());
|
|
29
|
-
socket.on('close', () => {
|
|
30
|
-
this.emit('close');
|
|
31
|
-
});
|
|
32
25
|
frameStream.on('data', data => {
|
|
33
26
|
this.emit('data', data);
|
|
34
27
|
this._onData(data);
|
|
35
28
|
});
|
|
29
|
+
this._frameStream = frameStream;
|
|
30
|
+
this._bindSocket(socket);
|
|
31
|
+
}
|
|
32
|
+
get socket() {
|
|
33
|
+
return this._socket;
|
|
36
34
|
}
|
|
37
35
|
get connected() {
|
|
38
36
|
return !this.socket.closed;
|
|
@@ -41,7 +39,7 @@ export class HL7Socket extends AsyncEventEmitter {
|
|
|
41
39
|
return this.socket.closed;
|
|
42
40
|
}
|
|
43
41
|
get readyState() {
|
|
44
|
-
return this.socket
|
|
42
|
+
return this.socket?.readyState || 'closed';
|
|
45
43
|
}
|
|
46
44
|
get maxBufferSize() {
|
|
47
45
|
return this._frameStream.maxBufferSize || 0;
|
|
@@ -50,14 +48,14 @@ export class HL7Socket extends AsyncEventEmitter {
|
|
|
50
48
|
this._frameStream.maxBufferSize = value;
|
|
51
49
|
}
|
|
52
50
|
address() {
|
|
53
|
-
return this.socket
|
|
51
|
+
return this.socket?.address() || {};
|
|
54
52
|
}
|
|
55
53
|
remoteAddress() {
|
|
56
|
-
const addr = this.socket
|
|
54
|
+
const addr = this.socket?.remoteAddress;
|
|
57
55
|
return addr?.startsWith('::ffff:') ? addr.slice(7) : addr;
|
|
58
56
|
}
|
|
59
57
|
get writable() {
|
|
60
|
-
return this.connected && this.socket
|
|
58
|
+
return this.connected && this.socket?.writable;
|
|
61
59
|
}
|
|
62
60
|
async close(waitRunningHandlers) {
|
|
63
61
|
if (this.closed)
|
|
@@ -102,10 +100,14 @@ export class HL7Socket extends AsyncEventEmitter {
|
|
|
102
100
|
}
|
|
103
101
|
const str = message.toHL7String();
|
|
104
102
|
const buf = iconv.encode(str, encoding);
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
103
|
+
const outBuffer = Buffer.concat([
|
|
104
|
+
Buffer.from(VT),
|
|
105
|
+
buf,
|
|
106
|
+
Buffer.from(FS + CR),
|
|
107
|
+
]);
|
|
108
|
+
this.socket.write(outBuffer);
|
|
108
109
|
this.emit('send', message);
|
|
110
|
+
this.emit('write', outBuffer);
|
|
109
111
|
}
|
|
110
112
|
catch (err) {
|
|
111
113
|
this.emit('error', err);
|
|
@@ -185,4 +187,43 @@ export class HL7Socket extends AsyncEventEmitter {
|
|
|
185
187
|
this.sendMessage(nak);
|
|
186
188
|
}
|
|
187
189
|
}
|
|
190
|
+
_bindSocket(socket) {
|
|
191
|
+
if (socket === this._socket)
|
|
192
|
+
return;
|
|
193
|
+
this._unBindSocket();
|
|
194
|
+
this._socket = socket;
|
|
195
|
+
const hl7EventListeners = (socket.__hl7EventListeners = {});
|
|
196
|
+
hl7EventListeners.onConnect = () => this.emit('connect');
|
|
197
|
+
hl7EventListeners.onReady = () => this.emit('ready');
|
|
198
|
+
hl7EventListeners.onLookup = (err, address, family, host) => this.emit('lookup', err, address, family, host);
|
|
199
|
+
hl7EventListeners.onTimeout = () => socket.destroy();
|
|
200
|
+
hl7EventListeners.onClose = () => this.emit('close');
|
|
201
|
+
hl7EventListeners.onError = (err) => {
|
|
202
|
+
if (err.code === 'ECONNRESET') {
|
|
203
|
+
err.message = `Connection reset by peer`;
|
|
204
|
+
}
|
|
205
|
+
this.emit('error', err);
|
|
206
|
+
};
|
|
207
|
+
socket.on('connect', hl7EventListeners.onConnect);
|
|
208
|
+
socket.on('ready', hl7EventListeners.onReady);
|
|
209
|
+
socket.on('lookup', hl7EventListeners.onLookup);
|
|
210
|
+
socket.on('timeout', hl7EventListeners.onTimeout);
|
|
211
|
+
socket.on('close', hl7EventListeners.onClose);
|
|
212
|
+
socket.on('error', hl7EventListeners.onError);
|
|
213
|
+
socket.pipe(this._frameStream);
|
|
214
|
+
}
|
|
215
|
+
_unBindSocket() {
|
|
216
|
+
if (!this.socket)
|
|
217
|
+
return;
|
|
218
|
+
this.socket.unpipe(this._frameStream);
|
|
219
|
+
const hl7EventListeners = this.socket.__hl7EventListeners;
|
|
220
|
+
if (hl7EventListeners) {
|
|
221
|
+
this.socket.removeListener('connect', hl7EventListeners.onConnect);
|
|
222
|
+
this.socket.removeListener('ready', hl7EventListeners.onReady);
|
|
223
|
+
this.socket.removeListener('lookup', hl7EventListeners.onLookup);
|
|
224
|
+
this.socket.removeListener('timeout', hl7EventListeners.onTimeout);
|
|
225
|
+
this.socket.removeListener('close', hl7EventListeners.onClose);
|
|
226
|
+
this.socket.removeListener('error', hl7EventListeners.onError);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
188
229
|
}
|
package/package.json
CHANGED
|
@@ -1,22 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hl7v2-net",
|
|
3
3
|
"description": "HL7 v2 server/client for NodeJS",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.6.0",
|
|
5
5
|
"author": "Panates",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"dependencies": {
|
|
8
8
|
"@jsopen/objects": "^2.0.2",
|
|
9
|
-
"
|
|
9
|
+
"backoff": "^2.5.0",
|
|
10
|
+
"iconv-lite": "^0.7.1",
|
|
10
11
|
"is-typedarray": "^1.0.0",
|
|
11
12
|
"node-events-async": "^1.2.0",
|
|
13
|
+
"reconnect-core": "^1.3.0",
|
|
12
14
|
"ts-gems": "^3.11.3",
|
|
13
15
|
"tslib": "^2.8.1",
|
|
14
|
-
"valgen": "^5.
|
|
16
|
+
"valgen": "^5.18.2",
|
|
15
17
|
"uid": "^2.0.2"
|
|
16
18
|
},
|
|
17
19
|
"peerDependencies": {
|
|
18
|
-
"hl7v2": "^1.
|
|
19
|
-
"hl7v2-dictionary": "^1.
|
|
20
|
+
"hl7v2": "^1.6.0",
|
|
21
|
+
"hl7v2-dictionary": "^1.6.0"
|
|
20
22
|
},
|
|
21
23
|
"type": "module",
|
|
22
24
|
"exports": {
|
package/types/hl7-client.d.ts
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import net from 'node:net';
|
|
2
2
|
import tls from 'node:tls';
|
|
3
|
+
import { Backoff } from 'backoff';
|
|
3
4
|
import { HL7Message } from 'hl7v2';
|
|
4
|
-
import { AddressInfo } from 'net';
|
|
5
5
|
import { AsyncEventEmitter } from 'node-events-async';
|
|
6
|
+
import reconnectCore from 'reconnect-core';
|
|
6
7
|
import { StrictOmit } from 'ts-gems';
|
|
7
8
|
import { HL7Router } from './hl7-router.js';
|
|
8
9
|
import { HL7Socket } from './hl7-socket.js';
|
|
9
10
|
import { HL7Middleware } from './types.js';
|
|
10
11
|
export declare class Hl7Client extends AsyncEventEmitter<Hl7Client.Events> {
|
|
12
|
+
protected _connectionManager: ReturnType<typeof socketReconnect>;
|
|
11
13
|
protected _router: HL7Router;
|
|
12
14
|
protected _socket?: HL7Socket;
|
|
13
15
|
protected _tls?: boolean;
|
|
@@ -32,7 +34,7 @@ export declare class Hl7Client extends AsyncEventEmitter<Hl7Client.Events> {
|
|
|
32
34
|
get closed(): boolean;
|
|
33
35
|
get readyState(): net.SocketReadyState;
|
|
34
36
|
get uri(): string;
|
|
35
|
-
address(): AddressInfo;
|
|
37
|
+
address(): net.AddressInfo;
|
|
36
38
|
get connectTimeout(): number | undefined;
|
|
37
39
|
set connectTimeout(value: number | null);
|
|
38
40
|
get responseTimeout(): number | undefined;
|
|
@@ -48,6 +50,10 @@ export declare class Hl7Client extends AsyncEventEmitter<Hl7Client.Events> {
|
|
|
48
50
|
protected _onMessage(message: HL7Message): void;
|
|
49
51
|
}
|
|
50
52
|
export declare namespace Hl7Client {
|
|
53
|
+
export interface Events extends HL7Socket.Events {
|
|
54
|
+
reconnecting: [n: number, delay: number];
|
|
55
|
+
reconnect: [socket: net.Socket];
|
|
56
|
+
}
|
|
51
57
|
interface CommonConnectOptions {
|
|
52
58
|
connectTimeout?: number;
|
|
53
59
|
maxBufferSize?: number;
|
|
@@ -55,10 +61,22 @@ export declare namespace Hl7Client {
|
|
|
55
61
|
keepAlive?: boolean;
|
|
56
62
|
keepAliveInitialDelay?: number;
|
|
57
63
|
parseStrict?: boolean;
|
|
64
|
+
reconnect?: ReconnectOptions;
|
|
58
65
|
}
|
|
59
66
|
export type NetConnectOptions = StrictOmit<net.TcpNetConnectOpts, 'onread' | 'readable' | 'writable'> & CommonConnectOptions;
|
|
60
67
|
export type TlsConnectOptions = StrictOmit<tls.ConnectionOptions, 'socket'> & CommonConnectOptions;
|
|
61
|
-
export interface
|
|
68
|
+
export interface ReconnectOptions {
|
|
69
|
+
strategy?: 'fibonacci' | 'exponential' | Backoff;
|
|
70
|
+
immediate?: boolean | undefined;
|
|
71
|
+
failAfter?: number | undefined;
|
|
72
|
+
randomisationFactor?: number | undefined;
|
|
73
|
+
initialDelay?: number | undefined;
|
|
74
|
+
maxDelay?: number | undefined;
|
|
62
75
|
}
|
|
63
76
|
export {};
|
|
64
77
|
}
|
|
78
|
+
declare const socketReconnect: reconnectCore.CustomModule<{
|
|
79
|
+
tls?: boolean;
|
|
80
|
+
options: Hl7Client.NetConnectOptions | Hl7Client.TlsConnectOptions;
|
|
81
|
+
}, net.Socket>;
|
|
82
|
+
export {};
|
package/types/hl7-server.d.ts
CHANGED
|
@@ -108,7 +108,8 @@ export declare namespace HL7Server {
|
|
|
108
108
|
error: [error: Error, HL7Socket | undefined];
|
|
109
109
|
message: [message: HL7Message, socket: HL7Socket];
|
|
110
110
|
send: [message: HL7Message, socket: HL7Socket];
|
|
111
|
-
data: [Buffer];
|
|
111
|
+
data: [Buffer, socket: HL7Socket];
|
|
112
|
+
write: [buffer: Buffer, socket: HL7Socket];
|
|
112
113
|
}
|
|
113
114
|
interface Options {
|
|
114
115
|
applicationName?: string;
|
package/types/hl7-socket.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { Socket } from 'net';
|
|
|
4
4
|
import { AsyncEventEmitter } from 'node-events-async';
|
|
5
5
|
import { FrameStream } from './helpers/frame-stream.js';
|
|
6
6
|
export declare class HL7Socket extends AsyncEventEmitter<HL7Socket.Events> {
|
|
7
|
-
|
|
7
|
+
protected _socket: Socket;
|
|
8
8
|
protected _messageHooks: Set<(resp: HL7Message) => boolean>;
|
|
9
9
|
protected _frameStream: FrameStream;
|
|
10
10
|
protected _waitPromises: Set<Promise<any>>;
|
|
@@ -16,12 +16,13 @@ export declare class HL7Socket extends AsyncEventEmitter<HL7Socket.Events> {
|
|
|
16
16
|
*/
|
|
17
17
|
protected user?: any;
|
|
18
18
|
constructor(socket: Socket, options: HL7Socket.Options);
|
|
19
|
+
get socket(): Socket;
|
|
19
20
|
get connected(): boolean;
|
|
20
21
|
get closed(): boolean;
|
|
21
|
-
get readyState(): import("net").SocketReadyState;
|
|
22
|
+
get readyState(): import("node:net").SocketReadyState;
|
|
22
23
|
get maxBufferSize(): number;
|
|
23
24
|
set maxBufferSize(value: number);
|
|
24
|
-
address(): {}
|
|
25
|
+
address(): {};
|
|
25
26
|
remoteAddress(): string | undefined;
|
|
26
27
|
get writable(): boolean;
|
|
27
28
|
close(waitRunningHandlers?: number): Promise<void>;
|
|
@@ -29,6 +30,8 @@ export declare class HL7Socket extends AsyncEventEmitter<HL7Socket.Events> {
|
|
|
29
30
|
sendMessageWaitAck(message: HL7Message): Promise<HL7Message>;
|
|
30
31
|
setKeepAlive(enable?: boolean, initialDelay?: number): void;
|
|
31
32
|
protected _onData(data: Buffer): void;
|
|
33
|
+
_bindSocket(socket: Socket): void;
|
|
34
|
+
protected _unBindSocket(): void;
|
|
32
35
|
}
|
|
33
36
|
export declare namespace HL7Socket {
|
|
34
37
|
interface Events {
|
|
@@ -37,14 +40,15 @@ export declare namespace HL7Socket {
|
|
|
37
40
|
close: [];
|
|
38
41
|
error: [error: Error];
|
|
39
42
|
lookup: [
|
|
40
|
-
err: Error,
|
|
43
|
+
err: Error | null,
|
|
41
44
|
address: string,
|
|
42
|
-
family:
|
|
45
|
+
family: number | null,
|
|
43
46
|
host: string
|
|
44
47
|
];
|
|
45
48
|
message: [message: HL7Message];
|
|
46
49
|
send: [message: HL7Message];
|
|
47
|
-
data: [Buffer];
|
|
50
|
+
data: [buffer: Buffer];
|
|
51
|
+
write: [buffer: Buffer];
|
|
48
52
|
}
|
|
49
53
|
interface Options {
|
|
50
54
|
responseTimeout?: number;
|