empire
Version:
Empire API JavaScript client ========================
222 lines (197 loc) • 6.37 kB
JavaScript
var Request = require('./request.js').Request;
var Walkthrough = require('./walkthrough.js').Walkthrough;
/**
* app_key is your Empire application key, and is necessary for using the API
* opts can include any of:
* 'api_server' : the server to connect to (default: api.empiredata.com)
* 'enduser' : a string identifying the end user, required for any operations on views (default: nil)
* 'secrets' : a JSON object generated by https://login.empiredata.co (default: nil)
* 'secretsJson' : the path to a JSON file generated by https://login.empiredata.co (default: nil)
*/
exports.Empire = function(appKey, opts) {
var self = this;
function initialize() {
if (!opts) { opts = {}; }
var apiServer = opts['apiServer'] || 'api.empiredata.co';
self.appKey = appKey;
self.enduser = opts['enduser'];
self.sessionKey = '';
var protocol = (apiServer.indexOf('localhost') > -1) ? 'http' : 'https';
self.baseUrl = protocol + '://' + apiServer + '/empire/';
self.serviceSecrets = null;
if (opts['secrets']) {
self.serviceSecrets = opts['secrets'];
}
}
/**
* Load secrets from a JSON file
* (this operation is async in browser and sync in node, but the interface is identical)
* file: the path to the JSON secrets file
* event handlers: .ready(), .error({type, statusCode, body})
*/
self.loadSecrets = function (file) {
if (typeof window === 'undefined') {
// in node - load secrets synchronously
self.serviceSecrets = require(process.cwd() + '/' + file);
return {
'ready': function (handler) {
handler();
}
};
} else {
// in browser - load secrets asynchroously
return new Request(self, file, {
local: true,
customHandlers: {
'ready': function (handler, response) {
self.serviceSecrets = response;
self.isReady = true;
handler();
}
}
});
}
}
/**
* Connect to specific service
* service: service name
* secrets: object with service secrets (optional if the Empire instance was initialized with a secrets JSON file)
* event handlers: .success(response), .error({type, statusCode, body})
*/
self.connect = function (service, secrets) {
if (!secrets) {
secrets = {};
for (k in self.serviceSecrets[service].option) {
v = self.serviceSecrets[service].option[k];
secrets[k] = v.value;
}
}
return new Request(self, "services/" + service + "/connect", {
method: 'post',
body: secrets
});
};
/**
* Describe all services, all tables within a given service, or a given table
* event handlers: .success(response), .error({type, statusCode, body})
*/
self.describe = function (service, table) {
var path = "services";
if (service) {
path += "/" + service;
if (table) {
path += "/" + table;
}
} else if (table) {
throw new Error("Service must be specified if table is specified!");
}
return new Request(self, path);
};
/**
* Print the result of an SQL query
*/
self.printQuery = function (sql) {
self.query(sql).forEach(function (row) {
console.log(row);
});
};
/**
* Issue an SQL query
* event handlers: .forEach(row), .success(response), .error({type, statusCode, body})
*/
self.query = function (sql) {
return new Request(self, "query", {
method: 'post',
body: {'query': sql},
raw: true,
customHandlers: {
'forEach': function (handler, response) {
response.split('\n').forEach (function (row) {
if (row != '') {
handler(JSON.parse(row));
}
})
}
}
});
};
/**
* Insert a new row into this service table. The row should be an object of {column: value}
* event handlers: .success(response), .error({type, statusCode, body})
*/
self.insert = function (service, table, row) {
return new Request(self, "services/" + service + "/" + table, {
method: 'post',
body: row
});
};
/**
* Materialize a SQL query as a view. This creates or updates a view.
* event handlers: .ready(), .error({type, statusCode, body})
*/
self.materializeView = function (name, sql) {
if (!self.enduser) {
throw new Error("Cannot use a materialized view within a session initiated without an enduser")
}
return new Request(self, "view/" + name, {
method: 'put',
body: {'query': sql},
customHandlers: {
'ready': function (handler) {
waitUntilViewIsReady(name, handler, 100);
}
}
});
};
/**
* Delete a materialized view of SQL query.
* event handlers: .success(response), .error({type, statusCode, body})
*/
self.dropView = function (name) {
if (!self.enduser) {
throw new Error("Cannot use a materialized view within a session initiated without an enduser")
}
return new Request(self, "view/" + name, {
method: 'delete'
});
};
/**
* Queries the Date that this view was materialized at (or null, if the materialization is currently pending).
* event handlers: .success(date), .error({type, statusCode, body})
*/
self.viewMaterializedAt = function (name) {
if (!self.enduser) {
throw new Error("Cannot use a materialized view within a session initiated without an enduser")
}
return new Request(self, "view/" + name + "/status", {
filter: function (response) {
try {
return new Date(response['materializedAt']);
} catch (e) {
return null;
}
}
});
}
/**
* Run automatic test of all services from JSON
*/
self.walkthrough = function () {
new Walkthrough(self).run();
};
function waitUntilViewIsReady(name, callback, interval) {
new Request(self, "view/" + name + "/status").success(function (result) {
if (result['viewStatus'] == 'ready') {
callback();
} else if (result['viewStatus'] == 'pending') {
setTimeout(function () {
waitUntilViewIsReady(name, callback, interval) // (interval is in ms)
}, interval);
}
});
}
initialize();
};
if (typeof window !== 'undefined') {
window.Empire = exports.Empire;
}