node-plotly
Version:
An un-official plot.ly API client
185 lines (139 loc) • 4.08 kB
JavaScript
require('isomorphic-fetch');
var R = require('ramda');
var URL = require('url');
var API_VERSION = 'v2';
// api client
function PlotlyAPIClient() {
this._config = {
protocol: 'https',
host: 'api.plot.ly',
username: undefined,
apiKey: undefined
};
this.Users = new UsersAPI(this);
this.Files = new FilesAPI(this);
this.Grids = new GridsAPI(this);
this.Plots = new PlotsAPI(this);
this.Dashboards = new DashboardsAPI(this);
}
PlotlyClient.prototype.config = function(config) {
this._config = R.merge(this._config, config);
return this;
};
PlotlyClient.prototype.basicAuth = function() {
if (!this._config.username || !this._config.apiKey) {
return undefined;
}
return 'Basic ' + base64encode(this._config.username + ':' + this._config.apiKey);
};
PlotlyClient.prototype.apiUrl = function(path, query) {
return URL.format({
protocol: this._config.protocol,
host: this._config.host,
pathname: API_VERSION + path,
query: query
});
};
PlotlyClient.prototype._request = function(method, url, body) {
var options = {
method: method,
credentials: 'include'
};
if (body) {
options.body = body;
}
var headers = new Headers();
options.headers = headers;
headers.set('Accept', 'application/json');
// if we have a username and apikey configured, use those
var basicAuth = this.basicAuth();
if (basicAuth) {
headers.set('Authorization', basicAuth);
}
// if we are sending a json payload
// TODO quite britle checking
if (method !== 'GET' && body && body[0] === '{') {
headers.set('Content-Type', 'application/json');
}
return fetch(url, options).then(function(response) {
return response.text().then(function(text) {
return {text: text, response: response};
});
}).then(function(data) {
var text = data.text;
var response = data.response;
// No content is a valid API response for some POST/PATCH/202
if (text === '') {
return {response: response, json: {}};
}
try {
return {response: response, json: JSON.parse(text)};
} catch (e) {
throw new Error('Failed to parse response JSON');
}
}).then(function(data) {
var json = data.json;
var response = data.response;
if (!response.ok) {
// TODO Parse better API errors
return Promise.reject(json.errors);
}
return json;
});
};
PlotlyClient.prototype.request = function(method, path, query, body) {
var encodedBody;
if (body) {
encodedBody = JSON.stringify(body);
}
return this._request(method, this.apiUrl(path, query), encodedBody);
};
// users
function UsersAPI(apiClient) {
this.apiClient = apiClient;
}
// files
function FilesAPI(apiClient) {
this.apiClient = apiClient;
}
FilesAPI.prototype.retrieve = function(fileId, shareKey) {
return this.apiClient.request('GET', '/files/' + fileId, {shareKey: shareKey});
};
FilesAPI.prototype.update = function(file) {
return this.apiClient.request('PATCH', '/files/' + file.fid, {}, file);
};
// grids
function GridsAPI(apiClient) {
this.apiClient = apiClient;
}
GridsAPI.prototype.content = function(fileId, shareKey) {
return this.apiClient.request('GET', '/grids/' + fileId + '/content', {shareKey: shareKey});
};
// plots
function PlotsAPI(apiClient) {
this.apiClient = apiClient;
}
PlotsAPI.prototype.content = function(fileId, shareKey) {
return this.apiClient.request('GET', '/plots/' + fileId + '/content', {shareKey: shareKey});
};
// dashboards
function DashboardsAPI(apiClient) {
this.apiClient = apiClient;
}
DashboardsAPI.prototype.content = function(fileId, shareKey) {
return this.apiClient.request('GET', '/dashboards/' + fileId, {shareKey: shareKey});
};
// helpers
function base64encode(value) {
if (typeof window !== 'undefined') {
return atob(value);
} else {
return new Buffer(value).toString('base64');
}
}
if (typeof module !== 'undefined') {
module.exports = new PlotlyAPIClient();
}
if (typeof window !== 'undefined') {
window.PlotlyAPI = new PlotlyAPIClient();
}