Skip to content

Commit

Permalink
feat: client work
Browse files Browse the repository at this point in the history
- outbound to a server is working
- issue: the server responds back to the client with the same message that it was sent. not sure why.
- updated packages

#15

[ci skip]
  • Loading branch information
Bugs5382 committed Dec 13, 2023
1 parent 43ab455 commit fc863f6
Show file tree
Hide file tree
Showing 10 changed files with 54 additions and 58 deletions.
2 changes: 1 addition & 1 deletion __tests__/__data__/sample_messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export const sample_hl7 =
"PID|||555-44-4444||EVERYWOMAN^EVE^E^^^^L|JONES|196203520|F|||153 FERNWOOD DR.^^STATESVILLE^OH^35292||(206)3345232|(206)752-121||||AC555444444||67-A4335^OH^20030520",
"OBR|1|845439^GHH OE|1045813^GHH LAB|1554-5^GLUCOSE|||200202150730||||||||555-55-5555^PRIMARY^PATRICIA P^^^^MD^^LEVEL SEVEN HEALTHCARE, INC.|||||||||F||||||444-44-4444^HIPPOCRATES^HOWARD H^^^^MD",
"OBX|1|SN|1554-5^GLUCOSE^POST 12H CFST:MCNC:PT:SER/PLAS:QN||^182|mg/dl|70_105|H|||F",
"OBX|2|FN|1553-5^GLUCOSE^POST 12H CFST:MCNC:PT:SER/PLAS:QN||^182|mg/dl|70_105|H|||F\r",
"OBX|2|FN|1553-5^GLUCOSE^POST 12H CFST:MCNC:PT:SER/PLAS:QN||^182|mg/dl|70_105|H|||F",
].join("\r")

export const rep_sample_hl7 =
Expand Down
32 changes: 8 additions & 24 deletions __tests__/hl7.build.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ describe('node hl7 client - builder tests', () => {
try {
new Message({
messageHeader: {
// @ts-expect-error 9.1 should be not empty
msh_9: {
// @ts-expect-error 9.1 should be not empty
msh_9_1: "",
},
}
Expand All @@ -50,30 +50,16 @@ describe('node hl7 client - builder tests', () => {
test("error - Message Object - msh 9.2 is empty ", async () => {
try {
new Message({
// @ts-expect-error 9.2 should be not empty
messageHeader: {
msh_9: {
// @ts-expect-error 9.2 should be not empty
msh_9_1: "ADT",
msh_9_2: "",
},
}
})
} catch (err) {
expect(err).toEqual(new Error('MSH.9.1 & MSH 9.2 & MSH 9.3 must be defined.'))
}
})

test("error - Message Object - msh 9.3 is empty ", async () => {
try {
new Message({
messageHeader: {
msh_9: {
// @ts-expect-error 9.3 should be not empty
msh_9_3: "",
},
}
})
} catch (err) {
expect(err).toEqual(new Error('MSH.9.1 & MSH 9.2 & MSH 9.3 must be defined.'))
expect(err).toEqual(new Error('MSH.9.2 must be 3 characters in length.'))
}
})

Expand All @@ -82,11 +68,10 @@ describe('node hl7 client - builder tests', () => {
new Message({
messageHeader: {
msh_9: {
// @ts-expect-error 9.1 should be 3 characters
msh_9_1: "ADTY",
msh_9_2: "A01",
msh_9_3: "ADT_A01"
msh_9_2: "A01"
},
msh_10: "123456"
}
})
} catch (err) {
Expand All @@ -100,10 +85,9 @@ describe('node hl7 client - builder tests', () => {
messageHeader: {
msh_9: {
msh_9_1: "ADT",
// @ts-expect-error 9.2 should be 3 characters
msh_9_2: "A01Y",
msh_9_3: "ADT_A01"
msh_9_2: "A01Y"
},
msh_10: "123456"
}
})
} catch (err) {
Expand Down
2 changes: 1 addition & 1 deletion __tests__/hl7.client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ describe('node hl7 client', () => {

describe('basic listener tests', () => {

test('...simple connect', async () => {
test.skip('...simple connect', async () => {

const LISTEN_PORT = await portfinder.getPortPromise({
port: 3000,
Expand Down
8 changes: 5 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,21 +52,23 @@
"url": "https://github.com/Bugs5382/node-hl7-client/issues"
},
"homepage": "https://github.com/Bugs5382/node-hl7-client#readme",
"dependencies": {
"node-hl7-server": "file:../node-hl7-server"
},
"devDependencies": {
"@semantic-release/changelog": "^6.0.3",
"@semantic-release/commit-analyzer": "^11.1.0",
"@semantic-release/git": "^10.0.1",
"@semantic-release/release-notes-generator": "^12.1.0",
"@types/jest": "^29.5.11",
"@types/node": "^20.10.4",
"@typescript-eslint/parser": "^6.13.2",
"@typescript-eslint/parser": "^6.14.0",
"jest": "^29.7.0",
"jest-ts-webcompat-resolver": "^1.0.0",
"node-hl7-server": "file:../node-hl7-server",
"npm-check-updates": "^16.14.11",
"portfinder": "^1.0.32",
"pre-commit": "^1.2.2",
"semantic-release": "^22.0.10",
"semantic-release": "^22.0.11",
"snazzy": "^9.0.0",
"tcp-port-used": "^1.0.2",
"ts-jest": "^29.1.1",
Expand Down
8 changes: 4 additions & 4 deletions src/client/client.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import EventEmitter from 'events'
import { normalizeClientOptions, ClientListenerOptions, ClientOptions } from '../utils/normalizeClient.js'
import {HL7Outbound} from "./hl7Outbound";
import { normalizeClientOptions, ClientListenerOptions, ClientOptions } from '../utils/normalizedClient.js'
import {HL7Outbound, OutboundHandler} from "./hl7Outbound";

/**
* Client Class
Expand All @@ -16,8 +16,8 @@ export class Client extends EventEmitter {

/** Connect to a listener to a specified port.
* @since 1.0.0 */
createOutbound (props: ClientListenerOptions, handler?: any): HL7Outbound {
return new HL7Outbound(this, props, handler)
createOutbound (props: ClientListenerOptions, cb: OutboundHandler): HL7Outbound {
return new HL7Outbound(this, props, cb)
}

getHost(): string {
Expand Down
45 changes: 26 additions & 19 deletions src/client/hl7Outbound.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,46 +4,47 @@ import * as tls from 'tls'
import {Batch} from '../builder/batch.js'
import {Message} from '../builder/message.js'
import {randomString} from "../utils";
//import { CR, FS, VT } from '../utils/constants.js'
import {HL7FatalError} from '../utils/exception'
import {ClientListenerOptions, normalizeClientListenerOptions} from '../utils/normalizeClient.js'
import {ClientListenerOptions, normalizeClientListenerOptions} from '../utils/normalizedClient.js'
import {Client} from './client.js'

export type OutboundHandler = (res: Buffer) => Promise<void>

/** HL7 Outbound Class
* @since 1.0.0 */
export class HL7Outbound extends EventEmitter {
/** @internal */
private _awaitingResponse: boolean
/** @internal */
_handler?: any | undefined // @todo is this needed?
private readonly _handler: (res: Buffer) => void
/** @internal */
private _main: Client
/** @internal */
private _nodeId: string
private readonly _nodeId: string
/** @internal */
private _opt: ReturnType<typeof normalizeClientListenerOptions>
/** @internal */
private _server: net.Socket | tls.TLSSocket
/** @internal */
private _sockets: Map<any, any>

constructor (client: Client, props: ClientListenerOptions, handler?: any) {
constructor (client: Client, props: ClientListenerOptions, handler: OutboundHandler) {
super()
this._awaitingResponse = false
this._handler = handler
this._main = client
this._nodeId = randomString(5)

this._awaitingResponse = false

// process listener options
this._opt = normalizeClientListenerOptions(props)

this._sockets = new Map()
this._handler = handler

this._connect = this._connect.bind(this)
this._server = this._connect()
}

getHost(): string {
return this._main._opt.host
}

getPort(): string {
return this._opt.port.toString()
}
Expand All @@ -54,18 +55,25 @@ export class HL7Outbound extends EventEmitter {
async sendMessage (message: Message | Batch): Promise<boolean> {
// if we are waiting for an ack before we can send something else, and we are in that process.
if (this._opt.waitAck && this._awaitingResponse) {
throw new HL7FatalError(500, 'Can\'t send message while we are waiting for a response.')
throw new HL7FatalError(500, `Can't send message while we are waiting for a response.`)
}

// ok, if our options are to wait for an acknowledgement, set the var to "true"
if (this._opt.waitAck) {
this._awaitingResponse = true
}

const toSendData = Buffer.from(message.toString())
let messageToSend = Buffer.from(message.toString())

return this._server?.write(toSendData, 'utf8', () => {
// console.log(toSendData)
const header = Buffer.alloc(6);
header.writeInt32BE(messageToSend.length + 6, 1);
header.writeInt8(2, 5);
header[0] = header[1] ^ header[2] ^ header[3] ^ header[4] ^ header[5];

const payload = Buffer.concat([header, messageToSend]);

return this._server.write(payload, this._opt.encoding, () => {
// FOR DEBUGGING ONLY: console.log(toSendData)
})

}
Expand All @@ -78,10 +86,9 @@ export class HL7Outbound extends EventEmitter {
let _opt_tls = this._main._opt.tls

if (typeof _opt_tls !== 'undefined') {
// @todo this needs to be expanded on for TLS options
// @TODO this needs to be expanded on for TLS options
server = tls.connect({host, port})
} else {

server = net.createConnection({host, port}, () => {

// set no delay
Expand All @@ -101,8 +108,8 @@ export class HL7Outbound extends EventEmitter {
this.emit('connect')
})

server.on('data', buffer => {
this.emit('data', buffer.toString())
server.on('data', (buffer: Buffer) => {
this._handler(buffer)
})

server.on('error', err => {
Expand Down
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@ export type { HL7_2_7_MSH } from './specification/2.7.js'
/** HL7 Class **/
export { HL7_SPEC, HL7_SPEC_BASE, HL7_2_7 }

export type { ClientOptions, ClientListenerOptions, ParserProcessRawData } from './utils/normalizeClient.js'
export type { ClientOptions, ClientListenerOptions, ParserProcessRawData } from './utils/normalizedClient.js'
export type { ClientBuilderFileOptions, ClientBuilderBatchOptions, ClientBuilderOptions } from './utils/normalizedBuilder.js'
export type { HL7Error, HL7FatalError, HL7ParserError } from './utils/exception.js'
4 changes: 2 additions & 2 deletions src/specification/generic.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
/** @internal */
export interface HL7_MSH_MESSAGE_TYPE {
/** Message Code */
msh_9_1: 'ACK' | 'ADR' | 'ADT'
msh_9_1: string
/** Trigger Event */
msh_9_2: 'A01'
msh_9_2: string
}

/** @internal */
Expand Down
3 changes: 0 additions & 3 deletions src/utils/constants.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import * as Util from './index.js'
const DEFAULT_CLIENT_OPTS = {
acquireTimeout: 20000,
connectionTimeout: 10000,
encoding: 'utf-8',
maxConnections: 10,
waitAck: true
}
Expand Down Expand Up @@ -48,6 +49,10 @@ export interface ClientListenerOptions {
* This will override the overall client connection for this particular connection.
* @default 10_000 */
connectionTimeout?: number
/** Encoding of the messages we expect from the HL7 message.
* @default "utf-8"
*/
encoding?: BufferEncoding
/** Keep the connection alive after sending data and getting a response.
* @default true */
keepAlive?: boolean
Expand Down Expand Up @@ -78,6 +83,7 @@ interface ValidatedClientOptions extends Pick<Required<ClientOptions>, Validated
}

interface ValidatedClientListenerOptions extends Pick<Required<ClientListenerOptions>, ValidatedClientListenerKeys> {
encoding: BufferEncoding
port: number
maxConnections: number
waitAck: boolean
Expand Down

0 comments on commit fc863f6

Please sign in to comment.