polfan-server-js-client 0.2.6 → 0.2.7

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.
@@ -4,25 +4,13 @@
4
4
  <option name="autoReloadType" value="SELECTIVE" />
5
5
  </component>
6
6
  <component name="ChangeListManager">
7
- <list default="true" id="831dae43-0da1-47fd-a5f7-33dd5eec2992" name="Changes" comment="Improvements and fixes to collection mirroring">
8
- <change afterPath="$PROJECT_DIR$/src/types/src/schemes/commands/UpdateRoomMember.ts" afterDir="false" />
7
+ <list default="true" id="831dae43-0da1-47fd-a5f7-33dd5eec2992" name="Changes" comment="Improve reconnect on timeout">
9
8
  <change beforePath="$PROJECT_DIR$/build/index.cjs.js" beforeDir="false" afterPath="$PROJECT_DIR$/build/index.cjs.js" afterDir="false" />
10
9
  <change beforePath="$PROJECT_DIR$/build/index.cjs.js.map" beforeDir="false" afterPath="$PROJECT_DIR$/build/index.cjs.js.map" afterDir="false" />
11
10
  <change beforePath="$PROJECT_DIR$/build/index.umd.js" beforeDir="false" afterPath="$PROJECT_DIR$/build/index.umd.js" afterDir="false" />
12
11
  <change beforePath="$PROJECT_DIR$/build/index.umd.js.map" beforeDir="false" afterPath="$PROJECT_DIR$/build/index.umd.js.map" afterDir="false" />
13
- <change beforePath="$PROJECT_DIR$/build/types/AbstractChatClient.d.ts" beforeDir="false" afterPath="$PROJECT_DIR$/build/types/AbstractChatClient.d.ts" afterDir="false" />
14
- <change beforePath="$PROJECT_DIR$/build/types/Permissions.d.ts" beforeDir="false" afterPath="$PROJECT_DIR$/build/types/Permissions.d.ts" afterDir="false" />
15
- <change beforePath="$PROJECT_DIR$/build/types/types/src/index.d.ts" beforeDir="false" afterPath="$PROJECT_DIR$/build/types/types/src/index.d.ts" afterDir="false" />
16
- <change beforePath="$PROJECT_DIR$/build/types/types/src/schemes/User.d.ts" beforeDir="false" afterPath="$PROJECT_DIR$/build/types/types/src/schemes/User.d.ts" afterDir="false" />
17
- <change beforePath="$PROJECT_DIR$/build/types/types/src/schemes/commands/CreateMessage.d.ts" beforeDir="false" afterPath="$PROJECT_DIR$/build/types/types/src/schemes/commands/CreateMessage.d.ts" afterDir="false" />
18
12
  <change beforePath="$PROJECT_DIR$/package.json" beforeDir="false" afterPath="$PROJECT_DIR$/package.json" afterDir="false" />
19
- <change beforePath="$PROJECT_DIR$/src/AbstractChatClient.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/AbstractChatClient.ts" afterDir="false" />
20
- <change beforePath="$PROJECT_DIR$/src/Permissions.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/Permissions.ts" afterDir="false" />
21
- <change beforePath="$PROJECT_DIR$/src/types" beforeDir="false" afterPath="$PROJECT_DIR$/src/types" afterDir="false" />
22
- <change beforePath="$PROJECT_DIR$/src/types/src/index.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/types/src/index.ts" afterDir="false" />
23
- <change beforePath="$PROJECT_DIR$/src/types/src/schemes/User.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/types/src/schemes/User.ts" afterDir="false" />
24
- <change beforePath="$PROJECT_DIR$/src/types/src/schemes/commands/CreateMessage.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/types/src/schemes/commands/CreateMessage.ts" afterDir="false" />
25
- <change beforePath="$PROJECT_DIR$/src/types/src/schemes/commands/SetCustomNick.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/types/src/schemes/commands/UpdateSpaceMember.ts" afterDir="false" />
13
+ <change beforePath="$PROJECT_DIR$/src/WebSocketChatClient.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/WebSocketChatClient.ts" afterDir="false" />
26
14
  </list>
27
15
  <option name="SHOW_DIALOG" value="false" />
28
16
  <option name="HIGHLIGHT_CONFLICTS" value="true" />
@@ -68,32 +56,33 @@
68
56
  <option name="hideEmptyMiddlePackages" value="true" />
69
57
  <option name="showLibraryContents" value="true" />
70
58
  </component>
71
- <component name="PropertiesComponent"><![CDATA[{
72
- "keyToString": {
73
- "RunOnceActivity.ShowReadmeOnStart": "true",
74
- "RunOnceActivity.TerminalTabsStorage.copyFrom.TerminalArrangementManager": "true",
75
- "RunOnceActivity.TerminalTabsStorage.copyFrom.TerminalArrangementManager.252": "true",
76
- "RunOnceActivity.git.unshallow": "true",
77
- "com.intellij.ml.llm.matterhorn.ej.ui.settings.DefaultModelSelectionForGA.v1": "true",
78
- "git-widget-placeholder": "master",
79
- "ignore.virus.scanning.warn.message": "true",
80
- "junie.onboarding.icon.badge.shown": "true",
81
- "last_opened_file_path": "//wsl.localhost/Debian/home/jarek/polfan-js-client-library",
82
- "node.js.detected.package.eslint": "true",
83
- "node.js.detected.package.tslint": "true",
84
- "node.js.selected.package.eslint": "(autodetect)",
85
- "node.js.selected.package.tslint": "(autodetect)",
86
- "nodejs_package_manager_path": "npm",
87
- "to.speed.mode.migration.done": "true",
88
- "ts.external.directory.path": "\\\\wsl.localhost\\Debian\\home\\jarek\\polfan-js-client-library\\node_modules\\typescript\\lib",
89
- "vue.rearranger.settings.migration": "true"
59
+ <component name="PropertiesComponent">{
60
+ &quot;keyToString&quot;: {
61
+ &quot;RunOnceActivity.ShowReadmeOnStart&quot;: &quot;true&quot;,
62
+ &quot;RunOnceActivity.TerminalTabsStorage.copyFrom.TerminalArrangementManager&quot;: &quot;true&quot;,
63
+ &quot;RunOnceActivity.TerminalTabsStorage.copyFrom.TerminalArrangementManager.252&quot;: &quot;true&quot;,
64
+ &quot;RunOnceActivity.git.unshallow&quot;: &quot;true&quot;,
65
+ &quot;RunOnceActivity.typescript.service.memoryLimit.init&quot;: &quot;true&quot;,
66
+ &quot;com.intellij.ml.llm.matterhorn.ej.ui.settings.DefaultModelSelectionForGA.v1&quot;: &quot;true&quot;,
67
+ &quot;git-widget-placeholder&quot;: &quot;master&quot;,
68
+ &quot;ignore.virus.scanning.warn.message&quot;: &quot;true&quot;,
69
+ &quot;junie.onboarding.icon.badge.shown&quot;: &quot;true&quot;,
70
+ &quot;last_opened_file_path&quot;: &quot;//wsl.localhost/Debian/home/jarek/polfan-js-client-library&quot;,
71
+ &quot;node.js.detected.package.eslint&quot;: &quot;true&quot;,
72
+ &quot;node.js.detected.package.tslint&quot;: &quot;true&quot;,
73
+ &quot;node.js.selected.package.eslint&quot;: &quot;(autodetect)&quot;,
74
+ &quot;node.js.selected.package.tslint&quot;: &quot;(autodetect)&quot;,
75
+ &quot;nodejs_package_manager_path&quot;: &quot;npm&quot;,
76
+ &quot;to.speed.mode.migration.done&quot;: &quot;true&quot;,
77
+ &quot;ts.external.directory.path&quot;: &quot;\\\\wsl.localhost\\Debian\\home\\jarek\\polfan-js-client-library\\node_modules\\typescript\\lib&quot;,
78
+ &quot;vue.rearranger.settings.migration&quot;: &quot;true&quot;
90
79
  }
91
- }]]></component>
80
+ }</component>
92
81
  <component name="SharedIndexes">
93
82
  <attachedChunks>
94
83
  <set>
95
- <option value="bundled-js-predefined-d6986cc7102b-c7e53b3be11b-JavaScript-PS-253.28086.57" />
96
- <option value="bundled-php-predefined-a98d8de5180a-09080813851e-com.jetbrains.php.sharedIndexes-PS-253.28086.57" />
84
+ <option value="bundled-js-predefined-d6986cc7102b-c7e53b3be11b-JavaScript-PS-253.28294.257" />
85
+ <option value="bundled-php-predefined-a98d8de5180a-09080813851e-com.jetbrains.php.sharedIndexes-PS-253.28294.257" />
97
86
  </set>
98
87
  </attachedChunks>
99
88
  </component>
@@ -167,47 +156,15 @@
167
156
  <workItem from="1763410036992" duration="181000" />
168
157
  <workItem from="1763457144937" duration="13889000" />
169
158
  <workItem from="1764419232591" duration="640000" />
170
- <workItem from="1764525611464" duration="5294000" />
171
- </task>
172
- <task id="LOCAL-00015" summary="Restore support for nullable parameter in permission overwrites id function">
173
- <option name="closed" value="true" />
174
- <created>1739444617033</created>
175
- <option name="number" value="00015" />
176
- <option name="presentableId" value="LOCAL-00015" />
177
- <option name="project" value="LOCAL" />
178
- <updated>1739444617033</updated>
179
- </task>
180
- <task id="LOCAL-00016" summary="Bans support">
181
- <option name="closed" value="true" />
182
- <created>1740177682341</created>
183
- <option name="number" value="00016" />
184
- <option name="presentableId" value="LOCAL-00016" />
185
- <option name="project" value="LOCAL" />
186
- <updated>1740177682341</updated>
187
- </task>
188
- <task id="LOCAL-00017" summary="New scheme of Bye event">
189
- <option name="closed" value="true" />
190
- <created>1740250355576</created>
191
- <option name="number" value="00017" />
192
- <option name="presentableId" value="LOCAL-00017" />
193
- <option name="project" value="LOCAL" />
194
- <updated>1740250355576</updated>
195
- </task>
196
- <task id="LOCAL-00018" summary="Fix authentication">
197
- <option name="closed" value="true" />
198
- <created>1740253483444</created>
199
- <option name="number" value="00018" />
200
- <option name="presentableId" value="LOCAL-00018" />
201
- <option name="project" value="LOCAL" />
202
- <updated>1740253483444</updated>
203
- </task>
204
- <task id="LOCAL-00019" summary="Add notify option to Kick command">
205
- <option name="closed" value="true" />
206
- <created>1740515104457</created>
207
- <option name="number" value="00019" />
208
- <option name="presentableId" value="LOCAL-00019" />
209
- <option name="project" value="LOCAL" />
210
- <updated>1740515104457</updated>
159
+ <workItem from="1764525611464" duration="5340000" />
160
+ <workItem from="1764689604655" duration="307000" />
161
+ <workItem from="1764716454990" duration="1338000" />
162
+ <workItem from="1764758258935" duration="1127000" />
163
+ <workItem from="1764792690210" duration="1002000" />
164
+ <workItem from="1764794428269" duration="595000" />
165
+ <workItem from="1764847260499" duration="28335000" />
166
+ <workItem from="1765180748047" duration="596000" />
167
+ <workItem from="1765272289918" duration="2750000" />
211
168
  </task>
212
169
  <task id="LOCAL-00020" summary="UsersManager">
213
170
  <option name="closed" value="true" />
@@ -561,7 +518,47 @@
561
518
  <option name="project" value="LOCAL" />
562
519
  <updated>1763587170121</updated>
563
520
  </task>
564
- <option name="localTasksCounter" value="64" />
521
+ <task id="LOCAL-00064" summary="Align to custom colors and nicks protocol changes">
522
+ <option name="closed" value="true" />
523
+ <created>1764688847485</created>
524
+ <option name="number" value="00064" />
525
+ <option name="presentableId" value="LOCAL-00064" />
526
+ <option name="project" value="LOCAL" />
527
+ <updated>1764688847485</updated>
528
+ </task>
529
+ <task id="LOCAL-00065" summary="Align to custom colors and nicks protocol changes">
530
+ <option name="closed" value="true" />
531
+ <created>1764689897013</created>
532
+ <option name="number" value="00065" />
533
+ <option name="presentableId" value="LOCAL-00065" />
534
+ <option name="project" value="LOCAL" />
535
+ <updated>1764689897014</updated>
536
+ </task>
537
+ <task id="LOCAL-00066" summary="Connection handling optimizations">
538
+ <option name="closed" value="true" />
539
+ <created>1764955397384</created>
540
+ <option name="number" value="00066" />
541
+ <option name="presentableId" value="LOCAL-00066" />
542
+ <option name="project" value="LOCAL" />
543
+ <updated>1764955397384</updated>
544
+ </task>
545
+ <task id="LOCAL-00067" summary="Ping-pong connection monitoring">
546
+ <option name="closed" value="true" />
547
+ <created>1765145134871</created>
548
+ <option name="number" value="00067" />
549
+ <option name="presentableId" value="LOCAL-00067" />
550
+ <option name="project" value="LOCAL" />
551
+ <updated>1765145134871</updated>
552
+ </task>
553
+ <task id="LOCAL-00068" summary="Improve reconnect on timeout">
554
+ <option name="closed" value="true" />
555
+ <created>1765145773196</created>
556
+ <option name="number" value="00068" />
557
+ <option name="presentableId" value="LOCAL-00068" />
558
+ <option name="project" value="LOCAL" />
559
+ <updated>1765145773196</updated>
560
+ </task>
561
+ <option name="localTasksCounter" value="69" />
565
562
  <servers />
566
563
  </component>
567
564
  <component name="TypeScriptGeneratedFilesManager">
@@ -579,10 +576,6 @@
579
576
  </option>
580
577
  </component>
581
578
  <component name="VcsManagerConfiguration">
582
- <MESSAGE value="Fix JoinRoom command response type" />
583
- <MESSAGE value="Fix package.json exports" />
584
- <MESSAGE value="Fix package.json type exports" />
585
- <MESSAGE value="New message type" />
586
579
  <MESSAGE value="Dedicated event for user status change" />
587
580
  <MESSAGE value="Fix update the latest message in a room default topic" />
588
581
  <MESSAGE value="Adapt FilesClient to new files API" />
@@ -604,6 +597,18 @@
604
597
  <MESSAGE value="Collection integration with React JS rework" />
605
598
  <MESSAGE value="Update deps and improve library building" />
606
599
  <MESSAGE value="Improvements and fixes to collection mirroring" />
607
- <option name="LAST_COMMIT_MESSAGE" value="Improvements and fixes to collection mirroring" />
600
+ <MESSAGE value="Align to custom colors and nicks protocol changes" />
601
+ <MESSAGE value="Connection handling optimizations" />
602
+ <MESSAGE value="Ping-pong connection monitoring" />
603
+ <MESSAGE value="Improve reconnect on timeout" />
604
+ <option name="LAST_COMMIT_MESSAGE" value="Improve reconnect on timeout" />
605
+ </component>
606
+ <component name="github-copilot-workspace">
607
+ <instructionFileLocations>
608
+ <option value=".github/instructions" />
609
+ </instructionFileLocations>
610
+ <promptFileLocations>
611
+ <option value=".github/prompts" />
612
+ </promptFileLocations>
608
613
  </component>
609
614
  </project>
package/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  # pserv-js-client-library
2
- TypeScript client library to handle connection with Polfan chat service.
2
+ TypeScript client library to handle connection with Devana (new Polfan) chat service.
3
3
 
4
4
  ## How to use?
5
5
 
@@ -22,4 +22,24 @@ TypeScript client library to handle connection with Polfan chat service.
22
22
  console.log("The spaces you are in:", session.spaces);
23
23
  console.log("The version of server you connected to:", session.serverVersion);
24
24
  })();
25
- ```
25
+ ```
26
+
27
+ ## State management
28
+
29
+ The library provides built-in state management for WebSocket client. To enable it, just pass `stateTracking`
30
+ option to the `WebSocketChatClient` constructor:
31
+
32
+ ```js
33
+ const wsClient = new PServ.WebSocketChatClient({
34
+ token: 'your-access-token',
35
+ url: 'wss://pserv-websocket-address',
36
+ stateTracking: true, // Enable state tracking
37
+ });
38
+ ```
39
+
40
+ With state tracking enabled, the client will automatically maintain the current state of rooms, users, and messages,
41
+ by handling incoming events from the server. Reactive data structures are available via `ObservableIndexedObjectCollection`
42
+ objects, which allows you to subscribe to changes.
43
+
44
+ **Important note:** you can cache these objects for the connection lifetime, but you should refetch them after reconnecting,
45
+ because some structures are rebuild from scratch on `Session` event.
@@ -968,9 +968,6 @@ var TopicHistoryWindow = /*#__PURE__*/function (_TraversableRemoteCol) {
968
968
  _this2.tracker = tracker;
969
969
  _this2.internalState.traverseLock = false;
970
970
  if (bindEvents) {
971
- _this2.tracker.client.on('Session', function (ev) {
972
- return _this2.handleSession(ev);
973
- });
974
971
  _this2.tracker.client.on('NewMessage', function (ev) {
975
972
  return _this2.handleNewMessage(ev);
976
973
  });
@@ -1117,19 +1114,6 @@ var TopicHistoryWindow = /*#__PURE__*/function (_TraversableRemoteCol) {
1117
1114
  }
1118
1115
  return handleNewMessage;
1119
1116
  }()
1120
- }, {
1121
- key: "handleSession",
1122
- value: function handleSession(ev) {
1123
- var _this3 = this;
1124
- var rooms = ev.state.rooms;
1125
- if (rooms.find(function (room) {
1126
- return room.id === _this3.roomId;
1127
- })) {
1128
- void this.resetToLatest();
1129
- } else {
1130
- this.deleteAll();
1131
- }
1132
- }
1133
1117
  }, {
1134
1118
  key: "fetchItemsAfter",
1135
1119
  value: function () {
@@ -2428,7 +2412,10 @@ var RoomsManager = /*#__PURE__*/function () {
2428
2412
  return {
2429
2413
  user: user,
2430
2414
  spaceMember: null,
2431
- roles: null
2415
+ roles: null,
2416
+ customColor: null,
2417
+ customNick: null,
2418
+ extras: ''
2432
2419
  };
2433
2420
  })
2434
2421
  });
@@ -4282,7 +4269,7 @@ var WebSocketChatClientEvent = /*#__PURE__*/function (WebSocketChatClientEvent)
4282
4269
  }(WebSocketChatClientEvent || {});
4283
4270
  var WebSocketChatClient = /*#__PURE__*/function (_AbstractChatClient) {
4284
4271
  function WebSocketChatClient(options) {
4285
- var _this$options$stateTr;
4272
+ var _this$options$stateTr, _options$ping, _options$ping2, _options$ping2$enable, _options$ping3, _options$ping3$noActi, _options$ping4, _options$ping4$pongBa;
4286
4273
  var _this;
4287
4274
  WebSocketChatClient_classCallCheck(this, WebSocketChatClient);
4288
4275
  _this = WebSocketChatClient_callSuper(this, WebSocketChatClient);
@@ -4293,10 +4280,17 @@ var WebSocketChatClient = /*#__PURE__*/function (_AbstractChatClient) {
4293
4280
  WebSocketChatClient_defineProperty(_this, "connectingTimeoutId", void 0);
4294
4281
  WebSocketChatClient_defineProperty(_this, "authenticated", void 0);
4295
4282
  WebSocketChatClient_defineProperty(_this, "authenticatedResolvers", void 0);
4283
+ WebSocketChatClient_defineProperty(_this, "pingIntervalId", void 0);
4284
+ WebSocketChatClient_defineProperty(_this, "lastReceivedMessageAt", void 0);
4285
+ WebSocketChatClient_defineProperty(_this, "pingInFlight", void 0);
4296
4286
  _this.options = options;
4297
4287
  if ((_this$options$stateTr = _this.options.stateTracking) !== null && _this$options$stateTr !== void 0 ? _this$options$stateTr : true) {
4298
4288
  _this.state = new ChatStateTracker(_this);
4299
4289
  }
4290
+ (_options$ping = options.ping) !== null && _options$ping !== void 0 ? _options$ping : options.ping = {};
4291
+ (_options$ping2$enable = (_options$ping2 = options.ping).enabled) !== null && _options$ping2$enable !== void 0 ? _options$ping2$enable : _options$ping2.enabled = true;
4292
+ (_options$ping3$noActi = (_options$ping3 = options.ping).noActivityTimeoutMs) !== null && _options$ping3$noActi !== void 0 ? _options$ping3$noActi : _options$ping3.noActivityTimeoutMs = 15000;
4293
+ (_options$ping4$pongBa = (_options$ping4 = options.ping).pongBackTimeoutMs) !== null && _options$ping4$pongBa !== void 0 ? _options$ping4$pongBa : _options$ping4.pongBackTimeoutMs = 5000;
4300
4294
  return _this;
4301
4295
  }
4302
4296
  WebSocketChatClient_inherits(WebSocketChatClient, _AbstractChatClient);
@@ -4311,6 +4305,12 @@ var WebSocketChatClient = /*#__PURE__*/function (_AbstractChatClient) {
4311
4305
  return WebSocketChatClient_regenerator().w(function (_context) {
4312
4306
  while (1) switch (_context.n) {
4313
4307
  case 0:
4308
+ if (!(this.isOpenWsState() || this.isConnectingWsState())) {
4309
+ _context.n = 1;
4310
+ break;
4311
+ }
4312
+ return _context.a(2);
4313
+ case 1:
4314
4314
  params = new URLSearchParams((_this$options$queryPa = this.options.queryParams) !== null && _this$options$queryPa !== void 0 ? _this$options$queryPa : {});
4315
4315
  params.set('token', this.options.token);
4316
4316
  this.ws = new WebSocket("".concat(this.options.url, "?").concat(params));
@@ -4343,7 +4343,7 @@ var WebSocketChatClient = /*#__PURE__*/function (_AbstractChatClient) {
4343
4343
  value: function disconnect() {
4344
4344
  var _this$ws;
4345
4345
  this.sendQueue = [];
4346
- (_this$ws = this.ws) === null || _this$ws === void 0 || _this$ws.close();
4346
+ (_this$ws = this.ws) === null || _this$ws === void 0 || _this$ws.close(1000); // Normal closure
4347
4347
  this.ws = null;
4348
4348
  }
4349
4349
  }, {
@@ -4356,7 +4356,7 @@ var WebSocketChatClient = /*#__PURE__*/function (_AbstractChatClient) {
4356
4356
  case 0:
4357
4357
  envelope = this.createEnvelope(commandType, commandData);
4358
4358
  promise = this.createPromiseFromCommandEnvelope(envelope);
4359
- if (!this.isPendingReadyWsState()) {
4359
+ if (!(this.isConnectingWsState() || !this.authenticated && this.isOpenWsState())) {
4360
4360
  _context2.n = 1;
4361
4361
  break;
4362
4362
  }
@@ -4373,19 +4373,25 @@ var WebSocketChatClient = /*#__PURE__*/function (_AbstractChatClient) {
4373
4373
  }
4374
4374
  return send;
4375
4375
  }()
4376
+ }, {
4377
+ key: "isReady",
4378
+ get: function get() {
4379
+ return this.isOpenWsState() && this.authenticated;
4380
+ }
4376
4381
  }, {
4377
4382
  key: "sendEnvelope",
4378
4383
  value: function sendEnvelope(envelope) {
4379
4384
  var _this$ws$readyState, _this$ws2;
4380
- if (this.isReadyToSendWsState()) {
4385
+ if (this.isReady) {
4381
4386
  this.ws.send(JSON.stringify(envelope));
4382
4387
  return;
4383
4388
  }
4384
- this.handleEnvelopeSendError(envelope, new Error("Cannot send; invalid websocket state=".concat((_this$ws$readyState = (_this$ws2 = this.ws) === null || _this$ws2 === void 0 ? void 0 : _this$ws2.readyState) !== null && _this$ws$readyState !== void 0 ? _this$ws$readyState : '[no connection]')));
4389
+ this.handleEnvelopeSendError(envelope, new Error("Cannot send - client is not ready (state=".concat((_this$ws$readyState = (_this$ws2 = this.ws) === null || _this$ws2 === void 0 ? void 0 : _this$ws2.readyState) !== null && _this$ws$readyState !== void 0 ? _this$ws$readyState : '[no connection]', "; authenticated=").concat(this.authenticated, ")")));
4385
4390
  }
4386
4391
  }, {
4387
4392
  key: "onMessage",
4388
4393
  value: function onMessage(event) {
4394
+ this.lastReceivedMessageAt = Date.now();
4389
4395
  var envelope = JSON.parse(event.data);
4390
4396
  this.handleIncomingEnvelope(envelope);
4391
4397
  this.emit(envelope.type, envelope.data);
@@ -4396,6 +4402,7 @@ var WebSocketChatClient = /*#__PURE__*/function (_AbstractChatClient) {
4396
4402
  var isAuthenticated = envelope.type !== 'Bye';
4397
4403
  this.authenticated = isAuthenticated;
4398
4404
  if (isAuthenticated) {
4405
+ this.startConnectionMonitor();
4399
4406
  this.authenticatedResolvers[0]();
4400
4407
  this.emit(this.Event.connect);
4401
4408
  this.sendFromQueue();
@@ -4407,6 +4414,7 @@ var WebSocketChatClient = /*#__PURE__*/function (_AbstractChatClient) {
4407
4414
  }, {
4408
4415
  key: "onClose",
4409
4416
  value: function onClose(event) {
4417
+ this.stopConnectionMonitor();
4410
4418
  clearTimeout(this.connectingTimeoutId);
4411
4419
  var reconnect = event.code !== 1000; // Connection was closed because of error
4412
4420
  if (reconnect) {
@@ -4441,14 +4449,63 @@ var WebSocketChatClient = /*#__PURE__*/function (_AbstractChatClient) {
4441
4449
  this.emit(this.Event.error, new Error('Connection timeout'));
4442
4450
  }
4443
4451
  }, {
4444
- key: "isPendingReadyWsState",
4445
- value: function isPendingReadyWsState() {
4446
- return this.ws && this.ws.readyState === this.ws.CONNECTING || !this.authenticated;
4452
+ key: "isConnectingWsState",
4453
+ value: function isConnectingWsState() {
4454
+ return this.ws && this.ws.readyState === this.ws.CONNECTING;
4447
4455
  }
4448
4456
  }, {
4449
- key: "isReadyToSendWsState",
4450
- value: function isReadyToSendWsState() {
4451
- return this.ws && this.ws.readyState === this.ws.OPEN && this.authenticated;
4457
+ key: "isOpenWsState",
4458
+ value: function isOpenWsState() {
4459
+ return this.ws && this.ws.readyState === this.ws.OPEN;
4460
+ }
4461
+ }, {
4462
+ key: "startConnectionMonitor",
4463
+ value: function startConnectionMonitor() {
4464
+ var _this4 = this;
4465
+ if (!this.options.ping.enabled) {
4466
+ return;
4467
+ }
4468
+ this.lastReceivedMessageAt = Date.now();
4469
+ this.pingIntervalId = setInterval(/*#__PURE__*/WebSocketChatClient_asyncToGenerator(/*#__PURE__*/WebSocketChatClient_regenerator().m(function _callee3() {
4470
+ var timeout;
4471
+ return WebSocketChatClient_regenerator().w(function (_context3) {
4472
+ while (1) switch (_context3.n) {
4473
+ case 0:
4474
+ if (!(!_this4.isReady || _this4.pingInFlight)) {
4475
+ _context3.n = 1;
4476
+ break;
4477
+ }
4478
+ return _context3.a(2);
4479
+ case 1:
4480
+ if (!(Date.now() - _this4.lastReceivedMessageAt < _this4.options.ping.noActivityTimeoutMs)) {
4481
+ _context3.n = 2;
4482
+ break;
4483
+ }
4484
+ return _context3.a(2);
4485
+ case 2:
4486
+ timeout = setTimeout(function () {
4487
+ _this4.pingInFlight = false;
4488
+ _this4.ws.close(3000); // Service Restart (reconnect)
4489
+ }, _this4.options.ping.pongBackTimeoutMs);
4490
+ _this4.pingInFlight = true;
4491
+ _this4.send('Ping', {}).then(function () {
4492
+ _this4.pingInFlight = false;
4493
+ clearTimeout(timeout);
4494
+ });
4495
+ case 3:
4496
+ return _context3.a(2);
4497
+ }
4498
+ }, _callee3);
4499
+ })), 1000);
4500
+ }
4501
+ }, {
4502
+ key: "stopConnectionMonitor",
4503
+ value: function stopConnectionMonitor() {
4504
+ if (this.pingIntervalId) {
4505
+ clearInterval(this.pingIntervalId);
4506
+ this.pingIntervalId = undefined;
4507
+ }
4508
+ this.pingInFlight = false;
4452
4509
  }
4453
4510
  }]);
4454
4511
  }(AbstractChatClient);