UNPKG

jscrambler

Version:

Jscrambler Code Integrity API client.

282 lines (276 loc) 9.2 kB
"use strict"; require("core-js/modules/es.regexp.exec.js"); require("core-js/modules/es.string.replace.js"); require("core-js/modules/es.string.trim.js"); require("core-js/modules/web.dom-collections.iterator.js"); var _lodash = _interopRequireDefault(require("lodash.defaults")); var _fs = _interopRequireDefault(require("fs")); var _lodash2 = _interopRequireDefault(require("lodash.keys")); var _axios = _interopRequireDefault(require("axios")); var _zlib = require("zlib"); var _url = _interopRequireDefault(require("url")); var _https = _interopRequireDefault(require("https")); var _http = _interopRequireDefault(require("http")); var _httpsProxyAgent = require("https-proxy-agent"); var _httpProxyAgent = require("http-proxy-agent"); var _config = _interopRequireDefault(require("./config")); var _generateSignedParams = _interopRequireDefault(require("./generate-signed-params")); var _constants = require("./constants"); var _package = require("../package.json"); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } const debug = !!process.env.DEBUG; const metrics = !!process.env.METRICS; const noCompression = !!process.env.NO_COMPRESSION; class ClientError extends Error { constructor(message, statusCode) { super(message); this.statusCode = statusCode; } } /** * @class JScramblerClient * @param {Object} options * @param {String} options.accessKey * @param {String} options.secretKey * @param {String} [options.host=api.jscrambler.com] * @param {String} [options.port=443] * @param {String} [options.basePath] * @param {String} [options.clientId=0] * @author Jscrambler * @license MIT <http://opensource.org/licenses/MIT> */ function JScramblerClient(options) { // Sluggish hack for backwards compatibility if (options && !options.keys && (options.accessKey || options.secretKey)) { options.keys = {}; options.keys.accessKey = options.accessKey; options.keys.secretKey = options.secretKey; } options.keys = (0, _lodash.default)(options.keys || {}, _config.default.keys); /** * @member */ this.options = (0, _lodash.default)(options || {}, _config.default); const { jscramblerVersion, clientId } = this.options; this.axiosInstance = _axios.default.create({ headers: { jscramblerVersion, clientId }, transformRequest: _axios.default.defaults.transformRequest.concat(function (data, headers) { // gzip request with more than 1KiB if (!noCompression && typeof data === 'string' && data.length > 1024) { headers['Content-Encoding'] = 'gzip'; data = (0, _zlib.gzipSync)(data); if (metrics) { process.stdout.write("[gzip ".concat(data.length, "B] ")); } } return data; }) }); } /** * Delete request. * @param {String} path * @param {Object} params * @param {Callback} callback */ JScramblerClient.prototype.delete = function (path, params) { return this.request('DELETE', path, params); }; /** * Get request. * @param {String} path * @param {Object} params * @param {Callback} callback */ JScramblerClient.prototype.get = function (path, params) { let isJSON = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; return this.request('GET', path, params, isJSON); }; /** * HTTP request. * @param {String} method * @param {String} path * @param {Object} params * @param {Callback} callback */ JScramblerClient.prototype.request = function (method, path) { let params = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; let isJSON = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true; let signedData; if (this.options.useHeaderAuth) { if (!this.token) { throw new Error('Generating auth token when useHeaderAuth === true is not yet supported. You need to set the jscramblerClient token property explicitly.'); } } else { if (this.token) { params.token = this.token; } else { if (!this.options.keys.accessKey) { throw new Error('Required *accessKey* not provided'); } if (!this.options.keys.secretKey) { throw new Error('Required *secretKey* not provided'); } } } const _keys = (0, _lodash2.default)(params); for (let i = 0, l = _keys.length; i < l; i++) { if (params[_keys[i]] instanceof Array) { params[_keys[i]] = params[_keys[i]].join(','); } } // If post sign data and set the request as multipart if (this.options.keys.accessKey && this.options.keys.secretKey) { signedData = (0, _generateSignedParams.default)(method, path, this.options.host, this.options.keys, params, this.options.utc); } else { signedData = params; } let { protocol, port, proxy } = this.options; if (!port && !protocol) { port = 443; protocol = 'https'; } if (!port) { port = protocol === 'https' ? 443 : 80; } if (!protocol) { protocol = port === 443 ? 'https' : 'http'; } const formattedUrl = _url.default.format({ hostname: this.options.host, port, pathname: this.options.basePath + path, protocol }); let data; const settings = {}; // Internal CA let agentOptions = {}; if (this.options.cafile) { agentOptions = { ca: _fs.default.readFileSync(this.options.cafile) }; } if (proxy || typeof proxy === 'object') { const { host, port = 8080, auth } = proxy; if (!host) { throw new Error('Required *proxy.host* not provided'); } let username; let password; if (auth) { ({ username, password } = auth); if (!username || !password) { throw new Error('Required *proxy.auth* username or/and password not provided'); } } settings.proxy = false; const proxyConfig = { host, port, username, password, protocol: "".concat(proxy.protocol || 'http', ":") }; settings.httpsAgent = new _httpsProxyAgent.HttpsProxyAgent(proxyConfig, agentOptions); settings.httpAgent = new _httpProxyAgent.HttpProxyAgent(proxyConfig, agentOptions); } else if (agentOptions) { settings.httpsAgent = new _https.default.Agent(agentOptions); settings.httpAgent = new _http.default.Agent(agentOptions); } if (!isJSON) { settings.responseType = 'arraybuffer'; } let promise; if (method === 'GET' || method === 'DELETE') { settings.params = signedData; promise = this.axiosInstance[method.toLowerCase()](formattedUrl, settings); } else { data = signedData; promise = this.axiosInstance[method.toLowerCase()](formattedUrl, data, settings); } const start = Date.now(); return promise.then(res => { if (metrics || debug) { console.log("".concat(method, " ").concat(path, " ").concat(((data || settings.params).query || '').split('(')[0].trim().replace(' ', '-'), " ").concat(JSON.stringify(data || settings.params).length, "B ").concat(Date.now() - start, "ms")); } return res.data; }).catch(err => { let errorMessage = 'Unexpected Response: '; let statusCode = 500; if (err.response) { if (debug) { console.error(err.response); } errorMessage += "".concat(err.response.status, " ").concat(err.response.statusText); statusCode = err.response.status; let incompatibleApi = false; if (statusCode === _constants.HTTP_STATUS_CODES.UNAUTHORIZED && /Invalid Signature/i.test(err.response.data.message)) { incompatibleApi = err.response.data.errorCode !== _constants.JSCRAMBLER_ERROR_CODES.INVALID_SIGNATURE; } if (incompatibleApi) { errorMessage = "Incompatible jscrambler CLI version (".concat(_package.version, "). Please downgrade to: \n\t$ npm install ").concat(_constants.CLIENT_PACKAGES[this.options.clientId], "@5"); } else if ( // For when we have API error messages err.response.data && err.response.data.error && err.response.data.message) { errorMessage += " - ".concat(err.response.data.message); } else if (err.response.data && err.response.data.errors && err.response.data.errors.length > 0) { errorMessage += " - ".concat(err.response.data.errors); } } else { errorMessage += err.message; } throw new ClientError(errorMessage, statusCode); }); }; /** * Post request. * @param {String} path * @param {Object} params * @param {Callback} callback */ JScramblerClient.prototype.post = function (path, params) { return this.request('POST', path, params); }; /** * Patch request. * @param {string} path * @param {object} params */ JScramblerClient.prototype.patch = function (path, params) { return this.request('PATCH', path, params); }; let _token; Object.defineProperty(JScramblerClient.prototype, 'token', { get() { return _token; }, set(value) { _token = value; if (value) { if (this.options.useHeaderAuth) { this.axiosInstance.defaults.headers['x-user-authentication'] = _token; } } else { delete this.axiosInstance.defaults.headers['x-user-authentication']; } } }); exports = module.exports = JScramblerClient;