infinispan 0.14.0 → 0.16.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.
package/lib/protocols.js CHANGED
@@ -23,6 +23,15 @@
23
23
  var INFINITE_LIFESPAN = 0x01, INFINITE_MAXIDLE = 0x02; // Duration flag masks
24
24
  var MAGIC = 0xA0;
25
25
 
26
+ var FLAGS = {
27
+ FORCE_RETURN_VALUE: 0x0001,
28
+ DEFAULT_LIFESPAN: 0x0002,
29
+ DEFAULT_MAXIDLE: 0x0004,
30
+ SKIP_CACHE_LOAD: 0x0008,
31
+ SKIP_INDEXING: 0x0010,
32
+ SKIP_LISTENER_NOTIFICATION: 0x0020
33
+ };
34
+
26
35
  /**
27
36
  * Creates decode actions for a key-value pair.
28
37
  * @param {Object} decoderKey Key decoder descriptor.
@@ -129,8 +138,10 @@
129
138
  };
130
139
 
131
140
  return {
132
- buildFlags: function (opts) { // TODO: Move out to a Mixin (similar to expiry)
133
- return hasOptPrev(opts) ? 0x01 : 0;
141
+ buildFlags: function (opts) {
142
+ var result = hasOptPrev(opts) ? FLAGS.FORCE_RETURN_VALUE : 0;
143
+ if (hasOpt(opts, 'flags')) result |= opts.flags;
144
+ return result;
134
145
  },
135
146
  /**
136
147
  * Returns the protocol version as a human-readable string (e.g. '3.1').
@@ -577,8 +588,8 @@
577
588
  return hasPrevious(header.status);
578
589
  },
579
590
  isEvent: function(header) {
580
- //return ((op(header) >> 4) & 0x06) == 0x06;
581
- return ((header.opCode >> 4) & 0x06) == 0x06;
591
+ var op = header.opCode;
592
+ return op >= 0x60 && op <= 0x64;
582
593
  },
583
594
  isError: function(header) {
584
595
  return header.opCode == 0x50;
@@ -699,18 +710,31 @@
699
710
 
700
711
  var steps = [
701
712
  codec.encodeString(listenerId), // listener id
702
- codec.encodeUByte(includeState), // include state
703
- codec.encodeUByte(0) // TODO filter factory name
713
+ codec.encodeUByte(includeState) // include state
704
714
  ];
705
715
 
716
+ // Filter factory
717
+ if (_.has(opts, 'filterFactory') && _.has(opts.filterFactory, 'name')) {
718
+ steps.push(codec.encodeString(opts.filterFactory.name));
719
+ var filterParams = opts.filterFactory.params || [];
720
+ steps.push(codec.encodeUByte(filterParams.length));
721
+ filterParams.forEach(function(p) { steps.push(codec.encodeBytesWithLength(p)); });
722
+ } else {
723
+ steps.push(codec.encodeUByte(0));
724
+ }
725
+
726
+ // Converter factory
706
727
  if (_.has(opts, 'converterFactory') && _.has(opts.converterFactory, 'name')) {
707
728
  steps.push(codec.encodeString(opts.converterFactory.name));
708
- steps.push(codec.encodeUByte(0)); // TODO add converter parameter support
729
+ var converterParams = opts.converterFactory.params || [];
730
+ steps.push(codec.encodeUByte(converterParams.length));
731
+ converterParams.forEach(function(p) { steps.push(codec.encodeBytesWithLength(p)); });
709
732
  } else {
710
- steps.push(codec.encodeUByte(0)); // no converter
733
+ steps.push(codec.encodeUByte(0));
711
734
  }
712
735
 
713
- steps.push(codec.encodeUByte(0)); // raw data disabled
736
+ // Raw data
737
+ steps.push(codec.encodeUByte(hasOpt(opts, 'useRawData') ? 1 : 0));
714
738
 
715
739
  return function() {
716
740
  return steps;
@@ -1105,9 +1129,9 @@
1105
1129
  var authDone = DECODE_UBYTE(bytebuf);
1106
1130
  if(authDone == 1) {
1107
1131
  logger.tracef('SASL authentication complete');
1108
- return {result: {response: DECODE_UBYTE(bytebuf)}, continue: true};
1132
+ return {result: {response: DECODE_UBYTE(bytebuf), complete: true}, continue: true};
1109
1133
  } else {
1110
- return {result: {response: DECODE_STRING(bytebuf)}, continue: true};
1134
+ return {result: {response: DECODE_STRING(bytebuf), complete: false}, continue: true};
1111
1135
  }
1112
1136
  }
1113
1137
  };
@@ -1310,6 +1334,81 @@
1310
1334
  };
1311
1335
  }());
1312
1336
 
1337
+ var MultimapMixin = (function() {
1338
+ var SUPPORTS_DUPLICATES = codec.encodeUByte(0x00);
1339
+
1340
+ return {
1341
+ encodeMultimapKey: function(k) {
1342
+ var outer = this;
1343
+ return function() {
1344
+ return [outer.encodeMediaKey(k), SUPPORTS_DUPLICATES];
1345
+ };
1346
+ },
1347
+ encodeMultimapPut: function(k, v) {
1348
+ var outer = this;
1349
+ return function(opts) {
1350
+ return f.cat(
1351
+ [outer.encodeMediaKey(k)],
1352
+ outer.encodeExpiry(opts),
1353
+ [outer.encodeMediaValue(v), SUPPORTS_DUPLICATES]
1354
+ );
1355
+ };
1356
+ },
1357
+ encodeMultimapKeyValue: function(k, v) {
1358
+ var outer = this;
1359
+ return function() {
1360
+ return f.cat(
1361
+ [outer.encodeMediaKey(k)],
1362
+ [codec.encodeUByte(0x77)],
1363
+ [outer.encodeMediaValue(v), SUPPORTS_DUPLICATES]
1364
+ );
1365
+ };
1366
+ },
1367
+ encodeMultimapValue: function(v) {
1368
+ var outer = this;
1369
+ return function() {
1370
+ return [codec.encodeUByte(0x77), outer.encodeMediaValue(v), SUPPORTS_DUPLICATES];
1371
+ };
1372
+ },
1373
+ encodeMultimapSupportsDuplicates: function() {
1374
+ return function() {
1375
+ return [SUPPORTS_DUPLICATES];
1376
+ };
1377
+ },
1378
+ decodeMultimapCollection: function() {
1379
+ var decoderValue = decoderMedia(this.valueMediaType);
1380
+ var decodeSingleValue = decodeSingle(decoderValue);
1381
+ return function(header, bytebuf) {
1382
+ if (header.status !== 0x00 && header.status !== 0x03)
1383
+ return {result: [], continue: true};
1384
+ var count = DECODE_VINT(bytebuf);
1385
+ if (!f.existy(count))
1386
+ return {continue: false};
1387
+ var values = [];
1388
+ for (var i = 0; i < count; i++) {
1389
+ var v = decodeSingleValue(bytebuf);
1390
+ if (!f.existy(v))
1391
+ return {continue: false};
1392
+ values.push(v);
1393
+ }
1394
+ return {result: values, continue: true};
1395
+ };
1396
+ },
1397
+ decodeMultimapBoolean: function(header, bytebuf) {
1398
+ var b = DECODE_UBYTE(bytebuf);
1399
+ if (!f.existy(b))
1400
+ return {continue: false};
1401
+ return {result: b !== 0, continue: true};
1402
+ },
1403
+ decodeMultimapSize: function(header, bytebuf) {
1404
+ var size = f.actions([codec.decodeVLong()], codec.lastDecoded)(bytebuf);
1405
+ if (!f.existy(size) && size !== 0)
1406
+ return {continue: false};
1407
+ return {result: size, continue: true};
1408
+ }
1409
+ };
1410
+ }());
1411
+
1313
1412
  /**
1314
1413
  * Protocol 4.0+ requires an 'otherParams' map after media types in the header.
1315
1414
  * This mixin overrides stepsHeader to append the count (0 = no params).
@@ -1415,6 +1514,54 @@
1415
1514
  }());
1416
1515
 
1417
1516
 
1517
+ var DECODE_INT = f.actions([codec.decodeInt()], codec.lastDecoded);
1518
+
1519
+ var TransactionMixin = {
1520
+ encodeXid: function(xid) {
1521
+ return [
1522
+ codec.encodeSignedInt(xid.formatId),
1523
+ codec.encodeBytesWithLength(xid.globalTxId),
1524
+ codec.encodeBytesWithLength(xid.branchQualifier)
1525
+ ];
1526
+ },
1527
+ encodePrepare: function(xid, modifications, onePhaseCommit, timeout) {
1528
+ var outer = this;
1529
+ return function() {
1530
+ var steps = outer.encodeXid(xid);
1531
+ steps.push(codec.encodeUByte(onePhaseCommit ? 1 : 0));
1532
+ steps.push(codec.encodeUByte(0)); // not recoverable
1533
+ steps.push(codec.encodeLong(timeout));
1534
+ steps.push(codec.encodeVInt(modifications.length));
1535
+ for (var i = 0; i < modifications.length; i++) {
1536
+ var mod = modifications[i];
1537
+ steps.push(outer.encodeMediaKey(mod.key));
1538
+ steps.push(codec.encodeUByte(mod.controlByte));
1539
+ if (!(mod.controlByte & 0x1) && !(mod.controlByte & 0x2)) {
1540
+ steps.push(codec.encodeBytes(mod.versionRead));
1541
+ }
1542
+ if (!(mod.controlByte & 0x4)) {
1543
+ steps.push(codec.encodeUByte(0x77));
1544
+ steps.push(outer.encodeMediaValue(mod.value));
1545
+ }
1546
+ }
1547
+ return steps;
1548
+ };
1549
+ },
1550
+ encodeXidOnly: function(xid) {
1551
+ var outer = this;
1552
+ return function() {
1553
+ return outer.encodeXid(xid);
1554
+ };
1555
+ },
1556
+ decodeXaResponse: function() {
1557
+ return function(header, bytebuf) {
1558
+ var code = DECODE_INT(bytebuf);
1559
+ if (!f.existy(code)) return {continue: false};
1560
+ return {result: code, continue: true};
1561
+ };
1562
+ }
1563
+ };
1564
+
1418
1565
  /**
1419
1566
  * Constructs a Hot Rod protocol instance for the given version.
1420
1567
  * @param {number} v Protocol version number.
@@ -1503,13 +1650,7 @@
1503
1650
  , Ping29Mixin
1504
1651
  , ProtostreamType
1505
1652
  , ProtobufRoot
1506
- // TODO 2.6 new ops: getStream and putStream
1507
- // TODO 2.6 add listener change: listener event interests
1508
- // TODO 2.7 new ops: prepare, commit and rollback
1509
- // TODO 2.7 new ops: counter operations
1510
- // TODO 2.7 new events: counter events
1511
- // TODO 2.8 listener events: can come from any connection
1512
- // TODO 2.8 header change: media types
1653
+ , TransactionMixin
1513
1654
  );
1514
1655
 
1515
1656
  _.extend(Protocol30.prototype
@@ -1525,6 +1666,7 @@
1525
1666
  , Ping30Mixin
1526
1667
  , ProtostreamType
1527
1668
  , ProtobufRoot
1669
+ , TransactionMixin
1528
1670
  );
1529
1671
 
1530
1672
  _.extend(Protocol31.prototype
@@ -1539,9 +1681,10 @@
1539
1681
  , SASLMixin
1540
1682
  , Ping30Mixin
1541
1683
  , CounterMixin
1684
+ , MultimapMixin
1542
1685
  , ProtostreamType
1543
1686
  , ProtobufRoot
1544
- // TODO 3.1 new ops: bloom filter near-cache
1687
+ , TransactionMixin
1545
1688
  );
1546
1689
 
1547
1690
  _.extend(Protocol40.prototype
@@ -1558,8 +1701,10 @@
1558
1701
  , SASLMixin
1559
1702
  , Ping30Mixin
1560
1703
  , CounterMixin
1704
+ , MultimapMixin
1561
1705
  , ProtostreamType
1562
1706
  , ProtobufRoot
1707
+ , TransactionMixin
1563
1708
  );
1564
1709
 
1565
1710
  _.extend(Protocol41.prototype
@@ -1576,9 +1721,10 @@
1576
1721
  , SASLMixin
1577
1722
  , Ping30Mixin
1578
1723
  , CounterMixin
1724
+ , MultimapMixin
1579
1725
  , ProtostreamType
1580
1726
  , ProtobufRoot
1581
- // TODO 4.1 new ops: chunked streaming (GetStreamStart/Next/End, PutStreamStart/Next/End)
1727
+ , TransactionMixin
1582
1728
  );
1583
1729
 
1584
1730
  exports.version22 = function(clientOpts) {
@@ -1613,6 +1759,8 @@
1613
1759
 
1614
1760
  exports.VERSION_ORDER = VERSION_ORDER;
1615
1761
 
1762
+ exports.FLAGS = FLAGS;
1763
+
1616
1764
  /**
1617
1765
  * Creates a protocol instance for the given version string.
1618
1766
  * @param {string} version Protocol version (e.g. '3.1', '4.0').
@@ -0,0 +1,123 @@
1
+ 'use strict';
2
+
3
+ (function() {
4
+
5
+ var crypto = require('crypto');
6
+
7
+ var FORMAT_ID = 0x48525458;
8
+ var NOT_READ = 0x1, NON_EXISTING = 0x2, REMOVE_OP = 0x4;
9
+ var XA_OK = 0, XA_RDONLY = 3;
10
+
11
+ function generateXid() {
12
+ return {
13
+ formatId: FORMAT_ID,
14
+ globalTxId: crypto.randomBytes(16),
15
+ branchQualifier: crypto.randomBytes(16)
16
+ };
17
+ }
18
+
19
+ function TransactionContext() {
20
+ this.xid = generateXid();
21
+ // key (string) → { value, removed (bool), versionRead (Buffer|null), wasRead (bool), existed (bool) }
22
+ this.entries = new Map();
23
+ this.active = true;
24
+ }
25
+
26
+ TransactionContext.prototype.trackPut = function(key, value) {
27
+ var entry = this.entries.get(key);
28
+ if (entry) {
29
+ entry.value = value;
30
+ entry.removed = false;
31
+ } else {
32
+ this.entries.set(key, {
33
+ value: value,
34
+ removed: false,
35
+ versionRead: null,
36
+ wasRead: false,
37
+ existed: false
38
+ });
39
+ }
40
+ };
41
+
42
+ TransactionContext.prototype.trackRemove = function(key) {
43
+ var entry = this.entries.get(key);
44
+ if (entry) {
45
+ entry.removed = true;
46
+ entry.value = undefined;
47
+ } else {
48
+ this.entries.set(key, {
49
+ value: undefined,
50
+ removed: true,
51
+ versionRead: null,
52
+ wasRead: false,
53
+ existed: false
54
+ });
55
+ }
56
+ };
57
+
58
+ TransactionContext.prototype.trackRead = function(key, meta) {
59
+ var entry = this.entries.get(key);
60
+ var version = meta ? meta.version : null;
61
+ var existed = meta !== undefined;
62
+ if (entry) {
63
+ if (!entry.wasRead) {
64
+ entry.wasRead = true;
65
+ entry.versionRead = version;
66
+ entry.existed = existed;
67
+ }
68
+ } else {
69
+ this.entries.set(key, {
70
+ value: meta ? meta.value : undefined,
71
+ removed: false,
72
+ versionRead: version,
73
+ wasRead: true,
74
+ existed: existed
75
+ });
76
+ }
77
+ };
78
+
79
+ TransactionContext.prototype.getLocalValue = function(key) {
80
+ var entry = this.entries.get(key);
81
+ if (!entry) return { found: false };
82
+ if (entry.removed) return { found: true, value: undefined };
83
+ if (entry.value !== undefined) return { found: true, value: entry.value };
84
+ return { found: false };
85
+ };
86
+
87
+ TransactionContext.prototype.computeControlByte = function(entry) {
88
+ var control = 0;
89
+ if (!entry.wasRead) {
90
+ control |= NOT_READ;
91
+ } else if (!entry.existed) {
92
+ control |= NON_EXISTING;
93
+ }
94
+ if (entry.removed) {
95
+ control |= REMOVE_OP;
96
+ }
97
+ return control;
98
+ };
99
+
100
+ TransactionContext.prototype.getModifications = function() {
101
+ var mods = [];
102
+ this.entries.forEach(function(entry, key) {
103
+ var control = this.computeControlByte(entry);
104
+ mods.push({
105
+ key: key,
106
+ controlByte: control,
107
+ versionRead: entry.versionRead,
108
+ value: entry.value
109
+ });
110
+ }.bind(this));
111
+ return mods;
112
+ };
113
+
114
+ exports.TransactionContext = TransactionContext;
115
+ exports.generateXid = generateXid;
116
+ exports.FORMAT_ID = FORMAT_ID;
117
+ exports.NOT_READ = NOT_READ;
118
+ exports.NON_EXISTING = NON_EXISTING;
119
+ exports.REMOVE_OP = REMOVE_OP;
120
+ exports.XA_OK = XA_OK;
121
+ exports.XA_RDONLY = XA_RDONLY;
122
+
123
+ }.call(this));
package/lib/uri.js ADDED
@@ -0,0 +1,206 @@
1
+ 'use strict';
2
+
3
+ (function() {
4
+
5
+ var _ = require('underscore');
6
+
7
+ var DEFAULT_PORT = 11222;
8
+
9
+ var QUERY_PARAMS = {
10
+ 'sasl_mechanism': { path: ['authentication', 'saslMechanism'], type: 'string' },
11
+ 'trust_store_file_name': { path: ['ssl', 'trustCerts'], type: 'string_array' },
12
+ 'trust_ca': { path: ['ssl', 'trustCerts'], type: 'string_array' },
13
+ 'key_store_file_name': { path: ['ssl', 'clientAuth', 'cert'], type: 'string' },
14
+ 'client_cert': { path: ['ssl', 'clientAuth', 'cert'], type: 'string' },
15
+ 'key_store_password': { path: ['ssl', 'clientAuth', 'key'], type: 'string' },
16
+ 'client_key': { path: ['ssl', 'clientAuth', 'key'], type: 'string' },
17
+ 'sni_host_name': { path: ['ssl', 'sniHostName'], type: 'string' },
18
+ 'sni_host': { path: ['ssl', 'sniHostName'], type: 'string' },
19
+ 'max_retries': { path: ['maxRetries'], type: 'int' },
20
+ 'cache_name': { path: ['cacheName'], type: 'string' }
21
+ };
22
+
23
+ /**
24
+ * Checks whether the argument is a Hot Rod URI string.
25
+ * @param {*} arg Value to check.
26
+ * @returns {boolean} True if the argument is a hotrod:// or hotrods:// URI.
27
+ */
28
+ function isHotrodURI(arg) {
29
+ return _.isString(arg) &&
30
+ (arg.indexOf('hotrod://') === 0 || arg.indexOf('hotrods://') === 0);
31
+ }
32
+
33
+ /**
34
+ * Splits a host string into host and port, handling IPv6 bracket notation.
35
+ * @param {string} hostStr Host string like "host:port" or "[::1]:port".
36
+ * @returns {{host: string, port: number}} Parsed host and port.
37
+ */
38
+ function splitHostPort(hostStr) {
39
+ hostStr = hostStr.trim();
40
+ if (hostStr.length === 0) {
41
+ throw new Error('Empty host in URI');
42
+ }
43
+
44
+ // IPv6 bracket notation: [::1]:port
45
+ if (hostStr.charAt(0) === '[') {
46
+ var closeBracket = hostStr.indexOf(']');
47
+ if (closeBracket === -1) {
48
+ throw new Error(`Invalid IPv6 address, missing closing bracket: ${hostStr}`);
49
+ }
50
+ var ipv6Host = hostStr.substring(1, closeBracket);
51
+ var afterBracket = hostStr.substring(closeBracket + 1);
52
+ if (afterBracket.length === 0) {
53
+ return { host: ipv6Host, port: DEFAULT_PORT };
54
+ }
55
+ if (afterBracket.charAt(0) === ':') {
56
+ var ipv6Port = parseInt(afterBracket.substring(1), 10);
57
+ if (isNaN(ipv6Port)) {
58
+ throw new Error(`Invalid port in URI: ${afterBracket.substring(1)}`);
59
+ }
60
+ return { host: ipv6Host, port: ipv6Port };
61
+ }
62
+ throw new Error(`Invalid IPv6 host format: ${hostStr}`);
63
+ }
64
+
65
+ var lastColon = hostStr.lastIndexOf(':');
66
+ if (lastColon === -1) {
67
+ return { host: hostStr, port: DEFAULT_PORT };
68
+ }
69
+
70
+ var host = hostStr.substring(0, lastColon);
71
+ var portStr = hostStr.substring(lastColon + 1);
72
+ var port = parseInt(portStr, 10);
73
+ if (isNaN(port)) {
74
+ throw new Error(`Invalid port in URI: ${portStr}`);
75
+ }
76
+ return { host: host, port: port };
77
+ }
78
+
79
+ /**
80
+ * Sets a nested value in an object given a path array.
81
+ * @param {Object} obj Target object.
82
+ * @param {string[]} path Array of keys.
83
+ * @param {*} value Value to set.
84
+ * @returns {void}
85
+ */
86
+ function setNested(obj, path, value) {
87
+ var current = obj;
88
+ for (var i = 0; i < path.length - 1; i++) {
89
+ if (!current[path[i]] || !_.isObject(current[path[i]])) {
90
+ current[path[i]] = {};
91
+ }
92
+ current = current[path[i]];
93
+ }
94
+ current[path[path.length - 1]] = value;
95
+ }
96
+
97
+ /**
98
+ * Parses a Hot Rod URI string into servers and options.
99
+ * @param {string} uriString URI in the format hotrod://[user:pass@]host1[:port1][,host2[:port2]][?params].
100
+ * @returns {{servers: Array<{host: string, port: number}>, options: Object}} Parsed result.
101
+ */
102
+ function parseHotrodURI(uriString) {
103
+ var tls = false;
104
+ var rest;
105
+
106
+ if (uriString.indexOf('hotrods://') === 0) {
107
+ tls = true;
108
+ rest = uriString.substring('hotrods://'.length);
109
+ } else if (uriString.indexOf('hotrod://') === 0) {
110
+ rest = uriString.substring('hotrod://'.length);
111
+ } else {
112
+ throw new Error('Invalid URI scheme, expected hotrod:// or hotrods://');
113
+ }
114
+
115
+ // Split authority from query string
116
+ var queryString = '';
117
+ var qIndex = rest.indexOf('?');
118
+ var authority;
119
+ if (qIndex !== -1) {
120
+ authority = rest.substring(0, qIndex);
121
+ queryString = rest.substring(qIndex + 1);
122
+ } else {
123
+ authority = rest;
124
+ }
125
+
126
+ // Split userinfo from hosts (find last @ to handle passwords with @)
127
+ var userName, password;
128
+ var atIndex = authority.lastIndexOf('@');
129
+ var hostsStr;
130
+ if (atIndex !== -1) {
131
+ var userinfo = authority.substring(0, atIndex);
132
+ hostsStr = authority.substring(atIndex + 1);
133
+ var colonIndex = userinfo.indexOf(':');
134
+ if (colonIndex !== -1) {
135
+ userName = decodeURIComponent(userinfo.substring(0, colonIndex));
136
+ password = decodeURIComponent(userinfo.substring(colonIndex + 1));
137
+ } else {
138
+ userName = decodeURIComponent(userinfo);
139
+ }
140
+ } else {
141
+ hostsStr = authority;
142
+ }
143
+
144
+ if (hostsStr.length === 0) {
145
+ throw new Error('No host specified in URI');
146
+ }
147
+
148
+ // Parse comma-separated hosts
149
+ var hostParts = hostsStr.split(',');
150
+ var servers = [];
151
+ for (var i = 0; i < hostParts.length; i++) {
152
+ if (hostParts[i].length > 0) {
153
+ servers.push(splitHostPort(hostParts[i]));
154
+ }
155
+ }
156
+ if (servers.length === 0) {
157
+ throw new Error('No host specified in URI');
158
+ }
159
+
160
+ // Build options from URI components
161
+ var options = {};
162
+
163
+ if (tls) {
164
+ setNested(options, ['ssl', 'enabled'], true);
165
+ }
166
+
167
+ if (userName !== undefined) {
168
+ setNested(options, ['authentication', 'enabled'], true);
169
+ setNested(options, ['authentication', 'userName'], userName);
170
+ if (password !== undefined) {
171
+ setNested(options, ['authentication', 'password'], password);
172
+ }
173
+ setNested(options, ['authentication', 'saslMechanism'], 'PLAIN');
174
+ }
175
+
176
+ // Parse query parameters
177
+ if (queryString.length > 0) {
178
+ var params = new URLSearchParams(queryString);
179
+ params.forEach(function(value, key) {
180
+ var mapping = QUERY_PARAMS[key];
181
+ if (!mapping) {
182
+ throw new Error(`Unknown URI parameter: ${key}`);
183
+ }
184
+
185
+ var parsed;
186
+ if (mapping.type === 'int') {
187
+ parsed = parseInt(value, 10);
188
+ if (isNaN(parsed)) {
189
+ throw new Error(`Invalid integer value for ${key}: ${value}`);
190
+ }
191
+ } else if (mapping.type === 'string_array') {
192
+ parsed = [value];
193
+ } else {
194
+ parsed = value;
195
+ }
196
+ setNested(options, mapping.path, parsed);
197
+ });
198
+ }
199
+
200
+ return { servers: servers, options: options };
201
+ }
202
+
203
+ exports.isHotrodURI = isHotrodURI;
204
+ exports.parseHotrodURI = parseHotrodURI;
205
+
206
+ }.call(this));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "infinispan",
3
- "version": "0.14.0",
3
+ "version": "0.16.0",
4
4
  "description": "Infinispan Javascript client",
5
5
  "main": "index",
6
6
  "typings": "./types",
@@ -9,7 +9,12 @@
9
9
  },
10
10
  "scripts": {
11
11
  "lint": "eslint --ignore-path .gitignore lib spec index.js",
12
- "test": "jasmine"
12
+ "test": "node scripts/docker-test.js",
13
+ "docker:up": "docker compose -p ispn-test up -d --wait && docker compose -p ispn-test --profile failover create server-failover-one server-failover-two server-failover-three",
14
+ "docker:down": "docker compose -p ispn-test --profile failover down --remove-orphans",
15
+ "ssl:generate": "node scripts/make-ssl.js",
16
+ "docs:api": "jsdoc lib/*.js",
17
+ "docs:user": "node scripts/gen-asciidoc.js"
13
18
  },
14
19
  "author": "Infinispan Community",
15
20
  "license": "Apache-2.0",
@@ -28,7 +33,6 @@
28
33
  },
29
34
  "dependencies": {
30
35
  "buffer-xor": "^2.0.2",
31
- "jsdoc": "^4.0.2",
32
36
  "log4js": "^6.4.6",
33
37
  "protobufjs": "^7.0.0",
34
38
  "underscore": "^1.13.3",
@@ -37,6 +41,7 @@
37
41
  "devDependencies": {
38
42
  "eslint": "^8.26.0",
39
43
  "jasmine": "^6.1.0",
44
+ "jsdoc": "^4.0.2",
40
45
  "long": "^5.2.3"
41
46
  }
42
47
  }
package/server/.keep ADDED
File without changes