neo4j-driver 1.1.1 → 1.3.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 (39) hide show
  1. package/README.md +97 -35
  2. package/gulpfile.babel.js +15 -52
  3. package/lib/browser/neo4j-web.js +3882 -1919
  4. package/lib/browser/neo4j-web.min.js +16 -15
  5. package/lib/v1/driver.js +93 -93
  6. package/lib/v1/error.js +9 -0
  7. package/lib/v1/graph-types.js +12 -12
  8. package/lib/v1/index.js +53 -31
  9. package/lib/v1/internal/ch-config.js +87 -0
  10. package/lib/v1/internal/ch-dummy.js +6 -1
  11. package/lib/v1/internal/ch-node.js +50 -44
  12. package/lib/v1/internal/ch-websocket.js +9 -10
  13. package/lib/v1/internal/connection-holder.js +204 -0
  14. package/lib/v1/internal/connection-providers.js +378 -0
  15. package/lib/v1/internal/connector.js +177 -55
  16. package/lib/v1/internal/features.js +11 -0
  17. package/lib/v1/internal/get-servers-util.js +10 -10
  18. package/lib/v1/internal/host-name-resolvers.js +131 -0
  19. package/lib/v1/internal/rediscovery.js +49 -38
  20. package/lib/v1/internal/round-robin-array.js +9 -0
  21. package/lib/v1/internal/routing-table.js +49 -35
  22. package/lib/v1/internal/routing-util.js +168 -0
  23. package/lib/v1/internal/server-version.js +123 -0
  24. package/lib/v1/internal/stream-observer.js +4 -2
  25. package/lib/v1/internal/transaction-executor.js +204 -0
  26. package/lib/v1/internal/util.js +66 -6
  27. package/lib/v1/record.js +2 -2
  28. package/lib/v1/result-summary.js +1 -1
  29. package/lib/v1/result.js +53 -31
  30. package/lib/v1/routing-driver.js +49 -152
  31. package/lib/v1/session.js +196 -74
  32. package/lib/v1/transaction.js +147 -75
  33. package/lib/version.js +1 -1
  34. package/package.json +1 -1
  35. package/.gitmodules +0 -3
  36. package/neokit/README.md +0 -89
  37. package/neokit/neoctl.py +0 -131
  38. package/neokit/neoget.py +0 -185
  39. package/neokit/neorun.py +0 -180
package/README.md CHANGED
@@ -63,39 +63,45 @@ driver.close();
63
63
 
64
64
  ## Usage examples
65
65
 
66
+ Driver creation:
66
67
  ```javascript
67
-
68
68
  // Create a driver instance, for the user neo4j with password neo4j.
69
69
  // It should be enough to have a single driver per database per application.
70
70
  var driver = neo4j.driver("bolt://localhost", neo4j.auth.basic("neo4j", "neo4j"));
71
71
 
72
72
  // Register a callback to know if driver creation was successful:
73
- driver.onCompleted = function() {
73
+ driver.onCompleted = function () {
74
74
  // proceed with using the driver, it was successfully instantiated
75
75
  };
76
76
 
77
77
  // Register a callback to know if driver creation failed.
78
78
  // This could happen due to wrong credentials or database unavailability:
79
- driver.onError = function(error) {
79
+ driver.onError = function (error) {
80
80
  console.log('Driver instantiation failed', error);
81
81
  };
82
82
 
83
+ // Close the driver when application exits.
84
+ // This closes all used network connections.
85
+ driver.close();
86
+ ```
87
+
88
+ Session API:
89
+ ```javascript
83
90
  // Create a session to run Cypher statements in.
84
91
  // Note: Always make sure to close sessions when you are done using them!
85
92
  var session = driver.session();
86
93
 
87
94
  // Run a Cypher statement, reading the result in a streaming manner as records arrive:
88
95
  session
89
- .run("MERGE (alice:Person {name : {nameParam} }) RETURN alice.name", { nameParam:'Alice' })
96
+ .run('MERGE (alice:Person {name : {nameParam} }) RETURN alice.name AS name', {nameParam: 'Alice'})
90
97
  .subscribe({
91
- onNext: function(record) {
92
- console.log(record._fields);
98
+ onNext: function (record) {
99
+ console.log(record.get('name'));
93
100
  },
94
- onCompleted: function() {
95
- // Completed!
101
+ onCompleted: function () {
96
102
  session.close();
97
103
  },
98
- onError: function(error) {
104
+ onError: function (error) {
99
105
  console.log(error);
100
106
  }
101
107
  });
@@ -103,55 +109,102 @@ session
103
109
  // or
104
110
  // the Promise way, where the complete result is collected before we act on it:
105
111
  session
106
- .run("MERGE (james:Person {name : {nameParam} }) RETURN james.name", { nameParam:'James' })
107
- .then(function(result){
108
- result.records.forEach(function(record) {
109
- console.log(record._fields);
112
+ .run('MERGE (james:Person {name : {nameParam} }) RETURN james.name AS name', {nameParam: 'James'})
113
+ .then(function (result) {
114
+ result.records.forEach(function (record) {
115
+ console.log(record.get('name'));
110
116
  });
111
- // Completed!
112
117
  session.close();
113
118
  })
114
- .catch(function(error) {
119
+ .catch(function (error) {
115
120
  console.log(error);
116
121
  });
122
+ ```
123
+
124
+ Transaction functions API:
125
+ ```javascript
126
+ // Transaction functions provide a convenient API with minimal boilerplate and
127
+ // retries on network fluctuations and transient errors. Maximum retry time is
128
+ // configured on the driver level and is 30 seconds by default:
129
+ neo4j.driver("bolt://localhost", neo4j.auth.basic("neo4j", "neo4j"), {maxTransactionRetryTime: 30000});
130
+
131
+ // It is possible to execute read transactions that will benefit from automatic
132
+ // retries on both single instance ('bolt' URI scheme) and Causal Cluster
133
+ // ('bolt+routing' URI scheme) and will get automatic load balancing in cluster deployments
134
+ var readTxResultPromise = session.readTransaction(function (transaction) {
135
+ // used transaction will be committed automatically, no need for explicit commit/rollback
136
+
137
+ var result = transaction.run('MATCH (person:Person) RETURN person.name AS name');
138
+ // at this point it is possible to either return the result or process it and return the
139
+ // result of processing it is also possible to run more statements in the same transaction
140
+ return result;
141
+ });
142
+
143
+ // returned Promise can be later consumed like this:
144
+ readTxResultPromise.then(function (result) {
145
+ session.close();
146
+ console.log(result.records);
147
+ }).catch(function (error) {
148
+ console.log(error);
149
+ });
150
+
151
+ // It is possible to execute write transactions that will benefit from automatic retries
152
+ // on both single instance ('bolt' URI scheme) and Causal Cluster ('bolt+routing' URI scheme)
153
+ var writeTxResultPromise = session.writeTransaction(function (transaction) {
154
+ // used transaction will be committed automatically, no need for explicit commit/rollback
155
+
156
+ var result = transaction.run('MERGE (alice:Person {name : \'Alice\' }) RETURN alice.name AS name');
157
+ // at this point it is possible to either return the result or process it and return the
158
+ // result of processing it is also possible to run more statements in the same transaction
159
+ return result.records.map(function (record) {
160
+ return record.get('name');
161
+ });
162
+ });
163
+
164
+ // returned Promise can be later consumed like this:
165
+ writeTxResultPromise.then(function (namesArray) {
166
+ session.close();
167
+ console.log(namesArray);
168
+ }).catch(function (error) {
169
+ console.log(error);
170
+ });
171
+ ```
117
172
 
118
- //run statement in a transaction
173
+ Explicit transactions API:
174
+ ```javascript
175
+ // run statement in a transaction
119
176
  var tx = session.beginTransaction();
120
- tx.run("MERGE (bob:Person {name : {nameParam} }) RETURN bob.name", { nameParam:'Bob' })
177
+ tx.run("MERGE (bob:Person {name : {nameParam} }) RETURN bob.name AS name", {nameParam: 'Bob'})
121
178
  .subscribe({
122
- onNext: function(record) {
123
- console.log(record._fields);
124
- },
125
- onCompleted: function() {
126
- // Completed!
179
+ onNext: function (record) {
180
+ console.log(record.get('name'));
181
+ },
182
+ onCompleted: function () {
127
183
  session.close();
128
184
  },
129
- onError: function(error) {
185
+ onError: function (error) {
130
186
  console.log(error);
131
187
  }
132
188
  });
133
-
189
+
134
190
  //decide if the transaction should be committed or rolled back
135
191
  var success = false;
136
192
 
137
193
  if (success) {
138
194
  tx.commit()
139
195
  .subscribe({
140
- onCompleted: function() {
141
- // Completed!
196
+ onCompleted: function () {
197
+ // this transaction is now committed
142
198
  },
143
- onError: function(error) {
199
+ onError: function (error) {
144
200
  console.log(error);
145
- }
146
- });
147
- } else {
201
+ }
202
+ });
203
+ } else {
148
204
  //transaction is rolled black and nothing is created in the database
149
205
  console.log('rolled back');
150
206
  tx.rollback();
151
207
  }
152
-
153
- // Close the driver when application exits
154
- driver.close();
155
208
  ```
156
209
 
157
210
  Subscriber API allows following combinations of `onNext`, `onCompleted` and `onError` callback invocations:
@@ -171,10 +224,19 @@ See files under `examples/` on how to use.
171
224
 
172
225
  ## Testing
173
226
 
227
+ Tests **require** latest [Boltkit](https://github.com/neo4j-contrib/boltkit) to be installed in the system. It is needed to start, stop and configure local test database. Boltkit can be installed with the following command:
228
+
229
+ pip install --upgrade boltkit
230
+
231
+ To run tests against "default" Neo4j version:
232
+
174
233
  ./runTests.sh
234
+
235
+ To run tests against specified Neo4j version:
236
+
237
+ ./runTests.sh '-e 3.1.3'
175
238
 
176
- This runs the test suite against a fresh download of Neo4j.
177
- Or `npm test` if you already have a running version of a compatible Neo4j server.
239
+ Simple `npm test` can also be used if you already have a running version of a compatible Neo4j server.
178
240
 
179
241
  For development, you can have the build tool rerun the tests each time you change
180
242
  the source code:
package/gulpfile.babel.js CHANGED
@@ -22,7 +22,6 @@ var source = require('vinyl-source-stream');
22
22
  var buffer = require('vinyl-buffer');
23
23
  var gulp = require('gulp');
24
24
  var through = require('through2');
25
- var gulpif = require('gulp-if');
26
25
  var uglify = require('gulp-uglify');
27
26
  var concat = require('gulp-concat');
28
27
  var gutil = require('gulp-util');
@@ -40,7 +39,6 @@ var decompress = require('gulp-decompress');
40
39
  var fs = require("fs-extra");
41
40
  var runSequence = require('run-sequence');
42
41
  var path = require('path');
43
- var childProcess = require("child_process");
44
42
  var minimist = require('minimist');
45
43
  var cucumber = require('gulp-cucumber');
46
44
  var merge = require('merge-stream');
@@ -48,6 +46,7 @@ var install = require("gulp-install");
48
46
  var os = require('os');
49
47
  var file = require('gulp-file');
50
48
  var semver = require('semver');
49
+ var sharedNeo4j = require('./test/internal/shared-neo4j').default;
51
50
 
52
51
  gulp.task('default', ["test"]);
53
52
 
@@ -56,8 +55,7 @@ gulp.task('browser', function(cb){
56
55
  });
57
56
 
58
57
  /** Build all-in-one files for use in the browser */
59
- gulp.task('bu' +
60
- 'ild-browser', function () {
58
+ gulp.task('build-browser', function () {
61
59
  var browserOutput = 'lib/browser';
62
60
  // Our app bundler
63
61
  var appBundler = browserify({
@@ -164,23 +162,17 @@ gulp.task('test', function(cb){
164
162
 
165
163
  gulp.task('test-nodejs', ['install-driver-into-sandbox'], function () {
166
164
  return gulp.src('test/**/*.test.js')
167
- .pipe(jasmine({
168
- // reporter: new reporters.JUnitXmlReporter({
169
- // savePath: "build/nodejs-test-reports",
170
- // consolidateAll: false
171
- // }),
172
- includeStackTrace: true
173
- }));
165
+ .pipe(jasmine({
166
+ includeStackTrace: true,
167
+ verbose: true
168
+ }));
174
169
  });
175
170
 
176
171
  gulp.task('test-boltkit', ['nodejs'], function () {
177
172
  return gulp.src('test/**/*.boltkit.it.js')
178
173
  .pipe(jasmine({
179
- // reporter: new reporters.JUnitXmlReporter({
180
- // savePath: "build/nodejs-test-reports",
181
- // consolidateAll: false
182
- // }),
183
- includeStackTrace: true
174
+ includeStackTrace: true,
175
+ verbose: true
184
176
  }));
185
177
  });
186
178
 
@@ -239,43 +231,14 @@ gulp.task('set', function() {
239
231
  });
240
232
 
241
233
 
242
- var neo4jHome = path.resolve('./build/neo4j');
243
- var neorunPath = path.resolve('./neokit/neorun.py');
244
- var neorunStartArgsName = "--neorun.start.args"; // use this args to provide additional args for running neorun.start
245
-
246
- gulp.task('start-neo4j', function() {
247
-
248
- var neorunStartArgs = '-p neo4j'; // default args to neorun.start: change the default password to neo4j
249
- process.argv.slice(2).forEach(function (val) {
250
- if(val.startsWith(neorunStartArgsName))
251
- {
252
- neorunStartArgs = val.split("=")[1];
253
- }
254
- });
234
+ var neo4jHome = path.resolve('./build/neo4j');
255
235
 
256
- neorunStartArgs = neorunStartArgs.match(/\S+/g) || '';
257
-
258
- return runScript([
259
- neorunPath, '--start=' + neo4jHome
260
- ].concat( neorunStartArgs ) );
236
+ gulp.task('start-neo4j', function (done) {
237
+ sharedNeo4j.start(neo4jHome, process.env.NEOCTRL_ARGS);
238
+ done();
261
239
  });
262
240
 
263
- gulp.task('stop-neo4j', function() {
264
- return runScript([
265
- neorunPath, '--stop=' + neo4jHome
266
- ]);
241
+ gulp.task('stop-neo4j', function (done) {
242
+ sharedNeo4j.stop(neo4jHome);
243
+ done();
267
244
  });
268
-
269
- var runScript = function(cmd) {
270
- var spawnSync = childProcess.spawnSync, child, code;
271
- child = spawnSync('python', cmd);
272
- console.log("Script Outputs:\n" + child.stdout.toString());
273
- var error = child.stderr.toString();
274
- if (error.trim() !== "")
275
- console.log("Script Errors:\n"+ error);
276
- code = child.status;
277
- if( code !==0 )
278
- {
279
- throw "Script finished with code " + code
280
- }
281
- };