@qikdev/sdk 1.0.6 → 1.0.8

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qikdev/sdk",
3
- "version": "1.0.6",
3
+ "version": "1.0.8",
4
4
  "type": "module",
5
5
  "description": "Promise based Javascript SDK",
6
6
  "main": "./dist/main.js",
@@ -607,7 +607,8 @@ var QikAuth = function(qik) {
607
607
 
608
608
  var currentUser = service.getCurrentUser();
609
609
  if (!currentUser) {
610
- return Promise.reject('No user');
610
+ // Reject with an Error so uncaught rejections carry a stacktrace
611
+ return Promise.reject(new Error('No user'));
611
612
  }
612
613
 
613
614
  // Check if we're in cookie mode
@@ -141,6 +141,15 @@ const QikSocket = function(qik, mode) {
141
141
 
142
142
  dispatcher.dispatch('connected', event);
143
143
 
144
+ // Replay every recorded subscription — frames broadcast before the
145
+ // connection opened were dropped, and reconnects need them resent.
146
+ Object.keys(channels).forEach(function(channel) {
147
+ broadcast({
148
+ action: 'subscribe',
149
+ channel,
150
+ });
151
+ });
152
+
144
153
  // startHeartbeat();
145
154
  }
146
155
 
@@ -181,6 +190,14 @@ const QikSocket = function(qik, mode) {
181
190
  }
182
191
 
183
192
  async function broadcast(data) {
193
+ // A socket that exists but isn't OPEN (CONNECTING, CLOSING or CLOSED)
194
+ // throws InvalidStateError on send. Drop the frame instead — subscribe
195
+ // frames are replayed from `channels` when the connection opens.
196
+ if (!socket || socket.readyState !== WebSocket.OPEN) {
197
+ service.debug ? console.log('[socket] - frame dropped, socket not open', data) : null;
198
+ return;
199
+ }
200
+
184
201
  socket.send(JSON.stringify(data));
185
202
  }
186
203
 
@@ -251,17 +268,10 @@ const QikSocket = function(qik, mode) {
251
268
  }
252
269
 
253
270
  service.debug ? console.log(`[socket] reconnecting...`) : null;
254
-
255
- // Reconnect all listeners
256
- const result = await service.connect();
257
-
258
- // Resubscribe to all previously connected channels
259
- const subscribedChannels = Object.keys(channels);
260
- subscribedChannels.forEach(function(channel) {
261
- service.subscribe(channel);
262
- })
263
271
 
264
- return result;
272
+ // Reconnect all listeners. Previously subscribed channels are replayed
273
+ // by socketOpened() the moment the connection opens.
274
+ return await service.connect();
265
275
  }
266
276
 
267
277
 
@@ -243,15 +243,49 @@ service.parseURL = function (string) {
243
243
  //TODO: test this more.
244
244
  string = string.replace(/\s/g, "");
245
245
 
246
- var valid = RegExp(
247
- "(https?:\\/\\/)?((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|((\\d{1,3}\\.){3}\\d{1,3}))(\\:\\d+)?(\\/[-a-z\\d%_.~+@]*)*(\\?[;&a-z\\d%_.~+=-@]*)?(\\#[-a-z\\d_@]*)?$",
248
- "i",
249
- ).test(string);
246
+ // Validate the host portion in linear time. The previous single-regex
247
+ // validation suffered catastrophic backtracking (40s+ freezing the main
248
+ // thread) on long URLs it couldn't match, and rejected legitimate URLs with
249
+ // hyphens in the query string. Anything after the host is accepted as-is.
250
+ var host = String(string)
251
+ .replace(/^https?:\/\//i, "")
252
+ .split(/[/?#]/)[0];
253
+
254
+ var portIndex = host.lastIndexOf(":");
255
+ if (portIndex !== -1) {
256
+ if (!/^\d+$/.test(host.slice(portIndex + 1))) {
257
+ return false;
258
+ }
259
+ host = host.slice(0, portIndex);
260
+ }
250
261
 
251
- if (!valid) {
262
+ if (!host) {
252
263
  return false;
253
264
  }
254
265
 
266
+ var labels = host.split(".");
267
+ var isIPv4 =
268
+ labels.length === 4 &&
269
+ labels.every(function (label) {
270
+ return /^\d{1,3}$/.test(label);
271
+ });
272
+
273
+ if (!isIPv4) {
274
+ // Domains need at least two labels ("roger" is invalid, "www.roger" is
275
+ // allowed) and an alphabetic final label of 2+ characters
276
+ if (labels.length < 2) {
277
+ return false;
278
+ }
279
+
280
+ var validLabels = labels.every(function (label) {
281
+ return /^[a-z\d]([a-z\d-]*[a-z\d])?$/i.test(label);
282
+ });
283
+
284
+ if (!validLabels || !/^[a-z]{2,}$/i.test(labels[labels.length - 1])) {
285
+ return false;
286
+ }
287
+ }
288
+
255
289
  ///////////////////////////
256
290
 
257
291
  return withHttp(string);
package/src/version.js CHANGED
@@ -1 +1 @@
1
- export const version = "1.0.6";
1
+ export const version = "1.0.8";