Skip to content

Commit

Permalink
Implemented stricter JSHint'ing and fixed the problems caused by it.
Browse files Browse the repository at this point in the history
  • Loading branch information
Chris Sainty committed Dec 19, 2011
1 parent 5beabcf commit f4085c1
Show file tree
Hide file tree
Showing 5 changed files with 150 additions and 71 deletions.
33 changes: 17 additions & 16 deletions lib/HiLoKeyGenerator.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ function HiLoKeyGenerator(options) {
* @param {string} entityName The name of the entities we are generating keys for
* @param {Function(error, key)} callback Callback which provides the generated key
*/
HiLoKeyGenerator.prototype.generateDocumentKey = function(entityName, callback) {
HiLoKeyGenerator.prototype.generateDocumentKey = function (entityName, callback) {
var self = this;
self.nextId(entityName, function(error, id) {
self.nextId(entityName, function (error, id) {
if (error) { return callback(error, null); }

callback(undefined, entityName + self.keySeparator + id);
Expand All @@ -47,27 +47,28 @@ HiLoKeyGenerator.prototype.generateDocumentKey = function(entityName, callback)
* @param {string} entityName The name of the entities we are generating keys for
* @param {Function(error, id)} callback Callback which provides the generated id
*/
HiLoKeyGenerator.prototype.nextId = function(entityName, callback) {
var self = this;
HiLoKeyGenerator.prototype.nextId = function (entityName, callback) {
var self = this,
generator;
if (!self.entityGenerators[entityName]) {
// First time generating this entity, create a placeholder document before fetching it from the server.
self.entityGenerators[entityName] = { lastId: 0, currentMax: 0 };
}

// Increment our current then validate against the max
var generator = self.entityGenerators[entityName];
generator = self.entityGenerators[entityName];
generator.lastId += 1;
if (generator.lastId > generator.currentMax) {
// We have exceeded the currently assigned limit, get a new limit
self.getNextMax(entityName, function(error) {
self.getNextMax(entityName, function (error) {
if (error) { return callback(error); }

generator.lastId += 1;
callback(undefined, generator.lastId);
});
} else {
// We are still in range, so just send it back
callback(undefined, generator.lastId);
callback(undefined, generator.lastId);
}
};

Expand All @@ -76,33 +77,33 @@ HiLoKeyGenerator.prototype.nextId = function(entityName, callback) {
* @param {string} entityName The name of the entities we are generating keys for
* @param {Function(error)} callback Callback to indicate we have queried the server and are ready to generate more keys
*/
HiLoKeyGenerator.prototype.getNextMax = function(entityName, callback) {
HiLoKeyGenerator.prototype.getNextMax = function (entityName, callback) {
var self = this;

self.client.getDocument(self.documentPrefix + entityName, function(error, result, doc) {
self.client.getDocument(self.documentPrefix + entityName, function (error, result, doc) {
if (error) { return callback(error); }

if (doc) {
if (doc.ServerHi) {
// We have the older format ServerHi document, convert to the new Max which supports changing capacity
doc.max = (doc.ServerHi - 1) * self.capacity;
doc.ServerHi= undefined;
doc.ServerHi = undefined;
}

var lastMax = doc.max;
doc.max += self.capacity;
self.client.putDocument(self.documentPrefix + entityName, doc, function(error, result, ok) {
self.client.putDocument(self.documentPrefix + entityName, doc, function (error, result, ok) {
if (error) { return callback(error); }
if (!ok) { return callback(new Error('Unable to update HiLO metadata')); }

self.entityGenerators[entityName].currentMax = doc.max;
self.entityGenerators[entityName].lastId = lastMax;
callback(undefined);
});
});
} else {
doc = { max: self.capacity };
self.client.putDocument(self.documentPrefix + entityName, doc, function(error, result, ok) {
if (error) return callback(error);
self.client.putDocument(self.documentPrefix + entityName, doc, function (error, result, ok) {
if (error) { return callback(error); }
if (!ok) { return callback(new Error('Unable to update HiLoKeyGenerator metadata')); }

self.entityGenerators[entityName].currentMax = doc.max;
Expand All @@ -114,8 +115,8 @@ HiLoKeyGenerator.prototype.getNextMax = function(entityName, callback) {
});
};

function generator(options){
function generator(options) {
return new HiLoKeyGenerator(options);
}

module.exports = generator;
module.exports = generator;
73 changes: 38 additions & 35 deletions lib/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,34 +4,34 @@
* MIT License
*
* RavenDb client for node
*
*
* options:
* server_url - The URL for the server, including multi-tenant path if applicable
*/

var ravenHttpClient = require('./ravenhttpclient'),
qs = require('querystring');

function Client (options) {
if (typeof options === 'string') options = { 'server_url' : options };
function Client(options) {
if (typeof options === 'string') { options = { 'server_url' : options }; }

for (var i in options) {
this[i] = options[i];
}
}
this.httpClient = ravenHttpClient({ server_url: this.server_url });

if (!this.keyGenerator) this.keyGenerator= require('./hilokeygenerator')({ client: this });
if (!this.keyGenerator) { this.keyGenerator = require('./hilokeygenerator')({ client: this }); }
}

/**
* Fetch a document, by key, from the server
* @param {string} key Document key to fetch
* @param {Function(error, response, document)} callback Callback function, received error, server response and the document
*/
Client.prototype.getDocument = function(key, callback){
Client.prototype.getDocument = function (key, callback) {
var self = this;
self.httpClient.get('docs/' + key, null, function(error, result){
callback(error, result, result.statusCode == 200 ? result.asJson() : null);
self.httpClient.get('docs/' + key, null, function (error, result) {
callback(error, result, result.statusCode === 200 ? result.asJson() : null);
});
};

Expand All @@ -41,10 +41,10 @@ Client.prototype.getDocument = function(key, callback){
* @param {object} doc Hash representing the document
* @param {Function(error, response, success)} callback Callback function. Receives error, server response and boolean success
*/
Client.prototype.putDocument = function(key, doc, callback){
Client.prototype.putDocument = function (key, doc, callback) {
var self = this;
self.httpClient.put('docs/' + key, null, doc, function (error, result) {
callback(error, result, result.statusCode == 201);
callback(error, result, result.statusCode === 201);
});
};

Expand All @@ -54,24 +54,24 @@ Client.prototype.putDocument = function(key, doc, callback){
* @param {object} options Hash of query options. { query: <Hash of fields to query>, waitForNonStaleResults : boolean, }
* @param {Function(error, response, results)} callback Callback function. Receives error, server response, query results.
*/
Client.prototype.queryIndex = function(indexName, options, callback) {
var self = this;
var queryOptions = {
'query' : self.buildRavenQuery(options.query)
};
self.httpClient.get('indexes/' + indexName, queryOptions, function(error, result) {
Client.prototype.queryIndex = function (indexName, options, callback) {
var self = this,
queryOptions = {
'query' : self.buildRavenQuery(options.query)
};
self.httpClient.get('indexes/' + indexName, queryOptions, function (error, result) {
// Optionally request a non-stale index
if (!error && result.statusCode === 200 && options.waitForNonStaleResults) {
var data = result.asJson();
if (data.IsStale) {
return setTimeout(function() {
return setTimeout(function () {
self.queryIndex(indexName, options, callback);
}, 500);
} else {
return callback(error, result, data);
return callback(error, result, data);
}
}
callback(error, result, result.statusCode == 200 ? result.asJson() : null);
callback(error, result, result.statusCode === 200 ? result.asJson() : null);
});
};

Expand All @@ -80,11 +80,11 @@ Client.prototype.queryIndex = function(indexName, options, callback) {
/**
* Fetch a list of database names from the server
* @param {Function(error, response, results)} callback Callback function. Receives error, server response, array of databases.
*/
Client.prototype.getDatabaseNames = function(callback) {
*/
Client.prototype.getDatabaseNames = function (callback) {
var self = this;
self.httpClient.get('/databases', null, function(error, result){
callback(error, result, result.statusCode == 200 ? result.asJson() : null);
self.httpClient.get('/databases', null, function (error, result) {
callback(error, result, result.statusCode === 200 ? result.asJson() : null);
});
};

Expand All @@ -93,13 +93,15 @@ Client.prototype.getDatabaseNames = function(callback) {
* @param {string} name Name of the database to check/create
* @param {Function(error, response, success)} callback Callback function. Receives error, server response, boolean success
*/
Client.prototype.ensureDatabaseExists = function(name, callback) {
var self = this;
Client.prototype.ensureDatabaseExists = function (name, callback) {
var self = this,
docId,
doc;

if (name.search(/[\/\\"'<>]/) !== -1) { return callback(new Error('Database name is invalid'), null, false); } // Invalid database name
if (name.search(/[\/\\"'<>]/) !== -1) { return callback(new Error('Database name is invalid'), null, false); } // Invalid database name

var docId = 'Raven/Databases/' + name;
var doc = { 'Settings' : { "Raven/DataDir" : "~/Tenants/" + name } };
docId = 'Raven/Databases/' + name;
doc = { 'Settings' : { "Raven/DataDir" : "~/Tenants/" + name } };
self.getDocument(docId, function (error, result, data) {
if (error) { return callback(error, result, false); } // Error connecting to server
if (data) { return callback(error, result, true); } // Document and therefore database already exists
Expand All @@ -117,9 +119,9 @@ Client.prototype.ensureDatabaseExists = function(name, callback) {
* @param {object} entity The document whose key is being generated
* @param {Function(error, entity, key)} callback Callback function. Receives error, the document, the new key
*/
Client.prototype.generateDocumentKey = function(entityName, entity, callback) {
Client.prototype.generateDocumentKey = function (entityName, entity, callback) {
var self = this;
self.keyGenerator.generateDocumentKey(entityName, function(error, key) {
self.keyGenerator.generateDocumentKey(entityName, function (error, key) {
if (error) { return callback(error, entity); }

// Assign the id to the entity so it is immediateley available
Expand All @@ -136,15 +138,16 @@ Client.prototype.generateDocumentKey = function(entityName, entity, callback) {
* @return {string}
*/
Client.prototype.buildRavenQuery = function (query) {
var s = '';
for(var i in query){
s = s + (s.length === 0 ? '' : ' ') + i + ':' + query[i];
var s = '',
i;
for (i in query) {
s = s + (s.length === 0 ? '' : ' ') + i + ':' + query[i];
}
return qs.escape(s);
};

function raven (options) {
if (typeof options === 'string') options = { 'server_url' : options};
function raven(options) {
if (typeof options === 'string') { options = { 'server_url' : options}; }
return new Client(options);
}

Expand Down
40 changes: 21 additions & 19 deletions lib/ravenhttpclient.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,58 +14,60 @@ var request = require('request'),
url = require('url');

function RavenHttpClient(options) {
if (typeof options === 'string') options = { 'server_url' : options };
if (typeof options === 'string') { options = { 'server_url' : options }; }

for (var i in options) {
this[i] = options[i];
}

if (!this.server_url || typeof(this.server_url) !== 'string') { throw new Error('You must specify a serevr_url'); }

this.server_url_parts = url.parse(this.server_url);
this.server_url_parts = url.parse(this.server_url);
}

/**
* Combines url of the server with path and query segments
* @param {string} path Path of the request. Paths are relative to the multi-tenant server url, use absolute paths for server level requests, and relative for database level
* @param {object} query Hash of querystring parameters
* @param {object} query Hash of querystring parameters
* @return {string}
*/
RavenHttpClient.prototype.buildUrl = function(path, query) {
RavenHttpClient.prototype.buildUrl = function (path, query) {
var parts = Object.create(this.server_url_parts);
if (path)
if (path) {
parts.pathname = (path[0] === '/' ? path : (parts.pathname + path));
if (query)
}
if (query) {
parts.query = query;
return url.format(parts);
}
return url.format(parts);
};

/**
* Perform a GET request against the server
* @param {string} path Path of the request. Paths are relative to the multi-tenant server url, use absolute paths for server level requests, and relative for database level
* @param {object} query Hash of querystring parameters
* @param {object} query Hash of querystring parameters
* @param {Function(error, response, body)} callback Callback receives an error object, a wrapped httpResponse and the body of the response
*/
RavenHttpClient.prototype.get = function(path, query, callback) {
RavenHttpClient.prototype.get = function (path, query, callback) {
var self = this;
request.get(self.buildUrl(path, query), function (error, response, body) {
callback(error, {
httpResponse: response,
statusCode: response ? response.statusCode : -1,
content: body,
asJson: function() { return JSON.parse(body); }
asJson: function () { return JSON.parse(body); }
});
});
});
};

/**
* Perform a PUT request against the server
* @param {string} path Path of the request. Paths are relative to the multi-tenant server url, use absolute paths for server level requests, and relative for database level
* @param {object} query Hash of querystring parameters
* @param {object} query Hash of querystring parameters
* @param {object} content Hash to be converted to JSON and sent to the server as the body of the request
* @param {Function(error, response, body)} callback Callback receives an error object, a wrapped httpResponse and the body of the response
*/
RavenHttpClient.prototype.put = function(path, query, content, callback) {
RavenHttpClient.prototype.put = function (path, query, content, callback) {
var self = this;
request.put({
uri: self.buildUrl(path, query),
Expand All @@ -75,19 +77,19 @@ RavenHttpClient.prototype.put = function(path, query, content, callback) {
httpResponse: response,
statusCode: response ? response.statusCode : -1,
content: body,
asJson: function() { return JSON.parse(body); }
asJson: function () { return JSON.parse(body); }
});
});
});
};

/**
* Perform a POST request against the server
* @param {string} path Path of the request. Paths are relative to the multi-tenant server url, use absolute paths for server level requests, and relative for database level
* @param {object} query Hash of querystring parameters
* @param {object} query Hash of querystring parameters
* @param {object} content Hash to be converted to JSON and sent to the server as the body of the request
* @param {Function(error, response, body)} callback Callback receives an error object, a wrapped httpResponse and the body of the response
*/
RavenHttpClient.prototype.post = function(path, query, content, callback) {
RavenHttpClient.prototype.post = function (path, query, content, callback) {
var self = this;
request.post({
uri: self.buildUrl(path, query),
Expand All @@ -97,9 +99,9 @@ RavenHttpClient.prototype.post = function(path, query, content, callback) {
httpResponse: response,
statusCode: response ? response.statusCode : -1,
content: body,
asJson: function() { return JSON.parse(body); }
asJson: function () { return JSON.parse(body); }
});
});
});
};

function ravenHttpClient(options) {
Expand Down
2 changes: 1 addition & 1 deletion test.cmd
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
FOR /D %%f IN (RavenDb*) DO CALL :test %%f

echo.---JShint results---
cmd /C .\node_modules\.bin\jshint .\lib\client.js .\lib\ravenhttpclient.js .\lib\HiLoKeyGenerator.js
cmd /C .\node_modules\.bin\jshint .\lib\client.js .\lib\ravenhttpclient.js .\lib\HiLoKeyGenerator.js --config test\jshint-config.json

GOTO :EOF

Expand Down
Loading

0 comments on commit f4085c1

Please sign in to comment.