quickblox 2.21.0-alpha.1 → 2.21.0-alpha.2

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,7 +1,7 @@
1
1
  {
2
2
  "name": "quickblox",
3
3
  "description": "QuickBlox JavaScript SDK",
4
- "version": "2.21.0-alpha.1",
4
+ "version": "2.21.0-alpha.2",
5
5
  "homepage": "https://quickblox.com/developers/Javascript",
6
6
  "main": "src/qbMain.js",
7
7
  "types": "quickblox.d.ts",
package/quickblox.d.ts CHANGED
@@ -144,6 +144,10 @@ export declare interface QBConfig {
144
144
  pingDebug?: boolean
145
145
  pingLocalhostTimeInterval?: number
146
146
  chatReconnectionTimeInterval?: number
147
+ /** If true, QB.init will do a short synchronous block after starting account_settings. Default: true. */
148
+ initBlockOnSettings?: boolean
149
+ /** Busy-wait duration in ms used when initBlockOnSettings=true. Default: 3000. */
150
+ initBlockDurationMs?: number
147
151
  }
148
152
 
149
153
  export declare interface QBError {
@@ -1637,6 +1641,13 @@ export class QuickBlox {
1637
1641
  config?: QBConfig,
1638
1642
  ): void
1639
1643
 
1644
+ /**
1645
+ * Resolves when internal async initialization (e.g., fetching `account_settings`
1646
+ * and rebinding endpoints) is finished. If no async work was scheduled during
1647
+ * `init`, it resolves immediately.
1648
+ */
1649
+ ready(): Promise<void>
1650
+
1640
1651
  /**
1641
1652
  * Init QuickBlox SDK with User Account data to start session with token
1642
1653
  * ([read more](https://docs.quickblox.com/docs/js-setup#initialize-quickblox-sdk-without-authorization-key-and-secret)).
package/quickblox.js CHANGED
@@ -55078,8 +55078,8 @@ module.exports = StreamManagement;
55078
55078
  */
55079
55079
 
55080
55080
  var config = {
55081
- version: '2.20.0',
55082
- buildNumber: '1166',
55081
+ version: '2.21.0',
55082
+ buildNumber: '1167',
55083
55083
  creds: {
55084
55084
  'appId': 0,
55085
55085
  'authKey': '',
@@ -55102,6 +55102,8 @@ var config = {
55102
55102
  },
55103
55103
  pingTimeout: 1,
55104
55104
  pingDebug: false,
55105
+ initBlockOnSettings: false,
55106
+ initBlockDurationMs: 3000,
55105
55107
  pingLocalhostTimeInterval: 5,
55106
55108
  chatReconnectionTimeInterval: 3,
55107
55109
  webrtc: {
@@ -55210,6 +55212,7 @@ const MessageProxy = require("./modules/chat/qbMessage");
55210
55212
  const Chat = require("./modules/chat/qbChat");
55211
55213
  const DialogProxy = require("./modules/chat/qbDialog");
55212
55214
  const WebRTCClient = require("./modules/webrtc/qbWebRTCClient");
55215
+ const PushNotifications = require("./modules/qbPushNotifications");
55213
55216
 
55214
55217
  // Actual QuickBlox API starts here
55215
55218
  function QuickBlox() {}
@@ -55294,6 +55297,10 @@ QuickBlox.prototype = {
55294
55297
  } else {
55295
55298
  this.webrtc = false;
55296
55299
  }
55300
+ this._initReady = Promise.resolve();
55301
+ var initBlockOnSettings = (typeof config.initBlockOnSettings === 'boolean') ? config.initBlockOnSettings : true;
55302
+ var initBlockDurationMs = (typeof config.initBlockDurationMs === 'number') ? config.initBlockDurationMs : 3000;
55303
+
55297
55304
 
55298
55305
  // Initialization by outside token
55299
55306
  if (typeof appIdOrToken === 'string' && (!authKeyOrAppId || typeof authKeyOrAppId === 'number') && !authSecret) {
@@ -55321,42 +55328,148 @@ QuickBlox.prototype = {
55321
55328
  config.urls.account,
55322
55329
  config.urls.type
55323
55330
  ].join('');
55331
+
55332
+ // generic function to capture (extract) listeners
55333
+ var preserveListeners = function (obj) {
55334
+ var map = {};
55335
+ if (!obj) return map;
55336
+ Object.keys(obj).forEach(function (k) {
55337
+ if (/^on[A-Z]/.test(k) && typeof obj[k] === 'function') {
55338
+ map[k] = obj[k];
55339
+ }
55340
+ });
55341
+ return map;
55342
+ };
55343
+
55344
+ // restore
55345
+ var reassignListeners = function (target, map) {
55346
+ if (!target || !map) return;
55347
+ Object.keys(map).forEach(function (k) {
55348
+ target[k] = map[k];
55349
+ });
55350
+ };
55351
+
55324
55352
  // account settings
55325
55353
  var self = this;
55326
- this.service.ajax({
55327
- url: accountSettingsUrl
55328
- }, function (err, response) {
55329
- if (!err && typeof response === 'object') {
55330
- var update = {
55331
- endpoints: {
55332
- api: response.api_endpoint.replace(/^https?:\/\//, ''),
55333
- chat: response.chat_endpoint
55334
- }
55335
- };
55336
- config.set(update);
55337
- //
55338
- self.chat = new Chat(self.service);
55339
- self.chat.dialog = new DialogProxy(self.service);
55340
- self.chat.message = new MessageProxy(self.service);
55341
- //
55342
- if (Utils.getEnv().browser) {
55343
- /** add adapter.js*/
55344
- require('webrtc-adapter');
55345
-
55346
- /** add WebRTC API if API is avaible */
55347
- if( Utils.isWebRTCAvailble() ) {
55348
- var WebRTCClient = require('./modules/webrtc/qbWebRTCClient');
55349
- self.webrtc = new WebRTCClient(self.service, self.chat);
55354
+ //
55355
+ this._initReady = new Promise(function(resolve) {
55356
+ self.service.ajax({ url: accountSettingsUrl }, function (err, response) {
55357
+ // resolve in any case (so legacy clients won’t hang)
55358
+ if (!err && typeof response === 'object') {
55359
+ // 1) apply endpoints
55360
+ var update = {
55361
+ endpoints: {
55362
+ api: response.api_endpoint.replace(/^https?:\/\//, ''),
55363
+ chat: response.chat_endpoint
55364
+ }
55365
+ };
55366
+ config.set(update);
55367
+
55368
+ // 2) preserve ALL previously assigned listeners (dynamically)
55369
+ var savedChatListeners = preserveListeners(self.chat);
55370
+ var savedWebRTCListeners = preserveListeners(self.webrtc);
55371
+
55372
+ // 3) re-create dependent components for the new endpoints
55373
+ self.pushnotifications = new PushNotifications(self.service);
55374
+ self.chat = new Chat(self.service);
55375
+ self.chat.dialog = new DialogProxy(self.service);
55376
+ self.chat.message = new MessageProxy(self.service);
55377
+
55378
+ if (Utils.getEnv().browser) {
55379
+ require('webrtc-adapter');
55380
+ if (Utils.isWebRTCAvailble()) {
55381
+ var WebRTCClient = require('./modules/webrtc/qbWebRTCClient');
55382
+ self.webrtc = new WebRTCClient(self.service, self.chat);
55383
+ } else {
55384
+ self.webrtc = false;
55385
+ }
55350
55386
  } else {
55351
55387
  self.webrtc = false;
55352
55388
  }
55353
- } else {
55354
- self.webrtc = false;
55389
+
55390
+ // 4) reattach listeners to the new instances
55391
+ reassignListeners(self.chat, savedChatListeners);
55392
+ reassignListeners(self.webrtc, savedWebRTCListeners);
55355
55393
  }
55356
- //
55357
- }
55394
+
55395
+ resolve(); // init completed (with or without migration)
55396
+ });
55358
55397
  });
55398
+ //
55399
+ // previous version with callback
55400
+ // this.service.ajax({
55401
+ // url: accountSettingsUrl
55402
+ // }, function (err, response) {
55403
+ // if (!err && typeof response === 'object') {
55404
+ // var update = {
55405
+ // endpoints: {
55406
+ // api: response.api_endpoint.replace(/^https?:\/\//, ''),
55407
+ // chat: response.chat_endpoint
55408
+ // }
55409
+ // };
55410
+ // config.set(update);
55411
+ // //
55412
+ // self.pushnotifications = new PushNotifications(self.service);
55413
+ // self.chat = new Chat(self.service);
55414
+ // self.chat.dialog = new DialogProxy(self.service);
55415
+ // self.chat.message = new MessageProxy(self.service);
55416
+ // //
55417
+ // if (Utils.getEnv().browser) {
55418
+ // /** add adapter.js*/
55419
+ // require('webrtc-adapter');
55420
+ //
55421
+ // /** add WebRTC API if API is avaible */
55422
+ // if( Utils.isWebRTCAvailble() ) {
55423
+ // var WebRTCClient = require('./modules/webrtc/qbWebRTCClient');
55424
+ // self.webrtc = new WebRTCClient(self.service, self.chat);
55425
+ // } else {
55426
+ // self.webrtc = false;
55427
+ // }
55428
+ // } else {
55429
+ // self.webrtc = false;
55430
+ // }
55431
+ // //
55432
+ // }
55433
+ // });
55434
+ //
55359
55435
  }
55436
+ //
55437
+ // --- artificial sync delay to increase the chance account_settings completes before legacy code continues
55438
+ // enabled only when shouldGetSettings && config.initBlockOnSettings !== false
55439
+ if (shouldGetSettings && initBlockOnSettings) {
55440
+ try {
55441
+ var __qb_init_block_until__ = Date.now() + initBlockDurationMs;
55442
+ while (Date.now() < __qb_init_block_until__) {
55443
+ // intentional busy-wait (do not remove)
55444
+ }
55445
+ } catch (_) { /* never throw from here */ }
55446
+ }
55447
+ //
55448
+
55449
+ },
55450
+
55451
+ /**
55452
+ * Wait until SDK async initialization finishes (if any).
55453
+ * It resolves after internal tasks like fetching `account_settings`,
55454
+ * rebinding endpoints, and re-instantiating dependent modules are completed.
55455
+ * If no async work was scheduled during `QB.init(...)`, it resolves immediately.
55456
+ *
55457
+ * @memberof QB
55458
+ * @returns {Promise<void>} A promise that resolves when initialization is complete.
55459
+ *
55460
+ * @example
55461
+ * QB.init(appId, authKey, authSecret, accountKey, config);
55462
+ * QB.ready().then(function () {
55463
+ * // Safe point: endpoints are updated, chat/webrtc are re-created, listeners preserved.
55464
+ * QB.startSession({ login: 'john', password: 'secret' }, function (err, res) {
55465
+ * if (!err) {
55466
+ * QB.chat.connect({ userId: res.user.id, password: res.session.token }, function(){});
55467
+ * }
55468
+ * });
55469
+ * });
55470
+ */
55471
+ ready: function() {
55472
+ return this._initReady || Promise.resolve();
55360
55473
  },
55361
55474
 
55362
55475
  /**
package/src/qbConfig.js CHANGED
@@ -12,8 +12,8 @@
12
12
  */
13
13
 
14
14
  var config = {
15
- version: '2.20.0',
16
- buildNumber: '1166',
15
+ version: '2.21.0',
16
+ buildNumber: '1167',
17
17
  creds: {
18
18
  'appId': 0,
19
19
  'authKey': '',
@@ -36,6 +36,8 @@ var config = {
36
36
  },
37
37
  pingTimeout: 1,
38
38
  pingDebug: false,
39
+ initBlockOnSettings: false,
40
+ initBlockDurationMs: 3000,
39
41
  pingLocalhostTimeInterval: 5,
40
42
  chatReconnectionTimeInterval: 3,
41
43
  webrtc: {
package/src/qbMain.js CHANGED
@@ -12,6 +12,7 @@ const MessageProxy = require("./modules/chat/qbMessage");
12
12
  const Chat = require("./modules/chat/qbChat");
13
13
  const DialogProxy = require("./modules/chat/qbDialog");
14
14
  const WebRTCClient = require("./modules/webrtc/qbWebRTCClient");
15
+ const PushNotifications = require("./modules/qbPushNotifications");
15
16
 
16
17
  // Actual QuickBlox API starts here
17
18
  function QuickBlox() {}
@@ -96,6 +97,10 @@ QuickBlox.prototype = {
96
97
  } else {
97
98
  this.webrtc = false;
98
99
  }
100
+ this._initReady = Promise.resolve();
101
+ var initBlockOnSettings = (typeof config.initBlockOnSettings === 'boolean') ? config.initBlockOnSettings : true;
102
+ var initBlockDurationMs = (typeof config.initBlockDurationMs === 'number') ? config.initBlockDurationMs : 3000;
103
+
99
104
 
100
105
  // Initialization by outside token
101
106
  if (typeof appIdOrToken === 'string' && (!authKeyOrAppId || typeof authKeyOrAppId === 'number') && !authSecret) {
@@ -123,42 +128,148 @@ QuickBlox.prototype = {
123
128
  config.urls.account,
124
129
  config.urls.type
125
130
  ].join('');
131
+
132
+ // generic function to capture (extract) listeners
133
+ var preserveListeners = function (obj) {
134
+ var map = {};
135
+ if (!obj) return map;
136
+ Object.keys(obj).forEach(function (k) {
137
+ if (/^on[A-Z]/.test(k) && typeof obj[k] === 'function') {
138
+ map[k] = obj[k];
139
+ }
140
+ });
141
+ return map;
142
+ };
143
+
144
+ // restore
145
+ var reassignListeners = function (target, map) {
146
+ if (!target || !map) return;
147
+ Object.keys(map).forEach(function (k) {
148
+ target[k] = map[k];
149
+ });
150
+ };
151
+
126
152
  // account settings
127
153
  var self = this;
128
- this.service.ajax({
129
- url: accountSettingsUrl
130
- }, function (err, response) {
131
- if (!err && typeof response === 'object') {
132
- var update = {
133
- endpoints: {
134
- api: response.api_endpoint.replace(/^https?:\/\//, ''),
135
- chat: response.chat_endpoint
136
- }
137
- };
138
- config.set(update);
139
- //
140
- self.chat = new Chat(self.service);
141
- self.chat.dialog = new DialogProxy(self.service);
142
- self.chat.message = new MessageProxy(self.service);
143
- //
144
- if (Utils.getEnv().browser) {
145
- /** add adapter.js*/
146
- require('webrtc-adapter');
147
-
148
- /** add WebRTC API if API is avaible */
149
- if( Utils.isWebRTCAvailble() ) {
150
- var WebRTCClient = require('./modules/webrtc/qbWebRTCClient');
151
- self.webrtc = new WebRTCClient(self.service, self.chat);
154
+ //
155
+ this._initReady = new Promise(function(resolve) {
156
+ self.service.ajax({ url: accountSettingsUrl }, function (err, response) {
157
+ // resolve in any case (so legacy clients won’t hang)
158
+ if (!err && typeof response === 'object') {
159
+ // 1) apply endpoints
160
+ var update = {
161
+ endpoints: {
162
+ api: response.api_endpoint.replace(/^https?:\/\//, ''),
163
+ chat: response.chat_endpoint
164
+ }
165
+ };
166
+ config.set(update);
167
+
168
+ // 2) preserve ALL previously assigned listeners (dynamically)
169
+ var savedChatListeners = preserveListeners(self.chat);
170
+ var savedWebRTCListeners = preserveListeners(self.webrtc);
171
+
172
+ // 3) re-create dependent components for the new endpoints
173
+ self.pushnotifications = new PushNotifications(self.service);
174
+ self.chat = new Chat(self.service);
175
+ self.chat.dialog = new DialogProxy(self.service);
176
+ self.chat.message = new MessageProxy(self.service);
177
+
178
+ if (Utils.getEnv().browser) {
179
+ require('webrtc-adapter');
180
+ if (Utils.isWebRTCAvailble()) {
181
+ var WebRTCClient = require('./modules/webrtc/qbWebRTCClient');
182
+ self.webrtc = new WebRTCClient(self.service, self.chat);
183
+ } else {
184
+ self.webrtc = false;
185
+ }
152
186
  } else {
153
187
  self.webrtc = false;
154
188
  }
155
- } else {
156
- self.webrtc = false;
189
+
190
+ // 4) reattach listeners to the new instances
191
+ reassignListeners(self.chat, savedChatListeners);
192
+ reassignListeners(self.webrtc, savedWebRTCListeners);
157
193
  }
158
- //
159
- }
194
+
195
+ resolve(); // init completed (with or without migration)
196
+ });
160
197
  });
198
+ //
199
+ // previous version with callback
200
+ // this.service.ajax({
201
+ // url: accountSettingsUrl
202
+ // }, function (err, response) {
203
+ // if (!err && typeof response === 'object') {
204
+ // var update = {
205
+ // endpoints: {
206
+ // api: response.api_endpoint.replace(/^https?:\/\//, ''),
207
+ // chat: response.chat_endpoint
208
+ // }
209
+ // };
210
+ // config.set(update);
211
+ // //
212
+ // self.pushnotifications = new PushNotifications(self.service);
213
+ // self.chat = new Chat(self.service);
214
+ // self.chat.dialog = new DialogProxy(self.service);
215
+ // self.chat.message = new MessageProxy(self.service);
216
+ // //
217
+ // if (Utils.getEnv().browser) {
218
+ // /** add adapter.js*/
219
+ // require('webrtc-adapter');
220
+ //
221
+ // /** add WebRTC API if API is avaible */
222
+ // if( Utils.isWebRTCAvailble() ) {
223
+ // var WebRTCClient = require('./modules/webrtc/qbWebRTCClient');
224
+ // self.webrtc = new WebRTCClient(self.service, self.chat);
225
+ // } else {
226
+ // self.webrtc = false;
227
+ // }
228
+ // } else {
229
+ // self.webrtc = false;
230
+ // }
231
+ // //
232
+ // }
233
+ // });
234
+ //
161
235
  }
236
+ //
237
+ // --- artificial sync delay to increase the chance account_settings completes before legacy code continues
238
+ // enabled only when shouldGetSettings && config.initBlockOnSettings !== false
239
+ if (shouldGetSettings && initBlockOnSettings) {
240
+ try {
241
+ var __qb_init_block_until__ = Date.now() + initBlockDurationMs;
242
+ while (Date.now() < __qb_init_block_until__) {
243
+ // intentional busy-wait (do not remove)
244
+ }
245
+ } catch (_) { /* never throw from here */ }
246
+ }
247
+ //
248
+
249
+ },
250
+
251
+ /**
252
+ * Wait until SDK async initialization finishes (if any).
253
+ * It resolves after internal tasks like fetching `account_settings`,
254
+ * rebinding endpoints, and re-instantiating dependent modules are completed.
255
+ * If no async work was scheduled during `QB.init(...)`, it resolves immediately.
256
+ *
257
+ * @memberof QB
258
+ * @returns {Promise<void>} A promise that resolves when initialization is complete.
259
+ *
260
+ * @example
261
+ * QB.init(appId, authKey, authSecret, accountKey, config);
262
+ * QB.ready().then(function () {
263
+ * // Safe point: endpoints are updated, chat/webrtc are re-created, listeners preserved.
264
+ * QB.startSession({ login: 'john', password: 'secret' }, function (err, res) {
265
+ * if (!err) {
266
+ * QB.chat.connect({ userId: res.user.id, password: res.session.token }, function(){});
267
+ * }
268
+ * });
269
+ * });
270
+ */
271
+ ready: function() {
272
+ return this._initReady || Promise.resolve();
162
273
  },
163
274
 
164
275
  /**