diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index 2441e71..0000000 --- a/.eslintignore +++ /dev/null @@ -1,3 +0,0 @@ -/__tests__/* -/bin/**/* -vitest.config.ts \ No newline at end of file diff --git a/.github/dependabot.yml b/.github/dependabot.yml deleted file mode 100644 index aad6462..0000000 --- a/.github/dependabot.yml +++ /dev/null @@ -1,9 +0,0 @@ -version: 2 -updates: - - package-ecosystem: npm - directory: "/" - target-branch: 'develop' - schedule: - interval: daily - time: "10:00" - open-pull-requests-limit: 10 \ No newline at end of file diff --git a/.github/pr-title-checker-config.json b/.github/pr-title-checker-config.json deleted file mode 100644 index 3894be0..0000000 --- a/.github/pr-title-checker-config.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "LABEL": { - "name": "title needs formatting", - "color": "EEEEEE" - }, - "CHECKS": { - "prefixes": ["[Bot] docs: "], - "regexp": "^(feat|fix|docs|test|ci|chore)!?(\\(.*\\))?!?:.*" - }, - "MESSAGES": { - "success": "PR title is valid", - "failure": "PR title is invalid", - "notice": "PR Title needs to pass regex '^(feat|fix|docs|test|ci|chore)!?(\\(.*\\))?!?:.*" - } -} \ No newline at end of file diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml index aabeea1..6f9e4e1 100644 --- a/.github/release-drafter.yml +++ b/.github/release-drafter.yml @@ -53,4 +53,4 @@ version-resolver: - patch default: patch exclude-labels: - - skip-changelog + - skip-changelog \ No newline at end of file diff --git a/.github/workflows/action-deploy.yaml b/.github/workflows/action-deploy.yaml new file mode 100644 index 0000000..afc1877 --- /dev/null +++ b/.github/workflows/action-deploy.yaml @@ -0,0 +1,108 @@ +name: Release and Publish +on: + release: + types: + - released + +permissions: + contents: write + actions: write + checks: write + id-token: write + +jobs: + Test: + uses: ./.github/workflows/action-test.yaml + + Strip_Version: + runs-on: ubuntu-latest + outputs: + CLEAN_TAG: ${{ steps.set-output.outputs.CLEAN_TAG }} + steps: + - name: Strip "v" from Tag + id: set-output + run: echo "CLEAN_TAG=${GITHUB_EVENT_RELEASE_TAG_NAME#v}" >> $GITHUB_OUTPUT + env: + GITHUB_EVENT_RELEASE_TAG_NAME: ${{ github.event.release.tag_name }} + + Publish: + runs-on: ubuntu-latest + outputs: + GIT_BRANCH_TARGET: ${{ steps.set-npm-tag.outputs.GIT_BRANCH_TARGET }} + needs: ['Test', 'Strip_Version'] + env: + CLEAN_TAG: ${{ needs.Strip_Version.outputs.CLEAN_TAG }} + steps: + - name: Create Directory + run: mkdir -p ./lib + + - name: Download the build artifact + uses: actions/download-artifact@v4 + with: + name: cache + path: ./ + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: lts/* + registry-url: 'https://registry.npmjs.org/' + + - name: Update Version in Package.json + id: set-npm-tag + run: | + npm version $CLEAN_TAG --no-git-tag-version + if [[ "$CLEAN_TAG" == *"beta"* ]]; then + echo "NPM_TAG=beta" >> $GITHUB_OUTPUT + echo "GIT_BRANCH_TARGET=develop" >> $GITHUB_OUTPUT + else + echo "NPM_TAG=latest" >> $GITHUB_OUTPUT + echo "GIT_BRANCH_TARGET=main" >> $GITHUB_OUTPUT + fi + + - name: Publish to npm + uses: JS-DevTools/npm-publish@v3 + with: + token: ${{ secrets.NPM_TOKEN }} + tag: ${{ steps.set-npm-tag.outputs.NPM_TAG }} + + Update_Repo: + runs-on: ubuntu-latest + needs: ['Test', 'Strip_Version', 'Publish'] + permissions: + contents: write + actions: write + checks: write + env: + CLEAN_TAG: ${{ needs.Strip_Version.outputs.CLEAN_TAG }} + GIT_BRANCH_TARGET: ${{ needs.Publish.outputs.GIT_BRANCH_TARGET }} + steps: + # - uses: hmarr/debug-action@v3 + + - uses: actions/checkout@v4 + with: + token: '${{ secrets.GITHUB_TOKEN }}' + ref: ${{ env.GIT_BRANCH_TARGET }} + sparse-checkout: | + package.json + CHANGELOG.md + sparse-checkout-cone-mode: false + + - name: Update Version in Package.json + id: set-git-branch + run: npm version $CLEAN_TAG --no-git-tag-version + + - name: Update Changelog + uses: stefanzweifel/changelog-updater-action@v1 + with: + latest-version: ${{ github.event.release.name }} + release-notes: ${{ github.event.release.body }} + + - name: Commit and Push Version Update + uses: stefanzweifel/git-auto-commit-action@v4 + with: + commit_message: "chore(release): ${{ github.event.release.tag_name }} [skip ci]" + + Document: + needs: ['Update_Repo', 'Publish'] + uses: ./.github/workflows/action-docs.yaml diff --git a/.github/workflows/action-docs.yaml b/.github/workflows/action-docs.yaml new file mode 100644 index 0000000..e66c349 --- /dev/null +++ b/.github/workflows/action-docs.yaml @@ -0,0 +1,125 @@ +name: Publish Docs +on: + workflow_dispatch: + workflow_call: + +permissions: + contents: write + actions: write + checks: write + +jobs: + History: + runs-on: ubuntu-latest + steps: + - name: Check if branch exists + id: branch_check + run: | + if git show-ref --verify --quiet refs/heads/gh-pages; then + echo "Branch exists" + echo "exists=true" >> $GITHUB_ENV + else + echo "Branch does not exist" + echo "exists=false" >> $GITHUB_ENV + fi + continue-on-error: true + + - name: Get the gh-pages repo + if: env.exists == 'true' + uses: actions/checkout@v4 + with: + ref: gh-pages + + - name: TAR the existing docs + if: env.exists == 'true' + run: | + mkdir -p ./docs + tar -cvf documentation.tar ./docs + + - name: Create a document artifact + if: env.exists == 'true' + uses: actions/upload-artifact@v4 + with: + name: documentation + path: documentation.tar + Build: + needs: History + runs-on: ubuntu-latest + steps: + - name: Checkout src + uses: actions/checkout@v4 + + - name: Create Directory + run: mkdir -p ./docs + + - name: Download the existing documents artifact + uses: actions/download-artifact@v4 + with: + name: documentation + continue-on-error: true + + - run: tar -xf documentation.tar ./docs -C ./docs + continue-on-error: true + + - name: Build + uses: actions/setup-node@v4 + with: + node-version: lts/* + + - name: Install NPM + run: npm install --ignore-scripts + + - name: Build Documents + run: npm run typedoc + + - name: Tar the new docs + run: tar -cvf newdocumentation.tar ./docs + + - name: Create a new document artifact + uses: actions/upload-artifact@v4 + with: + name: newdocumentation + path: newdocumentation.tar + Commit: + needs: Build + runs-on: ubuntu-latest + steps: + - name: Check if branch exists + id: branch_check + run: | + if git show-ref --verify --quiet refs/heads/gh-pages; then + echo "Branch exists" + echo "exists=true" >> $GITHUB_ENV + else + echo "Branch does not exist" + echo "exists=false" >> $GITHUB_ENV + fi + continue-on-error: true + + - name: Checkout the gh-pages repo + if: env.exists == 'true' + uses: actions/checkout@v4 + with: + ref: gh-pages + + - name: Create Directory + run: mkdir -p ./docs + + - name: Download the new documents artifact + uses: actions/download-artifact@v4 + with: + name: newdocumentation + continue-on-error: true + + - name: Extract Tar + run: tar -xf newdocumentation.tar ./docs -C ./docs + + - name: Deploy to GitHub Pages + uses: peaceiris/actions-gh-pages@v4 + with: + allow_empty_commit: true + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_branch: gh-pages + publish_dir: ./docs + user_name: 'github-actions[bot]' + user_email: 'github-actions[bot]@users.noreply.github.com' \ No newline at end of file diff --git a/.github/workflows/action-test.yaml b/.github/workflows/action-test.yaml new file mode 100644 index 0000000..b24caa1 --- /dev/null +++ b/.github/workflows/action-test.yaml @@ -0,0 +1,55 @@ +name: Test +on: + workflow_dispatch: + workflow_call: + pull_request: + branches: + - main + - develop + types: + - opened + - reopened + - ready_for_review + - synchronize + + +jobs: + + Build: + runs-on: ubuntu-latest + strategy: + matrix: + node-version: [20.x, 'lts/*', 'latest'] + steps: + - uses: actions/checkout@v4 + + - name: Test with Node ${{matrix.node-version}} + uses: actions/setup-node@v4 + with: + node-version: ${{matrix.node-version}} + + - name: Pre-Run + run: | + npm install --package-lock-only + npm install --ignore-scripts + + - name: Run Tests and Lint + run: | + npm run lint + npm run test + + - name: Run Build + run: | + npm run build + + - name: Upload build artifact + if: matrix.node-version == 'lts/*' + uses: actions/upload-artifact@v4 + with: + name: cache + path: | + package.json + package-lock.json + README.md + LICENSE + ./lib diff --git a/.github/workflows/dependabot-action.yml b/.github/workflows/dependabot-action.yml deleted file mode 100644 index 18811a7..0000000 --- a/.github/workflows/dependabot-action.yml +++ /dev/null @@ -1,61 +0,0 @@ -name: Dependabot Auto-Merge - -on: - pull_request_target: - types: [review_requested] - -permissions: - contents: write - pull-requests: write - packages: read - -jobs: - Dependabot: - runs-on: ubuntu-latest - strategy: - matrix: - node-version: [ 20.x, 'lts/*' ] - if: ${{ github.actor == 'dependabot[bot]' }} - steps: - - name: Dependabot metadata - id: metadata - uses: dependabot/fetch-metadata@v1.3.4 - with: - github-token: "${{ secrets.GH_TOKEN }}" - skip-commit-verification: true - - name: Checkout repository - uses: actions/checkout@v4 - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v4 - with: - node-version: ${{ matrix.node-version }} - - name: Install Dependencies - run: npm install --ignore-scripts - - name: Approve PR, if not already approved - run: | - gh pr checkout "$PR_URL" - if [ "$(gh pr status --json reviewDecision -q .currentBranch.reviewDecision)" != "APPROVED" ]; then - gh pr review --approve "$PR_URL" - else - echo "PR Already Approved."; - fi - env: - PR_URL: ${{ github.event.pull_request.html_url }} - GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} - - name: Run unit tests - run: | - npm run test - - name: Aggregate Dependabot PRs - id: aggregate_prs - run: | - PR_URL=$(gh pr list --json state:open author:dependabot[bot] base:$PR_BASE_BRANCH -q '.[].url' | jq -r 'join(" ")') - echo "::set-output name=pr_url::$PR_URL" - env: - PR_BASE_BRANCH: develop - GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} - - name: Merge aggregated PRs - if: steps.aggregate_prs.outputs.pr_url != '' - run: | - gh pr merge --auto --merge ${{ steps.aggregate_prs.outputs.pr_url }} - env: - GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} diff --git a/.github/workflows/deploy-ci.yaml b/.github/workflows/deploy-ci.yaml deleted file mode 100644 index 7275dad..0000000 --- a/.github/workflows/deploy-ci.yaml +++ /dev/null @@ -1,117 +0,0 @@ -name: "Deploy: CI" -on: - push: - branches: [ 'main', 'develop' ] - -permissions: - contents: write - issues: write - pull-requests: write - id-token: write - -jobs: - Test: - runs-on: ubuntu-latest - outputs: - src: ${{ steps.filter.outputs.src }} - test: ${{ steps.filter.outputs.test }} - strategy: - matrix: - node-version: [ 20.x, 'lts/*' ] - steps: - - uses: actions/checkout@v4 - with: - persist-credentials: false - - uses: dorny/paths-filter@v3.0.2 - id: filter - with: - filters: | - src: - - 'src/**' - test: - - '__tests__/**' - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v4 - with: - node-version: ${{ matrix.node-version }} - - name: Install Dependencies - if: steps.filter.outputs.src == 'true' && steps.filter.outputs.test == 'true' - run: npm install --ignore-scripts - - name: Run Lint - if: steps.filter.outputs.src == 'true' && steps.filter.outputs.test == 'true' - run: npm run lint - - name: Run Unit Tests - if: steps.filter.outputs.src == 'true' && steps.filter.outputs.test == 'true' - run: npm run test - Release: - runs-on: ubuntu-latest - needs: [ 'Test' ] - steps: - - uses: actions/checkout@v4 - if: ${{ needs.Test.outputs.src == 'true' && needs.Test.outputs.test == 'true' }} - with: - persist-credentials: false - - name: Use Node.js - if: ${{ needs.Test.outputs.src == 'true' && needs.Test.outputs.test == 'true' }} - uses: actions/setup-node@v4 - with: - node-version: 'lts/*' - - name: NPM Install - if: ${{ needs.Test.outputs.src == 'true' && needs.Test.outputs.test == 'true' }} - run: npm install --ignore-scripts - - name: Semantic Release (Dry Run) - if: ${{ needs.Test.outputs.src == 'true' && needs.Test.outputs.test == 'true' }} - run: npm run semantic-release:dry-run - env: - GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} - - name: Semantic Release - if: ${{ needs.Test.outputs.src == 'true' && needs.Test.outputs.test == 'true' }} - run: npm run semantic-release - env: - GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} - Merge: - runs-on: ubuntu-latest - needs: [ 'Release' ] - if: github.ref == 'refs/heads/main' - steps: - - uses: actions/checkout@v4 - with: - persist-credentials: false - ref: main - - name: Configure Git - run: | - git config --global user.email "bugs5382@users.noreply.github.com" - git config --global user.name "Bugs5382" - - name: Merge main into develop - run: | - git remote set-url origin https://x-access-token:${{ secrets.GH_TOKEN }}@github.com/${{ github.repository }} - git fetch origin - git checkout develop - git merge origin/main -m "chore(ci): merge main into develop [ci skip]" - git push origin develop - Docs: - runs-on: ubuntu-latest - needs: [ 'Release' ] - if: github.ref == 'refs/heads/main' - steps: - - uses: actions/checkout@v4 - with: - persist-credentials: false - ref: main - - name: Use Node.js - uses: actions/setup-node@v4 - with: - node-version: 'lts/*' - - name: NPM Install - run: npm install --ignore-scripts - - name: Generate Typedoc documentation - run: npm run typedoc - - name: Deploy to GitHub Pages - uses: peaceiris/actions-gh-pages@v4 - with: - github_token: ${{ secrets.GH_TOKEN }} - publish_dir: ./docs - user_name: 'github-actions[bot]' - user_email: 'github-actions[bot]@users.noreply.github.com' \ No newline at end of file diff --git a/.github/workflows/job-label-checker.yaml b/.github/workflows/job-label-checker.yaml new file mode 100644 index 0000000..dc194a1 --- /dev/null +++ b/.github/workflows/job-label-checker.yaml @@ -0,0 +1,36 @@ +name: Label Checker + +on: + pull_request: + types: + - opened + - synchronize + - reopened + - labeled + - unlabeled + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number }} + cancel-in-progress: true + +jobs: + Check_SemVer_Labels: + name: Check Semver labels + runs-on: ubuntu-latest + + steps: + - name: Check for Semver labels + if: github.ref == 'refs/heads/main' + uses: danielchabr/pr-labels-checker@v3.3 + with: + hasSome: major,minor,patch + githubToken: ${{ secrets.GITHUB_TOKEN }} + + Check_CC_Labels: + name: Check conventional commits labels + runs-on: ubuntu-latest + steps: + - uses: danielchabr/pr-labels-checker@v3.3 + with: + hasSome: feature,fix,changed,deprecated,removed,security,docs,dependencies,enhancement,bug,documentation + githubToken: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/job-pr-title-checker.yaml b/.github/workflows/job-pr-title-checker.yaml new file mode 100644 index 0000000..0cd5664 --- /dev/null +++ b/.github/workflows/job-pr-title-checker.yaml @@ -0,0 +1,23 @@ +name: Check PR title + +on: + pull_request: + types: + - opened + - reopened + - edited + - synchronize + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number }} + cancel-in-progress: true + +jobs: + Title_Checker: + name: Check PR title + runs-on: ubuntu-latest + + steps: + - uses: amannn/action-semantic-pull-request@v5.5.3 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/job-release-drafter.yaml b/.github/workflows/job-release-drafter.yaml new file mode 100644 index 0000000..fa0e26e --- /dev/null +++ b/.github/workflows/job-release-drafter.yaml @@ -0,0 +1,34 @@ +name: Release Drafter + +on: + push: + branches: + - main + - develop + pull_request: + branches: + - develop + +jobs: + Update_Draft_Release: + name: Release Drafter + runs-on: ubuntu-latest + + steps: + + - name: Update Release Draft (Develop) + if: github.ref_name == 'develop' + uses: release-drafter/release-drafter@v6 + with: + prerelease: ${{ github.ref_name == 'develop' }} + commitish: ${{ github.ref_name }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Update Release Draft + if: github.ref_name == 'main' + uses: release-drafter/release-drafter@v6 + with: + commitish: ${{ github.ref_name }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/pr-title-check.yml b/.github/workflows/pr-title-check.yml deleted file mode 100644 index a2fd48e..0000000 --- a/.github/workflows/pr-title-check.yml +++ /dev/null @@ -1,29 +0,0 @@ -name: "PR: Lint Title" - -on: - pull_request_target: - types: [opened, edited, reopened, synchronize] - -# IMPORTANT: No checkout actions, scripts, or builds should be added to this workflow. Permissions should always be used -# with extreme caution. https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_target -permissions: {} - -# PR updates can happen in quick succession, leading to this -# workflow being trigger a number of times. This limits it -# to one run per PR. -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - - -jobs: - Validate: - permissions: - contents: read - pull-requests: read - name: Validate PR Title - runs-on: ubuntu-latest - steps: - - uses: thehanimo/pr-title-checker@v1.4.2 - with: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - configuration_path: ".github/pr-title-checker-config.json" \ No newline at end of file diff --git a/.github/workflows/pr-unit-tests.yml b/.github/workflows/pr-unit-tests.yml deleted file mode 100644 index f58254b..0000000 --- a/.github/workflows/pr-unit-tests.yml +++ /dev/null @@ -1,46 +0,0 @@ -name: "PR: Unit Tests" - -on: - pull_request: - branches: - - develop - types: - - opened - - synchronize - -jobs: - Test: - name: Run Unit tests - runs-on: ubuntu-latest - strategy: - matrix: - node-version: [ 20.x, 'lts/*' ] - steps: - - uses: actions/checkout@v4 - with: - persist-credentials: false - - uses: dorny/paths-filter@v3.0.2 - id: filter - with: - filters: | - src: - - 'src/**' - test: - - '__tests__/**' - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v4 - with: - node-version: ${{ matrix.node-version }} - - name: Install Dependencies - if: steps.filter.outputs.src == 'true' && steps.filter.outputs.test == 'true' - run: npm install --ignore-scripts - - name: Run Lint - if: steps.filter.outputs.src == 'true' && steps.filter.outputs.test == 'true' - run: npm run lint - - name: Run Unit Tests - if: steps.filter.outputs.src == 'true' && steps.filter.outputs.test == 'true' - run: npm run test - - name: Check test results - if: steps.filter.outputs.src == 'true' && steps.filter.outputs.test == 'true' - run: exit ${{ steps.Test.outputs.test_result }} - id: check_test_result diff --git a/.run/Regular Server.run.xml b/.run/Regular Server.run.xml new file mode 100644 index 0000000..862bb6f --- /dev/null +++ b/.run/Regular Server.run.xml @@ -0,0 +1,21 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.run/TLS Server.run.xml b/.run/TLS Server.run.xml new file mode 100644 index 0000000..e0d9171 --- /dev/null +++ b/.run/TLS Server.run.xml @@ -0,0 +1,21 @@ + + + + + + + + + + \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 7a79b6a..8e605e3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,464 +1 @@ -# [3.0.0](https://github.com/Bugs5382/node-hl7-server/compare/v2.5.0...v3.0.0) (2024-09-21) - - -* 103 feat allow overriding response msh content ([#107](https://github.com/Bugs5382/node-hl7-server/issues/107)) ([ba7ec92](https://github.com/Bugs5382/node-hl7-server/commit/ba7ec92f9626146464e1071230c37fc6a2fa1026)) - - -### Features - -* 3.0.0 ([#108](https://github.com/Bugs5382/node-hl7-server/issues/108)) ([1252e23](https://github.com/Bugs5382/node-hl7-server/commit/1252e236e1814e48bef27a203a1ca55fc0ad7457)) -* Allow overriding response MSH content [#103](https://github.com/Bugs5382/node-hl7-server/issues/103) ([b208429](https://github.com/Bugs5382/node-hl7-server/commit/b2084293a0f94dbd26ee75bc4eb78b3c6a2c8c00)) -* Allow overriding response MSH content [#103](https://github.com/Bugs5382/node-hl7-server/issues/103) ([#106](https://github.com/Bugs5382/node-hl7-server/issues/106)) ([1dcef70](https://github.com/Bugs5382/node-hl7-server/commit/1dcef70849ba17feec1209134cd4b16dc4c1c232)) - - -### BREAKING CHANGES - -* MSH Override Changes -* MSH Override Changes - -# [3.0.0-beta.2](https://github.com/Bugs5382/node-hl7-server/compare/v3.0.0-beta.1...v3.0.0-beta.2) (2024-09-21) - - -### Features - -* develop ([#104](https://github.com/Bugs5382/node-hl7-server/issues/104)) ([b38334b](https://github.com/Bugs5382/node-hl7-server/commit/b38334b5f6bb9cc205f7eb1979eac2848a400ece)) - -# [3.0.0-beta.1](https://github.com/Bugs5382/node-hl7-server/compare/v2.5.0-beta.1...v3.0.0-beta.1) (2024-09-21) - -### Features - -* Allow overriding response MSH content [#103](https://github.com/Bugs5382/node-hl7-server/issues/103) ([b208429](https://github.com/Bugs5382/node-hl7-server/commit/b2084293a0f94dbd26ee75bc4eb78b3c6a2c8c00)) - - -### BREAKING CHANGES - -* MSH Override Changes - -# [2.5.0](https://github.com/Bugs5382/node-hl7-server/compare/v2.4.1...v2.5.0) (2024-08-29) - - -### Features - -* **#100:** added AE support ([20f33c3](https://github.com/Bugs5382/node-hl7-server/commit/20f33c37943677bb2d21a386fbdf3fec63fe1d86)), closes [#100](https://github.com/Bugs5382/node-hl7-server/issues/100) -* **#100:** support ae type in send response ([#101](https://github.com/Bugs5382/node-hl7-server/issues/101)) ([5e09595](https://github.com/Bugs5382/node-hl7-server/commit/5e095952b4a4894c46b28e27734d2b2509b91af2)), closes [#100](https://github.com/Bugs5382/node-hl7-server/issues/100) -* develop ([#104](https://github.com/Bugs5382/node-hl7-server/issues/104)) ([b38334b](https://github.com/Bugs5382/node-hl7-server/commit/b38334b5f6bb9cc205f7eb1979eac2848a400ece)) - -# [2.5.0-beta.1](https://github.com/Bugs5382/node-hl7-server/compare/v2.4.1...v2.5.0-beta.1) (2024-08-20) - - -### Features - -* **#100:** added AE support ([20f33c3](https://github.com/Bugs5382/node-hl7-server/commit/20f33c37943677bb2d21a386fbdf3fec63fe1d86)), closes [#100](https://github.com/Bugs5382/node-hl7-server/issues/100) -* **#100:** support ae type in send response ([#101](https://github.com/Bugs5382/node-hl7-server/issues/101)) ([5e09595](https://github.com/Bugs5382/node-hl7-server/commit/5e095952b4a4894c46b28e27734d2b2509b91af2)), closes [#100](https://github.com/Bugs5382/node-hl7-server/issues/100) - -## [2.4.1](https://github.com/Bugs5382/node-hl7-server/compare/v2.4.0...v2.4.1) (2024-06-25) - - -### Bug Fixes - -* **60:** Added test to replicate the issue ([f745ceb](https://github.com/Bugs5382/node-hl7-server/commit/f745cebe8e93c2ebb4a14211abf9cb6be4dcdc5e)) -* **60:** Ensure large messages like encapsulated PDFs are not split and ignored by the server ([#86](https://github.com/Bugs5382/node-hl7-server/issues/86)) ([c92a612](https://github.com/Bugs5382/node-hl7-server/commit/c92a612a215223f752fe097926d55291194ad753)) -* Added additional assertion ([6b596eb](https://github.com/Bugs5382/node-hl7-server/commit/6b596ebb517516cc989a3540f0f2b308d2019bee)) -* Added fix to ensure message body is concatenated ([9d927ab](https://github.com/Bugs5382/node-hl7-server/commit/9d927ab272757e5fb24655e357afaeff3f7f0c17)) -* large files ([#87](https://github.com/Bugs5382/node-hl7-server/issues/87)) ([a73d993](https://github.com/Bugs5382/node-hl7-server/commit/a73d99369429157ba48f62588fd1078ae79c9d87)) - -## [2.4.1-beta.1](https://github.com/Bugs5382/node-hl7-server/compare/v2.4.0...v2.4.1-beta.1) (2024-06-25) - - -### Bug Fixes - -* **60:** Added test to replicate the issue ([f745ceb](https://github.com/Bugs5382/node-hl7-server/commit/f745cebe8e93c2ebb4a14211abf9cb6be4dcdc5e)) -* **60:** Ensure large messages like encapsulated PDFs are not split and ignored by the server ([#86](https://github.com/Bugs5382/node-hl7-server/issues/86)) ([c92a612](https://github.com/Bugs5382/node-hl7-server/commit/c92a612a215223f752fe097926d55291194ad753)) -* Added additional assertion ([6b596eb](https://github.com/Bugs5382/node-hl7-server/commit/6b596ebb517516cc989a3540f0f2b308d2019bee)) -* Added fix to ensure message body is concatenated ([9d927ab](https://github.com/Bugs5382/node-hl7-server/commit/9d927ab272757e5fb24655e357afaeff3f7f0c17)) - -# [2.4.0](https://github.com/Bugs5382/node-hl7-server/compare/v2.3.0...v2.4.0) (2024-06-25) - - -### Features - -* update ([#83](https://github.com/Bugs5382/node-hl7-server/issues/83)) ([6071fb1](https://github.com/Bugs5382/node-hl7-server/commit/6071fb15556d5d42c86e316bb4b5346fe77633b5)) -* update packages ([422fa6f](https://github.com/Bugs5382/node-hl7-server/commit/422fa6f958fe7d3cab9baa50055deac79a006fe9)) -* update packages ([#82](https://github.com/Bugs5382/node-hl7-server/issues/82)) ([8e9fe1f](https://github.com/Bugs5382/node-hl7-server/commit/8e9fe1f6bcf83868c09bd9690e5557f963c9bc95)) - -# [2.4.0-beta.1](https://github.com/Bugs5382/node-hl7-server/compare/v2.3.0...v2.4.0-beta.1) (2024-06-25) - - -### Features - -* update packages ([422fa6f](https://github.com/Bugs5382/node-hl7-server/commit/422fa6f958fe7d3cab9baa50055deac79a006fe9)) -* update packages ([#82](https://github.com/Bugs5382/node-hl7-server/issues/82)) ([8e9fe1f](https://github.com/Bugs5382/node-hl7-server/commit/8e9fe1f6bcf83868c09bd9690e5557f963c9bc95)) - -# [2.3.0-beta.1](https://github.com/Bugs5382/node-hl7-server/compare/v2.2.0...v2.3.0-beta.1) (2024-06-04) -# [2.3.0](https://github.com/Bugs5382/node-hl7-server/compare/v2.2.0...v2.3.0) (2024-06-04) - - - -### Features - -* added MSH override with spec being passed over ([c0754e1](https://github.com/Bugs5382/node-hl7-server/commit/c0754e15742fb6674718c80116a07f4ebe2caaf1)) -* added MSH override with spec being passed over ([#77](https://github.com/Bugs5382/node-hl7-server/issues/77)) ([8ecdb26](https://github.com/Bugs5382/node-hl7-server/commit/8ecdb263da4d615da6fad091ce4db3bbba5d80b5)) -* update packages ([06f6fc9](https://github.com/Bugs5382/node-hl7-server/commit/06f6fc9993c71c295021d5baa8aae10d3f02fb67)) -* updated MSH response issues ([#78](https://github.com/Bugs5382/node-hl7-server/issues/78)) ([25a4405](https://github.com/Bugs5382/node-hl7-server/commit/25a4405cb5b86a061c13bd14db512450e3c7d93c)) - -# [2.2.0-beta.2](https://github.com/Bugs5382/node-hl7-server/compare/v2.2.0-beta.1...v2.2.0-beta.2) (2024-06-04) - - -### Features - -* added MSH override with spec being passed over ([c0754e1](https://github.com/Bugs5382/node-hl7-server/commit/c0754e15742fb6674718c80116a07f4ebe2caaf1)) -* added MSH override with spec being passed over ([#77](https://github.com/Bugs5382/node-hl7-server/issues/77)) ([8ecdb26](https://github.com/Bugs5382/node-hl7-server/commit/8ecdb263da4d615da6fad091ce4db3bbba5d80b5)) -* update packages ([06f6fc9](https://github.com/Bugs5382/node-hl7-server/commit/06f6fc9993c71c295021d5baa8aae10d3f02fb67)) - -# [2.2.0-beta.1](https://github.com/Bugs5382/node-hl7-server/compare/v2.1.0...v2.2.0-beta.1) (2024-04-30) - -# [2.2.0](https://github.com/Bugs5382/node-hl7-server/compare/v2.1.0...v2.2.0) (2024-04-30) - - - -### Features - -* add getAckMessage ([c2d5442](https://github.com/Bugs5382/node-hl7-server/commit/c2d544212c97c52bd0adf9820343deb2241b70e6)), closes [#61](https://github.com/Bugs5382/node-hl7-server/issues/61) -* completed missing function ([#70](https://github.com/Bugs5382/node-hl7-server/issues/70)) ([03b012a](https://github.com/Bugs5382/node-hl7-server/commit/03b012a22ff1a361862c0c58f38a013712596c5a)) -* res.getackmessage() is not defined ([#69](https://github.com/Bugs5382/node-hl7-server/issues/69)) ([d37aaff](https://github.com/Bugs5382/node-hl7-server/commit/d37aaff486ed38441b244611f921cec87927fe44)) - -# [2.1.0-beta.3](https://github.com/Bugs5382/node-hl7-server/compare/v2.1.0-beta.2...v2.1.0-beta.3) (2024-04-30) -# [2.1.0](https://github.com/Bugs5382/node-hl7-server/compare/v2.0.0...v2.1.0) (2024-03-02) - - -### Features - -* add getAckMessage ([c2d5442](https://github.com/Bugs5382/node-hl7-server/commit/c2d544212c97c52bd0adf9820343deb2241b70e6)), closes [#61](https://github.com/Bugs5382/node-hl7-server/issues/61) -* res.getackmessage() is not defined ([#69](https://github.com/Bugs5382/node-hl7-server/issues/69)) ([d37aaff](https://github.com/Bugs5382/node-hl7-server/commit/d37aaff486ed38441b244611f921cec87927fe44)) -* added docker stuff ([f1a4140](https://github.com/Bugs5382/node-hl7-server/commit/f1a4140402be07ba5745e7d386295aade8aec4ff)) -* added docker stuff ([#57](https://github.com/Bugs5382/node-hl7-server/issues/57)) ([1052745](https://github.com/Bugs5382/node-hl7-server/commit/10527455154f587a2a020e71cd5e8e9168b0c4c6)) -* bind to 0.0.0.0 ([9f8c088](https://github.com/Bugs5382/node-hl7-server/commit/9f8c088361c3c6953e2db537e377c90904847a8b)) -* update node-hl7-client ([12876bf](https://github.com/Bugs5382/node-hl7-server/commit/12876bf20e2ec407cabff971a8acc08de40c0140)) -* update packages ([#58](https://github.com/Bugs5382/node-hl7-server/issues/58)) ([824eb6c](https://github.com/Bugs5382/node-hl7-server/commit/824eb6cd8c9ae4aa0df1b0f70f802cae972f38b6)) -* updated packages ([#59](https://github.com/Bugs5382/node-hl7-server/issues/59)) ([34978bc](https://github.com/Bugs5382/node-hl7-server/commit/34978bc2b916e5b0e6cb315d2c49006e9343c087)) - -# [2.1.0-beta.2](https://github.com/Bugs5382/node-hl7-server/compare/v2.1.0-beta.1...v2.1.0-beta.2) (2024-03-02) - - -### Features - -* update node-hl7-client ([12876bf](https://github.com/Bugs5382/node-hl7-server/commit/12876bf20e2ec407cabff971a8acc08de40c0140)) -* update packages ([#58](https://github.com/Bugs5382/node-hl7-server/issues/58)) ([824eb6c](https://github.com/Bugs5382/node-hl7-server/commit/824eb6cd8c9ae4aa0df1b0f70f802cae972f38b6)) - -# [2.1.0-beta.1](https://github.com/Bugs5382/node-hl7-server/compare/v2.0.0...v2.1.0-beta.1) (2024-03-02) - - -### Features - -* added docker stuff ([f1a4140](https://github.com/Bugs5382/node-hl7-server/commit/f1a4140402be07ba5745e7d386295aade8aec4ff)) -* added docker stuff ([#57](https://github.com/Bugs5382/node-hl7-server/issues/57)) ([1052745](https://github.com/Bugs5382/node-hl7-server/commit/10527455154f587a2a020e71cd5e8e9168b0c4c6)) -* bind to 0.0.0.0 ([9f8c088](https://github.com/Bugs5382/node-hl7-server/commit/9f8c088361c3c6953e2db537e377c90904847a8b)) - -# [2.0.0](https://github.com/Bugs5382/node-hl7-server/compare/v1.2.3...v2.0.0) (2024-02-04) - - -### Features - -* added stats ([cd4d345](https://github.com/Bugs5382/node-hl7-server/commit/cd4d34505bd0d62f6d9c3bdbc5b5cb10e801caa9)) -* added stats ([#48](https://github.com/Bugs5382/node-hl7-server/issues/48)) ([83365d2](https://github.com/Bugs5382/node-hl7-server/commit/83365d2f9d679217019fb8cfd1307b9f08573c20)) -* simple docker ([38d13ae](https://github.com/Bugs5382/node-hl7-server/commit/38d13aef449aaf8fc65c60450df0d54efaa0d2d5)) -* simple docker ([#49](https://github.com/Bugs5382/node-hl7-server/issues/49)) ([93928ec](https://github.com/Bugs5382/node-hl7-server/commit/93928ecc95c116de9438d480c4706f6cf50c026a)) -* updates ([7f855d2](https://github.com/Bugs5382/node-hl7-server/commit/7f855d246933ce81fcb9aa682ea203b0a471f63b)) -* updates ([#47](https://github.com/Bugs5382/node-hl7-server/issues/47)) ([f93d765](https://github.com/Bugs5382/node-hl7-server/commit/f93d7652d212a5a7a71d3b9e2908dce8e563dbbc)) -* v2.0.0 ([#51](https://github.com/Bugs5382/node-hl7-server/issues/51)) ([9fcd9f6](https://github.com/Bugs5382/node-hl7-server/commit/9fcd9f67123631c8b3ab847e74adfbcf986618f0)) - - -### BREAKING CHANGES - -* - node 20 -- updated to node-hl7-client to 2.0.0 - -# [2.0.0-beta.4](https://github.com/Bugs5382/node-hl7-server/compare/v2.0.0-beta.3...v2.0.0-beta.4) (2024-02-04) - - -### Bug Fixes - -* imports ([#45](https://github.com/Bugs5382/node-hl7-server/issues/45)) ([1e5165a](https://github.com/Bugs5382/node-hl7-server/commit/1e5165aad448afbf8775a18598dc19749182d1dd)) - -# [2.0.0-beta.3](https://github.com/Bugs5382/node-hl7-server/compare/v2.0.0-beta.2...v2.0.0-beta.3) (2024-02-04) - - -### Features - -* simple docker ([38d13ae](https://github.com/Bugs5382/node-hl7-server/commit/38d13aef449aaf8fc65c60450df0d54efaa0d2d5)) -* simple docker ([#49](https://github.com/Bugs5382/node-hl7-server/issues/49)) ([93928ec](https://github.com/Bugs5382/node-hl7-server/commit/93928ecc95c116de9438d480c4706f6cf50c026a)) - -# [2.0.0-beta.2](https://github.com/Bugs5382/node-hl7-server/compare/v2.0.0-beta.1...v2.0.0-beta.2) (2024-02-04) - - -### Features - -* added stats ([cd4d345](https://github.com/Bugs5382/node-hl7-server/commit/cd4d34505bd0d62f6d9c3bdbc5b5cb10e801caa9)) -* added stats ([#48](https://github.com/Bugs5382/node-hl7-server/issues/48)) ([83365d2](https://github.com/Bugs5382/node-hl7-server/commit/83365d2f9d679217019fb8cfd1307b9f08573c20)) - -# [2.0.0-beta.1](https://github.com/Bugs5382/node-hl7-server/compare/v1.2.3-beta.1...v2.0.0-beta.1) (2024-02-04) - - -### Features - -* updates ([7f855d2](https://github.com/Bugs5382/node-hl7-server/commit/7f855d246933ce81fcb9aa682ea203b0a471f63b)) -* updates ([#47](https://github.com/Bugs5382/node-hl7-server/issues/47)) ([f93d765](https://github.com/Bugs5382/node-hl7-server/commit/f93d7652d212a5a7a71d3b9e2908dce8e563dbbc)) - - -### BREAKING CHANGES - -* - node 20 -- updated to node-hl7-client to 2.0.0 - -## [1.2.3-beta.1](https://github.com/Bugs5382/node-hl7-server/compare/v1.2.2...v1.2.3-beta.1) (2024-01-18) - - -### Bug Fixes - -* added .js ([77607ab](https://github.com/Bugs5382/node-hl7-server/commit/77607abc66dd00baf10c834d1e685d93acde5540)) -* error err module not found ([#44](https://github.com/Bugs5382/node-hl7-server/issues/44)) ([99ec3db](https://github.com/Bugs5382/node-hl7-server/commit/99ec3dbca10f85d133af043ba63481bc86e3e4ac)) - -## [1.2.2](https://github.com/Bugs5382/node-hl7-server/compare/v1.2.1...v1.2.2) (2024-01-11) - - -### Bug Fixes - -* node-hl7-client ([#40](https://github.com/Bugs5382/node-hl7-server/issues/40)) ([4a0b76f](https://github.com/Bugs5382/node-hl7-server/commit/4a0b76f2060008cce5f574e334afbe3bbe644c32)) -* update node-hl7-client ([59bd843](https://github.com/Bugs5382/node-hl7-server/commit/59bd84393a5db97f01940d4a039f0802be47f975)) - -## [1.2.2-beta.1](https://github.com/Bugs5382/node-hl7-server/compare/v1.2.1...v1.2.2-beta.1) (2024-01-11) - - -### Bug Fixes - -* update node-hl7-client ([59bd843](https://github.com/Bugs5382/node-hl7-server/commit/59bd84393a5db97f01940d4a039f0802be47f975)) - -## [1.2.1-beta.1](https://github.com/Bugs5382/node-hl7-server/compare/v1.2.0...v1.2.1-beta.1) (2024-01-10) - - -### Bug Fixes - -* update node-hl7-client ([c1b91ca](https://github.com/Bugs5382/node-hl7-server/commit/c1b91cae20ef7b2f3453dfa7e92a240244fe2bb4)) - -## [1.2.1](https://github.com/Bugs5382/node-hl7-server/compare/v1.2.0...v1.2.1) (2024-01-10) - - -### Bug Fixes - -* update node-hl7-client ([c1b91ca](https://github.com/Bugs5382/node-hl7-server/commit/c1b91cae20ef7b2f3453dfa7e92a240244fe2bb4)) -* update node-hl7-client ([#39](https://github.com/Bugs5382/node-hl7-server/issues/39)) ([4006bf9](https://github.com/Bugs5382/node-hl7-server/commit/4006bf9d30ceb3c4daa3dc91ea80321dcbeb6112)) - -# [1.2.0](https://github.com/Bugs5382/node-hl7-server/compare/v1.1.0...v1.2.0) (2024-01-08) - - -### Bug Fixes - -* update node-hl7-client ([fc84d30](https://github.com/Bugs5382/node-hl7-server/commit/fc84d30779a866e15060d5e9a5e8e2807542ff83)) - - -### Features - -* update packages ([#38](https://github.com/Bugs5382/node-hl7-server/issues/38)) ([105b9a3](https://github.com/Bugs5382/node-hl7-server/commit/105b9a3e7b9ff1b6878a536abc6756758cbcb934)) - -# [1.1.0-beta.2](https://github.com/Bugs5382/node-hl7-server/compare/v1.1.0-beta.1...v1.1.0-beta.2) (2024-01-08) - -# [1.1.0](https://github.com/Bugs5382/node-hl7-server/compare/v1.0.0...v1.1.0) (2023-12-31) - - - -### Bug Fixes - - -* update node-hl7-client ([fc84d30](https://github.com/Bugs5382/node-hl7-server/commit/fc84d30779a866e15060d5e9a5e8e2807542ff83)) -* default export back in the code ([d125a95](https://github.com/Bugs5382/node-hl7-server/commit/d125a95fa1d393fb6b346b12481cb8f6fe5104f2)) -* default export back in the code ([#29](https://github.com/Bugs5382/node-hl7-server/issues/29)) ([a523596](https://github.com/Bugs5382/node-hl7-server/commit/a5235969e8e44e03941ca64fb979477051f08e25)) -* fixed ci ([0e61e98](https://github.com/Bugs5382/node-hl7-server/commit/0e61e98673f725d437120acc64820fea466b65b7)) -* fixed ci ([#32](https://github.com/Bugs5382/node-hl7-server/issues/32)) ([f052900](https://github.com/Bugs5382/node-hl7-server/commit/f05290049d872541958937515360b71699ec79a6)) -* fixed ci x2 ([a2622ac](https://github.com/Bugs5382/node-hl7-server/commit/a2622ac3a8c858e8bdea51d3400bb53e0bb0a8ec)) -* fixed ci x2 ([#33](https://github.com/Bugs5382/node-hl7-server/issues/33)) ([f35b924](https://github.com/Bugs5382/node-hl7-server/commit/f35b924fc99a5a080b326419d211e7e7932f56a8)) -* fixed name spelling ([f41e69a](https://github.com/Bugs5382/node-hl7-server/commit/f41e69ab00e076373a0ddf61ba68648bbd210e35)) -* fixed name spelling x2 ([20acd10](https://github.com/Bugs5382/node-hl7-server/commit/20acd107fb2cbe04efc4cc65f981a6c9e39e5350)) -* fixed name spelling x2 ([#31](https://github.com/Bugs5382/node-hl7-server/issues/31)) ([18851dc](https://github.com/Bugs5382/node-hl7-server/commit/18851dc2f285bd3b6adc6b1d9435a9fe4e824716)) -* fixed name spelling: Hl7Inbound --> HL7Inbound ([#30](https://github.com/Bugs5382/node-hl7-server/issues/30)) ([16c3dfb](https://github.com/Bugs5382/node-hl7-server/commit/16c3dfba949750533fb235da1ec692aef177fb60)) - - -### Features - -* update node hl7 client ([#35](https://github.com/Bugs5382/node-hl7-server/issues/35)) ([4c385eb](https://github.com/Bugs5382/node-hl7-server/commit/4c385ebf0b59f23c8d224cadbd8591a99b121259)) -* v1.1.0 ([#36](https://github.com/Bugs5382/node-hl7-server/issues/36)) ([9b6e199](https://github.com/Bugs5382/node-hl7-server/commit/9b6e19951e64afa05f36f79134d0c3f883a33a54)) - -# [1.1.0-beta.1](https://github.com/Bugs5382/node-hl7-server/compare/v1.0.1-beta.3...v1.1.0-beta.1) (2023-12-31) - - -### Features - -* update node hl7 client ([#35](https://github.com/Bugs5382/node-hl7-server/issues/35)) ([4c385eb](https://github.com/Bugs5382/node-hl7-server/commit/4c385ebf0b59f23c8d224cadbd8591a99b121259)) - -## [1.0.1-beta.3](https://github.com/Bugs5382/node-hl7-server/compare/v1.0.1-beta.2...v1.0.1-beta.3) (2023-12-29) - - -### Bug Fixes - -* fixed ci ([0e61e98](https://github.com/Bugs5382/node-hl7-server/commit/0e61e98673f725d437120acc64820fea466b65b7)) -* fixed ci ([#32](https://github.com/Bugs5382/node-hl7-server/issues/32)) ([f052900](https://github.com/Bugs5382/node-hl7-server/commit/f05290049d872541958937515360b71699ec79a6)) -* fixed ci x2 ([a2622ac](https://github.com/Bugs5382/node-hl7-server/commit/a2622ac3a8c858e8bdea51d3400bb53e0bb0a8ec)) -* fixed ci x2 ([#33](https://github.com/Bugs5382/node-hl7-server/issues/33)) ([f35b924](https://github.com/Bugs5382/node-hl7-server/commit/f35b924fc99a5a080b326419d211e7e7932f56a8)) -* fixed name spelling x2 ([20acd10](https://github.com/Bugs5382/node-hl7-server/commit/20acd107fb2cbe04efc4cc65f981a6c9e39e5350)) -* fixed name spelling x2 ([#31](https://github.com/Bugs5382/node-hl7-server/issues/31)) ([18851dc](https://github.com/Bugs5382/node-hl7-server/commit/18851dc2f285bd3b6adc6b1d9435a9fe4e824716)) - -## [1.0.1-beta.2](https://github.com/Bugs5382/node-hl7-server/compare/v1.0.1-beta.1...v1.0.1-beta.2) (2023-12-29) - - -### Bug Fixes - -* fixed name spelling ([f41e69a](https://github.com/Bugs5382/node-hl7-server/commit/f41e69ab00e076373a0ddf61ba68648bbd210e35)) -* fixed name spelling: Hl7Inbound --> HL7Inbound ([#30](https://github.com/Bugs5382/node-hl7-server/issues/30)) ([16c3dfb](https://github.com/Bugs5382/node-hl7-server/commit/16c3dfba949750533fb235da1ec692aef177fb60)) - -## [1.0.1-beta.1](https://github.com/Bugs5382/node-hl7-server/compare/v1.0.0...v1.0.1-beta.1) (2023-12-27) - - -### Bug Fixes - -* default export back in the code ([d125a95](https://github.com/Bugs5382/node-hl7-server/commit/d125a95fa1d393fb6b346b12481cb8f6fe5104f2)) -* default export back in the code ([#29](https://github.com/Bugs5382/node-hl7-server/issues/29)) ([a523596](https://github.com/Bugs5382/node-hl7-server/commit/a5235969e8e44e03941ca64fb979477051f08e25)) - -# 1.0.0 (2023-12-25) - - -### Bug Fixes - -* fix node-hl7-client dependency ([253f7c4](https://github.com/Bugs5382/node-hl7-server/commit/253f7c4d2da769c1a8d8c35b4fcdeb686a8cf966)) -* fix node-hl7-client dependency x2 ([653cdc7](https://github.com/Bugs5382/node-hl7-server/commit/653cdc7f79155662d566b9b59c030e222e180ed3)) -* removed temp folder from the npm package ([235876e](https://github.com/Bugs5382/node-hl7-server/commit/235876ed5aead741c0ccefe0a6ebcccb2070b0fb)) -* sendResponse ([7cc8b71](https://github.com/Bugs5382/node-hl7-server/commit/7cc8b714e03c5aef684f73a7e15805af78b68e51)) -* spelling mistake ([728ea5d](https://github.com/Bugs5382/node-hl7-server/commit/728ea5d6d11a73d11e47e2c5bae6f48a6e6e42e1)), closes [#4](https://github.com/Bugs5382/node-hl7-server/issues/4) - - -### Features - -* _server for _socket ([f712a2e](https://github.com/Bugs5382/node-hl7-server/commit/f712a2e2f16ac87391c917324151dcdb3197bba4)) -* add more documentation ([#25](https://github.com/Bugs5382/node-hl7-server/issues/25)) ([fa012fe](https://github.com/Bugs5382/node-hl7-server/commit/fa012fe35e72b11163bbfc808e961f67b674dc5d)) -* added basic unit testing ([99423b6](https://github.com/Bugs5382/node-hl7-server/commit/99423b6b3c4f6df2654ab42b76bc67a9771b9c01)), closes [#4](https://github.com/Bugs5382/node-hl7-server/issues/4) -* added close method ([2a2dc06](https://github.com/Bugs5382/node-hl7-server/commit/2a2dc06017acc06573ae37f9b781cb0c04185225)), closes [#4](https://github.com/Bugs5382/node-hl7-server/issues/4) -* big blob of structure ([3391bb6](https://github.com/Bugs5382/node-hl7-server/commit/3391bb683ead1c2872ab9bdda11c439df483e762)), closes [#1](https://github.com/Bugs5382/node-hl7-server/issues/1) -* bulk of changes ([855ffea](https://github.com/Bugs5382/node-hl7-server/commit/855ffea4ff589305e59acadc15338565200ea9b5)), closes [#4](https://github.com/Bugs5382/node-hl7-server/issues/4) -* emit sends can send raw data back to the server ([558a5d1](https://github.com/Bugs5382/node-hl7-server/commit/558a5d193af188f55d15ab16df25f7d07ebd8c18)) -* first-published version ([221f710](https://github.com/Bugs5382/node-hl7-server/commit/221f7102c3e08de8ad2ac23f24a0213a6942a684)) -* fixed send response ([b9a40e8](https://github.com/Bugs5382/node-hl7-server/commit/b9a40e848da80c4765ccac7cc6687bd7c8e72cef)) -* fixed send response ([f4c8b5e](https://github.com/Bugs5382/node-hl7-server/commit/f4c8b5e1a7e81a9e029cc25fa9d4bc689c21cae7)) -* inbound request parma ([4f9fb63](https://github.com/Bugs5382/node-hl7-server/commit/4f9fb631cdbbf3a23cf4c90f64aa73a65550dbcc)), closes [#20](https://github.com/Bugs5382/node-hl7-server/issues/20) [#21](https://github.com/Bugs5382/node-hl7-server/issues/21) -* initial blob of server class ([c4db6ba](https://github.com/Bugs5382/node-hl7-server/commit/c4db6ba9aacd7f91cda80904f75bb7f1db7d154f)), closes [#1](https://github.com/Bugs5382/node-hl7-server/issues/1) -* lots of updates ([384013f](https://github.com/Bugs5382/node-hl7-server/commit/384013fd9ffc5866b1d308bb4c7163453d5fb035)), closes [#4](https://github.com/Bugs5382/node-hl7-server/issues/4) -* remove utils from test folder ([3cad3bf](https://github.com/Bugs5382/node-hl7-server/commit/3cad3bf18109b473640fa6ee2f37b5dd160905f7)), closes [#4](https://github.com/Bugs5382/node-hl7-server/issues/4) -* removed passing 'this._message' ([60f5798](https://github.com/Bugs5382/node-hl7-server/commit/60f5798704029aec2a2cf47d039b4fa37d3122db)) -* restructure and first client/server tests ([c6436d3](https://github.com/Bugs5382/node-hl7-server/commit/c6436d3832341751e567093708d0da23522cf45f)), closes [#4](https://github.com/Bugs5382/node-hl7-server/issues/4) -* revamp the server system ([0c388a0](https://github.com/Bugs5382/node-hl7-server/commit/0c388a038565b551d89fdd4eee72a9c6a3746010)) -* revamp the server system ([d53ec37](https://github.com/Bugs5382/node-hl7-server/commit/d53ec37519b14647ec77e119c87250618b4954b8)) -* server listens ([27910ce](https://github.com/Bugs5382/node-hl7-server/commit/27910ce494a7bca91cd769236039fa407675ecdd)), closes [#4](https://github.com/Bugs5382/node-hl7-server/issues/4) -* server sends back proper response ([681be32](https://github.com/Bugs5382/node-hl7-server/commit/681be328e0de07fa5d5838877aa30ffed2496c66)), closes [#13](https://github.com/Bugs5382/node-hl7-server/issues/13) -* server working ([f19df18](https://github.com/Bugs5382/node-hl7-server/commit/f19df180c8376d4e5896d9ade3139525f8142400)), closes [#4](https://github.com/Bugs5382/node-hl7-server/issues/4) -* server working x2 ([1ebe15a](https://github.com/Bugs5382/node-hl7-server/commit/1ebe15ac9a1c5f923fd10092328c91183f52926e)), closes [#4](https://github.com/Bugs5382/node-hl7-server/issues/4) -* tls connection working ([bb714c9](https://github.com/Bugs5382/node-hl7-server/commit/bb714c9ae1d8c01a3d846024e668518ac20ecd19)) -* unit test merge issue ([4e20e54](https://github.com/Bugs5382/node-hl7-server/commit/4e20e54eed5282d1fe45af6be0809bf93e9d3b95)) -* updates to the structure ([75e1b7f](https://github.com/Bugs5382/node-hl7-server/commit/75e1b7f84b0403df13a87d64f91730ba304fc097)), closes [#4](https://github.com/Bugs5382/node-hl7-server/issues/4) -* using v1.0.0 of node-hl7-client ([dfdc4c6](https://github.com/Bugs5382/node-hl7-server/commit/dfdc4c6a9541a6f11a057b894a66a58c6d414fcf)) -* v1.0.0 ([#24](https://github.com/Bugs5382/node-hl7-server/issues/24)) ([956f902](https://github.com/Bugs5382/node-hl7-server/commit/956f902741e2c35b66788ce67d5502ac1170c83c)) - - -### Performance Improvements - -* unit tests ([68c8a10](https://github.com/Bugs5382/node-hl7-server/commit/68c8a10b2d23ab377adf5ecaa54e1ea21f33dc8d)) -* unit tests ([0856a07](https://github.com/Bugs5382/node-hl7-server/commit/0856a07d06572f556ee164adef61a5b2fbc40906)) - -# [1.0.0-beta.8](https://github.com/Bugs5382/node-hl7-server/compare/v1.0.0-beta.7...v1.0.0-beta.8) (2023-12-25) - - -### Bug Fixes - -* sendResponse ([7cc8b71](https://github.com/Bugs5382/node-hl7-server/commit/7cc8b714e03c5aef684f73a7e15805af78b68e51)) - - -### Features - -* add more documentation ([#25](https://github.com/Bugs5382/node-hl7-server/issues/25)) ([fa012fe](https://github.com/Bugs5382/node-hl7-server/commit/fa012fe35e72b11163bbfc808e961f67b674dc5d)) -* using v1.0.0 of node-hl7-client ([dfdc4c6](https://github.com/Bugs5382/node-hl7-server/commit/dfdc4c6a9541a6f11a057b894a66a58c6d414fcf)) - - -### Performance Improvements - -* unit tests ([68c8a10](https://github.com/Bugs5382/node-hl7-server/commit/68c8a10b2d23ab377adf5ecaa54e1ea21f33dc8d)) -* unit tests ([0856a07](https://github.com/Bugs5382/node-hl7-server/commit/0856a07d06572f556ee164adef61a5b2fbc40906)) - -# [1.0.0-beta.7](https://github.com/Bugs5382/node-hl7-server/compare/v1.0.0-beta.6...v1.0.0-beta.7) (2023-12-21) - - -### Bug Fixes - -* removed temp folder from the npm package ([235876e](https://github.com/Bugs5382/node-hl7-server/commit/235876ed5aead741c0ccefe0a6ebcccb2070b0fb)) - -# [1.0.0-beta.6](https://github.com/Bugs5382/node-hl7-server/compare/v1.0.0-beta.5...v1.0.0-beta.6) (2023-12-20) - - -### Bug Fixes - -* fix node-hl7-client dependency ([253f7c4](https://github.com/Bugs5382/node-hl7-server/commit/253f7c4d2da769c1a8d8c35b4fcdeb686a8cf966)) -* fix node-hl7-client dependency x2 ([653cdc7](https://github.com/Bugs5382/node-hl7-server/commit/653cdc7f79155662d566b9b59c030e222e180ed3)) - -# [1.0.0-beta.5](https://github.com/Bugs5382/node-hl7-server/compare/v1.0.0-beta.4...v1.0.0-beta.5) (2023-12-20) - - -### Features - -* emit sends can send raw data back to the server ([558a5d1](https://github.com/Bugs5382/node-hl7-server/commit/558a5d193af188f55d15ab16df25f7d07ebd8c18)) -* inbound request parma ([4f9fb63](https://github.com/Bugs5382/node-hl7-server/commit/4f9fb631cdbbf3a23cf4c90f64aa73a65550dbcc)), closes [#20](https://github.com/Bugs5382/node-hl7-server/issues/20) [#21](https://github.com/Bugs5382/node-hl7-server/issues/21) - -# [1.0.0-beta.4](https://github.com/Bugs5382/node-hl7-server/compare/v1.0.0-beta.3...v1.0.0-beta.4) (2023-12-20) - - -### Features - -* fixed send response ([f4c8b5e](https://github.com/Bugs5382/node-hl7-server/commit/f4c8b5e1a7e81a9e029cc25fa9d4bc689c21cae7)) -* removed passing 'this._message' ([60f5798](https://github.com/Bugs5382/node-hl7-server/commit/60f5798704029aec2a2cf47d039b4fa37d3122db)) -* revamp the server system ([d53ec37](https://github.com/Bugs5382/node-hl7-server/commit/d53ec37519b14647ec77e119c87250618b4954b8)) -* unit test merge issue ([4e20e54](https://github.com/Bugs5382/node-hl7-server/commit/4e20e54eed5282d1fe45af6be0809bf93e9d3b95)) - -# [1.0.0-beta.3](https://github.com/Bugs5382/node-hl7-server/compare/v1.0.0-beta.2...v1.0.0-beta.3) (2023-12-20) - - -### Features - -* fixed send response ([b9a40e8](https://github.com/Bugs5382/node-hl7-server/commit/b9a40e848da80c4765ccac7cc6687bd7c8e72cef)) -* revamp the server system ([0c388a0](https://github.com/Bugs5382/node-hl7-server/commit/0c388a038565b551d89fdd4eee72a9c6a3746010)) - -# [1.0.0-beta.2](https://github.com/Bugs5382/node-hl7-server/compare/v1.0.0-beta.1...v1.0.0-beta.2) (2023-12-17) - - -### Features - -* server sends back proper response ([681be32](https://github.com/Bugs5382/node-hl7-server/commit/681be328e0de07fa5d5838877aa30ffed2496c66)), closes [#13](https://github.com/Bugs5382/node-hl7-server/issues/13) - -# 1.0.0-beta.1 (2023-12-16) - - -### Bug Fixes - -* spelling mistake ([728ea5d](https://github.com/Bugs5382/node-hl7-server/commit/728ea5d6d11a73d11e47e2c5bae6f48a6e6e42e1)), closes [#4](https://github.com/Bugs5382/node-hl7-server/issues/4) - - -### Features - -* _server for _socket ([f712a2e](https://github.com/Bugs5382/node-hl7-server/commit/f712a2e2f16ac87391c917324151dcdb3197bba4)) -* added basic unit testing ([99423b6](https://github.com/Bugs5382/node-hl7-server/commit/99423b6b3c4f6df2654ab42b76bc67a9771b9c01)), closes [#4](https://github.com/Bugs5382/node-hl7-server/issues/4) -* added close method ([2a2dc06](https://github.com/Bugs5382/node-hl7-server/commit/2a2dc06017acc06573ae37f9b781cb0c04185225)), closes [#4](https://github.com/Bugs5382/node-hl7-server/issues/4) -* big blob of structure ([3391bb6](https://github.com/Bugs5382/node-hl7-server/commit/3391bb683ead1c2872ab9bdda11c439df483e762)), closes [#1](https://github.com/Bugs5382/node-hl7-server/issues/1) -* bulk of changes ([855ffea](https://github.com/Bugs5382/node-hl7-server/commit/855ffea4ff589305e59acadc15338565200ea9b5)), closes [#4](https://github.com/Bugs5382/node-hl7-server/issues/4) -* first-published version ([221f710](https://github.com/Bugs5382/node-hl7-server/commit/221f7102c3e08de8ad2ac23f24a0213a6942a684)) -* initial blob of server class ([c4db6ba](https://github.com/Bugs5382/node-hl7-server/commit/c4db6ba9aacd7f91cda80904f75bb7f1db7d154f)), closes [#1](https://github.com/Bugs5382/node-hl7-server/issues/1) -* lots of updates ([384013f](https://github.com/Bugs5382/node-hl7-server/commit/384013fd9ffc5866b1d308bb4c7163453d5fb035)), closes [#4](https://github.com/Bugs5382/node-hl7-server/issues/4) -* remove utils from test folder ([3cad3bf](https://github.com/Bugs5382/node-hl7-server/commit/3cad3bf18109b473640fa6ee2f37b5dd160905f7)), closes [#4](https://github.com/Bugs5382/node-hl7-server/issues/4) -* restructure and first client/server tests ([c6436d3](https://github.com/Bugs5382/node-hl7-server/commit/c6436d3832341751e567093708d0da23522cf45f)), closes [#4](https://github.com/Bugs5382/node-hl7-server/issues/4) -* server listens ([27910ce](https://github.com/Bugs5382/node-hl7-server/commit/27910ce494a7bca91cd769236039fa407675ecdd)), closes [#4](https://github.com/Bugs5382/node-hl7-server/issues/4) -* server working ([f19df18](https://github.com/Bugs5382/node-hl7-server/commit/f19df180c8376d4e5896d9ade3139525f8142400)), closes [#4](https://github.com/Bugs5382/node-hl7-server/issues/4) -* server working x2 ([1ebe15a](https://github.com/Bugs5382/node-hl7-server/commit/1ebe15ac9a1c5f923fd10092328c91183f52926e)), closes [#4](https://github.com/Bugs5382/node-hl7-server/issues/4) -* tls connection working ([bb714c9](https://github.com/Bugs5382/node-hl7-server/commit/bb714c9ae1d8c01a3d846024e668518ac20ecd19)) -* updates to the structure ([75e1b7f](https://github.com/Bugs5382/node-hl7-server/commit/75e1b7f84b0403df13a87d64f91730ba304fc097)), closes [#4](https://github.com/Bugs5382/node-hl7-server/issues/4) +# Node HL7 Server \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 30666d7..b4748ce 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,9 +1,9 @@ FROM node:20.11.0-alpine3.19 -# set working directory in the image +# Set working directory in the image WORKDIR /home/node/app -## copy files over +## Copy files over COPY docker/package.json . COPY docker/server.js . COPY docker/tls.server.js . @@ -13,5 +13,5 @@ COPY certs certs RUN npm install RUN npm i node-hl7-server -# EXPOSE -EXPOSE 3000 \ No newline at end of file +## Expose +EXPOSE 3000 diff --git a/__tests__/__utils__/index.ts b/__tests__/__utils__/index.ts index f0a5c12..6c5fc15 100644 --- a/__tests__/__utils__/index.ts +++ b/__tests__/__utils__/index.ts @@ -1,35 +1,40 @@ -import EventEmitter from 'node:events' +import EventEmitter from "node:events"; /** @internal */ export const sleep = async (ms: number): Promise => { - return await new Promise(resolve => setTimeout(resolve, ms)) -} + return await new Promise((resolve) => setTimeout(resolve, ms)); +}; /** @internal */ -export const expectEvent = async (emitter: EventEmitter, name: string | symbol): Promise => { - return await new Promise((resolve) => { emitter.once(name, resolve) }) -} +export const expectEvent = async ( + emitter: EventEmitter, + name: string | symbol, +): Promise => { + return await new Promise((resolve) => { + emitter.once(name, resolve); + }); +}; /** @internal */ -export interface Deferred { - resolve: (value: T | PromiseLike) => void - reject: (reason?: any) => void - promise: Promise +export interface Deferred { + resolve: (value: T | PromiseLike) => void; + reject: (reason?: any) => void; + promise: Promise; } /** @internal */ -export const createDeferred = (noUncaught?: boolean): Deferred => { - const dfd: any = {} +export const createDeferred = (noUncaught?: boolean): Deferred => { + const dfd: any = {}; dfd.promise = new Promise((resolve, reject) => { - dfd.resolve = resolve - dfd.reject = reject - }) + dfd.resolve = resolve; + dfd.reject = reject; + }); /* istanbul ignore next */ if (noUncaught === false) { - dfd.promise.catch(() => {}) + dfd.promise.catch(() => {}); } - return dfd -} + return dfd; +}; /** @internal */ export const generateLargeBase64String = (sizeInKb: number = 200) => { diff --git a/__tests__/hl7.end2end.test.ts b/__tests__/hl7.end2end.test.ts index 00d8464..7ca47de 100644 --- a/__tests__/hl7.end2end.test.ts +++ b/__tests__/hl7.end2end.test.ts @@ -1,416 +1,412 @@ import fs from "fs"; import path from "node:path"; -import { describe, expect, test } from 'vitest'; -import tcpPortUsed from 'tcp-port-used' -import Client, {Batch, Message} from "node-hl7-client"; -import {createDeferred, expectEvent, generateLargeBase64String} from './__utils__' +import { describe, expect, test } from "vitest"; +import tcpPortUsed from "tcp-port-used"; +import Client, { Batch, Message } from "node-hl7-client"; +import { + createDeferred, + expectEvent, + generateLargeBase64String, +} from "./__utils__"; import Server from "../src"; -describe('node hl7 end to end - client', () => { +const port = Number(process.env.TEST_PORT) || 3000; - describe('server/client sanity checks', () => { - - test('...simple connect .. send AA', async () => { - - let dfd = createDeferred() +describe("node hl7 end to end - client", () => { + describe("server/client sanity checks", () => { + test("...simple connect .. send AA", async () => { + let dfd = createDeferred(); - const server = new Server({bindAddress: '0.0.0.0'}) - const listener = server.createInbound({port: 3000}, async (req, res) => { - const messageReq = req.getMessage() - expect(messageReq.get('MSH.12').toString()).toBe('2.7') - await res.sendResponse('AA') - const messageRes = res.getAckMessage() - expect(messageRes?.get('MSA.1').toString()).toBe('AA') - }) + const server = new Server({ bindAddress: "0.0.0.0" }); + const listener = server.createInbound({ port }, async (req, res) => { + const messageReq = req.getMessage(); + expect(messageReq.get("MSH.12").toString()).toBe("2.7"); + await res.sendResponse("AA"); + const messageRes = res.getAckMessage(); + expect(messageRes?.get("MSA.1").toString()).toBe("AA"); + }); - await expectEvent(listener, 'listen') + await expectEvent(listener, "listen"); - const client = new Client({ host: '0.0.0.0' }) + const client = new Client({ host: "0.0.0.0" }); - const outbound = client.createConnection({ port: 3000 }, async (res) => { - const messageRes = res.getMessage() - expect(messageRes.get('MSA.1').toString()).toBe('AA') - dfd.resolve() - }) + const outbound = client.createConnection({ port }, async (res) => { + const messageRes = res.getMessage(); + expect(messageRes.get("MSA.1").toString()).toBe("AA"); + dfd.resolve(); + }); - await expectEvent(outbound, 'connect') + await expectEvent(outbound, "connect"); let message = new Message({ messageHeader: { - msh_9_1: 'ADT', - msh_9_2: 'A01', - msh_10: 'CONTROL_ID', - msh_11_1: 'D' - } - }) - - await outbound.sendMessage(message) - - await dfd.promise + msh_9_1: "ADT", + msh_9_2: "A01", + msh_10: "CONTROL_ID", + msh_11_1: "D", + }, + }); - expect(client.totalSent()).toEqual(1) - expect(client.totalAck()).toEqual(1) + await outbound.sendMessage(message); - await outbound.close() - await listener.close() + await dfd.promise; - client.closeAll() + expect(client.totalSent()).toEqual(1); + expect(client.totalAck()).toEqual(1); - }) + await outbound.close(); + await listener.close(); - test('...simple connect .. send AR', async () => { + client.closeAll(); + }); - let dfd = createDeferred() + test("...simple connect .. send AR", async () => { + let dfd = createDeferred(); - const server = new Server({bindAddress: '0.0.0.0'}) - const listener = server.createInbound({port: 3000}, async (req, res) => { - const messageReq = req.getMessage() - expect(messageReq.get('MSH.12').toString()).toBe('2.7') - await res.sendResponse('AR') - const messageRes = res.getAckMessage() - expect(messageRes?.get('MSA.1').toString()).toBe('AR') - }) + const server = new Server({ bindAddress: "0.0.0.0" }); + const listener = server.createInbound({ port }, async (req, res) => { + const messageReq = req.getMessage(); + expect(messageReq.get("MSH.12").toString()).toBe("2.7"); + await res.sendResponse("AR"); + const messageRes = res.getAckMessage(); + expect(messageRes?.get("MSA.1").toString()).toBe("AR"); + }); - await expectEvent(listener, 'listen') + await expectEvent(listener, "listen"); - const client = new Client({ host: '0.0.0.0' }) + const client = new Client({ host: "0.0.0.0" }); - const outbound = client.createConnection({ port: 3000 }, async (res) => { - const messageRes = res.getMessage() - expect(messageRes.get('MSA.1').toString()).toBe('AR') - dfd.resolve() - }) + const outbound = client.createConnection({ port }, async (res) => { + const messageRes = res.getMessage(); + expect(messageRes.get("MSA.1").toString()).toBe("AR"); + dfd.resolve(); + }); - await expectEvent(outbound, 'connect') + await expectEvent(outbound, "connect"); let message = new Message({ messageHeader: { - msh_9_1: 'ADT', - msh_9_2: 'A01', - msh_10: 'CONTROL_ID', - msh_11_1: 'D' - } - }) - - await outbound.sendMessage(message) - - await dfd.promise + msh_9_1: "ADT", + msh_9_2: "A01", + msh_10: "CONTROL_ID", + msh_11_1: "D", + }, + }); - expect(client.totalSent()).toEqual(1) - expect(client.totalAck()).toEqual(1) + await outbound.sendMessage(message); - await outbound.close() - await listener.close() + await dfd.promise; - client.closeAll() + expect(client.totalSent()).toEqual(1); + expect(client.totalAck()).toEqual(1); - }) + await outbound.close(); + await listener.close(); - test('...simple connect .. send AE', async () => { + client.closeAll(); + }); - let dfd = createDeferred() + test("...simple connect .. send AE", async () => { + let dfd = createDeferred(); - const server = new Server({bindAddress: '0.0.0.0'}) - const listener = server.createInbound({port: 3000}, async (req, res) => { - const messageReq = req.getMessage() - expect(messageReq.get('MSH.12').toString()).toBe('2.7') - await res.sendResponse('AE') - const messageRes = res.getAckMessage() - expect(messageRes?.get('MSA.1').toString()).toBe('AE') - }) + const server = new Server({ bindAddress: "0.0.0.0" }); + const listener = server.createInbound({ port }, async (req, res) => { + const messageReq = req.getMessage(); + expect(messageReq.get("MSH.12").toString()).toBe("2.7"); + await res.sendResponse("AE"); + const messageRes = res.getAckMessage(); + expect(messageRes?.get("MSA.1").toString()).toBe("AE"); + }); - await expectEvent(listener, 'listen') + await expectEvent(listener, "listen"); - const client = new Client({ host: '0.0.0.0' }) + const client = new Client({ host: "0.0.0.0" }); - const outbound = client.createConnection({ port: 3000 }, async (res) => { - const messageRes = res.getMessage() - expect(messageRes.get('MSA.1').toString()).toBe('AE') - dfd.resolve() - }) + const outbound = client.createConnection({ port }, async (res) => { + const messageRes = res.getMessage(); + expect(messageRes.get("MSA.1").toString()).toBe("AE"); + dfd.resolve(); + }); - await expectEvent(outbound, 'connect') + await expectEvent(outbound, "connect"); let message = new Message({ messageHeader: { - msh_9_1: 'ADT', - msh_9_2: 'A01', - msh_10: 'CONTROL_ID', - msh_11_1: 'D' - } - }) - - await outbound.sendMessage(message) - - await dfd.promise + msh_9_1: "ADT", + msh_9_2: "A01", + msh_10: "CONTROL_ID", + msh_11_1: "D", + }, + }); - expect(client.totalSent()).toEqual(1) - expect(client.totalAck()).toEqual(1) + await outbound.sendMessage(message); - await outbound.close() - await listener.close() + await dfd.promise; - client.closeAll() + expect(client.totalSent()).toEqual(1); + expect(client.totalAck()).toEqual(1); - }) + await outbound.close(); + await listener.close(); - test('...simple connect ... MSH overrides', async () => { + client.closeAll(); + }); - let dfd = createDeferred() + test("...simple connect ... MSH overrides", async () => { + let dfd = createDeferred(); - const server = new Server({bindAddress: '0.0.0.0'}) + const server = new Server({ bindAddress: "0.0.0.0" }); // override MSH field 9.3 to "ACK" and field 18 to "UNICODE UTF-8" - const listener = server.createInbound({port: 3000, mshOverrides: { '9.3': 'ACK', '18': 'UNICODE UTF-8' } }, async (req, res) => { - const messageReq = req.getMessage() - expect(messageReq.get('MSH.12').toString()).toBe('2.7') - await res.sendResponse('AA') - const messageRes = res.getAckMessage() - expect(messageRes?.get('MSA.1').toString()).toBe('AA') - expect(messageRes?.get('MSH.9.3').toString()).toBe('ACK') - expect(messageRes?.get('MSH.18').toString()).toBe('UNICODE UTF-8') - }) + const listener = server.createInbound( + { port, mshOverrides: { "9.3": "ACK", "18": "UNICODE UTF-8" } }, + async (req, res) => { + const messageReq = req.getMessage(); + expect(messageReq.get("MSH.12").toString()).toBe("2.7"); + await res.sendResponse("AA"); + const messageRes = res.getAckMessage(); + expect(messageRes?.get("MSA.1").toString()).toBe("AA"); + expect(messageRes?.get("MSH.9.3").toString()).toBe("ACK"); + expect(messageRes?.get("MSH.18").toString()).toBe("UNICODE UTF-8"); + }, + ); - await expectEvent(listener, 'listen') + await expectEvent(listener, "listen"); - const client = new Client({ host: '0.0.0.0' }) + const client = new Client({ host: "0.0.0.0" }); - const outbound = client.createConnection({ port: 3000 }, async (res) => { - const messageRes = res.getMessage() - expect(messageRes.get('MSA.1').toString()).toBe('AA') - dfd.resolve() - }) + const outbound = client.createConnection({ port }, async (res) => { + const messageRes = res.getMessage(); + expect(messageRes.get("MSA.1").toString()).toBe("AA"); + dfd.resolve(); + }); - await expectEvent(outbound, 'connect') + await expectEvent(outbound, "connect"); let message = new Message({ messageHeader: { - msh_9_1: 'ADT', - msh_9_2: 'A01', - msh_10: 'CONTROL_ID', - msh_11_1: 'D' - } - }) - - await outbound.sendMessage(message) - - await dfd.promise + msh_9_1: "ADT", + msh_9_2: "A01", + msh_10: "CONTROL_ID", + msh_11_1: "D", + }, + }); - expect(client.totalSent()).toEqual(1) - expect(client.totalAck()).toEqual(1) + await outbound.sendMessage(message); - await outbound.close() - await listener.close() + await dfd.promise; - client.closeAll() + expect(client.totalSent()).toEqual(1); + expect(client.totalAck()).toEqual(1); - }) + await outbound.close(); + await listener.close(); - test('...send simple message twice, no ACK needed', async () => { + client.closeAll(); + }); - await tcpPortUsed.check(3000, '0.0.0.0') + test("...send simple message twice, no ACK needed before sending the next message", async () => { + await tcpPortUsed.check(3000, "0.0.0.0"); - let dfd = createDeferred() + let dfd = createDeferred(); - const server = new Server({bindAddress: '0.0.0.0'}) - const listener = server.createInbound({port: 3000}, async (req, res) => { - const messageReq = req.getMessage() - expect(messageReq.get('MSH.12').toString()).toBe('2.7') - await res.sendResponse('AA') - const messageRes = res.getAckMessage() - expect(messageRes?.get('MSA.1').toString()).toBe('AA') - }) + const server = new Server({ bindAddress: "0.0.0.0" }); + const listener = server.createInbound({ port }, async (req, res) => { + const messageReq = req.getMessage(); + expect(messageReq.get("MSH.12").toString()).toBe("2.7"); + await res.sendResponse("AA"); + const messageRes = res.getAckMessage(); + expect(messageRes?.get("MSA.1").toString()).toBe("AA"); + }); - await expectEvent(listener, 'listen') + await expectEvent(listener, "listen"); - const client = new Client({ host: '0.0.0.0' }) - const outbound = client.createConnection({ port: 3000, waitAck: false }, async () => { - dfd.resolve() - }) + const client = new Client({ host: "0.0.0.0" }); + const outbound = client.createConnection( + { port, waitAck: false }, + async () => { + dfd.resolve(); + }, + ); - await expectEvent(outbound, 'connect') + await expectEvent(outbound, "connect"); let message = new Message({ messageHeader: { - msh_9_1: 'ADT', - msh_9_2: 'A01', - msh_10: 'CONTROL_ID', - msh_11_1: 'D' - } - }) - - await outbound.sendMessage(message) - - await dfd.promise - - expect(client.totalSent()).toEqual(1) - expect(client.totalAck()).toEqual(1) - - await outbound.close() - await listener.close() - - client.closeAll() - - }) + msh_9_1: "ADT", + msh_9_2: "A01", + msh_10: "CONTROL_ID", + msh_11_1: "D", + }, + }); - }) + await outbound.sendMessage(message); - describe('server/client failure checks', () => { + let message2 = new Message({ + messageHeader: { + msh_9_1: "ADT", + msh_9_2: "A01", + msh_10: "CONTROL_ID_01", + msh_11_1: "D", + }, + }); - test('...host does not exist, error out', async () => { + await outbound.sendMessage(message2); - const client = new Client({ host: '0.0.0.0' }) - const outbound = client.createConnection({ port: 1234, maxConnectionAttempts: 1 }, async () => {}) + await dfd.promise; - const error = await expectEvent(outbound, 'client.error') - expect(error.code).toBe('ECONNREFUSED') - }) + expect(client.totalSent()).toEqual(2); + expect(client.totalAck()).toEqual(2); - }) + await outbound.close(); + await listener.close(); - describe('...no tls', () => { + client.closeAll(); + }); + }); - describe('...no file', () => { + describe("server/client failure checks", () => { + test.skip("...host does not exist, error out", async () => { + const client = new Client({ host: "0.0.0.0" }); + const outbound = client.createConnection( + { port: 1234, maxConnectionAttempts: 1 }, + async () => {}, + ); - test('...send batch with two message, get proper ACK', async () => { + const error = await expectEvent(outbound, "client.error"); + expect(error.code).toBe("ECONNREFUSED"); + }); + }); - let dfd = createDeferred() + describe("...no tls", () => { + describe("...no file", () => { + test("...send batch with two message, get proper ACK", async () => { + let dfd = createDeferred(); - const server = new Server({ bindAddress: '0.0.0.0' }) - const inbound = server.createInbound({ port: 3000 }, async (req, res) => { - const messageReq = req.getMessage() - expect(messageReq.get('MSH.12').toString()).toBe('2.7') - await res.sendResponse('AA') - const messageRes = res.getAckMessage() - expect(messageRes?.get('MSA.1').toString()).toBe('AA') - }) + const server = new Server({ bindAddress: "0.0.0.0" }); + const inbound = server.createInbound({ port }, async (req, res) => { + const messageReq = req.getMessage(); + expect(messageReq.get("MSH.12").toString()).toBe("2.7"); + await res.sendResponse("AA"); + const messageRes = res.getAckMessage(); + expect(messageRes?.get("MSA.1").toString()).toBe("AA"); + }); - await expectEvent(inbound, 'listen') + await expectEvent(inbound, "listen"); - const client = new Client({ host: '0.0.0.0' }) - const outbound = client.createConnection({ port: 3000 }, async (res) => { - const messageRes = res.getMessage() - expect(messageRes.get('MSA.1').toString()).toBe('AA') - dfd.resolve() - }) + const client = new Client({ host: "0.0.0.0" }); + const outbound = client.createConnection({ port }, async (res) => { + const messageRes = res.getMessage(); + expect(messageRes.get("MSA.1").toString()).toBe("AA"); + dfd.resolve(); + }); - const batch = new Batch() - batch.start() + const batch = new Batch(); + batch.start(); const message = new Message({ messageHeader: { - msh_9_1: 'ADT', - msh_9_2: 'A01', - msh_10: 'CONTROL_ID', - msh_11_1: 'D' - } - }) - - batch.add(message) - batch.add(message) - - batch.end() - - await outbound.sendMessage(batch) + msh_9_1: "ADT", + msh_9_2: "A01", + msh_10: "CONTROL_ID", + msh_11_1: "D", + }, + }); - await dfd.promise + batch.add(message); + batch.add(message); - expect(client.totalSent()).toEqual(1) - expect(client.totalAck()).toEqual(1) + batch.end(); - await outbound.close() - await inbound.close() + await outbound.sendMessage(batch); - client.closeAll() - }) + await dfd.promise; - }) + expect(client.totalSent()).toEqual(1); + expect(client.totalAck()).toEqual(2); - }) + await outbound.close(); + await inbound.close(); - describe('...tls', () => { - - describe('...no file', () => { - - test('...simple', async () => { - - let dfd = createDeferred() - - const server = new Server( - { - bindAddress: '0.0.0.0', - tls: - { - key: fs.readFileSync(path.join('certs/', 'server-key.pem')), - cert: fs.readFileSync(path.join('certs/', 'server-crt.pem')), - rejectUnauthorized: false - } - }) - const inbound = server.createInbound({ port: 3000 }, async (req, res) => { - const messageReq = req.getMessage() - expect(messageReq.get('MSH.12').toString()).toBe('2.7') - await res.sendResponse('AA') - const messageRes = res.getAckMessage() - expect(messageRes?.get('MSA.1').toString()).toBe('AA') - }) - - await expectEvent(inbound, 'listen') - - const client = new Client({ host: '0.0.0.0', tls: { rejectUnauthorized: false } }) - const outbound = client.createConnection({ port: 3000 }, async (res) => { - const messageRes = res.getMessage() - expect(messageRes.get('MSA.1').toString()).toBe('AA') - dfd.resolve() - }) + client.closeAll(); + }); + }); + }); - await expectEvent(outbound, 'connect') + describe("...tls", () => { + describe("...no file", () => { + test("...simple", async () => { + let dfd = createDeferred(); + + const server = new Server({ + bindAddress: "0.0.0.0", + tls: { + key: fs.readFileSync(path.join("certs/", "server-key.pem")), + cert: fs.readFileSync(path.join("certs/", "server-crt.pem")), + rejectUnauthorized: false, + }, + }); + const inbound = server.createInbound({ port }, async (req, res) => { + const messageReq = req.getMessage(); + expect(messageReq.get("MSH.12").toString()).toBe("2.7"); + await res.sendResponse("AA"); + const messageRes = res.getAckMessage(); + expect(messageRes?.get("MSA.1").toString()).toBe("AA"); + }); + + await expectEvent(inbound, "listen"); + + const client = new Client({ + host: "0.0.0.0", + tls: { rejectUnauthorized: false }, + }); + const outbound = client.createConnection({ port }, async (res) => { + const messageRes = res.getMessage(); + expect(messageRes.get("MSA.1").toString()).toBe("AA"); + dfd.resolve(); + }); + + await expectEvent(outbound, "connect"); const message = new Message({ messageHeader: { - msh_9_1: 'ADT', - msh_9_2: 'A01', - msh_10: 'CONTROL_ID', - msh_11_1: 'D' - } - }) - - await outbound.sendMessage(message) + msh_9_1: "ADT", + msh_9_2: "A01", + msh_10: "CONTROL_ID", + msh_11_1: "D", + }, + }); - dfd.promise + await outbound.sendMessage(message); - await outbound.close() - await inbound.close() + dfd.promise; - client.closeAll() + await outbound.close(); + await inbound.close(); - }) - - }) - - }) + client.closeAll(); + }); + }); + }); describe("server/client large data checks", () => { - test("...large encapsulated data", async () => { let dfd = createDeferred(); const server = new Server({ bindAddress: "0.0.0.0" }); - const listener = server.createInbound( - { port: 3000 }, - async (req, res) => { - const messageReq = req.getMessage(); - expect(messageReq.get("MSH.12").toString()).toBe("2.7"); - expect(messageReq.get("OBX.3.1").toString()).toBe("SOME-PDF"); - await res.sendResponse("AA"); - const messageRes = res.getAckMessage(); - expect(messageRes?.get("MSA.1").toString()).toBe("AA"); - } - ); + const listener = server.createInbound({ port }, async (req, res) => { + const messageReq = req.getMessage(); + expect(messageReq.get("MSH.12").toString()).toBe("2.7"); + expect(messageReq.get("OBX.3.1").toString()).toBe("SOME-PDF"); + await res.sendResponse("AA"); + const messageRes = res.getAckMessage(); + expect(messageRes?.get("MSA.1").toString()).toBe("AA"); + }); await expectEvent(listener, "listen"); const client = new Client({ host: "0.0.0.0" }); - const outbound = client.createConnection({ port: 3000 }, async (res) => { + const outbound = client.createConnection({ port }, async (res) => { const messageRes = res.getMessage(); expect(messageRes.get("MSA.1").toString()).toBe("AA"); dfd.resolve(); @@ -437,7 +433,7 @@ describe('node hl7 end to end - client', () => { OBX.set("5.2", "application"); // Type of referenced data OBX.set("5.3", "pdf"); // Data Sub type OBX.set("5.4", "Base64"); // PDF Data - OBX.set("5.5", generateLargeBase64String(300)); // PDF Data + OBX.set("5.5", generateLargeBase64String(600)); // PDF Data OBX.set("8", "A"); // (A)bnormal or (N)ormal result OBX.set("11", "F"); // Final result or correction to final result OBX.set("14", "20240625103600"); // Result creation time @@ -454,6 +450,5 @@ describe('node hl7 end to end - client', () => { client.closeAll(); }); - }); }); diff --git a/__tests__/hl7.server.test.ts b/__tests__/hl7.server.test.ts index 40ed728..d8f0395 100644 --- a/__tests__/hl7.server.test.ts +++ b/__tests__/hl7.server.test.ts @@ -1,148 +1,163 @@ -import { describe, expect, test } from 'vitest'; -import {HL7ListenerError, InboundRequest, Server} from '../src' +import { describe, expect, test } from "vitest"; +import { HL7ListenerError, InboundRequest, Server } from "../src"; -describe('node hl7 server', () => { - - describe('sanity tests - modules', () => { - test('InboundRequest - message undefined', async () => { +describe("node hl7 server", () => { + describe("sanity tests - modules", () => { + test("InboundRequest - message undefined", async () => { // @ts-expect-error - const empty = new InboundRequest(undefined, { type: 'file' }) + const empty = new InboundRequest(undefined, { type: "file" }); try { - empty.getMessage() + empty.getMessage(); } catch (e) { - expect(e).toStrictEqual(new HL7ListenerError('Message is not defined.')) + expect(e).toStrictEqual( + new HL7ListenerError("Message is not defined."), + ); } - }) + }); - test('InboundRequest - type check', async () => { + test("InboundRequest - type check", async () => { // @ts-expect-error - const req = new InboundRequest('', { type: 'file' }) - expect(req.getType()).toBe('file') - }) - - }) + const req = new InboundRequest("", { type: "file" }); + expect(req.getType()).toBe("file"); + }); + }); - describe('sanity tests - server class', () => { - test('error - bindAddress has to be string', async () => { + describe("sanity tests - server class", () => { + test("error - bindAddress has to be string", async () => { try { // @ts-expect-error this is not a string - new Server({ bindAddress: 351123 }) + new Server({ bindAddress: 351123 }); } catch (err: any) { - expect(err.message).toBe('bindAddress is not valid string.') + expect(err.message).toBe("bindAddress is not valid string."); } - }) + }); - test('error - ipv4 and ipv6 both can not be true exist', async () => { + test("error - ipv4 and ipv6 both can not be true exist", async () => { try { - new Server({ ipv6: true, ipv4: true }) + new Server({ ipv6: true, ipv4: true }); } catch (err: any) { - expect(err.message).toBe('ipv4 and ipv6 both can\'t be set to be exclusive.') + expect(err.message).toBe( + "ipv4 and ipv6 both can't be set to be exclusive.", + ); } - }) + }); - test('error - ipv4 not empty', async () => { + test("error - ipv4 not empty", async () => { try { - new Server({ bindAddress: '' }) + new Server({ bindAddress: "" }); } catch (err: any) { - expect(err.message).toBe('bindAddress is an invalid ipv4 address.') + expect(err.message).toBe("bindAddress is an invalid ipv4 address."); } - }) + }); - test('error - ipv4 not valid address', async () => { + test("error - ipv4 not valid address", async () => { try { - new Server({ bindAddress: '123.34.52.455' }) + new Server({ bindAddress: "123.34.52.455" }); } catch (err: any) { - expect(err.message).toBe('bindAddress is an invalid ipv4 address.') + expect(err.message).toBe("bindAddress is an invalid ipv4 address."); } - }) + }); - test('error - ipv6 not empty', async () => { + test("error - ipv6 not empty", async () => { try { - new Server({ bindAddress: '', ipv6: true, ipv4: false }) + new Server({ bindAddress: "", ipv6: true, ipv4: false }); } catch (err: any) { - expect(err.message).toBe('bindAddress is an invalid ipv6 address.') + expect(err.message).toBe("bindAddress is an invalid ipv6 address."); } - }) + }); - test('error - ipv6 not valid address', async () => { + test("error - ipv6 not valid address", async () => { try { - new Server({ bindAddress: '2001:0db8:85a3:0000:zz00:8a2e:0370:7334', ipv6: true, ipv4: false }) + new Server({ + bindAddress: "2001:0db8:85a3:0000:zz00:8a2e:0370:7334", + ipv6: true, + ipv4: false, + }); } catch (err: any) { - expect(err.message).toBe('bindAddress is an invalid ipv6 address.') + expect(err.message).toBe("bindAddress is an invalid ipv6 address."); } - }) + }); - test('error - ipv6 valid address', async () => { + test("error - ipv6 valid address", async () => { try { - new Server({ bindAddress: '2001:0db8:85a3:0000:0000:8a2e:0370:7334', ipv6: true, ipv4: false }) + new Server({ + bindAddress: "2001:0db8:85a3:0000:0000:8a2e:0370:7334", + ipv6: true, + ipv4: false, + }); } catch (err: any) { - expect(err.message).toBeUndefined() + expect(err.message).toBeUndefined(); } - }) + }); - test('properties exist', async () => { - const server = new Server() - expect(server).toHaveProperty('createInbound') - }) - }) + test("properties exist", async () => { + const server = new Server(); + expect(server).toHaveProperty("createInbound"); + }); + }); - describe('sanity tests - listener class', () => { - test('error - no port specified', async () => { + describe("sanity tests - listener class", () => { + test("error - no port specified", async () => { try { - const server = new Server() + const server = new Server(); // @ts-expect-error port is not specified - server.createInbound() + server.createInbound(); } catch (err: any) { - expect(err.message).toBe('port is not defined.') + expect(err.message).toBe("port is not defined."); } - }) + }); - test('error - port not a number', async () => { + test("error - port not a number", async () => { try { - const server = new Server() + const server = new Server(); // @ts-expect-error port is not specified - server.createInbound({ port: '12345' }, async () => {}) + server.createInbound({ port: "12345" }, async () => {}); } catch (err: any) { - expect(err.message).toBe('port is not valid number.') + expect(err.message).toBe("port is not valid number."); } - }) + }); - test('error - port less than 0', async () => { + test("error - port less than 0", async () => { try { - const server = new Server() - server.createInbound({ port: -1 }, async () => {}) + const server = new Server(); + server.createInbound({ port: -1 }, async () => {}); } catch (err: any) { - expect(err.message).toBe('port must be a number (0, 65353).') + expect(err.message).toBe("port must be a number (0, 65353)."); } - }) + }); - test('error - port greater than 65353', async () => { + test("error - port greater than 65353", async () => { try { - const server = new Server() - server.createInbound({ port: 65354 }, async () => {}) + const server = new Server(); + server.createInbound({ port: 65354 }, async () => {}); } catch (err: any) { - expect(err.message).toBe('port must be a number (0, 65353).') + expect(err.message).toBe("port must be a number (0, 65353)."); } - }) + }); - test('error - name is invalid', async () => { + test("error - name is invalid", async () => { try { - const server = new Server() - server.createInbound({ name: '$#@!sdfe-`', port: 65354 }, async () => {}) + const server = new Server(); + server.createInbound( + { name: "$#@!sdfe-`", port: 65354 }, + async () => {}, + ); } catch (err: any) { - expect(err.message).toContain('name must not contain certain characters: `!@#$%^&*()+\\-=\\[\\]{};\':\"\\\\|,.<>\\/?~.') + expect(err.message).toContain( + "name must not contain certain characters: `!@#$%^&*()+\\-=\\[\\]{};':\"\\\\|,.<>\\/?~.", + ); } - }) + }); - test('error - getMessage() - no message passed to inbound request', async () => { + test("error - getMessage() - no message passed to inbound request", async () => { try { // @ts-expect-error no message. - const inboundReq = new InboundRequest('', { type: 'message' }) + const inboundReq = new InboundRequest("", { type: "message" }); // this should cause an error - inboundReq.getMessage() + inboundReq.getMessage(); } catch (err: any) { - expect(err.message).toBe('Message is not defined.') + expect(err.message).toBe("Message is not defined."); } - }) - }) -}) + }); + }); +}); diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 0000000..29fdecd --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,24 @@ +import pluginJs from "@eslint/js"; +import tseslint from "typescript-eslint"; +import pluginPrettier from 'eslint-plugin-prettier'; + +export default [ + pluginJs.configs.recommended, + ...tseslint.configs.recommended, + { + files: ["**/*.{js,mjs,cjs,ts}"], + plugins: { + 'prettier': pluginPrettier + } + }, + { + rules: { + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/no-unused-vars': 'off', + '@typescript-eslint/no-unsafe-declaration-merging': 'off' + } + }, + { + ignores: [".node_modules/*", "docs/*", "lib/*", "__tests__/*", "docker/*"] + } +]; diff --git a/package.json b/package.json index 35c470a..5e1bdc5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "node-hl7-server", - "version": "3.0.0", + "version": "3.0.1-beta.1", "description": "Node.js client library for creating a HL7 Server which can accept incoming a properly formatted HL7 message(s), and then parses the HL7 message. Once the message has been parsed you can then do something with the final result that you so desire.", "module": "./lib/esm/index.js", "main": "./lib/cjs/index.js", @@ -14,7 +14,9 @@ } }, "files": [ - "lib/" + "lib/", + "README.md", + "LICENSE" ], "engines": { "node": ">=20.15.0" @@ -25,8 +27,9 @@ "build:watch": "tsc -p src/tsconfig.esm.json -w", "docker:build": "docker build -t docker-node-hl7-server:latest .", "npm:lint": "npmPkgJsonLint .", - "lint": "npm run npm:lint && ts-standard -p src/tsconfig.esm.json | snazzy", - "lint:fix": "npm run npm:lint . && ts-standard -p src/tsconfig.esm.json --fix | snazzy", + "format": "prettier --write 'src/**/*.ts' '__tests__/**/*.ts'", + "lint": "npm run npm:lint && eslint | snazzy", + "lint:fix": "npm run npm:lint && eslint --fix | snazzy", "pack": "npm pack", "prepublishOnly": "npm run clean && npm run build && npm run pack", "test": "vitest run", @@ -35,8 +38,6 @@ "test:coverage": "vitest --coverage", "typedoc": "typedoc", "typedoc:watch": "typedoc -watch", - "semantic-release": "semantic-release", - "semantic-release:dry-run": "semantic-release --dry-run", "update": "npx npm-check-updates -u --enginesNode && npm run update:post-update", "update:post-update": "npm install && npm run test" }, @@ -60,31 +61,34 @@ }, "homepage": "https://github.com/Bugs5382/node-hl7-server#readme", "devDependencies": { - "@semantic-release/changelog": "^6.0.3", - "@semantic-release/commit-analyzer": "^13.0.0", - "@semantic-release/git": "^10.0.1", - "@semantic-release/release-notes-generator": "^14.0.1", - "@the-rabbit-hole/semantic-release-config": "^1.5.0", - "@types/node": "^22.5.5", + "@eslint/js": "^9.15.0", + "@shipgirl/typedoc-plugin-versions": "^0.2.8", + "@types/eslint__js": "^8.42.3", + "@types/node": "^22.9.0", "@types/tcp-port-used": "^1.0.4", - "@typescript-eslint/parser": "^8.6.0", - "@vitest/coverage-v8": "^2.1.1", - "@vitest/ui": "^2.1.1", + "@typescript-eslint/eslint-plugin": "^8.14.0", + "@typescript-eslint/parser": "^8.14.0", + "@vitest/coverage-v8": "^2.1.5", + "@vitest/ui": "^2.1.5", + "eslint": "^9.14.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-prettier": "^5.2.1", + "globals": "^15.12.0", + "npm-check-updates": "^17.1.11", "npm-package-json-lint": "^8.0.0", "portfinder": "^1.0.32", "pre-commit": "^1.2.2", - "semantic-release": "^24.1.1", "snazzy": "^9.0.0", "tcp-port-used": "^1.0.2", "ts-node": "^10.9.2", - "ts-standard": "^12.0.2", "tsd": "^0.31.2", - "typedoc": "^0.26.7", - "typescript": "5.6.2", - "vitest": "^2.1.1" + "typedoc": "^0.26.11", + "typescript": "^5.6.3", + "typescript-eslint": "^8.14.0", + "vitest": "^2.1.5" }, "dependencies": { - "node-hl7-client": "^2.3.1" + "node-hl7-client": "^3.0.0" }, "precommit": [ "lint:fix", diff --git a/release.config.cjs b/release.config.cjs deleted file mode 100644 index 99c1bd8..0000000 --- a/release.config.cjs +++ /dev/null @@ -1,7 +0,0 @@ -module.exports = { - extends: '@the-rabbit-hole/semantic-release-config', - branches: [ - 'main', - { name: 'develop', prerelease: 'beta' } - ] -} diff --git a/src/index.ts b/src/index.ts index 2c24e04..0aadb66 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,9 +1,13 @@ -import { Server } from './server/server.js' +import { Server } from "./server/server.js"; -export default Server -export { Server } -export { Inbound, InboundHandler } from './server/inbound.js' -export { HL7ListenerError, HL7ServerError } from './utils/exception.js' -export { ServerOptions, ListenerOptions } from './utils/normalize.js' -export { InboundRequest, InboundRequestProps } from './server/modules/inboundRequest.js' -export { SendResponse } from './server/modules/sendResponse.js' +export default Server; +export { Server }; +export { MLLPCodec } from "./utils/codec.js"; +export { Inbound, InboundHandler } from "./server/inbound.js"; +export { HL7ListenerError, HL7ServerError } from "./utils/exception.js"; +export { ServerOptions, ListenerOptions } from "./utils/normalize.js"; +export { + InboundRequest, + InboundRequestProps, +} from "./server/modules/inboundRequest.js"; +export { SendResponse } from "./server/modules/sendResponse.js"; diff --git a/src/server/inbound.ts b/src/server/inbound.ts index 8ed9237..46ebc81 100644 --- a/src/server/inbound.ts +++ b/src/server/inbound.ts @@ -1,12 +1,15 @@ -import EventEmitter from 'events' -import net, { Socket } from 'net' -import tls from 'tls' -import { FileBatch, Batch, Message, isBatch, isFile } from 'node-hl7-client' -import { PROTOCOL_MLLP_FOOTER, PROTOCOL_MLLP_HEADER } from '../utils/constants.js' -import { ListenerOptions, normalizeListenerOptions } from '../utils/normalize.js' -import { InboundRequest } from './modules/inboundRequest.js' -import { SendResponse } from './modules/sendResponse.js' -import { Server } from './server.js' +import EventEmitter from "events"; +import net, { Socket } from "net"; +import tls from "tls"; +import { FileBatch, Batch, Message, isBatch, isFile } from "node-hl7-client"; +import { + ListenerOptions, + normalizeListenerOptions, +} from "../utils/normalize.js"; +import { InboundRequest } from "./modules/inboundRequest.js"; +import { SendResponse } from "./modules/sendResponse.js"; +import { Server } from "./server.js"; +import { MLLPCodec } from "../utils/codec.js"; /** * Inbound Handler @@ -21,28 +24,26 @@ import { Server } from './server.js' * }) *``` */ -export type InboundHandler = (req: InboundRequest, res: SendResponse) => void +export type InboundHandler = (req: InboundRequest, res: SendResponse) => void; -/* eslint-disable */ export interface Inbound extends EventEmitter { /** When the connection form the client is closed. We might have an error, we might not. */ - on(name: 'client.close', cb: (hasError: boolean) => void): this; + on(name: "client.close", cb: (hasError: boolean) => void): this; /** When a connection from the client is made. */ - on(name: 'client.connect', cb: (socket: Socket) => void): this; + on(name: "client.connect", cb: (socket: Socket) => void): this; /** When an error was sent by the connecting source. */ - on(name: 'client.error', cb: (err: any) => void): this; + on(name: "client.error", cb: (err: any) => void): this; /** Something wrong happened during data parsing. */ - on(name: 'data.error', cb: (err: any) => void): this; + on(name: "data.error", cb: (err: any) => void): this; /** The raw data received by this particular inbound connection. */ - on(name: 'data.raw', cb: (rawData: string) => void): this; + on(name: "data.raw", cb: (rawData: string) => void): this; /** When the socket itself has an error. */ - on(name: 'error', cb: (err: any) => void): this; + on(name: "error", cb: (err: any) => void): this; /** When the socket is ready and listening on the port. */ - on(name: 'listen', cb: () => void): this; + on(name: "listen", cb: () => void): this; /** An HL7 response was sent */ - on(name: 'response.sent', cb: () => void): this; + on(name: "response.sent", cb: () => void): this; } -/* eslint-enable */ /** * Inbound Listener Class @@ -50,15 +51,19 @@ export interface Inbound extends EventEmitter { */ export class Inbound extends EventEmitter implements Inbound { /** @internal */ - private readonly _handler: (req: InboundRequest, res: SendResponse) => void + private readonly _handler: (req: InboundRequest, res: SendResponse) => void; /** @internal */ - _main: Server + _main: Server; /** @internal */ - _opt: ReturnType + _opt: ReturnType; /** @internal */ - private readonly _socket: net.Server | tls.Server + private readonly _socket: net.Server | tls.Server; /** @internal */ - private readonly _sockets: Socket[] + private readonly _sockets: Socket[]; + /** @internal */ + private _dataResult: boolean | undefined; + /** @internal */ + private _codec: MLLPCodec | null; /** @internal */ readonly stats = { /** Total message received to server. @@ -66,8 +71,8 @@ export class Inbound extends EventEmitter implements Inbound { received: 0, /** Total message parsed by the server.. * @since 2.0.0 */ - totalMessage: 0 - } + totalMessage: 0, + }; /** * Build a Listener @@ -76,171 +81,191 @@ export class Inbound extends EventEmitter implements Inbound { * @param props * @param handler */ - constructor (server: Server, props: ListenerOptions, handler: InboundHandler) { - super() + constructor(server: Server, props: ListenerOptions, handler: InboundHandler) { + super(); - this._handler = handler - this._main = server + this._handler = handler; + this._main = server; - this._opt = normalizeListenerOptions(props) + this._opt = normalizeListenerOptions(props); - this._sockets = [] + this._sockets = []; - this._listen = this._listen.bind(this) - this._onTcpClientConnected = this._onTcpClientConnected.bind(this) + this._listen = this._listen.bind(this); + this._onTcpClientConnected = this._onTcpClientConnected.bind(this); - this._socket = this._listen() + this._codec = null; + + this._socket = this._listen(); } /** Close Listener Instance. * This be called for each listener, but if the server instance is closed and shut down, this will also fire off. * @since 1.0.0 */ - async close (): Promise { + async close(): Promise { this._sockets.forEach((socket) => { - socket.destroy() - }) + socket.destroy(); + }); this._socket?.close(() => { - this._socket?.unref() - }) + this._socket?.unref(); + }); - return true + return true; } /** @internal */ - private _listen (): net.Server | tls.Server { - let socket: net.Server | tls.Server - const port = this._opt.port - const bindAddress = this._main._opt.bindAddress - const ipv6 = this._main._opt.ipv6 - - if (typeof this._main._opt.tls !== 'undefined') { - const { key, cert, requestCert, ca } = this._main._opt.tls - socket = tls.createServer({ key, cert, requestCert, ca }, socket => this._onTcpClientConnected(socket)) + private _listen(): net.Server | tls.Server { + let socket: net.Server | tls.Server; + const port = this._opt.port; + const bindAddress = this._main._opt.bindAddress; + const ipv6 = this._main._opt.ipv6; + + if (typeof this._main._opt.tls !== "undefined") { + const { key, cert, requestCert, ca } = this._main._opt.tls; + socket = tls.createServer({ key, cert, requestCert, ca }, (socket) => { + this._codec = new MLLPCodec(); + this._onTcpClientConnected(socket); + }); } else { - socket = net.createServer(socket => this._onTcpClientConnected(socket)) + socket = net.createServer((socket) => { + this._codec = new MLLPCodec(); + this._onTcpClientConnected(socket); + }); } - socket.on('error', err => { - this.emit('error', err) - }) + socket.on("error", (err) => { + this.emit("error", err); + }); socket.listen({ port, ipv6Only: ipv6, hostname: bindAddress }, () => { - this.emit('listen') - }) + this.emit("listen"); + }); - return socket + return socket; } /** @internal */ - private _onTcpClientConnected (socket: Socket): void { - // set message - let loadedMessage: string = '' - + private _onTcpClientConnected(socket: Socket): void { // add socked connection to array - this._sockets.push(socket) + this._sockets.push(socket); // no delay in processing the message - socket.setNoDelay(true) + socket.setNoDelay(true); + + socket.on("data", (buffer) => { + socket.cork(); - // set encoding - socket.setEncoding(this._opt.encoding) + try { + this._dataResult = this._codec?.receiveData(buffer); + } catch (err) { + this.emit("data.error", err); + } - socket.on('data', (buffer) => { - socket.cork() + socket.uncork(); - // we got a message, we don't care if it's good or not - ++this.stats.received + if (this._dataResult === true) { + // we got a message, we don't care if it's good or not + ++this.stats.received; - try { - // set message - loadedMessage += buffer.toString().replace(PROTOCOL_MLLP_HEADER, '') + const loadedMessage = this._codec?.getLastMessage(); - // is there is F5 and CR in this message? - if (loadedMessage.includes(PROTOCOL_MLLP_FOOTER)) { - // strip them out - loadedMessage = loadedMessage.replace(PROTOCOL_MLLP_FOOTER, '') + try { + // copy the completed message to continue processing and clear the buffer + const completedMessageCopy = JSON.parse( + JSON.stringify(loadedMessage), + ); // parser either is batch or a message - let parser: FileBatch | Batch | Message + let parser: FileBatch | Batch | Message; - // send raw information to the emit - this.emit('data.raw', loadedMessage) + // send raw information to the emitting + this.emit("data.raw", completedMessageCopy); - if (isFile(loadedMessage)) { + if (isFile(completedMessageCopy)) { // parser the batch - parser = new FileBatch({ text: loadedMessage }) + parser = new FileBatch({ text: completedMessageCopy }); // load the messages - const allMessage = parser.messages() + const allMessage = parser.messages(); allMessage.forEach((message: Message) => { // parse this message - const messageParsed = new Message({ text: message.toString() }) + const messageParsed = new Message({ text: message.toString() }); // increase the total message - ++this.stats.totalMessage + ++this.stats.totalMessage; // create the inbound request - const req = new InboundRequest(messageParsed, { type: 'file' }) + const req = new InboundRequest(messageParsed, { type: "file" }); // create the send response function - const res = new SendResponse(socket, message, this._opt.mshOverrides) + const res = new SendResponse( + socket, + message, + this._opt.mshOverrides, + ); // on a response sent, tell the inbound listener - res.on('response.sent', () => { - this.emit('response.sent') - }) - void this._handler(req, res) - }) - } else if (isBatch(loadedMessage)) { + res.on("response.sent", () => { + this.emit("response.sent"); + }); + void this._handler(req, res); + }); + } else if (isBatch(completedMessageCopy)) { // parser the batch - parser = new Batch({ text: loadedMessage }) + parser = new Batch({ text: completedMessageCopy }); // load the messages - const allMessage = parser.messages() + const allMessage = parser.messages(); // loop messages allMessage.forEach((message: Message) => { // parse this message - const messageParsed = new Message({ text: message.toString() }) + const messageParsed = new Message({ text: message.toString() }); // increase the total message - ++this.stats.totalMessage + ++this.stats.totalMessage; // create the inbound request - const req = new InboundRequest(messageParsed, { type: 'file' }) + const req = new InboundRequest(messageParsed, { type: "file" }); // create the send response function - const res = new SendResponse(socket, messageParsed, this._opt.mshOverrides) + const res = new SendResponse( + socket, + messageParsed, + this._opt.mshOverrides, + ); // on a response sent, tell the inbound listener - void this._handler(req, res) - }) + void this._handler(req, res); + }); } else { // parse this message - const messageParsed = new Message({ text: loadedMessage }) + const messageParsed = new Message({ text: completedMessageCopy }); // increase the total message - ++this.stats.totalMessage + ++this.stats.totalMessage; // create the inbound request - const req = new InboundRequest(messageParsed, { type: 'file' }) + const req = new InboundRequest(messageParsed, { type: "file" }); // create the send response function - const res = new SendResponse(socket, messageParsed, this._opt.mshOverrides) + const res = new SendResponse( + socket, + messageParsed, + this._opt.mshOverrides, + ); // on a response sent, tell the inbound listener - void this._handler(req, res) + void this._handler(req, res); } + } catch (err) { + this.emit("data.error", err); } - } catch (err) { - this.emit('data.error', err) } + }); - socket.uncork() - }) - - socket.on('error', err => { - this.emit('client.error', err) - this._closeSocket(socket) - }) + socket.on("error", (err) => { + this.emit("client.error", err); + this._closeSocket(socket); + }); - socket.on('close', hadError => { - this.emit('client.close', hadError) - this._closeSocket(socket) - }) + socket.on("close", (hadError) => { + this.emit("client.close", hadError); + this._closeSocket(socket); + }); - this.emit('client.connect', socket) + this.emit("client.connect", socket); } /** @internal */ - private _closeSocket (socket: Socket): void { - socket.destroy() - this._sockets.splice(this._sockets.indexOf(socket), 1) + private _closeSocket(socket: Socket): void { + socket.destroy(); + this._sockets.splice(this._sockets.indexOf(socket), 1); } } diff --git a/src/server/modules/inboundRequest.ts b/src/server/modules/inboundRequest.ts index 9218f2f..56557b5 100644 --- a/src/server/modules/inboundRequest.ts +++ b/src/server/modules/inboundRequest.ts @@ -1,12 +1,12 @@ -import { Message } from 'node-hl7-client' -import { HL7ListenerError } from '../../utils/exception.js' +import { Message } from "node-hl7-client"; +import { HL7ListenerError } from "../../utils/exception.js"; /** * Inbound Request Props * @since 1.0.0 */ export interface InboundRequestProps { - type: string + type: string; } /** @@ -15,32 +15,32 @@ export interface InboundRequestProps { */ export class InboundRequest { /** @internal */ - private readonly _message?: Message + private readonly _message?: Message; /** @internal */ - private readonly _fromType: string + private readonly _fromType: string; /** * @since 1.0.0 * @param message * @param props */ - constructor (message: Message, props: InboundRequestProps) { - this._fromType = props.type - this._message = message + constructor(message: Message, props: InboundRequestProps) { + this._fromType = props.type; + this._message = message; } /** ' * Get Stored Message * @since 1.0.0 */ - getMessage (): Message { - if (typeof this._message !== 'undefined') { - return this._message + getMessage(): Message { + if (typeof this._message !== "undefined") { + return this._message; } - throw new HL7ListenerError('Message is not defined.') + throw new HL7ListenerError("Message is not defined."); } - getType (): string { - return this._fromType + getType(): string { + return this._fromType; } } diff --git a/src/server/modules/sendResponse.ts b/src/server/modules/sendResponse.ts index 18c77a8..91e55a7 100644 --- a/src/server/modules/sendResponse.ts +++ b/src/server/modules/sendResponse.ts @@ -1,6 +1,6 @@ -import EventEmitter from 'events' -import { Socket } from 'net' -import { Message, randomString } from 'node-hl7-client' +import EventEmitter from "events"; +import { Socket } from "net"; +import { Message, randomString } from "node-hl7-client"; import { HL7_2_1, HL7_2_2, @@ -8,10 +8,14 @@ import { HL7_2_3_1, HL7_2_4, HL7_2_5, - HL7_2_5_1, HL7_2_6, HL7_2_7, HL7_2_7_1, HL7_2_8 -} from 'node-hl7-client/hl7' -import { PROTOCOL_MLLP_FOOTER, PROTOCOL_MLLP_HEADER } from '../../utils/constants.js' -import type { ListenerOptions } from '../../utils/normalize.js' + HL7_2_5_1, + HL7_2_6, + HL7_2_7, + HL7_2_7_1, + HL7_2_8, +} from "node-hl7-client/hl7"; +import type { ListenerOptions } from "../../utils/normalize.js"; +import { MLLPCodec } from "../../utils/codec.js"; /** * Send Response @@ -19,20 +23,27 @@ import type { ListenerOptions } from '../../utils/normalize.js' */ export class SendResponse extends EventEmitter { /** @internal */ - private _ack: Message | undefined + private _ack: Message | undefined; /** @internal */ - private readonly _socket: Socket + private readonly _socket: Socket; /** @internal */ - private readonly _message: Message + private readonly _message: Message; /** @internal */ - private readonly _mshOverrides: ListenerOptions['mshOverrides'] - - constructor (socket: Socket, message: Message, mshOverrides?: ListenerOptions['mshOverrides']) { - super() - this._ack = undefined - this._message = message - this._mshOverrides = mshOverrides - this._socket = socket + private readonly _mshOverrides: ListenerOptions["mshOverrides"]; + /** @internal */ + private readonly _codec: MLLPCodec; + + constructor( + socket: Socket, + message: Message, + mshOverrides?: ListenerOptions["mshOverrides"], + ) { + super(); + this._ack = undefined; + this._message = message; + this._mshOverrides = mshOverrides; + this._socket = socket; + this._codec = new MLLPCodec(); } /** @@ -40,6 +51,7 @@ export class SendResponse extends EventEmitter { * @since 1.0.0 * @see {@link https://hl7-definition.caristix.com/v2/HL7v2.1/Tables/0008} * @param type + * @param encoding * @example * If you are to confirm to the end user (client) that the message they sent was good and processed successfully. * you would send an "AA" style message (Application Accept). @@ -73,17 +85,20 @@ export class SendResponse extends EventEmitter { * "AE" (Application Error) will be automatically sent if there is a problem creating either an "AA" or "AR" * message from the original message sent because the original message structure sent wrong in the first place. */ - async sendResponse (type: 'AA' | 'AR' | 'AE'): Promise { + async sendResponse( + type: "AA" | "AR" | "AE", + encoding: BufferEncoding = "utf-8", + ): Promise { try { - this._ack = this._createAckMessage(type, this._message) - this._socket.write(Buffer.from(`${PROTOCOL_MLLP_HEADER}${this._ack.toString()}${PROTOCOL_MLLP_FOOTER}`)) + this._ack = this._createAckMessage(type, this._message); } catch (_e: any) { - this._ack = this._createAEAckMessage() - this._socket.write(Buffer.from(`${PROTOCOL_MLLP_HEADER}${this._ack.toString()}${PROTOCOL_MLLP_FOOTER}`)) + this._ack = this._createAEAckMessage(); } + this._codec.sendMessage(this._socket, this._ack.toString(), encoding); + // we are sending a response back, why not? - this.emit('response.sent') + this.emit("response.sent"); } /** @@ -92,101 +107,101 @@ export class SendResponse extends EventEmitter { * @remarks Get the acknowledged message that was sent to the client. * This could return undefined if accessed prior to sending the response */ - getAckMessage (): Message | undefined { - return this._ack + getAckMessage(): Message | undefined { + return this._ack; } /** @internal */ - private _createAckMessage (type: string, message: Message): Message { - let specClass - const spec = message.get('MSH.12').toString() + private _createAckMessage(type: string, message: Message): Message { + let specClass; + const spec = message.get("MSH.12").toString(); switch (spec) { - case '2.1': - specClass = new HL7_2_1() - break - case '2.2': - specClass = new HL7_2_2() - break - case '2.3': - specClass = new HL7_2_3() - break - case '2.3.1': - specClass = new HL7_2_3_1() - break - case '2.4': - specClass = new HL7_2_4() - break - case '2.5': - specClass = new HL7_2_5() - break - case '2.5.1': - specClass = new HL7_2_5_1() - break - case '2.6': - specClass = new HL7_2_6() - break - case '2.7': - specClass = new HL7_2_7() - break - case '2.7.1': - specClass = new HL7_2_7_1() - break - case '2.8': - specClass = new HL7_2_8() - break + case "2.1": + specClass = new HL7_2_1(); + break; + case "2.2": + specClass = new HL7_2_2(); + break; + case "2.3": + specClass = new HL7_2_3(); + break; + case "2.3.1": + specClass = new HL7_2_3_1(); + break; + case "2.4": + specClass = new HL7_2_4(); + break; + case "2.5": + specClass = new HL7_2_5(); + break; + case "2.5.1": + specClass = new HL7_2_5_1(); + break; + case "2.6": + specClass = new HL7_2_6(); + break; + case "2.7": + specClass = new HL7_2_7(); + break; + case "2.7.1": + specClass = new HL7_2_7_1(); + break; + case "2.8": + specClass = new HL7_2_8(); + break; } const ackMessage = new Message({ specification: specClass, messageHeader: { - msh_9_1: 'ACK', - msh_9_2: message.get('MSH.9.2').toString(), - msh_10: 'ACK', - msh_11_1: message.get('MSH.11.1').toString() as 'P' | 'D' | 'T' - } - }) - - ackMessage.set('MSH.3', message.get('MSH.5').toString()) - ackMessage.set('MSH.4', message.get('MSH.6').toString()) - ackMessage.set('MSH.5', message.get('MSH.3').toString()) - ackMessage.set('MSH.6', message.get('MSH.4').toString()) - ackMessage.set('MSH.12', message.get('MSH.12').toString()) - - if (typeof this._mshOverrides === 'object') { + msh_9_1: "ACK", + msh_9_2: message.get("MSH.9.2").toString(), + msh_10: "ACK", + msh_11_1: message.get("MSH.11.1").toString() as "P" | "D" | "T", + }, + }); + + ackMessage.set("MSH.3", message.get("MSH.5").toString()); + ackMessage.set("MSH.4", message.get("MSH.6").toString()); + ackMessage.set("MSH.5", message.get("MSH.3").toString()); + ackMessage.set("MSH.6", message.get("MSH.4").toString()); + ackMessage.set("MSH.12", message.get("MSH.12").toString()); + + if (typeof this._mshOverrides === "object") { Object.entries(this._mshOverrides).forEach(([path, value]) => { - ackMessage.set(`MSH.${path}`, value) - }) + ackMessage.set(`MSH.${path}`, value); + }); } - const segment = ackMessage.addSegment('MSA') - segment.set('1', type) - segment.set('2', message.get('MSH.10').toString()) + const segment = ackMessage.addSegment("MSA"); + segment.set("1", type); + segment.set("2", message.get("MSH.10").toString()); - return ackMessage + return ackMessage; } /** @internal */ - private _createAEAckMessage (): Message { + private _createAEAckMessage(): Message { const ackMessage = new Message({ messageHeader: { - msh_9_1: 'ACK', + msh_9_1: "ACK", // There is not an MSH 9.2 for ACK a failure. // There should be. // So we are using Z99, which is not assigned yet. - msh_9_2: 'Z99', - msh_9_3: 'ACK', - msh_10: 'ACK', - msh_11_1: 'P' - } - }) + msh_9_2: "Z99", + msh_9_3: "ACK", + msh_10: "ACK", + msh_11_1: "P", + }, + }); - ackMessage.set('MSH.3', '') // This would need to be set by the application. Maybe from the server class? - ackMessage.set('MSH.4', '') // This would need to be set by the application. Maybe from the server class? + ackMessage.set("MSH.3", ""); // This would need to be set by the application. Maybe from the server class? + ackMessage.set("MSH.4", ""); // This would need to be set by the application. Maybe from the server class? - const segment = ackMessage.addSegment('MSA') - segment.set('1', 'AE') - segment.set('2', randomString()) + const segment = ackMessage.addSegment("MSA"); + segment.set("1", "AE"); + segment.set("2", randomString()); - return ackMessage + return ackMessage; } } diff --git a/src/server/server.ts b/src/server/server.ts index 564a149..ebec041 100644 --- a/src/server/server.ts +++ b/src/server/server.ts @@ -1,6 +1,10 @@ -import EventEmitter from 'events' -import { Inbound, InboundHandler } from './inbound.js' -import { ServerOptions, normalizeServerOptions, ListenerOptions } from '../utils/normalize.js' +import EventEmitter from "events"; +import { Inbound, InboundHandler } from "./inbound.js"; +import { + ServerOptions, + normalizeServerOptions, + ListenerOptions, +} from "../utils/normalize.js"; /** * Server Class @@ -10,7 +14,7 @@ import { ServerOptions, normalizeServerOptions, ListenerOptions } from '../utils */ export class Server extends EventEmitter { /** @internal */ - _opt: ReturnType + _opt: ReturnType; /** * @since 1.0.0 @@ -36,9 +40,9 @@ export class Server extends EventEmitter { * ``` * */ - constructor (props?: ServerOptions) { - super() - this._opt = normalizeServerOptions(props) + constructor(props?: ServerOptions) { + super(); + this._opt = normalizeServerOptions(props); } /** This creates an instance of a HL7 server. @@ -56,7 +60,7 @@ export class Server extends EventEmitter { *``` * * */ - createInbound (props: ListenerOptions, cb: InboundHandler): Inbound { - return new Inbound(this, props, cb) + createInbound(props: ListenerOptions, cb: InboundHandler): Inbound { + return new Inbound(this, props, cb); } } diff --git a/src/utils/codec.ts b/src/utils/codec.ts new file mode 100644 index 0000000..9a0b7ed --- /dev/null +++ b/src/utils/codec.ts @@ -0,0 +1,117 @@ +import { Socket } from "node:net"; +import { + PROTOCOL_MLLP_END, + PROTOCOL_MLLP_FOOTER, + PROTOCOL_MLLP_HEADER, +} from "./constants.js"; + +/** MLLPCodec Class + * @since 3.1.0 */ +export class MLLPCodec { + /** @internal */ + private lastMessage: string | null = null; + /** @internal */ + private dataBuffer: Buffer = Buffer.alloc(0); + /** @internal */ + private readonly _encoding: BufferEncoding; + /** @internal */ + private readonly _returnCharacter: string; + + /** + * @since 3.1.0 + * @param encoding + * @param returnCharacter + */ + constructor( + encoding: BufferEncoding = "utf-8", + returnCharacter: string = "\r", + ) { + this._encoding = encoding; + this._returnCharacter = returnCharacter; + } + + /** + * Process the stored message that was sent over. + * @since 3.1.0 + * @private + */ + private processMessage(): void { + const messages: string[] = []; + const dataString = this.dataBuffer.toString(this._encoding); + const messageParts = dataString.split("\u001c\r"); + + // loop though the message parts + for (const part of messageParts) { + if (part.trim() !== "") { + const trimmedPart = part.trim(); + messages.push(this.stripMLLPCharacters(trimmedPart)); + } + } + + // put the entire message together + this.lastMessage = messages.join(this._returnCharacter); + + // clear the data buffer + this.dataBuffer = Buffer.alloc(0); + } + + /** + * @since 3.1.0 + * @param message + * @private + */ + private stripMLLPCharacters(message: string): string { + // eslint-disable-next-line no-control-regex + return message.replace(/\u000b/g, "").replace(/\u001c/g, ""); + } + + /** + * Process the incoming data from the client. + * @since 3.1.0 + * @param data + */ + public receiveData(data: Buffer): boolean { + this.dataBuffer = Buffer.concat([this.dataBuffer, data]); + + // only go into this code see that the last part of the dataBuffer contains the end and footer protocol + if (this.dataBuffer.includes(0x1c) && this.dataBuffer.includes(0x0d)) { + // process the message now + void this.processMessage(); + // return true + return true; + } + + // return false because we are still waiting for more of the message to come over + return false; + } + + /** + * Get the last message. + * @since 3.1.0 + */ + public getLastMessage(): string | null { + return this.lastMessage; + } + + /** + * Send a message and send it to the remote side. + * @since 3.1.0 + * @param socket + * @param message + * @param encoding + */ + public sendMessage( + socket: Socket | undefined, + message: string, + encoding: BufferEncoding, + ): void { + const messageBuffer = Buffer.concat([ + PROTOCOL_MLLP_HEADER, + Buffer.from(message, encoding), + PROTOCOL_MLLP_END, + PROTOCOL_MLLP_FOOTER, + ]); + + socket?.write(messageBuffer); + } +} diff --git a/src/utils/constants.ts b/src/utils/constants.ts index 53e518c..fe712b7 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -1,5 +1,11 @@ /** @internal */ -export const PROTOCOL_MLLP_HEADER = String.fromCharCode(0x0b) +export const PROTOCOL_MLLP_HEADER = Buffer.from([0x0b]); /** @internal */ -export const PROTOCOL_MLLP_FOOTER = `${String.fromCharCode(0x1c)}${String.fromCharCode(0x0d)}` +export const PROTOCOL_MLLP_END = Buffer.from([0x1c]); + +/** @internal */ +export const PROTOCOL_MLLP_FOOTER = Buffer.from([0x0d]); + +/** @internal */ +export const NAME_FORMAT = /[ `!@#$%^&*()+\-=\[\]{};':"\\|,.<>\/?~]/; //eslint-disable-line diff --git a/src/utils/exception.ts b/src/utils/exception.ts index 9a0b892..93ec505 100644 --- a/src/utils/exception.ts +++ b/src/utils/exception.ts @@ -2,12 +2,12 @@ * @since 1.0.0 */ class HL7Error extends Error { /** @internal */ - code: number + code: number; /** @internal */ - constructor (code: number, message: string) { - super(message) - this.name = 'HL7ServerError' - this.code = code + constructor(code: number, message: string) { + super(message); + this.name = "HL7ServerError"; + this.code = code; } } @@ -15,9 +15,9 @@ class HL7Error extends Error { * @since 1.0.0 */ export class HL7ServerError extends HL7Error { /** @internal */ - name = 'HL7ServerError' - constructor (message: string) { - super(500, message) + name = "HL7ServerError"; + constructor(message: string) { + super(500, message); } } @@ -25,5 +25,5 @@ export class HL7ServerError extends HL7Error { * @since 1.0.0 */ export class HL7ListenerError extends Error { /** @internal */ - name = 'HL7ListenerError' + name = "HL7ListenerError"; } diff --git a/src/utils/normalize.ts b/src/utils/normalize.ts index f3f3077..1a6cc3a 100644 --- a/src/utils/normalize.ts +++ b/src/utils/normalize.ts @@ -1,18 +1,23 @@ -import { TcpSocketConnectOpts } from 'node:net' -import type { ConnectionOptions as TLSOptions } from 'node:tls' -import { assertNumber, randomString, validIPv4, validIPv6 } from 'node-hl7-client' -import { HL7ListenerError, HL7ServerError } from './exception.js' +import { TcpSocketConnectOpts } from "node:net"; +import type { ConnectionOptions as TLSOptions } from "node:tls"; +import { + assertNumber, + randomString, + validIPv4, + validIPv6, +} from "node-hl7-client"; +import { HL7ListenerError, HL7ServerError } from "./exception.js"; const DEFAULT_SERVER_OPTS = { - bindAddress: '0.0.0.0', - encoding: 'utf-8', + bindAddress: "0.0.0.0", + encoding: "utf-8", ipv4: true, - ipv6: false -} + ipv6: false, +}; const DEFAULT_LISTENER_OPTS = { - encoding: 'utf-8' -} + encoding: "utf-8", +}; /** * @since 1.0.0 @@ -20,18 +25,18 @@ const DEFAULT_LISTENER_OPTS = { export interface ServerOptions { /** The network address to listen on expediently. * @default 0.0.0.0 */ - bindAddress?: string + bindAddress?: string; /** IPv4 Only - If this is set to true, only IPv4 address will be used. * @default false */ - ipv4?: boolean + ipv4?: boolean; /** IPv6 Only - If this is set to true, only IPv6 address will be used. * @default false */ - ipv6?: boolean + ipv6?: boolean; /** Additional options when creating the TCP socket with net.connect(). */ - socket?: TcpSocketConnectOpts + socket?: TcpSocketConnectOpts; /** Enable TLS, or set TLS specific options like overriding the CA for * self-signed certificates. */ - tls?: TLSOptions + tls?: TLSOptions; } /** @@ -42,82 +47,94 @@ export interface ListenerOptions { * syntax: "field path as numbers separated by dots": "field value" * e.g. { '9.3': 'ACK' } → MSH field 9.3 set to "ACK" * @since 2.5.0 */ - mshOverrides?: Record + mshOverrides?: Record; /** Name of the Listener (e.g., IB_EPIC_ADT) * @default Randomized String */ - name?: string + name?: string; /** The network address to listen on expediently. * Must be set between 0 and 65353 */ - port: number + port: number; /** Encoding of the messages we expect from the HL7 message. * @default "utf-8" */ - encoding?: BufferEncoding + encoding?: BufferEncoding; } /** * @since 1.0.0 */ -type ValidatedKeys = - | 'name' - | 'port' - | 'encoding' +type ValidatedKeys = "name" | "port" | "encoding"; /** * @since 1.0.0 */ -interface ValidatedOptions extends Pick, ValidatedKeys> { - mshOverrides?: Record - name: string - port: number +interface ValidatedOptions + extends Pick, ValidatedKeys> { + mshOverrides?: Record; + name: string; + port: number; } /** @internal */ -export function normalizeServerOptions (raw?: ServerOptions): ServerOptions { - const props: any = { ...DEFAULT_SERVER_OPTS, ...raw } +export function normalizeServerOptions(raw?: ServerOptions): ServerOptions { + const props: any = { ...DEFAULT_SERVER_OPTS, ...raw }; if (props.ipv4 === true && props.ipv6 === true) { - throw new HL7ServerError('ipv4 and ipv6 both can\'t be set to be exclusive.') + throw new HL7ServerError( + "ipv4 and ipv6 both can't be set to be exclusive.", + ); } - if (typeof props.bindAddress !== 'string') { - throw new HL7ServerError('bindAddress is not valid string.') - } else if (props.bindAddress !== 'localhost') { - if (typeof props.bindAddress !== 'undefined' && props.ipv6 === true && !validIPv6(props.bindAddress)) { - throw new HL7ServerError('bindAddress is an invalid ipv6 address.') + if (typeof props.bindAddress !== "string") { + throw new HL7ServerError("bindAddress is not valid string."); + } else if (props.bindAddress !== "localhost") { + if ( + typeof props.bindAddress !== "undefined" && + props.ipv6 === true && + !validIPv6(props.bindAddress) + ) { + throw new HL7ServerError("bindAddress is an invalid ipv6 address."); } - if (typeof props.bindAddress !== 'undefined' && props.ipv4 === true && !validIPv4(props.bindAddress)) { - throw new HL7ServerError('bindAddress is an invalid ipv4 address.') + if ( + typeof props.bindAddress !== "undefined" && + props.ipv4 === true && + !validIPv4(props.bindAddress) + ) { + throw new HL7ServerError("bindAddress is an invalid ipv4 address."); } } - return props + return props; } /** @internal */ -export function normalizeListenerOptions (raw?: ListenerOptions): ValidatedOptions { - const props: any = { ...DEFAULT_LISTENER_OPTS, ...raw } +export function normalizeListenerOptions( + raw?: ListenerOptions, +): ValidatedOptions { + const props: any = { ...DEFAULT_LISTENER_OPTS, ...raw }; - const nameFormat = /[ `!@#$%^&*()+\-=\[\]{};':"\\|,.<>\/?~]/ //eslint-disable-line + const nameFormat = /[ `!@#$%^&*()+\-=\[\]{};':"\\|,.<>\/?~]/; //eslint-disable-line - if (typeof props.name === 'undefined') { - props.name = randomString() + if (typeof props.name === "undefined") { + props.name = randomString(); } else { if (nameFormat.test(props.name)) { - throw new HL7ListenerError('name must not contain certain characters: `!@#$%^&*()+\\-=\\[\\]{};\':"\\\\|,.<>\\/?~.') + throw new HL7ListenerError( + "name must not contain certain characters: `!@#$%^&*()+\\-=\\[\\]{};':\"\\\\|,.<>\\/?~.", + ); } } - if (typeof props.port === 'undefined') { - throw new HL7ListenerError('port is not defined.') + if (typeof props.port === "undefined") { + throw new HL7ListenerError("port is not defined."); } - if (typeof props.port !== 'number') { - throw new HL7ListenerError('port is not valid number.') + if (typeof props.port !== "number") { + throw new HL7ListenerError("port is not valid number."); } - assertNumber(props, 'port', 0, 65353) + assertNumber(props, "port", 0, 65353); - return props + return props; } diff --git a/typedoc.json b/typedoc.json index 6ce51af..501a254 100644 --- a/typedoc.json +++ b/typedoc.json @@ -5,6 +5,7 @@ "excludeInternal": true, "includeVersion": true, "githubPages": false, + "plugin": ["@shipgirl/typedoc-plugin-versions"], "out": "./docs", "name": "Node HL7 Server", "navigationLinks": { diff --git a/vitest.config.mts b/vitest.config.mts index 8d60134..903abf7 100644 --- a/vitest.config.mts +++ b/vitest.config.mts @@ -9,8 +9,7 @@ export default defineConfig({ 'bin', 'certs', 'docs', - 'lib', - 'release.config.cjs' + 'lib' ] } }