jsgar 4.6.2 → 4.8.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 +28 -5
  2. package/gar.js +28 -5
  3. package/package.json +1 -1
package/dist/gar.umd.js CHANGED
@@ -193,8 +193,9 @@
193
193
  * @param {string} [logLevel='INFO'] - Logging level (DEBUG, INFO, WARNING, ERROR, CRITICAL)
194
194
  * @param {boolean} [uniqueKeyAndRecordUpdates=false] - Only one update per key/record
195
195
  * @param {string} [token=null] - Token for authenticated connections (appended as ?token= query param)
196
+ * @param {boolean} [logEveryMessage=false] - If true, log every message sent and received at INFO level.
196
197
  */
197
- constructor(wsEndpoint, user, working_namespace = null, heartbeatTimeoutInterval = 60000, allowSelfSignedCertificate = false, logLevel = 'INFO', uniqueKeyAndRecordUpdates = false, token = null) {
198
+ constructor(wsEndpoint, user, working_namespace = null, heartbeatTimeoutInterval = 60000, allowSelfSignedCertificate = false, logLevel = 'INFO', uniqueKeyAndRecordUpdates = false, token = null, logEveryMessage = false) {
198
199
  this.wsEndpoint = token ? `${wsEndpoint}${wsEndpoint.includes('?') ? '&' : '?'}token=${token}` : wsEndpoint;
199
200
  this.websocket = null;
200
201
  this.messageQueue = [];
@@ -208,6 +209,7 @@
208
209
  this.scaledHeartbeatTimeoutInterval *= this.timeoutScale;
209
210
  }
210
211
  this.unique_key_and_record_updates = uniqueKeyAndRecordUpdates;
212
+ this.logEveryMessage = logEveryMessage;
211
213
  this.version = 650709;
212
214
  this.uuid = GARClient._generateUUID();
213
215
 
@@ -440,7 +442,9 @@
440
442
  if (message === null) break;
441
443
  if (this._isSocketOpen()) {
442
444
  this.websocket.send(JSON.stringify(message));
443
- this.log('DEBUG', `Sent: ${JSON.stringify(message)}`);
445
+ if (this.logEveryMessage) {
446
+ this.log('INFO', `Sent: ${JSON.stringify(message)}`);
447
+ }
444
448
  }
445
449
  } catch (e) {
446
450
  this.log('WARNING', `Error sending message: ${e.message}`);
@@ -915,6 +919,9 @@
915
919
  * @param {Object} message - Incoming message
916
920
  */
917
921
  _processMessage(message) {
922
+ if (this.logEveryMessage) {
923
+ this.log('INFO', `Received: ${JSON.stringify(message)}`);
924
+ }
918
925
  const msgType = message.message_type;
919
926
  let subscriptionGroup = 0;
920
927
  if (msgType === 'TopicIntroduction') {
@@ -1324,13 +1331,29 @@
1324
1331
  * @param {boolean} [options.skipOwnershipChecks=false] - Bypass ownership validation.
1325
1332
  * @param {boolean} [options.requireExisting=false] - Only write to existing keys; do not create new keys.
1326
1333
  * @param {number} [options.clientKeyId=0] - The g::Client key ID for ownership. 0 uses the connection key.
1334
+ * @param {string} [options.clientKeyName=''] - If non-empty, atomically introduce this g::Client key with
1335
+ * the message. The server creates the key and maps the remote id in one round-trip; no separate
1336
+ * KeyIntroduction is sent. Ignored if the name is already mapped locally (existing id is reused).
1327
1337
  */
1328
- updateActiveOwnership({ msgRef = 0, ownershipAction = 'None', skipOwnershipChecks = false, requireExisting = false, clientKeyId = 0 } = {}) {
1338
+ updateActiveOwnership({ msgRef = 0, ownershipAction = 'None', skipOwnershipChecks = false, requireExisting = false, clientKeyId = 0, clientKeyName = '' } = {}) {
1339
+ if (clientKeyName) {
1340
+ const existingId = this.localKeyMap.get(clientKeyName);
1341
+ if (existingId !== undefined) {
1342
+ clientKeyId = existingId;
1343
+ clientKeyName = '';
1344
+ } else {
1345
+ clientKeyId = this.localKeyCounter++;
1346
+ this.localKeyMap.set(clientKeyName, clientKeyId);
1347
+ }
1348
+ }
1329
1349
  const newOwnership = { msg_ref: msgRef, ownership_action: ownershipAction, skip_ownership_checks: skipOwnershipChecks, require_existing: requireExisting, client_key_id: clientKeyId };
1330
1350
  const cur = this._activeOwnership;
1331
- if (newOwnership.msg_ref !== cur.msg_ref || newOwnership.ownership_action !== cur.ownership_action || newOwnership.skip_ownership_checks !== cur.skip_ownership_checks || newOwnership.require_existing !== cur.require_existing || newOwnership.client_key_id !== cur.client_key_id) {
1351
+ const changed = newOwnership.msg_ref !== cur.msg_ref || newOwnership.ownership_action !== cur.ownership_action || newOwnership.skip_ownership_checks !== cur.skip_ownership_checks || newOwnership.require_existing !== cur.require_existing || newOwnership.client_key_id !== cur.client_key_id;
1352
+ if (changed || clientKeyName) {
1332
1353
  this._activeOwnership = newOwnership;
1333
- this.sendMessage({ message_type: 'ActiveOwnership', value: newOwnership });
1354
+ const value = { ...newOwnership };
1355
+ if (clientKeyName) value.client_key_name = clientKeyName;
1356
+ this.sendMessage({ message_type: 'ActiveOwnership', value });
1334
1357
  }
1335
1358
  }
1336
1359
 
package/gar.js CHANGED
@@ -187,8 +187,9 @@ class GARClient {
187
187
  * @param {string} [logLevel='INFO'] - Logging level (DEBUG, INFO, WARNING, ERROR, CRITICAL)
188
188
  * @param {boolean} [uniqueKeyAndRecordUpdates=false] - Only one update per key/record
189
189
  * @param {string} [token=null] - Token for authenticated connections (appended as ?token= query param)
190
+ * @param {boolean} [logEveryMessage=false] - If true, log every message sent and received at INFO level.
190
191
  */
191
- constructor(wsEndpoint, user, working_namespace = null, heartbeatTimeoutInterval = 60000, allowSelfSignedCertificate = false, logLevel = 'INFO', uniqueKeyAndRecordUpdates = false, token = null) {
192
+ constructor(wsEndpoint, user, working_namespace = null, heartbeatTimeoutInterval = 60000, allowSelfSignedCertificate = false, logLevel = 'INFO', uniqueKeyAndRecordUpdates = false, token = null, logEveryMessage = false) {
192
193
  this.wsEndpoint = token ? `${wsEndpoint}${wsEndpoint.includes('?') ? '&' : '?'}token=${token}` : wsEndpoint;
193
194
  this.websocket = null;
194
195
  this.messageQueue = [];
@@ -202,6 +203,7 @@ class GARClient {
202
203
  this.scaledHeartbeatTimeoutInterval *= this.timeoutScale;
203
204
  }
204
205
  this.unique_key_and_record_updates = uniqueKeyAndRecordUpdates;
206
+ this.logEveryMessage = logEveryMessage;
205
207
  this.version = 650709;
206
208
  this.uuid = GARClient._generateUUID();
207
209
 
@@ -434,7 +436,9 @@ class GARClient {
434
436
  if (message === null) break;
435
437
  if (this._isSocketOpen()) {
436
438
  this.websocket.send(JSON.stringify(message));
437
- this.log('DEBUG', `Sent: ${JSON.stringify(message)}`);
439
+ if (this.logEveryMessage) {
440
+ this.log('INFO', `Sent: ${JSON.stringify(message)}`);
441
+ }
438
442
  }
439
443
  } catch (e) {
440
444
  this.log('WARNING', `Error sending message: ${e.message}`);
@@ -909,6 +913,9 @@ class GARClient {
909
913
  * @param {Object} message - Incoming message
910
914
  */
911
915
  _processMessage(message) {
916
+ if (this.logEveryMessage) {
917
+ this.log('INFO', `Received: ${JSON.stringify(message)}`);
918
+ }
912
919
  const msgType = message.message_type;
913
920
  let subscriptionGroup = 0;
914
921
  if (msgType === 'TopicIntroduction') {
@@ -1318,13 +1325,29 @@ class GARClient {
1318
1325
  * @param {boolean} [options.skipOwnershipChecks=false] - Bypass ownership validation.
1319
1326
  * @param {boolean} [options.requireExisting=false] - Only write to existing keys; do not create new keys.
1320
1327
  * @param {number} [options.clientKeyId=0] - The g::Client key ID for ownership. 0 uses the connection key.
1328
+ * @param {string} [options.clientKeyName=''] - If non-empty, atomically introduce this g::Client key with
1329
+ * the message. The server creates the key and maps the remote id in one round-trip; no separate
1330
+ * KeyIntroduction is sent. Ignored if the name is already mapped locally (existing id is reused).
1321
1331
  */
1322
- updateActiveOwnership({ msgRef = 0, ownershipAction = 'None', skipOwnershipChecks = false, requireExisting = false, clientKeyId = 0 } = {}) {
1332
+ updateActiveOwnership({ msgRef = 0, ownershipAction = 'None', skipOwnershipChecks = false, requireExisting = false, clientKeyId = 0, clientKeyName = '' } = {}) {
1333
+ if (clientKeyName) {
1334
+ const existingId = this.localKeyMap.get(clientKeyName);
1335
+ if (existingId !== undefined) {
1336
+ clientKeyId = existingId;
1337
+ clientKeyName = '';
1338
+ } else {
1339
+ clientKeyId = this.localKeyCounter++;
1340
+ this.localKeyMap.set(clientKeyName, clientKeyId);
1341
+ }
1342
+ }
1323
1343
  const newOwnership = { msg_ref: msgRef, ownership_action: ownershipAction, skip_ownership_checks: skipOwnershipChecks, require_existing: requireExisting, client_key_id: clientKeyId };
1324
1344
  const cur = this._activeOwnership;
1325
- if (newOwnership.msg_ref !== cur.msg_ref || newOwnership.ownership_action !== cur.ownership_action || newOwnership.skip_ownership_checks !== cur.skip_ownership_checks || newOwnership.require_existing !== cur.require_existing || newOwnership.client_key_id !== cur.client_key_id) {
1345
+ const changed = newOwnership.msg_ref !== cur.msg_ref || newOwnership.ownership_action !== cur.ownership_action || newOwnership.skip_ownership_checks !== cur.skip_ownership_checks || newOwnership.require_existing !== cur.require_existing || newOwnership.client_key_id !== cur.client_key_id;
1346
+ if (changed || clientKeyName) {
1326
1347
  this._activeOwnership = newOwnership;
1327
- this.sendMessage({ message_type: 'ActiveOwnership', value: newOwnership });
1348
+ const value = { ...newOwnership };
1349
+ if (clientKeyName) value.client_key_name = clientKeyName;
1350
+ this.sendMessage({ message_type: 'ActiveOwnership', value });
1328
1351
  }
1329
1352
  }
1330
1353
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jsgar",
3
- "version": "4.6.2",
3
+ "version": "4.8.0",
4
4
  "description": "A Javascript client for the GAR protocol",
5
5
  "type": "module",
6
6
  "main": "dist/gar.umd.js",