centrifuge 5.3.4 → 5.4.0-beta.1

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/README.md CHANGED
@@ -28,6 +28,7 @@ The features implemented by this SDK can be found in [SDK feature matrix](https:
28
28
  * [Using with NodeJS](#using-with-nodejs)
29
29
  * [Custom WebSocket constructor](#custom-websocket-constructor)
30
30
  * [Using with React Native on Android](#using-with-react-native-on-android)
31
+ * [Errors in callbacks](#errors-in-callbacks)
31
32
  * [Run tests locally](#run-tests-locally)
32
33
 
33
34
  ## Install
@@ -605,7 +606,7 @@ getSubscription returns `Subscription` if it's registered in the internal regist
605
606
 
606
607
  `removeSubscription(sub: Subscription | null)`
607
608
 
608
- removeSubscription allows removing Subcription from the internal registry. Subscrption must be in unsubscribed state.
609
+ removeSubscription allows removing Subcription from the internal registry.
609
610
 
610
611
  ### subscriptions
611
612
 
@@ -822,6 +823,10 @@ See a basic example with React Native where this technique is used [in this comm
822
823
 
823
824
  If you have issues with the connection on Android when using React Native – [check out this comment](https://github.com/centrifugal/centrifuge-js/issues/242#issuecomment-2569474401) – you may be using non-secure endpoint schemes and need to explicitly allow it.
824
825
 
826
+ ## Errors in callbacks
827
+
828
+ There is currently no built-in error handling in the SDK for exceptions happening in application-level callbacks, which means you must catch any error that could be thrown in a listener. Not doing that may corrupt a state of SDK making it unusable.
829
+
825
830
  ## Run tests locally
826
831
 
827
832
  If you want to run `centrifuge-js` tests locally, start test Centrifugo server:
@@ -57,8 +57,7 @@ export declare class Centrifuge extends Centrifuge_base {
57
57
  /** getSubscription returns Subscription if it's registered in the internal
58
58
  * registry or null. */
59
59
  getSubscription(channel: string): Subscription | null;
60
- /** removeSubscription allows removing Subcription from the internal registry. Subscrption
61
- * must be in unsubscribed state. */
60
+ /** removeSubscription allows removing Subcription from the internal registry. */
62
61
  removeSubscription(sub: Subscription | null): void;
63
62
  /** Get a map with all current client-side subscriptions. */
64
63
  subscriptions(): Record<string, Subscription>;
@@ -88,7 +87,6 @@ export declare class Centrifuge extends Centrifuge_base {
88
87
  history(channel: string, options?: HistoryOptions): Promise<HistoryResult>;
89
88
  /** presence for a channel. */
90
89
  presence(channel: string): Promise<PresenceResult>;
91
- /** presence stats for a channel. */
92
90
  presenceStats(channel: string): Promise<PresenceStatsResult>;
93
91
  /** start command batching (collect into temporary buffer without sending to a server)
94
92
  * until stopBatching called.*/
@@ -97,6 +95,7 @@ export declare class Centrifuge extends Centrifuge_base {
97
95
  * network (all in one request/frame).*/
98
96
  stopBatching(): void;
99
97
  private _debug;
98
+ private _codecName;
100
99
  private _configure;
101
100
  private _setState;
102
101
  private _isDisconnected;
package/build/index.js CHANGED
@@ -699,31 +699,31 @@ class Subscription extends EventEmitter$1 {
699
699
  }
700
700
  /** publish data to a channel.*/
701
701
  publish(data) {
702
- const self = this;
703
- return this._methodCall().then(function () {
704
- return self._centrifuge.publish(self.channel, data);
702
+ return __awaiter(this, void 0, void 0, function* () {
703
+ yield this._methodCall();
704
+ return this._centrifuge.publish(this.channel, data);
705
705
  });
706
706
  }
707
707
  /** get online presence for a channel.*/
708
708
  presence() {
709
- const self = this;
710
- return this._methodCall().then(function () {
711
- return self._centrifuge.presence(self.channel);
709
+ return __awaiter(this, void 0, void 0, function* () {
710
+ yield this._methodCall();
711
+ return this._centrifuge.presence(this.channel);
712
712
  });
713
713
  }
714
714
  /** presence stats for a channel (num clients and unique users).*/
715
715
  presenceStats() {
716
- const self = this;
717
- return this._methodCall().then(function () {
718
- return self._centrifuge.presenceStats(self.channel);
716
+ return __awaiter(this, void 0, void 0, function* () {
717
+ yield this._methodCall();
718
+ return this._centrifuge.presenceStats(this.channel);
719
719
  });
720
720
  }
721
721
  /** history for a channel. By default it does not return publications (only current
722
722
  * StreamPosition data) – provide an explicit limit > 0 to load publications.*/
723
723
  history(opts) {
724
- const self = this;
725
- return this._methodCall().then(function () {
726
- return self._centrifuge.history(self.channel, opts);
724
+ return __awaiter(this, void 0, void 0, function* () {
725
+ yield this._methodCall();
726
+ return this._centrifuge.history(this.channel, opts);
727
727
  });
728
728
  }
729
729
  _methodCall() {
@@ -731,17 +731,21 @@ class Subscription extends EventEmitter$1 {
731
731
  return Promise.resolve();
732
732
  }
733
733
  if (this._isUnsubscribed()) {
734
- return Promise.reject({ code: exports.errorCodes.subscriptionUnsubscribed, message: this.state });
734
+ return Promise.reject({
735
+ code: exports.errorCodes.subscriptionUnsubscribed,
736
+ message: this.state
737
+ });
735
738
  }
736
- return new Promise((res, rej) => {
737
- const timeout = setTimeout(function () {
738
- rej({ code: exports.errorCodes.timeout, message: 'timeout' });
739
- // @ts-ignore we are hiding some symbols from public API autocompletion.
740
- }, this._centrifuge._config.timeout);
739
+ return new Promise((resolve, reject) => {
740
+ // @ts-ignore we are hiding some symbols from public API autocompletion.
741
+ const timeoutDuration = this._centrifuge._config.timeout;
742
+ const timeout = setTimeout(() => {
743
+ reject({ code: exports.errorCodes.timeout, message: 'timeout' });
744
+ }, timeoutDuration);
741
745
  this._promises[this._nextPromiseId()] = {
742
- timeout: timeout,
743
- resolve: res,
744
- reject: rej
746
+ timeout,
747
+ resolve,
748
+ reject
745
749
  };
746
750
  });
747
751
  }
@@ -953,12 +957,9 @@ class Subscription extends EventEmitter$1 {
953
957
  // @ts-ignore – we are hiding some symbols from public API autocompletion.
954
958
  this._centrifuge._call(cmd).then(resolveCtx => {
955
959
  this._inflight = false;
956
- // @ts-ignore - improve later.
957
960
  const result = resolveCtx.reply.subscribe;
958
961
  this._handleSubscribeResponse(result);
959
- // @ts-ignore - improve later.
960
962
  if (resolveCtx.next) {
961
- // @ts-ignore - improve later.
962
963
  resolveCtx.next();
963
964
  }
964
965
  }, rejectCtx => {
@@ -1136,8 +1137,8 @@ class Subscription extends EventEmitter$1 {
1136
1137
  return;
1137
1138
  }
1138
1139
  if (options.since) {
1139
- this._offset = options.since.offset;
1140
- this._epoch = options.since.epoch;
1140
+ this._offset = options.since.offset || 0;
1141
+ this._epoch = options.since.epoch || '';
1141
1142
  this._recover = true;
1142
1143
  }
1143
1144
  if (options.data) {
@@ -1215,7 +1216,7 @@ class Subscription extends EventEmitter$1 {
1215
1216
  message: 'provide a function to get channel subscription token'
1216
1217
  }
1217
1218
  });
1218
- throw new UnauthorizedError('');
1219
+ return Promise.reject(new UnauthorizedError(''));
1219
1220
  }
1220
1221
  return getToken(ctx);
1221
1222
  }
@@ -1240,12 +1241,9 @@ class Subscription extends EventEmitter$1 {
1240
1241
  };
1241
1242
  // @ts-ignore – we are hiding some symbols from public API autocompletion.
1242
1243
  self._centrifuge._call(msg).then(resolveCtx => {
1243
- // @ts-ignore - improve later.
1244
1244
  const result = resolveCtx.reply.sub_refresh;
1245
1245
  self._refreshResponse(result);
1246
- // @ts-ignore - improve later.
1247
1246
  if (resolveCtx.next) {
1248
- // @ts-ignore - improve later.
1249
1247
  resolveCtx.next();
1250
1248
  }
1251
1249
  }, rejectCtx => {
@@ -2139,8 +2137,7 @@ class Centrifuge extends EventEmitter$1 {
2139
2137
  getSubscription(channel) {
2140
2138
  return this._getSub(channel);
2141
2139
  }
2142
- /** removeSubscription allows removing Subcription from the internal registry. Subscrption
2143
- * must be in unsubscribed state. */
2140
+ /** removeSubscription allows removing Subcription from the internal registry. */
2144
2141
  removeSubscription(sub) {
2145
2142
  if (!sub) {
2146
2143
  return;
@@ -2158,24 +2155,22 @@ class Centrifuge extends EventEmitter$1 {
2158
2155
  * state and rejects in case of client goes to Disconnected or Failed state.
2159
2156
  * Users can provide optional timeout in milliseconds. */
2160
2157
  ready(timeout) {
2161
- if (this.state === exports.State.Disconnected) {
2162
- return Promise.reject({ code: exports.errorCodes.clientDisconnected, message: 'client disconnected' });
2163
- }
2164
- if (this.state === exports.State.Connected) {
2165
- return Promise.resolve();
2158
+ switch (this.state) {
2159
+ case exports.State.Disconnected:
2160
+ return Promise.reject({ code: exports.errorCodes.clientDisconnected, message: 'client disconnected' });
2161
+ case exports.State.Connected:
2162
+ return Promise.resolve();
2163
+ default:
2164
+ return new Promise((resolve, reject) => {
2165
+ const ctx = { resolve, reject };
2166
+ if (timeout) {
2167
+ ctx.timeout = setTimeout(() => {
2168
+ reject({ code: exports.errorCodes.timeout, message: 'timeout' });
2169
+ }, timeout);
2170
+ }
2171
+ this._promises[this._nextPromiseId()] = ctx;
2172
+ });
2166
2173
  }
2167
- return new Promise((res, rej) => {
2168
- const ctx = {
2169
- resolve: res,
2170
- reject: rej
2171
- };
2172
- if (timeout) {
2173
- ctx.timeout = setTimeout(function () {
2174
- rej({ code: exports.errorCodes.timeout, message: 'timeout' });
2175
- }, timeout);
2176
- }
2177
- this._promises[this._nextPromiseId()] = ctx;
2178
- });
2179
2174
  }
2180
2175
  /** connect to a server. */
2181
2176
  connect() {
@@ -2206,121 +2201,113 @@ class Centrifuge extends EventEmitter$1 {
2206
2201
  /** send asynchronous data to a server (without any response from a server
2207
2202
  * expected, see rpc method if you need response). */
2208
2203
  send(data) {
2209
- const cmd = {
2210
- send: {
2211
- data: data
2212
- }
2213
- };
2214
- const self = this;
2215
- return this._methodCall().then(function () {
2216
- const sent = self._transportSendCommands([cmd]); // can send message to server without id set
2204
+ return __awaiter(this, void 0, void 0, function* () {
2205
+ const cmd = {
2206
+ send: {
2207
+ data
2208
+ }
2209
+ };
2210
+ yield this._methodCall();
2211
+ const sent = this._transportSendCommands([cmd]); // can send message to server without id set
2217
2212
  if (!sent) {
2218
- return Promise.reject(self._createErrorObject(exports.errorCodes.transportWriteError, 'transport write error'));
2213
+ throw this._createErrorObject(exports.errorCodes.transportWriteError, 'transport write error');
2219
2214
  }
2220
- return Promise.resolve();
2221
2215
  });
2222
2216
  }
2223
2217
  /** rpc to a server - i.e. a call which waits for a response with data. */
2224
2218
  rpc(method, data) {
2225
- const cmd = {
2226
- rpc: {
2227
- method: method,
2228
- data: data
2229
- }
2230
- };
2231
- const self = this;
2232
- return this._methodCall().then(function () {
2233
- return self._callPromise(cmd, function (reply) {
2234
- return {
2235
- 'data': reply.rpc.data
2236
- };
2237
- });
2219
+ return __awaiter(this, void 0, void 0, function* () {
2220
+ const cmd = {
2221
+ rpc: {
2222
+ method,
2223
+ data
2224
+ }
2225
+ };
2226
+ yield this._methodCall();
2227
+ const result = yield this._callPromise(cmd, (reply) => reply.rpc);
2228
+ return {
2229
+ data: result.data
2230
+ };
2238
2231
  });
2239
2232
  }
2240
2233
  /** publish data to a channel. */
2241
2234
  publish(channel, data) {
2242
- const cmd = {
2243
- publish: {
2244
- channel: channel,
2245
- data: data
2246
- }
2247
- };
2248
- const self = this;
2249
- return this._methodCall().then(function () {
2250
- return self._callPromise(cmd, function () {
2251
- return {};
2252
- });
2235
+ return __awaiter(this, void 0, void 0, function* () {
2236
+ const cmd = {
2237
+ publish: {
2238
+ channel,
2239
+ data
2240
+ }
2241
+ };
2242
+ yield this._methodCall();
2243
+ yield this._callPromise(cmd, () => ({}));
2244
+ return {};
2253
2245
  });
2254
2246
  }
2255
2247
  /** history for a channel. By default it does not return publications (only current
2256
2248
  * StreamPosition data) – provide an explicit limit > 0 to load publications.*/
2257
2249
  history(channel, options) {
2258
- const cmd = {
2259
- history: this._getHistoryRequest(channel, options)
2260
- };
2261
- const self = this;
2262
- return this._methodCall().then(function () {
2263
- return self._callPromise(cmd, function (reply) {
2264
- const result = reply.history;
2265
- const publications = [];
2266
- if (result.publications) {
2267
- for (let i = 0; i < result.publications.length; i++) {
2268
- publications.push(self._getPublicationContext(channel, result.publications[i]));
2269
- }
2250
+ return __awaiter(this, void 0, void 0, function* () {
2251
+ const cmd = {
2252
+ history: this._getHistoryRequest(channel, options)
2253
+ };
2254
+ yield this._methodCall();
2255
+ const result = yield this._callPromise(cmd, (reply) => reply.history);
2256
+ const publications = [];
2257
+ if (result.publications) {
2258
+ for (let i = 0; i < result.publications.length; i++) {
2259
+ publications.push(this._getPublicationContext(channel, result.publications[i]));
2270
2260
  }
2271
- return {
2272
- 'publications': publications,
2273
- 'epoch': result.epoch || '',
2274
- 'offset': result.offset || 0
2275
- };
2276
- });
2261
+ }
2262
+ return {
2263
+ publications,
2264
+ epoch: result.epoch || '',
2265
+ offset: result.offset || 0
2266
+ };
2277
2267
  });
2278
2268
  }
2279
2269
  /** presence for a channel. */
2280
2270
  presence(channel) {
2281
- const cmd = {
2282
- presence: {
2283
- channel: channel
2284
- }
2285
- };
2286
- const self = this;
2287
- return this._methodCall().then(function () {
2288
- return self._callPromise(cmd, function (reply) {
2289
- const clients = reply.presence.presence;
2290
- for (const clientId in clients) {
2291
- if (clients.hasOwnProperty(clientId)) {
2292
- const connInfo = clients[clientId]['conn_info'];
2293
- const chanInfo = clients[clientId]['chan_info'];
2294
- if (connInfo) {
2295
- clients[clientId].connInfo = connInfo;
2296
- }
2297
- if (chanInfo) {
2298
- clients[clientId].chanInfo = chanInfo;
2299
- }
2271
+ return __awaiter(this, void 0, void 0, function* () {
2272
+ const cmd = {
2273
+ presence: {
2274
+ channel
2275
+ }
2276
+ };
2277
+ yield this._methodCall();
2278
+ const result = yield this._callPromise(cmd, (reply) => reply.presence);
2279
+ const clients = result.presence;
2280
+ for (const clientId in clients) {
2281
+ if (Object.prototype.hasOwnProperty.call(clients, clientId)) {
2282
+ const rawClient = clients[clientId];
2283
+ const connInfo = rawClient['conn_info'];
2284
+ const chanInfo = rawClient['chan_info'];
2285
+ if (connInfo) {
2286
+ rawClient.connInfo = connInfo;
2287
+ }
2288
+ if (chanInfo) {
2289
+ rawClient.chanInfo = chanInfo;
2300
2290
  }
2301
2291
  }
2302
- return {
2303
- 'clients': clients
2304
- };
2305
- });
2292
+ }
2293
+ return { clients };
2306
2294
  });
2307
2295
  }
2308
- /** presence stats for a channel. */
2309
2296
  presenceStats(channel) {
2310
- const cmd = {
2311
- 'presence_stats': {
2312
- channel: channel
2313
- }
2314
- };
2315
- const self = this;
2316
- return this._methodCall().then(function () {
2317
- return self._callPromise(cmd, function (reply) {
2318
- const result = reply.presence_stats;
2319
- return {
2320
- 'numUsers': result.num_users,
2321
- 'numClients': result.num_clients
2322
- };
2297
+ return __awaiter(this, void 0, void 0, function* () {
2298
+ const cmd = {
2299
+ 'presence_stats': {
2300
+ channel
2301
+ }
2302
+ };
2303
+ yield this._methodCall();
2304
+ const result = yield this._callPromise(cmd, (reply) => {
2305
+ return reply.presence_stats;
2323
2306
  });
2307
+ return {
2308
+ numUsers: result.num_users,
2309
+ numClients: result.num_clients
2310
+ };
2324
2311
  });
2325
2312
  }
2326
2313
  /** start command batching (collect into temporary buffer without sending to a server)
@@ -2350,6 +2337,9 @@ class Centrifuge extends EventEmitter$1 {
2350
2337
  }
2351
2338
  log('debug', args);
2352
2339
  }
2340
+ _codecName() {
2341
+ return this._codec.name();
2342
+ }
2353
2343
  /** @internal */
2354
2344
  _formatOverride() {
2355
2345
  return;
@@ -2693,7 +2683,7 @@ class Centrifuge extends EventEmitter$1 {
2693
2683
  connectTimeout = setTimeout(function () {
2694
2684
  transport.close();
2695
2685
  }, this._config.timeout);
2696
- this._transport.initialize(this._codec.name(), {
2686
+ this._transport.initialize(this._codecName(), {
2697
2687
  onOpen: function () {
2698
2688
  if (connectTimeout) {
2699
2689
  clearTimeout(connectTimeout);
@@ -2802,12 +2792,9 @@ class Centrifuge extends EventEmitter$1 {
2802
2792
  const connectCommand = this._constructConnectCommand();
2803
2793
  const self = this;
2804
2794
  this._call(connectCommand, skipSending).then(resolveCtx => {
2805
- // @ts-ignore = improve later.
2806
2795
  const result = resolveCtx.reply.connect;
2807
2796
  self._connectResponse(result);
2808
- // @ts-ignore - improve later.
2809
2797
  if (resolveCtx.next) {
2810
- // @ts-ignore - improve later.
2811
2798
  resolveCtx.next();
2812
2799
  }
2813
2800
  }, rejectCtx => {
@@ -3035,19 +3022,15 @@ class Centrifuge extends EventEmitter$1 {
3035
3022
  }
3036
3023
  _callPromise(cmd, resultCB) {
3037
3024
  return new Promise((resolve, reject) => {
3038
- this._call(cmd, false).then(resolveCtx => {
3039
- // @ts-ignore - improve later.
3040
- resolve(resultCB(resolveCtx.reply));
3041
- // @ts-ignore - improve later.
3042
- if (resolveCtx.next) {
3043
- // @ts-ignore - improve later.
3044
- resolveCtx.next();
3045
- }
3046
- }, rejectCtx => {
3025
+ this._call(cmd, false).then((resolveCtx) => {
3026
+ var _a;
3027
+ const result = resultCB(resolveCtx.reply);
3028
+ resolve(result);
3029
+ (_a = resolveCtx.next) === null || _a === void 0 ? void 0 : _a.call(resolveCtx);
3030
+ }, (rejectCtx) => {
3031
+ var _a;
3047
3032
  reject(rejectCtx.error);
3048
- if (rejectCtx.next) {
3049
- rejectCtx.next();
3050
- }
3033
+ (_a = rejectCtx.next) === null || _a === void 0 ? void 0 : _a.call(rejectCtx);
3051
3034
  });
3052
3035
  });
3053
3036
  }
@@ -3186,7 +3169,7 @@ class Centrifuge extends EventEmitter$1 {
3186
3169
  message: 'token expired but no getToken function set in the configuration'
3187
3170
  }
3188
3171
  });
3189
- throw new UnauthorizedError('');
3172
+ return Promise.reject(new UnauthorizedError(''));
3190
3173
  }
3191
3174
  return this._config.getToken({});
3192
3175
  }
@@ -3210,12 +3193,9 @@ class Centrifuge extends EventEmitter$1 {
3210
3193
  refresh: { token: self._token }
3211
3194
  };
3212
3195
  self._call(cmd, false).then(resolveCtx => {
3213
- // @ts-ignore - improve later.
3214
3196
  const result = resolveCtx.reply.refresh;
3215
3197
  self._refreshResponse(result);
3216
- // @ts-ignore - improve later.
3217
3198
  if (resolveCtx.next) {
3218
- // @ts-ignore - improve later.
3219
3199
  resolveCtx.next();
3220
3200
  }
3221
3201
  }, rejectCtx => {
@@ -3285,9 +3265,7 @@ class Centrifuge extends EventEmitter$1 {
3285
3265
  const unsubscribePromise = new Promise((resolve, _) => {
3286
3266
  this._call(cmd, false).then(resolveCtx => {
3287
3267
  resolve();
3288
- // @ts-ignore - improve later.
3289
3268
  if (resolveCtx.next) {
3290
- // @ts-ignore - improve later.
3291
3269
  resolveCtx.next();
3292
3270
  }
3293
3271
  }, rejectCtx => {
@@ -3450,7 +3428,8 @@ class Centrifuge extends EventEmitter$1 {
3450
3428
  positioned: false,
3451
3429
  recoverable: false,
3452
3430
  wasRecovering: false,
3453
- recovered: false
3431
+ recovered: false,
3432
+ hasRecoveredPublications: false,
3454
3433
  };
3455
3434
  if (result.recovered) {
3456
3435
  ctx.recovered = true;
@@ -3478,6 +3457,9 @@ class Centrifuge extends EventEmitter$1 {
3478
3457
  'epoch': epoch
3479
3458
  };
3480
3459
  }
3460
+ if (Array.isArray(result.publications) && result.publications.length > 0) {
3461
+ ctx.hasRecoveredPublications = true;
3462
+ }
3481
3463
  if (result.data) {
3482
3464
  ctx.data = result.data;
3483
3465
  }
@@ -3505,7 +3487,7 @@ class Centrifuge extends EventEmitter$1 {
3505
3487
  next();
3506
3488
  return;
3507
3489
  }
3508
- const error = reply.error;
3490
+ const error = { code: reply.error.code, message: reply.error.message || '', temporary: reply.error.temporary || false };
3509
3491
  errback({ error, next });
3510
3492
  }
3511
3493
  }
@@ -3588,11 +3570,13 @@ class Centrifuge extends EventEmitter$1 {
3588
3570
  client: clientInfo.client,
3589
3571
  user: clientInfo.user
3590
3572
  };
3591
- if (clientInfo.conn_info) {
3592
- info.connInfo = clientInfo.conn_info;
3573
+ const connInfo = clientInfo['conn_info'];
3574
+ if (connInfo) {
3575
+ info.connInfo = connInfo;
3593
3576
  }
3594
- if (clientInfo.chan_info) {
3595
- info.chanInfo = clientInfo.chan_info;
3577
+ const chanInfo = clientInfo['chan_info'];
3578
+ if (chanInfo) {
3579
+ info.chanInfo = chanInfo;
3596
3580
  }
3597
3581
  return info;
3598
3582
  }