infinispan 0.14.0 → 0.15.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.
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env bash
2
+
3
+ REGEX='^\[#[0-9]+\]\s[A-Z].*\n?(\n(\*\s.*\n)+)?$'
4
+ if ! grep -qE "$REGEX" "$1"; then
5
+ echo "Commit message format is incorrect. Run the following command:" >&2
6
+ echo " git config commit.template .gitmessage" >&2
7
+ echo "and retry" >&2
8
+ exit 1
9
+ fi
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env bash
2
+
3
+ BASEDIR=$(dirname "$0")/..
4
+ BASEDIR_RESOLVED=$(realpath "$BASEDIR")
5
+
6
+ git config get --local core.hooksPath || git config set --local core.hooksPath "$BASEDIR_RESOLVED"/.githooks
7
+ git config get --local commit.template || git config set --local commit.template "$BASEDIR_RESOLVED"/.gitmessage
@@ -0,0 +1,15 @@
1
+ @echo off
2
+
3
+ set "DIRNAME=%~dp0%"
4
+ pushd "%DIRNAME%.."
5
+ set "BASEDIR_RESOLVED=%CD%"
6
+ popd
7
+
8
+ git config get --local core.hooksPath
9
+ if ERRORLEVEL 1 (
10
+ git config set --local core.hooksPath "%BASEDIR_RESOLVED%/.githooks
11
+ )
12
+ git config get --local commit.template
13
+ if ERRORLEVEL 1 (
14
+ git config set --local commit.template "%BASEDIR_RESOLVED%/.gitmessage
15
+ )
package/.gitmessage ADDED
@@ -0,0 +1,7 @@
1
+ # [#nnnnn] Title, summary, imperative, start upper case, don't end with a period
2
+ # No more than 50 chars. #### 50 chars is here: #
3
+ # Remember blank line between title and body.
4
+
5
+ # Body: Explain *what* and *why* (not *how*)
6
+ # Wrap at 72 chars. ################################## which is here: #
7
+
package/AI-CODE.md ADDED
@@ -0,0 +1,86 @@
1
+ # JS Client Code Instructions
2
+
3
+ ## Tech Stack
4
+ * **Runtime:** Node.js 24 LTS
5
+ * **Language:** JavaScript (ES6+) with TypeScript definition files (`types/index.d.ts`)
6
+ * **Protocol:** Hot Rod binary protocol — versions 2.2, 2.5, 2.9, 3.0, 4.0, 4.1
7
+ * **Test framework:** Jasmine 6
8
+ * **Linting:** ESLint (ES2022, single quotes, semicolons required, JSDoc required)
9
+ * **Docs:** JSDoc for API docs, AsciiDoc for user documentation
10
+
11
+ ## Project Structure
12
+
13
+ ```
14
+ index.js # Entry point — re-exports lib/infinispan.js
15
+ lib/
16
+ infinispan.js # Main client API (connect, CRUD, listeners, queries, scripts)
17
+ io.js # Transport layer (TCP sockets, topology, failover, consistent hashing)
18
+ protocols.js # Hot Rod protocol encode/decode for all supported versions
19
+ codec.js # Binary codec (VInt, VLong, strings, Protobuf, JSON)
20
+ listeners.js # Remote/local event listener management
21
+ functional.js # Functional combinators (lift, actions, pipeline, partial application)
22
+ utils.js # Logging, MurmurHash3, ReplayableBuffer, address normalization
23
+ uri.js # Hot Rod URI parsing (hotrod:// and hotrods:// schemes)
24
+ sasl/ # SASL authentication mechanisms
25
+ factory.js # Mechanism registry and negotiation
26
+ plain.js # PLAIN
27
+ digest.js # DIGEST-MD5
28
+ scram.js # SCRAM-SHA-1/256/384/512
29
+ external.js # EXTERNAL (TLS cert)
30
+ oauthbearer.js # OAUTHBEARER
31
+ spec/ # Tests
32
+ *_spec.js # Test suites
33
+ utils/testing.js # Shared test utilities and assertion helpers
34
+ configs/ # Infinispan server XML configurations for test scenarios
35
+ types/ # TypeScript type definitions
36
+ documentation/ # AsciiDoc user documentation
37
+ scripts/ # Build and test tooling
38
+ ```
39
+
40
+ ## Build and Test Commands
41
+ * **Install dependencies:** `npm install`
42
+ * **Lint:** `npm run lint`
43
+ * **Run tests (with containers):** `npm run test:docker`
44
+ * **Run tests (containers already running):** `npm test`
45
+ * **Start test containers:** `npm run docker:up`
46
+ * **Stop test containers:** `npm run docker:down`
47
+ * **Run a single spec:** `npx jasmine spec/infinispan_local_spec.js`
48
+ * **Generate SSL certificates:** `npm run ssl:generate`
49
+ * **Generate API docs:** `npm run docs:api`
50
+ * **Override server version:** `INFINISPAN_VERSION=16.1.3 npm run test:docker`
51
+
52
+ ## Architecture Notes
53
+
54
+ * **Consistent hashing:** Keys are routed to owning servers using MurmurHash3. Topology updates from the server adjust the hash ring automatically.
55
+ * **Multiplexing:** Multiple in-flight requests share a single TCP connection per server, routed by message ID.
56
+ * **State threading in codec:** The codec layer uses a functional "lift" pattern where encode/decode functions return `{answer, state}` tuples for immutable state management through the pipeline.
57
+ * **Failover:** Automatic retry with round-robin fallback to other cluster members. Cross-site failover supported via `clusters` option and `switchToCluster()`.
58
+
59
+ ## Development Standards
60
+ * **Style:** Use `var` for variable declarations (not `const`/`let`) to match existing codebase.
61
+ * **Module pattern:** All modules wrap code in an IIFE: `(function() { ... }.call(this));`
62
+ * **JSDoc:** Required for all public functions. Use `@param`, `@returns`, `@since` tags.
63
+ * **Testing:** Tests use Promise chains with `spec/utils/testing.js` helpers. Follow the pattern:
64
+ ```javascript
65
+ var t = require('./utils/testing');
66
+ it('should do something', function(done) {
67
+ t.client(t.local, t.authOpts)
68
+ .then(t.assert(t.put('key', 'value')))
69
+ .then(t.assert(t.get('key'), t.toBe('value')))
70
+ .then(t.assert(t.disconnect()))
71
+ .then(function() { done(); }, t.failed(done));
72
+ });
73
+ ```
74
+ * **Commit logs:** Commit logs must always start with `[#nnnnn] Summary`.
75
+ * **Git branches:** Branches should be named `issueid/issue_summary` and use `origin/main` as the upstream.
76
+
77
+ ## Development Platform
78
+ * **Repository:** https://github.com/infinispan/js-client
79
+ * **Issues:** Use GitHub Issues with appropriate labels.
80
+ * **License:** Apache-2.0
81
+
82
+ ## Related Projects
83
+
84
+ * **Infinispan server:** The Infinispan server source code is in ../infinispan
85
+ * **Operator:** The Infinispan Operator source code is in ../infinispan-operator
86
+ * **Console:** The Infinispan Console source code is in ../infinispan-console
package/README.md CHANGED
@@ -1,13 +1,18 @@
1
1
  # Hot Rod JS Client
2
2
 
3
+ [![npm version](https://img.shields.io/npm/v/infinispan)](https://www.npmjs.com/package/infinispan)
4
+ [![License](https://img.shields.io/npm/l/infinispan)](https://github.com/infinispan/js-client/blob/main/LICENSE)
5
+ [![CI](https://github.com/infinispan/js-client/actions/workflows/ci.yml/badge.svg)](https://github.com/infinispan/js-client/actions/workflows/ci.yml)
6
+ [![Node.js](https://img.shields.io/node/v/infinispan)](https://www.npmjs.com/package/infinispan)
7
+ [![npm downloads](https://img.shields.io/npm/dm/infinispan)](https://www.npmjs.com/package/infinispan)
8
+
3
9
  `infinispan` is an asynchronous event-driven Infinispan client for Node.js.
4
10
  The results of the asynchronous operations are represented using
5
11
  [Promise](https://www.promisejs.org) instances. Amongst many advantages,
6
12
  promises make it easy to transform/chain multiple asynchronous invocations
7
13
  and they improve error handling by making it easy to centralise it.
8
14
 
9
- The client is under heavy development but here's a summary of its
10
- current capabilities:
15
+ Here's a summary of its current capabilities:
11
16
 
12
17
  * `infinispan` client can be constructed with a single server address or
13
18
  multiple servers addresses. When passing multiple addresses, it will iterate
@@ -54,100 +59,91 @@ The client is normally connected to one of the sites, but if its members fail to
54
59
 
55
60
  Find installation, configuration, and example usage in the Hot Rod JS Client Guide at [infinispan.org/documentation](https://infinispan.org/documentation/).
56
61
 
57
- You can also build the Hot Rod JS Client Guide as follows:
58
-
59
- 1. Clone the source repository.
60
- ```bash
61
- $ git clone git@github.com:infinispan/js-client.git
62
- ```
62
+ You can also build the Hot Rod JS Client Guide locally:
63
63
 
64
- 2. Build the HTML from the asciidoc source.
65
64
  ```bash
66
- $ asciidoctor documentation/asciidoc/titles/js_client.asciidoc
65
+ npm run docs:user
67
66
  ```
68
67
 
69
- 3. Open `documentation/asciidoc/titles/js_client.html` in any browser.
68
+ Open `out/docs/index.html` in any browser.
70
69
 
71
70
  # API docs
72
71
 
73
72
  Review [Hot Rod JS client API documentation](http://docs.jboss.org/infinispan/hotrod-clients/javascript/1.0/apidocs/module-infinispan.html).
74
73
 
75
- You can also build API docs from the source repository as follows:
74
+ To generate API docs locally:
76
75
 
77
- 1. Generate JSDoc formatted API docs.
78
76
  ```bash
79
- $ npm install jsdoc
80
- $ ./node_modules/.bin/jsdoc lib/*.js
77
+ npm run docs:api
81
78
  ```
82
79
 
83
- 2. Open `open out/index.html` in any browser.
80
+ Open `out/index.html` in any browser.
84
81
 
85
82
  # Testing
86
83
 
87
- Before executing any tests, Infinispan Server instances need to be started
88
- up so that testsuite can run against those. To ease this process, a script
89
- has been created in the root directory to start all the expected server
90
- instances.
84
+ Tests run against Infinispan Server instances in Docker containers.
91
85
 
92
- Go to the root of the repo and execute:
86
+ ## Prerequisites
93
87
 
94
- ```bash
95
- $ npm install
96
- ```
88
+ - Docker and Docker Compose
89
+ - Java (for SSL certificate generation via `keytool`)
90
+ - Node.js 24+
97
91
 
98
- Next, start the Infinispan Servers via:
92
+ ## Running tests
99
93
 
100
94
  ```bash
101
- $ ./run-servers.sh
95
+ npm install
96
+ npm run test:docker
102
97
  ```
103
98
 
104
- To run the testsuite once execute:
99
+ This starts all required containers, generates SSL certificates if needed,
100
+ waits for the cluster to form, runs the full test suite, and tears down
101
+ the containers on exit.
105
102
 
106
- ```bash
107
- $ ./run-testsuite.sh
108
- ```
109
-
110
- To run individual tests execute:
103
+ To test against a specific Infinispan version:
111
104
 
112
105
  ```bash
113
- $ npx jasmine spec/infinispan_local_spec.js
106
+ INFINISPAN_VERSION=16.1.3 npm run test:docker
114
107
  ```
115
108
 
116
- To help with testing, you can quickly run the smoke tests via:
117
-
118
- ```bash
119
- $ ./smoke-tests.sh
120
- ```
109
+ ### Manual container lifecycle
121
110
 
122
- Both testsuite and smoke tests can be run with older protocol versions, e.g.
111
+ For iterative development, start containers once and run tests repeatedly:
123
112
 
124
113
  ```bash
125
- $ protocol=2.5 ./smoke-tests.sh
114
+ npm run docker:up
115
+ npm test
116
+ # ... make changes ...
117
+ npm test
118
+ npm run docker:down
126
119
  ```
127
120
 
128
- ## Note for Mac Users:
129
- You might experience MPING issues running an Infinispan cluster.
121
+ ### Individual tests
122
+
123
+ With containers running:
130
124
 
131
125
  ```bash
132
- 13:37:15,561 ERROR (jgroups-5,server-two) [org.jgroups.protocols.MPING]
126
+ npx jasmine spec/infinispan_local_spec.js
133
127
  ```
134
128
 
135
- If you run into the errors above, add the following to the routes of your host
129
+ ### SSL certificates
130
+
131
+ Certificates are generated automatically on first test run. To regenerate:
136
132
 
137
133
  ```bash
138
- sudo route add -net 224.0.0.0/5 127.0.0.1
139
- sudo route add -net 232.0.0.0/5 192.168.1.3
134
+ npm run ssl:generate
140
135
  ```
141
136
 
142
- # Manual stress tests
137
+ ## Manual stress tests
143
138
 
144
- The testsuite now contains manual stress tests that take several minutes to run.
139
+ The testsuite contains manual stress tests that take several minutes to run.
145
140
  To run these tests, execute:
146
141
 
147
- $ npx jasmine spec-manual/*_spec.js
148
-
142
+ ```bash
143
+ npx jasmine spec-manual/*_spec.js
144
+ ```
149
145
 
150
- # Memory profiling
146
+ ## Memory profiling
151
147
 
152
148
  The source code comes with some programs that allow the client's memory consumption to be profiled.
153
149
  Those programs rely on having access to the global garbage collector.
@@ -158,38 +154,20 @@ Example:
158
154
  node --expose-gc memory-profiling/infinispan_memory_many_get.js
159
155
  ```
160
156
 
161
- So of programs might only report the memory usage before/after.
157
+ Some programs might only report the memory usage before/after.
162
158
  Others might generate heap dumps which can be visualized using Google Chrome.
163
159
  Within Chrome, the Developer Tools UI contains a `Memory` tab where heap dumps can be loaded.
164
160
 
165
-
166
- # Debugging
161
+ ## Debugging
167
162
 
168
163
  To debug tests with IDE:
169
164
 
170
- node --inspect-brk node_modules/.bin/jasmine spec/codec_spec.js
171
-
172
- Or:
173
-
174
- node --inspect-brk node_modules/.bin/jasmine spec/infinispan_local_spec.js
165
+ ```bash
166
+ node --inspect-brk node_modules/.bin/jasmine spec/codec_spec.js
167
+ ```
175
168
 
176
169
  And then start a remote Node.js debugger from IDE on port 9229.
177
170
 
178
- # Tests, servers and ports
179
-
180
- Here's some more detailed information on which tests interact with which servers and on which ports.
181
- On top of that, you can find information on which tests are always running as opposed to those that are started (and stopped) by the tests themselves.
182
-
183
- | Test | Server Profile | Ports (Auto/Manual) |
184
- | :------------ | :-------------: | :-------------------------------------- |
185
- | local spec | local | `11222` (A) |
186
- | expiry spec | local | `11222` (A) |
187
- | cluster spec | clustered | `11322` (A), `11332` (A), `11342` (A) |
188
- | failover spec | clustered | `11422` (M), `11432` (M), `11442` (M) |
189
- | ssl spec | local | `11232` (A), `12242` (A), `12252` (A) |
190
- | xsite spec | earth, moon | `11522` (earth, M), `11532` (moon, M) |
191
-
192
171
  # Reporting an issue
193
172
 
194
- This project does not use Github issues.
195
- Instead, please report them via JIRA (project [HRJS](https://issues.jboss.org/projects/HRJS/summary)).
173
+ Report issues via [GitHub Issues](https://github.com/infinispan/js-client/issues).
package/lib/codec.js CHANGED
@@ -821,11 +821,48 @@
821
821
  protobuf.loadSync(path.join(`${__dirname}/protostream/message-wrapping.proto`),root); //loaded the wrappedMessage.proto to the root
822
822
  var QueryRequest = root.lookupType('org.infinispan.query.remote.client.QueryRequest');
823
823
  var QueryResponse = root.lookupType('org.infinispan.query.remote.client.QueryResponse');
824
+ var ContinuousQueryResult = root.lookupType('org.infinispan.query.remote.client.ContinuousQueryResult');
824
825
 
825
826
  return {
826
827
  QueryRequest,
827
- QueryResponse
828
+ QueryResponse,
829
+ ContinuousQueryResult
828
830
  };
829
831
  }());
830
832
 
833
+ var CQ_RESULT_TYPES = ['leaving', 'joining', 'updated'];
834
+
835
+ /**
836
+ * Wrap a scalar value as a WrappedMessage byte array.
837
+ * @param {string|number|boolean} value - The value to wrap.
838
+ * @returns {Buffer} The encoded WrappedMessage bytes.
839
+ */
840
+ exports.wrapScalar = function(value) {
841
+ return WrappedMessage.encode(createWrappedMessage(value, _.identity)).finish();
842
+ };
843
+
844
+ /**
845
+ * Decode a ContinuousQueryResult from raw protobuf bytes.
846
+ * @param {Buffer} bytes - The raw ContinuousQueryResult bytes.
847
+ * @returns {Object} Decoded result with resultType, key, value, projection.
848
+ */
849
+ exports.decodeContinuousQueryResult = function(bytes) {
850
+ var msg = Query.ContinuousQueryResult.decode(bytes);
851
+ return {
852
+ resultType: CQ_RESULT_TYPES[msg.resultType] || 'leaving',
853
+ key: msg.key,
854
+ value: msg.value,
855
+ projection: msg.projection
856
+ };
857
+ };
858
+
859
+ /**
860
+ * Decode a WrappedMessage from raw bytes.
861
+ * @param {Buffer} bytes - The raw WrappedMessage bytes.
862
+ * @returns {Object} The decoded WrappedMessage object.
863
+ */
864
+ exports.decodeWrappedMessage = function(bytes) {
865
+ return WrappedMessage.decode(bytes);
866
+ };
867
+
831
868
  }.call(this));
package/lib/functional.js CHANGED
@@ -193,6 +193,31 @@
193
193
  return _.extend.apply(null, construct({}, arguments));
194
194
  };
195
195
 
196
+ /**
197
+ * Deep merges multiple objects, with later arguments taking precedence.
198
+ * @returns {Object} A new merged object.
199
+ */
200
+ exports.deepMerge = function(/*args*/) {
201
+ var sources = _.toArray(arguments);
202
+ var result = {};
203
+ for (var i = 0; i < sources.length; i++) {
204
+ var src = sources[i];
205
+ if (!existy(src)) continue;
206
+ var keys = _.keys(src);
207
+ for (var k = 0; k < keys.length; k++) {
208
+ var key = keys[k];
209
+ var val = src[key];
210
+ if (!existy(val)) continue;
211
+ if (_.isObject(val) && !_.isArray(val) && _.isObject(result[key]) && !_.isArray(result[key])) {
212
+ result[key] = exports.deepMerge(result[key], val);
213
+ } else {
214
+ result[key] = val;
215
+ }
216
+ }
217
+ }
218
+ return result;
219
+ };
220
+
196
221
  exports.dispatch = function(/* funs */) {
197
222
  var funs = _.toArray(arguments);
198
223
  var size = funs.length;
package/lib/infinispan.js CHANGED
@@ -13,6 +13,7 @@
13
13
  var f = require('./functional');
14
14
  var codec = require('./codec');
15
15
  var u = require('./utils');
16
+ var uri = require('./uri');
16
17
  var protocols = require('./protocols');
17
18
  var io = require('./io');
18
19
  var listeners = require('./listeners');
@@ -824,6 +825,58 @@
824
825
  return false;
825
826
  });
826
827
  },
828
+ /**
829
+ * Continuous query options.
830
+ *
831
+ * @typedef {Object} ContinuousQueryOptions
832
+ * @property {Object} [params] - Named parameter bindings for the Ickle query.
833
+ * @since 0.16
834
+ */
835
+ /**
836
+ * Register a continuous query that watches for cache changes
837
+ * matching the given Ickle query.
838
+ *
839
+ * @param {String} queryString Ickle query string.
840
+ * @param {ContinuousQueryOptions=} opts Optional CQ options.
841
+ * @returns {Promise<Object>}
842
+ * A promise completed with a ContinuousQuery handle.
843
+ * Use cq.on('joining', fn), cq.on('leaving', fn), cq.on('updated', fn)
844
+ * to receive events.
845
+ * @memberof Client#
846
+ * @since 0.16
847
+ */
848
+ addContinuousQuery: function(queryString, opts) {
849
+ var ctx = transport.context(SMALL);
850
+ logger.debugf('Invoke addContinuousQuery(msgId=%d,query=%s)', ctx.id, queryString);
851
+ return listen.addContinuousQueryListener(transport, ctx, queryString, opts);
852
+ },
853
+ /**
854
+ * Remove a continuous query.
855
+ *
856
+ * @param {Object} cq ContinuousQuery handle returned by addContinuousQuery.
857
+ * @returns {Promise}
858
+ * A promise completed when the continuous query has been removed.
859
+ * @memberof Client#
860
+ * @since 0.16
861
+ */
862
+ removeContinuousQuery: function(cq) {
863
+ var listenerId = cq.getListenerId();
864
+ var ctx = transport.context(SMALL);
865
+ logger.debugf('Invoke removeContinuousQuery(msgId=%d,listenerId=%s)', ctx.id, listenerId);
866
+ var conn = listen.findConnectionListener(listenerId);
867
+ if (!f.existy(conn))
868
+ return Promise.reject(
869
+ new Error(`No server connection for CQ listener (listenerId=${ listenerId })`));
870
+
871
+ var remote = futurePinned(ctx, 0x27, p.encodeListenerId(listenerId), p.complete(p.hasSuccess), conn);
872
+ return remote.then(function (success) {
873
+ if (success) {
874
+ listen.removeListeners(listenerId);
875
+ return true;
876
+ }
877
+ return false;
878
+ });
879
+ },
827
880
  /**
828
881
  * Add script to server(s).
829
882
  *
@@ -1294,8 +1347,24 @@
1294
1347
  */
1295
1348
  /**
1296
1349
  * Infinispan client constructor taking an optional initial address,
1297
- * or multiple addresses, to which the client will try to connect to,
1298
- * as well as optional configuration settings.
1350
+ * multiple addresses, or a Hot Rod URI string to which the client
1351
+ * will try to connect, as well as optional configuration settings.
1352
+ *
1353
+ * @example
1354
+ * // Connect with a Hot Rod URI
1355
+ * client('hotrod://admin:password@localhost:11222')
1356
+ *
1357
+ * @example
1358
+ * // URI with TLS and query parameters
1359
+ * client('hotrods://admin:password@localhost:11222?trust_ca=/ca.pem')
1360
+ *
1361
+ * @example
1362
+ * // URI with programmatic overrides
1363
+ * client('hotrod://admin:password@localhost:11222', {authentication: {saslMechanism: 'SCRAM-SHA-256'}})
1364
+ *
1365
+ * @example
1366
+ * // URI with multiple servers
1367
+ * client('hotrod://admin:password@node1:11222,node2:11322')
1299
1368
  *
1300
1369
  * @example
1301
1370
  * client({port: 11222, host: 'localhost'})
@@ -1310,18 +1379,29 @@
1310
1379
  * client([{port: 11522, host: 'myhost'}, {port: 11622, host: 'myhost'}],
1311
1380
  * {version: '2.2', cacheName: 'myCache'})
1312
1381
  *
1313
- * @param {(ServerAddress|ServerAddress[])} args
1314
- * Optional single or multiple addresses to which to connect. If none
1315
- * provided, the client will connect to localhost:11222 address by default.
1382
+ * @param {(String|ServerAddress|ServerAddress[])} args
1383
+ * A Hot Rod URI string (hotrod:// or hotrods://), a single server address,
1384
+ * or an array of server addresses. If none provided, the client connects
1385
+ * to localhost:11222 by default.
1316
1386
  * @param {ClientOptions=} options
1317
- * Optional configuration settings.
1387
+ * Optional configuration settings. When a URI is provided, these settings
1388
+ * override URI values.
1318
1389
  * @constructs Client
1319
1390
  * @returns {Promise<ReturnType<Client>>} A promise that resolves to a connected client.
1320
1391
  * @since 0.3
1321
1392
  */
1322
1393
  exports.client = function client(args, options) {
1323
- var merged = f.merge(Client.config, options);
1324
- var c = new Client(u.normalizeAddresses(args), merged);
1394
+ var addrs, uriOpts;
1395
+ if (uri.isHotrodURI(args)) {
1396
+ var parsed = uri.parseHotrodURI(args);
1397
+ addrs = parsed.servers;
1398
+ uriOpts = parsed.options;
1399
+ } else {
1400
+ addrs = u.normalizeAddresses(args);
1401
+ uriOpts = {};
1402
+ }
1403
+ var merged = f.deepMerge(Client.config, uriOpts, options || {});
1404
+ var c = new Client(addrs, merged);
1325
1405
 
1326
1406
  return c.connect();
1327
1407
  };
@@ -1389,16 +1469,7 @@
1389
1469
  enabled: false,
1390
1470
  secureProtocol: 'TLS_client_method',
1391
1471
  trustCerts: [],
1392
- clientAuth: {
1393
- key: undefined,
1394
- passphrase: undefined,
1395
- cert: undefined
1396
- },
1397
- sniHostName: undefined,
1398
- cryptoStore: {
1399
- path: undefined,
1400
- passphrase: undefined
1401
- }
1472
+ sniHostName: undefined
1402
1473
  },
1403
1474
  dataFormat : {
1404
1475
  keyType: 'text/plain',
package/lib/io.js CHANGED
@@ -1116,6 +1116,9 @@
1116
1116
  f.actions(p.stepsHeaderBody(ctx, 0x23, p.sasl(transport.authOpts(), holder), undefined), codec.bytesEncoded)(ctx);
1117
1117
  var result = transport.writeCommandPinned(ctx, p.decodeSasl, conn);
1118
1118
  return result.then(function (r) {
1119
+ if (r.complete) {
1120
+ return r;
1121
+ }
1119
1122
  ctx = u.context(16);
1120
1123
  ctx.topologyId = topologyId;
1121
1124
  holder.challenge = r.response;
@@ -1123,7 +1126,6 @@
1123
1126
  return transport.writeCommandPinned(ctx, p.decodeSasl, conn).then(function (r) {
1124
1127
  return r;
1125
1128
  });
1126
- return r;
1127
1129
  });
1128
1130
  }
1129
1131