@reactoo/watchtogether-sdk-js 2.7.21 → 2.7.24

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.
@@ -161,6 +161,14 @@
161
161
  Instance.room.getSessionByConstructId(constructId).toggleVideo()
162
162
  }
163
163
 
164
+ function checkConnection() {
165
+ return Instance.iot.checkConnection()
166
+ }
167
+
168
+ function disconnect() {
169
+ return Instance.iot.disconnect()
170
+ }
171
+
164
172
  function toggleAudio() {
165
173
  Instance.room.getSessionByConstructId(constructId).toggleAudio()
166
174
  }
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@reactoo/watchtogether-sdk-js",
3
- "version": "2.7.21",
3
+ "version": "2.7.24",
4
4
  "description": "Javascript SDK for Reactoo",
5
5
  "main": "src/index.js",
6
6
  "unpkg": "dist/watchtogether-sdk.min.js",
7
7
  "scripts": {
8
- "build": "webpack --env dev && webpack --env build",
9
- "dev": "webpack --progress --colors --watch --env dev"
8
+ "build": "webpack --mode=production",
9
+ "dev": "webpack --mode=development --watch"
10
10
  },
11
11
  "repository": {
12
12
  "type": "git",
@@ -25,24 +25,27 @@
25
25
  },
26
26
  "homepage": "https://github.com/picitujeromanov/WR-SDK",
27
27
  "devDependencies": {
28
- "@babel/core": "^7.16.5",
29
- "@babel/plugin-proposal-class-properties": "^7.16.5",
30
- "@babel/plugin-proposal-optional-chaining": "^7.16.5",
31
- "@babel/plugin-proposal-private-property-in-object": "^7.16.5",
32
- "@babel/preset-env": "^7.16.5",
33
- "acorn": "^6.4.2",
34
- "babel-core": "^6.26.3",
35
- "babel-loader": "^8.2.3",
36
- "babel-plugin-add-module-exports": "^1.0.4",
37
- "babel-preset-env": "^1.7.0",
38
- "babel-preset-minify": "^0.5.1",
39
- "terser-webpack-plugin": "^1.4.5",
40
- "webpack": "^4.46.0",
41
- "webpack-cli": "^3.3.12",
42
- "yargs": "^10.1.2"
28
+ "@babel/core": "^7.22.10",
29
+ "@babel/plugin-proposal-class-properties": "^7.18.6",
30
+ "@babel/plugin-proposal-optional-chaining": "^7.21.0",
31
+ "@babel/plugin-proposal-private-property-in-object": "^7.21.11",
32
+ "@babel/preset-env": "^7.22.10",
33
+ "babel-loader": "^9.1.3",
34
+ "buffer": "^6.0.3",
35
+ "clean-webpack-plugin": "^4.0.0",
36
+ "crypto-browserify": "^3.12.0",
37
+ "process": "^0.11.10",
38
+ "stream-browserify": "^3.0.0",
39
+ "terser-webpack-plugin": "^5.3.9",
40
+ "util": "^0.12.4",
41
+ "webpack": "^5.88.2",
42
+ "webpack-cli": "^5.1.4",
43
+ "worker-loader": "^3.0.8",
44
+ "yargs": "^17.7.2"
43
45
  },
44
46
  "dependencies": {
45
47
  "aws-iot-device-sdk": "^2.2.15",
48
+ "aws-iot-device-sdk-v2": "^1.21.1",
46
49
  "serialize-error": "9.1.0",
47
50
  "swagger-client": "3.18.0",
48
51
  "webrtc-adapter": "^9.0.1"
package/src/models/iot.js CHANGED
@@ -1,28 +1,26 @@
1
1
  'use strict';
2
2
 
3
3
  let iot = function () {
4
- let __currentTopics = [];
5
- let __ = null;
4
+ let __currentTopics = new Set();
5
+ let visibilityChangeHandler = null;
6
+
6
7
  return {
7
8
 
8
9
  __promise: null,
9
-
10
- __reconnect: (err) => {
11
-
12
- this.__privates.iot.log('MQTT Error:', err, `Is event error: ${err instanceof Event}`);
13
-
14
- if(err instanceof Event && err.type === 'error') {
15
- this.__privates.iot.log('SDK MQTT Reconnection attempt');
16
- clearTimeout(__);
17
- __ = setTimeout(() => {
18
- this.iot.iotLogin(true, true).catch((e) => this.__privates.iot.log('MQTT Connection Error:', e))
19
- }, 1000);
20
- }
21
- },
22
-
10
+
23
11
  __updateCredentials: () => {
24
- this.iot.getCredentials()
25
- .then(response => this.__privates.iot.updateWebSocketCredentials(response.data.credentials.accessKeyId, response.data.credentials.secretAccessKey, response.data.credentials.sessionToken, response.data.credentials.expiration));
12
+ return this.iot.getCredentials()
13
+ .then(response => this.__privates.iot.updateWebSocketCredentials(
14
+ response.data.credentials.accessKeyId,
15
+ response.data.credentials.secretAccessKey,
16
+ response.data.credentials.sessionToken,
17
+ response.data.credentials.expiration
18
+ ))
19
+ .catch(error => {
20
+ this.__privates.iot.log('Failed to update credentials:', error);
21
+ // Let the error propagate to be handled by the Iot class
22
+ throw error;
23
+ });
26
24
  },
27
25
 
28
26
  getCredentials: () => {
@@ -31,48 +29,87 @@ let iot = function () {
31
29
 
32
30
  },
33
31
 
34
- iotLogin: (subscribeToSuggestedTopics = true, forceDisconnect = false) => {
35
- this.iot.$off('error', this.iot.__reconnect, this);
32
+ iotLogin: (subscribeToSuggestedTopics = true) => {
36
33
  this.iot.__promise = new Promise((resolve, reject) => {
37
34
  this.iot.getCredentials()
38
35
  .then(response => {
39
36
  return Promise.all([
40
37
  response.data.suggestedTopics,
41
- this.__privates.iot.connect(response.data.endpoint, response.data.clientId, response.data.region, response.data.credentials.accessKeyId, response.data.credentials.secretAccessKey, response.data.credentials.sessionToken, response.data.credentials.expiration, forceDisconnect)
38
+ this.__privates.iot.connect(
39
+ response.data.endpoint,
40
+ response.data.clientId,
41
+ response.data.region,
42
+ response.data.credentials.accessKeyId,
43
+ response.data.credentials.secretAccessKey,
44
+ response.data.credentials.sessionToken,
45
+ response.data.credentials.expiration,
46
+ )
42
47
  ])
43
48
  })
44
49
  .then(resolve)
45
50
  .catch(reject)
46
51
  });
47
52
 
48
- let __currentTopicsCopy = [...__currentTopics];
49
- __currentTopics.length = 0;
50
-
53
+ let __currentTopicsCopy = new Set(__currentTopics); // Keep this line
54
+ __currentTopics.clear();
55
+
56
+ this.iot.$on('connect', () => {
57
+ this.__privates.iot.log('MQTT client connected');
58
+ this.iot.setupVisibilityChangeListener();
59
+ });
60
+
61
+ this.iot.$on('closed', () => {
62
+ this.__privates.iot.log('MQTT client closed');
63
+ this.iot.disableVisibilityChangeListener();
64
+ });
65
+
66
+ this.iot.$on('error', () => {
67
+ this.__privates.iot.log('MQTT client error');
68
+ });
69
+
70
+ this.iot.$on('disconnect', () => {
71
+ this.__privates.iot.log('MQTT client disconnect');
72
+ });
73
+
74
+ this.iot.$on('interrupt', () => {
75
+ this.__privates.iot.log('MQTT client interrupt');
76
+ });
77
+
78
+ this.iot.$on('resume', () => {
79
+ this.__privates.iot.log('MQTT client resume');
80
+ });
81
+
82
+ this.iot.$on('connection_success', () => {
83
+ this.__privates.iot.log('MQTT client connection_success');
84
+ });
85
+
86
+ this.iot.$on('connection_failure', () => {
87
+ this.__privates.iot.log('MQTT client connection_failure');
88
+ });
89
+
51
90
  this.iot.__promise
52
91
  .then(([suggestedTopic, instance]) => {
53
92
  if(!subscribeToSuggestedTopics) {
54
93
  return Promise.resolve(instance)
55
94
  }
56
- let topics = [...suggestedTopic, ...__currentTopicsCopy];
57
- topics = topics.filter((c, index) => {
58
- return topics.indexOf(c) === index;
59
- });
60
- return Promise.all(topics.map(topic => this.iot.subscribe(topic))).then(() => instance)
95
+ let topics = new Set([...suggestedTopic, ...__currentTopicsCopy]); // Filter out any undefined or null topics
96
+ return Promise.all(Array.from(topics).map(topic => this.iot.subscribe(topic))).then(() => instance)
61
97
  })
62
98
  .then((instance) => {
63
- this.iot.$on('error', this.iot.__reconnect, this);
64
99
  this.iot.$on('updateCredentials', this.iot.__updateCredentials, this);
65
100
  return instance;
101
+ })
102
+ .catch((error) => {
103
+ this.__privates.iot.log('MQTT Login Error:', error);
104
+ throw error;
66
105
  });
67
-
106
+
68
107
  return this.iot.__promise;
69
108
  },
70
109
 
71
110
  iotLogout: (keepCurrentTopics = false) => {
72
- this.iot.$off('error', this.iot.__reconnect, this);
73
- this.iot.$off('updateCredentials', this.iot.__updateCredentials, this);
74
111
  if(!keepCurrentTopics) {
75
- __currentTopics.length = 0;
112
+ __currentTopics.clear();
76
113
  }
77
114
  return this.__privates.iot.disconnect()
78
115
  .then(() => {
@@ -86,16 +123,15 @@ let iot = function () {
86
123
  },
87
124
 
88
125
  subscribe: (topic) => {
89
- if(__currentTopics.indexOf(topic) === -1) {
90
- __currentTopics.push(topic);
126
+ if(!__currentTopics.has(topic)) {
127
+ __currentTopics.add(topic);
91
128
  if(!this.iot.__promise) return Promise.resolve('not_connected');
92
129
  return this.iot.__promise.then(() => this.__privates.iot.subscribe(topic));
93
130
  }
94
131
  },
95
132
 
96
133
  unsubscribe: (topic) => {
97
- let index = __currentTopics.indexOf(topic);
98
- (index > -1) && __currentTopics.splice(index, 1);
134
+ __currentTopics.delete(topic);
99
135
  if(!this.iot.__promise) return Promise.resolve('not_connected');
100
136
  return this.iot.__promise.then(() => this.__privates.iot.unsubscribe(topic));
101
137
  },
@@ -118,6 +154,34 @@ let iot = function () {
118
154
 
119
155
  $clear: () => {
120
156
  return this.__privates.iot.clear();
157
+ },
158
+
159
+ checkConnection: () => {
160
+ return this.__privates.iot.checkConnection()
161
+ .catch(error => {
162
+ this.__privates.iot.log('Connection check failed:', error);
163
+ return this.iot.__updateCredentials();
164
+ });
165
+ },
166
+
167
+ setupVisibilityChangeListener: () => {
168
+ if (visibilityChangeHandler) {
169
+ // Listener is already set up
170
+ return;
171
+ }
172
+ visibilityChangeHandler = () => {
173
+ if (!document.hidden) {
174
+ this.iot.checkConnection();
175
+ }
176
+ };
177
+ document.addEventListener('visibilitychange', visibilityChangeHandler);
178
+ },
179
+
180
+ disableVisibilityChangeListener: () => {
181
+ if (visibilityChangeHandler) {
182
+ document.removeEventListener('visibilitychange', visibilityChangeHandler);
183
+ visibilityChangeHandler = null;
184
+ }
121
185
  }
122
186
  };
123
187
  };
@@ -147,14 +147,15 @@ let room = function () {
147
147
  }
148
148
  }))
149
149
  },
150
-
151
- getInviteUrl: (roomId, domain, url) => {
150
+
151
+ getInviteUrl: ({roomId, domain, url, autologin}) => {
152
152
  return this.__privates.auth.__client
153
153
  .then(client => client.apis.wt.invite({}, {
154
154
  requestBody: {
155
155
  roomId,
156
156
  domain: domain || location.host,
157
- url: url || location.href
157
+ url: url || location.href,
158
+ ...(autologin && {autologin}),
158
159
  }
159
160
  }))
160
161
  },
@@ -210,11 +211,11 @@ let room = function () {
210
211
 
211
212
  },
212
213
 
213
- roomRecorder: ({roomId, operation = 'get', config, outputs, destinationIds, destinations, screenWidth, screenHeight, payload} = {}) => {
214
+ roomRecorder: ({roomId, operation = 'get', config, outputs, destinationIds, destinations, screenWidth, screenHeight, payload, requestId} = {}) => {
214
215
  return this.__privates.auth.__client
215
216
  .then(client => client.apis.wt.recordRoom({}, {
216
217
  requestBody: {
217
- roomId, operation, config, outputs, destinationIds, destinations, screenWidth, screenHeight, payload
218
+ roomId, operation, config, outputs, destinationIds, destinations, screenWidth, screenHeight, payload, requestId
218
219
  }
219
220
  }))
220
221
  },
@@ -0,0 +1,84 @@
1
+ import { mqtt, iot } from 'aws-iot-device-sdk-v2';
2
+
3
+ let connection = null;
4
+
5
+ self.onmessage = function(e) {
6
+ const { action, payload } = e.data;
7
+
8
+ switch (action) {
9
+ case 'connect':
10
+ connect(payload);
11
+ break;
12
+ case 'disconnect':
13
+ disconnect();
14
+ break;
15
+ case 'subscribe':
16
+ subscribe(payload.topic);
17
+ break;
18
+ case 'unsubscribe':
19
+ unsubscribe(payload.topic);
20
+ break;
21
+ case 'send':
22
+ send(payload.topic, payload.message);
23
+ break;
24
+ }
25
+ };
26
+
27
+ function connect({ apiMqttUrl, apiMqttClientId, region, accessKeyId, secretAccessKey, sessionToken }) {
28
+ const configBuilder = iot.AwsIotMqttConnectionConfigBuilder.new_with_websockets();
29
+
30
+ configBuilder.with_clean_session(true);
31
+ configBuilder.with_client_id(apiMqttClientId);
32
+ configBuilder.with_endpoint(apiMqttUrl);
33
+ configBuilder.with_credentials(region, accessKeyId, secretAccessKey, sessionToken);
34
+ configBuilder.with_keep_alive_seconds(30);
35
+ configBuilder.with_ping_timeout_ms(3000);
36
+
37
+ const config = configBuilder.build();
38
+
39
+ const client = new mqtt.MqttClient();
40
+ connection = client.new_connection(config);
41
+
42
+ connection.on('connect', () => {
43
+ self.postMessage({ event: 'connect' });
44
+ });
45
+
46
+ connection.on('disconnect', () => {
47
+ self.postMessage({ event: 'disconnect' });
48
+ });
49
+
50
+ connection.on('error', (error) => {
51
+ self.postMessage({ event: 'error', error: error.toString() });
52
+ });
53
+
54
+ connection.on('message', (topic, payload) => {
55
+ self.postMessage({ event: 'message', topic, payload: new Uint8Array(payload) });
56
+ });
57
+
58
+ connection.connect();
59
+ }
60
+
61
+ function disconnect() {
62
+ if (connection) {
63
+ connection.disconnect();
64
+ connection = null;
65
+ }
66
+ }
67
+
68
+ function subscribe(topic) {
69
+ if (connection) {
70
+ connection.subscribe(topic, mqtt.QoS.AtLeastOnce);
71
+ }
72
+ }
73
+
74
+ function unsubscribe(topic) {
75
+ if (connection) {
76
+ connection.unsubscribe(topic);
77
+ }
78
+ }
79
+
80
+ function send(topic, message) {
81
+ if (connection) {
82
+ connection.publish(topic, message, mqtt.QoS.AtLeastOnce);
83
+ }
84
+ }