Added browser build, including angular version. minified versions available
This commit is contained in:
67
Gruntfile.js
67
Gruntfile.js
@ -3,8 +3,18 @@
|
||||
|
||||
module.exports = function (grunt) {
|
||||
|
||||
var _ = require('lodash');
|
||||
var sharedBrowserfyExclusions = [
|
||||
'src/lib/connectors/http.js',
|
||||
'src/lib/loggers/file.js',
|
||||
'src/lib/loggers/stdio.js',
|
||||
'src/lib/loggers/stream.js',
|
||||
'src/lib/loggers/stream.js'
|
||||
];
|
||||
|
||||
// Project configuration.
|
||||
grunt.initConfig({
|
||||
distDir: 'dist',
|
||||
pkg: grunt.file.readJSON('package.json'),
|
||||
meta: {
|
||||
banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' +
|
||||
@ -13,6 +23,11 @@ module.exports = function (grunt) {
|
||||
' * Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;' +
|
||||
' Licensed <%= pkg.license %> */\n\n'
|
||||
},
|
||||
clean: {
|
||||
dist: {
|
||||
src: ['<%= distDir %>']
|
||||
}
|
||||
},
|
||||
mochaTest: {
|
||||
unit: [
|
||||
'test/unit/**/*.test.js'
|
||||
@ -76,6 +91,49 @@ module.exports = function (grunt) {
|
||||
'scripts/generate/yaml_tests'
|
||||
]
|
||||
}
|
||||
},
|
||||
browserify: {
|
||||
generic: {
|
||||
files: {
|
||||
'<%= distDir %>/elasticsearch.js': 'src/elasticsearch.js'
|
||||
},
|
||||
options: {
|
||||
standalone: 'true',
|
||||
ignore: _.union(sharedBrowserfyExclusions, [
|
||||
'src/lib/connectors/jquery.js',
|
||||
'src/lib/connectors/angular.js'
|
||||
])
|
||||
}
|
||||
},
|
||||
angular: {
|
||||
files: {
|
||||
'<%= distDir %>/elasticsearch.angular.js': ['src/elasticsearch.angular.js']
|
||||
},
|
||||
options: {
|
||||
standalone: 'true',
|
||||
ignore: _.union(sharedBrowserfyExclusions, [
|
||||
'src/lib/connectors/jquery.js',
|
||||
'src/lib/connectors/xhr.js'
|
||||
])
|
||||
}
|
||||
}
|
||||
},
|
||||
uglify: {
|
||||
dist: {
|
||||
files: {
|
||||
'<%= distDir %>/elasticsearch.min.js': '<%= distDir %>/elasticsearch.js',
|
||||
'<%= distDir %>/elasticsearch.angular.min.js': '<%= distDir %>/elasticsearch.angular.js'
|
||||
},
|
||||
options: {
|
||||
report: 'min',
|
||||
banner: '<%= meta.banner %>'
|
||||
},
|
||||
global_defs: {
|
||||
process: {
|
||||
browser: true
|
||||
}
|
||||
}
|
||||
}
|
||||
}//,
|
||||
// docular: {
|
||||
// groups: [
|
||||
@ -119,8 +177,11 @@ module.exports = function (grunt) {
|
||||
|
||||
// load plugins
|
||||
// grunt.loadNpmTasks('grunt-docular');
|
||||
grunt.loadNpmTasks('grunt-browserify');
|
||||
grunt.loadNpmTasks('grunt-mocha-test');
|
||||
grunt.loadNpmTasks('grunt-contrib-clean');
|
||||
grunt.loadNpmTasks('grunt-contrib-watch');
|
||||
grunt.loadNpmTasks('grunt-contrib-uglify');
|
||||
grunt.loadNpmTasks('grunt-contrib-jshint');
|
||||
|
||||
// Default task.
|
||||
@ -131,6 +192,12 @@ module.exports = function (grunt) {
|
||||
'mochaTest:yaml_suite'
|
||||
]);
|
||||
|
||||
grunt.registerTask('build', [
|
||||
'clean:dist',
|
||||
'browserify',
|
||||
'uglify:dist'
|
||||
]);
|
||||
|
||||
grunt.task.registerMultiTask('generate', 'used to generate things', function () {
|
||||
var done = this.async();
|
||||
var proc = require('child_process').spawn(
|
||||
|
||||
15951
dist/elasticsearch.angular.js
vendored
Normal file
15951
dist/elasticsearch.angular.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
8
dist/elasticsearch.angular.min.js
vendored
Normal file
8
dist/elasticsearch.angular.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
15948
dist/elasticsearch.js
vendored
Normal file
15948
dist/elasticsearch.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
8
dist/elasticsearch.min.js
vendored
Normal file
8
dist/elasticsearch.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -19,11 +19,14 @@
|
||||
"expect.js": "~0.2.0",
|
||||
"async": "~0.2.9",
|
||||
"optimist": "~0.6.0",
|
||||
"minimatch": "~0.2.12"
|
||||
"minimatch": "~0.2.12",
|
||||
"browserify": "~2.35.0",
|
||||
"grunt-browserify": "~1.2.9",
|
||||
"grunt-contrib-clean": "~0.5.0",
|
||||
"grunt-contrib-uglify": "~0.2.5"
|
||||
},
|
||||
"license": "Apache License",
|
||||
"dependencies": {
|
||||
"require-directory": "git://github.com/spenceralger/node-require-directory.git#master",
|
||||
"cli-color": "~0.2.3",
|
||||
"lodash": "~2.2.1",
|
||||
"tar": "~0.1.18"
|
||||
|
||||
@ -26,7 +26,25 @@ function transformFile(entry) {
|
||||
|
||||
// itterate all of the specs within the file, should only be one
|
||||
_.each(JSON.parse(entry.data), function (def, name) {
|
||||
//camelcase the name
|
||||
name = _.map(name.split('.'), _.camelCase).join('.');
|
||||
|
||||
var steps = name.split('.');
|
||||
|
||||
function transformParamKeys(note, param, key) {
|
||||
var cmlKey = _.camelCase(key);
|
||||
if (cmlKey !== key) {
|
||||
param.name = key;
|
||||
if (key.charAt(0) === '_') {
|
||||
cmlKey = '_' + cmlKey;
|
||||
}
|
||||
}
|
||||
note[cmlKey] = param;
|
||||
}
|
||||
|
||||
def.url.params = _.transform(def.url.params, transformParamKeys, {});
|
||||
def.url.parts = _.transform(def.url.parts, transformParamKeys, {});
|
||||
|
||||
var allParams = _.extend({}, def.url.params, def.url.parts);
|
||||
var spec = {
|
||||
name: name,
|
||||
@ -53,6 +71,7 @@ function transformFile(entry) {
|
||||
var optionalVars = {};
|
||||
var requiredVars = {};
|
||||
var param;
|
||||
var name;
|
||||
var target;
|
||||
var match;
|
||||
|
||||
@ -61,19 +80,16 @@ function transformFile(entry) {
|
||||
}
|
||||
|
||||
while (match = urlParamRE.exec(url)) {
|
||||
param = def.url.parts[match[1]] || {};
|
||||
name = _.camelCase(match[1]);
|
||||
param = def.url.parts[name] || {};
|
||||
target = (param.required || !param.default) ? requiredVars : optionalVars;
|
||||
target[match[1]] = _.omit(param, 'required');
|
||||
target[name] = _.omit(param, 'required', 'description', 'name');
|
||||
}
|
||||
|
||||
[requiredVars, optionalVars].forEach(function (vars) {
|
||||
_.each(vars, function (v, name) {
|
||||
vars[name] = _.omit(v, 'description');
|
||||
});
|
||||
});
|
||||
|
||||
return _.omit({
|
||||
fmt: url.replace(urlParamRE, '<%=$1%>'),
|
||||
fmt: url.replace(urlParamRE, function (full, match) {
|
||||
return '<%=' + _.camelCase(match) + '%>';
|
||||
}),
|
||||
opt: _.size(optionalVars) ? optionalVars : null,
|
||||
req: _.size(requiredVars) ? requiredVars : null,
|
||||
sortOrder: _.size(requiredVars) * -1
|
||||
@ -87,15 +103,14 @@ function transformFile(entry) {
|
||||
});
|
||||
|
||||
spec.params = _.transform(spec.params, function (note, param, name) {
|
||||
param.name = name;
|
||||
// param.name = name;
|
||||
note[name] = _.pick(param, [
|
||||
'type', 'default', 'options', 'required'
|
||||
'type', 'default', 'options', 'required', 'name'
|
||||
]);
|
||||
}, {});
|
||||
|
||||
// escape method names with "special" keywords
|
||||
var location = _.map(spec.name.split('.'), _.camelCase)
|
||||
.join('.prototype.')
|
||||
var location = spec.name.split('.').join('.prototype.')
|
||||
.replace(/(^|\.)(delete|default)(\.|$)/g, '[\'$2\']');
|
||||
|
||||
var action = {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
module.exports = {
|
||||
'cluster.node_hot_threads': [
|
||||
'cluster.nodeHotThreads': [
|
||||
'/_cluster/nodes/hotthreads',
|
||||
'/_cluster/nodes/hot_threads',
|
||||
'/_nodes/hot_threads',
|
||||
@ -7,7 +7,7 @@ module.exports = {
|
||||
'/_cluster/nodes/{node_id}/hot_threads',
|
||||
'/_nodes/{node_id}/hot_threads'
|
||||
],
|
||||
'cluster.node_info': [
|
||||
'cluster.nodeInfo': [
|
||||
'/_cluster/nodes',
|
||||
'/_nodes/settings',
|
||||
'/_nodes/os',
|
||||
@ -29,10 +29,10 @@ module.exports = {
|
||||
'/_nodes/{node_id}/http',
|
||||
'/_nodes/{node_id}/plugin'
|
||||
],
|
||||
'cluster.node_shutdown': [
|
||||
'cluster.nodeShutdown': [
|
||||
'/_cluster/nodes/_shutdown'
|
||||
],
|
||||
'cluster.node_stats': [
|
||||
'cluster.nodeStats': [
|
||||
'/_cluster/nodes/stats',
|
||||
'/_nodes/stats/{metric_family}',
|
||||
'/_nodes/stats/indices/{metric}/{fields}',
|
||||
@ -43,7 +43,7 @@ module.exports = {
|
||||
'get': [
|
||||
'/{index}/{type}/{id}/_source'
|
||||
],
|
||||
'indices.delete_mapping': [
|
||||
'indices.deleteMapping': [
|
||||
'/{index}/{type}/_mapping'
|
||||
],
|
||||
'indices.stats': [
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
/* jshint maxlen: false */
|
||||
|
||||
var ca = require('./client_action');
|
||||
var errors = require('./errors');
|
||||
|
||||
|
||||
@ -33,8 +33,9 @@ var es = require('../../../src/elasticsearch'),
|
||||
startingMoment = moment().startOf('day').subtract('days', days),
|
||||
endingMoment = moment().endOf('day').add('days', days),
|
||||
clientConfig = {
|
||||
maxSockets: 1000,
|
||||
log: {
|
||||
level: ['info', 'error']
|
||||
level: 'error'
|
||||
}
|
||||
};
|
||||
|
||||
@ -47,13 +48,13 @@ if (argv.host) {
|
||||
var client = new es.Client(clientConfig);
|
||||
var log = client.config.log;
|
||||
|
||||
log.info('Generating', count, 'events across ±', days, 'days');
|
||||
console.log('Generating', count, 'events across ±', days, 'days');
|
||||
|
||||
fillIndecies(function () {
|
||||
var actions = [],
|
||||
samples = makeSamples(startingMoment, endingMoment);
|
||||
|
||||
async.timesSeries(count, function (i, done) {
|
||||
async.times(count, function (i, done) {
|
||||
// random date, plus less random time
|
||||
var date = moment(samples.randomMsInDayRange())
|
||||
.utc()
|
||||
@ -175,7 +176,7 @@ function fillIndecies(cb) {
|
||||
movingDate.add('day', 1);
|
||||
}
|
||||
|
||||
async.parralel(indexPushActions, function (err, responses) {
|
||||
async.parallel(indexPushActions, function (err, responses) {
|
||||
if (err) {
|
||||
client.config.log.error(err.message = 'Unable to create indicies: ' + err.message);
|
||||
} else {
|
||||
|
||||
@ -44,5 +44,7 @@ async.series([
|
||||
});
|
||||
}
|
||||
], function (err) {
|
||||
if (err) console.error(err);
|
||||
if (err) {
|
||||
console.error(err);
|
||||
}
|
||||
});
|
||||
|
||||
44
src/elasticsearch.angular.js
Normal file
44
src/elasticsearch.angular.js
Normal file
@ -0,0 +1,44 @@
|
||||
/**
|
||||
* Wrapper for the elasticsearch.js client, which will register the client constructor
|
||||
* as a factory within angular that can be easily injected with Angular's awesome DI.
|
||||
*
|
||||
* It will also instruct the client to use Angular's $http service for it's ajax requests
|
||||
*/
|
||||
var AngularConnector = require('./lib/connectors/angular');
|
||||
var Transport = require('./lib/transport');
|
||||
var Client = require('./lib/client');
|
||||
|
||||
/* global angular */
|
||||
angular.module('elasticsearch.client', [])
|
||||
.factory('esFactory', ['$http', '$q', function ($http, $q) {
|
||||
|
||||
AngularConnector.prototype.$http = $http;
|
||||
|
||||
// store the original request function
|
||||
Transport.prototype._request = Transport.prototype.request;
|
||||
|
||||
// overwrite the request function to return a promise
|
||||
// and support the callback
|
||||
Transport.prototype.request = function (params, cb) {
|
||||
var deferred = $q.defer();
|
||||
this._request(params, function (err, body, status) {
|
||||
if (typeof cb === 'function') {
|
||||
cb(err, body, status);
|
||||
}
|
||||
|
||||
if (err) {
|
||||
deferred.reject(err);
|
||||
} else {
|
||||
deferred.resolve({ body: body, status: status });
|
||||
}
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
return function (config) {
|
||||
config = config || {};
|
||||
config.connectionClass = AngularConnector;
|
||||
return new Client(config);
|
||||
};
|
||||
}]);
|
||||
902
src/lib/api.js
902
src/lib/api.js
File diff suppressed because it is too large
Load Diff
@ -149,7 +149,11 @@ function exec(transport, spec, params, cb) {
|
||||
|
||||
params.body && (request.body = params.body);
|
||||
params.ignore && (request.ignore = _.isArray(params.ignore) ? params.ignore : [params.ignore]);
|
||||
params.timeout && (request.ignore = _.isArray(params.ignore) ? params.ignore : [params.ignore]);
|
||||
if (params.timeout === void 0) {
|
||||
request.timeout = 10000;
|
||||
} else {
|
||||
request.timeout = params.timeout;
|
||||
}
|
||||
|
||||
// copy over some properties from the spec
|
||||
spec.bulkBody && (request.bulkBody = true);
|
||||
@ -227,5 +231,5 @@ function exec(transport, spec, params, cb) {
|
||||
|
||||
request.query = query;
|
||||
|
||||
transport.request(request, cb);
|
||||
return transport.request(request, cb);
|
||||
}
|
||||
|
||||
@ -9,9 +9,26 @@ module.exports = ClientConfig;
|
||||
var url = require('url');
|
||||
var _ = require('./utils');
|
||||
var Host = require('./host');
|
||||
var selectors = _.reKey(_.requireDir(module, './selectors'), _.camelCase);
|
||||
var connections = _.requireClasses(module, './connections');
|
||||
var serializers = _.requireClasses(module, './serializers');
|
||||
var selectors = require('./selectors');
|
||||
|
||||
var connectors = {};
|
||||
if (process.browser) {
|
||||
connectors.Xhr = require('./connectors/xhr');
|
||||
connectors.Angular = require('./connectors/angular');
|
||||
connectors.jQuery = require('./connectors/jquery');
|
||||
} else {
|
||||
connectors.Http = require('./connectors/http');
|
||||
}
|
||||
|
||||
_.each(connectors, function (conn, name) {
|
||||
if (typeof conn !== 'function') {
|
||||
delete connectors[name];
|
||||
}
|
||||
});
|
||||
|
||||
var serializers = {
|
||||
Json: require('./serializers/json')
|
||||
};
|
||||
|
||||
var extractHostPartsRE = /\[([^:]+):(\d+)]/;
|
||||
var hostProtocolRE = /^([a-z]+:)?\/\//;
|
||||
@ -31,7 +48,7 @@ var defaultConfig = {
|
||||
protocol: 'http'
|
||||
}
|
||||
],
|
||||
connectionClass: connections.Http,
|
||||
connectionClass: process.browser ? connectors.Xhr : connectors.Http,
|
||||
selector: selectors.roundRobin,
|
||||
sniffOnStart: false,
|
||||
sniffAfterRequests: null,
|
||||
@ -59,16 +76,23 @@ var defaultConfig = {
|
||||
}
|
||||
};
|
||||
|
||||
// remove connector classes that were not included in the build
|
||||
connectors = _.transform(connectors, function (note, connector, name) {
|
||||
if (connector) {
|
||||
note[name] = connector;
|
||||
}
|
||||
}, {});
|
||||
|
||||
function ClientConfig(config) {
|
||||
_.extend(this, defaultConfig, config);
|
||||
|
||||
// validate connectionClass
|
||||
if (typeof this.connectionClass !== 'function') {
|
||||
if (typeof connections[this.connectionClass] === 'function') {
|
||||
this.connectionClass = connections[this.connectionClass];
|
||||
if (typeof connectors[this.connectionClass] === 'function') {
|
||||
this.connectionClass = connectors[this.connectionClass];
|
||||
} else {
|
||||
throw new TypeError('Invalid connectionClass ' + this.connectionClass + '. ' +
|
||||
'Expected a constructor or one of ' + _.keys(connections).join(', '));
|
||||
throw new TypeError('Invalid connectionClass "' + this.connectionClass + '". ' +
|
||||
'Expected a constructor or one of ' + _.keys(connectors).join(', '));
|
||||
}
|
||||
}
|
||||
|
||||
@ -77,7 +101,7 @@ function ClientConfig(config) {
|
||||
if (_.has(selectors, this.selector)) {
|
||||
this.selector = selectors[this.selector];
|
||||
} else {
|
||||
throw new TypeError('Invalid Selector ' + this.selector + '. ' +
|
||||
throw new TypeError('Invalid Selector "' + this.selector + '". ' +
|
||||
'Expected a function or one of ' + _.keys(selectors).join(', '));
|
||||
}
|
||||
}
|
||||
@ -108,7 +132,7 @@ ClientConfig.prototype.prepareHosts = function (hosts) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Shutdown the connections, log outputs, and clear timers
|
||||
* Shutdown the connectionPool, log outputs, and clear timers
|
||||
*/
|
||||
ClientConfig.prototype.close = function () {
|
||||
this.log.close();
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
module.exports = ConnectionAbstract;
|
||||
|
||||
var _ = require('./utils'),
|
||||
EventEmitter = require('events').EventEmitter;
|
||||
var _ = require('./utils');
|
||||
var EventEmitter = require('events').EventEmitter;
|
||||
|
||||
/**
|
||||
* Abstract class used for Connection classes
|
||||
|
||||
@ -9,8 +9,7 @@
|
||||
module.exports = ConnectionPool;
|
||||
|
||||
var _ = require('./utils');
|
||||
var selectors = _.reKey(_.requireDir(module, './selectors'), _.camelCase);
|
||||
var connectors = _.reKey(_.requireDir(module, './connections'), _.studlyCase);
|
||||
var selectors = require('./selectors');
|
||||
var EventEmitter = require('events').EventEmitter;
|
||||
var errors = require('./errors');
|
||||
var Host = require('./host');
|
||||
@ -31,7 +30,7 @@ ConnectionPool.prototype.select = function (cb) {
|
||||
this.config.selector(this.connections.alive, cb);
|
||||
} else {
|
||||
try {
|
||||
cb(null, this.config.selector(this.connections.alive));
|
||||
_.nextTick(cb, null, this.config.selector(this.connections.alive));
|
||||
} catch (e) {
|
||||
this.config.log.error(e);
|
||||
cb(e);
|
||||
|
||||
15
src/lib/connections/angular.js
vendored
15
src/lib/connections/angular.js
vendored
@ -1,15 +0,0 @@
|
||||
/**
|
||||
* Connection that registers a module with angular, using angular's $http service
|
||||
* to communicate with ES.
|
||||
*
|
||||
* @class connections.Angular
|
||||
*/
|
||||
module.exports = AngularConnection;
|
||||
|
||||
var _ = require('../utils'),
|
||||
ConnectionAbstract = require('../connection');
|
||||
|
||||
function AngularConnection() {
|
||||
|
||||
}
|
||||
_.inherits(AngularConnection, ConnectionAbstract);
|
||||
38
src/lib/connectors/angular.js
vendored
Normal file
38
src/lib/connectors/angular.js
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Connection that registers a module with angular, using angular's $http service
|
||||
* to communicate with ES.
|
||||
*
|
||||
* @class connections.Angular
|
||||
*/
|
||||
module.exports = AngularConnection;
|
||||
|
||||
var _ = require('../utils');
|
||||
var ConnectionAbstract = require('../connection');
|
||||
var ConnectionFault = require('../errors').ConnectionFault;
|
||||
|
||||
/* global angular */
|
||||
|
||||
function AngularConnection(host, config) {
|
||||
ConnectionAbstract.call(this, host, config);
|
||||
}
|
||||
_.inherits(AngularConnection, ConnectionAbstract);
|
||||
|
||||
AngularConnection.prototype.request = function (params, cb) {
|
||||
var timeoutId;
|
||||
|
||||
this.$http({
|
||||
method: params.method,
|
||||
url: this.host.makeUrl(params),
|
||||
data: params.body,
|
||||
cache: false,
|
||||
timeout: params.timeout !== Infinity ? params.timeout : 0
|
||||
}).then(function (response) {
|
||||
cb(null, response.data, response.status);
|
||||
}, function (err) {
|
||||
cb(new ConnectionFault(err.message));
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
// must be overwritten before this connection can be used
|
||||
AngularConnection.prototype.$http = null;
|
||||
@ -9,11 +9,11 @@ module.exports = XhrConnection;
|
||||
|
||||
var _ = require('../utils');
|
||||
var ConnectionAbstract = require('../connection');
|
||||
var ConnectionError = require('../errors').ConnectionError;
|
||||
var TimeoutError = require('../errors').TimeoutError;
|
||||
var ConnectionFault = require('../errors').ConnectionFault;
|
||||
var TimeoutError = require('../errors').RequestTimeout;
|
||||
|
||||
function XhrConnection(config, nodeInfo) {
|
||||
ConnectionAbstract.call(this, config, nodeInfo);
|
||||
function XhrConnection(host, config) {
|
||||
ConnectionAbstract.call(this, host, config);
|
||||
}
|
||||
_.inherits(XhrConnection, ConnectionAbstract);
|
||||
|
||||
@ -49,17 +49,17 @@ if (!getXhr) {
|
||||
XhrConnection.prototype.request = function (params, cb) {
|
||||
var xhr = getXhr();
|
||||
var timeoutId;
|
||||
|
||||
var url = this.host.makeUrl(params);
|
||||
if (params.auth) {
|
||||
xhr.open(params.method, params.url, true, params.auth.user, params.auth.pass);
|
||||
xhr.open(params.method, url, true, params.auth.user, params.auth.pass);
|
||||
} else {
|
||||
xhr.open(params.method, params.url, true);
|
||||
xhr.open(params.method, url, true);
|
||||
}
|
||||
|
||||
xhr.onreadystatechange = function (e) {
|
||||
if (xhr.readyState === 4) {
|
||||
clearTimeout(timeoutId);
|
||||
cb(xhr.status ? null : new ConnectionError(), xhr.responseText, xhr.status);
|
||||
cb(xhr.status ? null : new ConnectionFault(), xhr.responseText, xhr.status);
|
||||
}
|
||||
};
|
||||
|
||||
@ -49,17 +49,48 @@ Host.prototype = {
|
||||
port: 9200,
|
||||
auth: '',
|
||||
path: '',
|
||||
query: {}
|
||||
query: false
|
||||
};
|
||||
|
||||
Host.prototype.toUrl = function (path, query) {
|
||||
if (query) {
|
||||
query = '?' + qs.stringify(_.defaults(typeof query === 'string' ? qs.parse(query) : query, this.query));
|
||||
} else {
|
||||
query = '';
|
||||
Host.prototype.makeUrl = function (params) {
|
||||
params = params || {};
|
||||
// build the port
|
||||
var port = '';
|
||||
if (this.port !== defaultPort[this.protocol]) {
|
||||
// add an actual port
|
||||
port = ':' + this.port;
|
||||
}
|
||||
|
||||
return this.protocol + '://' +
|
||||
this.host + (this.port !== defaultPort[this.protocol] ? ':' + this.port : '') +
|
||||
'/' + this.path + (path || '') + query;
|
||||
// build the path
|
||||
var path = '';
|
||||
// add the path prefix if set
|
||||
if (this.path) {
|
||||
path += this.path;
|
||||
}
|
||||
// then the path from the params
|
||||
if (params.path) {
|
||||
path += params.path;
|
||||
}
|
||||
// if we still have a path, and it doesn't start with '/' add it.
|
||||
if (path && path.charAt(0) !== '/') {
|
||||
path = '/' + path;
|
||||
}
|
||||
|
||||
// build the query string
|
||||
var query = '';
|
||||
if (params.query) {
|
||||
// if the user passed in a query, merge it with the defaults from the host
|
||||
query = qs.stringify(
|
||||
_.defaults(typeof params.query === 'string' ? qs.parse(params.query) : params.query, this.query)
|
||||
);
|
||||
} else if (this.query) {
|
||||
// just stringify the hosts query
|
||||
query = qs.stringify(this.query);
|
||||
}
|
||||
// prepend the ? if there is actually a valid query string
|
||||
if (query) {
|
||||
query = '?' + query;
|
||||
}
|
||||
|
||||
return this.protocol + '://' + this.host + port + path + query;
|
||||
};
|
||||
|
||||
@ -1,6 +1,17 @@
|
||||
var _ = require('./utils'),
|
||||
url = require('url'),
|
||||
EventEmitter = require('events').EventEmitter;
|
||||
var _ = require('./utils');
|
||||
var url = require('url');
|
||||
var EventEmitter = require('events').EventEmitter;
|
||||
if (process.browser) {
|
||||
var loggers = {
|
||||
Console: require('./loggers/console')
|
||||
};
|
||||
} else {
|
||||
var loggers = {
|
||||
File: require('./loggers/file'),
|
||||
Stream: require('./loggers/file'),
|
||||
Stdio: require('./loggers/stdio')
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Log bridge, which is an [EventEmitter](http://nodejs.org/api/events.html#events_class_events_eventemitter)
|
||||
@ -20,7 +31,7 @@ function Log(config) {
|
||||
this.config = config || {};
|
||||
|
||||
var i;
|
||||
var output = config.log || 2;
|
||||
var output = _.isPlainObject(config.log) ? config.log : 'warning';
|
||||
|
||||
if (_.isString(output) || _.isFinite(output)) {
|
||||
output = [
|
||||
@ -170,15 +181,19 @@ Log.prototype.addOutput = function (config) {
|
||||
var levels = Log.parseLevels(config.levels || config.level || 'warning');
|
||||
|
||||
_.defaults(config || {}, {
|
||||
type: 'stdio',
|
||||
type: process.browser ? 'Console' : 'Stdio',
|
||||
});
|
||||
|
||||
// force the levels config
|
||||
delete config.level;
|
||||
config.levels = levels;
|
||||
|
||||
var Logger = require('./loggers/' + config.type);
|
||||
var Logger = loggers[config.type];
|
||||
if (Logger) {
|
||||
return new Logger(config, this);
|
||||
} else {
|
||||
throw new Error('Invalid logger type "' + config.type + '". Expected one of ' + _.keys(loggers).join(', '));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
103
src/lib/loggers/console.js
Normal file
103
src/lib/loggers/console.js
Normal file
@ -0,0 +1,103 @@
|
||||
/**
|
||||
* Special version of the Stream logger, which logs errors and warnings to stderr and all other
|
||||
* levels to stdout.
|
||||
*
|
||||
* @class Loggers.Console
|
||||
* @extends LoggerAbstract
|
||||
* @constructor
|
||||
* @param {Object} config - The configuration for the Logger
|
||||
* @param {string} config.level - The highest log level for this logger to output.
|
||||
* @param {Log} bridge - The object that triggers logging events, which we will record
|
||||
*/
|
||||
|
||||
module.exports = Console;
|
||||
|
||||
var LoggerAbstract = require('../logger');
|
||||
var _ = require('../utils');
|
||||
|
||||
function Console(config, bridge) {
|
||||
LoggerAbstract.call(this, config, bridge);
|
||||
|
||||
// config/state
|
||||
this.color = _.has(config, 'color') ? !!config.color : true;
|
||||
}
|
||||
_.inherits(Console, LoggerAbstract);
|
||||
|
||||
/**
|
||||
* Override the LoggerAbstract's setup listeners to do a little extra setup
|
||||
*
|
||||
* @param {Array} levels - The levels that we should be listeneing for
|
||||
*/
|
||||
Console.prototype.setupListeners = function (levels) {
|
||||
// since some of our functions are bound a bit differently (to the console)
|
||||
// create some of the bound properties manually
|
||||
this.bound.onWarning = this.onWarning;
|
||||
this.bound.onInfo = this.onInfo;
|
||||
this.bound.onDebug = this.onDebug;
|
||||
|
||||
// call the super method
|
||||
LoggerAbstract.prototype.setupListeners.call(this, levels);
|
||||
};
|
||||
|
||||
/**
|
||||
* Handler for the bridges "error" event
|
||||
*
|
||||
* @method onError
|
||||
* @private
|
||||
* @param {Error} e - The Error object to log
|
||||
* @return {undefined}
|
||||
*/
|
||||
Console.prototype.onError = _.handler(function (e) {
|
||||
if (console.error && console.trace) {
|
||||
console.error(e.name === 'Error' ? 'ERROR' : e.name);
|
||||
console.trace();
|
||||
} else {
|
||||
console.log(e.name === 'Error' ? 'ERROR' : e.name, e.stack);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Handler for the bridges "warning" event
|
||||
*
|
||||
* @method onWarning
|
||||
* @private
|
||||
* @param {String} msg - The message to be logged
|
||||
* @return {undefined}
|
||||
*/
|
||||
Console.prototype.onWarning = console[console.warn ? 'warn' : 'log'].bind(console, 'WARNING');
|
||||
|
||||
/**
|
||||
* Handler for the bridges "info" event
|
||||
*
|
||||
* @method onInfo
|
||||
* @private
|
||||
* @param {String} msg - The message to be logged
|
||||
* @return {undefined}
|
||||
*/
|
||||
Console.prototype.onInfo = console[console.info ? 'info' : 'log'].bind(console, 'INFO');
|
||||
|
||||
/**
|
||||
* Handler for the bridges "debug" event
|
||||
*
|
||||
* @method onDebug
|
||||
* @private
|
||||
* @param {String} msg - The message to be logged
|
||||
* @return {undefined}
|
||||
*/
|
||||
Console.prototype.onDebug = console[console.debug ? 'debug' : 'log'].bind(console, 'DEBUG');
|
||||
|
||||
/**
|
||||
* Handler for the bridges "trace" event
|
||||
*
|
||||
* @method onTrace
|
||||
* @private
|
||||
* @return {undefined}
|
||||
*/
|
||||
Console.prototype.onTrace = _.handler(function (method, url, body, responseBody, responseStatus) {
|
||||
var message = 'curl "' + url.replace(/"/g, '\\"') + '" -X' + method.toUpperCase();
|
||||
if (body) {
|
||||
message += ' -d "' + body.replace(/"/g, '\\"') + '"';
|
||||
}
|
||||
message += '\n<- ' + responseStatus + '\n' + responseBody;
|
||||
console.log('TRACE', message);
|
||||
});
|
||||
4
src/lib/selectors/index.js
Normal file
4
src/lib/selectors/index.js
Normal file
@ -0,0 +1,4 @@
|
||||
module.exports = {
|
||||
random: require('./random'),
|
||||
roundRobin: require('./round_robin')
|
||||
};
|
||||
@ -45,6 +45,7 @@ TransportRequest.prototype._startRequest = function () {
|
||||
}
|
||||
|
||||
params.req = {
|
||||
timeout: params.timeout,
|
||||
path: params.path,
|
||||
query: params.query,
|
||||
method: params.method,
|
||||
|
||||
105
src/lib/utils.js
105
src/lib/utils.js
@ -1,7 +1,5 @@
|
||||
var path = require('path'),
|
||||
_ = require('lodash'),
|
||||
fs = require('fs'),
|
||||
requireDir = require('require-directory'),
|
||||
nodeUtils = require('util');
|
||||
|
||||
/**
|
||||
@ -32,37 +30,11 @@ utils.inspect = function (thing, opts) {
|
||||
*/
|
||||
utils.joinPath = path.join;
|
||||
|
||||
/**
|
||||
* Require all of the modules in a directory
|
||||
*
|
||||
* @method requireDir
|
||||
* @param {Function} module - The module object which will own the required modules.
|
||||
* @param {String} path - Path to the directory which will be traversed (can be relative to module)
|
||||
* @return {Object} - An object with each required files
|
||||
*/
|
||||
utils.requireDir = function (module, dirPath) {
|
||||
if (dirPath && dirPath[0] === '.') {
|
||||
dirPath = path.join(path.dirname(module.filename), dirPath);
|
||||
}
|
||||
return requireDir(module, dirPath);
|
||||
};
|
||||
|
||||
/**
|
||||
* Requires all of the files in a directory, then transforms the filenames into
|
||||
* StudlyCase -- one level deep for now.
|
||||
* @param {Function} module - The module object which will own the required modules.
|
||||
* @param {String} dirPath - Path to the directory which will be traversed (can be relative to module)
|
||||
* @return {Object} - An object with each required files, keys will be the StudlyCase version of the filenames.
|
||||
*/
|
||||
utils.requireClasses = function (module, dirPath) {
|
||||
return utils.reKey(utils.requireDir(module, dirPath), utils.studlyCase, false);
|
||||
};
|
||||
|
||||
/**
|
||||
* Recursively re-key an object, applying "transform" to each key
|
||||
* @param {Object} obj - The object to re-key
|
||||
* @param {Function} transform - The transformation function to apply to each key
|
||||
* @param {Boolean} [recursive=false] - Should this act recursively?
|
||||
* @param {Boolean} [recursive=true] - Should this act recursively?
|
||||
* @param {Object} out - used primarily for recursion, allows you to specify the object which new keys will be written to
|
||||
* @return {Object}
|
||||
*/
|
||||
@ -141,6 +113,53 @@ utils.ucfirst = function (word) {
|
||||
return word[0].toUpperCase() + word.substring(1).toLowerCase();
|
||||
};
|
||||
|
||||
/**
|
||||
* Base algo for studlyCase and camelCase
|
||||
* @param {boolean} firstWordCap - Should the first character of the first word be capitalized
|
||||
* @return {Function}
|
||||
*/
|
||||
function adjustWordCase(firstWordCap, otherWordsCap, sep) {
|
||||
return function (string) {
|
||||
var inWord = false;
|
||||
var i = 0;
|
||||
var words = [];
|
||||
var word = '';
|
||||
var code, c, upper, lower;
|
||||
|
||||
for (; i < string.length; i++) {
|
||||
code = string.charCodeAt(i);
|
||||
c = string.charAt(i);
|
||||
lower = code >= 97 && code <= 122;
|
||||
upper = code >= 65 && code <= 90;
|
||||
|
||||
if (upper || !lower) {
|
||||
// new word
|
||||
if (word.length) {
|
||||
words.push(word);
|
||||
}
|
||||
word = '';
|
||||
}
|
||||
|
||||
if (upper || lower) {
|
||||
if (lower && word.length) {
|
||||
word += c;
|
||||
} else {
|
||||
if ((!words.length && firstWordCap) || (words.length && otherWordsCap)) {
|
||||
word = c.toUpperCase();
|
||||
}
|
||||
else {
|
||||
word = c.toLowerCase();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (word.length) {
|
||||
words.push(word);
|
||||
}
|
||||
return words.join(sep);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform a string into StudlyCase
|
||||
*
|
||||
@ -149,29 +168,27 @@ utils.ucfirst = function (word) {
|
||||
* @param {String} string
|
||||
* @return {String}
|
||||
*/
|
||||
utils.studlyCase = function (string) {
|
||||
return _.map(string.split(/\b|_/), function (word, i) {
|
||||
return word.match(/^[a-z]+$/i) ? utils.ucfirst(word) : '';
|
||||
}).join('');
|
||||
};
|
||||
utils.studlyCase = adjustWordCase(true, true, '');
|
||||
|
||||
/**
|
||||
* Transform a string into camelCase
|
||||
*
|
||||
* @todo Tests
|
||||
* @method cameCase
|
||||
* @method camelCase
|
||||
* @param {String} string
|
||||
* @return {String}
|
||||
*/
|
||||
utils.camelCase = function (string) {
|
||||
return _.map(string.split(/\b|_/), function (word, i) {
|
||||
if (word.match(/^[a-z]+$/i)) {
|
||||
return i === 0 ? word.toLowerCase() : utils.ucfirst(word);
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}).join('');
|
||||
};
|
||||
utils.camelCase = adjustWordCase(false, true, '');
|
||||
|
||||
/**
|
||||
* Transform a string into snakeCase
|
||||
*
|
||||
* @todo Tests
|
||||
* @method snakeCase
|
||||
* @param {String} string
|
||||
* @return {String}
|
||||
*/
|
||||
utils.snakeCase = adjustWordCase(false, false, '_');
|
||||
|
||||
/**
|
||||
* Lower-case a string, and return an empty string if any is not a string
|
||||
|
||||
@ -118,21 +118,43 @@ describe('Utils', function () {
|
||||
|
||||
describe('#camelCase', function () {
|
||||
it('find spaces, underscores, and other natural word breaks', function () {
|
||||
expect(_.camelCase('Neil PatRICK hArris-is_a.dog')).to.eql('neilPatrickHarrisIsADog');
|
||||
expect(_.camelCase('Neil Patrick.Harris-is_a.dog')).to.eql('neilPatrickHarrisIsADog');
|
||||
});
|
||||
|
||||
it('ignores abreviations', function () {
|
||||
expect(_.camelCase('JSON_parser')).to.eql('jsonParser');
|
||||
expect(_.camelCase('Json_parser')).to.eql('jsonParser');
|
||||
});
|
||||
|
||||
it('handles trailing _', function () {
|
||||
expect(_.camelCase('_thing_one_')).to.eql('thingOne');
|
||||
});
|
||||
});
|
||||
|
||||
describe('#studlyCase', function () {
|
||||
it('find spaces, underscores, and other natural word breaks', function () {
|
||||
expect(_.studlyCase('Neil PatRICK hArris-is_a.dog')).to.eql('NeilPatrickHarrisIsADog');
|
||||
expect(_.studlyCase('Neil Patrick.Harris-is_a.dog')).to.eql('NeilPatrickHarrisIsADog');
|
||||
});
|
||||
|
||||
it('ignores abreviations', function () {
|
||||
expect(_.studlyCase('JSON_parser')).to.eql('JsonParser');
|
||||
expect(_.studlyCase('Json_parser')).to.eql('JsonParser');
|
||||
});
|
||||
|
||||
it('handles trailing _', function () {
|
||||
expect(_.studlyCase('_thing_one_')).to.eql('ThingOne');
|
||||
});
|
||||
});
|
||||
|
||||
describe('#snakeCase', function () {
|
||||
it('find spaces, underscores, and other natural word breaks', function () {
|
||||
expect(_.snakeCase('Neil Patrick.Harris-is_a.dog')).to.eql('neil_patrick_harris_is_a_dog');
|
||||
});
|
||||
|
||||
it('ignores abreviations', function () {
|
||||
expect(_.snakeCase('Json_parser')).to.eql('json_parser');
|
||||
});
|
||||
|
||||
it('handles trailing _', function () {
|
||||
expect(_.snakeCase('_thing_one_')).to.eql('thing_one');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user