zcatalyst-cli
Version:
Command Line Tool for CATALYST
308 lines (307 loc) • 14.2 kB
JavaScript
'use strict';
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const request_1 = __importDefault(require("request"));
const progress_1 = __importDefault(require("../progress"));
const error_1 = __importDefault(require("../error"));
const errorResponse_1 = __importDefault(require("../errorResponse"));
const runtime_store_1 = __importDefault(require("../runtime-store"));
const constants_1 = require("../util_modules/constants");
const js_1 = require("../util_modules/js");
const logger_1 = require("../util_modules/logger");
const project_1 = require("../util_modules/project");
const fs_1 = require("fs");
const throbber_1 = __importDefault(require("../throbber"));
class API {
constructor({ authNeeded = true, resolveOnError = false, maxRetry = 3, env = constants_1.DEFAULT.env_name, log = {}, headers = {}, isExternal = false, origin = constants_1.ORIGIN.admin, json = true, showWarning = true, envId = (0, project_1.getEnvId)(), printError = true } = {}) {
this.requestOpts = {
url: origin,
method: 'GET',
json,
headers
};
const projectSecretKey = process.env.CATALYST_PROJECT_SECRET_KEY || process.env.ZC_PROJECT_SECRET_KEY;
if (!isExternal) {
this.requestOpts.headers = Object.assign(Object.assign({}, this.requestOpts.headers), { Accept: 'application/vnd.catalyst.v2+json', 'X-CATALYST-Environment': env });
if (projectSecretKey) {
this.requestOpts.headers['X-ZC-PROJECT-SECRET-KEY'] = projectSecretKey;
}
if (envId) {
this.requestOpts.headers['CATALYST-ORG'] = envId;
}
}
this.requestOpts.headers = Object.assign(Object.assign({}, this.requestOpts.headers), { 'User-Agent': runtime_store_1.default.get('context.cli.package.name') +
'/' +
runtime_store_1.default.get('context.cli.package.version') });
this.authNeeded = authNeeded;
this.resolveOnHTTPError = resolveOnError;
this.logOpts = log;
this.maxRetryCount = maxRetry;
this.retryCount = 0;
this.showWarning = showWarning;
this.printError = printError;
}
_logReq() {
let qs = this.requestOpts.qs
? '\nQuery params: ' + JSON.stringify(this.requestOpts.qs)
: '';
qs = this.logOpts.skipQuery === true ? '\n<request query omitted>' : qs;
let body = this.requestOpts.body
? '\nRequest Body: ' + JSON.stringify(this.requestOpts.body)
: '';
body += this.requestOpts.form
? '\nRequest Form: ' + JSON.stringify(this.requestOpts.form)
: '';
body = this.logOpts.skipReqBody === true ? '\n<request body omitted>' : body;
(0, logger_1.debug)('>>>> HTTP REQUEST : ' +
this.requestOpts.method +
' ' +
this.requestOpts.url +
' ' +
qs +
body +
'\n');
}
_logResp(resp) {
const ignoreHeaders = [
'content-security-policy-report-only',
'set-cookie',
'content-security-policy'
];
const logHeaders = Object.assign({}, resp.headers);
ignoreHeaders.forEach((header) => delete logHeaders[header]);
(0, logger_1.debug)('<<<< HTTP RESPONSE : ' +
resp.statusCode +
'\n' +
'Response Headers: ' +
JSON.stringify(logHeaders) +
'\n');
if (!js_1.JS.isUndefined(resp.timings)) {
(0, logger_1.debug)('TOTAL TIME TAKEN : ' + Number(resp.timings.end.toFixed(3)) + ' ms\n');
(0, logger_1.debug)('REQUEST PHASES : ' + resp.timingPhases);
}
if (resp.statusCode >= 200 &&
resp.statusCode < 300 &&
this.logOpts.progress !== undefined) {
js_1.JS.set(this.logOpts, 'progress.total', resp.headers['content-length']);
this.downloadProgress = new progress_1.default(this.logOpts.progress);
}
}
_logUploadProgress({ chunk, error } = {}) {
if (this.uploadProgress) {
!chunk || error
? this.uploadProgress.error(error)
: this.uploadProgress.tick(chunk.length);
}
}
_logDownloadProgress({ chunk, error } = {}) {
if (this.downloadProgress) {
!chunk || error
? this.downloadProgress.error(error)
: this.downloadProgress.tick(chunk.length);
}
}
_addAuthHeader() {
return __awaiter(this, void 0, void 0, function* () {
const credential = (yield Promise.resolve().then(() => __importStar(require('./credential')))).default;
const accessToken = yield credential.getAccessToken();
js_1.JS.set(this.requestOpts, 'headers.authorization', 'Bearer ' + accessToken);
});
}
_parseResponse(resp, body, rawResponse) {
const rawResponseData = rawResponse.length > 0 ? Buffer.concat(rawResponse) : undefined;
if (rawResponseData && js_1.JS.includes(resp.headers['content-type'], 'json')) {
try {
body = JSON.parse(rawResponseData.toString());
}
catch (e) {
const err = error_1.default.getErrorInstance(e);
(0, logger_1.debug)('API Parsing Error: ' + err.message);
}
}
if (resp.statusCode >= 400 && !this.logOpts.skipRespBody) {
(0, logger_1.debug)('Response Body : ' + JSON.stringify(resp.body) + '\n');
if (!this.resolveOnHTTPError) {
const errRes = (0, errorResponse_1.default)(resp, body, !this.printError);
this._logDownloadProgress({ error: errRes });
throw errRes;
}
this._logDownloadProgress({ error: (0, errorResponse_1.default)(resp, body, !this.printError) });
}
return {
status: resp.statusCode,
response: resp,
body: js_1.JS.includes(resp.headers['content-type'], 'json') && typeof body === 'string'
? JSON.parse(body)
: body
};
}
_retry(err) {
return __awaiter(this, void 0, void 0, function* () {
if (++this.retryCount > this.maxRetryCount) {
throw new error_1.default('API Error after retrying : ' + err.message, {
original: err,
exit: 2
});
}
(0, logger_1.debug)('API Error while firing request : ' + err.message + '\n');
(0, logger_1.debug)('>>>> RETRYING\n');
return this._request(true);
});
}
_request(retry = false) {
return __awaiter(this, void 0, void 0, function* () {
if (!retry) {
this._logReq();
}
return new Promise((resolve, reject) => {
const responseBuffer = [];
let isJSONResponse = false;
let isErrorPage = false;
const throbber = throbber_1.default.getInstance();
if (this.logOpts.uploadProgress !== undefined &&
this.logOpts.stream instanceof fs_1.ReadStream) {
const _stream = this.logOpts.stream;
this.uploadProgress = new progress_1.default(this.logOpts.uploadProgress);
_stream.on('data', (chunk) => {
this._logUploadProgress({ chunk });
});
}
if (this.logOpts.awaitingSpinner) {
this.logOpts.stream
? this.logOpts.stream.on('end', () => throbber.add('response_await', { text: this.logOpts.awaitingSpinner }))
: throbber.add('response_await', { text: this.logOpts.awaitingSpinner });
}
(0, request_1.default)(this.requestOpts, (err) => __awaiter(this, void 0, void 0, function* () {
this.logOpts.awaitingSpinner && throbber.remove('response_await');
if (err) {
switch (err.code) {
case 'ETIMEDOUT':
case 'ENOTFOUND':
case 'ESOCKETTIMEDOUT':
this.showWarning &&
(0, logger_1.warning)(err.code +
' has occured while communicating remote server. Kindly be patient while the cli retries this request.');
try {
resolve(yield this._retry(err));
}
catch (e) {
const error = error_1.default.getErrorInstance(e);
error.exit = 2;
reject(error);
}
break;
}
reject(new error_1.default('API Error: ' + err.message, {
original: err,
exit: 2
}));
}
}))
.on('response', (resp) => {
isJSONResponse = js_1.JS.includes(resp.headers['content-type'], 'json');
isErrorPage = !(resp.statusCode >= 200 && resp.statusCode < 300);
this._logResp(resp);
})
.on('complete', (resp, body) => __awaiter(this, void 0, void 0, function* () {
try {
resolve(this._parseResponse(resp, body, responseBuffer));
}
catch (err) {
reject(err);
}
}))
.on('data', (data) => {
if (isJSONResponse) {
responseBuffer.push(data);
}
if (!isErrorPage) {
this._logDownloadProgress({ chunk: data });
}
});
});
});
}
fire(method, path, options) {
return __awaiter(this, void 0, void 0, function* () {
this.resolveOnHTTPError = js_1.JS.get(options, 'resolveOnError', this.resolveOnHTTPError);
this.printError = (options === null || options === void 0 ? void 0 : options.printError) || this.printError;
this.maxRetryCount = js_1.JS.get(options, 'maxRetry', this.maxRetryCount);
this.authNeeded = js_1.JS.get(options, 'authNeeded', this.authNeeded);
this.logOpts = js_1.JS.get(options, 'log', this.logOpts);
this.requestOpts = js_1.JS.defaultsDeep(js_1.JS.omit(options, ['origin', 'auth', 'maxRetry', 'resolveOnError', 'log']), this.requestOpts);
this.requestOpts.url = ((options === null || options === void 0 ? void 0 : options.origin) || this.requestOpts.url || constants_1.ORIGIN.admin) + path;
this.requestOpts.method = method;
if (this.authNeeded) {
yield this._addAuthHeader();
return this._request();
}
return this._request();
});
}
get(path, options) {
return __awaiter(this, void 0, void 0, function* () {
return this.fire('GET', path, options);
});
}
put(path, options) {
return __awaiter(this, void 0, void 0, function* () {
return this.fire('PUT', path, options);
});
}
post(path, options) {
return __awaiter(this, void 0, void 0, function* () {
return this.fire('POST', path, options);
});
}
delete(path, options) {
return __awaiter(this, void 0, void 0, function* () {
return this.fire('DELETE', path, options);
});
}
head(path) {
return __awaiter(this, void 0, void 0, function* () {
return this.fire('HEAD', path);
});
}
patch(path, options) {
return __awaiter(this, void 0, void 0, function* () {
return this.fire('PATCH', path, options);
});
}
}
exports.default = API;