From 7af097037e201b7fb63394ea757c2edf688a965c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CBugs5382=E2=80=9D?= Date: Mon, 3 Jun 2024 06:15:55 -0400 Subject: [PATCH 1/2] fix: 2.4 spec MSH9.3 - fixed MSH 2.4 and above to support MSH9.3 as an ACK --- __tests__/hl7.build.test.ts | 32 +++++++++++++++++++++++++++++++ __tests__/hl7.sanity.test.ts | 37 ++++++++++++++++++++++++++++++++++++ package.json | 16 ++++++++-------- src/hl7.ts | 2 +- src/specification/2.4.ts | 9 ++++++++- src/specification/2.5.1.ts | 4 ++++ src/specification/2.5.ts | 4 ++++ src/specification/2.6.ts | 4 ++++ src/specification/2.7.1.ts | 5 +++++ src/specification/2.7.ts | 5 +++++ src/specification/2.8.ts | 5 +++++ 11 files changed, 113 insertions(+), 10 deletions(-) diff --git a/__tests__/hl7.build.test.ts b/__tests__/hl7.build.test.ts index 401ca2c..d8edfa8 100644 --- a/__tests__/hl7.build.test.ts +++ b/__tests__/hl7.build.test.ts @@ -120,6 +120,22 @@ describe('node hl7 client - builder tests', () => { expect(message.toString()).toBe('MSH|^~\\&|||||20081231||ADT^A01|12345|D^A|2.3.1') }) + test('2.3.1 - build - MSH9.3 has no bearing', async () => { + const message = new Message({ + specification: new HL7_2_3_1(), + messageHeader: { + msh_9_1: 'ADT', + msh_9_2: 'A01', + msh_9_3: 'ACK', + msh_10: '12345', + msh_11_1: 'D', + msh_11_2: 'A' + } + }) + message.set('MSH.7', '20081231') + expect(message.toString()).toBe('MSH|^~\\&|||||20081231||ADT^A01|12345|D^A|2.3.1') + }) + test('2.4 - build', async () => { const message = new Message({ specification: new HL7_2_4(), @@ -135,6 +151,22 @@ describe('node hl7 client - builder tests', () => { expect(message.toString()).toBe('MSH|^~\\&|||||20081231||ADT^A01^ADT_A01|12345|D^A|2.4') }) + test('2.4 - build - MSH9.3 override', async () => { + const message = new Message({ + specification: new HL7_2_4(), + messageHeader: { + msh_9_1: 'ACK', + msh_9_2: 'A01', + msh_9_3: 'ACK', + msh_10: '12345', + msh_11_1: 'D', + msh_11_2: 'A' + } + }) + message.set('MSH.7', '20081231') + expect(message.toString()).toBe('MSH|^~\\&|||||20081231||ACK^A01^ACK|12345|D^A|2.4') + }) + test('2.5 - build', async () => { const message = new Message({ specification: new HL7_2_5(), diff --git a/__tests__/hl7.sanity.test.ts b/__tests__/hl7.sanity.test.ts index dc5f82b..2a42db3 100644 --- a/__tests__/hl7.sanity.test.ts +++ b/__tests__/hl7.sanity.test.ts @@ -1,5 +1,6 @@ import { describe, expect, test } from 'vitest'; import {Batch, FileBatch, isBatch, isFile, Message} from "../src"; +import {HL7_2_4} from "../src/specification/2.4"; import {MSH_HEADER} from "./__data__/constants"; describe('node hl7 client - sanity tests', () => { @@ -88,6 +89,42 @@ describe('node hl7 client - sanity tests', () => { } }) + test('error - Message Object - msh 9.3 less than 3.', async () => { + try { + new Message({ + specification: new HL7_2_4(), + messageHeader: { + msh_9_1: 'ADT', + msh_9_2: 'A01', + msh_9_3: 'AC', + msh_10: '12345', + msh_11_1: 'D', + msh_11_2: 'A' + } + }) + } catch (err) { + expect(err).toEqual(new Error('MSH.9.3 must be 3 to 10 characters in length if specified.')) + } + }) + + test('error - Message Object - msh 9.3 more than 10.', async () => { + try { + new Message({ + specification: new HL7_2_4(), + messageHeader: { + msh_9_1: 'ADT', + msh_9_2: 'A01', + msh_9_3: 'ADT_A01Y', + msh_10: '12345', + msh_11_1: 'D', + msh_11_2: 'A' + } + }) + } catch (err) { + expect(err).toEqual(new Error('MSH.9.3 must be 3 to 10 characters in length if specified.')) + } + }) + test('error - Message Object - msh 10 is more than 199 characters ', async () => { try { new Message({ diff --git a/package.json b/package.json index a802416..ba76428 100644 --- a/package.json +++ b/package.json @@ -75,13 +75,13 @@ "@semantic-release/changelog": "^6.0.3", "@semantic-release/git": "^10.0.1", "@the-rabbit-hole/semantic-release-config": "^1.5.0", - "@types/node": "^20.11.21", + "@types/node": "^20.14.0", "@types/tcp-port-used": "^1.0.4", - "@typescript-eslint/parser": "^7.1.0", - "@vitest/coverage-v8": "^1.3.1", - "@vitest/ui": "^1.3.1", - "node-hl7-server": "^2.0.0", - "npm-check-updates": "^16.14.15", + "@typescript-eslint/parser": "^7.11.0", + "@vitest/coverage-v8": "^1.6.0", + "@vitest/ui": "^1.6.0", + "node-hl7-server": "^2.2.0", + "npm-check-updates": "^16.14.20", "npm-package-json-lint": "^7.1.0", "portfinder": "^1.0.32", "pre-commit": "^1.2.2", @@ -91,9 +91,9 @@ "ts-node": "^10.9.2", "ts-standard": "^12.0.2", "tsd": "^0.31.0", - "typedoc": "^0.25.9", + "typedoc": "^0.25.13", "typescript": "5.4.5", - "vitest": "^1.3.1" + "vitest": "^1.6.0" }, "precommit": [ "lint:fix", diff --git a/src/hl7.ts b/src/hl7.ts index e437284..d7e40ea 100644 --- a/src/hl7.ts +++ b/src/hl7.ts @@ -11,4 +11,4 @@ export { HL7_2_7, HL7_2_7_MSH } from './specification/2.7.js' export { HL7_2_7_1, HL7_2_7_1_MSH } from './specification/2.7.1.js' export { HL7_2_8, HL7_2_8_MSH } from './specification/2.8.js' export { HL7_SPEC, HL7_SPEC_BASE } from './specification/specification.js' -export { MSH } from './specification/specification.js' \ No newline at end of file +export { MSH } from './specification/specification.js' diff --git a/src/specification/2.4.ts b/src/specification/2.4.ts index 9e67d63..fd7d332 100644 --- a/src/specification/2.4.ts +++ b/src/specification/2.4.ts @@ -31,6 +31,10 @@ export interface HL7_2_4_MSH { /** Trigger Event * @since 1.0.0 */ msh_9_2: string + /** Message Structure + * @since 2.2.0 + * @default If not specified, it will be the combo of 9.1 and 9.2 with an underscore. */ + msh_9_3?: string /** Message Control ID * @description This ID is unique to the message being sent * so the client can track @@ -66,6 +70,9 @@ export class HL7_2_4 extends HL7_2_3_1 { */ checkMSH (msh: HL7_2_4_MSH): boolean { super.checkMSH(msh) + if (typeof msh.msh_9_3 !== 'undefined' && (msh.msh_9_3.length < 3 || msh.msh_9_3.length > 10)) { + throw new Error('MSH.9.3 must be 3 to 10 characters in length if specified.') + } return true } @@ -77,6 +84,6 @@ export class HL7_2_4 extends HL7_2_3_1 { */ buildMSH (mshHeader: HL7_2_4_MSH, message: Message): void { super.buildMSH(mshHeader, message) - message.set('MSH.9.3', `${mshHeader.msh_9_1.toString()}_${mshHeader.msh_9_2.toString()}`) + message.set('MSH.9.3', typeof mshHeader.msh_9_3 !== 'undefined' ? mshHeader.msh_9_3.toString() : `${mshHeader.msh_9_1.toString()}_${mshHeader.msh_9_2.toString()}`) } } diff --git a/src/specification/2.5.1.ts b/src/specification/2.5.1.ts index 31a1676..da16246 100644 --- a/src/specification/2.5.1.ts +++ b/src/specification/2.5.1.ts @@ -31,6 +31,10 @@ export interface HL7_2_5_1_MSH { /** Trigger Event * @since 1.0.0 */ msh_9_2: string + /** Message Structure + * @since 2.2.0 + * @default If not specified, it will be the combo of 9.1 and 9.2 with an underscore. */ + msh_9_3?: string /** Message Control ID * @description This ID is unique to the message being sent * so the client can track diff --git a/src/specification/2.5.ts b/src/specification/2.5.ts index 3c6ee17..46a1adf 100644 --- a/src/specification/2.5.ts +++ b/src/specification/2.5.ts @@ -31,6 +31,10 @@ export interface HL7_2_5_MSH { /** Trigger Event * @since 1.0.0 */ msh_9_2: string + /** Message Structure + * @since 2.2.0 + * @default If not specified, it will be the combo of 9.1 and 9.2 with an underscore. */ + msh_9_3?: string /** Message Control ID * @description This ID is unique to the message being sent * so the client can track diff --git a/src/specification/2.6.ts b/src/specification/2.6.ts index 56c393a..e844b14 100644 --- a/src/specification/2.6.ts +++ b/src/specification/2.6.ts @@ -31,6 +31,10 @@ export interface HL7_2_6_MSH { /** Trigger Event * @since 1.0.0 */ msh_9_2: string + /** Message Structure + * @since 2.2.0 + * @default If not specified, it will be the combo of 9.1 and 9.2 with an underscore. */ + msh_9_3?: string /** Message Control ID * @description This ID is unique to the message being sent * so the client can track diff --git a/src/specification/2.7.1.ts b/src/specification/2.7.1.ts index b14a947..04972d0 100644 --- a/src/specification/2.7.1.ts +++ b/src/specification/2.7.1.ts @@ -30,6 +30,10 @@ export interface HL7_2_7_1_MSH { /** Trigger Event * @since 1.0.0 */ msh_9_2: string + /** Message Structure + * @since 2.2.0 + * @default If not specified, it will be the combo of 9.1 and 9.2 with an underscore. */ + msh_9_3?: string /** Message Control ID * @description This ID is unique to the message being sent * so the client can track @@ -68,6 +72,7 @@ export class HL7_2_7_1 extends HL7_2_7 { /** * Build HL7 MSH Segment + * @since 1.0.0 * @param mshHeader * @param message */ diff --git a/src/specification/2.7.ts b/src/specification/2.7.ts index f871e06..331274a 100644 --- a/src/specification/2.7.ts +++ b/src/specification/2.7.ts @@ -30,6 +30,10 @@ export interface HL7_2_7_MSH { /** Trigger Event * @since 1.0.0 */ msh_9_2: string + /** Message Structure + * @since 2.2.0 + * @default If not specified, it will be the combo of 9.1 and 9.2 with an underscore. */ + msh_9_3?: string /** Message Control ID * @description This ID is unique to the message being sent * so the client can track @@ -85,6 +89,7 @@ export class HL7_2_7 extends HL7_2_6 { /** * Build HL7 MSH Segment + * @since 1.0.0 * @param mshHeader * @param message */ diff --git a/src/specification/2.8.ts b/src/specification/2.8.ts index 3bd0166..103edca 100644 --- a/src/specification/2.8.ts +++ b/src/specification/2.8.ts @@ -30,6 +30,10 @@ export interface HL7_2_8_MSH { /** Trigger Event * @since 1.0.0 */ msh_9_2: string + /** Message Structure + * @since 2.2.0 + * @default If not specified, it will be the combo of 9.1 and 9.2 with an underscore. */ + msh_9_3?: string /** Message Control ID * @description This ID is unique to the message being sent * so the client can track @@ -68,6 +72,7 @@ export class HL7_2_8 extends HL7_2_7_1 { /** * Build HL7 MSH Segment + * @since 1.0.0 * @param mshHeader * @param message */ From c83c27044de0863cbe064283b1657372ddd4dc91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CBugs5382=E2=80=9D?= Date: Mon, 3 Jun 2024 09:34:46 -0400 Subject: [PATCH 2/2] docs: updated builder - added MSH 9.3 example --- pages/builder/index.md | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/pages/builder/index.md b/pages/builder/index.md index da2f067..bfd633d 100644 --- a/pages/builder/index.md +++ b/pages/builder/index.md @@ -28,6 +28,44 @@ This NPM package assumes that you understand HL7 requirements and understand whe ## Main Contents of HL7 +### HL7 Specifications + +HL7 is set to a set of specification. +They range from 2.1 to 2.8. +While it would take hundreds of pages here to describe the difference between the different specification, +[this site](https://hl7-definition.caristix.com/v2/) can review what the different segments do. + +The major difference for the MSH header segment for the versions is from 2.1 to 2.3.1, +where the field MSH 9.3 is a combined string of MSH 9.1 and MSH 9.2. +From HL7 version 2.4 and onward, MSH 9.3 can either be ACK or a combined string of MSH 9.1 and MSH 9.2. +To override MSH 9.3 in 2.4 and higher follow this example: + +```ts +const message = new Message({ + specification: new HL7_2_4(), + messageHeader: { + msh_9_1: 'ADT', + msh_9_2: 'A01', + msh_9_3: 'ACK', + msh_10: '12345', + msh_11_1: 'D', + msh_11_2: 'A' + } +}) +``` + +This will results in this: + +```ts +MSH|^~\&|||||20081231||ADT^A01^ACK|12345|D^A|2.4 +``` + +As the MSH header segment. Otherwise not including the msh_9_3 above will make it: + +```ts +MSH|^~\&|||||20081231||ADT^A01^ADT_A02|12345|D^A|2.4 +``` + ### Build a Sample HL7 MSH Segment All HL7 messages (not the Batch or File Batch which could contain Messages) start with MSH segments, and they are build quite easily. Right not the deface standard has been version 2.7 of its most common use. There isn't much different between v2.7, v2.7.1 and v2.8, and this is to the fact that v2.5 really expanded the segment types that exist was we moved to more modern Electronic Medical Record systems.