soda-js
Version:
js library for accessing a soda2 api
531 lines (472 loc) • 13.8 kB
JavaScript
// Generated by CoffeeScript 1.6.3
var Connection, Consumer, Dataset, EventEmitter, Operation, Producer, Query, addExpr, base64Lookup, eelib, expr, extend, handleLiteral, handleOrder, httpClient, isArray, isNumber, isString, rawToBase64, toBase64, toQuerystring,
__slice = [].slice,
__hasProp = {}.hasOwnProperty;
eelib = require('eventemitter2');
EventEmitter = eelib.EventEmitter2 || eelib;
httpClient = require('superagent');
isString = function(obj) {
return typeof obj === 'string';
};
isArray = function(obj) {
return Array.isArray(obj);
};
isNumber = function(obj) {
return !isNaN(parseFloat(obj));
};
extend = function() {
var k, source, sources, target, v, _i, _len;
target = arguments[0], sources = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
for (_i = 0, _len = sources.length; _i < _len; _i++) {
source = sources[_i];
for (k in source) {
v = source[k];
target[k] = v;
}
}
return null;
};
toBase64 = typeof Buffer !== "undefined" && Buffer !== null ? function(str) {
return new Buffer(str).toString('base64');
} : (base64Lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='.split(''), rawToBase64 = typeof btoa !== "undefined" && btoa !== null ? btoa : function(str) {
var chr1, chr2, chr3, enc1, enc2, enc3, enc4, i, result;
result = [];
i = 0;
while (i < str.length) {
chr1 = str.charCodeAt(i++);
chr2 = str.charCodeAt(i++);
chr3 = str.charCodeAt(i++);
if (Math.max(chr1, chr2, chr3) > 0xFF) {
throw new Error('Invalid character!');
}
enc1 = chr1 >> 2;
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
enc4 = chr3 & 63;
if (isNaN(chr2)) {
enc3 = enc4 = 64;
} else if (isNaN(chr3)) {
enc4 = 64;
}
result.push(base64Lookup[enc1]);
result.push(base64Lookup[enc2]);
result.push(base64Lookup[enc3]);
result.push(base64Lookup[enc4]);
}
return result.join('');
}, function(str) {
return rawToBase64(unescape(encodeURIComponent(str)));
});
handleLiteral = function(literal) {
if (isString(literal)) {
return "'" + literal + "'";
} else if (isNumber(literal)) {
return literal;
} else {
return literal;
}
};
handleOrder = function(order) {
if (/( asc$| desc$)/i.test(order)) {
return order;
} else {
return order + ' asc';
}
};
addExpr = function(target, args) {
var arg, k, v, _i, _len, _results;
_results = [];
for (_i = 0, _len = args.length; _i < _len; _i++) {
arg = args[_i];
if (isString(arg)) {
_results.push(target.push(arg));
} else {
_results.push((function() {
var _results1;
_results1 = [];
for (k in arg) {
v = arg[k];
_results1.push(target.push("" + k + " = " + (handleLiteral(v))));
}
return _results1;
})());
}
}
return _results;
};
expr = {
and: function() {
var clause, clauses;
clauses = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
return ((function() {
var _i, _len, _results;
_results = [];
for (_i = 0, _len = clauses.length; _i < _len; _i++) {
clause = clauses[_i];
_results.push("(" + clause + ")");
}
return _results;
})()).join(' and ');
},
or: function() {
var clause, clauses;
clauses = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
return ((function() {
var _i, _len, _results;
_results = [];
for (_i = 0, _len = clauses.length; _i < _len; _i++) {
clause = clauses[_i];
_results.push("(" + clause + ")");
}
return _results;
})()).join(' or ');
},
gt: function(column, literal) {
return "" + column + " > " + (handleLiteral(literal));
},
gte: function(column, literal) {
return "" + column + " >= " + (handleLiteral(literal));
},
lt: function(column, literal) {
return "" + column + " < " + (handleLiteral(literal));
},
lte: function(column, literal) {
return "" + column + " <= " + (handleLiteral(literal));
},
eq: function(column, literal) {
return "" + column + " = " + (handleLiteral(literal));
}
};
toQuerystring = function(obj) {
var key, str, val;
str = [];
for (key in obj) {
if (!__hasProp.call(obj, key)) continue;
val = obj[key];
str.push(encodeURIComponent(key) + '=' + encodeURIComponent(val));
}
return str.join('&');
};
Connection = (function() {
function Connection(dataSite, sodaOpts) {
var _ref;
this.dataSite = dataSite;
this.sodaOpts = sodaOpts != null ? sodaOpts : {};
if (!/^[a-z0-9-_.]+(:[0-9]+)?$/i.test(this.dataSite)) {
throw new Error('dataSite does not appear to be valid! Please supply a domain name, eg data.seattle.gov');
}
this.emitterOpts = (_ref = this.sodaOpts.emitterOpts) != null ? _ref : {
wildcard: true,
delimiter: '.',
maxListeners: 15
};
this.networker = function(opts, data) {
var client, url,
_this = this;
url = "https://" + this.dataSite + opts.path;
client = httpClient(opts.method, url);
if (data != null) {
client.set('Accept', "application/json");
}
if (data != null) {
client.set('Content-type', "application/json");
}
if (this.sodaOpts.apiToken != null) {
client.set('X-App-Token', this.sodaOpts.apiToken);
}
if ((this.sodaOpts.username != null) && (this.sodaOpts.password != null)) {
client.set('Authorization', "Basic " + toBase64("" + this.sodaOpts.username + ":" + this.sodaOpts.password));
}
if (this.sodaOpts.accessToken != null) {
client.set('Authorization', "OAuth " + accessToken);
}
if (opts.query != null) {
client.query(opts.query);
}
if (data != null) {
client.send(data);
}
return function(responseHandler) {
return client.end(responseHandler || _this.getDefaultHandler());
};
};
}
Connection.prototype.getDefaultHandler = function() {
var emitter, handler;
this.emitter = emitter = new EventEmitter(this.emitterOpts);
return handler = function(error, response) {
var _ref;
if (response.ok) {
if (response.accepted) {
emitter.emit('progress', response.body);
setTimeout((function() {
return this.consumer.networker(opts)(handler);
}), 5000);
} else {
emitter.emit('success', response.body);
}
} else {
emitter.emit('error', (_ref = response.body) != null ? _ref : response.text);
}
return emitter.emit('complete', response);
};
};
return Connection;
})();
Consumer = (function() {
function Consumer(dataSite, sodaOpts) {
this.dataSite = dataSite;
this.sodaOpts = sodaOpts != null ? sodaOpts : {};
this.connection = new Connection(this.dataSite, this.sodaOpts);
}
Consumer.prototype.query = function() {
return new Query(this);
};
Consumer.prototype.getDataset = function(id) {
var emitter;
return emitter = new EventEmitter(this.emitterOpts);
};
return Consumer;
})();
Producer = (function() {
function Producer(dataSite, sodaOpts) {
this.dataSite = dataSite;
this.sodaOpts = sodaOpts != null ? sodaOpts : {};
this.connection = new Connection(this.dataSite, this.sodaOpts);
}
Producer.prototype.operation = function() {
return new Operation(this);
};
return Producer;
})();
Operation = (function() {
function Operation(producer) {
this.producer = producer;
}
Operation.prototype.withDataset = function(datasetId) {
this._datasetId = datasetId;
return this;
};
Operation.prototype.truncate = function() {
var opts;
opts = {
method: 'delete'
};
opts.path = "/resource/" + this._datasetId;
return this._exec(opts);
};
Operation.prototype.add = function(data) {
var obj, opts, _data, _i, _len;
opts = {
method: 'post'
};
opts.path = "/resource/" + this._datasetId;
_data = JSON.parse(JSON.stringify(data));
delete _data[':id'];
delete _data[':delete'];
for (_i = 0, _len = _data.length; _i < _len; _i++) {
obj = _data[_i];
delete obj[':id'];
delete obj[':delete'];
}
return this._exec(opts, _data);
};
Operation.prototype["delete"] = function(id) {
var opts;
opts = {
method: 'delete'
};
opts.path = "/resource/" + this._datasetId + "/" + id;
return this._exec(opts);
};
Operation.prototype.update = function(id, data) {
var opts;
opts = {
method: 'post'
};
opts.path = "/resource/" + this._datasetId + "/" + id;
return this._exec(opts, data);
};
Operation.prototype.replace = function(id, data) {
var opts;
opts = {
method: 'put'
};
opts.path = "/resource/" + this._datasetId + "/" + id;
return this._exec(opts, data);
};
Operation.prototype.upsert = function(data) {
var opts;
opts = {
method: 'post'
};
opts.path = "/resource/" + this._datasetId;
return this._exec(opts, data);
};
Operation.prototype._exec = function(opts, data) {
if (this._datasetId == null) {
throw new Error('no dataset given to work against!');
}
this.producer.connection.networker(opts, data)();
return this.producer.connection.emitter;
};
return Operation;
})();
Query = (function() {
function Query(consumer) {
this.consumer = consumer;
this._select = [];
this._where = [];
this._group = [];
this._having = [];
this._order = [];
this._offset = this._limit = this._q = null;
}
Query.prototype.withDataset = function(datasetId) {
this._datasetId = datasetId;
return this;
};
Query.prototype.soql = function(query) {
this._soql = query;
return this;
};
Query.prototype.select = function() {
var select, selects, _i, _len;
selects = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
for (_i = 0, _len = selects.length; _i < _len; _i++) {
select = selects[_i];
this._select.push(select);
}
return this;
};
Query.prototype.where = function() {
var args;
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
addExpr(this._where, args);
return this;
};
Query.prototype.having = function() {
var args;
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
addExpr(this._having, args);
return this;
};
Query.prototype.group = function() {
var group, groups, _i, _len;
groups = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
for (_i = 0, _len = groups.length; _i < _len; _i++) {
group = groups[_i];
this._group.push(group);
}
return this;
};
Query.prototype.order = function() {
var order, orders, _i, _len;
orders = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
for (_i = 0, _len = orders.length; _i < _len; _i++) {
order = orders[_i];
this._order.push(handleOrder(order));
}
return this;
};
Query.prototype.offset = function(offset) {
this._offset = offset;
return this;
};
Query.prototype.limit = function(limit) {
this._limit = limit;
return this;
};
Query.prototype.q = function(q) {
this._q = q;
return this;
};
Query.prototype.getOpts = function() {
var k, opts, queryComponents, v;
opts = {
method: 'get'
};
if (this._datasetId == null) {
throw new Error('no dataset given to work against!');
}
opts.path = "/resource/" + this._datasetId + ".json";
queryComponents = this._buildQueryComponents();
opts.query = {};
for (k in queryComponents) {
v = queryComponents[k];
opts.query['$' + k] = v;
}
return opts;
};
Query.prototype.getURL = function() {
var opts, query;
opts = this.getOpts();
query = toQuerystring(opts.query);
return ("https://" + this.consumer.dataSite + opts.path) + (query ? "?" + query : "");
};
Query.prototype.getRows = function() {
var opts;
opts = this.getOpts();
this.consumer.connection.networker(opts)();
return this.consumer.connection.emitter;
};
Query.prototype._buildQueryComponents = function() {
var query;
query = {};
if (this._soql != null) {
query.query = this._soql;
} else {
if (this._select.length > 0) {
query.select = this._select.join(', ');
}
if (this._where.length > 0) {
query.where = expr.and.apply(this, this._where);
}
if (this._group.length > 0) {
query.group = this._group.join(', ');
}
if (this._having.length > 0) {
if (!(this._group.length > 0)) {
throw new Error('Having provided without group by!');
}
query.having = expr.and.apply(this, this._having);
}
if (this._order.length > 0) {
query.order = this._order.join(', ');
}
if (isNumber(this._offset)) {
query.offset = this._offset;
}
if (isNumber(this._limit)) {
query.limit = this._limit;
}
if (this._q) {
query.q = this._q;
}
}
return query;
};
return Query;
})();
Dataset = (function() {
function Dataset(data, client) {
this.data = data;
this.client = client;
}
return Dataset;
})();
extend(typeof exports !== "undefined" && exports !== null ? exports : this.soda, {
Consumer: Consumer,
Producer: Producer,
expr: expr,
_internal: {
Connection: Connection,
Query: Query,
Operation: Operation,
util: {
toBase64: toBase64,
handleLiteral: handleLiteral,
handleOrder: handleOrder
}
}
});