Switched the color package to one with more reasonable deps, added some examples to README.md, and included which will soon be used to make promisses.

This commit is contained in:
Spencer Alger
2013-11-07 14:53:06 -07:00
parent ca29fbe6e3
commit 28e99cf16b
7 changed files with 246 additions and 125 deletions

View File

@ -4,6 +4,7 @@
module.exports = function (grunt) {
var _ = require('lodash');
var child_process = require('child_process');
var sharedBrowserfyExclusions = [
'src/lib/connectors/http.js',
'src/lib/loggers/file.js',
@ -72,26 +73,25 @@ module.exports = function (grunt) {
interupt: true
}
},
generate: {
run: {
js_api: {
cmd: 'node',
args: [
'scripts/generate/js_api'
]
},
yaml_tests: {
cmd: 'node',
args: [
'scripts/generate/yaml_tests'
]
}
},
start: {
integration_server: {
cmd: 'node',
args: [
'test/browser_integration/server.js'
]
],
options: {
wait: false,
ready: /server listening/
}
}
},
browserify: {
@ -168,10 +168,18 @@ module.exports = function (grunt) {
'--web-security': false
}
}
},
open: {
yaml_suite: {
path: 'http://localhost:8888',
app: 'Google Chrome'
}
}
});
// load plugins
grunt.loadNpmTasks('grunt-run');
grunt.loadNpmTasks('grunt-open');
grunt.loadNpmTasks('grunt-mocha');
grunt.loadNpmTasks('grunt-browserify');
grunt.loadNpmTasks('grunt-mocha-test');
@ -197,73 +205,14 @@ module.exports = function (grunt) {
'browserify',
'uglify:dist',
'concat:dist_banners',
'generate:yaml_tests',
'generate:js_api'
'run:yaml_tests',
'run:js_api'
]);
grunt.task.registerMultiTask('generate', 'used to generate things', function () {
var done = this.async();
var proc = require('child_process').spawn(
this.data.cmd,
this.data.args,
{
stdio: ['ignore', 'pipe', 'pipe']
}
);
proc.stdout.on('data', grunt.log.write);
proc.stderr.on('data', grunt.log.error);
proc.on('close', function (exitCode) {
done(!exitCode);
});
});
var runningProcs = {};
process.on('exit', function () {
_.each(runningProcs, function (proc) {
proc.kill();
});
});
grunt.task.registerMultiTask('start', 'used to start external processes (like servers)', function () {
var self = this;
var proc = require('child_process').spawn(
self.data.cmd,
self.data.args,
{
stdio: ['ignore', 'pipe', 'pipe']
}
);
proc.stdout.on('data', grunt.log.write);
proc.stderr.on('data', function (chunk) {
grunt.log.error(chunk);
proc.kill();
self.ansyc()(new Error('Error output received'));
clearTimeout(timeoutId);
});
runningProcs[self.nameArgs] = proc;
proc.on('close', function (exitCode) {
delete runningProcs[self.nameArgs];
});
// operates asyncronously to give the processes a moment to start up, not sure if there is a signal for "I'm ready"
var timeoutId = setTimeout(self.async(), 1000);
});
grunt.task.registerMultiTask('stop', 'used to stop external processes (like servers)', function () {
var proc = runningProcs[this.nameArgs.replace(/^start:/, 'stop:')];
if (proc) {
proc.kill();
} else {
grunt.log.error(this.nameArgs + ' failed to find active process');
}
});
grunt.registerTask('browser', [
'run:integration_server',
'open:yaml_suite',
'wait:integration_server'
]);
};

101
README.md
View File

@ -1,20 +1,101 @@
elasticsearch-js
=================
[![Build Status](https://magnum.travis-ci.com/spenceralger/elasticsearch-js.png?token=tsFxSKHtVKG8EZavSjXY)](https://magnum.travis-ci.com/spenceralger/elasticsearch-js)
# elasticsearch.js
Official *low-level* client for Elasticsearch.
This project's goal it to give the JavaScript community a solif foundation for all Elasticsearch-related code. It features a complete API, provides a module for use in Node.js as well as several different build for use in the browser. We have tried to be opinion-free and very plugable.
This project's goal it to give the JavaScript community a solif foundation for all Elasticsearch-related code. It features a complete API, provides a module for use in Node.js as well as several different builds for use in the browser. We have tried to be opinion-free and very plugable.
To maintain consistency across all the low-level clients (Ruby, Python, etc), clients accept all of their parameters via a single object, along with a single callback.
Features
--------
## Features
- One-to-one mapping with REST API and other language clients
- Generalized, pluggable architecture. See [replacing core components](docs/replacing-core-components.md)
- Configurable, automatic discovery of cluster nodes
- Persistent, Keep-Alive connections
- Load balancing (with pluggable selection strategy) across all availible nodes. Defaults to round-robin
- Pluggable connection pools to offer different connection strategies
- Generalized, pluggable architecture - most components can be replaced with your own custom class if specialized behavior is required
## Node and the browser
elasticsearch.js works great in node, as well as the browser (many thanks to [browserify](https://github.com/substack/browserify)).
- Node: [![Build Status](https://magnum.travis-ci.com/spenceralger/elasticsearch-js.png?token=tsFxSKHtVKG8EZavSjXY)](https://magnum.travis-ci.com/spenceralger/elasticsearch-js)
- Browsers:
+ ![testling results for browser clients](https://ci.testling.com/spenceralger/xhr-method-test.png)
## Install in Node
```
npm install --save elasticsearch
```
## Browser Builds
Download one of these builds:
- [elasticsearch.js](dist/elasticsearch.js) - [minified](dist/elasticsearch.min.js)
- uses the browser's native XHR object
- Node style callbacks with a bare-bones `.then()` method
- [elasticsearch.angular.js](dist/elasticsearch.angular.js) - [minified](dist/elasticsearch.angular.min.js)
- Uses angular's $http servive
- returns promisses using angular's $q servive
## API
To maintain consistency across all the low-level clients (Ruby, Python, etc), clients accept all of their parameters via a single object, along with a single callback.
#### create the client
```
var es = new elasticsearch.Client({
hosts: [
'localhost:9200'
],
log: 'trace',
sniffOnStart: true
});
```
#### call an endpoint
```
es.cluster.nodeInfo({
clear: true,
jvm: true,
os: ture
}, function (err, resp, status) {
// do your thing
})
```
#### skip the callback to get a promise back
```
es.search({
q: 'pants'
}).then(function (resp) {
// use resp.body and resp.status
}, function (err) {
// freak out!
})
```
#### abort a request
```
var req = es.search({
q: 'robots'
}, function (err, body, status) {
clearTimeout(timeout);
// do something
});
var timeout = setTimeout(function () {
req.abort();
}, 200);
```
#### or just use the timeout param
```
es.search({
q: '*',
timeout: 200
}).then(function (resp) {
// Iterate all the hits
})
```

View File

@ -0,0 +1 @@
==

View File

@ -7,33 +7,36 @@
"homepage": "https://github.com/elasticsearch/elasticsearch-js",
"version": "0.0.1",
"devDependencies": {
"grunt": "*",
"grunt-contrib-jshint": "*",
"grunt-contrib-nodeunit": "*",
"js-yaml": "*",
"tar": "*",
"mocha": "*",
"async": "*",
"mkdirp": "*",
"moment": "*",
"should": "*",
"grunt-mocha-test": "*",
"grunt-contrib-watch": "*",
"expect.js": "*",
"async": "*",
"js-yaml": "*",
"optimist": "*",
"expect.js": "*",
"minimatch": "*",
"browserify": "*",
"grunt": "*",
"grunt-contrib-jshint": "*",
"grunt-contrib-nodeunit": "*",
"grunt-mocha-test": "*",
"grunt-contrib-watch": "*",
"grunt-browserify": "*",
"grunt-contrib-clean": "*",
"grunt-contrib-uglify": "*",
"mocha": "*",
"grunt-mocha": "*",
"grunt-contrib-concat": "~0.3.0"
"grunt-contrib-concat": "~0.3.0",
"grunt-open": "~0.2.2",
"grunt-run": "~0.1.0"
},
"license": "Apache License",
"dependencies": {
"cli-color": "*",
"when": "~2.6.0",
"lodash": "*",
"tar": "*",
"agentkeepalive": "*"
"agentkeepalive": "*",
"chalk": "~0.3.0"
},
"scripts": {
"test": "grunt"

View File

@ -0,0 +1,76 @@
var runningProcs = [];
process.on('exit', function () {
_.each(runningProcs, function (proc) {
proc.kill();
});
});
grunt.task.registerMultiTask('run', 'used to start external processes (like servers)', function () {
var self = this;
var name = this.target;
var opts = this.options({
wait: true,
killOnError: true
});
console.log(opts);
var proc = child_process.spawn(
self.data.cmd,
self.data.args,
{
stdio: ['ignore', 'pipe', 'pipe']
}
);
proc.stdout.on('data', grunt.log.write);
var done = this.async();
if (opts.killOnError) {
proc.stderr.on('data', function (chunk) {
grunt.log.error(chunk);
proc.kill();
self.ansyc()(new Error('Error output received'));
clearTimeout(timeoutId);
});
}
if (opts.wait) {
proc.on('close', function (exitCode) {
done(!exitCode);
});
} else {
grunt.config.set('stop.' + name + '._pid', proc.pid);
grunt.config.set('wait.' + name + '._pid', proc.pid);
runningProcs.push(proc);
var timeoutId = setTimeout(done, 1000);
}
proc.on('close', function (exitCode) {
var i;
if ((i = runningProcs.indexOf(proc)) !== -1) {
runningProcs.splice(i, 1);
}
grunt.log.debug('Process ' + name + ' closed.');
});
});
grunt.task.registerMultiTask('stop', 'stop a process started with "start" ' +
'(only works for tasks that use wait:false)', function () {
var pid = this.data._pid;
child_process.kill(pid);
});
grunt.task.registerMultiTask('wait', 'wait for a process to close ' +
'(only works for tasks that use wait:false)', function () {
var pid = this.data._pid;
var proc = _.find(runningProcs, { pid: pid });
if (proc) {
proc.on('close', this.async());
} else {
grunt.log.writeLn('process already closed');
}
});

View File

@ -12,15 +12,41 @@
module.exports = Stdio;
var clc = require('cli-color'),
LoggerAbstract = require('../logger'),
_ = require('../utils');
var chalk = require('chalk');
// let the user define if they want color in the client config.
chalk.enabled = true;
var LoggerAbstract = require('../logger');
var _ = require('../utils');
var defaultColors = {
error: function (txt) {
return chalk.red.bold(txt);
},
warning: function (txt) {
return chalk.yellow.bold(txt);
},
info: function (txt) {
return chalk.cyan.bold(txt);
},
debug: function (txt) {
return chalk.magenta.bold(txt);
},
trace: function (txt) {
return chalk.white.bold(txt);
},
traceStatus: function (status) {
return chalk[status >= 200 && status < 300 ? 'green' : 'red'].bold(status);
}
};
function Stdio(config, bridge) {
Stdio.callSuper(this, arguments);
// config/state
this.color = _.has(config, 'color') ? !!config.color : true;
this.color = Boolean(_.has(config, 'color') ? config.color : chalk.supportsColor);
this.colors = _.defaults(config.colors || {}, defaultColors);
}
_.inherits(Stdio, LoggerAbstract);
@ -52,7 +78,7 @@ Stdio.prototype.write = function (to, label, colorize, message) {
* @return {undefined}
*/
Stdio.prototype.onError = _.handler(function (e) {
this.write(process.stderr, e.name === 'Error' ? 'ERROR' : e.name, clc.red.bold, e.stack);
this.write(process.stderr, e.name === 'Error' ? 'ERROR' : e.name, this.colors.error, e.stack);
});
/**
@ -64,7 +90,7 @@ Stdio.prototype.onError = _.handler(function (e) {
* @return {undefined}
*/
Stdio.prototype.onWarning = _.handler(function (msg) {
this.write(process.stderr, 'WARNING', clc.yellow.bold, msg);
this.write(process.stderr, 'WARNING', this.colors.warning, msg);
});
/**
@ -76,7 +102,7 @@ Stdio.prototype.onWarning = _.handler(function (msg) {
* @return {undefined}
*/
Stdio.prototype.onInfo = _.handler(function (msg) {
this.write(process.stdout, 'INFO', clc.cyan.bold, msg);
this.write(process.stdout, 'INFO', this.colors.info, msg);
});
/**
@ -88,7 +114,7 @@ Stdio.prototype.onInfo = _.handler(function (msg) {
* @return {undefined}
*/
Stdio.prototype.onDebug = _.handler(function (msg) {
this.write(process.stdout, 'DEBUG', clc.magentaBright.bold, msg);
this.write(process.stdout, 'DEBUG', this.colors.debug, msg);
});
/**
@ -98,22 +124,18 @@ Stdio.prototype.onDebug = _.handler(function (msg) {
* @private
* @return {undefined}
*/
Stdio.prototype.onTrace = _.handler(function (method, url, body, responseBody, responseStatus) {
Stdio.prototype.onTrace = _.handler(function (method, url, body, resp, status) {
var message = 'curl "' + url.replace(/"/g, '\\"') + '" -X' + method.toUpperCase();
if (body) {
message += ' -d "' + body.replace(/"/g, '\\"') + '"';
}
message += '\n<- ';
if (this.color) {
if (responseStatus >= 200 && responseStatus < 300) {
message += clc.green.bold(responseStatus);
message += this.colors.traceStatus(status);
} else {
message += clc.red.bold(responseStatus);
message += status;
}
} else {
message += responseStatus;
}
message += '\n' + responseBody;
message += '\n' + resp;
this.write(process.stdout, 'TRACE', clc.cyanBright.bold, message);
this.write(process.stdout, 'TRACE', this.colors.trace, message);
});

View File

@ -17,18 +17,7 @@ var LoggerAbstract = require('../logger'),
_ = require('../utils'),
fs = require('fs');
// var = lessThanZeroTen (function () {
// var numbs = _.map(process.versions.node.split('.'), function (num) {
// return _.parseInt(num);
// });
// return numbs[0] === 0 && numbs[1] < 10;
// }());
function Stream(config, bridge) {
// if (lessThanZeroTen) {
// throw new Error('The stream logger is only compatible with node 0.10 and greater');
// }
Stream.callSuper(this, arguments);
_.makeBoundMethods(this);