@seriousme/opifex 2.2.0 → 2.3.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 (142) hide show
  1. package/README.md +7 -6
  2. package/bin/mqtt.ts +1 -1
  3. package/client/client.ts +57 -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/connNext.ts +44 -0
  8. package/deno/README.md +1 -1
  9. package/deno/denoConnToNext.ts +104 -0
  10. package/deno/tcpClient.ts +8 -24
  11. package/deno/tcpServer.test.ts +14 -103
  12. package/deno/tcpServer.ts +14 -6
  13. package/deno/tlsServer.test.ts +14 -58
  14. package/deno/tlsServer.ts +14 -6
  15. package/deno/wsServer.test.ts +15 -61
  16. package/deno/wsServer.ts +74 -32
  17. package/dev_utils/asyncStreamPair.ts +114 -0
  18. package/dev_utils/asyncStreamToNext.ts +171 -0
  19. package/dev_utils/connNextPair.test.ts +179 -0
  20. package/dev_utils/mockConn.ts +115 -29
  21. package/dev_utils/mockServer.ts +3 -4
  22. package/dev_utils/mod.ts +1 -2
  23. package/dev_utils/testClient.ts +64 -0
  24. package/dev_utils/webStreamToNext.ts +187 -0
  25. package/dist/bin/mqtt.js +1 -1
  26. package/dist/bin/mqtt.js.map +1 -1
  27. package/dist/client/client.d.ts +20 -3
  28. package/dist/client/client.d.ts.map +1 -1
  29. package/dist/client/client.js +42 -5
  30. package/dist/client/client.js.map +1 -1
  31. package/dist/client/context.d.ts +2 -2
  32. package/dist/client/context.d.ts.map +1 -1
  33. package/dist/client/deps.d.ts +1 -1
  34. package/dist/client/deps.d.ts.map +1 -1
  35. package/dist/client/mod.d.ts +1 -1
  36. package/dist/client/mod.d.ts.map +1 -1
  37. package/dist/connNext/connNext.d.ts +43 -0
  38. package/dist/connNext/connNext.d.ts.map +1 -0
  39. package/dist/connNext/connNext.js +2 -0
  40. package/dist/connNext/connNext.js.map +1 -0
  41. package/dist/examples/authHandler.test.js +2 -2
  42. package/dist/examples/authHandler.test.js.map +1 -1
  43. package/dist/examples/mqtt+mqtts.test.d.ts +2 -0
  44. package/dist/examples/mqtt+mqtts.test.d.ts.map +1 -0
  45. package/dist/examples/mqtt+mqtts.test.js +104 -0
  46. package/dist/examples/mqtt+mqtts.test.js.map +1 -0
  47. package/dist/examples/mqtt.test.js +2 -2
  48. package/dist/examples/mqtt.test.js.map +1 -1
  49. package/dist/examples/mqtts.test.js +2 -2
  50. package/dist/examples/mqtts.test.js.map +1 -1
  51. package/dist/mqttConn/mqttConn.d.ts +5 -6
  52. package/dist/mqttConn/mqttConn.d.ts.map +1 -1
  53. package/dist/mqttConn/mqttConn.js +2 -3
  54. package/dist/mqttConn/mqttConn.js.map +1 -1
  55. package/dist/node/nodeSocketToNext.d.ts +20 -0
  56. package/dist/node/nodeSocketToNext.d.ts.map +1 -0
  57. package/dist/node/nodeSocketToNext.js +161 -0
  58. package/dist/node/nodeSocketToNext.js.map +1 -0
  59. package/dist/node/tcpClient.d.ts +4 -6
  60. package/dist/node/tcpClient.d.ts.map +1 -1
  61. package/dist/node/tcpClient.js +6 -21
  62. package/dist/node/tcpClient.js.map +1 -1
  63. package/dist/node/tcpServer.d.ts +8 -4
  64. package/dist/node/tcpServer.d.ts.map +1 -1
  65. package/dist/node/tcpServer.js +14 -6
  66. package/dist/node/tcpServer.js.map +1 -1
  67. package/dist/node/tlsServer.d.ts +7 -3
  68. package/dist/node/tlsServer.d.ts.map +1 -1
  69. package/dist/node/tlsServer.js +13 -5
  70. package/dist/node/tlsServer.js.map +1 -1
  71. package/dist/server/context.d.ts +5 -5
  72. package/dist/server/context.d.ts.map +1 -1
  73. package/dist/server/context.js +4 -1
  74. package/dist/server/context.js.map +1 -1
  75. package/dist/server/deps.d.ts +1 -1
  76. package/dist/server/deps.d.ts.map +1 -1
  77. package/dist/server/mod.d.ts +1 -1
  78. package/dist/server/mod.d.ts.map +1 -1
  79. package/dist/server/server.d.ts +3 -3
  80. package/dist/server/server.d.ts.map +1 -1
  81. package/dist/server/server.js +3 -3
  82. package/dist/utils/utils.d.ts +1 -2
  83. package/dist/utils/utils.d.ts.map +1 -1
  84. package/dist/utils/utils.js +3 -2
  85. package/dist/utils/utils.js.map +1 -1
  86. package/dist/web/webSocketToNext.d.ts +3 -0
  87. package/dist/web/webSocketToNext.d.ts.map +1 -0
  88. package/dist/web/webSocketToNext.js +160 -0
  89. package/dist/web/webSocketToNext.js.map +1 -0
  90. package/dist/web/wsClient.d.ts +3 -3
  91. package/dist/web/wsClient.d.ts.map +1 -1
  92. package/dist/web/wsClient.js +19 -5
  93. package/dist/web/wsClient.js.map +1 -1
  94. package/dist/web/wsClient.test.js +15 -0
  95. package/dist/web/wsClient.test.js.map +1 -1
  96. package/examples/README.md +21 -0
  97. package/examples/authHandler.test.ts +2 -2
  98. package/examples/mqtt+mqtts.test.ts +122 -0
  99. package/examples/mqtt.test.ts +2 -2
  100. package/examples/mqtts.test.ts +2 -2
  101. package/examples/webSocket.test.ts +10 -64
  102. package/examples/webSocketServer.ts +98 -0
  103. package/mqttConn/mqttConn.test.ts +6 -6
  104. package/mqttConn/mqttConn.ts +8 -9
  105. package/node/README.md +1 -1
  106. package/node/{socket-node-stream.ts → nodeSocketToNext.ts} +78 -65
  107. package/node/tcpClient.ts +13 -27
  108. package/node/tcpServer.test.ts +12 -58
  109. package/node/tcpServer.ts +18 -8
  110. package/node/tlsServer.test.ts +11 -58
  111. package/node/tlsServer.ts +17 -7
  112. package/package.json +3 -2
  113. package/server/context.ts +9 -6
  114. package/server/deps.ts +1 -1
  115. package/server/mod.ts +1 -1
  116. package/server/server.ts +6 -6
  117. package/utils/utils.ts +3 -2
  118. package/web/webSocketToNext.ts +183 -0
  119. package/web/wsClient.test.ts +22 -0
  120. package/web/wsClient.ts +21 -8
  121. package/dist/node/wrapNodeSocket.d.ts +0 -12
  122. package/dist/node/wrapNodeSocket.d.ts.map +0 -1
  123. package/dist/node/wrapNodeSocket.js +0 -36
  124. package/dist/node/wrapNodeSocket.js.map +0 -1
  125. package/dist/socket/socket.d.ts +0 -58
  126. package/dist/socket/socket.d.ts.map +0 -1
  127. package/dist/socket/socket.js +0 -99
  128. package/dist/socket/socket.js.map +0 -1
  129. package/dist/web/webSocketStream.d.ts +0 -29
  130. package/dist/web/webSocketStream.d.ts.map +0 -1
  131. package/dist/web/webSocketStream.js +0 -69
  132. package/dist/web/webSocketStream.js.map +0 -1
  133. package/dist/web/wrapWebSocket.d.ts +0 -12
  134. package/dist/web/wrapWebSocket.d.ts.map +0 -1
  135. package/dist/web/wrapWebSocket.js +0 -41
  136. package/dist/web/wrapWebSocket.js.map +0 -1
  137. package/node/socket-node-stream.test.ts +0 -322
  138. package/node/wrapNodeSocket.ts +0 -44
  139. package/socket/socket.test.ts +0 -91
  140. package/socket/socket.ts +0 -149
  141. package/web/webSocketStream.ts +0 -97
  142. package/web/wrapWebSocket.ts +0 -52
@@ -1,4 +1,4 @@
1
- export type { SockAddr, SockConn } from "../socket/socket.ts";
1
+ export type { ConnAddr, ConnNext } from "../connNext/connNext.ts";
2
2
  export { MqttConn } from "../mqttConn/mqttConn.ts";
3
3
  export type { ClientSubscription, ExtPublishPacket, Persistence, ShareName, } from "../persistence/persistence.ts";
4
4
  export { MemoryPersistence } from "../persistence/memory/memoryPersistence.ts";
@@ -1 +1 @@
1
- {"version":3,"file":"deps.d.ts","sourceRoot":"","sources":["../../server/deps.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACnD,YAAY,EACV,kBAAkB,EAClB,gBAAgB,EAChB,WAAW,EACX,SAAS,GACV,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,iBAAiB,EAAE,MAAM,4CAA4C,CAAC;AAC/E,YAAY,EACV,SAAS,EACT,UAAU,EACV,QAAQ,EACR,aAAa,EACb,iBAAiB,EACjB,aAAa,EACb,gBAAgB,EAChB,QAAQ,EACR,aAAa,EACb,aAAa,EACb,aAAa,EACb,YAAY,EACZ,aAAa,EACb,aAAa,EACb,eAAe,EACf,YAAY,EACZ,YAAY,EACZ,GAAG,EACH,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,cAAc,EACd,KAAK,EACL,WAAW,EACX,cAAc,EACd,iBAAiB,GAClB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,oBAAoB,EACpB,SAAS,EACT,gBAAgB,EAChB,UAAU,EACV,UAAU,GACX,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC1C,OAAO,EACL,MAAM,EACN,YAAY,EACZ,qBAAqB,EACrB,YAAY,EACZ,kBAAkB,EAClB,eAAe,EACf,MAAM,EACN,QAAQ,EACR,yBAAyB,EACzB,gBAAgB,GACjB,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"deps.d.ts","sourceRoot":"","sources":["../../server/deps.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACnD,YAAY,EACV,kBAAkB,EAClB,gBAAgB,EAChB,WAAW,EACX,SAAS,GACV,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,iBAAiB,EAAE,MAAM,4CAA4C,CAAC;AAC/E,YAAY,EACV,SAAS,EACT,UAAU,EACV,QAAQ,EACR,aAAa,EACb,iBAAiB,EACjB,aAAa,EACb,gBAAgB,EAChB,QAAQ,EACR,aAAa,EACb,aAAa,EACb,aAAa,EACb,YAAY,EACZ,aAAa,EACb,aAAa,EACb,eAAe,EACf,YAAY,EACZ,YAAY,EACZ,GAAG,EACH,YAAY,EACZ,eAAe,EACf,YAAY,EACZ,cAAc,EACd,KAAK,EACL,WAAW,EACX,cAAc,EACd,iBAAiB,GAClB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,oBAAoB,EACpB,SAAS,EACT,gBAAgB,EAChB,UAAU,EACV,UAAU,GACX,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC1C,OAAO,EACL,MAAM,EACN,YAAY,EACZ,qBAAqB,EACrB,YAAY,EACZ,kBAAkB,EAClB,eAAe,EACf,MAAM,EACN,QAAQ,EACR,yBAAyB,EACzB,gBAAgB,GACjB,MAAM,iBAAiB,CAAC"}
@@ -3,7 +3,7 @@
3
3
  * @module
4
4
  */
5
5
  export { ReasonCode } from "./deps.ts";
6
- export type { ConnectPacket, Persistence, ShareName, SockConn, Topic, } from "./deps.ts";
6
+ export type { ConnectPacket, ConnNext, Persistence, ShareName, Topic, } from "./deps.ts";
7
7
  export { MqttServer } from "./server.ts";
8
8
  export type { MqttServerOptions } from "./server.ts";
9
9
  export { Context } from "./context.ts";
@@ -1 +1 @@
1
- {"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../../server/mod.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,YAAY,EACV,aAAa,EACb,WAAW,EACX,SAAS,EACT,QAAQ,EACR,KAAK,GACN,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,YAAY,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,YAAY,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../../server/mod.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,YAAY,EACV,aAAa,EACb,QAAQ,EACR,WAAW,EACX,SAAS,EACT,KAAK,GACN,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,YAAY,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,YAAY,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC"}
@@ -1,5 +1,5 @@
1
1
  import type { Handlers } from "./context.ts";
2
- import type { Persistence, SockConn } from "./deps.ts";
2
+ import type { ConnNext, Persistence } from "./deps.ts";
3
3
  import type { Configuration, ConfigurationInput } from "./config.ts";
4
4
  /**
5
5
  * Configuration options for creating an MqttServer instance.
@@ -37,10 +37,10 @@ export declare class MqttServer {
37
37
  constructor({ persistence, handlers, configuration, }: MqttServerOptions);
38
38
  /**
39
39
  * Serve a new client connection.
40
- * @param {SockConn} conn - The socket connection to serve.
40
+ * @param conn - The socket connection to serve.
41
41
  * @returns {Promise<void>} A promise that resolves when the connection is closed.
42
42
  */
43
- serve(conn: SockConn): Promise<void>;
43
+ serve(conn: ConnNext): Promise<void>;
44
44
  /**
45
45
  * Close the server and all active client connections.
46
46
  * @param {boolean} cleanUp - If true, clean up client sessions on close.
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../server/server.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,KAAK,EAAE,WAAW,EAAa,QAAQ,EAAS,MAAM,WAAW,CAAC;AAGzE,OAAO,KAAK,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AA4DrE;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,gFAAgF;IAChF,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,qEAAqE;IACrE,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,kCAAkC;IAClC,aAAa,CAAC,EAAE,kBAAkB,CAAC;CACpC,CAAC;AAEF;;;;;;;;;;GAUG;AACH,qBAAa,UAAU;IACrB,gEAAgE;IAChE,QAAQ,EAAE,QAAQ,CAAC;IACnB,oEAAoE;IACpE,WAAW,EAAE,WAAW,CAAC;IACzB,oEAAoE;IACpE,aAAa,EAAE,aAAa,CAAC;IAE7B;;;OAGG;IACH,YAAY,EACV,WAAW,EACX,QAAQ,EACR,aAAa,GACd,EAAE,iBAAiB,EAYnB;IAED;;;;OAIG;IACG,KAAK,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CA2BzC;IAED;;;OAGG;IACG,KAAK,CAAC,OAAO,GAAE,OAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CASnD;CACF"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../server/server.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAoB,MAAM,WAAW,CAAC;AAGzE,OAAO,KAAK,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AA4DrE;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,gFAAgF;IAChF,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,qEAAqE;IACrE,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,kCAAkC;IAClC,aAAa,CAAC,EAAE,kBAAkB,CAAC;CACpC,CAAC;AAEF;;;;;;;;;;GAUG;AACH,qBAAa,UAAU;IACrB,gEAAgE;IAChE,QAAQ,EAAE,QAAQ,CAAC;IACnB,oEAAoE;IACpE,WAAW,EAAE,WAAW,CAAC;IACzB,oEAAoE;IACpE,aAAa,EAAE,aAAa,CAAC;IAE7B;;;OAGG;IACH,YAAY,EACV,WAAW,EACX,QAAQ,EACR,aAAa,GACd,EAAE,iBAAiB,EAYnB;IAED;;;;OAIG;IACG,KAAK,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CA2BzC;IAED;;;OAGG;IACG,KAAK,CAAC,OAAO,GAAE,OAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CASnD;CACF"}
@@ -4,8 +4,8 @@ import { handlePacket } from "./handlers/handlePacket.js";
4
4
  import { createConfiguration } from "./config.js";
5
5
  /**
6
6
  * Default preconnect handler that unconditionally permits all connections.
7
- * @param {SockConn} _conn - The connection.
8
- * @returns {boolean} Always returns true
7
+ * @param _conn - The connection.
8
+ * @returns Always returns true
9
9
  */
10
10
  const defaultPreconnect = (_conn) => (true);
11
11
  /**
@@ -73,7 +73,7 @@ export class MqttServer {
73
73
  }
74
74
  /**
75
75
  * Serve a new client connection.
76
- * @param {SockConn} conn - The socket connection to serve.
76
+ * @param conn - The socket connection to serve.
77
77
  * @returns {Promise<void>} A promise that resolves when the connection is closed.
78
78
  */
79
79
  async serve(conn) {
@@ -1,4 +1,3 @@
1
- import { setTimeout as delay } from "node:timers/promises";
2
- export { delay };
1
+ export declare function delay(ms: number): Promise<void>;
3
2
  export declare const noop: () => void;
4
3
  //# sourceMappingURL=utils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../utils/utils.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,UAAU,IAAI,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,KAAK,EAAE,CAAC;AAEjB,eAAO,MAAM,IAAI,YAAW,CAAC"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../utils/utils.ts"],"names":[],"mappings":"AAKA,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/C;AAED,eAAO,MAAM,IAAI,YAAW,CAAC"}
@@ -2,7 +2,8 @@
2
2
  * This file contains utilities used throughout the project too small to
3
3
  * deserve their own dedicated files.
4
4
  */
5
- import { setTimeout as delay } from "node:timers/promises";
6
- export { delay };
5
+ export function delay(ms) {
6
+ return new Promise((resolve) => setTimeout(resolve, ms));
7
+ }
7
8
  export const noop = () => { };
8
9
  //# sourceMappingURL=utils.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../utils/utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,IAAI,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,KAAK,EAAE,CAAC;AAEjB,MAAM,CAAC,MAAM,IAAI,GAAG,GAAG,EAAE,GAAE,CAAC,CAAC"}
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../utils/utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,UAAU,KAAK,CAAC,EAAU;IAC9B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAC3D,CAAC;AAED,MAAM,CAAC,MAAM,IAAI,GAAG,GAAG,EAAE,GAAE,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { ConnAddr, ConnNext } from "../connNext/connNext.ts";
2
+ export declare function webSocketToNext(ws: WebSocket, remoteAddr?: ConnAddr): Promise<ConnNext>;
3
+ //# sourceMappingURL=webSocketToNext.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webSocketToNext.d.ts","sourceRoot":"","sources":["../../web/webSocketToNext.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAElE,wBAAsB,eAAe,CACnC,EAAE,EAAE,SAAS,EACb,UAAU,CAAC,EAAE,QAAQ,GACpB,OAAO,CAAC,QAAQ,CAAC,CAiLnB"}
@@ -0,0 +1,160 @@
1
+ export async function webSocketToNext(ws, remoteAddr) {
2
+ ws.binaryType = "arraybuffer";
3
+ const messageQueue = [];
4
+ let queueOffset = 0;
5
+ const readResolvers = [];
6
+ const notifyWaiters = () => {
7
+ while (readResolvers.length > 0) {
8
+ const resolve = readResolvers.shift();
9
+ resolve?.();
10
+ }
11
+ };
12
+ // helper to check if websocket is Open
13
+ const ensureOpen = () => {
14
+ if (ws.readyState === WebSocket.OPEN) {
15
+ return Promise.resolve();
16
+ }
17
+ if (ws.readyState >= WebSocket.CLOSING) {
18
+ return Promise.reject(new Error("WebSocket is closing or closed"));
19
+ }
20
+ return new Promise((resolve, reject) => {
21
+ const onOpen = () => {
22
+ cleanup();
23
+ resolve();
24
+ };
25
+ const onError = (err) => {
26
+ cleanup();
27
+ reject(err);
28
+ };
29
+ const onClose = () => {
30
+ cleanup();
31
+ reject(new Error("WebSocket closed before opening"));
32
+ };
33
+ const cleanup = () => {
34
+ ws.removeEventListener("open", onOpen);
35
+ ws.removeEventListener("error", onError);
36
+ ws.removeEventListener("close", onClose);
37
+ };
38
+ ws.addEventListener("open", onOpen);
39
+ ws.addEventListener("error", onError);
40
+ ws.addEventListener("close", onClose);
41
+ });
42
+ };
43
+ ws.addEventListener("message", (event) => {
44
+ let chunk;
45
+ if (typeof event.data === "string") {
46
+ chunk = new TextEncoder().encode(event.data);
47
+ }
48
+ else if (event.data instanceof ArrayBuffer) {
49
+ chunk = new Uint8Array(event.data);
50
+ }
51
+ else {
52
+ return;
53
+ }
54
+ messageQueue.push(chunk);
55
+ notifyWaiters();
56
+ });
57
+ ws.addEventListener("close", notifyWaiters);
58
+ ws.addEventListener("error", notifyWaiters);
59
+ const getBufferedBytes = () => {
60
+ let total = 0;
61
+ for (let i = 0; i < messageQueue.length; i++) {
62
+ total += i === 0
63
+ ? messageQueue[i].byteLength - queueOffset
64
+ : messageQueue[i].byteLength;
65
+ }
66
+ return total;
67
+ };
68
+ const waitForData = () => {
69
+ return new Promise((resolve) => {
70
+ readResolvers.push(resolve);
71
+ });
72
+ };
73
+ const connNext = {
74
+ remoteAddr,
75
+ localAddr: undefined,
76
+ async read(length) {
77
+ try {
78
+ await ensureOpen();
79
+ }
80
+ catch {
81
+ return null;
82
+ }
83
+ if (getBufferedBytes() === 0 && ws.readyState >= WebSocket.CLOSING) {
84
+ return null;
85
+ }
86
+ while (getBufferedBytes() === 0) {
87
+ if (ws.readyState >= WebSocket.CLOSING)
88
+ return null;
89
+ await waitForData();
90
+ }
91
+ if (length === undefined) {
92
+ const firstChunk = messageQueue.shift();
93
+ const result = firstChunk.subarray(queueOffset);
94
+ queueOffset = 0;
95
+ return result;
96
+ }
97
+ while (getBufferedBytes() < length) {
98
+ if (ws.readyState >= WebSocket.CLOSING) {
99
+ return null;
100
+ }
101
+ await waitForData();
102
+ }
103
+ const result = new Uint8Array(length);
104
+ let bytesCopied = 0;
105
+ while (bytesCopied < length && messageQueue.length > 0) {
106
+ const currentChunk = messageQueue[0];
107
+ const bytesNeeded = length - bytesCopied;
108
+ const bytesAvailable = currentChunk.byteLength - queueOffset;
109
+ if (bytesAvailable <= bytesNeeded) {
110
+ result.set(currentChunk.subarray(queueOffset), bytesCopied);
111
+ bytesCopied += bytesAvailable;
112
+ messageQueue.shift();
113
+ queueOffset = 0;
114
+ }
115
+ else {
116
+ result.set(currentChunk.subarray(queueOffset, queueOffset + bytesNeeded), bytesCopied);
117
+ bytesCopied += bytesNeeded;
118
+ queueOffset += bytesNeeded;
119
+ }
120
+ }
121
+ return result;
122
+ },
123
+ async write(data) {
124
+ await ensureOpen();
125
+ if (data instanceof Uint8Array) {
126
+ ws.send(data.buffer);
127
+ }
128
+ else {
129
+ ws.send(data);
130
+ }
131
+ const HIGH_WATER_MARK = 64 * 1024;
132
+ while (ws.bufferedAmount > HIGH_WATER_MARK) {
133
+ if (ws.readyState >= WebSocket.CLOSING) {
134
+ throw new Error("WebSocket closed while writing");
135
+ }
136
+ await new Promise((resolve) => setTimeout(resolve, 10));
137
+ }
138
+ },
139
+ close() {
140
+ try {
141
+ ws.close();
142
+ }
143
+ catch {
144
+ /* swallow */
145
+ }
146
+ notifyWaiters();
147
+ },
148
+ async *[Symbol.asyncIterator]() {
149
+ while (true) {
150
+ const chunk = await this.read();
151
+ if (chunk === null)
152
+ break;
153
+ yield chunk;
154
+ }
155
+ },
156
+ };
157
+ await ensureOpen();
158
+ return connNext;
159
+ }
160
+ //# sourceMappingURL=webSocketToNext.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webSocketToNext.js","sourceRoot":"","sources":["../../web/webSocketToNext.ts"],"names":[],"mappings":"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"}
@@ -4,16 +4,16 @@
4
4
  * @module
5
5
  */
6
6
  import { Client } from "../client/client.ts";
7
- import type { SockConn } from "../client/deps.ts";
7
+ import type { ConnNext } from "../client/deps.ts";
8
8
  /**
9
9
  * WsClient extends the Client class to provide WebSocket based clients
10
10
  * it is used by the MQTTclient to connect to the broker
11
11
  * see the /examples folder for an example
12
12
  */
13
13
  export declare class WsClient extends Client {
14
- /** create a websocket and wrap it in a SockConn */
14
+ /** create a websocket and wrap it in a ConnNext */
15
15
  private establishSocket;
16
16
  /** createConn provides support for both "ws:" and "wss:" URLs */
17
- protected createConn(): Promise<SockConn>;
17
+ protected createConn(): Promise<ConnNext>;
18
18
  }
19
19
  //# sourceMappingURL=wsClient.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"wsClient.d.ts","sourceRoot":"","sources":["../../web/wsClient.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAE7C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAGlD;;;;GAIG;AACH,qBAAa,QAAS,SAAQ,MAAM;IAClC,mDAAmD;YACrC,eAAe;IAM7B,iEAAiE;IACjE,UAAmB,UAAU,IAAI,OAAO,CAAC,QAAQ,CAAC,CAUjD;CACF"}
1
+ {"version":3,"file":"wsClient.d.ts","sourceRoot":"","sources":["../../web/wsClient.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAE7C,OAAO,KAAK,EAAE,QAAQ,EAAW,MAAM,mBAAmB,CAAC;AAG3D;;;;GAIG;AACH,qBAAa,QAAS,SAAQ,MAAM;IAClC,mDAAmD;YACrC,eAAe;IAmB7B,iEAAiE;IACjE,UAAmB,UAAU,IAAI,OAAO,CAAC,QAAQ,CAAC,CAUjD;CACF"}
@@ -5,18 +5,32 @@
5
5
  */
6
6
  import { Client } from "../client/client.js";
7
7
  import { logger } from "../client/deps.js";
8
- import { wrapWebSocket } from "./wrapWebSocket.js";
8
+ import { webSocketToNext } from "./webSocketToNext.js";
9
9
  /**
10
10
  * WsClient extends the Client class to provide WebSocket based clients
11
11
  * it is used by the MQTTclient to connect to the broker
12
12
  * see the /examples folder for an example
13
13
  */
14
14
  export class WsClient extends Client {
15
- /** create a websocket and wrap it in a SockConn */
15
+ /** create a websocket and wrap it in a ConnNext */
16
16
  async establishSocket(url) {
17
- const ws = new WebSocket(url);
18
- const conn = await wrapWebSocket(ws);
19
- return conn;
17
+ try {
18
+ const urlObj = new URL(url);
19
+ const remoteAddr = {
20
+ transport: "tcp",
21
+ hostname: urlObj.hostname,
22
+ port: Number(urlObj.port || 0),
23
+ };
24
+ const ws = new WebSocket(url);
25
+ const connNext = await webSocketToNext(ws, remoteAddr);
26
+ return connNext;
27
+ }
28
+ catch (error) {
29
+ const message = error instanceof ErrorEvent
30
+ ? ` because of ${error.message}`
31
+ : "";
32
+ throw new Error(`Failed to connect to WebSocket at ${url}${message}`);
33
+ }
20
34
  }
21
35
  /** createConn provides support for both "ws:" and "wss:" URLs */
22
36
  createConn() {
@@ -1 +1 @@
1
- {"version":3,"file":"wsClient.js","sourceRoot":"","sources":["../../web/wsClient.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAE3C,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD;;;;GAIG;AACH,MAAM,OAAO,QAAS,SAAQ,MAAM;IAClC,mDAAmD;IAC3C,KAAK,CAAC,eAAe,CAAC,GAAW;QACvC,MAAM,EAAE,GAAG,IAAI,SAAS,CAAC,GAAG,CAAC,CAAC;QAC9B,MAAM,IAAI,GAAG,MAAM,aAAa,CAAC,EAAE,CAAC,CAAC;QACrC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,iEAAiE;IAC9C,UAAU;QAC3B,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC,UAAU,CAAC;QACxE,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,KAAK,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC1E,MAAM,IAAI,GAAG,QAAQ,IAAI,OAAO,CAAC;QAEjC,MAAM,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QACvC,IAAI,QAAQ,KAAK,KAAK,IAAI,QAAQ,KAAK,MAAM,EAAE,CAAC;YAC9C,OAAO,IAAI,CAAC,eAAe,CAAC,GAAG,QAAQ,KAAK,QAAQ,IAAI,IAAI,GAAG,IAAI,EAAE,CAAC,CAAC;QACzE,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,yBAAyB,QAAQ,EAAE,CAAC,CAAC;IACvD,CAAC;CACF"}
1
+ {"version":3,"file":"wsClient.js","sourceRoot":"","sources":["../../web/wsClient.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAE3C,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD;;;;GAIG;AACH,MAAM,OAAO,QAAS,SAAQ,MAAM;IAClC,mDAAmD;IAC3C,KAAK,CAAC,eAAe,CAAC,GAAW;QACvC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;YAC5B,MAAM,UAAU,GAAY;gBAC1B,SAAS,EAAE,KAAK;gBAChB,QAAQ,EAAE,MAAM,CAAC,QAAQ;gBACzB,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,CAAC;aAC/B,CAAC;YACF,MAAM,EAAE,GAAG,IAAI,SAAS,CAAC,GAAG,CAAC,CAAC;YAC9B,MAAM,QAAQ,GAAG,MAAM,eAAe,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;YACvD,OAAO,QAAQ,CAAC;QAClB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,OAAO,GAAG,KAAK,YAAY,UAAU;gBACzC,CAAC,CAAC,eAAe,KAAK,CAAC,OAAO,EAAE;gBAChC,CAAC,CAAC,EAAE,CAAC;YACP,MAAM,IAAI,KAAK,CAAC,qCAAqC,GAAG,GAAG,OAAO,EAAE,CAAC,CAAC;QACxE,CAAC;IACH,CAAC;IAED,iEAAiE;IAC9C,UAAU;QAC3B,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC,UAAU,CAAC;QACxE,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,KAAK,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC1E,MAAM,IAAI,GAAG,QAAQ,IAAI,OAAO,CAAC;QAEjC,MAAM,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QACvC,IAAI,QAAQ,KAAK,KAAK,IAAI,QAAQ,KAAK,MAAM,EAAE,CAAC;YAC9C,OAAO,IAAI,CAAC,eAAe,CAAC,GAAG,QAAQ,KAAK,QAAQ,IAAI,IAAI,GAAG,IAAI,EAAE,CAAC,CAAC;QACzE,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,yBAAyB,QAAQ,EAAE,CAAC,CAAC;IACvD,CAAC;CACF"}
@@ -17,4 +17,19 @@ test("Web: Test createConn - unsupported protocol", async () => {
17
17
  message: "Unsupported protocol: ftp:",
18
18
  }, "Should throw an error when an unsupported protocol is provided");
19
19
  });
20
+ test("Web: Test createConn - unsupported host", async () => {
21
+ const client = new WsClient();
22
+ // Use an host protocol to trigger the ws error
23
+ const invalidParams = {
24
+ url: new URL("ws://test.invalid"),
25
+ numberOfRetries: 0,
26
+ };
27
+ // Assert that connect rejects with the specific error
28
+ await assert.rejects(async () => {
29
+ await client.connect(invalidParams);
30
+ }, {
31
+ name: "Error",
32
+ message: /^Failed to connect to WebSocket/,
33
+ }, "Should throw an error when an unreachable host is provided");
34
+ });
20
35
  //# sourceMappingURL=wsClient.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"wsClient.test.js","sourceRoot":"","sources":["../../web/wsClient.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,0DAA0D;AAC1D,IAAI,CAAC,6CAA6C,EAAE,KAAK,IAAI,EAAE;IAC7D,MAAM,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;IAE9B,+EAA+E;IAC/E,MAAM,aAAa,GAAG;QACpB,GAAG,EAAE,IAAI,GAAG,CAAC,sBAAsB,CAAC;QACpC,eAAe,EAAE,CAAC;KACnB,CAAC;IAEF,6EAA6E;IAC7E,MAAM,MAAM,CAAC,OAAO,CAClB,KAAK,IAAI,EAAE;QACT,MAAM,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;IACtC,CAAC,EACD;QACE,IAAI,EAAE,OAAO;QACb,OAAO,EAAE,4BAA4B;KACtC,EACD,gEAAgE,CACjE,CAAC;AACJ,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"wsClient.test.js","sourceRoot":"","sources":["../../web/wsClient.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,0DAA0D;AAC1D,IAAI,CAAC,6CAA6C,EAAE,KAAK,IAAI,EAAE;IAC7D,MAAM,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;IAE9B,+EAA+E;IAC/E,MAAM,aAAa,GAAG;QACpB,GAAG,EAAE,IAAI,GAAG,CAAC,sBAAsB,CAAC;QACpC,eAAe,EAAE,CAAC;KACnB,CAAC;IAEF,6EAA6E;IAC7E,MAAM,MAAM,CAAC,OAAO,CAClB,KAAK,IAAI,EAAE;QACT,MAAM,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;IACtC,CAAC,EACD;QACE,IAAI,EAAE,OAAO;QACb,OAAO,EAAE,4BAA4B;KACtC,EACD,gEAAgE,CACjE,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,yCAAyC,EAAE,KAAK,IAAI,EAAE;IACzD,MAAM,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;IAE9B,+CAA+C;IAC/C,MAAM,aAAa,GAAG;QACpB,GAAG,EAAE,IAAI,GAAG,CAAC,mBAAmB,CAAC;QACjC,eAAe,EAAE,CAAC;KACnB,CAAC;IAEF,sDAAsD;IACtD,MAAM,MAAM,CAAC,OAAO,CAClB,KAAK,IAAI,EAAE;QACT,MAAM,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;IACtC,CAAC,EACD;QACE,IAAI,EAAE,OAAO;QACb,OAAO,EAAE,iCAAiC;KAC3C,EACD,4DAA4D,CAC7D,CAAC;AACJ,CAAC,CAAC,CAAC"}
@@ -0,0 +1,21 @@
1
+ # Opifex Examples
2
+
3
+ This folder contains examples for [Opifex](../README.md). It serves as a
4
+ practical reference for setting up client/server communication, transport
5
+ handling, authentication, and persistence.
6
+
7
+ ## Index
8
+
9
+ - [`mqtt.test.ts`](mqtt.test.ts) — basic MQTT publish/subscribe flow over TCP
10
+ with in-memory persistence.
11
+ - [`mqtts.test.ts`](mqtts.test.ts) — TLS-based MQTT example using SQLite
12
+ persistence.
13
+ - [`mqtt+mqtts.test.ts`](mqtt+mqtts.test.ts) — Publish over TLS, subscribe over
14
+ TCP.
15
+ - [`authHandler.test.ts`](authHandler.test.ts) — MQTT v5 authentication example
16
+ with a custom `processAuth` handler.
17
+ - [`webSocket.test.ts`](webSocket.test.ts) — WebSocket-based client/server flow
18
+ for Deno.
19
+ - [`webSocketServer.ts`](webSocketServer.ts) — simple WebSocket serving example
20
+ for browser-based MQTT usage.
21
+ - [`public/`](public) — static assets used by the browser-facing WebSocket demo.
@@ -112,7 +112,7 @@ test("Test MQTTv5 Auth using TCP client and server", async function () {
112
112
  const client = new TcpClient();
113
113
  client.onAuth = clientProcessAuth;
114
114
  await client.connect(params);
115
- logger.info("Client connected to server at", client.url);
115
+ logger.info("Client connected to server at", client.url.toString());
116
116
 
117
117
  const publishSet: { topic: string; qos: QoS }[] = [
118
118
  { topic: "t0@q0", qos: 0 },
@@ -160,5 +160,5 @@ test("Test MQTTv5 Auth using TCP client and server", async function () {
160
160
  }
161
161
 
162
162
  logger.info("Stop server");
163
- server.stop();
163
+ await server.stop();
164
164
  });
@@ -0,0 +1,122 @@
1
+ import { test } from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { TcpClient } from "@seriousme/opifex/tcpClient";
4
+ import { TlsServer } from "@seriousme/opifex/tlsServer";
5
+ import { MqttServer } from "@seriousme/opifex/server";
6
+ import { delay, logger, LogLevel } from "@seriousme/opifex/utils";
7
+ import type { PublishPacket, QoS } from "@seriousme/opifex/mqttPacket";
8
+ import { generateLocalhostCerts } from "../dev_utils/generateCert.ts";
9
+ import { TcpServer } from "@seriousme/opifex/tcpServer";
10
+
11
+ logger.level(LogLevel.info);
12
+
13
+ test("Test pubSub using TLS client and a TCP client", async function () {
14
+ // the localhost certs generate here are great for testing but lack securiity
15
+ // use something like LetsEncrypt for any serious server
16
+ // generateLocalhostCerts is a dev tool and relies on node-forge as a (dev)dependency
17
+ const { key, cert, caCert } = generateLocalhostCerts();
18
+ // first create the mqttServer, so we can pass it to multiple protocol servers
19
+ const mqttServer = new MqttServer({});
20
+
21
+ const tlsServer = new TlsServer({ port: 0, key, cert }, mqttServer);
22
+ const tcpServer = new TcpServer({ port: 0 }, mqttServer);
23
+ // .start() combines instance creation and async initialization
24
+ tlsServer.start();
25
+ tcpServer.start();
26
+
27
+ logger.info(
28
+ `TLS server running on port: ${tlsServer.port}, address: ${tlsServer.address}`,
29
+ );
30
+ logger.info(
31
+ `TCP server running on port: ${tcpServer.port}, address: ${tcpServer.address}`,
32
+ );
33
+ // pick the correct hostname
34
+ const tlsHostname = tlsServer.address === "0.0.0.0"
35
+ ? "127.0.0.1"
36
+ : tlsServer.address;
37
+ const tcpHostname = tcpServer.address === "0.0.0.0"
38
+ ? "127.0.0.1"
39
+ : tcpServer.address;
40
+
41
+ const tlsParams = {
42
+ url: new URL(`mqtts://${tlsHostname}:${tlsServer.port}`),
43
+ clientId: "I am a TLS client",
44
+ numberOfRetries: 0,
45
+ // since we signed our server cert ourselves we need to add the caCert
46
+ // this is not required if you use a public Certificate Authority
47
+ caCerts: [caCert],
48
+ };
49
+
50
+ const tcpParams = {
51
+ url: new URL(`mqtt://${tcpHostname}:${tcpServer.port}`),
52
+ clientId: "I am a TCP client",
53
+ numberOfRetries: 0,
54
+ };
55
+
56
+ const tlsClient = new TcpClient(); // TcpClient can also handle TLS
57
+ const tcpClient = new TcpClient();
58
+ await tlsClient.connect(tlsParams);
59
+ await tcpClient.connect(tcpParams);
60
+ logger.info("tlsClient connected to server at", tlsClient.url.toString());
61
+ logger.info("tcpClient connected to server at", tcpClient.url.toString());
62
+
63
+ const publishSet: { topic: string; qos: QoS }[] = [
64
+ { topic: "t0@q0", qos: 0 },
65
+ { topic: "t1@q0", qos: 0 },
66
+ { topic: "t2@q0", qos: 0 },
67
+ { topic: "t0@q1", qos: 1 },
68
+ { topic: "t1@q1", qos: 1 },
69
+ { topic: "t2@q1", qos: 1 },
70
+ { topic: "t0@q2", qos: 2 },
71
+ { topic: "t1@q2", qos: 2 },
72
+ { topic: "t2@q2", qos: 2 },
73
+ ];
74
+
75
+ const subscriptions = publishSet.map((item) => ({
76
+ topicFilter: item.topic,
77
+ qos: item.qos,
78
+ }));
79
+ await tcpClient.subscribe({
80
+ subscriptions,
81
+ });
82
+
83
+ // the IIFE ensures message reception runs in parallel
84
+ logger.info("TCP client Start receiving");
85
+ const received: PublishPacket[] = [];
86
+ (async function () {
87
+ for await (const item of tcpClient.messages()) {
88
+ logger.verbose("Receiving:", item.topic, "--", item.qos);
89
+ received.push(item);
90
+ }
91
+ })();
92
+ // end of IIFE
93
+ logger.info("TLS client Start publishing");
94
+ for (const item of publishSet) {
95
+ logger.verbose("Publishing:", item.topic, "--", item.qos);
96
+ await tlsClient.publish({
97
+ topic: item.topic,
98
+ qos: item.qos,
99
+ payload: new Uint8Array([0x01]),
100
+ });
101
+ }
102
+
103
+ await delay(100);
104
+ logger.info("Disconnect TLS client");
105
+ await tlsClient.disconnect();
106
+ logger.info("Disconnect TCP client");
107
+ await tcpClient.disconnect();
108
+ logger.info("Check completeness");
109
+ for (const item of publishSet) {
110
+ const found = received.find((f) =>
111
+ f.topic == item.topic && f.qos === item.qos
112
+ );
113
+ logger.verbose("Found:", item.topic, "--", item.qos);
114
+ assert(found, `${item.topic} -- ${item.qos}`);
115
+ }
116
+
117
+ // just for demo, you can keep the MQTT server alive on the TCP server wile the TLSserver closes
118
+ logger.info("Stop TLS server");
119
+ await tlsServer.stop();
120
+ logger.info("Stop TCP server");
121
+ await tcpServer.stop();
122
+ });
@@ -30,7 +30,7 @@ test("Test pubSub using TCP client and server using memoryPersistence", async fu
30
30
 
31
31
  const client = new TcpClient();
32
32
  await client.connect(params);
33
- logger.info("Client connected to server at", client.url);
33
+ logger.info("Client connected to server at", client.url.toString());
34
34
 
35
35
  const publishSet: { topic: string; qos: QoS }[] = [
36
36
  { topic: "t0@q0", qos: 0 },
@@ -85,5 +85,5 @@ test("Test pubSub using TCP client and server using memoryPersistence", async fu
85
85
  }
86
86
 
87
87
  logger.info("Stop server");
88
- server.stop();
88
+ await server.stop();
89
89
  });
@@ -41,7 +41,7 @@ test("Test pubSub using TLS client and server and sqlitePersistence", async func
41
41
 
42
42
  const client = new TcpClient();
43
43
  await client.connect(params);
44
- logger.info("Client connected to server at", client.url);
44
+ logger.info("Client connected to server at", client.url.toString());
45
45
 
46
46
  const publishSet: { topic: string; qos: QoS }[] = [
47
47
  { topic: "t0@q0", qos: 0 },
@@ -96,5 +96,5 @@ test("Test pubSub using TLS client and server and sqlitePersistence", async func
96
96
  }
97
97
 
98
98
  logger.info("Stop server");
99
- server.stop();
99
+ await server.stop();
100
100
  });