@glion/mllp-client 0.16.0 → 0.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/README.md +466 -193
  2. package/dist/assertions.d.ts +17 -0
  3. package/dist/assertions.d.ts.map +1 -0
  4. package/dist/chunks/mllp-invalid-option-error.js +32 -0
  5. package/dist/chunks/mllp-invalid-option-error.js.map +1 -0
  6. package/dist/client.d.ts +127 -0
  7. package/dist/client.d.ts.map +1 -0
  8. package/dist/constants.d.ts +23 -0
  9. package/dist/constants.d.ts.map +1 -0
  10. package/dist/errors/base.d.ts +30 -0
  11. package/dist/errors/base.d.ts.map +1 -0
  12. package/dist/errors/index.d.ts +14 -0
  13. package/dist/errors/index.d.ts.map +1 -0
  14. package/dist/errors/mllp-client-closed-error.d.ts +12 -0
  15. package/dist/errors/mllp-client-closed-error.d.ts.map +1 -0
  16. package/dist/errors/mllp-connection-error.d.ts +9 -0
  17. package/dist/errors/mllp-connection-error.d.ts.map +1 -0
  18. package/dist/errors/mllp-connection-failed-error.d.ts +12 -0
  19. package/dist/errors/mllp-connection-failed-error.d.ts.map +1 -0
  20. package/dist/errors/mllp-connection-lost-error.d.ts +13 -0
  21. package/dist/errors/mllp-connection-lost-error.d.ts.map +1 -0
  22. package/dist/errors/mllp-connection-timeout-error.d.ts +13 -0
  23. package/dist/errors/mllp-connection-timeout-error.d.ts.map +1 -0
  24. package/dist/errors/mllp-invalid-message-error.d.ts +13 -0
  25. package/dist/errors/mllp-invalid-message-error.d.ts.map +1 -0
  26. package/dist/errors/mllp-invalid-option-error.d.ts +8 -0
  27. package/dist/errors/mllp-invalid-option-error.d.ts.map +1 -0
  28. package/dist/errors/mllp-invalid-response-error.d.ts +16 -0
  29. package/dist/errors/mllp-invalid-response-error.d.ts.map +1 -0
  30. package/dist/errors/mllp-send-aborted-error.d.ts +12 -0
  31. package/dist/errors/mllp-send-aborted-error.d.ts.map +1 -0
  32. package/dist/errors/mllp-send-timeout-error.d.ts +13 -0
  33. package/dist/errors/mllp-send-timeout-error.d.ts.map +1 -0
  34. package/dist/errors/nak-exception.d.ts +17 -0
  35. package/dist/errors/nak-exception.d.ts.map +1 -0
  36. package/dist/events.d.ts +35 -0
  37. package/dist/events.d.ts.map +1 -0
  38. package/dist/index.d.ts +13 -20
  39. package/dist/index.d.ts.map +1 -1
  40. package/dist/index.js +843 -3
  41. package/dist/index.js.map +1 -0
  42. package/dist/messages.d.ts +37 -0
  43. package/dist/messages.d.ts.map +1 -0
  44. package/dist/queue.d.ts +25 -0
  45. package/dist/queue.d.ts.map +1 -0
  46. package/dist/reconnect.d.ts +18 -0
  47. package/dist/reconnect.d.ts.map +1 -0
  48. package/dist/runtime/node.d.ts +61 -0
  49. package/dist/runtime/node.d.ts.map +1 -0
  50. package/dist/runtime/node.js +121 -0
  51. package/dist/runtime/node.js.map +1 -0
  52. package/dist/runtime/workers.d.ts +33 -0
  53. package/dist/runtime/workers.d.ts.map +1 -0
  54. package/dist/runtime/workers.js +70 -0
  55. package/dist/runtime/workers.js.map +1 -0
  56. package/dist/session.d.ts +63 -0
  57. package/dist/session.d.ts.map +1 -0
  58. package/dist/state.d.ts +42 -0
  59. package/dist/state.d.ts.map +1 -0
  60. package/dist/types.d.ts +109 -0
  61. package/dist/types.d.ts.map +1 -0
  62. package/dist/utils.d.ts +9 -0
  63. package/dist/utils.d.ts.map +1 -0
  64. package/package.json +37 -46
  65. package/dist/client.js +0 -549
  66. package/dist/client.js.map +0 -1
  67. package/dist/core/acknowledgment.d.ts +0 -103
  68. package/dist/core/acknowledgment.d.ts.map +0 -1
  69. package/dist/core/client.d.ts +0 -256
  70. package/dist/core/client.d.ts.map +0 -1
  71. package/dist/core/connect.d.ts +0 -101
  72. package/dist/core/connect.d.ts.map +0 -1
  73. package/dist/core/errors.d.ts +0 -81
  74. package/dist/core/errors.d.ts.map +0 -1
  75. package/dist/core/index.d.ts +0 -23
  76. package/dist/core/index.d.ts.map +0 -1
  77. package/dist/core/index.js +0 -2
  78. package/dist/core/internal/ack-parser-stream.d.ts +0 -22
  79. package/dist/core/internal/ack-parser-stream.d.ts.map +0 -1
  80. package/dist/core/internal/subscribe-abort.d.ts +0 -30
  81. package/dist/core/internal/subscribe-abort.d.ts.map +0 -1
  82. package/dist/node.js +0 -214
  83. package/dist/node.js.map +0 -1
  84. package/dist/runtimes/internal/node-error-mapping.d.ts +0 -68
  85. package/dist/runtimes/internal/node-error-mapping.d.ts.map +0 -1
  86. package/dist/runtimes/node.d.ts +0 -47
  87. package/dist/runtimes/node.d.ts.map +0 -1
  88. package/dist/runtimes/node.js +0 -3
  89. package/dist/runtimes/workers.d.ts +0 -64
  90. package/dist/runtimes/workers.d.ts.map +0 -1
  91. package/dist/runtimes/workers.js +0 -143
  92. package/dist/runtimes/workers.js.map +0 -1
@@ -0,0 +1,42 @@
1
+ /**
2
+ * The client's phases, and what each one is holding: the session, the message
3
+ * in flight, and the close.
4
+ *
5
+ * Types only. A phase changes by replacing the object, never by mutating it.
6
+ *
7
+ * @module
8
+ */
9
+ import type { MllpClientError } from "./errors";
10
+ import type { MllpSession } from "./session";
11
+ export type State = {
12
+ readonly phase: "idle";
13
+ } | {
14
+ readonly phase: "connecting";
15
+ /** The dialing. Settles as `connect()` does. */
16
+ readonly opening: Promise<void>;
17
+ /** Aborted by `close()` and `destroy()`. Stops the dialing. */
18
+ readonly abort: AbortController;
19
+ } | {
20
+ readonly phase: "connected";
21
+ readonly session: MllpSession;
22
+ } | {
23
+ readonly phase: "sending";
24
+ readonly session: MllpSession;
25
+ } | {
26
+ readonly phase: "closing";
27
+ /** The failure the client is closing on, or `null` when the owner is. */
28
+ readonly reason: MllpClientError | null;
29
+ /** The session being ended, or `null` when it is the dial. */
30
+ readonly session: MllpSession | null;
31
+ /** Settles once the client is `closed`. */
32
+ readonly closed: Promise<unknown>;
33
+ } | {
34
+ readonly phase: "closed";
35
+ /** The failure that closed the client, or `null` when the owner did. */
36
+ readonly reason: MllpClientError | null;
37
+ };
38
+ /** The phases with something open: the dial, or the session. */
39
+ export type Open = Extract<State, {
40
+ phase: "connecting" | "connected" | "sending";
41
+ }>;
42
+ //# sourceMappingURL=state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAChD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAE7C,MAAM,MAAM,KAAK,GACb;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC1B;IACE,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;IAC7B,gDAAgD;IAChD,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAChC,+DAA+D;IAC/D,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAC;CACjC,GACD;IACE,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;CAC/B,GACD;IACE,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;CAC/B,GACD;IACE,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAC1B,yEAAyE;IACzE,QAAQ,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI,CAAC;IACxC,8DAA8D;IAC9D,QAAQ,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;IACrC,2CAA2C;IAC3C,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;CACnC,GACD;IACE,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;IACzB,wEAAwE;IACxE,QAAQ,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI,CAAC;CACzC,CAAC;AAEN,gEAAgE;AAChE,MAAM,MAAM,IAAI,GAAG,OAAO,CACxB,KAAK,EACL;IAAE,KAAK,EAAE,YAAY,GAAG,WAAW,GAAG,SAAS,CAAA;CAAE,CAClD,CAAC"}
@@ -0,0 +1,109 @@
1
+ /**
2
+ * The public types of `@glion/mllp-client`. Types only — no runtime values.
3
+ *
4
+ * @module
5
+ */
6
+ import type { AckSuccessCode } from "@glion/ack";
7
+ import type { Root } from "@glion/ast";
8
+ /** The byte streams an open socket carries. */
9
+ export interface MllpStreams {
10
+ /** Bytes from the remote system. */
11
+ readonly readable: ReadableStream<Uint8Array>;
12
+ /** Bytes to the remote system. */
13
+ readonly writable: WritableStream<Uint8Array>;
14
+ }
15
+ /** A socket to one remote system. */
16
+ export interface MllpSocket {
17
+ /**
18
+ * Opens the socket and returns its byte streams.
19
+ *
20
+ * Rejects with `signal.reason` when cancelled. A rejection leaves nothing
21
+ * open. Called again only after `close()`.
22
+ */
23
+ connect(signal: AbortSignal): Promise<MllpStreams>;
24
+ /**
25
+ * Ends the socket `connect()` opened, and resolves once it is down.
26
+ *
27
+ * Never rejects. Idempotent. Bounded, even when the remote system does not
28
+ * answer. An attempt still in flight is cancelled through its signal.
29
+ */
30
+ close(): Promise<void>;
31
+ }
32
+ /** The client's phase. */
33
+ export type MllpClientState = "closed" | "closing" | "connected" | "connecting" | "idle" | "sending";
34
+ export interface MllpReconnectOptions {
35
+ /**
36
+ * Attempts after a failed one before the client closes. `Infinity` for no
37
+ * limit.
38
+ *
39
+ * @default 5
40
+ */
41
+ readonly attempts?: number;
42
+ /**
43
+ * Time to wait before `attempt` in milliseconds.
44
+ *
45
+ * @default full-jitter exponential backoff from 1 s, capped at 30 s
46
+ */
47
+ readonly delay?: (attempt: number) => number;
48
+ }
49
+ export interface MllpSendOptions {
50
+ /** Overrides the default send deadline: write plus acknowledgment wait. */
51
+ readonly timeoutMs?: number;
52
+ }
53
+ export interface MllpClientOptions {
54
+ /** Runtime adapter; e.g. `nodeSocket` from `@glion/mllp-client/node`. */
55
+ readonly socket: MllpSocket;
56
+ /**
57
+ * Time to wait for the connection to open, in milliseconds.
58
+ *
59
+ * @default 10_000
60
+ */
61
+ readonly connectTimeoutMs?: number;
62
+ /**
63
+ * Time to wait for an acknowledgment after sending, in milliseconds.
64
+ *
65
+ * @default 30_000
66
+ */
67
+ readonly sendTimeoutMs?: number;
68
+ /**
69
+ * Maximum bytes buffered while receiving one message. A remote system that
70
+ * never finishes one is dropped once it exceeds this.
71
+ *
72
+ * @default 16 MiB
73
+ */
74
+ readonly maxBufferedBytes?: number;
75
+ /**
76
+ * How the client dials again after a connection attempt fails. `false`: it
77
+ * dials once.
78
+ *
79
+ * @default 5 attempts with full-jitter backoff, about 30 seconds in all
80
+ */
81
+ readonly reconnect?: MllpReconnectOptions | false;
82
+ }
83
+ /**
84
+ * An acknowledgment that accepted the message: MSA-1 is `AA` or `CA`.
85
+ *
86
+ * A NAK never reaches here — `send()` throws the matching `@glion/ack`
87
+ * exception instead.
88
+ */
89
+ export interface MllpClientResponse {
90
+ /**
91
+ * MSH-10 of the acknowledgment itself, for tracing. MUST NOT be used for
92
+ * correlation; see `controlId`.
93
+ */
94
+ readonly id: string;
95
+ /**
96
+ * MSA-2: the MSH-10 of the message this one answers. HL7v2 names both
97
+ * fields Message Control ID. The only field correlation may use.
98
+ */
99
+ readonly controlId: string;
100
+ /** The acknowledgment, parsed. */
101
+ readonly tree: Root;
102
+ /** The acknowledgment as received, decoded to text. */
103
+ readonly raw: string;
104
+ /** MSA-3: the remote system's own diagnostic, when it gave one. */
105
+ readonly text?: string;
106
+ /** MSA-1: `AA` or `CA`. */
107
+ readonly code: AckSuccessCode;
108
+ }
109
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAIvC,+CAA+C;AAC/C,MAAM,WAAW,WAAW;IAC1B,oCAAoC;IACpC,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC,UAAU,CAAC,CAAC;IAC9C,kCAAkC;IAClC,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC,UAAU,CAAC,CAAC;CAC/C;AAED,qCAAqC;AACrC,MAAM,WAAW,UAAU;IACzB;;;;;OAKG;IACH,OAAO,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IACnD;;;;;OAKG;IACH,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAID,0BAA0B;AAC1B,MAAM,MAAM,eAAe,GACvB,QAAQ,GACR,SAAS,GACT,WAAW,GACX,YAAY,GACZ,MAAM,GACN,SAAS,CAAC;AAEd,MAAM,WAAW,oBAAoB;IACnC;;;;;OAKG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B;;;;OAIG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,CAAC;CAC9C;AAED,MAAM,WAAW,eAAe;IAC9B,2EAA2E;IAC3E,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,iBAAiB;IAChC,yEAAyE;IACzE,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC;;;;OAIG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC;;;;;OAKG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC;;;;;OAKG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,oBAAoB,GAAG,KAAK,CAAC;CACnD;AAED;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,kCAAkC;IAClC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,uDAAuD;IACvD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,mEAAmE;IACnE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,2BAA2B;IAC3B,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;CAC/B"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Reading a single value out of an HL7v2 tree.
3
+ *
4
+ * @module
5
+ */
6
+ import type { Root } from "@glion/ast";
7
+ /** The value at `path`, or `""` when the field is absent. */
8
+ export declare function read(tree: Root, path: string): string;
9
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAGvC,6DAA6D;AAC7D,wBAAgB,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAErD"}
package/package.json CHANGED
@@ -1,9 +1,8 @@
1
1
  {
2
2
  "name": "@glion/mllp-client",
3
- "version": "0.16.0",
4
- "description": "MLLP client for sending HL7v2 messages and receiving acknowledgments",
3
+ "version": "0.20.0",
4
+ "description": "Persistent, single-flight MLLP client for HL7v2",
5
5
  "keywords": [
6
- "client",
7
6
  "health",
8
7
  "healthcare",
9
8
  "hl7",
@@ -29,67 +28,59 @@
29
28
  "type": "module",
30
29
  "types": "./dist/index.d.ts",
31
30
  "exports": {
32
- ".": {
33
- "workerd": {
34
- "types": "./dist/runtimes/workers.d.ts",
35
- "import": "./dist/runtimes/workers.js"
36
- },
37
- "default": {
38
- "types": "./dist/index.d.ts",
39
- "import": "./dist/index.js"
40
- }
41
- },
42
- "./core": {
43
- "types": "./dist/core/index.d.ts",
44
- "import": "./dist/core/index.js"
45
- },
46
- "./node": {
47
- "types": "./dist/runtimes/node.d.ts",
48
- "import": "./dist/runtimes/node.js"
49
- },
50
- "./workers": {
51
- "types": "./dist/runtimes/workers.d.ts",
52
- "import": "./dist/runtimes/workers.js"
53
- }
31
+ ".": "./dist/index.js",
32
+ "./node": "./dist/runtime/node.js",
33
+ "./workers": "./dist/runtime/workers.js"
54
34
  },
55
35
  "publishConfig": {
56
36
  "access": "public"
57
37
  },
58
38
  "dependencies": {
59
- "@glion/ack": "0.16.0",
60
- "@glion/ast": "0.16.0",
61
- "@glion/mllp-transport": "0.16.0",
62
- "@glion/util-query": "0.16.0",
63
- "@glion/parser": "0.16.0"
39
+ "@glion/ack": "0.20.0",
40
+ "@glion/ast": "0.20.0",
41
+ "@glion/mllp-codec": "0.20.0",
42
+ "@glion/to-hl7v2": "0.20.0",
43
+ "@glion/util-query": "0.20.0",
44
+ "@glion/parser": "0.20.0",
45
+ "@glion/util-charset": "0.20.0"
64
46
  },
65
47
  "devDependencies": {
48
+ "@cloudflare/vitest-plugin": "1.1.13",
49
+ "@cloudflare/workers-types": "5.20260915.1",
50
+ "@stryker-mutator/core": "10.0.0",
51
+ "@stryker-mutator/vitest-runner": "10.0.0",
66
52
  "@types/node": "25.6.0",
67
- "@vitest/coverage-v8": "4.1.5",
53
+ "@vitest/coverage-v8": "4.1.11",
68
54
  "publint": "0.3.18",
55
+ "selfsigned": "5.5.0",
69
56
  "tsdown": "0.21.10",
70
57
  "typescript": "6.0.3",
71
- "vitest": "4.1.5",
72
- "wrangler": "^4.86.0",
73
- "@glion/hl7v2": "0.16.0",
74
- "@glion/mllp": "0.16.0",
75
- "@glion/mllp-ack": "0.16.0",
76
- "@glion/testing": "0.16.0",
77
- "@glion/tsconfig": "0.16.0",
78
- "@glion/check-readme": "0.16.0"
58
+ "vitest": "4.1.11",
59
+ "@glion/check-readme": "0.18.0",
60
+ "@glion/testing": "0.18.0",
61
+ "@glion/tsconfig": "0.18.0"
62
+ },
63
+ "peerDependencies": {
64
+ "@types/node": ">=22"
65
+ },
66
+ "peerDependenciesMeta": {
67
+ "@types/node": {
68
+ "optional": true
69
+ }
79
70
  },
80
71
  "engines": {
81
- "node": ">=20"
72
+ "node": ">=22"
82
73
  },
83
74
  "scripts": {
84
75
  "build": "tsdown && tsc --emitDeclarationOnly",
85
- "check-types": "tsc --noEmit",
76
+ "check-types": "tsc --noEmit && tsc --noEmit -p tests/tsconfig.json && tsc -p tsconfig.cloudflare.json",
86
77
  "check:readme": "glion-check-readme",
78
+ "mutate": "stryker run",
87
79
  "publint": "publint --strict",
88
- "test": "vitest run --project 'hl7v2-mllp-client (node)'",
89
- "test:bun": "bun --bun test test/core.test.ts",
90
- "test:cf": "vitest run --project 'hl7v2-mllp-client (workerd)'",
91
- "test:coverage": "vitest run --coverage --project 'hl7v2-mllp-client (node)'",
92
- "test:node": "vitest run --project 'hl7v2-mllp-client (node)'",
80
+ "test": "vitest run",
81
+ "test:cf": "vitest run --config vitest.workers.config.ts",
82
+ "test:coverage": "vitest run --coverage",
83
+ "test:integration": "vitest run --config vitest.integration.config.ts",
93
84
  "test:watch": "vitest"
94
85
  }
95
86
  }