liveperson-functions-cli
Version:
LivePerson Functions CLI
238 lines • 10.2 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.RestClient = void 0;
/* eslint-disable @typescript-eslint/require-await */
const bent = require("bent");
const uuid_1 = require("uuid");
const constants_1 = require("../util/constants");
const predicates_1 = require("../util/predicates");
const restError_1 = require("../types/errors/restError");
const helper_1 = require("../util/helper");
const networkError_1 = require("../types/errors/networkError");
class RestClient {
constructor(baseUrl, apiKey) {
this.baseUrl = baseUrl;
this.apiKey = apiKey;
// This allows us to use the http protocol for QA
if (baseUrl.startsWith('http')) {
this.baseUrl = baseUrl.replace('http://', '');
this.protocol = 'http';
}
else {
this.protocol = 'https';
}
}
async createNamespace(accountId, namespace, options) {
try {
const query = options.ttl ? `?ttlSecond=${options.ttl}` : '';
const url = `${this.protocol}://${this.baseUrl}/v1/account/${accountId}${query}`;
const body = { name: namespace };
await this.performRequestWithDeadline('POST', url, body, {
acceptedStatusCodes: [204],
contentType: 'buffer',
timeout: constants_1.TEN_SECONDS,
});
const namespaces = await this.getListOfNamespaces(accountId);
return namespaces.find((current) => current.name === namespace);
}
catch (error) {
throw await this.transform(error);
}
}
async deleteNamespace(accountId, namespace) {
try {
const url = `${this.protocol}://${this.baseUrl}/v1/account/${accountId}/${namespace}`;
await this.performRequestWithDeadline('DELETE', url, undefined, {
acceptedStatusCodes: [204],
contentType: 'buffer',
timeout: constants_1.TEN_SECONDS,
});
}
catch (error) {
throw await this.transform(error);
}
}
async getListOfNamespaces(accountId) {
try {
const url = `${this.protocol}://${this.baseUrl}/v1/account/${accountId}`;
const namespaces = (await this.performRequestWithDeadline('GET', url, undefined, {
acceptedStatusCodes: [200],
contentType: 'json',
timeout: constants_1.TEN_SECONDS,
}));
return namespaces.map((current) => ({
name: current === null || current === void 0 ? void 0 : current.name,
createdAt: new Date(current === null || current === void 0 ? void 0 : current.createdAt),
...((current === null || current === void 0 ? void 0 : current.ttlSecond) && {
ttlSecond: current === null || current === void 0 ? void 0 : current.ttlSecond,
}), // Will add property if present
}));
}
catch (error) {
throw await this.transform(error);
}
}
async setOrUpdatePropertiesInNamespace(accountId, namespace, properties, sessionId = constants_1.DEFAULT_ENTITIY) {
try {
const url = `${this.protocol}://${this.baseUrl}/v1/account/${accountId}/${namespace}/${sessionId}/properties`;
await this.performRequestWithDeadline('PATCH', url, properties, {
acceptedStatusCodes: [204],
contentType: 'buffer',
timeout: constants_1.TEN_SECONDS,
});
return await this.getAllPropertiesInSession(accountId, namespace, sessionId);
}
catch (error) {
throw await this.transform(error);
}
}
async getAllPropertiesInSession(accountId, namespace, sessionId = constants_1.DEFAULT_ENTITIY) {
try {
const url = `${this.protocol}://${this.baseUrl}/v1/account/${accountId}/${namespace}/${sessionId}/properties`;
const entitiy = await this.performRequestWithDeadline('GET', url, undefined, {
acceptedStatusCodes: [200],
contentType: 'json',
timeout: constants_1.TEN_SECONDS,
});
return entitiy;
}
catch (error) {
throw await this.transform(error);
}
}
async getSelectedPropertiesInSession(accountId, namespace, propertyNames, sessionId = constants_1.DEFAULT_ENTITIY) {
const outEntity = {};
// TODO: Maybe need to parallize requests to increase speed
for (const property of propertyNames) {
try {
outEntity[property] = await this.getPropertyInSession(accountId, namespace, property, sessionId);
}
catch (error) {
if (!(0, predicates_1.isNotFoundError)(error)) {
throw error;
}
}
}
return outEntity;
}
async getPropertyInSession(accountId, namespace, propertyName, sessionId = constants_1.DEFAULT_ENTITIY) {
try {
const url = `${this.protocol}://${this.baseUrl}/v1/account/${accountId}/${namespace}/${sessionId}/properties/${propertyName}`;
const value = await this.performRequestWithDeadline('GET', url, undefined, {
acceptedStatusCodes: [200],
contentType: 'string',
timeout: constants_1.TEN_SECONDS,
});
try {
return JSON.parse(value);
}
catch (error) {
return value;
}
}
catch (error) {
throw await this.transform(error);
}
}
async deletePropertyInSession(accountId, namespace, propertyName, sessionId = constants_1.DEFAULT_ENTITIY) {
try {
const url = `${this.protocol}://${this.baseUrl}/v1/account/${accountId}/${namespace}/${sessionId}/properties/${propertyName}`;
await this.performRequestWithDeadline('DELETE', url, undefined, {
acceptedStatusCodes: [204],
contentType: 'buffer',
timeout: constants_1.TEN_SECONDS,
});
}
catch (error) {
throw await this.transform(error);
}
}
async deleteSession(accountId, namespace, sessionId) {
try {
const url = `${this.protocol}://${this.baseUrl}/v1/account/${accountId}/${namespace}/${sessionId}/properties/`;
await this.performRequestWithDeadline('DELETE', url, undefined, {
acceptedStatusCodes: [204],
contentType: 'buffer',
timeout: constants_1.TEN_SECONDS,
});
}
catch (error) {
throw await this.transform(error);
}
}
async getListOfSessions(accountId, namespace) {
try {
const url = `${this.protocol}://${this.baseUrl}/v1/account/${accountId}/${namespace}/session-ids`;
const entityList = await this.performRequestWithDeadline('GET', url, undefined, {
acceptedStatusCodes: [200],
contentType: 'json',
timeout: constants_1.TEN_SECONDS,
});
return entityList;
}
catch (error) {
throw await this.transform(error);
}
}
async performRequestWithDeadline(method, url, body = undefined, options) {
const request = bent(method, options.contentType, ...options.acceptedStatusCodes);
for (let attempt = 0; attempt < 3; attempt++) {
try {
return await (0, helper_1.runTaskWithDeadline)(request(url, body, this.generateHeaders()), options.timeout);
}
catch (error) {
if (!(0, predicates_1.isRetriableError)(error)) {
throw error;
}
if (attempt >= 2) {
throw error;
}
await new Promise((resolve) => setTimeout(resolve, (attempt + 1) * constants_1.CALL_DELAY));
}
}
// This is here because otherwise Typescript complains, but should never reach here
return null;
}
/**
* Helper Method returning an object containing all relevant headers.
*/
generateHeaders() {
// Try to keep then in sync with package.json
const name = '@liveperson/context-service';
const version = '0.1.0';
return {
'maven-api-key': this.apiKey,
// eslint-disable-next-line @typescript-eslint/naming-convention
'Content-Type': 'application/json',
// eslint-disable-next-line @typescript-eslint/naming-convention
Accept: 'application/json',
// eslint-disable-next-line @typescript-eslint/naming-convention
'X-REQUEST-ID': (0, uuid_1.v4)(),
// eslint-disable-next-line @typescript-eslint/naming-convention
'User-Agent': `${name} v${version}`,
};
}
/**
* This method takes an error returned by the bent library and turn it into
* either an RestError or a NetworkError
* @param error object from bent
*/
async transform(error) {
if ((0, predicates_1.isNetworkError)(error)) {
return new networkError_1.NetworkError((error.code || error.errno), error.message);
}
if (typeof (error === null || error === void 0 ? void 0 : error.json) === 'function') {
try {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const { message } = await error.json();
return new restError_1.RestError((error === null || error === void 0 ? void 0 : error.statusCode) || -1, message);
}
catch (_) {
return new restError_1.RestError((error === null || error === void 0 ? void 0 : error.statusCode) || -1, error.message);
}
}
return new restError_1.RestError((error === null || error === void 0 ? void 0 : error.statusCode) || -1, error.message);
}
}
exports.RestClient = RestClient;
//# sourceMappingURL=client.js.map