UNPKG

@gridscale/api

Version:
383 lines (381 loc) 14.7 kB
"use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.api = exports.APIClass = exports.GSError = void 0; var lodash_1 = require("lodash"); require('es6-promise').polyfill(); require('isomorphic-fetch'); var GSError = /** @class */ (function (_super) { __extends(GSError, _super); function GSError(message, result) { var _this = _super.call(this) || this; _this.success = false; _this.name = 'GridscaleError'; // try to assemble message with more details from result if (result.response && result.response.request && result.response.request.method && typeof (result.response.status) !== 'undefined' && result.response.request.url) { _this.message = 'Error : ' + result.response.request.method + ' | ' + result.response.status + ' | ' + result.response.request.url.split('?')[0]; } else { _this.message = message || 'Default Message'; } _this.result = result; _this.response = result.response || undefined; return _this; } return GSError; }(Error)); exports.GSError = GSError; var APIClass = /** @class */ (function () { function APIClass() { var _this = this; // Local Settings this.settings = { endpoint: 'https://api.gridscale.io', endpointOverrides: {}, token: '', userId: '', limit: 25, watchdelay: 1000, apiClient: 'gsclient-js' }; /** * Update local Request Options * * @param _option */ this.setOptions = function (_option) { // Assign new Values lodash_1.assignIn(_this.settings, _option); }; this.callbacks = []; /** * Adds a new logger for error logging * @param _callback */ this.addLogger = function (_callback) { _this.callbacks.push(_callback); }; this.log = function (_logData) { for (var i = 0; i < _this.callbacks.length; i++) { _this.callbacks[i](_logData); } }; } /** * Store api client in current session * @param _client String */ APIClass.prototype.storeClient = function (_client) { this.settings.apiClient = _client; }; /** * Store Token for Current Session * @param _token Secret Token */ APIClass.prototype.storeToken = function (_token, _userId) { // Store Token this.settings.token = _token; this.settings.userId = _userId; }; /** * Start the API Request * * @param _path * @param _options * @param _callback * @returns {Promise} */ APIClass.prototype.request = function (_path, _options, _callback) { var _this = this; if (_path === void 0) { _path = ''; } if (_callback === void 0) { _callback = function (response, result) { }; } var options = !lodash_1.isObject(_options) ? {} : lodash_1.assignIn({}, _options); // check if we should use another endpoint for this path (mocking) var endpoint = this.settings.endpoint; if (this.settings.endpointOverrides && typeof (this.settings.endpointOverrides) === 'object') { lodash_1.forEach(this.settings.endpointOverrides, function (_overrideEndpoint, _overridePath) { if (_overridePath.match(/^\/(.*)\/$/) && _path.split('?')[0].match(new RegExp(RegExp.$1))) { endpoint = _overrideEndpoint; } else if (_path.split('?')[0] === _overridePath) { endpoint = _overrideEndpoint; } else { return true; } return false; }); } // Build Options var url = _path.search('https://') === 0 ? _path : endpoint + _path; // on Links there is already options.headers = options.headers ? options.headers : {}; options.headers['X-Auth-UserId'] = this.settings.userId; options.headers['X-Auth-Token'] = this.settings.token; options.headers['X-Api-Client'] = this.settings.apiClient; // return results as object or text var getResult = function (_response, _rejectOnJsonFailure) { if (_rejectOnJsonFailure === void 0) { _rejectOnJsonFailure = true; } return new Promise(function (_resolve, _reject) { if (_response.status !== 204 && _response.headers.has('Content-Type') && _response.headers.get('Content-Type').indexOf('application/json') === 0) { _response.json() .then(function (json) { _resolve(json); }) .catch(function () { if (_rejectOnJsonFailure) { _reject(); } else { // try text _response.text().then(function (text) { return _resolve(text); }) .catch(function (e) { return _resolve(null); }); } }); } else { _response.text().then(function (text) { return _resolve(text); }) .catch(function (e) { return _resolve(null); }); } }); }; // Setup DEF var def = new Promise(function (_resolve, _reject) { // Fire Request var onSuccess = function (_response, _request, _requestInit) { getResult(_response.clone()).then(function (_result) { var result = { success: true, result: _result, response: _response.clone(), id: null, requestInit: _requestInit }; // Check for Links and generate them as Functions if (_result && _result._links) { var links_1 = {}; lodash_1.forEach(_result._links, function (link, linkname) { links_1[linkname] = _this.link(_result._links[linkname]); }); result.links = links_1; } if (_result && _result._meta) { result.meta = _result._meta; } /** * On POST, PATCH and DELETE Request we will inject a watch Function into the Response so you can easiely start watching the current Job */ if (options['method'] === 'POST' || options['method'] === 'PATCH' || options['method'] === 'DELETE') { if (result.response.headers.has('x-request-id')) { result.watch = function () { return _this.watchRequest(result.response.headers.get('x-request-id')); }; } } _resolve(result); setTimeout(function () { return _callback(_response.clone(), result); }); }) .catch(function () { // tslint:disable-next-line: no-use-before-declare onFail(_response, _request, _requestInit, 'json'); }); }; var onFail = function (_response, _request, _requestInit, _failType) { if (_failType === void 0) { _failType = 'request'; } getResult(_response.clone(), false).then(function (_result) { var result = { success: false, result: _result, response: lodash_1.assign(_response.clone(), { request: _request }), links: {}, watch: null, id: lodash_1.uniqueId('apierror_' + (new Date()).getTime() + '_'), requestInit: _requestInit, failureType: _failType }; _this.log({ result: result, response: _response.clone(), id: result.id, requestInit: result.requestInit }); _reject(new GSError('Request Error', result)); setTimeout(function () { return _callback(_response.clone(), result); }); }); }; var request = new Request(url, options); var promise = (_this.settings.fetch || fetch)(request); promise .then(function (_response) { if (_response.ok) { // The promise does not reject on HTTP errors onSuccess(_response, request, options); } else { onFail(_response, request, options); } }) .catch(function (_response) { _reject(new GSError('Network failure', _response)); }); // Return promise return promise; }); // Catch all Errors and // Return DEF return def; }; /** * Build Option URL to expand URL * @param _options * @returns {string} */ APIClass.prototype.buildRequestURL = function (_options) { // Push Valued var url = []; // Add Options to URL lodash_1.forEach(_options, function (val, key) { if (lodash_1.isArray(_options[key])) { if (_options[key].length > 0) { url.push(key + '=' + _options[key].join(',')); } } else { url.push(key + '=' + _options[key]); } }); return url.length > 0 ? ('?' + url.join('&')) : ''; }; /** * Start Get Call * @param _path * @param _callback */ APIClass.prototype.get = function (_path, _options, _callback) { if (lodash_1.isObject(_options)) { _path += this.buildRequestURL(_options); } // If No Options but Callback is given if (lodash_1.isUndefined(_callback) && lodash_1.isFunction(_options)) { _callback = _options; } return this.request(_path, { method: 'GET' }, _callback); }; /** * Start Delete Call * @param _path * @param _callback */ APIClass.prototype.remove = function (_path, _callback) { return this.request(_path, { method: 'DELETE' }, _callback); }; /** * Send Post Request * * @param _path Endpoint * @param _attributes Attributes for Post Body * @param _callback Optional Callback * @returns {Promise} */ APIClass.prototype.post = function (_path, _attributes, _callback) { return this.request(_path, { method: 'POST', body: JSON.stringify(_attributes), headers: { 'Content-Type': 'application/json' } }, _callback); }; /** * Send PAtCH Request * * @param _path Endpoint * @param _attributes Attributes for Post Body * @param _callback Optional Callback * @returns {Promise} */ APIClass.prototype.patch = function (_path, _attributes, _callback) { return this.request(_path, { method: 'PATCH', body: JSON.stringify(_attributes), headers: { 'Content-Type': 'application/json' } }, _callback); }; /** * Generate URL for Linked Request. No Options are required because its in the URL already * * @param _link * @param _callback * @returns {Function} */ APIClass.prototype.link = function (_link) { var _this = this; /** * generate Function that has an Optional Callback */ return function (_callback) { return _this.request(_link.href, { method: 'GET' }, _callback); }; }; /** * Start Pooling on Request Endpoint * * * @param _requestid * @param _callback * @returns {Promise} */ APIClass.prototype.requestpooling = function (_requestid, _callback) { return this.request('/requests/' + _requestid, { method: 'GET' }, _callback); }; /** * Recursive creating of Request Proises * * * @param _requestid * @param _resolve * @param _reject */ APIClass.prototype.buildAndStartRequestCallback = function (_requestid, _resolve, _reject) { var _this = this; /** * Start new Request */ this.requestpooling(_requestid).then(function (_result) { // Check Request Status to Decide if we start again if (_result.result[_requestid].status === 'pending') { setTimeout(function () { _this.buildAndStartRequestCallback(_requestid, _resolve, _reject); }, _this.settings.watchdelay); } else if (_result.response.status === 200) { // Job done _resolve(_result); } else { // IF _reject(_result); } }, function (_result) { return _reject(_result); }); }; /** * Watch a Single Request until it is ready or failed * * @param _requestid * @param _callback */ APIClass.prototype.watchRequest = function (_requestid) { var _this = this; return new Promise(function (_resolve, _reject) { _this.buildAndStartRequestCallback(_requestid, _resolve, _reject); }); }; return APIClass; }()); exports.APIClass = APIClass; exports.api = new APIClass(); //# sourceMappingURL=api.js.map