jsgar 4.8.0 → 4.9.0

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.
Files changed (3) hide show
  1. package/dist/gar.umd.js +50 -8
  2. package/gar.js +50 -8
  3. package/package.json +4 -1
package/dist/gar.umd.js CHANGED
@@ -200,6 +200,7 @@
200
200
  this.websocket = null;
201
201
  this.messageQueue = [];
202
202
  this.connected = false;
203
+ this.connectedCallback = null;
203
204
  this.reconnectDelay = 5000; // Milliseconds
204
205
  this.user = user;
205
206
  this.working_namespace = working_namespace;
@@ -383,18 +384,18 @@
383
384
  });
384
385
 
385
386
  this.websocket = await connectionPromise;
386
- this.connected = true;
387
+ this._setConnected(true);
387
388
  this.log('INFO', `Connected to WebSocket server at ${this.wsEndpoint} using gar-protocol`);
388
389
 
389
390
  this.websocket.onclose = () => {
390
391
  this.log('WARNING', 'WebSocket connection closed.');
391
- this.connected = false;
392
+ this._setConnected(false);
392
393
  this.websocket = null;
393
394
  this._reconnect();
394
395
  };
395
396
  this.websocket.onerror = (error) => {
396
397
  this.log('ERROR', `WebSocket error: ${error.message || 'Unknown error'}`);
397
- this.connected = false;
398
+ this._setConnected(false);
398
399
  this.websocket = null;
399
400
  };
400
401
 
@@ -402,7 +403,7 @@
402
403
  this._receiveMessages();
403
404
 
404
405
  } catch (e) {
405
- this.connected = false;
406
+ this._setConnected(false);
406
407
  this.websocket = null;
407
408
  // 401 is a permanent auth rejection — retrying won't help
408
409
  if (e.message && e.message.includes('401')) {
@@ -454,7 +455,7 @@
454
455
  }
455
456
  this.log('INFO', 'Done sending messages.');
456
457
  this.stop();
457
- this.connected = false;
458
+ this._setConnected(false);
458
459
  }
459
460
 
460
461
  /**
@@ -467,6 +468,34 @@
467
468
  };
468
469
  }
469
470
 
471
+ /**
472
+ * Register a callback fired when the WS `connected` flag transitions.
473
+ * @param {Function} handler - Callback receiving the new boolean value
474
+ */
475
+ registerConnectedHandler(handler) {
476
+ this.connectedCallback = handler;
477
+ }
478
+
479
+ /**
480
+ * Clear the connected handler.
481
+ */
482
+ clearConnectedHandler() {
483
+ this.connectedCallback = null;
484
+ }
485
+
486
+ /**
487
+ * Internal setter that fires connectedCallback on state transitions.
488
+ * @param {boolean} value
489
+ */
490
+ _setConnected(value) {
491
+ if (this.connected === value) return;
492
+ this.connected = value;
493
+ if (this.connectedCallback) {
494
+ try { this.connectedCallback(value); }
495
+ catch (e) { this.log('ERROR', `connectedCallback threw: ${e.message}`); }
496
+ }
497
+ }
498
+
470
499
  /**
471
500
  * Register a callback handler for a specific message type.
472
501
  * @param {string} messageType - Type of message
@@ -802,7 +831,7 @@
802
831
  * Stop the client without sending pending messages.
803
832
  */
804
833
  halt() {
805
- this.connected = false;
834
+ this._setConnected(false);
806
835
  this.stop();
807
836
  }
808
837
 
@@ -1421,11 +1450,24 @@
1421
1450
  /**
1422
1451
  * Delete a key by name if it exists in the localKeyMap. Safe to call multiple times.
1423
1452
  * @param {string} keyName - Key name
1453
+ * @param {string|null} [className=null] - If set, removes the key from this class only via
1454
+ * a KeyIntroduction with deleted_class set; the key may still exist on the server in
1455
+ * other classes and the localKeyMap entry is preserved. If unset, sends DeleteKey to
1456
+ * remove the key entirely and forgets the local id so a future
1457
+ * getAndPossiblyIntroduceKeyId(keyName) re-introduces with a fresh id.
1424
1458
  */
1425
- deleteKey(keyName) {
1459
+ deleteKey(keyName, className = null) {
1426
1460
  const keyId = this.localKeyMap.get(keyName);
1427
- if (keyId) {
1461
+ if (keyId === undefined) return;
1462
+ if (className) {
1463
+ this.sendMessage({
1464
+ message_type: 'KeyIntroduction',
1465
+ value: { key_id: keyId, name: keyName, deleted_class: className },
1466
+ });
1467
+ } else {
1428
1468
  this.publishDeleteKey(keyId);
1469
+ // Forget the local id so future re-introduction allocates a new one.
1470
+ this.localKeyMap.delete(keyName);
1429
1471
  }
1430
1472
  }
1431
1473
 
package/gar.js CHANGED
@@ -194,6 +194,7 @@ class GARClient {
194
194
  this.websocket = null;
195
195
  this.messageQueue = [];
196
196
  this.connected = false;
197
+ this.connectedCallback = null;
197
198
  this.reconnectDelay = 5000; // Milliseconds
198
199
  this.user = user;
199
200
  this.working_namespace = working_namespace;
@@ -377,18 +378,18 @@ class GARClient {
377
378
  });
378
379
 
379
380
  this.websocket = await connectionPromise;
380
- this.connected = true;
381
+ this._setConnected(true);
381
382
  this.log('INFO', `Connected to WebSocket server at ${this.wsEndpoint} using gar-protocol`);
382
383
 
383
384
  this.websocket.onclose = () => {
384
385
  this.log('WARNING', 'WebSocket connection closed.');
385
- this.connected = false;
386
+ this._setConnected(false);
386
387
  this.websocket = null;
387
388
  this._reconnect();
388
389
  };
389
390
  this.websocket.onerror = (error) => {
390
391
  this.log('ERROR', `WebSocket error: ${error.message || 'Unknown error'}`);
391
- this.connected = false;
392
+ this._setConnected(false);
392
393
  this.websocket = null;
393
394
  };
394
395
 
@@ -396,7 +397,7 @@ class GARClient {
396
397
  this._receiveMessages();
397
398
 
398
399
  } catch (e) {
399
- this.connected = false;
400
+ this._setConnected(false);
400
401
  this.websocket = null;
401
402
  // 401 is a permanent auth rejection — retrying won't help
402
403
  if (e.message && e.message.includes('401')) {
@@ -448,7 +449,7 @@ class GARClient {
448
449
  }
449
450
  this.log('INFO', 'Done sending messages.');
450
451
  this.stop()
451
- this.connected = false;
452
+ this._setConnected(false);
452
453
  }
453
454
 
454
455
  /**
@@ -461,6 +462,34 @@ class GARClient {
461
462
  };
462
463
  }
463
464
 
465
+ /**
466
+ * Register a callback fired when the WS `connected` flag transitions.
467
+ * @param {Function} handler - Callback receiving the new boolean value
468
+ */
469
+ registerConnectedHandler(handler) {
470
+ this.connectedCallback = handler;
471
+ }
472
+
473
+ /**
474
+ * Clear the connected handler.
475
+ */
476
+ clearConnectedHandler() {
477
+ this.connectedCallback = null;
478
+ }
479
+
480
+ /**
481
+ * Internal setter that fires connectedCallback on state transitions.
482
+ * @param {boolean} value
483
+ */
484
+ _setConnected(value) {
485
+ if (this.connected === value) return;
486
+ this.connected = value;
487
+ if (this.connectedCallback) {
488
+ try { this.connectedCallback(value); }
489
+ catch (e) { this.log('ERROR', `connectedCallback threw: ${e.message}`); }
490
+ }
491
+ }
492
+
464
493
  /**
465
494
  * Register a callback handler for a specific message type.
466
495
  * @param {string} messageType - Type of message
@@ -796,7 +825,7 @@ class GARClient {
796
825
  * Stop the client without sending pending messages.
797
826
  */
798
827
  halt() {
799
- this.connected = false;
828
+ this._setConnected(false);
800
829
  this.stop();
801
830
  }
802
831
 
@@ -1415,11 +1444,24 @@ class GARClient {
1415
1444
  /**
1416
1445
  * Delete a key by name if it exists in the localKeyMap. Safe to call multiple times.
1417
1446
  * @param {string} keyName - Key name
1447
+ * @param {string|null} [className=null] - If set, removes the key from this class only via
1448
+ * a KeyIntroduction with deleted_class set; the key may still exist on the server in
1449
+ * other classes and the localKeyMap entry is preserved. If unset, sends DeleteKey to
1450
+ * remove the key entirely and forgets the local id so a future
1451
+ * getAndPossiblyIntroduceKeyId(keyName) re-introduces with a fresh id.
1418
1452
  */
1419
- deleteKey(keyName) {
1453
+ deleteKey(keyName, className = null) {
1420
1454
  const keyId = this.localKeyMap.get(keyName);
1421
- if (keyId) {
1455
+ if (keyId === undefined) return;
1456
+ if (className) {
1457
+ this.sendMessage({
1458
+ message_type: 'KeyIntroduction',
1459
+ value: { key_id: keyId, name: keyName, deleted_class: className },
1460
+ });
1461
+ } else {
1422
1462
  this.publishDeleteKey(keyId);
1463
+ // Forget the local id so future re-introduction allocates a new one.
1464
+ this.localKeyMap.delete(keyName);
1423
1465
  }
1424
1466
  }
1425
1467
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jsgar",
3
- "version": "4.8.0",
3
+ "version": "4.9.0",
4
4
  "description": "A Javascript client for the GAR protocol",
5
5
  "type": "module",
6
6
  "main": "dist/gar.umd.js",
@@ -36,8 +36,11 @@
36
36
  "@eslint/json": "^0.13.2",
37
37
  "@rollup/plugin-commonjs": "^24.0.0",
38
38
  "@rollup/plugin-node-resolve": "^15.0.0",
39
+ "ag-grid-community": "^34.1.1",
40
+ "ag-grid-enterprise": "^34.1.1",
39
41
  "eslint": "^9.39.4",
40
42
  "globals": "^16.0.0",
43
+ "playwright": "^1.50.0",
41
44
  "rollup": "^3.0.0"
42
45
  }
43
46
  }