<commit_before>gremlin-client
==============

A proof of concept WebSocket JavaScript client for TinkerPop3 Gremlin Server.

Tested with Node.js v0.10.29 and v0.11.13.
Tested with Chrome 35, Firefox 28, Safari 7.

## Installation

Gremlin Client is an AMD/CommonJS module that works in both Node.js and WebSocket enabled browsers.

```
npm install gremlin-client --save
```

In the browser, you can require the module with browserify or directly insert a `<script>` tag, which will expose a global `gremlin` variable:
```html
<script type="text/javascript" src="gremlin.js"></script>
```

## Usage

### Set-up client

```javascript
// Will open a WebSocket to ws://localhost:8182 by default
var client = gremlin.createClient();
```
same as:
```javascript
var client = gremlin.createClient(8182, 'localhost');
```

If you want to use Gremlin-Server sessions, you can set the `session` argument as true in the `options` object:
```javascript
var client = gremlin.createClient(8182, 'localhost', { session: true });
```

The client supports two modes: streaming results, or traditional callback mode.

### Stream mode: client.stream(script)

Return a Node.js stream which emits a `data` event with the raw data returned by Gremlin Server every time it receives a message. The stream simultaneously also emits a higher level `result` event.

The stream emits an `end` event when receiving the last, `type: 0` message.

```javascript
var query = client.stream('g.V()');

query.on('result', function(result) {
  console.log(result);
});

// Alternatively:
// query.on('data', function(message) {
//   console.log(message.result);
// });

query.on('end', function(msg) {
  console.log("All results fetched", msg);
});

```

### Callback mode: client.execute(script, callback)

Will execute the provided callback when all results are actually returned from the server. Until it receives the final `type: 0` message, the client will internally concatenate all partial results returned over different messages.

### Using Gremlin-JavaScript syntax with Nashorn

Providing your configured `nashorn` script engine in your `gremlin-server.yaml` file, you can send and execute Gremlin-JavaScript formatted queries:

```yaml
scriptEngines: {
  gremlin-groovy: {
    imports: [java.lang.Math, org.apache.commons.math3.util.FastMath],
    staticImports: [java.lang.Math.PI],
    scripts: [scripts/generate-classic.groovy]},
  nashorn: {
      imports: [java.lang.Math, org.apache.commons.math3.util.FastMath],
      staticImports: [java.lang.Math.PI]}}
```

Then, in your Node.js/Browser environment:

```javascript
var client = gremlin.createClient({ language: 'nashorn' });

// Wrap a script definition in a JavaScript function
var script = function() {
  // Retrieve all vertices ordered by name
  g.V().order(function(a, b) {
    return a.get().value('name').localeCompare(b.get().value('name')); // JavaScript replacement for <=> spaceship operator
  });
};

// Send that script function body to Gremlin Server for execution in Nashorn engine
client.execute(script, function(err, response) {
  // Handle response.results
});
```

The client gets a string representation of the function passed to `client.stream()` or `client.query()` by calling the `.toString()` method.

### Bound parameters

The following example shows how to send a Gremlin-Javascript formatted script to Gremlin Server with bound parameters using the stream API:

```javascript
var s = client.stream(function() { g.v(id); }, { id: 1 });

s.on('data', function(result) {
  // handle result
});
```

## Running the Examples

This section assumes that you configured `resultIterationBatchSize: 1` in your Gremlin Server .yaml config file and loaded the default TinkerPop graph with `scripts: [scripts/generate-classic.groovy]`


To run the command line example:
```<commit_msg>Update doc to reflect latest changes on low level messages<commit_after>gremlin-client
==============

A proof of concept WebSocket JavaScript client for TinkerPop3 Gremlin Server.

Tested with Node.js v0.10.29 and v0.11.13.
Tested with Chrome 35, Firefox 28, Safari 7.

## Installation

Gremlin Client is an AMD/CommonJS module that works in both Node.js and WebSocket enabled browsers.

```
npm install gremlin-client --save
```

In the browser, you can require the module with browserify or directly insert a `<script>` tag, which will expose a global `gremlin` variable:
```html
<script type="text/javascript" src="gremlin.js"></script>
```

## Usage

### Creating a new client

```javascript
// Will open a WebSocket to ws://localhost:8182 by default
var client = gremlin.createClient();
```
This is a shorthand for:
```javascript
var client = gremlin.createClient(8182, 'localhost');
```

If you want to use Gremlin Server sessions, you can set the `session` argument as true in the `options` object:
```javascript
var client = gremlin.createClient(8182, 'localhost', { session: true });
```

The `options` object currently allows you to set two options:
* `session`: whether to use sessions or not (default: `false`)
* `language`: the script engine to use on the server, see your gremlin-server.yaml file (default: `"gremlin-groovy"`)

### Sending scripts to Gremlin Server for execution
The client supports two modes: streaming results, or traditional callback mode.

#### Stream mode: client.stream(script)

Return a Node.js stream which emits a `data` event with the raw data returned by Gremlin Server every time it receives a message (ie. the raw message returned by Gremlin Server). The stream simultaneously also emits a higher level `result` event, with `message.result` as a payload.

The stream emits an `end` event when the client receives the last `statusCode: 299` message.

```javascript
var query = client.stream('g.V()');

query.on('data', function(message) {
  console.log(message.result);
});

// Alternatively
// query.on('result', function(result) {
//  console.log(result);
// });

query.on('end', function(msg) {
  console.log("All results fetched", msg);
});

```

#### Callback mode: client.execute(script, callback)

Will execute the provided callback when all results are actually returned from the server.

```javascript
var client = gremlin.createClient();

client.execute('g.V()', function(err, response) {
  if (!err) {
    console.log(response.result)
  }
});
```

The client will internally concatenate all partial results returned over different messages (possibly, depending on the total number of results and the value of `resultIterationBatchSize` set in your .yaml file).

When the client receives the final `statusCode: 299` message, the callback will be executed.

### Adding bound parameters to your scripts

For better performance and security concerns, you may wish to send bound parameters to your scripts.

```javascript
var client = gremlin.createClient();

client.execute('g.v(id)', { id: 1 }, function(err, response) {
  // Handle result
});
```

### Overriding low level settings on a per request basis

For advanced usage, for example if you wish to set the the `op` or `processor` values, you may wish to override values in the raw message sent to Gremlin Server:

```javascript
client.execute('g.v(1)', null, { args: { language: 'nashorn' }}, function(err, response) {
  // Handle result
});
```

Because we're not sending any bound parameters, notice how the second argument **must** be set to null so the low level message object is not mistaken with bound arguments.

If you wish to also send bound parameters while overriding the low level message, you can do the following:

```javascript
client.execute('g.v(id)', { id: 1 }, { args: { language: 'nashorn' }}, function(err, response) {
  // Handle result
});
```

The same method signature also applies to `client.stream()`:

```javascript
var s = client.stream(script, bindings, message);
```


### Using Gremlin-JavaScript syntax with Nashorn

Providing your configured `nashorn` script engine in your `gremlin-server.yaml` file, you can send and execute Gremlin-JavaScript formatted queries:

```yaml
scriptEngines: {
  gremlin-groovy: {
    imports: [java.lang.Math],
    staticImports: [java.lang.Math.PI],
    scripts: [scripts/generate-classic.groovy]},
  nashorn: {
      imports: [java.lang.Math],
      staticImports: [java.lang.Math.PI]}}
```

Then, in your Node.js/Browser environment:

```javascript
var client = gremlin.createClient({ language: 'nashorn' });

// Wrap a script definition in a JavaScript function
var script = function() {
  // Retrieve all vertices ordered by name
  g.V().order(function(a, b) {
    return a.get().value('name').localeCompare(b.get().value('name')); // JavaScript replacement for <=> spaceship operator
  });
};

// Send that script function body to Gremlin Server for execution in Nashorn engine
client.execute(script, function(err, response) {
  // Handle response.results
});
```

The client gets a string representation of the function passed to `client.stream()` or `client.query()` by calling the `.toString()` method.

Passing bound parameters and/or low level message will also work when using nashorn script engine.

## Running the Examples

This section assumes that you configured `resultIterationBatchSize: 1` in your Gremlin Server .yaml config file and loaded the default TinkerPop graph with `scripts: [scripts/generate-classic.groovy]`


To run the command line example:
```
{'fraction_non_alphanumeric': 0.11935208866155157, 'fraction_numerical': 0.0076726342710997444, 'mean_word_length': 4.636636636636637, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5463584', 'n_tokens_mistral': 2769, 'n_tokens_neox': 2576, 'n_words': 1071}