@kuralle-syrinx/server-websocket 4.4.1 → 4.5.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 (132) hide show
  1. package/dist/backchannel-cue-fixtures.d.ts +4 -0
  2. package/dist/backchannel-cue-fixtures.d.ts.map +1 -0
  3. package/dist/backchannel-cue-fixtures.js +25 -0
  4. package/dist/backchannel-cue-fixtures.js.map +1 -0
  5. package/dist/background-audio.d.ts +59 -0
  6. package/dist/background-audio.d.ts.map +1 -0
  7. package/dist/background-audio.js +248 -0
  8. package/dist/background-audio.js.map +1 -0
  9. package/dist/browser-opus.d.ts +12 -0
  10. package/dist/browser-opus.d.ts.map +1 -0
  11. package/dist/browser-opus.js +48 -0
  12. package/dist/browser-opus.js.map +1 -0
  13. package/dist/carrier-commands.d.ts +124 -0
  14. package/dist/carrier-commands.d.ts.map +1 -0
  15. package/dist/carrier-commands.js +193 -0
  16. package/dist/carrier-commands.js.map +1 -0
  17. package/dist/edge-telnyx.d.ts +37 -0
  18. package/dist/edge-telnyx.d.ts.map +1 -0
  19. package/dist/edge-telnyx.js +320 -0
  20. package/dist/edge-telnyx.js.map +1 -0
  21. package/dist/edge-twilio.d.ts +31 -0
  22. package/dist/edge-twilio.d.ts.map +1 -0
  23. package/dist/edge-twilio.js +286 -0
  24. package/dist/edge-twilio.js.map +1 -0
  25. package/dist/edge.d.ts +71 -0
  26. package/dist/edge.d.ts.map +1 -0
  27. package/dist/edge.js +560 -0
  28. package/dist/edge.js.map +1 -0
  29. package/dist/inbound-audio.d.ts +13 -0
  30. package/dist/inbound-audio.d.ts.map +1 -0
  31. package/dist/inbound-audio.js +66 -0
  32. package/dist/inbound-audio.js.map +1 -0
  33. package/dist/index.d.ts +81 -0
  34. package/dist/index.d.ts.map +1 -0
  35. package/dist/index.js +718 -0
  36. package/dist/index.js.map +1 -0
  37. package/dist/json-message.d.ts +7 -0
  38. package/dist/json-message.d.ts.map +1 -0
  39. package/dist/json-message.js +41 -0
  40. package/dist/json-message.js.map +1 -0
  41. package/dist/outbound-playout-pipeline.d.ts +53 -0
  42. package/dist/outbound-playout-pipeline.d.ts.map +1 -0
  43. package/dist/outbound-playout-pipeline.js +148 -0
  44. package/dist/outbound-playout-pipeline.js.map +1 -0
  45. package/dist/paced-playout.d.ts +42 -0
  46. package/dist/paced-playout.d.ts.map +1 -0
  47. package/dist/paced-playout.js +151 -0
  48. package/dist/paced-playout.js.map +1 -0
  49. package/dist/playout-progress.d.ts +26 -0
  50. package/dist/playout-progress.d.ts.map +1 -0
  51. package/dist/playout-progress.js +64 -0
  52. package/dist/playout-progress.js.map +1 -0
  53. package/dist/session-store.d.ts +39 -0
  54. package/dist/session-store.d.ts.map +1 -0
  55. package/dist/session-store.js +80 -0
  56. package/dist/session-store.js.map +1 -0
  57. package/dist/smartpbx.d.ts +47 -0
  58. package/dist/smartpbx.d.ts.map +1 -0
  59. package/dist/smartpbx.js +437 -0
  60. package/dist/smartpbx.js.map +1 -0
  61. package/dist/telnyx-codec.d.ts +41 -0
  62. package/dist/telnyx-codec.d.ts.map +1 -0
  63. package/dist/telnyx-codec.js +114 -0
  64. package/dist/telnyx-codec.js.map +1 -0
  65. package/dist/telnyx.d.ts +52 -0
  66. package/dist/telnyx.d.ts.map +1 -0
  67. package/dist/telnyx.js +550 -0
  68. package/dist/telnyx.js.map +1 -0
  69. package/dist/test-helpers.d.ts +20 -0
  70. package/dist/test-helpers.d.ts.map +1 -0
  71. package/dist/test-helpers.js +242 -0
  72. package/dist/test-helpers.js.map +1 -0
  73. package/dist/transport-helpers.d.ts +12 -0
  74. package/dist/transport-helpers.d.ts.map +1 -0
  75. package/dist/transport-helpers.js +90 -0
  76. package/dist/transport-helpers.js.map +1 -0
  77. package/dist/transport-host.d.ts +56 -0
  78. package/dist/transport-host.d.ts.map +1 -0
  79. package/dist/transport-host.js +110 -0
  80. package/dist/transport-host.js.map +1 -0
  81. package/dist/turn-metrics.d.ts +79 -0
  82. package/dist/turn-metrics.d.ts.map +1 -0
  83. package/dist/turn-metrics.js +208 -0
  84. package/dist/turn-metrics.js.map +1 -0
  85. package/dist/twilio-auth.d.ts +12 -0
  86. package/dist/twilio-auth.d.ts.map +1 -0
  87. package/dist/twilio-auth.js +44 -0
  88. package/dist/twilio-auth.js.map +1 -0
  89. package/dist/twilio.d.ts +56 -0
  90. package/dist/twilio.d.ts.map +1 -0
  91. package/dist/twilio.js +511 -0
  92. package/dist/twilio.js.map +1 -0
  93. package/dist/websocket-close.d.ts +12 -0
  94. package/dist/websocket-close.d.ts.map +1 -0
  95. package/dist/websocket-close.js +58 -0
  96. package/dist/websocket-close.js.map +1 -0
  97. package/dist/websocket-lifecycle.d.ts +29 -0
  98. package/dist/websocket-lifecycle.d.ts.map +1 -0
  99. package/dist/websocket-lifecycle.js +87 -0
  100. package/dist/websocket-lifecycle.js.map +1 -0
  101. package/dist/websocket-upgrade.d.ts +9 -0
  102. package/dist/websocket-upgrade.d.ts.map +1 -0
  103. package/dist/websocket-upgrade.js +91 -0
  104. package/dist/websocket-upgrade.js.map +1 -0
  105. package/dist/wire-carrier-control.d.ts +27 -0
  106. package/dist/wire-carrier-control.d.ts.map +1 -0
  107. package/dist/wire-carrier-control.js +116 -0
  108. package/dist/wire-carrier-control.js.map +1 -0
  109. package/package.json +32 -11
  110. package/src/admission-control.test.ts +270 -0
  111. package/src/background-audio.test.ts +224 -0
  112. package/src/browser-opus.test.ts +41 -0
  113. package/src/browser-pacing.test.ts +440 -0
  114. package/src/carrier-commands.test.ts +198 -0
  115. package/src/edge-telnyx.test.ts +333 -0
  116. package/src/edge-twilio.test.ts +293 -0
  117. package/src/edge.test.ts +727 -0
  118. package/src/graceful-drain.test.ts +306 -0
  119. package/src/inbound-audio.test.ts +58 -0
  120. package/src/index.test.ts +2078 -0
  121. package/src/outbound-playout-pipeline.test.ts +314 -0
  122. package/src/paced-playout.test.ts +247 -0
  123. package/src/playout-progress.test.ts +56 -0
  124. package/src/session-store.test.ts +274 -0
  125. package/src/smartpbx.test.ts +986 -0
  126. package/src/telnyx.test.ts +1633 -0
  127. package/src/transport-host.test.ts +51 -0
  128. package/src/turn-metrics.test.ts +503 -0
  129. package/src/twilio-auth.test.ts +36 -0
  130. package/src/twilio.test.ts +1274 -0
  131. package/src/websocket-close.test.ts +63 -0
  132. package/src/websocket-lifecycle.test.ts +49 -0
@@ -0,0 +1,63 @@
1
+ // SPDX-License-Identifier: MIT
2
+
3
+ import { describe, expect, it } from "vitest";
4
+ import { WebSocket } from "ws";
5
+ import { sendJsonCapped } from "./websocket-close.js";
6
+
7
+ interface FakeSocket {
8
+ readyState: number;
9
+ bufferedAmount: number;
10
+ sent: string[];
11
+ closed: { code: number; reason: string } | null;
12
+ }
13
+
14
+ function makeSocket(overrides: Partial<FakeSocket> = {}): WebSocket {
15
+ const socket: FakeSocket & { send(d: string): void; close(c: number, r: string): void; once(): void } = {
16
+ readyState: WebSocket.OPEN,
17
+ bufferedAmount: 0,
18
+ sent: [],
19
+ closed: null,
20
+ ...overrides,
21
+ send(data: string) { this.sent.push(data); },
22
+ close(code: number, reason: string) { this.closed = { code, reason }; this.readyState = WebSocket.CLOSING; },
23
+ once() { /* close-cleanup listener — unused in these paths */ },
24
+ };
25
+ return socket as unknown as WebSocket;
26
+ }
27
+
28
+ describe("sendJsonCapped", () => {
29
+ it("serializes and sends when OPEN and under the buffer cap", () => {
30
+ const socket = makeSocket();
31
+ const ok = sendJsonCapped(socket, { event: "media", n: 1 }, 1_000);
32
+ expect(ok).toBe(true);
33
+ expect((socket as unknown as FakeSocket).sent).toEqual([JSON.stringify({ event: "media", n: 1 })]);
34
+ });
35
+
36
+ it("sends nothing and returns false when the socket is not OPEN", () => {
37
+ const socket = makeSocket({ readyState: WebSocket.CONNECTING });
38
+ const ok = sendJsonCapped(socket, { event: "media" }, 1_000);
39
+ expect(ok).toBe(false);
40
+ expect((socket as unknown as FakeSocket).sent).toHaveLength(0);
41
+ });
42
+
43
+ it("closes 1013 and drops the message when the send would exceed the buffer cap", () => {
44
+ const payload = { event: "media", blob: "x".repeat(100) };
45
+ const cap = 50; // far below the serialized size
46
+ const socket = makeSocket({ bufferedAmount: 0 });
47
+ const ok = sendJsonCapped(socket, payload, cap);
48
+ expect(ok).toBe(false);
49
+ const fake = socket as unknown as FakeSocket;
50
+ expect(fake.sent).toHaveLength(0);
51
+ expect(fake.closed?.code).toBe(1013);
52
+ });
53
+
54
+ it("accounts for already-buffered bytes against the cap", () => {
55
+ const data = JSON.stringify({ event: "media" });
56
+ const cap = Buffer.byteLength(data, "utf8") + 5;
57
+ // Already near the cap: adding this message tips it over.
58
+ const socket = makeSocket({ bufferedAmount: 10 });
59
+ const ok = sendJsonCapped(socket, { event: "media" }, cap);
60
+ expect(ok).toBe(false);
61
+ expect((socket as unknown as FakeSocket).closed?.code).toBe(1013);
62
+ });
63
+ });
@@ -0,0 +1,49 @@
1
+ // SPDX-License-Identifier: MIT
2
+
3
+ import { afterEach, describe, expect, it, vi } from "vitest";
4
+ import { installGracefulShutdown, type GracefulClosable } from "./websocket-lifecycle.js";
5
+
6
+ describe("installGracefulShutdown", () => {
7
+ afterEach(() => {
8
+ process.removeAllListeners("SIGTERM");
9
+ process.removeAllListeners("SIGINT");
10
+ });
11
+
12
+ it("drains the server gracefully on a termination signal", async () => {
13
+ const closeCalls: Array<{ graceful?: boolean; drainDeadlineMs?: number }> = [];
14
+ const server: GracefulClosable = {
15
+ close: async (opts) => {
16
+ closeCalls.push(opts ?? {});
17
+ },
18
+ };
19
+ const onClosed = vi.fn();
20
+ installGracefulShutdown(server, { drainDeadlineMs: 7000, onClosed });
21
+
22
+ process.emit("SIGTERM");
23
+ await vi.waitFor(() => expect(onClosed).toHaveBeenCalledTimes(1));
24
+
25
+ expect(closeCalls).toEqual([{ graceful: true, drainDeadlineMs: 7000 }]);
26
+ });
27
+
28
+ it("is idempotent — a second signal during shutdown does not double-close", async () => {
29
+ let closeCount = 0;
30
+ const server: GracefulClosable = { close: async () => { closeCount += 1; } };
31
+ installGracefulShutdown(server, { signals: ["SIGTERM"] });
32
+
33
+ process.emit("SIGTERM");
34
+ process.emit("SIGTERM");
35
+ await vi.waitFor(() => expect(closeCount).toBe(1));
36
+ expect(closeCount).toBe(1);
37
+ });
38
+
39
+ it("the disposer removes the signal handler", async () => {
40
+ let closeCount = 0;
41
+ const server: GracefulClosable = { close: async () => { closeCount += 1; } };
42
+ const dispose = installGracefulShutdown(server, { signals: ["SIGINT"] });
43
+ dispose();
44
+
45
+ process.emit("SIGINT");
46
+ await new Promise((r) => setTimeout(r, 10));
47
+ expect(closeCount).toBe(0);
48
+ });
49
+ });