jsgar 4.9.0 → 4.9.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/dist/gar.umd.js +27 -13
- package/gar.js +27 -13
- package/package.json +1 -1
package/dist/gar.umd.js
CHANGED
|
@@ -1101,9 +1101,18 @@
|
|
|
1101
1101
|
this.log('INFO', 'Received Logoff from server');
|
|
1102
1102
|
this.stop();
|
|
1103
1103
|
} else if (msgType === 'Error') {
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1104
|
+
// proto.gar's `error` struct carries `recoverable: bool`. Recoverable errors mean
|
|
1105
|
+
// the server processed the failing message (e.g. a publish that violated some
|
|
1106
|
+
// server-side check), logged it, and kept the connection alive. We dispatch the
|
|
1107
|
+
// message to the user's error handler but don't tear down the client. Non-recoverable
|
|
1108
|
+
// errors are followed by a server disconnect; we set exit_code + stop() so callers
|
|
1109
|
+
// (CLI tools, the html_view UI) see the failure.
|
|
1110
|
+
const recoverable = !!message.value.recoverable;
|
|
1111
|
+
this.log(recoverable ? 'WARNING' : 'ERROR', `GAR ${message.value.message}`);
|
|
1112
|
+
if (!recoverable) {
|
|
1113
|
+
this.exitCode = 1;
|
|
1114
|
+
this.stop();
|
|
1115
|
+
}
|
|
1107
1116
|
}
|
|
1108
1117
|
|
|
1109
1118
|
this.checkHeartbeat();
|
|
@@ -1387,28 +1396,25 @@
|
|
|
1387
1396
|
}
|
|
1388
1397
|
|
|
1389
1398
|
/**
|
|
1390
|
-
* Introduce a new key if not already known and return local key ID.
|
|
1399
|
+
* Introduce a new key if not already known and return local key ID. className is required;
|
|
1400
|
+
* a bare introduction with no class_list can't be routed by upstream proxies.
|
|
1391
1401
|
* @param {string} name - Key name
|
|
1392
|
-
* @param {string|Array<string
|
|
1402
|
+
* @param {string|Array<string>} className - Class name(s)
|
|
1393
1403
|
* @returns {number} Local key ID
|
|
1394
1404
|
*/
|
|
1395
|
-
getAndPossiblyIntroduceKeyId(name, className
|
|
1405
|
+
getAndPossiblyIntroduceKeyId(name, className) {
|
|
1396
1406
|
const existingId = this.localKeyMap.get(name);
|
|
1397
1407
|
if (existingId !== undefined && this.invalidatedKeyIds.has(existingId)) {
|
|
1398
1408
|
this.invalidatedKeyIds.delete(existingId);
|
|
1399
1409
|
this.localKeyMap.delete(name);
|
|
1400
1410
|
}
|
|
1401
1411
|
if (!this.localKeyMap.has(name)) {
|
|
1412
|
+
if (!className) throw new Error(`getAndPossiblyIntroduceKeyId: className required to introduce key "${name}"`);
|
|
1402
1413
|
const keyId = this.localKeyCounter++;
|
|
1403
1414
|
this.localKeyMap.set(name, keyId);
|
|
1404
1415
|
const value = { key_id: keyId, name };
|
|
1405
|
-
if (className)
|
|
1406
|
-
|
|
1407
|
-
value.class_list = className.split(/\s+/).filter(Boolean);
|
|
1408
|
-
} else if (Array.isArray(className)) {
|
|
1409
|
-
value.class_list = className;
|
|
1410
|
-
}
|
|
1411
|
-
}
|
|
1416
|
+
if (typeof className === 'string') value.class_list = className.split(/\s+/).filter(Boolean);
|
|
1417
|
+
else if (Array.isArray(className)) value.class_list = className;
|
|
1412
1418
|
this.sendMessage({ message_type: 'KeyIntroduction', value });
|
|
1413
1419
|
}
|
|
1414
1420
|
return this.localKeyMap.get(name);
|
|
@@ -1511,6 +1517,10 @@
|
|
|
1511
1517
|
* @param {any} value - JSON-serializable value
|
|
1512
1518
|
*/
|
|
1513
1519
|
publishRecordWithIds(keyId, topicId, value) {
|
|
1520
|
+
if (value === undefined) {
|
|
1521
|
+
this.log('ERROR', `publishRecordWithIds(${keyId}, ${topicId}): refusing to publish undefined — JSON.stringify would drop the "value" field and the server would reject with "Missing record 'value' field"`);
|
|
1522
|
+
return;
|
|
1523
|
+
}
|
|
1514
1524
|
const updateMsg = {
|
|
1515
1525
|
message_type: 'JSONRecordUpdate',
|
|
1516
1526
|
value: {
|
|
@@ -1529,6 +1539,10 @@
|
|
|
1529
1539
|
* @param {string|null} [className=null] - Class name
|
|
1530
1540
|
*/
|
|
1531
1541
|
publishRecord(keyName, topicName, value, className = null) {
|
|
1542
|
+
if (value === undefined) {
|
|
1543
|
+
this.log('ERROR', `publishRecord(${keyName}, ${topicName}): refusing to publish undefined — JSON.stringify would drop the "value" field and the server would reject with "Missing record 'value' field"`);
|
|
1544
|
+
return;
|
|
1545
|
+
}
|
|
1532
1546
|
const keyId = this.getAndPossiblyIntroduceKeyId(keyName, className);
|
|
1533
1547
|
const topicId = this.getAndPossiblyIntroduceTopicId(topicName);
|
|
1534
1548
|
this.publishRecordWithIds(keyId, topicId, value);
|
package/gar.js
CHANGED
|
@@ -1095,9 +1095,18 @@ class GARClient {
|
|
|
1095
1095
|
this.log('INFO', 'Received Logoff from server');
|
|
1096
1096
|
this.stop();
|
|
1097
1097
|
} else if (msgType === 'Error') {
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1098
|
+
// proto.gar's `error` struct carries `recoverable: bool`. Recoverable errors mean
|
|
1099
|
+
// the server processed the failing message (e.g. a publish that violated some
|
|
1100
|
+
// server-side check), logged it, and kept the connection alive. We dispatch the
|
|
1101
|
+
// message to the user's error handler but don't tear down the client. Non-recoverable
|
|
1102
|
+
// errors are followed by a server disconnect; we set exit_code + stop() so callers
|
|
1103
|
+
// (CLI tools, the html_view UI) see the failure.
|
|
1104
|
+
const recoverable = !!message.value.recoverable;
|
|
1105
|
+
this.log(recoverable ? 'WARNING' : 'ERROR', `GAR ${message.value.message}`);
|
|
1106
|
+
if (!recoverable) {
|
|
1107
|
+
this.exitCode = 1;
|
|
1108
|
+
this.stop();
|
|
1109
|
+
}
|
|
1101
1110
|
}
|
|
1102
1111
|
|
|
1103
1112
|
this.checkHeartbeat();
|
|
@@ -1381,28 +1390,25 @@ class GARClient {
|
|
|
1381
1390
|
}
|
|
1382
1391
|
|
|
1383
1392
|
/**
|
|
1384
|
-
* Introduce a new key if not already known and return local key ID.
|
|
1393
|
+
* Introduce a new key if not already known and return local key ID. className is required;
|
|
1394
|
+
* a bare introduction with no class_list can't be routed by upstream proxies.
|
|
1385
1395
|
* @param {string} name - Key name
|
|
1386
|
-
* @param {string|Array<string
|
|
1396
|
+
* @param {string|Array<string>} className - Class name(s)
|
|
1387
1397
|
* @returns {number} Local key ID
|
|
1388
1398
|
*/
|
|
1389
|
-
getAndPossiblyIntroduceKeyId(name, className
|
|
1399
|
+
getAndPossiblyIntroduceKeyId(name, className) {
|
|
1390
1400
|
const existingId = this.localKeyMap.get(name);
|
|
1391
1401
|
if (existingId !== undefined && this.invalidatedKeyIds.has(existingId)) {
|
|
1392
1402
|
this.invalidatedKeyIds.delete(existingId);
|
|
1393
1403
|
this.localKeyMap.delete(name);
|
|
1394
1404
|
}
|
|
1395
1405
|
if (!this.localKeyMap.has(name)) {
|
|
1406
|
+
if (!className) throw new Error(`getAndPossiblyIntroduceKeyId: className required to introduce key "${name}"`);
|
|
1396
1407
|
const keyId = this.localKeyCounter++;
|
|
1397
1408
|
this.localKeyMap.set(name, keyId);
|
|
1398
1409
|
const value = { key_id: keyId, name };
|
|
1399
|
-
if (className)
|
|
1400
|
-
|
|
1401
|
-
value.class_list = className.split(/\s+/).filter(Boolean);
|
|
1402
|
-
} else if (Array.isArray(className)) {
|
|
1403
|
-
value.class_list = className;
|
|
1404
|
-
}
|
|
1405
|
-
}
|
|
1410
|
+
if (typeof className === 'string') value.class_list = className.split(/\s+/).filter(Boolean);
|
|
1411
|
+
else if (Array.isArray(className)) value.class_list = className;
|
|
1406
1412
|
this.sendMessage({ message_type: 'KeyIntroduction', value });
|
|
1407
1413
|
}
|
|
1408
1414
|
return this.localKeyMap.get(name);
|
|
@@ -1505,6 +1511,10 @@ class GARClient {
|
|
|
1505
1511
|
* @param {any} value - JSON-serializable value
|
|
1506
1512
|
*/
|
|
1507
1513
|
publishRecordWithIds(keyId, topicId, value) {
|
|
1514
|
+
if (value === undefined) {
|
|
1515
|
+
this.log('ERROR', `publishRecordWithIds(${keyId}, ${topicId}): refusing to publish undefined — JSON.stringify would drop the "value" field and the server would reject with "Missing record 'value' field"`);
|
|
1516
|
+
return;
|
|
1517
|
+
}
|
|
1508
1518
|
const updateMsg = {
|
|
1509
1519
|
message_type: 'JSONRecordUpdate',
|
|
1510
1520
|
value: {
|
|
@@ -1523,6 +1533,10 @@ class GARClient {
|
|
|
1523
1533
|
* @param {string|null} [className=null] - Class name
|
|
1524
1534
|
*/
|
|
1525
1535
|
publishRecord(keyName, topicName, value, className = null) {
|
|
1536
|
+
if (value === undefined) {
|
|
1537
|
+
this.log('ERROR', `publishRecord(${keyName}, ${topicName}): refusing to publish undefined — JSON.stringify would drop the "value" field and the server would reject with "Missing record 'value' field"`);
|
|
1538
|
+
return;
|
|
1539
|
+
}
|
|
1526
1540
|
const keyId = this.getAndPossiblyIntroduceKeyId(keyName, className);
|
|
1527
1541
|
const topicId = this.getAndPossiblyIntroduceTopicId(topicName);
|
|
1528
1542
|
this.publishRecordWithIds(keyId, topicId, value);
|