@annadata/capacitor-mqtt-quic 0.1.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 (64) hide show
  1. package/README.md +399 -0
  2. package/android/NGTCP2_BUILD_INSTRUCTIONS.md +319 -0
  3. package/android/build-nghttp3.sh +182 -0
  4. package/android/build-ngtcp2.sh +289 -0
  5. package/android/build-openssl.sh +302 -0
  6. package/android/build.gradle +75 -0
  7. package/android/gradle.properties +3 -0
  8. package/android/proguard-rules.pro +2 -0
  9. package/android/settings.gradle +1 -0
  10. package/android/src/main/AndroidManifest.xml +1 -0
  11. package/android/src/main/assets/mqttquic_ca.pem +5 -0
  12. package/android/src/main/cpp/CMakeLists.txt +157 -0
  13. package/android/src/main/cpp/ngtcp2_jni.cpp +928 -0
  14. package/android/src/main/kotlin/ai/annadata/mqttquic/MqttQuicPlugin.kt +232 -0
  15. package/android/src/main/kotlin/ai/annadata/mqttquic/client/MQTTClient.kt +339 -0
  16. package/android/src/main/kotlin/ai/annadata/mqttquic/mqtt/MQTT5Properties.kt +250 -0
  17. package/android/src/main/kotlin/ai/annadata/mqttquic/mqtt/MQTT5Protocol.kt +281 -0
  18. package/android/src/main/kotlin/ai/annadata/mqttquic/mqtt/MQTT5ReasonCodes.kt +109 -0
  19. package/android/src/main/kotlin/ai/annadata/mqttquic/mqtt/MQTTProtocol.kt +249 -0
  20. package/android/src/main/kotlin/ai/annadata/mqttquic/mqtt/MQTTTypes.kt +47 -0
  21. package/android/src/main/kotlin/ai/annadata/mqttquic/quic/NGTCP2Client.kt +184 -0
  22. package/android/src/main/kotlin/ai/annadata/mqttquic/quic/QuicClientStub.kt +54 -0
  23. package/android/src/main/kotlin/ai/annadata/mqttquic/quic/QuicTypes.kt +21 -0
  24. package/android/src/main/kotlin/ai/annadata/mqttquic/transport/QUICStreamAdapter.kt +37 -0
  25. package/android/src/main/kotlin/ai/annadata/mqttquic/transport/StreamTransport.kt +91 -0
  26. package/android/src/test/kotlin/ai/annadata/mqttquic/mqtt/MQTTProtocolTest.kt +92 -0
  27. package/dist/esm/definitions.d.ts +66 -0
  28. package/dist/esm/definitions.d.ts.map +1 -0
  29. package/dist/esm/definitions.js +2 -0
  30. package/dist/esm/definitions.js.map +1 -0
  31. package/dist/esm/index.d.ts +5 -0
  32. package/dist/esm/index.d.ts.map +1 -0
  33. package/dist/esm/index.js +7 -0
  34. package/dist/esm/index.js.map +1 -0
  35. package/dist/esm/web.d.ts +28 -0
  36. package/dist/esm/web.d.ts.map +1 -0
  37. package/dist/esm/web.js +183 -0
  38. package/dist/esm/web.js.map +1 -0
  39. package/dist/plugin.cjs.js +217 -0
  40. package/dist/plugin.cjs.js.map +1 -0
  41. package/dist/plugin.js +215 -0
  42. package/dist/plugin.js.map +1 -0
  43. package/ios/MqttQuicPlugin.podspec +34 -0
  44. package/ios/NGTCP2_BUILD_INSTRUCTIONS.md +302 -0
  45. package/ios/Sources/MqttQuicPlugin/Client/MQTTClient.swift +343 -0
  46. package/ios/Sources/MqttQuicPlugin/MQTT/MQTT5Properties.swift +280 -0
  47. package/ios/Sources/MqttQuicPlugin/MQTT/MQTT5Protocol.swift +333 -0
  48. package/ios/Sources/MqttQuicPlugin/MQTT/MQTT5ReasonCodes.swift +113 -0
  49. package/ios/Sources/MqttQuicPlugin/MQTT/MQTTProtocol.swift +322 -0
  50. package/ios/Sources/MqttQuicPlugin/MQTT/MQTTTypes.swift +54 -0
  51. package/ios/Sources/MqttQuicPlugin/MqttQuicPlugin.swift +229 -0
  52. package/ios/Sources/MqttQuicPlugin/QUIC/NGTCP2Bridge.h +29 -0
  53. package/ios/Sources/MqttQuicPlugin/QUIC/NGTCP2Bridge.mm +865 -0
  54. package/ios/Sources/MqttQuicPlugin/QUIC/NGTCP2Client.swift +262 -0
  55. package/ios/Sources/MqttQuicPlugin/QUIC/QuicClientStub.swift +66 -0
  56. package/ios/Sources/MqttQuicPlugin/QUIC/QuicTypes.swift +23 -0
  57. package/ios/Sources/MqttQuicPlugin/Resources/mqttquic_ca.pem +5 -0
  58. package/ios/Sources/MqttQuicPlugin/Transport/QUICStreamAdapter.swift +50 -0
  59. package/ios/Sources/MqttQuicPlugin/Transport/StreamTransport.swift +105 -0
  60. package/ios/Tests/MQTTProtocolTests.swift +82 -0
  61. package/ios/build-nghttp3.sh +173 -0
  62. package/ios/build-ngtcp2.sh +278 -0
  63. package/ios/build-openssl.sh +405 -0
  64. package/package.json +63 -0
@@ -0,0 +1,92 @@
1
+ package ai.annadata.mqttquic.mqtt
2
+
3
+ import ai.annadata.mqttquic.transport.MockStreamBuffer
4
+ import ai.annadata.mqttquic.transport.MockStreamReader
5
+ import ai.annadata.mqttquic.transport.MockStreamWriter
6
+ import kotlinx.coroutines.runBlocking
7
+ import org.junit.Assert.assertEquals
8
+ import org.junit.Assert.assertNotNull
9
+ import org.junit.Test
10
+
11
+ class MQTTProtocolTest {
12
+
13
+ @Test
14
+ fun encodeDecodeRemainingLength() {
15
+ for ((len, bytes) in listOf(0 to 1, 127 to 1, 128 to 2, 16383 to 2, 16384 to 3, 2097151 to 3, 2097152 to 4)) {
16
+ val enc = MQTTProtocol.encodeRemainingLength(len)
17
+ assertEquals("length $len", bytes, enc.size)
18
+ val (dec, _) = MQTTProtocol.decodeRemainingLength(enc, 0)
19
+ assertEquals(len, dec)
20
+ }
21
+ }
22
+
23
+ @Test
24
+ fun encodeDecodeString() {
25
+ val s = "hello/mqtt"
26
+ val enc = MQTTProtocol.encodeString(s)
27
+ assertEquals(2 + s.toByteArray(Charsets.UTF_8).size, enc.size)
28
+ val (dec, _) = MQTTProtocol.decodeString(enc, 0)
29
+ assertEquals(s, dec)
30
+ }
31
+
32
+ @Test
33
+ fun buildConnect() {
34
+ val data = MQTTProtocol.buildConnect("test-client", "u", "p", 90, true)
35
+ assert(data.size >= 10)
36
+ assertEquals(MQTTMessageType.CONNECT, data[0])
37
+ }
38
+
39
+ @Test
40
+ fun buildConnack() {
41
+ val data = MQTTProtocol.buildConnack(MQTTConnAckCode.ACCEPTED)
42
+ assertEquals(4, data.size)
43
+ assertEquals(MQTTMessageType.CONNACK, data[0])
44
+ assertEquals(MQTTConnAckCode.ACCEPTED, data[3].toInt() and 0xFF)
45
+ }
46
+
47
+ @Test
48
+ fun buildPublish() {
49
+ val payload = "hello".toByteArray(Charsets.UTF_8)
50
+ val data = MQTTProtocol.buildPublish("a/b", payload, null, 0, false)
51
+ assert((data[0].toInt() and 0xF0) == (MQTTMessageType.PUBLISH.toInt() and 0xF0))
52
+ }
53
+
54
+ @Test
55
+ fun buildSubscribeAndSuback() {
56
+ val sub = MQTTProtocol.buildSubscribe(1, "t/1", 0)
57
+ assertEquals((MQTTMessageType.SUBSCRIBE.toInt() or 0x02).toByte(), sub[0])
58
+
59
+ val suback = MQTTProtocol.buildSuback(1, 0)
60
+ assertEquals(MQTTMessageType.SUBACK, suback[0])
61
+ val (pid, rc, _) = MQTTProtocol.parseSuback(suback, 2)
62
+ assertEquals(1, pid)
63
+ assertEquals(0, rc)
64
+ }
65
+
66
+ @Test
67
+ fun buildPingreqPingrespDisconnect() {
68
+ val pr = MQTTProtocol.buildPingreq()
69
+ assertEquals(MQTTMessageType.PINGREQ, pr[0])
70
+ val ps = MQTTProtocol.buildPingresp()
71
+ assertEquals(MQTTMessageType.PINGRESP, ps[0])
72
+ val dc = MQTTProtocol.buildDisconnect()
73
+ assertEquals(MQTTMessageType.DISCONNECT, dc[0])
74
+ }
75
+
76
+ @Test
77
+ fun mockStreamReaderWriter() = runBlocking {
78
+ val buf = MockStreamBuffer(byteArrayOf(1, 2, 3, 4, 5))
79
+ val reader = MockStreamReader(buf)
80
+ val writer = MockStreamWriter(buf)
81
+
82
+ val r1 = reader.read(2)
83
+ assertEquals(byteArrayOf(1, 2).toList(), r1.toList())
84
+ val r2 = reader.readexactly(3)
85
+ assertEquals(byteArrayOf(3, 4, 5).toList(), r2.toList())
86
+
87
+ writer.write(byteArrayOf(6, 7, 8))
88
+ writer.drain()
89
+ val written = buf.consumeWrite()
90
+ assertEquals(byteArrayOf(6, 7, 8).toList(), written.toList())
91
+ }
92
+ }
@@ -0,0 +1,66 @@
1
+ export interface MqttQuicConnectOptions {
2
+ host: string;
3
+ port: number;
4
+ clientId: string;
5
+ username?: string;
6
+ password?: string;
7
+ cleanSession?: boolean;
8
+ keepalive?: number;
9
+ caFile?: string;
10
+ caPath?: string;
11
+ protocolVersion?: '3.1.1' | '5.0' | 'auto';
12
+ sessionExpiryInterval?: number;
13
+ receiveMaximum?: number;
14
+ maximumPacketSize?: number;
15
+ topicAliasMaximum?: number;
16
+ }
17
+ export interface MqttQuicPublishOptions {
18
+ topic: string;
19
+ payload: string | Uint8Array;
20
+ qos?: 0 | 1 | 2;
21
+ retain?: boolean;
22
+ messageExpiryInterval?: number;
23
+ contentType?: string;
24
+ responseTopic?: string;
25
+ correlationData?: string | Uint8Array;
26
+ userProperties?: Array<{
27
+ name: string;
28
+ value: string;
29
+ }>;
30
+ }
31
+ export interface MqttQuicSubscribeOptions {
32
+ topic: string;
33
+ qos?: 0 | 1 | 2;
34
+ subscriptionIdentifier?: number;
35
+ }
36
+ export type MqttQuicConnectionState = 'disconnected' | 'connecting' | 'connected' | 'reconnecting' | 'error';
37
+ export interface MqttQuicTestHarnessOptions {
38
+ host: string;
39
+ port?: number;
40
+ clientId?: string;
41
+ topic?: string;
42
+ payload?: string;
43
+ caFile?: string;
44
+ caPath?: string;
45
+ }
46
+ export interface MqttQuicPlugin {
47
+ connect(options: MqttQuicConnectOptions): Promise<{
48
+ connected: boolean;
49
+ }>;
50
+ disconnect(): Promise<void>;
51
+ publish(options: MqttQuicPublishOptions): Promise<{
52
+ success: boolean;
53
+ }>;
54
+ subscribe(options: MqttQuicSubscribeOptions): Promise<{
55
+ success: boolean;
56
+ }>;
57
+ unsubscribe(options: {
58
+ topic: string;
59
+ }): Promise<{
60
+ success: boolean;
61
+ }>;
62
+ testHarness(options: MqttQuicTestHarnessOptions): Promise<{
63
+ success: boolean;
64
+ }>;
65
+ }
66
+ //# sourceMappingURL=definitions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"definitions.d.ts","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,eAAe,CAAC,EAAE,OAAO,GAAG,KAAK,GAAG,MAAM,CAAC;IAC3C,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,sBAAsB;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,GAAG,UAAU,CAAC;IAC7B,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IAEjB,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,GAAG,UAAU,CAAC;IACtC,cAAc,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACzD;AAED,MAAM,WAAW,wBAAwB;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAEhB,sBAAsB,CAAC,EAAE,MAAM,CAAC;CACjC;AAED,MAAM,MAAM,uBAAuB,GAAG,cAAc,GAAG,YAAY,GAAG,WAAW,GAAG,cAAc,GAAG,OAAO,CAAC;AAE7G,MAAM,WAAW,0BAA0B;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC;QAAE,SAAS,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAC1E,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,OAAO,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IACxE,SAAS,CAAC,OAAO,EAAE,wBAAwB,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAC5E,WAAW,CAAC,OAAO,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IACvE,WAAW,CAAC,OAAO,EAAE,0BAA0B,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CACjF"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=definitions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":""}
@@ -0,0 +1,5 @@
1
+ import type { MqttQuicPlugin } from './definitions';
2
+ declare const MqttQuic: MqttQuicPlugin;
3
+ export * from './definitions';
4
+ export { MqttQuic };
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpD,QAAA,MAAM,QAAQ,gBAEZ,CAAC;AAEH,cAAc,eAAe,CAAC;AAC9B,OAAO,EAAE,QAAQ,EAAE,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { registerPlugin } from '@capacitor/core';
2
+ const MqttQuic = registerPlugin('MqttQuic', {
3
+ web: () => import('./web').then((m) => new m.MqttQuicWeb()),
4
+ });
5
+ export * from './definitions';
6
+ export { MqttQuic };
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGjD,MAAM,QAAQ,GAAG,cAAc,CAAiB,UAAU,EAAE;IAC1D,GAAG,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;CAC5D,CAAC,CAAC;AAEH,cAAc,eAAe,CAAC;AAC9B,OAAO,EAAE,QAAQ,EAAE,CAAC"}
@@ -0,0 +1,28 @@
1
+ import type { MqttQuicConnectOptions, MqttQuicPublishOptions, MqttQuicSubscribeOptions, MqttQuicTestHarnessOptions } from './definitions';
2
+ /**
3
+ * Web/PWA implementation: MQTT over WebSocket (WSS).
4
+ * Browsers cannot use ngtcp2/QUIC; mqtt.js over WSS is used as fallback.
5
+ */
6
+ export declare class MqttQuicWeb {
7
+ private client;
8
+ private protocol;
9
+ connect(options: MqttQuicConnectOptions): Promise<{
10
+ connected: boolean;
11
+ }>;
12
+ disconnect(): Promise<void>;
13
+ publish(options: MqttQuicPublishOptions): Promise<{
14
+ success: boolean;
15
+ }>;
16
+ subscribe(options: MqttQuicSubscribeOptions): Promise<{
17
+ success: boolean;
18
+ }>;
19
+ unsubscribe(options: {
20
+ topic: string;
21
+ }): Promise<{
22
+ success: boolean;
23
+ }>;
24
+ testHarness(options: MqttQuicTestHarnessOptions): Promise<{
25
+ success: boolean;
26
+ }>;
27
+ }
28
+ //# sourceMappingURL=web.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web.d.ts","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,sBAAsB,EACtB,sBAAsB,EACtB,wBAAwB,EACxB,0BAA0B,EAC3B,MAAM,eAAe,CAAC;AAEvB;;;GAGG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAA2B;IACzC,OAAO,CAAC,QAAQ,CAAuB;IAEjC,OAAO,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC;QAAE,SAAS,EAAE,OAAO,CAAA;KAAE,CAAC;IA8DzE,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAa3B,OAAO,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IAwCvE,SAAS,CAAC,OAAO,EAAE,wBAAwB,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IAqB3E,WAAW,CAAC,OAAO,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IActE,WAAW,CAAC,OAAO,EAAE,0BAA0B,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;CAuBtF"}
@@ -0,0 +1,183 @@
1
+ import mqtt from 'mqtt';
2
+ /**
3
+ * Web/PWA implementation: MQTT over WebSocket (WSS).
4
+ * Browsers cannot use ngtcp2/QUIC; mqtt.js over WSS is used as fallback.
5
+ */
6
+ export class MqttQuicWeb {
7
+ constructor() {
8
+ this.client = null;
9
+ this.protocol = 'wss';
10
+ }
11
+ async connect(options) {
12
+ return new Promise((resolve, reject) => {
13
+ var _a, _b, _c, _d, _e;
14
+ if ((_a = this.client) === null || _a === void 0 ? void 0 : _a.connected) {
15
+ resolve({ connected: true });
16
+ return;
17
+ }
18
+ if (this.client && !this.client.connected) {
19
+ reject(new Error('already connecting'));
20
+ return;
21
+ }
22
+ const port = (_b = options.port) !== null && _b !== void 0 ? _b : 1884;
23
+ this.protocol = port === 8884 || port === 443 ? 'wss' : 'ws';
24
+ const url = `${this.protocol}://${options.host}:${port}`;
25
+ const connectOpts = {
26
+ clientId: options.clientId,
27
+ username: options.username,
28
+ password: options.password,
29
+ clean: (_c = options.cleanSession) !== null && _c !== void 0 ? _c : true,
30
+ keepalive: (_d = options.keepalive) !== null && _d !== void 0 ? _d : 60,
31
+ reconnectPeriod: 0,
32
+ connectTimeout: 30000,
33
+ };
34
+ const pv = (_e = options.protocolVersion) !== null && _e !== void 0 ? _e : 'auto';
35
+ if (pv === '5.0') {
36
+ connectOpts.protocolVersion = 5;
37
+ connectOpts.properties = {
38
+ sessionExpiryInterval: options.sessionExpiryInterval,
39
+ };
40
+ }
41
+ else if (pv === '3.1.1') {
42
+ connectOpts.protocolVersion = 4;
43
+ }
44
+ else {
45
+ connectOpts.protocolVersion = 5;
46
+ connectOpts.properties = options.sessionExpiryInterval != null
47
+ ? { sessionExpiryInterval: options.sessionExpiryInterval }
48
+ : undefined;
49
+ }
50
+ try {
51
+ this.client = mqtt.connect(url, connectOpts);
52
+ }
53
+ catch (e) {
54
+ reject(e instanceof Error ? e.message : 'Connect failed');
55
+ return;
56
+ }
57
+ const onConnect = () => {
58
+ this.client.removeListener('error', onError);
59
+ resolve({ connected: true });
60
+ };
61
+ const onError = (err) => {
62
+ var _a;
63
+ (_a = this.client) === null || _a === void 0 ? void 0 : _a.removeListener('connect', onConnect);
64
+ reject(err.message);
65
+ };
66
+ this.client.once('connect', onConnect);
67
+ this.client.once('error', onError);
68
+ });
69
+ }
70
+ async disconnect() {
71
+ return new Promise((resolve) => {
72
+ if (!this.client) {
73
+ resolve();
74
+ return;
75
+ }
76
+ const c = this.client;
77
+ this.client = null;
78
+ c.end(false, () => resolve());
79
+ c.removeAllListeners();
80
+ });
81
+ }
82
+ async publish(options) {
83
+ return new Promise((resolve, reject) => {
84
+ var _a, _b, _c, _d;
85
+ if (!((_a = this.client) === null || _a === void 0 ? void 0 : _a.connected)) {
86
+ reject(new Error('Not connected'));
87
+ return;
88
+ }
89
+ const payload = typeof options.payload === 'string'
90
+ ? options.payload
91
+ : Buffer.from(options.payload);
92
+ const opts = {
93
+ qos: ((_b = options.qos) !== null && _b !== void 0 ? _b : 0),
94
+ retain: (_c = options.retain) !== null && _c !== void 0 ? _c : false,
95
+ };
96
+ const props = {};
97
+ if (options.messageExpiryInterval != null)
98
+ props.messageExpiryInterval = options.messageExpiryInterval;
99
+ if (options.contentType)
100
+ props.contentType = options.contentType;
101
+ if (options.responseTopic)
102
+ props.responseTopic = options.responseTopic;
103
+ if (options.correlationData != null) {
104
+ props.correlationData =
105
+ typeof options.correlationData === 'string'
106
+ ? Buffer.from(options.correlationData, 'utf8')
107
+ : Buffer.from(options.correlationData);
108
+ }
109
+ if ((_d = options.userProperties) === null || _d === void 0 ? void 0 : _d.length) {
110
+ props.userProperties = Object.fromEntries(options.userProperties.map((p) => [p.name, p.value]));
111
+ }
112
+ if (Object.keys(props).length)
113
+ opts.properties = props;
114
+ this.client.publish(options.topic, payload, opts, (err) => {
115
+ if (err)
116
+ reject(err);
117
+ else
118
+ resolve({ success: true });
119
+ });
120
+ });
121
+ }
122
+ async subscribe(options) {
123
+ return new Promise((resolve, reject) => {
124
+ var _a, _b;
125
+ if (!((_a = this.client) === null || _a === void 0 ? void 0 : _a.connected)) {
126
+ reject(new Error('Not connected'));
127
+ return;
128
+ }
129
+ const opts = {
130
+ qos: ((_b = options.qos) !== null && _b !== void 0 ? _b : 0),
131
+ };
132
+ if (options.subscriptionIdentifier != null) {
133
+ opts.properties = { subscriptionIdentifier: options.subscriptionIdentifier };
134
+ }
135
+ this.client.subscribe(options.topic, opts, (err) => {
136
+ if (err)
137
+ reject(err);
138
+ else
139
+ resolve({ success: true });
140
+ });
141
+ });
142
+ }
143
+ async unsubscribe(options) {
144
+ return new Promise((resolve, reject) => {
145
+ var _a;
146
+ if (!((_a = this.client) === null || _a === void 0 ? void 0 : _a.connected)) {
147
+ reject(new Error('Not connected'));
148
+ return;
149
+ }
150
+ this.client.unsubscribe(options.topic, (err) => {
151
+ if (err)
152
+ reject(err);
153
+ else
154
+ resolve({ success: true });
155
+ });
156
+ });
157
+ }
158
+ async testHarness(options) {
159
+ var _a, _b, _c, _d;
160
+ const host = options.host;
161
+ const port = (_a = options.port) !== null && _a !== void 0 ? _a : 1884;
162
+ const clientId = (_b = options.clientId) !== null && _b !== void 0 ? _b : 'mqttquic_test_client';
163
+ const topic = (_c = options.topic) !== null && _c !== void 0 ? _c : 'test/topic';
164
+ const payload = (_d = options.payload) !== null && _d !== void 0 ? _d : 'Hello QUIC!';
165
+ try {
166
+ await this.connect({
167
+ host,
168
+ port,
169
+ clientId,
170
+ cleanSession: true,
171
+ keepalive: 60,
172
+ });
173
+ await this.subscribe({ topic, qos: 0 });
174
+ await this.publish({ topic, payload, qos: 0 });
175
+ await this.disconnect();
176
+ return { success: true };
177
+ }
178
+ catch (error) {
179
+ throw error instanceof Error ? error : new Error(String(error));
180
+ }
181
+ }
182
+ }
183
+ //# sourceMappingURL=web.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":"AAAA,OAAO,IAA0E,MAAM,MAAM,CAAC;AAQ9F;;;GAGG;AACH,MAAM,OAAO,WAAW;IAAxB;QACU,WAAM,GAAsB,IAAI,CAAC;QACjC,aAAQ,GAAiB,KAAK,CAAC;IA+KzC,CAAC;IA7KC,KAAK,CAAC,OAAO,CAAC,OAA+B;QAC3C,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;;YACrC,IAAI,MAAA,IAAI,CAAC,MAAM,0CAAE,SAAS,EAAE,CAAC;gBAC3B,OAAO,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;gBAC7B,OAAO;YACT,CAAC;YACD,IAAI,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;gBAC1C,MAAM,CAAC,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC,CAAC;gBACxC,OAAO;YACT,CAAC;YAED,MAAM,IAAI,GAAG,MAAA,OAAO,CAAC,IAAI,mCAAI,IAAI,CAAC;YAClC,IAAI,CAAC,QAAQ,GAAG,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;YAC7D,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,QAAQ,MAAM,OAAO,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC;YAEzD,MAAM,WAAW,GAAmB;gBAClC,QAAQ,EAAE,OAAO,CAAC,QAAQ;gBAC1B,QAAQ,EAAE,OAAO,CAAC,QAAQ;gBAC1B,QAAQ,EAAE,OAAO,CAAC,QAAQ;gBAC1B,KAAK,EAAE,MAAA,OAAO,CAAC,YAAY,mCAAI,IAAI;gBACnC,SAAS,EAAE,MAAA,OAAO,CAAC,SAAS,mCAAI,EAAE;gBAClC,eAAe,EAAE,CAAC;gBAClB,cAAc,EAAE,KAAM;aACvB,CAAC;YAEF,MAAM,EAAE,GAAG,MAAA,OAAO,CAAC,eAAe,mCAAI,MAAM,CAAC;YAC7C,IAAI,EAAE,KAAK,KAAK,EAAE,CAAC;gBACjB,WAAW,CAAC,eAAe,GAAG,CAAC,CAAC;gBAChC,WAAW,CAAC,UAAU,GAAG;oBACvB,qBAAqB,EAAE,OAAO,CAAC,qBAAqB;iBACrD,CAAC;YACJ,CAAC;iBAAM,IAAI,EAAE,KAAK,OAAO,EAAE,CAAC;gBAC1B,WAAW,CAAC,eAAe,GAAG,CAAC,CAAC;YAClC,CAAC;iBAAM,CAAC;gBACN,WAAW,CAAC,eAAe,GAAG,CAAC,CAAC;gBAChC,WAAW,CAAC,UAAU,GAAG,OAAO,CAAC,qBAAqB,IAAI,IAAI;oBAC5D,CAAC,CAAC,EAAE,qBAAqB,EAAE,OAAO,CAAC,qBAAqB,EAAE;oBAC1D,CAAC,CAAC,SAAS,CAAC;YAChB,CAAC;YAED,IAAI,CAAC;gBACH,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;YAC/C,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,MAAM,CAAC,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC;gBAC1D,OAAO;YACT,CAAC;YAED,MAAM,SAAS,GAAG,GAAG,EAAE;gBACrB,IAAI,CAAC,MAAO,CAAC,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;gBAC9C,OAAO,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAC/B,CAAC,CAAC;YAEF,MAAM,OAAO,GAAG,CAAC,GAAU,EAAE,EAAE;;gBAC7B,MAAA,IAAI,CAAC,MAAM,0CAAE,cAAc,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;gBAClD,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACtB,CAAC,CAAC;YAEF,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;YACvC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACrC,CAAC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,UAAU;QACd,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;YAC7B,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;gBACjB,OAAO,EAAE,CAAC;gBACV,OAAO;YACT,CAAC;YACD,MAAM,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC;YACtB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;YACnB,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC;YAC9B,CAAC,CAAC,kBAAkB,EAAE,CAAC;QACzB,CAAC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,OAA+B;QAC3C,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;;YACrC,IAAI,CAAC,CAAA,MAAA,IAAI,CAAC,MAAM,0CAAE,SAAS,CAAA,EAAE,CAAC;gBAC5B,MAAM,CAAC,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC,CAAC;gBACnC,OAAO;YACT,CAAC;YAED,MAAM,OAAO,GACX,OAAO,OAAO,CAAC,OAAO,KAAK,QAAQ;gBACjC,CAAC,CAAC,OAAO,CAAC,OAAO;gBACjB,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YAEnC,MAAM,IAAI,GAA0B;gBAClC,GAAG,EAAE,CAAC,MAAA,OAAO,CAAC,GAAG,mCAAI,CAAC,CAAc;gBACpC,MAAM,EAAE,MAAA,OAAO,CAAC,MAAM,mCAAI,KAAK;aAChC,CAAC;YACF,MAAM,KAAK,GAA4B,EAAE,CAAC;YAC1C,IAAI,OAAO,CAAC,qBAAqB,IAAI,IAAI;gBAAE,KAAK,CAAC,qBAAqB,GAAG,OAAO,CAAC,qBAAqB,CAAC;YACvG,IAAI,OAAO,CAAC,WAAW;gBAAE,KAAK,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;YACjE,IAAI,OAAO,CAAC,aAAa;gBAAE,KAAK,CAAC,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;YACvE,IAAI,OAAO,CAAC,eAAe,IAAI,IAAI,EAAE,CAAC;gBACpC,KAAK,CAAC,eAAe;oBACnB,OAAO,OAAO,CAAC,eAAe,KAAK,QAAQ;wBACzC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,eAAe,EAAE,MAAM,CAAC;wBAC9C,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;YAC7C,CAAC;YACD,IAAI,MAAA,OAAO,CAAC,cAAc,0CAAE,MAAM,EAAE,CAAC;gBACnC,KAAK,CAAC,cAAc,GAAG,MAAM,CAAC,WAAW,CACvC,OAAO,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CACrD,CAAC;YACJ,CAAC;YACD,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM;gBAAE,IAAI,CAAC,UAAU,GAAG,KAA4C,CAAC;YAE9F,IAAI,CAAC,MAAO,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,GAAG,EAAE,EAAE;gBACzD,IAAI,GAAG;oBAAE,MAAM,CAAC,GAAG,CAAC,CAAC;;oBAChB,OAAO,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;YAClC,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,OAAiC;QAC/C,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;;YACrC,IAAI,CAAC,CAAA,MAAA,IAAI,CAAC,MAAM,0CAAE,SAAS,CAAA,EAAE,CAAC;gBAC5B,MAAM,CAAC,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC,CAAC;gBACnC,OAAO;YACT,CAAC;YAED,MAAM,IAAI,GAAwE;gBAChF,GAAG,EAAE,CAAC,MAAA,OAAO,CAAC,GAAG,mCAAI,CAAC,CAAc;aACrC,CAAC;YACF,IAAI,OAAO,CAAC,sBAAsB,IAAI,IAAI,EAAE,CAAC;gBAC3C,IAAI,CAAC,UAAU,GAAG,EAAE,sBAAsB,EAAE,OAAO,CAAC,sBAAsB,EAAE,CAAC;YAC/E,CAAC;YAED,IAAI,CAAC,MAAO,CAAC,SAAS,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,GAAG,EAAE,EAAE;gBAClD,IAAI,GAAG;oBAAE,MAAM,CAAC,GAAG,CAAC,CAAC;;oBAChB,OAAO,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;YAClC,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,OAA0B;QAC1C,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;;YACrC,IAAI,CAAC,CAAA,MAAA,IAAI,CAAC,MAAM,0CAAE,SAAS,CAAA,EAAE,CAAC;gBAC5B,MAAM,CAAC,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC,CAAC;gBACnC,OAAO;YACT,CAAC;YAED,IAAI,CAAC,MAAO,CAAC,WAAW,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,GAAG,EAAE,EAAE;gBAC9C,IAAI,GAAG;oBAAE,MAAM,CAAC,GAAG,CAAC,CAAC;;oBAChB,OAAO,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;YAClC,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,OAAmC;;QACnD,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;QAC1B,MAAM,IAAI,GAAG,MAAA,OAAO,CAAC,IAAI,mCAAI,IAAI,CAAC;QAClC,MAAM,QAAQ,GAAG,MAAA,OAAO,CAAC,QAAQ,mCAAI,sBAAsB,CAAC;QAC5D,MAAM,KAAK,GAAG,MAAA,OAAO,CAAC,KAAK,mCAAI,YAAY,CAAC;QAC5C,MAAM,OAAO,GAAG,MAAA,OAAO,CAAC,OAAO,mCAAI,aAAa,CAAC;QAEjD,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,OAAO,CAAC;gBACjB,IAAI;gBACJ,IAAI;gBACJ,QAAQ;gBACR,YAAY,EAAE,IAAI;gBAClB,SAAS,EAAE,EAAE;aACd,CAAC,CAAC;YACH,MAAM,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;YACxC,MAAM,IAAI,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;YAC/C,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;YACxB,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC3B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QAClE,CAAC;IACH,CAAC;CACF"}