jsgar 3.8.3 → 4.0.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.
Files changed (2) hide show
  1. package/dist/gar.umd.js +68 -2
  2. package/package.json +1 -1
package/dist/gar.umd.js CHANGED
@@ -54,7 +54,8 @@
54
54
  this.scaledHeartbeatTimeoutInterval *= this.timeoutScale;
55
55
  }
56
56
  this.unique_key_and_record_updates = uniqueKeyAndRecordUpdates;
57
- this.version = 650707;
57
+ this.version = 650708;
58
+ this.uuid = GARClient._generateUUID();
58
59
 
59
60
  if (typeof window !== 'undefined' && window.location) {
60
61
  this.application = window.location.href;
@@ -412,6 +413,15 @@
412
413
  }, subscriptionGroup);
413
414
  }
414
415
 
416
+ /**
417
+ * Register handler for JSONCompareExchangeResult message.
418
+ * @param {Function} handler - Callback with (message)
419
+ * @param {number} [subscriptionGroup=0] - The subscription group for callback
420
+ */
421
+ registerCompareExchangeResultHandler(handler, subscriptionGroup = 0) {
422
+ this.registerHandler('JSONCompareExchangeResult', handler, subscriptionGroup);
423
+ }
424
+
415
425
  /**
416
426
  * Register handler for BatchUpdate message.
417
427
  * If a batch handler is registered it is expected to process all the updates in the batch.
@@ -508,6 +518,7 @@
508
518
  version: this.version,
509
519
  heartbeat_timeout_interval: Math.floor(this.scaledHeartbeatTimeoutInterval),
510
520
  unique_key_and_record_updates: this.unique_key_and_record_updates,
521
+ uuid: this.uuid,
511
522
  user: this.user,
512
523
  working_namespace: this.working_namespace
513
524
  }
@@ -758,6 +769,8 @@
758
769
  // New Introduction: do not reset the first-heartbeat promise to avoid racing
759
770
  // with consumers already awaiting it. The existing promise will resolve on
760
771
  // the first Heartbeat observed during the grace period above.
772
+ } else if (msgType === 'JSONCompareExchangeResult') {
773
+ subscriptionGroup = this.activeSubscriptionGroup;
761
774
  } else if (msgType === 'JSONRecordUpdate') {
762
775
  subscriptionGroup = this.activeSubscriptionGroup;
763
776
  const recordId = message.value.record_id;
@@ -903,6 +916,7 @@
903
916
  * @param {number} [snapshotSizeLimit=0] - Limit snapshot size
904
917
  * @param {number} [nagleInterval=0] - Nagle interval in milliseconds
905
918
  * @param {number} [limit=0] - Limits records in initial snapshot (0 = all)
919
+ * @param {string|Array<string>|null} [referencingClassList=null] - Referencing class name(s); if provided, include referencing keys and records per proto.gar subscribe.referencing_class_list
906
920
  */
907
921
  subscribe(
908
922
  name,
@@ -924,7 +938,8 @@
924
938
  subscriptionSet = null,
925
939
  snapshotSizeLimit = 0,
926
940
  nagleInterval = 0,
927
- limit = 0
941
+ limit = 0,
942
+ referencingClassList = null
928
943
  ) {
929
944
  // Validate mutually exclusive parameters
930
945
  if (keyName && (keyFilter || excludeKeyFilter)) {
@@ -948,6 +963,14 @@
948
963
  classList = className;
949
964
  }
950
965
 
966
+ // Normalize referencingClassList to an array
967
+ let referencingClasses = null;
968
+ if (typeof referencingClassList === 'string') {
969
+ referencingClasses = referencingClassList.split(/\s+/).filter(Boolean);
970
+ } else if (Array.isArray(referencingClassList)) {
971
+ referencingClasses = referencingClassList;
972
+ }
973
+
951
974
  let singleClass = Array.isArray(classList) && classList.length === 1 ? classList[0] : null;
952
975
 
953
976
  // Convert keyName to array
@@ -1014,6 +1037,9 @@
1014
1037
  if (classList) {
1015
1038
  valueDict.class_list = classList;
1016
1039
  }
1040
+ if (referencingClasses && referencingClasses.length > 0) {
1041
+ valueDict.referencing_class_list = referencingClasses;
1042
+ }
1017
1043
  if (keyFilter) {
1018
1044
  valueDict.key_filter = keyFilter;
1019
1045
  }
@@ -1222,6 +1248,34 @@
1222
1248
  this.publishRecordWithIds(keyId, topicId, value);
1223
1249
  }
1224
1250
 
1251
+ /**
1252
+ * Send a compare-exchange using explicit key and topic IDs.
1253
+ * @param {number} keyId - Key ID
1254
+ * @param {number} topicId - Topic ID
1255
+ * @param {any} test - Expected current value (null = expect missing/empty)
1256
+ * @param {any} value - New value to set on match
1257
+ */
1258
+ compareExchangeRecordWithIds(keyId, topicId, test, value) {
1259
+ this.sendMessage({
1260
+ message_type: 'JSONCompareExchange',
1261
+ value: { record_id: { key_id: keyId, topic_id: topicId }, test, value }
1262
+ });
1263
+ }
1264
+
1265
+ /**
1266
+ * Send a compare-exchange using names, converting to local IDs.
1267
+ * @param {string} keyName - Key name
1268
+ * @param {string} topicName - Topic name
1269
+ * @param {any} test - Expected current value (null = expect missing/empty)
1270
+ * @param {any} value - New value to set on match
1271
+ * @param {string|null} [className=null] - Class name
1272
+ */
1273
+ compareExchangeRecord(keyName, topicName, test, value, className = null) {
1274
+ const keyId = this.getAndPossiblyIntroduceKeyId(keyName, className);
1275
+ const topicId = this.getAndPossiblyIntroduceTopicId(topicName);
1276
+ this.compareExchangeRecordWithIds(keyId, topicId, test, value);
1277
+ }
1278
+
1225
1279
  /**
1226
1280
  * Query GAR deployment routing to find servers with matching publications.
1227
1281
  * Mirrors the Python client's route_query implementation.
@@ -1401,6 +1455,18 @@
1401
1455
  }, Math.max(0, Math.floor(timeout * 1000)));
1402
1456
  });
1403
1457
  }
1458
+
1459
+ static _generateUUID() {
1460
+ const bytes = new Uint8Array(16);
1461
+ if (typeof globalThis.crypto !== 'undefined' && globalThis.crypto.getRandomValues)
1462
+ globalThis.crypto.getRandomValues(bytes);
1463
+ else
1464
+ require('crypto').randomFillSync(bytes);
1465
+ bytes[6] = (bytes[6] & 0x0f) | 0x40; // version 4
1466
+ bytes[8] = (bytes[8] & 0x3f) | 0x80; // variant RFC 4122
1467
+ const view = new DataView(bytes.buffer);
1468
+ return { low: Number(view.getBigUint64(0, true)), high: Number(view.getBigUint64(8, true)) };
1469
+ }
1404
1470
  }
1405
1471
 
1406
1472
  return GARClient;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jsgar",
3
- "version": "3.8.3",
3
+ "version": "4.0.1",
4
4
  "description": "A Javascript client for the GAR protocol",
5
5
  "type": "module",
6
6
  "main": "dist/gar.umd.js",