@phystack/hub-client 4.5.19-dev → 4.5.20-dev

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 (119) hide show
  1. package/dist/index.d.ts +22 -28
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +252 -378
  4. package/dist/index.js.map +1 -1
  5. package/dist/peripheral-twin.d.ts +34 -0
  6. package/dist/peripheral-twin.d.ts.map +1 -0
  7. package/dist/peripheral-twin.js +234 -0
  8. package/dist/peripheral-twin.js.map +1 -0
  9. package/dist/services/phyhub-connection.service.d.ts +1 -0
  10. package/dist/services/phyhub-connection.service.d.ts.map +1 -1
  11. package/dist/services/phyhub-connection.service.js +17 -0
  12. package/dist/services/phyhub-connection.service.js.map +1 -1
  13. package/dist/services/phyhub-direct-connection.service.d.ts +21 -0
  14. package/dist/services/phyhub-direct-connection.service.d.ts.map +1 -0
  15. package/dist/services/phyhub-direct-connection.service.js +101 -0
  16. package/dist/services/phyhub-direct-connection.service.js.map +1 -0
  17. package/dist/services/webrtc/data-channel-handler.d.ts +45 -0
  18. package/dist/services/webrtc/data-channel-handler.d.ts.map +1 -0
  19. package/dist/services/webrtc/data-channel-handler.js +260 -0
  20. package/dist/services/webrtc/data-channel-handler.js.map +1 -0
  21. package/dist/services/webrtc/index.d.ts +8 -0
  22. package/dist/services/webrtc/index.d.ts.map +1 -0
  23. package/dist/services/webrtc/index.js +18 -0
  24. package/dist/services/webrtc/index.js.map +1 -0
  25. package/dist/services/webrtc/media-stream-handler.d.ts +57 -0
  26. package/dist/services/webrtc/media-stream-handler.d.ts.map +1 -0
  27. package/dist/services/webrtc/media-stream-handler.js +383 -0
  28. package/dist/services/webrtc/media-stream-handler.js.map +1 -0
  29. package/dist/services/webrtc/peer-connection-manager.d.ts +40 -0
  30. package/dist/services/webrtc/peer-connection-manager.d.ts.map +1 -0
  31. package/dist/services/webrtc/peer-connection-manager.js +336 -0
  32. package/dist/services/webrtc/peer-connection-manager.js.map +1 -0
  33. package/dist/services/webrtc/types.d.ts +134 -0
  34. package/dist/services/webrtc/types.d.ts.map +1 -0
  35. package/dist/services/webrtc/types.js +12 -0
  36. package/dist/services/webrtc/types.js.map +1 -0
  37. package/dist/services/webrtc/webrtc-globals.d.ts +4 -0
  38. package/dist/services/webrtc/webrtc-globals.d.ts.map +1 -0
  39. package/dist/services/webrtc/webrtc-globals.js +72 -0
  40. package/dist/services/webrtc/webrtc-globals.js.map +1 -0
  41. package/dist/services/webrtc/webrtc-manager.d.ts +35 -0
  42. package/dist/services/webrtc/webrtc-manager.d.ts.map +1 -0
  43. package/dist/services/webrtc/webrtc-manager.js +274 -0
  44. package/dist/services/webrtc/webrtc-manager.js.map +1 -0
  45. package/dist/test/communication-comprehensive-test.d.ts +8 -0
  46. package/dist/test/communication-comprehensive-test.d.ts.map +1 -0
  47. package/dist/test/communication-comprehensive-test.js +356 -0
  48. package/dist/test/communication-comprehensive-test.js.map +1 -0
  49. package/dist/test/webrtc-channel-names-test.d.ts +2 -0
  50. package/dist/test/webrtc-channel-names-test.d.ts.map +1 -0
  51. package/dist/test/webrtc-channel-names-test.js +177 -0
  52. package/dist/test/webrtc-channel-names-test.js.map +1 -0
  53. package/dist/test/webrtc-comprehensive-test.d.ts +2 -0
  54. package/dist/test/webrtc-comprehensive-test.d.ts.map +1 -0
  55. package/dist/test/webrtc-comprehensive-test.js +328 -0
  56. package/dist/test/webrtc-comprehensive-test.js.map +1 -0
  57. package/dist/test/webrtc-reconnect-test.d.ts +4 -0
  58. package/dist/test/webrtc-reconnect-test.d.ts.map +1 -0
  59. package/dist/test/webrtc-reconnect-test.js +244 -0
  60. package/dist/test/webrtc-reconnect-test.js.map +1 -0
  61. package/dist/test/webrtc-test-harness.d.ts +4 -0
  62. package/dist/test/webrtc-test-harness.d.ts.map +1 -0
  63. package/dist/test/webrtc-test-harness.js +169 -0
  64. package/dist/test/webrtc-test-harness.js.map +1 -0
  65. package/dist/twin-messaging.d.ts +20 -0
  66. package/dist/twin-messaging.d.ts.map +1 -0
  67. package/dist/twin-messaging.js +94 -0
  68. package/dist/twin-messaging.js.map +1 -0
  69. package/dist/twin-registry.d.ts +9 -0
  70. package/dist/twin-registry.d.ts.map +1 -0
  71. package/dist/twin-registry.js +26 -0
  72. package/dist/twin-registry.js.map +1 -0
  73. package/dist/types/index.d.ts +4 -0
  74. package/dist/types/index.d.ts.map +1 -0
  75. package/dist/types/index.js +20 -0
  76. package/dist/types/index.js.map +1 -0
  77. package/dist/types/twin.types.d.ts +62 -14
  78. package/dist/types/twin.types.d.ts.map +1 -1
  79. package/dist/types/twin.types.js +8 -1
  80. package/dist/types/twin.types.js.map +1 -1
  81. package/docs/webrtc-howto.md +398 -0
  82. package/docs/webrtc-test.md +330 -0
  83. package/package.json +3 -3
  84. package/scripts/webrtc-test.sh +401 -0
  85. package/src/index.ts +378 -568
  86. package/src/peripheral-twin.ts +337 -0
  87. package/src/services/phyhub-connection.service.ts +24 -0
  88. package/src/services/phyhub-direct-connection.service.ts +159 -0
  89. package/src/services/webrtc/data-channel-handler.ts +362 -0
  90. package/src/services/webrtc/index.ts +36 -0
  91. package/src/services/webrtc/media-stream-handler.ts +536 -0
  92. package/src/services/webrtc/peer-connection-manager.ts +467 -0
  93. package/src/services/webrtc/types.ts +273 -0
  94. package/src/services/webrtc/webrtc-globals.ts +108 -0
  95. package/src/services/webrtc/webrtc-manager.ts +490 -0
  96. package/src/test/communication-comprehensive-test.ts +533 -0
  97. package/src/test/webrtc-channel-names-test.ts +266 -0
  98. package/src/test/webrtc-comprehensive-test.ts +494 -0
  99. package/src/test/webrtc-reconnect-test.ts +345 -0
  100. package/src/test/webrtc-test-harness.ts +254 -0
  101. package/src/twin-messaging.ts +184 -0
  102. package/src/twin-registry.ts +39 -0
  103. package/src/types/index.ts +3 -0
  104. package/src/types/twin.types.ts +80 -14
  105. package/dist/services/webrtc/datachannel.d.ts +0 -10
  106. package/dist/services/webrtc/datachannel.d.ts.map +0 -1
  107. package/dist/services/webrtc/datachannel.js +0 -290
  108. package/dist/services/webrtc/datachannel.js.map +0 -1
  109. package/dist/services/webrtc/mediastream.d.ts +0 -10
  110. package/dist/services/webrtc/mediastream.d.ts.map +0 -1
  111. package/dist/services/webrtc/mediastream.js +0 -396
  112. package/dist/services/webrtc/mediastream.js.map +0 -1
  113. package/dist/services/webrtc/peer-connection-ice.d.ts +0 -32
  114. package/dist/services/webrtc/peer-connection-ice.d.ts.map +0 -1
  115. package/dist/services/webrtc/peer-connection-ice.js +0 -483
  116. package/dist/services/webrtc/peer-connection-ice.js.map +0 -1
  117. package/src/services/webrtc/datachannel.ts +0 -421
  118. package/src/services/webrtc/mediastream.ts +0 -602
  119. package/src/services/webrtc/peer-connection-ice.ts +0 -689
@@ -0,0 +1,274 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WebRTCManager = void 0;
4
+ const data_channel_handler_1 = require("./data-channel-handler");
5
+ const media_stream_handler_1 = require("./media-stream-handler");
6
+ const webrtc_globals_1 = require("./webrtc-globals");
7
+ const types_1 = require("./types");
8
+ class WebRTCManager {
9
+ constructor(twinMessaging, options = {}) {
10
+ var _a, _b, _c, _d, _e, _f;
11
+ this.dataChannelHandlers = new Map();
12
+ this.mediaStreamHandlers = new Map();
13
+ this.dataChannelListeners = new Set();
14
+ this.mediaStreamListeners = new Set();
15
+ this.eventListeners = new Map();
16
+ this.isInitialized = false;
17
+ this.isClosed = false;
18
+ this.twinMessaging = twinMessaging;
19
+ this.options = {
20
+ verbose: (_a = options.verbose) !== null && _a !== void 0 ? _a : types_1.DEFAULT_WEBRTC_OPTIONS.verbose,
21
+ useStun: (_b = options.useStun) !== null && _b !== void 0 ? _b : types_1.DEFAULT_WEBRTC_OPTIONS.useStun,
22
+ stunServers: (_c = options.stunServers) !== null && _c !== void 0 ? _c : types_1.DEFAULT_WEBRTC_OPTIONS.stunServers,
23
+ connectionTimeout: (_d = options.connectionTimeout) !== null && _d !== void 0 ? _d : types_1.DEFAULT_WEBRTC_OPTIONS.connectionTimeout,
24
+ initialRetryDelay: (_e = options.initialRetryDelay) !== null && _e !== void 0 ? _e : types_1.DEFAULT_WEBRTC_OPTIONS.initialRetryDelay,
25
+ maxRetryDelay: (_f = options.maxRetryDelay) !== null && _f !== void 0 ? _f : types_1.DEFAULT_WEBRTC_OPTIONS.maxRetryDelay,
26
+ };
27
+ }
28
+ async createDataChannel(targetTwinId, channelName = 'default') {
29
+ await this.ensureInitialized();
30
+ if (this.isClosed) {
31
+ throw new Error('WebRTCManager has been closed');
32
+ }
33
+ const handlerKey = `${targetTwinId}:${channelName}`;
34
+ const existing = this.dataChannelHandlers.get(handlerKey);
35
+ if (existing) {
36
+ return existing.connect();
37
+ }
38
+ const handler = new data_channel_handler_1.DataChannelHandler(targetTwinId, true, this.twinMessaging, {
39
+ useStun: this.options.useStun,
40
+ stunServers: this.options.stunServers,
41
+ connectionTimeout: this.options.connectionTimeout,
42
+ initialRetryDelay: this.options.initialRetryDelay,
43
+ maxRetryDelay: this.options.maxRetryDelay,
44
+ }, channelName);
45
+ this.setupDataChannelHandlerCallbacks(handler, targetTwinId);
46
+ this.dataChannelHandlers.set(handlerKey, handler);
47
+ try {
48
+ return await handler.connect();
49
+ }
50
+ catch (error) {
51
+ this.dataChannelHandlers.delete(handlerKey);
52
+ throw error;
53
+ }
54
+ }
55
+ onDataChannel(callback) {
56
+ this.dataChannelListeners.add(callback);
57
+ }
58
+ offDataChannel(callback) {
59
+ this.dataChannelListeners.delete(callback);
60
+ }
61
+ async acceptDataChannel(sourceTwinId, channelName = 'default') {
62
+ await this.ensureInitialized();
63
+ if (this.isClosed) {
64
+ throw new Error('WebRTCManager has been closed');
65
+ }
66
+ const handlerKey = `${sourceTwinId}:${channelName}`;
67
+ const handler = new data_channel_handler_1.DataChannelHandler(sourceTwinId, false, this.twinMessaging, {
68
+ useStun: this.options.useStun,
69
+ stunServers: this.options.stunServers,
70
+ connectionTimeout: this.options.connectionTimeout,
71
+ initialRetryDelay: this.options.initialRetryDelay,
72
+ maxRetryDelay: this.options.maxRetryDelay,
73
+ }, channelName);
74
+ this.setupDataChannelHandlerCallbacks(handler, sourceTwinId);
75
+ this.dataChannelHandlers.set(handlerKey, handler);
76
+ try {
77
+ const channel = await handler.connect();
78
+ this.dataChannelListeners.forEach((listener) => {
79
+ try {
80
+ listener(channel, sourceTwinId);
81
+ }
82
+ catch (err) {
83
+ console.error('[WebRTCManager] Error in DataChannel listener:', err);
84
+ }
85
+ });
86
+ return channel;
87
+ }
88
+ catch (error) {
89
+ this.dataChannelHandlers.delete(handlerKey);
90
+ throw error;
91
+ }
92
+ }
93
+ async createMediaStream(targetTwinId, options, channelName = 'default') {
94
+ await this.ensureInitialized();
95
+ if (this.isClosed) {
96
+ throw new Error('WebRTCManager has been closed');
97
+ }
98
+ const handlerKey = `${targetTwinId}:${channelName}`;
99
+ const existing = this.mediaStreamHandlers.get(handlerKey);
100
+ if (existing) {
101
+ return existing.connect();
102
+ }
103
+ const handler = new media_stream_handler_1.MediaStreamHandler(targetTwinId, true, this.twinMessaging, {
104
+ useStun: this.options.useStun,
105
+ stunServers: this.options.stunServers,
106
+ connectionTimeout: this.options.connectionTimeout,
107
+ initialRetryDelay: this.options.initialRetryDelay,
108
+ maxRetryDelay: this.options.maxRetryDelay,
109
+ mediaOptions: options,
110
+ }, channelName);
111
+ this.setupMediaStreamHandlerCallbacks(handler, targetTwinId);
112
+ this.mediaStreamHandlers.set(handlerKey, handler);
113
+ try {
114
+ return await handler.connect();
115
+ }
116
+ catch (error) {
117
+ this.mediaStreamHandlers.delete(handlerKey);
118
+ throw error;
119
+ }
120
+ }
121
+ onMediaStream(callback) {
122
+ this.mediaStreamListeners.add(callback);
123
+ }
124
+ offMediaStream(callback) {
125
+ this.mediaStreamListeners.delete(callback);
126
+ }
127
+ async acceptMediaStream(sourceTwinId, options, channelName = 'default') {
128
+ await this.ensureInitialized();
129
+ if (this.isClosed) {
130
+ throw new Error('WebRTCManager has been closed');
131
+ }
132
+ const handlerKey = `${sourceTwinId}:${channelName}`;
133
+ const handler = new media_stream_handler_1.MediaStreamHandler(sourceTwinId, false, this.twinMessaging, {
134
+ useStun: this.options.useStun,
135
+ stunServers: this.options.stunServers,
136
+ connectionTimeout: this.options.connectionTimeout,
137
+ initialRetryDelay: this.options.initialRetryDelay,
138
+ maxRetryDelay: this.options.maxRetryDelay,
139
+ mediaOptions: options,
140
+ }, channelName);
141
+ this.setupMediaStreamHandlerCallbacks(handler, sourceTwinId);
142
+ this.mediaStreamHandlers.set(handlerKey, handler);
143
+ try {
144
+ const stream = await handler.connect();
145
+ this.mediaStreamListeners.forEach((listener) => {
146
+ try {
147
+ listener(stream, sourceTwinId);
148
+ }
149
+ catch (err) {
150
+ console.error('[WebRTCManager] Error in MediaStream listener:', err);
151
+ }
152
+ });
153
+ return stream;
154
+ }
155
+ catch (error) {
156
+ this.mediaStreamHandlers.delete(handlerKey);
157
+ throw error;
158
+ }
159
+ }
160
+ on(event, callback) {
161
+ if (!this.eventListeners.has(event)) {
162
+ this.eventListeners.set(event, new Set());
163
+ }
164
+ this.eventListeners.get(event).add(callback);
165
+ }
166
+ off(event, callback) {
167
+ const listeners = this.eventListeners.get(event);
168
+ if (listeners) {
169
+ listeners.delete(callback);
170
+ }
171
+ }
172
+ static isAvailable() {
173
+ return (0, webrtc_globals_1.isWebRTCAvailable)();
174
+ }
175
+ getActiveDataChannelCount() {
176
+ return this.dataChannelHandlers.size;
177
+ }
178
+ getActiveMediaStreamCount() {
179
+ return this.mediaStreamHandlers.size;
180
+ }
181
+ close() {
182
+ if (this.isClosed)
183
+ return;
184
+ this.isClosed = true;
185
+ this.dataChannelHandlers.forEach((handler) => {
186
+ try {
187
+ handler.close();
188
+ }
189
+ catch (err) {
190
+ console.error('[WebRTCManager] Error closing DataChannel handler:', err);
191
+ }
192
+ });
193
+ this.dataChannelHandlers.clear();
194
+ this.mediaStreamHandlers.forEach((handler) => {
195
+ try {
196
+ handler.close();
197
+ }
198
+ catch (err) {
199
+ console.error('[WebRTCManager] Error closing MediaStream handler:', err);
200
+ }
201
+ });
202
+ this.mediaStreamHandlers.clear();
203
+ this.dataChannelListeners.clear();
204
+ this.mediaStreamListeners.clear();
205
+ this.eventListeners.clear();
206
+ }
207
+ async ensureInitialized() {
208
+ if (this.isInitialized)
209
+ return;
210
+ await (0, webrtc_globals_1.ensureWebRTCGlobals)();
211
+ this.isInitialized = true;
212
+ }
213
+ setupDataChannelHandlerCallbacks(handler, targetTwinId) {
214
+ handler.setCallbacks({
215
+ onConnected: () => {
216
+ this.emit('connected', { targetTwinId, connectionType: 'datachannel' });
217
+ },
218
+ onDisconnected: () => {
219
+ this.emit('disconnected', { targetTwinId, connectionType: 'datachannel' });
220
+ },
221
+ onError: (error) => {
222
+ this.emit('error', { targetTwinId, error });
223
+ },
224
+ onReconnecting: (attempt) => {
225
+ if (this.options.verbose) {
226
+ this.emit('reconnecting', { targetTwinId, attempt });
227
+ }
228
+ },
229
+ onReconnected: (attempt) => {
230
+ if (this.options.verbose) {
231
+ this.emit('reconnected', { targetTwinId, attempt });
232
+ }
233
+ },
234
+ });
235
+ }
236
+ setupMediaStreamHandlerCallbacks(handler, targetTwinId) {
237
+ handler.setCallbacks({
238
+ onConnected: () => {
239
+ this.emit('connected', { targetTwinId, connectionType: 'mediastream' });
240
+ },
241
+ onDisconnected: () => {
242
+ this.emit('disconnected', { targetTwinId, connectionType: 'mediastream' });
243
+ },
244
+ onError: (error) => {
245
+ this.emit('error', { targetTwinId, error });
246
+ },
247
+ onReconnecting: (attempt) => {
248
+ if (this.options.verbose) {
249
+ this.emit('reconnecting', { targetTwinId, attempt });
250
+ }
251
+ },
252
+ onReconnected: (attempt) => {
253
+ if (this.options.verbose) {
254
+ this.emit('reconnected', { targetTwinId, attempt });
255
+ }
256
+ },
257
+ });
258
+ }
259
+ emit(event, data) {
260
+ const listeners = this.eventListeners.get(event);
261
+ if (!listeners)
262
+ return;
263
+ listeners.forEach((callback) => {
264
+ try {
265
+ callback(data);
266
+ }
267
+ catch (err) {
268
+ console.error(`[WebRTCManager] Error in ${event} event listener:`, err);
269
+ }
270
+ });
271
+ }
272
+ }
273
+ exports.WebRTCManager = WebRTCManager;
274
+ //# sourceMappingURL=webrtc-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webrtc-manager.js","sourceRoot":"","sources":["../../../src/services/webrtc/webrtc-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import { PhyHubClient, Instance } from '../index';
2
+ declare function testEvents(client: PhyHubClient, instance: Instance, peerTwinId: string, isInitiator: boolean): Promise<void>;
3
+ declare function testActions(_client: PhyHubClient, instance: Instance, peerTwinId: string, isInitiator: boolean): Promise<void>;
4
+ declare function testDataChannelDefault(client: PhyHubClient, peerTwinId: string, isInitiator: boolean): Promise<void>;
5
+ declare function testDataChannelNamed(client: PhyHubClient, peerTwinId: string, isInitiator: boolean): Promise<void>;
6
+ declare function testMediaStreamConnection(client: PhyHubClient, peerTwinId: string, isInitiator: boolean): Promise<void>;
7
+ export { testEvents, testActions, testDataChannelDefault, testDataChannelNamed, testMediaStreamConnection };
8
+ //# sourceMappingURL=communication-comprehensive-test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"communication-comprehensive-test.d.ts","sourceRoot":"","sources":["../../src/test/communication-comprehensive-test.ts"],"names":[],"mappings":"AAqCA,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AA+BlD,iBAAe,UAAU,CACvB,MAAM,EAAE,YAAY,EACpB,QAAQ,EAAE,QAAQ,EAClB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,OAAO,GACnB,OAAO,CAAC,IAAI,CAAC,CAgEf;AAKD,iBAAe,WAAW,CACxB,OAAO,EAAE,YAAY,EACrB,QAAQ,EAAE,QAAQ,EAClB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,OAAO,GACnB,OAAO,CAAC,IAAI,CAAC,CAmEf;AAKD,iBAAe,sBAAsB,CACnC,MAAM,EAAE,YAAY,EACpB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,OAAO,GACnB,OAAO,CAAC,IAAI,CAAC,CA+Df;AAKD,iBAAe,oBAAoB,CACjC,MAAM,EAAE,YAAY,EACpB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,OAAO,GACnB,OAAO,CAAC,IAAI,CAAC,CA4Ef;AAKD,iBAAe,yBAAyB,CACtC,MAAM,EAAE,YAAY,EACpB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,OAAO,GACnB,OAAO,CAAC,IAAI,CAAC,CA+Cf;AAyGD,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,sBAAsB,EAAE,oBAAoB,EAAE,yBAAyB,EAAE,CAAC"}
@@ -0,0 +1,356 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.testEvents = testEvents;
4
+ exports.testActions = testActions;
5
+ exports.testDataChannelDefault = testDataChannelDefault;
6
+ exports.testDataChannelNamed = testDataChannelNamed;
7
+ exports.testMediaStreamConnection = testMediaStreamConnection;
8
+ const index_1 = require("../index");
9
+ const MESSAGES_PER_TEST = 3;
10
+ const results = [];
11
+ function log(msg) {
12
+ console.log(`[${new Date().toISOString().split('T')[1].slice(0, 8)}] ${msg}`);
13
+ }
14
+ function sleep(ms) {
15
+ return new Promise((resolve) => setTimeout(resolve, ms));
16
+ }
17
+ function addResult(name, passed, details, startTime) {
18
+ const duration = Date.now() - startTime;
19
+ results.push({ name, passed, details, duration });
20
+ const status = passed ? '\x1b[32mPASS\x1b[0m' : '\x1b[31mFAIL\x1b[0m';
21
+ log(`[${status}] ${name}: ${details} (${duration}ms)`);
22
+ }
23
+ async function testEvents(client, instance, peerTwinId, isInitiator) {
24
+ const testName = 'Events (Hub-based)';
25
+ const startTime = Date.now();
26
+ log(`\n=== Test 1: ${testName} ===`);
27
+ try {
28
+ let receivedCount = 0;
29
+ const receivedMessages = [];
30
+ await client.subscribeTwin(peerTwinId);
31
+ log(`Subscribed to peer twin: ${peerTwinId}`);
32
+ instance.on('test-event', (data) => {
33
+ receivedCount++;
34
+ receivedMessages.push(data);
35
+ log(`[EVENT RECEIVED] ${JSON.stringify(data)}`);
36
+ });
37
+ if (isInitiator) {
38
+ log('Waiting for responder to set up listeners...');
39
+ await sleep(3000);
40
+ log('Sending test events...');
41
+ for (let i = 0; i < MESSAGES_PER_TEST; i++) {
42
+ const eventData = { type: 'test', count: i + 1, timestamp: Date.now() };
43
+ log(`[SENDING EVENT] ${JSON.stringify(eventData)}`);
44
+ instance.to(peerTwinId).emit('test-event', eventData);
45
+ await sleep(500);
46
+ }
47
+ await sleep(5000);
48
+ const passed = receivedCount >= MESSAGES_PER_TEST;
49
+ addResult(testName, passed, `Sent ${MESSAGES_PER_TEST}, received echoes: ${receivedCount}`, startTime);
50
+ }
51
+ else {
52
+ log('Waiting for events from initiator...');
53
+ instance.on('test-event', (data) => {
54
+ const echoData = { ...data, echo: true, echoedAt: Date.now() };
55
+ log(`[ECHOING EVENT] ${JSON.stringify(echoData)}`);
56
+ instance.to(peerTwinId).emit('test-event', echoData);
57
+ });
58
+ await sleep(10000);
59
+ const passed = receivedCount >= MESSAGES_PER_TEST;
60
+ addResult(testName, passed, `Received ${receivedCount} events from initiator`, startTime);
61
+ }
62
+ }
63
+ catch (error) {
64
+ addResult(testName, false, error.message, startTime);
65
+ }
66
+ }
67
+ async function testActions(_client, instance, peerTwinId, isInitiator) {
68
+ const testName = 'Actions (Hub-based)';
69
+ const startTime = Date.now();
70
+ log(`\n=== Test 2: ${testName} ===`);
71
+ try {
72
+ let successfulActions = 0;
73
+ let failedActions = 0;
74
+ if (isInitiator) {
75
+ log('Waiting for responder to set up action handlers...');
76
+ await sleep(3000);
77
+ log('Testing instance.to(peerTwinId).emit() with callback (action pattern)...');
78
+ for (let i = 0; i < MESSAGES_PER_TEST; i++) {
79
+ const actionType = 'test-action';
80
+ const actionPayload = {
81
+ command: 'process',
82
+ value: i * 10,
83
+ timestamp: Date.now()
84
+ };
85
+ log(`[SENDING ACTION ${i + 1}] ${actionType}: ${JSON.stringify(actionPayload)}`);
86
+ try {
87
+ const result = await instance.to(peerTwinId).emit(actionType, actionPayload, () => { });
88
+ log(`[ACTION RESPONSE] ${JSON.stringify(result)}`);
89
+ if ((result === null || result === void 0 ? void 0 : result.status) === 'success') {
90
+ successfulActions++;
91
+ }
92
+ else {
93
+ failedActions++;
94
+ }
95
+ }
96
+ catch (err) {
97
+ log(`[ACTION ERROR] ${err.message || JSON.stringify(err)}`);
98
+ failedActions++;
99
+ }
100
+ await sleep(500);
101
+ }
102
+ const passed = successfulActions >= MESSAGES_PER_TEST;
103
+ addResult(testName, passed, `Success: ${successfulActions}, Failed: ${failedActions}`, startTime);
104
+ }
105
+ else {
106
+ log('Setting up request handlers via instance.on()...');
107
+ instance.on('test-action', (message, respond) => {
108
+ log(`[REQUEST RECEIVED] ${JSON.stringify(message)}`);
109
+ if (respond) {
110
+ respond({ status: 'success', message: 'Request processed successfully' });
111
+ }
112
+ });
113
+ await sleep(15000);
114
+ addResult(testName, true, 'Request handler registered and responded', startTime);
115
+ }
116
+ }
117
+ catch (error) {
118
+ addResult(testName, false, error.message, startTime);
119
+ }
120
+ }
121
+ async function testDataChannelDefault(client, peerTwinId, isInitiator) {
122
+ const testName = 'DataChannel Default (P2P)';
123
+ const startTime = Date.now();
124
+ log(`\n=== Test 3: ${testName} ===`);
125
+ try {
126
+ let channel;
127
+ let receivedCount = 0;
128
+ if (isInitiator) {
129
+ channel = await client.getDataChannel(peerTwinId);
130
+ log(`Created default channel. Name: ${channel.getChannelName()}`);
131
+ if (channel.getChannelName() !== 'default') {
132
+ throw new Error(`Expected channel name 'default', got '${channel.getChannelName()}'`);
133
+ }
134
+ channel.onMessage((data) => {
135
+ receivedCount++;
136
+ log(`[DC RECEIVED] ${JSON.stringify(data)}`);
137
+ });
138
+ await sleep(2000);
139
+ for (let i = 0; i < MESSAGES_PER_TEST; i++) {
140
+ const msg = { test: 'default', num: i, timestamp: Date.now() };
141
+ log(`[DC SENDING] ${JSON.stringify(msg)}`);
142
+ channel.send(msg);
143
+ await sleep(300);
144
+ }
145
+ await sleep(3000);
146
+ addResult(testName, receivedCount >= MESSAGES_PER_TEST, `Sent ${MESSAGES_PER_TEST}, received echoes: ${receivedCount}`, startTime);
147
+ channel.close();
148
+ }
149
+ else {
150
+ await new Promise((resolve, reject) => {
151
+ const timeout = setTimeout(() => reject(new Error('Timeout')), 30000);
152
+ client.onDataChannel(peerTwinId, (ch) => {
153
+ clearTimeout(timeout);
154
+ channel = ch;
155
+ log(`Received default channel. Name: ${ch.getChannelName()}`);
156
+ ch.onMessage((data) => {
157
+ receivedCount++;
158
+ log(`[DC RECEIVED] ${JSON.stringify(data)}`);
159
+ ch.send({ echo: data });
160
+ });
161
+ setTimeout(() => {
162
+ addResult(testName, receivedCount >= MESSAGES_PER_TEST, `Received ${receivedCount} messages`, startTime);
163
+ resolve();
164
+ }, 8000);
165
+ });
166
+ });
167
+ }
168
+ }
169
+ catch (error) {
170
+ addResult(testName, false, error.message, startTime);
171
+ }
172
+ }
173
+ async function testDataChannelNamed(client, peerTwinId, isInitiator) {
174
+ const testName = 'DataChannel Named (P2P)';
175
+ const startTime = Date.now();
176
+ log(`\n=== Test 4: ${testName} ===`);
177
+ const channelNames = ['control', 'data'];
178
+ const receivedByChannel = new Map();
179
+ try {
180
+ if (isInitiator) {
181
+ const channels = [];
182
+ for (const name of channelNames) {
183
+ const ch = await client.getDataChannel(peerTwinId, name);
184
+ log(`Created channel '${name}'. Reported name: ${ch.getChannelName()}`);
185
+ if (ch.getChannelName() !== name) {
186
+ throw new Error(`Expected channel name '${name}', got '${ch.getChannelName()}'`);
187
+ }
188
+ receivedByChannel.set(name, 0);
189
+ ch.onMessage(() => {
190
+ receivedByChannel.set(name, (receivedByChannel.get(name) || 0) + 1);
191
+ });
192
+ channels.push(ch);
193
+ }
194
+ await sleep(3000);
195
+ for (let i = 0; i < channels.length; i++) {
196
+ const ch = channels[i];
197
+ for (let j = 0; j < MESSAGES_PER_TEST; j++) {
198
+ ch.send({ channel: channelNames[i], num: j });
199
+ await sleep(100);
200
+ }
201
+ }
202
+ await sleep(3000);
203
+ let allPassed = true;
204
+ for (const name of channelNames) {
205
+ const count = receivedByChannel.get(name) || 0;
206
+ if (count < MESSAGES_PER_TEST)
207
+ allPassed = false;
208
+ }
209
+ const details = channelNames.map(n => `${n}:${receivedByChannel.get(n)}`).join(', ');
210
+ addResult(testName, allPassed, details, startTime);
211
+ channels.forEach(ch => ch.close());
212
+ }
213
+ else {
214
+ const promises = channelNames.map(name => new Promise((resolve, reject) => {
215
+ const timeout = setTimeout(() => reject(new Error(`Timeout for ${name}`)), 30000);
216
+ receivedByChannel.set(name, 0);
217
+ client.onDataChannel(peerTwinId, (ch) => {
218
+ clearTimeout(timeout);
219
+ log(`Received channel '${name}'. Reported: ${ch.getChannelName()}`);
220
+ ch.onMessage((data) => {
221
+ receivedByChannel.set(name, (receivedByChannel.get(name) || 0) + 1);
222
+ ch.send({ echo: data });
223
+ });
224
+ setTimeout(resolve, 10000);
225
+ }, name);
226
+ }));
227
+ await Promise.all(promises);
228
+ const details = channelNames.map(n => `${n}:${receivedByChannel.get(n)}`).join(', ');
229
+ const allPassed = channelNames.every(n => (receivedByChannel.get(n) || 0) >= MESSAGES_PER_TEST);
230
+ addResult(testName, allPassed, details, startTime);
231
+ }
232
+ }
233
+ catch (error) {
234
+ addResult(testName, false, error.message, startTime);
235
+ }
236
+ }
237
+ async function testMediaStreamConnection(client, peerTwinId, isInitiator) {
238
+ const testName = 'MediaStream (P2P)';
239
+ const startTime = Date.now();
240
+ log(`\n=== Test 5: ${testName} ===`);
241
+ try {
242
+ if (isInitiator) {
243
+ const { stream, close } = await client.getMediaStream(peerTwinId);
244
+ log(`MediaStream created. Target: ${stream.getTargetTwinId()}, Channel: ${stream.getChannelName()}`);
245
+ if (stream.getChannelName() !== 'default') {
246
+ throw new Error(`Expected channel name 'default', got '${stream.getChannelName()}'`);
247
+ }
248
+ stream.onTrack((track) => {
249
+ log(`Received track: ${track.kind}`);
250
+ });
251
+ await sleep(5000);
252
+ addResult(testName, true, `Connected to ${stream.getTargetTwinId()}`, startTime);
253
+ close();
254
+ }
255
+ else {
256
+ await new Promise((resolve, reject) => {
257
+ const timeout = setTimeout(() => reject(new Error('Timeout')), 30000);
258
+ client.onMediaStream(peerTwinId, (stream) => {
259
+ clearTimeout(timeout);
260
+ log(`MediaStream received. Channel: ${stream.getChannelName()}`);
261
+ stream.onTrack((track) => {
262
+ log(`Track received: ${track.kind}`);
263
+ });
264
+ setTimeout(() => {
265
+ addResult(testName, true, `Connected from ${stream.getTargetTwinId()}`, startTime);
266
+ resolve();
267
+ }, 5000);
268
+ });
269
+ });
270
+ }
271
+ }
272
+ catch (error) {
273
+ addResult(testName, false, error.message, startTime);
274
+ }
275
+ }
276
+ async function main() {
277
+ var _a;
278
+ console.log('='.repeat(65));
279
+ console.log(' Communication Comprehensive Test Suite');
280
+ console.log(' Hub-based: Events, Actions | P2P: DataChannels, MediaStreams');
281
+ console.log('='.repeat(65));
282
+ if (process.env.PHYHUB_DIRECT !== 'true') {
283
+ console.error('ERROR: Set PHYHUB_DIRECT=true');
284
+ process.exit(1);
285
+ }
286
+ const peerTwinId = process.env.PEER_TWIN_ID;
287
+ const role = (_a = process.env.ROLE) === null || _a === void 0 ? void 0 : _a.toLowerCase();
288
+ const testFilter = process.env.TEST;
289
+ if (!peerTwinId) {
290
+ console.error('ERROR: Set PEER_TWIN_ID');
291
+ process.exit(1);
292
+ }
293
+ if (role !== 'initiator' && role !== 'responder') {
294
+ console.error('ERROR: Set ROLE to initiator or responder');
295
+ process.exit(1);
296
+ }
297
+ const isInitiator = role === 'initiator';
298
+ log(`Role: ${role}`);
299
+ log(`Peer Twin ID: ${peerTwinId}`);
300
+ if (testFilter)
301
+ log(`Running only: ${testFilter}`);
302
+ try {
303
+ log('\nConnecting to PhyHub...');
304
+ const client = await index_1.PhyHubClient.connect();
305
+ log('Connected!');
306
+ const instance = await client.getInstance();
307
+ log(`Instance ID: ${instance.id}\n`);
308
+ const tests = [
309
+ { name: 'events', fn: testEvents, needsInstance: true },
310
+ { name: 'actions', fn: testActions, needsInstance: true },
311
+ { name: 'datachannel', fn: testDataChannelDefault, needsInstance: false },
312
+ { name: 'datachannel-named', fn: testDataChannelNamed, needsInstance: false },
313
+ { name: 'mediastream', fn: testMediaStreamConnection, needsInstance: false },
314
+ ];
315
+ for (const test of tests) {
316
+ if (!testFilter || test.name === testFilter) {
317
+ if (test.needsInstance) {
318
+ await test.fn(client, instance, peerTwinId, isInitiator);
319
+ }
320
+ else {
321
+ await test.fn(client, peerTwinId, isInitiator, undefined);
322
+ }
323
+ await sleep(2000);
324
+ }
325
+ }
326
+ console.log('\n' + '='.repeat(65));
327
+ console.log('TEST SUMMARY');
328
+ console.log('='.repeat(65));
329
+ console.log('Test'.padEnd(40) + 'Status'.padEnd(10) + 'Time');
330
+ console.log('-'.repeat(65));
331
+ let passed = 0;
332
+ let failed = 0;
333
+ for (const r of results) {
334
+ const status = r.passed ? '\x1b[32mPASS\x1b[0m' : '\x1b[31mFAIL\x1b[0m';
335
+ console.log(r.name.padEnd(40) + status.padEnd(15) + `${r.duration}ms`);
336
+ if (r.passed)
337
+ passed++;
338
+ else
339
+ failed++;
340
+ }
341
+ console.log('-'.repeat(65));
342
+ const totalTime = results.reduce((sum, r) => sum + r.duration, 0);
343
+ console.log(`Total: ${passed} passed, ${failed} failed (${totalTime}ms)`);
344
+ console.log('='.repeat(65));
345
+ await sleep(1000);
346
+ process.exit(failed > 0 ? 1 : 0);
347
+ }
348
+ catch (error) {
349
+ console.error('\n[FATAL]', error);
350
+ process.exit(1);
351
+ }
352
+ }
353
+ if (require.main === module) {
354
+ main();
355
+ }
356
+ //# sourceMappingURL=communication-comprehensive-test.js.map