Consul
This is a Consul client.
Documentation
See the official HTTP API docs for more information.
consul([options])
Initialize a new Consul client.
Options
- host (String, default: 127.0.0.1): agent address
- port (String, default: 8500): agent HTTP(S) port
- secure (Boolean, default: false): enable HTTPS
- ca (String[], optional): array of strings or Buffers of trusted certificates in PEM format
- defaults (Object, optional): default options for method calls
- promisify (Boolean|Function, optional): convert callback methods to promises
Usage
var consul = require('consul')();
Callback
All callback methods have the following signature function(err, data, res)
.
- err (Error, optional): set if there was an error, otherwise falsy
- data (Object, optional): response data if any, otherwise
undefined
- res (http.IncomingMessage, optional): HTTP response object with additional
body
property. This might not exist when err
is set. The body
property can be a decoded object, string, or Buffer.
Promise
Promise support can be enabled by setting promisify
to true
in Node >= 0.12
or passing a wrapper (ex: bluebird.fromCallback
) in older versions.
If you need access to the res
object you can create a custom wrapper (see example below).
Common Options
These options will be passed along with any method call, although only certain endpoints support them. See the HTTP API for more information.
- dc (String, optional): datacenter (defaults to local for agent)
- wan (Boolean, default: false): return WAN members instead of LAN members
- consistent (Boolean, default: false): require strong consistency
- stale (Boolean, default: false): use whatever is available, can be arbitrarily stale
- index (String, optional): used with
ModifyIndex
to block and wait for changes - wait (String, optional): limit how long to wait for changes (ex:
5m
), used with index - token (String, optional): ACL token
These options work for all methods.
- ctx (EventEmitter, optional): emit
cancel
to abort request - timeout (Number, optional): number of milliseconds before request is aborted
consul.acl
consul.acl.create([options], callback)
Creates a new token with policy.
Options
- name (String, optional): human readable name for the token
- type (String, enum: client, management; default: client): type of token
- rules (String, optional): string encoded HCL or JSON
Usage
consul.acl.create(function(err, result) {
if (err) throw err;
});
Result
{
"ID": "b1f4c10e-b61b-e1de-de95-218c9fefdd3e"
}
consul.acl.update(options, callback)
Update the policy of a token.
Options
- id (String): token ID
- name (String, optional): human readable name for the token
- type (String, enum: client, management; default: client): type of token
- rules (String, optional): string encoded HCL or JSON
Usage
consul.acl.update({ id: '63e1d82e-f718-eb92-3b7d-61f0c71d45b4', name: 'test' }, function(err) {
if (err) throw err;
});
consul.acl.destroy(options, callback)
Destroys a given token.
Options
Usage
consul.acl.destroy('b1f4c10e-b61b-e1de-de95-218c9fefdd3e', function(err) {
if (err) throw err;
});
consul.acl.get(options, callback)
Queries the policy of a given token.
Options
Usage
consul.acl.get('63e1d82e-f718-eb92-3b7d-61f0c71d45b4', function(err, result) {
if (err) throw err;
});
Result
{
"CreateIndex": 7,
"ModifyIndex": 7,
"ID": "63e1d82e-f718-eb92-3b7d-61f0c71d45b4",
"Name": "Read only",
"Type": "client",
"Rules": "{\"key\":{\"\":{\"policy\":\"read\"}}}"
}
consul.acl.clone(options, callback)
Creates a new token by cloning an existing token.
Options
Usage
consul.acl.clone('63e1d82e-f718-eb92-3b7d-61f0c71d45b4', function(err) {
if (err) throw err;
});
Result
{
"ID": "9fb8b20b-2636-adbb-9b99-d879df3305ec"
}
consul.acl.list([options], callback)
Lists all the active tokens.
Usage
consul.acl.list(function(err, result) {
if (err) throw err;
});
Result
[
{
"CreateIndex": 2,
"ModifyIndex": 2,
"ID": "anonymous",
"Name": "Anonymous Token",
"Type": "client",
"Rules": ""
}
{
"CreateIndex": 3,
"ModifyIndex": 3,
"ID": "root",
"Name": "Master Token",
"Type": "management",
"Rules": ""
}
]
consul.agent
consul.agent.members([options], callback)
Returns the members as seen by the consul agent.
Options
- wan (Boolean, default: false): return WAN members instead of LAN members
Usage
consul.agent.members(function(err, result) {
if (err) throw err;
});
Result
[
{
"Name": "node1",
"Addr": "127.0.0.1",
"Port": 8301,
"Tags": {
"bootstrap": "1",
"build": "0.3.0:441d613e",
"dc": "dc1",
"port": "8300",
"role": "consul",
"vsn": "2",
"vsn_max": "2",
"vsn_min": "1"
},
"Status": 1,
"ProtocolMin": 1,
"ProtocolMax": 2,
"ProtocolCur": 2,
"DelegateMin": 2,
"DelegateMax": 4,
"DelegateCur": 4
}
]
consul.agent.self(callback)
Returns the agent node configuration.
Usage
consul.agent.self(function(err, result) {
if (err) throw err;
});
Result
{
"Config": {
"Bootstrap": true,
"Server": true,
"Datacenter": "dc1",
"DataDir": "/tmp/node1/data",
"DNSRecursor": "",
"DNSConfig": {
"NodeTTL": 0,
"ServiceTTL": null,
"AllowStale": false,
"MaxStale": 5000000000
},
"Domain": "consul.",
"LogLevel": "INFO",
"NodeName": "node1",
"ClientAddr": "127.0.0.1",
"BindAddr": "127.0.0.1",
"AdvertiseAddr": "127.0.0.1",
"Ports": {
"DNS": 8600,
"HTTP": 8500,
"RPC": 8400,
"SerfLan": 8301,
"SerfWan": 8302,
"Server": 8300
},
"LeaveOnTerm": false,
"SkipLeaveOnInt": false,
"StatsiteAddr": "",
"Protocol": 2,
"EnableDebug": false,
"VerifyIncoming": false,
"VerifyOutgoing": false,
"CAFile": "",
"CertFile": "",
"KeyFile": "",
"ServerName": "",
"StartJoin": [],
"UiDir": "",
"PidFile": "/tmp/node1/pid",
"EnableSyslog": false,
"SyslogFacility": "LOCAL0",
"RejoinAfterLeave": false,
"CheckUpdateInterval": 300000000000,
"Revision": "441d613e1bd96254c78c46ee7c1b35c161fc7295+CHANGES",
"Version": "0.3.0",
"VersionPrerelease": ""
},
"Member": {
"Name": "node1",
"Addr": "127.0.0.1",
"Port": 8301,
"Tags": {
"bootstrap": "1",
"build": "0.3.0:441d613e",
"dc": "dc1",
"port": "8300",
"role": "consul",
"vsn": "2",
"vsn_max": "2",
"vsn_min": "1"
},
"Status": 1,
"ProtocolMin": 1,
"ProtocolMax": 2,
"ProtocolCur": 2,
"DelegateMin": 2,
"DelegateMax": 4,
"DelegateCur": 4
}
}
consul.agent.maintenance(options, callback)
Set node maintenance mode.
Options
- enable (Boolean): maintenance mode enabled
- reason (String, optional): human readable reason for maintenance
Usage
consul.agent.maintenance(true, function(err) {
if (err) throw err;
});
consul.agent.join(options, callback)
Trigger agent to join a node.
Options
- address (String): node IP address to join
- wan (Boolean, default false): attempt to join using the WAN pool
Usage
consul.agent.join('127.0.0.2', function(err) {
if (err) throw err;
});
consul.agent.forceLeave(options, callback)
Force remove node.
Options
- node (String): node name to remove
Usage
consul.agent.forceLeave('node2', function(err) {
if (err) throw err;
});
consul.agent.check
consul.agent.check.list(callback)
Returns the checks the agent is managing.
Usage
consul.agent.check.list(function(err, result) {
if (err) throw err;
});
Result
{
"example": {
"Node": "node1",
"CheckID": "example",
"Name": "example",
"Status": "passing",
"Notes": "This is an example check.",
"Output": "",
"ServiceID": "",
"ServiceName": ""
}
}
consul.agent.check.register(options, callback)
Registers a new check.
Options
- name (String): check name
- id (String, optional): check ID
- serviceid (String, optional): service ID, associate check with existing service
- http (String): url to test, 2xx passes, 429 warns, and all others fail
- tcp (String): host:port to test, passes if connection is established, fails otherwise
- script (String): path to check script, requires interval
- dockercontainerid (String, optional): Docker container ID to run script
- shell (String, optional): shell in which to run script (currently only supported with Docker)
- interval (String): interval to run check, requires script (ex:
15s
) - timeout (String, optional): timeout for the check (ex:
10s
) - ttl (String): time to live before check must be updated, instead of http/tcp/script and interval (ex:
60s
) - notes (String, optional): human readable description of check
- status (String, optional): initial service status
- deregistercriticalserviceafter (String, optional, Consul 0.7+): timeout after
which to automatically deregister service if check remains in critical state
Usage
var check = {
name: 'example',
ttl: '15s',
notes: 'This is an example check.',
};
consul.agent.check.register(check, function(err) {
if (err) throw err;
});
consul.agent.check.deregister(options, callback)
Deregister a check.
Options
Usage
consul.agent.check.deregister('example', function(err) {
if (err) throw err;
});
consul.agent.check.pass(options, callback)
Mark a test as passing.
Options
- id (String): check ID
- note (String, optional): human readable message
Usage
consul.agent.check.pass('example', function(err) {
if (err) throw err;
});
consul.agent.check.warn(options, callback)
Mark a test as warning.
Options
- id (String): check ID
- note (String, optional): human readable message
Usage
consul.agent.check.warn('example', function(err) {
if (err) throw err;
});
consul.agent.check.fail(options, callback)
Mark a test as critical.
Options
- id (String): check ID
- note (String, optional): human readable message
Usage
consul.agent.check.fail('example', function(err) {
if (err) throw err;
});
consul.agent.service
consul.agent.service.list(callback)
Returns the services the agent is managing.
Usage
consul.agent.service.list(function(err, result) {
if (err) throw err;
});
Result
{
"example": {
"ID": "example",
"Service": "example",
"Tags": [
"dev",
"web"
],
"Port": 80
}
}
consul.agent.service.register(options, callback)
Registers a new service.
Options
- name (String): service name
- id (String, optional): service ID
- tags (String[], optional): service tags
- address (String, optional): service IP address
- port (Integer, optional): service port
- check (Object, optional): service check
- http (String): URL endpoint, requires interval
- tcp (String): host:port to test, passes if connection is established, fails otherwise
- script (String): path to check script, requires interval
- dockercontainerid (String, optional): Docker container ID to run script
- shell (String, optional): shell in which to run script (currently only supported with Docker)
- interval (String): interval to run check, requires script (ex:
15s
) - timeout (String, optional): timeout for the check (ex:
10s
) - ttl (String): time to live before check must be updated, instead of http/tcp/script and interval (ex:
60s
) - notes (String, optional): human readable description of check
- status (String, optional): initial service status
- deregistercriticalserviceafter (String, optional, Consul 0.7+): timeout after
which to automatically deregister service if check remains in critical state
- checks (Object[], optional): service checks (see
check
above)
Usage
consul.agent.service.register('example', function(err) {
if (err) throw err;
});
consul.agent.service.deregister(options, callback)
Deregister a service.
Options
Usage
consul.agent.service.deregister('example', function(err) {
if (err) throw err;
});
consul.agent.service.maintenance(options, callback)
Set service maintenance mode.
Options
- id (String): service ID
- enable (Boolean): maintenance mode enabled
- reason (String, optional): human readable reason for maintenance
Usage
consul.agent.service.maintenance({ id: 'example', enable: true }, function(err) {
if (err) throw err;
});
consul.catalog
consul.catalog.datacenters(callback)
Lists known datacenters.
Usage
consul.catalog.datacenters(function(err, result) {
if (err) throw err;
});
Result
[
"dc1"
]
consul.catalog.node
consul.catalog.node.list([options], callback)
Lists nodes in a given datacenter.
Options
- dc (String, optional): datacenter (defaults to local for agent)
Usage
consul.catalog.node.list(function(err, result) {
if (err) throw err;
});
Result
[
{
"Node": "node1",
"Address": "127.0.0.1"
}
]
consul.catalog.node.services(options, callback)
Lists the services provided by a node.
Options
Usage
consul.catalog.node.services('node1', function(err, result) {
if (err) throw err;
});
Result
{
"Node": {
"Node": "node1",
"Address": "127.0.0.1"
},
"Services": {
"consul": {
"ID": "consul",
"Service": "consul",
"Tags": [],
"Port": 8300
},
"example": {
"ID": "example",
"Service": "example",
"Tags": [
"dev",
"web"
],
"Port": 80
}
}
}
consul.catalog.service
consul.catalog.service.list([options], callback)
Lists services in a given datacenter.
Options
- dc (String): datacenter (defaults to local for agent)
Usage
consul.catalog.service.list(function(err, result) {
if (err) throw err;
});
Result
{
"consul": [],
"example": [
"dev",
"web"
]
}
consul.catalog.service.nodes(options, callback)
Lists the nodes in a given service.
Options
- service (String): service name
- dc (String, optional): datacenter (defaults to local for agent)
- tag (String, optional): filter by tag
Usage
consul.catalog.service.nodes('example', function(err, result) {
if (err) throw err;
});
Result
[
{
"Node": "node1",
"Address": "127.0.0.1",
"ServiceID": "example",
"ServiceName": "example",
"ServiceTags": [
"dev",
"web"
],
"ServicePort": 80
}
]
consul.event
consul.event.fire(options, callback)
Fires a new user event.
Options
- name (String): event name
- payload (String|Buffer): payload
- node (String, optional): regular expression to filter by node
- service (String, optional): regular expression to filter by service
- tag (String, optional): regular expression to filter by tag
Usage
consul.event.fire('deploy', '53', function(err, result) {
if (err) throw err;
});
Result
{
"ID": "4730953b-3135-7ff2-47a7-9d9fc9c4e5a2",
"Name": "deploy",
"Payload": "53",
"NodeFilter": "",
"ServiceFilter": "",
"TagFilter": "",
"Version": 1,
"LTime": 0
}
consul.event.list([options], callback)
Lists the most recent events an agent has seen.
Options
- name (String, optional): filter by event name
Usage
consul.event.list('deploy', function(err, result) {
if (err) throw err;
});
Result
[
{
"ID": "4730953b-3135-7ff2-47a7-9d9fc9c4e5a2",
"Name": "deploy",
"Payload": "53",
"NodeFilter": "",
"ServiceFilter": "",
"TagFilter": "",
"Version": 1,
"LTime": 2
}
]
consul.health
consul.health.node(options, callback)
Returns the health info of a node.
Options
- node (String): node
- dc (String, optional): datacenter (defaults to local for agent)
Usage
consul.health.node('node1', function(err, result) {
if (err) throw err;
});
Result
[
{
"Node": "node1",
"CheckID": "serfHealth",
"Name": "Serf Health Status",
"Status": "passing",
"Notes": "",
"Output": "Agent alive and reachable",
"ServiceID": "",
"ServiceName": ""
},
{
"Node": "node1",
"CheckID": "service:example",
"Name": "Service 'example' check",
"Status": "critical",
"Notes": "",
"Output": "",
"ServiceID": "example",
"ServiceName": "example"
}
]
consul.health.checks(options, callback)
Returns the checks of a service.
Options
- service (String): service name
- dc (String, optional): datacenter (defaults to local for agent)
Usage
consul.health.checks('example', function(err, result) {
if (err) throw err;
});
Result
[
{
"Node": "node1",
"CheckID": "service:example",
"Name": "Service 'example' check",
"Status": "critical",
"Notes": "",
"Output": "",
"ServiceID": "example",
"ServiceName": "example"
}
]
consul.health.service(options, callback)
Returns the nodes and health info of a service.
Options
- service (String): service name
- dc (String, optional): datacenter (defaults to local for agent)
- tag (String, optional): filter by tag
- passing (Boolean, optional): restrict to passing checks
Usage
consul.health.service('example', function(err, result) {
if (err) throw err;
});
Result
[
{
"Node": {
"Node": "node1",
"Address": "127.0.0.1"
},
"Service": {
"ID": "example",
"Service": "example",
"Tags": [],
"Port": 0
},
"Checks": [
{
"Node": "node1",
"CheckID": "service:example",
"Name": "Service 'example' check",
"Status": "critical",
"Notes": "",
"Output": "",
"ServiceID": "example",
"ServiceName": "example"
},
{
"Node": "node1",
"CheckID": "serfHealth",
"Name": "Serf Health Status",
"Status": "passing",
"Notes": "",
"Output": "Agent alive and reachable",
"ServiceID": "",
"ServiceName": ""
}
]
}
]
consul.health.state(options, callback)
Returns the checks in a given state.
Options
- state (String, enum: any, passing, warning, critical): state
- dc (String, optional): datacenter (defaults to local for agent)
Usage
consul.health.state('critical', function(err, result) {
if (err) throw err;
});
Result
[
{
"Node": "node1",
"CheckID": "service:example",
"Name": "Service 'example' check",
"Status": "critical",
"Notes": "",
"Output": "",
"ServiceID": "example",
"ServiceName": "example"
}
]
consul.kv
consul.kv.get(options, callback)
Return key/value (kv) pair(s).
Options
- key (String): path to value
- dc (String, optional): datacenter (defaults to local for agent)
- recurse (Boolean, default: false): return all keys with given key prefix
- index (String, optional): used with
ModifyIndex
to block and wait for changes - wait (String, optional): limit how long to wait for changes (ex:
5m
), used with index - raw (Boolean, optional): return raw value (can't be used with recursive, implies buffer)
- buffer (Boolean, default: false): decode value into Buffer instead of String
Usage
consul.kv.get('hello', function(err, result) {
if (err) throw err;
});
Result
{
"CreateIndex": 6,
"ModifyIndex": 6,
"LockIndex": 0,
"Key": "hello",
"Flags": 0,
"Value": "world"
}
consul.kv.keys(options, callback)
Return keys for a given prefix.
Options
- key (String): path prefix
- dc (String, optional): datacenter (defaults to local for agent)
- separator (String, optional): list keys up to a given separator
Usage
consul.kv.keys('a/', function(err, result) {
if (err) throw err;
});
Result
[
"a/b",
"a/c"
]
consul.kv.set(options, callback)
Set key/value (kv) pair.
Options
- key (String): key
- value (String|Buffer): value
- dc (String, optional): datacenter (defaults to local for agent)
- flags (Number, optional): unsigned integer opaque to user, can be used by application
- cas (String, optional): use with
ModifyIndex
to do a check-and-set operation - acquire (String, optional): session ID, lock acquisition operation
- release (String, optional): session ID, lock release operation
Usage
consul.kv.set('hello', 'world', function(err, result) {
if (err) throw err;
});
Result
true
consul.kv.del(options, callback)
Delete key/value (kv) pair(s).
Options
- key (String): key
- dc (String, optional): datacenter (defaults to local for agent)
- recurse (Boolean, default: false): delete all keys with given key prefix
- cas (String, optional): use with
ModifyIndex
to do a check-and-set operation (must be greater than 0
)
Usage
consul.kv.del('hello', function(err) {
if (err) throw err;
});
consul.lock(options)
Experimental
Lock a key using the method described in the leader election guide.
Options
- key (String): lock key
- value (String|Buffer, optional): lock value
- session (Object|String, optional): session options
Events
acquire
: lock successfully acquirederror
: lock related errorretry
: lock retry attemptrelease
: lock gracefully released (not always emitted)end
: lock ended (always emitted)
Usage
var lock = consul.lock({ key: 'test' });
lock.on('acquire', function() {
console.log('lock acquired');
lock.release();
});
lock.on('release', function() {
console.log('lock released');
});
lock.on('error', function() {
console.log('lock error:', err);
});
lock.on('end', function(err) {
console.log('lock released or there was a permanent failure');
});
lock.acquire();
Result
lock acquired
lock released
lock released or there was a permanent failure
consul.session
consul.session.create([options], callback)
Create a new session.
Options
- dc (String, optional): datacenter (defaults to local for agent)
- lockdelay (String, range: 1s-60s, default:
15s
): the time consul prevents locks held by the session from being acquired after a session has been invalidated - name (String, optional): human readable name for the session
- node (String, optional): node with which to associate session (defaults to connected agent)
- checks (String[], optional): checks to associate with session
- behavior (String, enum: release, delete; default: release): controls the behavior when a session is invalidated
- ttl (String, optional, valid:
10s
-3600s
): interval session must be renewed
Usage
consul.session.create(function(err, result) {
if (err) throw err;
});
Result
{
"ID": "a0f5dc05-84c3-5f5a-1d88-05b875e524e1"
}
consul.session.destroy(options, callback)
Destroy a given session.
Options
- id (String): session ID
- dc (String, optional): datacenter (defaults to local for agent)
Usage
consul.session.destroy('a0f5dc05-84c3-5f5a-1d88-05b875e524e1', function(err) {
if (err) throw err;
});
consul.session.get(options, callback)
Queries a given session.
Options
- id (String): session ID
- dc (String, optional): datacenter (defaults to local for agent)
Usage
consul.session.get('a0f5dc05-84c3-5f5a-1d88-05b875e524e1', function(err, result) {
if (err) throw err;
});
Result
{
"CreateIndex": 11,
"ID": "a0f5dc05-84c3-5f5a-1d88-05b875e524e1",
"Name": "",
"Node": "node1",
"Checks": [
"serfHealth"
],
"LockDelay": 15000000000
}
consul.session.node(options, callback)
Lists sessions belonging to a node.
Options
- node (String): node
- dc (String, optional): datacenter (defaults to local for agent)
Usage
consul.session.node('node1', function(err, result) {
if (err) throw err;
});
Result
[
{
"CreateIndex": 13,
"ID": "a0f5dc05-84c3-5f5a-1d88-05b875e524e1",
"Name": "",
"Node": "node1",
"Checks": [
"serfHealth"
],
"LockDelay": 15000000000
}
]
consul.session.list([options], callback)
Lists all the active sessions.
Options
- dc (String, optional): datacenter (defaults to local for agent)
Usage
consul.session.list(function(err, result) {
if (err) throw err;
});
Result
[
{
"CreateIndex": 15,
"ID": "a0f5dc05-84c3-5f5a-1d88-05b875e524e1",
"Name": "",
"Node": "node1",
"Checks": [
"serfHealth"
],
"LockDelay": 15000000000
}
]
consul.session.renew(options, callback)
Renew a given session.
Options
- id (String): session ID
- dc (String, optional): datacenter (defaults to local for agent)
Usage
consul.session.renew('a0f5dc05-84c3-5f5a-1d88-05b875e524e1', function(err, renew) {
if (err) throw err;
});
Result
[
{
"CreateIndex": 15,
"ID": "a0f5dc05-84c3-5f5a-1d88-05b875e524e1",
"Name": "",
"Node": "node1",
"Checks": [
"serfHealth"
],
"LockDelay": 15000000000,
"Behavior": "release",
"TTL": ""
}
]
consul.status
consul.status.leader(callback)
Returns the current Raft leader.
Usage
consul.status.leader(function(err, result) {
if (err) throw err;
});
Result
"127.0.0.1:8300"
consul.status.peers(callback)
Returns the current Raft peer set.
Usage
consul.status.peers(function(err, result) {
if (err) throw err;
});
Result
[
"127.0.0.1:8300"
]
consul.watch(options)
Watch an endpoint for changes.
The watch relies on blocking queries, adding the index
and wait
parameters as per Consul's documentation
If a blocking query is dropped due to a Consul crash or disconnect, watch will attempt to reinitiate the blocking query with logarithmic backoff.
Upon reconnect, unlike the first call to watch() in which the latest x-consul-index
is unknown, the last known x-consul-index
will be reused, thus not emitting the change
event unless it has been incremented since.
Options
- method (Function): method to watch
- options (Object): method options
Usage
var watch = consul.watch({ method: consul.kv.get, options: { key: 'test' });
watch.on('change', function(data, res) {
console.log('data:', data);
});
watch.on('error', function(err) {
console.log('error:', err);
});
setTimeout(function() { watch.end(); }, 30 * 1000);
Promise Wrapper
var Bluebird = require('bluebird');
function fromCallback(fn) {
return new Bluebird(function(resolve, reject) {
try {
return fn(function(err, data, res) {
if (err) {
err.res = res;
return reject(err);
}
return resolve([data, res]);
});
} catch (err) {
return reject(err);
}
});
}
var consul = require('consul')({ promisify: fromCallback });
consul.kv.set('test', 'hello world').then(function() {
consul.kv.keys().spread(function(data, res) {
console.log('data:', data);
console.log('headers:', res.headers);
});
});
Acceptance Tests
-
Install Consul into your PATH
$ brew install consul
-
Attach required IPs
$ sudo ifconfig lo0 alias 127.0.0.2 up
$ sudo ifconfig lo0 alias 127.0.0.3 up
-
Install client dependencies
$ npm install
-
Run tests
$ npm run acceptance
License
This work is licensed under the MIT License (see the LICENSE file).