@seriousme/opifex 2.2.0 → 2.4.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 (154) hide show
  1. package/README.md +7 -6
  2. package/bin/mqtt.ts +1 -1
  3. package/client/client.ts +62 -7
  4. package/client/context.ts +2 -2
  5. package/client/deps.ts +3 -3
  6. package/client/mod.ts +2 -2
  7. package/connNext/baseConnNext.ts +123 -0
  8. package/connNext/connNext.ts +44 -0
  9. package/deno/README.md +1 -1
  10. package/deno/denoConnToNext.ts +104 -0
  11. package/deno/tcpClient.ts +8 -24
  12. package/deno/tcpServer.test.ts +14 -103
  13. package/deno/tcpServer.ts +14 -6
  14. package/deno/tlsServer.test.ts +14 -58
  15. package/deno/tlsServer.ts +14 -6
  16. package/deno/wsServer.test.ts +15 -61
  17. package/deno/wsServer.ts +82 -32
  18. package/dev_utils/WebStreamEndpoint.ts +5 -0
  19. package/dev_utils/asyncStreamEndpoint.ts +5 -0
  20. package/dev_utils/asyncStreamPair.ts +109 -0
  21. package/dev_utils/asyncStreamPairToNext.ts +45 -0
  22. package/dev_utils/asyncStreamToNext.ts +64 -0
  23. package/dev_utils/connNextPair.test.ts +179 -0
  24. package/dev_utils/mockConn.ts +59 -29
  25. package/dev_utils/mockServer.ts +3 -4
  26. package/dev_utils/mod.ts +1 -2
  27. package/dev_utils/testClient.ts +64 -0
  28. package/dev_utils/webStreamPair.ts +3 -7
  29. package/dev_utils/webStreamPairToNext.ts +48 -0
  30. package/dev_utils/webStreamToNext.ts +54 -0
  31. package/dist/bin/mqtt.js +1 -1
  32. package/dist/bin/mqtt.js.map +1 -1
  33. package/dist/client/client.d.ts +24 -3
  34. package/dist/client/client.d.ts.map +1 -1
  35. package/dist/client/client.js +45 -5
  36. package/dist/client/client.js.map +1 -1
  37. package/dist/client/context.d.ts +2 -2
  38. package/dist/client/context.d.ts.map +1 -1
  39. package/dist/client/deps.d.ts +1 -1
  40. package/dist/client/deps.d.ts.map +1 -1
  41. package/dist/client/mod.d.ts +1 -1
  42. package/dist/client/mod.d.ts.map +1 -1
  43. package/dist/connNext/baseConnNext.d.ts +20 -0
  44. package/dist/connNext/baseConnNext.d.ts.map +1 -0
  45. package/dist/connNext/baseConnNext.js +95 -0
  46. package/dist/connNext/baseConnNext.js.map +1 -0
  47. package/dist/connNext/connNext.d.ts +43 -0
  48. package/dist/connNext/connNext.d.ts.map +1 -0
  49. package/dist/connNext/connNext.js +2 -0
  50. package/dist/connNext/connNext.js.map +1 -0
  51. package/dist/examples/authHandler.test.js +2 -2
  52. package/dist/examples/authHandler.test.js.map +1 -1
  53. package/dist/examples/mqtt+mqtts.test.d.ts +2 -0
  54. package/dist/examples/mqtt+mqtts.test.d.ts.map +1 -0
  55. package/dist/examples/mqtt+mqtts.test.js +104 -0
  56. package/dist/examples/mqtt+mqtts.test.js.map +1 -0
  57. package/dist/examples/mqtt.test.js +2 -2
  58. package/dist/examples/mqtt.test.js.map +1 -1
  59. package/dist/examples/mqtts.test.js +2 -2
  60. package/dist/examples/mqtts.test.js.map +1 -1
  61. package/dist/mqttConn/mqttConn.d.ts +5 -6
  62. package/dist/mqttConn/mqttConn.d.ts.map +1 -1
  63. package/dist/mqttConn/mqttConn.js +2 -3
  64. package/dist/mqttConn/mqttConn.js.map +1 -1
  65. package/dist/node/nodeSocketToNext.d.ts +17 -0
  66. package/dist/node/nodeSocketToNext.d.ts.map +1 -0
  67. package/dist/node/nodeSocketToNext.js +105 -0
  68. package/dist/node/nodeSocketToNext.js.map +1 -0
  69. package/dist/node/tcpClient.d.ts +4 -6
  70. package/dist/node/tcpClient.d.ts.map +1 -1
  71. package/dist/node/tcpClient.js +6 -21
  72. package/dist/node/tcpClient.js.map +1 -1
  73. package/dist/node/tcpServer.d.ts +8 -4
  74. package/dist/node/tcpServer.d.ts.map +1 -1
  75. package/dist/node/tcpServer.js +14 -6
  76. package/dist/node/tcpServer.js.map +1 -1
  77. package/dist/node/tlsServer.d.ts +7 -3
  78. package/dist/node/tlsServer.d.ts.map +1 -1
  79. package/dist/node/tlsServer.js +13 -5
  80. package/dist/node/tlsServer.js.map +1 -1
  81. package/dist/server/context.d.ts +5 -5
  82. package/dist/server/context.d.ts.map +1 -1
  83. package/dist/server/context.js +4 -1
  84. package/dist/server/context.js.map +1 -1
  85. package/dist/server/deps.d.ts +1 -1
  86. package/dist/server/deps.d.ts.map +1 -1
  87. package/dist/server/mod.d.ts +1 -1
  88. package/dist/server/mod.d.ts.map +1 -1
  89. package/dist/server/server.d.ts +3 -3
  90. package/dist/server/server.d.ts.map +1 -1
  91. package/dist/server/server.js +3 -3
  92. package/dist/utils/utils.d.ts +1 -2
  93. package/dist/utils/utils.d.ts.map +1 -1
  94. package/dist/utils/utils.js +3 -2
  95. package/dist/utils/utils.js.map +1 -1
  96. package/dist/web/webSocketToNext.d.ts +20 -0
  97. package/dist/web/webSocketToNext.d.ts.map +1 -0
  98. package/dist/web/webSocketToNext.js +125 -0
  99. package/dist/web/webSocketToNext.js.map +1 -0
  100. package/dist/web/wsClient.d.ts +3 -3
  101. package/dist/web/wsClient.d.ts.map +1 -1
  102. package/dist/web/wsClient.js +22 -7
  103. package/dist/web/wsClient.js.map +1 -1
  104. package/dist/web/wsClient.test.js +15 -0
  105. package/dist/web/wsClient.test.js.map +1 -1
  106. package/examples/README.md +21 -0
  107. package/examples/authHandler.test.ts +2 -2
  108. package/examples/mqtt+mqtts.test.ts +122 -0
  109. package/examples/mqtt.test.ts +2 -2
  110. package/examples/mqtts.test.ts +2 -2
  111. package/examples/webSocket.test.ts +10 -64
  112. package/examples/webSocketServer.ts +98 -0
  113. package/mqttConn/mqttConn.test.ts +6 -6
  114. package/mqttConn/mqttConn.ts +8 -9
  115. package/node/README.md +1 -1
  116. package/node/nodeSocketToNext.ts +124 -0
  117. package/node/tcpClient.ts +13 -27
  118. package/node/tcpServer.test.ts +12 -58
  119. package/node/tcpServer.ts +18 -8
  120. package/node/tlsServer.test.ts +11 -58
  121. package/node/tlsServer.ts +17 -7
  122. package/package.json +4 -3
  123. package/server/context.ts +9 -6
  124. package/server/deps.ts +1 -1
  125. package/server/mod.ts +1 -1
  126. package/server/server.ts +6 -6
  127. package/utils/utils.ts +3 -2
  128. package/web/webSocketToNext.ts +146 -0
  129. package/web/wsClient.test.ts +22 -0
  130. package/web/wsClient.ts +29 -9
  131. package/dev_utils/webStreamPair.test.ts +0 -171
  132. package/dist/node/wrapNodeSocket.d.ts +0 -12
  133. package/dist/node/wrapNodeSocket.d.ts.map +0 -1
  134. package/dist/node/wrapNodeSocket.js +0 -36
  135. package/dist/node/wrapNodeSocket.js.map +0 -1
  136. package/dist/socket/socket.d.ts +0 -58
  137. package/dist/socket/socket.d.ts.map +0 -1
  138. package/dist/socket/socket.js +0 -99
  139. package/dist/socket/socket.js.map +0 -1
  140. package/dist/web/webSocketStream.d.ts +0 -29
  141. package/dist/web/webSocketStream.d.ts.map +0 -1
  142. package/dist/web/webSocketStream.js +0 -69
  143. package/dist/web/webSocketStream.js.map +0 -1
  144. package/dist/web/wrapWebSocket.d.ts +0 -12
  145. package/dist/web/wrapWebSocket.d.ts.map +0 -1
  146. package/dist/web/wrapWebSocket.js +0 -41
  147. package/dist/web/wrapWebSocket.js.map +0 -1
  148. package/node/socket-node-stream.test.ts +0 -322
  149. package/node/socket-node-stream.ts +0 -174
  150. package/node/wrapNodeSocket.ts +0 -44
  151. package/socket/socket.test.ts +0 -91
  152. package/socket/socket.ts +0 -149
  153. package/web/webSocketStream.ts +0 -97
  154. package/web/wrapWebSocket.ts +0 -52
@@ -1,171 +0,0 @@
1
- import { test } from "node:test";
2
- import assert from "node:assert";
3
- import { createWebStreamPair } from "./webStreamPair.ts";
4
-
5
- test("Echo server shuts down cleanly when client closes input", async () => {
6
- const { input, output } = createWebStreamPair();
7
-
8
- const echoPromise = output.readable.pipeTo(output.writable);
9
-
10
- const writer = input.writable.getWriter();
11
- const reader = input.readable.getReader();
12
-
13
- // Client closes their side
14
- await writer.close();
15
-
16
- // The echo server's pipeTo should resolve and finish successfully
17
- await assert.doesNotReject(echoPromise);
18
-
19
- // The client's reader should now receive the end-of-stream signal
20
- const { done } = await reader.read();
21
- assert.strictEqual(done, true);
22
-
23
- writer.releaseLock();
24
- reader.releaseLock();
25
- });
26
-
27
- test("Data written to input.writable arrives at output.readable", async () => {
28
- const { input, output } = createWebStreamPair();
29
-
30
- const echoPromise = output.readable.pipeTo(output.writable);
31
-
32
- const writer = input.writable.getWriter();
33
- const reader = input.readable.getReader();
34
-
35
- const encoder = new TextEncoder();
36
- const decoder = new TextDecoder();
37
-
38
- // Write data to the input side
39
- await writer.write(encoder.encode("Hello streaming world!"));
40
- await writer.close(); // Close the stream after writing
41
-
42
- // The echo server's pipeTo should resolve and finish successfully
43
- await assert.doesNotReject(echoPromise);
44
-
45
- // Read the data from the input side
46
- const chunks: Uint8Array[] = [];
47
-
48
- while (true) {
49
- const { value, done } = await reader.read();
50
- if (done) break;
51
- if (value) chunks.push(value);
52
- }
53
-
54
- // Combine chunks and decode to string
55
- const totalLength = chunks.reduce((acc, chunk) => acc + chunk.length, 0);
56
- const resultUint8 = new Uint8Array(totalLength);
57
- let offset = 0;
58
- for (const chunk of chunks) {
59
- resultUint8.set(chunk, offset);
60
- offset += chunk.length;
61
- }
62
-
63
- const readText = decoder.decode(resultUint8);
64
-
65
- // Verify the text matches exactly
66
- assert.strictEqual(readText, "Hello streaming world!");
67
- reader.releaseLock();
68
- });
69
-
70
- test("Data can be written and read sequentially before closing", async () => {
71
- const { input, output } = createWebStreamPair();
72
- const echoPromise = output.readable.pipeTo(output.writable);
73
-
74
- const writer = input.writable.getWriter();
75
- const reader = input.readable.getReader();
76
-
77
- const encoder = new TextEncoder();
78
- const decoder = new TextDecoder();
79
-
80
- // 1. First Write & Read chunk
81
- await writer.write(encoder.encode("Chunk 1"));
82
- const result1 = await reader.read();
83
- assert.strictEqual(result1.done, false);
84
- assert.strictEqual(decoder.decode(result1.value), "Chunk 1");
85
-
86
- // 2. Second Write & Read chunk
87
- await writer.write(encoder.encode("Chunk 2"));
88
- const result2 = await reader.read();
89
- assert.strictEqual(result2.done, false);
90
- assert.strictEqual(decoder.decode(result2.value), "Chunk 2");
91
-
92
- // 3. Now we close the writable side mid-stream
93
- await writer.close();
94
-
95
- // The echo server's pipeTo should resolve and finish successfully
96
- await assert.doesNotReject(echoPromise);
97
-
98
- // 4. Verify that the readable side now registers the close signal
99
- const finalResult = await reader.read();
100
- assert.strictEqual(finalResult.done, true);
101
- assert.strictEqual(finalResult.value, undefined);
102
-
103
- writer.releaseLock();
104
- reader.releaseLock();
105
- });
106
-
107
- test("Client detects when the echo server abruptly closes its end", async () => {
108
- const { input, output } = createWebStreamPair();
109
- const encoder = new TextEncoder();
110
-
111
- // Set up a manual echo server so we can manipulate its controls
112
- const serverReader = output.readable.getReader();
113
- const serverWriter = output.writable.getWriter();
114
-
115
- // Start a basic manual loop in the background
116
- const serverLoop = (async () => {
117
- try {
118
- while (true) {
119
- const { value, done } = await serverReader.read();
120
- if (done) break;
121
- await serverWriter.write(value);
122
- }
123
- } finally {
124
- serverReader.releaseLock();
125
- serverWriter.releaseLock();
126
- }
127
- })();
128
-
129
- const clientWriter = input.writable.getWriter();
130
- const clientReader = input.readable.getReader();
131
-
132
- // --- Simulate Server Shutdown ---
133
- // The echo server decides to close its writing side out of nowhere
134
- try {
135
- await serverWriter.close();
136
- await serverReader.cancel();
137
- await serverLoop;
138
-
139
- const first = await clientReader.read();
140
- assert.strictEqual(first.done, true);
141
-
142
- await assert.rejects(
143
- () => clientWriter.write(encoder.encode("Is anyone there?")),
144
- /close|invalid/i,
145
- );
146
- } finally {
147
- clientWriter.releaseLock();
148
- clientReader.releaseLock();
149
- }
150
- });
151
-
152
- test("Repeated close and cancel calls are idempotent", async () => {
153
- const { input, output } = createWebStreamPair();
154
-
155
- const inputWriter = input.writable.getWriter();
156
- const inputReader = input.readable.getReader();
157
- const outputWriter = output.writable.getWriter();
158
- const outputReader = output.readable.getReader();
159
-
160
- await Promise.allSettled([
161
- inputWriter.close(),
162
- outputWriter.close(),
163
- inputReader.cancel(),
164
- outputReader.cancel(),
165
- ]);
166
-
167
- inputWriter.releaseLock();
168
- inputReader.releaseLock();
169
- outputWriter.releaseLock();
170
- outputReader.releaseLock();
171
- });
@@ -1,12 +0,0 @@
1
- /**
2
- * Utility functions for wrapping Node.js sockets into standard web streams.
3
- */
4
- import type { Socket } from "node:net";
5
- import type { SockConn } from "../socket/socket.ts";
6
- /**
7
- * Wraps a Node.js socket into a standard web streams-based socket connection
8
- * @param socket - The Node.js socket to wrap
9
- * @returns A socket connection object with readable/writable streams and close method
10
- */
11
- export declare function wrapNodeSocket(socket: Socket): SockConn;
12
- //# sourceMappingURL=wrapNodeSocket.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"wrapNodeSocket.d.ts","sourceRoot":"","sources":["../../node/wrapNodeSocket.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAEvC,OAAO,KAAK,EAAW,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAc7D;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,CAmBvD"}
@@ -1,36 +0,0 @@
1
- import { Readable, Writable } from "node:stream";
2
- /**
3
- * Closes a Node.js socket if it is not already closed
4
- * @param sock - The Node.js socket to close
5
- */
6
- function closer(sock) {
7
- // deno-coverage-ignore-start
8
- if (!sock.closed) {
9
- sock.end();
10
- }
11
- // deno-coverage-ignore-stop
12
- }
13
- /**
14
- * Wraps a Node.js socket into a standard web streams-based socket connection
15
- * @param socket - The Node.js socket to wrap
16
- * @returns A socket connection object with readable/writable streams and close method
17
- */
18
- export function wrapNodeSocket(socket) {
19
- const readable = Readable.toWeb(socket);
20
- const writable = Writable.toWeb(socket);
21
- // deno-coverage-ignore-start
22
- const remoteAddr = {
23
- hostname: socket.remoteAddress || "",
24
- port: socket.remotePort || 0,
25
- transport: "tcp",
26
- };
27
- // deno-coverage-ignore-stop
28
- const conn = {
29
- readable: readable,
30
- writable: writable,
31
- close: () => closer(socket),
32
- remoteAddr,
33
- };
34
- return conn;
35
- }
36
- //# sourceMappingURL=wrapNodeSocket.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"wrapNodeSocket.js","sourceRoot":"","sources":["../../node/wrapNodeSocket.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAGjD;;;GAGG;AACH,SAAS,MAAM,CAAC,IAAY;IAC1B,6BAA6B;IAC7B,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;QACjB,IAAI,CAAC,GAAG,EAAE,CAAC;IACb,CAAC;IACD,4BAA4B;AAC9B,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,MAAc;IAC3C,MAAM,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACxC,MAAM,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAExC,6BAA6B;IAC7B,MAAM,UAAU,GAAY;QAC1B,QAAQ,EAAE,MAAM,CAAC,aAAa,IAAI,EAAE;QACpC,IAAI,EAAE,MAAM,CAAC,UAAU,IAAI,CAAC;QAC5B,SAAS,EAAE,KAAK;KACjB,CAAC;IACF,4BAA4B;IAE5B,MAAM,IAAI,GAAa;QACrB,QAAQ,EAAE,QAAsC;QAChD,QAAQ,EAAE,QAAsC;QAChD,KAAK,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC;QAC3B,UAAU;KACX,CAAC;IACF,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -1,58 +0,0 @@
1
- /** Net addresses */
2
- export type NetAddr = {
3
- /** The IP-based transport protocol */
4
- transport: "tcp" | "udp";
5
- /** The hostname */
6
- hostname: string;
7
- /** The port number */
8
- port: number;
9
- };
10
- /** Unix addresses */
11
- export type UnixAddr = {
12
- /** The Unix domain socket transport protocol */
13
- transport: "unix" | "unixpacket";
14
- /** The file system path to the socket to connect to */
15
- path: string;
16
- };
17
- /** vSock addresses */
18
- export type VsockAddr = {
19
- /** The VSOCK transport protocol */
20
- transport: "vsock";
21
- /** The context identifier (CID) of the peer */
22
- cid: number;
23
- /** The port number */
24
- port: number;
25
- };
26
- /** Socket addresses */
27
- export type SockAddr = NetAddr | UnixAddr | VsockAddr;
28
- /** Socket connection descriptor. */
29
- export type SockConn = {
30
- /** The stream to read from */
31
- readable: ReadableStream<Uint8Array>;
32
- /** The stream to write to */
33
- writable: WritableStream<Uint8Array>;
34
- /** The callback to call on close */
35
- close: () => void;
36
- /** The local address of the connection */
37
- localAddr?: SockAddr;
38
- /** The remote address of the connection */
39
- remoteAddr?: SockAddr;
40
- };
41
- /** Connection class */
42
- export declare class Conn {
43
- reader: ReadableStreamDefaultReader<Uint8Array>;
44
- writer: WritableStreamDefaultWriter<Uint8Array>;
45
- closed: boolean;
46
- remoteAddr: SockAddr | undefined;
47
- closer: () => void;
48
- private leftover;
49
- /** Create a new Conn object from a SockConn */
50
- constructor(sockConn: SockConn);
51
- /** Read bytes from the connection */
52
- read(length: number): Promise<Uint8Array | null>;
53
- /** Write bytes to the connection */
54
- write(data: Uint8Array): Promise<number>;
55
- /** close the connection */
56
- close(): void;
57
- }
58
- //# sourceMappingURL=socket.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"socket.d.ts","sourceRoot":"","sources":["../../socket/socket.ts"],"names":[],"mappings":"AAAA,oBAAoB;AACpB,MAAM,MAAM,OAAO,GAAG;IACpB,sCAAsC;IACtC,SAAS,EAAE,KAAK,GAAG,KAAK,CAAC;IACzB,mBAAmB;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,sBAAsB;IACtB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AACF,qBAAqB;AACrB,MAAM,MAAM,QAAQ,GAAG;IACrB,gDAAgD;IAChD,SAAS,EAAE,MAAM,GAAG,YAAY,CAAC;IACjC,uDAAuD;IACvD,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AACF,sBAAsB;AACtB,MAAM,MAAM,SAAS,GAAG;IACtB,mCAAmC;IACnC,SAAS,EAAE,OAAO,CAAC;IACnB,+CAA+C;IAC/C,GAAG,EAAE,MAAM,CAAC;IACZ,sBAAsB;IACtB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AACF,uBAAuB;AACvB,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,QAAQ,GAAG,SAAS,CAAC;AACtD,oCAAoC;AACpC,MAAM,MAAM,QAAQ,GAAG;IACrB,8BAA8B;IAC9B,QAAQ,EAAE,cAAc,CAAC,UAAU,CAAC,CAAC;IACrC,6BAA6B;IAC7B,QAAQ,EAAE,cAAc,CAAC,UAAU,CAAC,CAAC;IACrC,oCAAoC;IACpC,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,0CAA0C;IAC1C,SAAS,CAAC,EAAE,QAAQ,CAAC;IACrB,2CAA2C;IAC3C,UAAU,CAAC,EAAE,QAAQ,CAAC;CACvB,CAAC;AAEF,uBAAuB;AACvB,qBAAa,IAAI;IACf,MAAM,EAAE,2BAA2B,CAAC,UAAU,CAAC,CAAC;IAChD,MAAM,EAAE,2BAA2B,CAAC,UAAU,CAAC,CAAC;IAChD,MAAM,EAAE,OAAO,CAAC;IAChB,UAAU,EAAE,QAAQ,GAAG,SAAS,CAAC;IACjC,MAAM,EAAE,MAAM,IAAI,CAAC;IAEnB,OAAO,CAAC,QAAQ,CAAiC;IAEjD,+CAA+C;IAC/C,YAAY,QAAQ,EAAE,QAAQ,EAQ7B;IAED,qCAAqC;IAC/B,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CA6CrD;IAED,oCAAoC;IAC9B,KAAK,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAW7C;IAED,2BAA2B;IAC3B,KAAK,SAsBJ;CACF"}
@@ -1,99 +0,0 @@
1
- /** Connection class */
2
- export class Conn {
3
- reader;
4
- writer;
5
- closed;
6
- remoteAddr;
7
- closer;
8
- leftover = new Uint8Array(0);
9
- /** Create a new Conn object from a SockConn */
10
- constructor(sockConn) {
11
- this.closed = false;
12
- this.reader = sockConn.readable.getReader();
13
- this.writer = sockConn.writable.getWriter();
14
- this.closer = sockConn.close.bind(sockConn);
15
- this.reader.closed.catch(() => { });
16
- this.writer.closed.catch(() => { });
17
- this.remoteAddr = sockConn.remoteAddr;
18
- }
19
- /** Read bytes from the connection */
20
- async read(length) {
21
- if (this.closed || length < 0) {
22
- return null;
23
- }
24
- if (length === 0) {
25
- return new Uint8Array(0);
26
- }
27
- const result = new Uint8Array(length);
28
- let bytesAccumulated = 0;
29
- // Do we have data from the previous read()
30
- if (this.leftover.length > 0) {
31
- const take = Math.min(this.leftover.length, length);
32
- result.set(this.leftover.subarray(0, take), bytesAccumulated);
33
- bytesAccumulated += take;
34
- this.leftover = this.leftover.subarray(take);
35
- }
36
- // Keep readin until we have enough data
37
- while (bytesAccumulated < length) {
38
- const { value, done } = await this.reader.read();
39
- if (value) {
40
- const needed = length - bytesAccumulated;
41
- if (value.length <= needed) {
42
- // We need the whole chunk
43
- result.set(value, bytesAccumulated);
44
- bytesAccumulated += value.length;
45
- }
46
- else {
47
- // Chunk is bigger than what we need
48
- result.set(value.subarray(0, needed), bytesAccumulated);
49
- bytesAccumulated += needed;
50
- // Save the rest for the next read() call
51
- this.leftover = value.subarray(needed);
52
- }
53
- }
54
- if (done) {
55
- // if the stream closed and not enough data was returned, return null
56
- return null;
57
- }
58
- }
59
- return result;
60
- }
61
- /** Write bytes to the connection */
62
- async write(data) {
63
- if (this.closed) {
64
- return Promise.reject(new Error("Connection closed"));
65
- }
66
- try {
67
- await this.writer.write(data);
68
- return data.length;
69
- }
70
- catch (err) {
71
- this.closed = true;
72
- throw err;
73
- }
74
- }
75
- /** close the connection */
76
- close() {
77
- if (!this.closed) {
78
- this.closed = true;
79
- // deno-coverage-ignore-start
80
- void this.writer.close().catch(() => {
81
- // ignore duplicate/late close attempts; the stream may already be closed
82
- });
83
- // deno-coverage-ignore-stop
84
- try {
85
- void this.reader.cancel().catch(() => {
86
- // ignore duplicate/late cancel attempts; the stream may already be closed
87
- });
88
- this.reader?.releaseLock();
89
- // deno-coverage-ignore
90
- }
91
- catch (_err) { /* swallow */ }
92
- try {
93
- this.closer();
94
- }
95
- catch (_err) { /* swallow */ }
96
- }
97
- }
98
- }
99
- //# sourceMappingURL=socket.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"socket.js","sourceRoot":"","sources":["../../socket/socket.ts"],"names":[],"mappings":"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"}
@@ -1,29 +0,0 @@
1
- /**
2
- * Utility functions for wrapping standard WebSockets into standard web streams.
3
- */
4
- export interface WebSocketConnection<T extends Uint8Array | string = Uint8Array | string> {
5
- readable: ReadableStream<T>;
6
- writable: WritableStream<T>;
7
- protocol: string;
8
- extensions: string;
9
- }
10
- export interface WebSocketCloseInfo {
11
- closeCode?: number;
12
- reason?: string;
13
- }
14
- export interface WebSocketStreamOptions {
15
- protocols?: string[];
16
- signal?: AbortSignal;
17
- }
18
- /**
19
- * [WebSocket](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket) with [Streams API](https://developer.mozilla.org/en-US/docs/Web/API/Streams_API)
20
- *
21
- * @see https://web.dev/websocketstream/
22
- */
23
- export declare class WebSocketStream<T extends Uint8Array | string = Uint8Array | string> {
24
- readonly opened: Promise<WebSocketConnection<T>>;
25
- readonly closed: Promise<WebSocketCloseInfo>;
26
- readonly close: (closeInfo?: WebSocketCloseInfo) => void;
27
- constructor(ws: WebSocket, options?: WebSocketStreamOptions);
28
- }
29
- //# sourceMappingURL=webSocketStream.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"webSocketStream.d.ts","sourceRoot":"","sources":["../../web/webSocketStream.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,mBAAmB,CAClC,CAAC,SAAS,UAAU,GAAG,MAAM,GAAG,UAAU,GAAG,MAAM;IAEnD,QAAQ,EAAE,cAAc,CAAC,CAAC,CAAC,CAAC;IAC5B,QAAQ,EAAE,cAAc,CAAC,CAAC,CAAC,CAAC;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,kBAAkB;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,sBAAsB;IACrC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED;;;;GAIG;AACH,qBAAa,eAAe,CAC1B,CAAC,SAAS,UAAU,GAAG,MAAM,GAAG,UAAU,GAAG,MAAM;IAEnD,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,CAAC;IAEjD,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,kBAAkB,CAAC,CAAC;IAE7C,QAAQ,CAAC,KAAK,EAAE,CAAC,SAAS,CAAC,EAAE,kBAAkB,KAAK,IAAI,CAAC;IAEzD,YAAY,EAAE,EAAE,SAAS,EAAE,OAAO,GAAE,sBAA2B,EA0D9D;CACF"}
@@ -1,69 +0,0 @@
1
- /**
2
- * Utility functions for wrapping standard WebSockets into standard web streams.
3
- */
4
- /**
5
- * [WebSocket](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket) with [Streams API](https://developer.mozilla.org/en-US/docs/Web/API/Streams_API)
6
- *
7
- * @see https://web.dev/websocketstream/
8
- */
9
- export class WebSocketStream {
10
- opened;
11
- closed;
12
- close;
13
- constructor(ws, options = {}) {
14
- if (options.signal?.aborted) {
15
- throw new DOMException("This operation was aborted", "AbortError");
16
- }
17
- const closeWithInfo = ({ closeCode: code, reason } = {}) => ws.close(code, reason);
18
- this.opened = new Promise((resolve, reject) => {
19
- ws.onopen = () => {
20
- resolve({
21
- readable: new ReadableStream({
22
- start(controller) {
23
- ws.onmessage = ({ data }) => {
24
- if (data instanceof ArrayBuffer) {
25
- controller.enqueue(new Uint8Array(data));
26
- }
27
- else {
28
- controller.enqueue(data);
29
- }
30
- };
31
- ws.onerror = (e) => controller.error(e);
32
- },
33
- cancel: closeWithInfo,
34
- }),
35
- writable: new WritableStream({
36
- write(chunk) {
37
- if (chunk instanceof Uint8Array) {
38
- ws.send(chunk.buffer);
39
- }
40
- else {
41
- ws.send(chunk);
42
- }
43
- },
44
- abort() {
45
- ws.close();
46
- },
47
- close: closeWithInfo,
48
- }),
49
- protocol: ws.protocol,
50
- extensions: ws.extensions,
51
- });
52
- ws.removeEventListener("error", reject);
53
- };
54
- ws.addEventListener("error", reject);
55
- });
56
- this.closed = new Promise((resolve, reject) => {
57
- ws.onclose = ({ code, reason }) => {
58
- resolve({ closeCode: code, reason });
59
- ws.removeEventListener("error", reject);
60
- };
61
- ws.addEventListener("error", reject);
62
- });
63
- if (options.signal) {
64
- options.signal.onabort = () => ws.close();
65
- }
66
- this.close = closeWithInfo;
67
- }
68
- }
69
- //# sourceMappingURL=webSocketStream.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"webSocketStream.js","sourceRoot":"","sources":["../../web/webSocketStream.ts"],"names":[],"mappings":"AAAA;;GAEG;AAqBH;;;;GAIG;AACH,MAAM,OAAO,eAAe;IAGjB,MAAM,CAAkC;IAExC,MAAM,CAA8B;IAEpC,KAAK,CAA2C;IAEzD,YAAY,EAAa,EAAE,OAAO,GAA2B,EAAE;QAC7D,IAAI,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC;YAC5B,MAAM,IAAI,YAAY,CAAC,4BAA4B,EAAE,YAAY,CAAC,CAAC;QACrE,CAAC;QACD,MAAM,aAAa,GAAG,CACpB,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,GAAuB,EAAE,EACpD,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAE5B,IAAI,CAAC,MAAM,GAAG,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC5C,EAAE,CAAC,MAAM,GAAG,GAAG,EAAE;gBACf,OAAO,CAAC;oBACN,QAAQ,EAAE,IAAI,cAAc,CAAI;wBAC9B,KAAK,CAAC,UAAU;4BACd,EAAE,CAAC,SAAS,GAAG,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE;gCAC1B,IAAI,IAAI,YAAY,WAAW,EAAE,CAAC;oCAChC,UAAU,CAAC,OAAO,CAAC,IAAI,UAAU,CAAC,IAAI,CAAM,CAAC,CAAC;gCAChD,CAAC;qCAAM,CAAC;oCACN,UAAU,CAAC,OAAO,CAAC,IAAS,CAAC,CAAC;gCAChC,CAAC;4BACH,CAAC,CAAC;4BACF,EAAE,CAAC,OAAO,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;wBAC1C,CAAC;wBACD,MAAM,EAAE,aAAa;qBACtB,CAAC;oBACF,QAAQ,EAAE,IAAI,cAAc,CAAI;wBAC9B,KAAK,CAAC,KAAK;4BACT,IAAI,KAAK,YAAY,UAAU,EAAE,CAAC;gCAChC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,MAAqB,CAAC,CAAC;4BACvC,CAAC;iCAAM,CAAC;gCACN,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;4BACjB,CAAC;wBACH,CAAC;wBACD,KAAK;4BACH,EAAE,CAAC,KAAK,EAAE,CAAC;wBACb,CAAC;wBACD,KAAK,EAAE,aAAa;qBACrB,CAAC;oBACF,QAAQ,EAAE,EAAE,CAAC,QAAQ;oBACrB,UAAU,EAAE,EAAE,CAAC,UAAU;iBAC1B,CAAC,CAAC;gBACH,EAAE,CAAC,mBAAmB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YAC1C,CAAC,CAAC;YACF,EAAE,CAAC,gBAAgB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,MAAM,GAAG,IAAI,OAAO,CAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAChE,EAAE,CAAC,OAAO,GAAG,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE;gBAChC,OAAO,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;gBACrC,EAAE,CAAC,mBAAmB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YAC1C,CAAC,CAAC;YACF,EAAE,CAAC,gBAAgB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;QAEH,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YACnB,OAAO,CAAC,MAAM,CAAC,OAAO,GAAG,GAAG,EAAE,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC;QAC5C,CAAC;QAED,IAAI,CAAC,KAAK,GAAG,aAAa,CAAC;IAC7B,CAAC;CACF"}
@@ -1,12 +0,0 @@
1
- import type { SockConn } from "../socket/socket.ts";
2
- export type HostnamePort = {
3
- hostname?: string;
4
- port?: string | number;
5
- };
6
- /**
7
- * Wraps a WebSocketStream socket into a standard web streams-based socket connection
8
- * @param ws - The WebSocket to wrap
9
- * @returns A SockConn object
10
- */
11
- export declare function wrapWebSocket(ws: WebSocket, remoteAddr?: HostnamePort): Promise<SockConn>;
12
- //# sourceMappingURL=wrapWebSocket.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"wrapWebSocket.d.ts","sourceRoot":"","sources":["../../web/wrapWebSocket.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAGpD,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CACxB,CAAC;AAYF;;;;GAIG;AACH,wBAAsB,aAAa,CACjC,EAAE,EAAE,SAAS,EACb,UAAU,CAAC,EAAE,YAAY,GACxB,OAAO,CAAC,QAAQ,CAAC,CAqBnB"}
@@ -1,41 +0,0 @@
1
- /**
2
- * Utility functions for wrapping WebSocketStream sockets into standard web streams.
3
- */
4
- import { WebSocketStream } from "./webSocketStream.js";
5
- import { logger } from "../utils/logger.js";
6
- /**
7
- * Closes a WebSocketStream socket if it is not already closed
8
- * @param sock - The WebSocketStream socket to close
9
- */
10
- async function closer(stream) {
11
- if (!await stream.closed) {
12
- stream.close();
13
- }
14
- }
15
- /**
16
- * Wraps a WebSocketStream socket into a standard web streams-based socket connection
17
- * @param ws - The WebSocket to wrap
18
- * @returns A SockConn object
19
- */
20
- export async function wrapWebSocket(ws, remoteAddr) {
21
- ws.binaryType = "arraybuffer";
22
- const wsstream = new WebSocketStream(ws);
23
- logger.debug("created wsstream");
24
- const stream = await wsstream.opened;
25
- logger.debug("wsstream is opened");
26
- const readable = stream.readable;
27
- const writable = stream.writable;
28
- const { hostname = "localhost", port = 0 } = remoteAddr || {};
29
- const conn = {
30
- readable: readable,
31
- writable: writable,
32
- close: () => closer(wsstream),
33
- remoteAddr: {
34
- hostname,
35
- port: Number(port),
36
- transport: "tcp",
37
- },
38
- };
39
- return conn;
40
- }
41
- //# sourceMappingURL=wrapWebSocket.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"wrapWebSocket.js","sourceRoot":"","sources":["../../web/wrapWebSocket.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAO5C;;;GAGG;AACH,KAAK,UAAU,MAAM,CAAC,MAAuB;IAC3C,IAAI,CAAC,MAAM,MAAM,CAAC,MAAM,EAAE,CAAC;QACzB,MAAM,CAAC,KAAK,EAAE,CAAC;IACjB,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,EAAa,EACb,UAAyB;IAEzB,EAAE,CAAC,UAAU,GAAG,aAAa,CAAC;IAC9B,MAAM,QAAQ,GAAG,IAAI,eAAe,CAAa,EAAE,CAAC,CAAC;IACrD,MAAM,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;IACjC,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC;IACrC,MAAM,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC;IACnC,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;IACjC,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;IACjC,MAAM,EAAE,QAAQ,GAAG,WAAW,EAAE,IAAI,GAAG,CAAC,EAAE,GAAG,UAAU,IAAI,EAAE,CAAC;IAE9D,MAAM,IAAI,GAAa;QACrB,QAAQ,EAAE,QAAsC;QAChD,QAAQ,EAAE,QAAsC;QAChD,KAAK,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC;QAC7B,UAAU,EAAE;YACV,QAAQ;YACR,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC;YAClB,SAAS,EAAE,KAAK;SACjB;KACF,CAAC;IACF,OAAO,IAAI,CAAC;AACd,CAAC"}