floriday/utils.js

653 lines
19 KiB
JavaScript
Raw Normal View History

2023-05-09 12:13:19 +00:00
import { models } from './models/sequelize.js';
2023-05-30 09:22:39 +00:00
import { Op } from 'sequelize';
2023-02-08 11:31:54 +00:00
import { v4 as uuidv4 } from 'uuid';
import axios from 'axios';
import moment from 'moment';
import chalk from 'chalk';
import ora from 'ora';
const env = process.env;
2023-01-11 13:37:46 +00:00
/**
2023-05-19 11:47:36 +00:00
* Gets the Access Token.
*
2023-05-15 12:19:43 +00:00
* @param {Boolean} isForce Force to request new token
*/
2023-05-15 12:19:43 +00:00
export async function requestToken(isForce = false) {
let spinner = ora(`Requesting new token...`).start();
2023-05-05 09:48:44 +00:00
try {
const clientConfigData = await models.config.findOne();
2023-05-05 09:48:44 +00:00
2023-05-19 06:47:32 +00:00
let tokenExpiration, token;
2023-05-11 07:43:27 +00:00
if (clientConfigData) {
token = clientConfigData.currentToken;
2023-05-19 06:47:32 +00:00
tokenExpiration = clientConfigData.tokenExpiration;
2023-05-11 07:43:27 +00:00
}
2023-05-15 12:19:43 +00:00
2023-05-19 06:47:32 +00:00
if (isForce || !token || !tokenExpiration || moment().isAfter(tokenExpiration)) {
const clientId = JSON.parse(env.USE_SECRETS_DB) ? clientConfigData.clientId || env.CLIENT_ID : env.CLIENT_ID;
const clientSecret = JSON.parse(env.USE_SECRETS_DB) ? clientConfigData.clientSecret || env.CLIENT_SECRET : env.CLIENT_SECRET;
2023-05-05 09:48:44 +00:00
2023-05-19 06:47:32 +00:00
const data = new URLSearchParams({
2023-05-05 09:48:44 +00:00
grant_type: 'client_credentials',
client_id: clientId,
client_secret: clientSecret,
scope: 'role:app catalog:read supply:read organization:read network:write network:read'
2023-05-19 06:47:32 +00:00
}).toString();
2023-05-15 12:19:43 +00:00
const headers = { 'Content-Type': 'application/x-www-form-urlencoded' };
const response = (await vnRequest('POST', env.API_ENDPOINT, data, headers, spinner)).data;
2023-05-19 06:47:32 +00:00
const tokenExpiration = moment()
.add(response.expires_in, 's')
2023-05-05 09:48:44 +00:00
.format('YYYY-MM-DD HH:mm:ss');
2023-05-19 06:47:32 +00:00
await updateClientConfig({
2023-05-05 09:48:44 +00:00
clientId,
clientSecret,
2023-05-19 06:47:32 +00:00
currentToken: response.access_token,
tokenExpiration,
});
spinner.succeed();
2023-05-15 12:19:43 +00:00
} else
spinner.succeed('Using stored token...');
2023-05-05 09:48:44 +00:00
} catch (err) {
spinner.fail();
throw err;
2023-04-24 10:46:06 +00:00
}
}
2023-04-06 08:56:52 +00:00
/**
2023-05-19 11:47:36 +00:00
* Returns the current token.
*
2023-04-06 08:56:52 +00:00
* @returns {string}
*/
export async function getCurrentToken() {
return (await models.config.findOne()).currentToken;
}
2023-05-08 10:18:14 +00:00
/**
2023-05-19 11:47:36 +00:00
* Check the floriday data config.
2023-05-08 10:18:14 +00:00
*/
export async function checkConfig() {
const spinner = ora(`Checking config...`).start();
const excludedEnvVars = ['VSCODE_GIT_ASKPASS_EXTRA_ARGS'];
const requiredEnvVars = Object.keys(env);
const filteredEnvVars = requiredEnvVars.filter(reqEnvVar => !excludedEnvVars.includes(reqEnvVar));
for (const reqEnvVar of filteredEnvVars) {
if (!process.env[reqEnvVar]) {
spinner.fail();
throw new Error(`You haven't provided the ${reqEnvVar} environment variable`);
}
}
const clientConfigData = await models.config.findOne();
2023-05-08 11:02:31 +00:00
if (!clientConfigData)
await updateClientConfig(env.CLIENT_ID, env.CLIENT_SECRET);
2023-05-08 10:18:14 +00:00
spinner.succeed();
}
2023-04-24 10:46:06 +00:00
2023-04-06 08:56:52 +00:00
/**
2023-05-19 11:47:36 +00:00
* Returns the expiration of current token.
*
2023-04-06 08:56:52 +00:00
* @returns {string}
*/
export async function getCurrentTokenExpiration() {
return (await models.config.findOne()).tokenExpiration;
}
/**
2023-05-19 11:47:36 +00:00
* Updates the access token in the client config table.
*
2023-05-19 06:47:32 +00:00
* @param {Array} clientConfig [clientId, clientSecret, currenToken, tokenExpiration]
*/
2023-05-19 06:47:32 +00:00
export async function updateClientConfig(clientConfig) {
try {
2023-06-12 12:42:33 +00:00
if (!JSON.parse(process.env.USE_SECRETS_DB))
clientId = clientSecret = null
await models.config.upsert({
id: 1,
...clientConfig,
});
2023-05-19 06:47:32 +00:00
} catch (err) {
throw(err);
}
}
2023-01-11 12:13:22 +00:00
/**
2023-05-19 11:47:36 +00:00
* Pauses the execution of the script for the specified number of milliseconds.
*
* @param {Integer} ms
2023-01-11 12:13:22 +00:00
*/
export async function sleep(ms) {
2023-05-19 11:47:36 +00:00
await new Promise(resolve => setTimeout(resolve, ms));
2023-01-11 12:13:22 +00:00
}
2023-05-17 05:36:58 +00:00
/**
2023-06-12 12:42:33 +00:00
* Sync a model.
*
* @param {String} model (organization | tradeItem | supplyLine | clockPresaleSupply)
2023-05-17 05:36:58 +00:00
*/
2023-06-12 12:42:33 +00:00
export async function syncModel(model) {
let spinner = ora(`Syncing ${model}...`).start();
let i = 1;
2023-04-24 10:46:06 +00:00
try {
2023-06-12 12:42:33 +00:00
const dbSeqNum = await models.sequenceNumber.findOne({ where: { model } })
let curSeqNum = dbSeqNum?.maxSequenceNumber ?? 0;
let maxSeqUrl, syncUrl;
switch (model) {
case 'organization':
maxSeqUrl = `${env.API_URL}/organizations/current-max-sequence`;
syncUrl = `${env.API_URL}/organizations/sync/`;
break;
case 'warehouse':
maxSeqUrl = `${env.API_URL}/warehouses/current-max-sequence`;
syncUrl = `${env.API_URL}/warehouses/sync/`;
break;
case 'tradeItem':
maxSeqUrl = `${env.API_URL}/trade-items/current-max-sequence`;
syncUrl = `${env.API_URL}/trade-items/sync/`;
break;
case 'supplyLine':
maxSeqUrl = `${env.API_URL}/supply-lines/current-max-sequence`;
syncUrl = `${env.API_URL}/supply-lines/sync/`;
break;
case 'clockPresaleSupply':
maxSeqUrl = `${env.API_URL}/auction/clock-presales-supply/max-sequence-number`;
syncUrl = `${env.API_URL}/auction/clock-presales-supply/sync/`;
break;
default:
throw new Error('Unsupported model');
}
const maxSeqNum = (await vnRequest('GET', maxSeqUrl, null, null, spinner)).data;
for (curSeqNum; curSeqNum < maxSeqNum; curSeqNum++) {
let params, misSeqNum;
if (model === 'organization')
params = new URLSearchParams({organizationType: 'SUPPLIER'}).toString();
else if (model === 'supplyLine')
params = new URLSearchParams({postFilterSelectedTradeItems: false}).toString();
const res = (await vnRequest('GET', `${syncUrl}${curSeqNum}${params ? `?${params}` : ''}`, null, null, spinner)).data;
curSeqNum = res.maximumSequenceNumber;
const objects = res.results;
misSeqNum = maxSeqNum - curSeqNum;
spinner.text = `Syncing ${i - 1} ${model}, ${misSeqNum} missing...`;
for (let object of objects) {
switch (model) {
case 'organization':
await insertOrganization(object);
break;
case 'warehouse':
await insertWarehouse(object);
break;
case 'tradeItem':
await insertTradeItem(object);
break;
case 'supplyLine':
await insertSupplyLine(object);
break;
case 'clockPresaleSupply':
await insertClockPresalesSupply(object);
break;
default:
throw new Error('Unsupported model');
}
spinner.text = `Syncing ${i++} ${model}, ${misSeqNum} missing...`
};
await insertSequenceNumber(model, curSeqNum);
}
if (curSeqNum < maxSeqNum)
await insertSequenceNumber(model, maxSeqNum);
spinner.text = (i != 1)
? `Syncing ${i} ${model}...`
: `Syncing ${model}... ${chalk.gray('(Not found)')}`;
spinner.succeed();
} catch (err) {
2023-04-24 10:46:06 +00:00
spinner.fail();
2023-06-12 12:42:33 +00:00
throw err;
2023-04-24 10:46:06 +00:00
}
2023-01-24 12:51:44 +00:00
}
2023-06-12 12:42:33 +00:00
/**
2023-05-19 11:47:36 +00:00
* Create the connections in Floriday.
*/
export async function syncConnections(){
await deleteConnections();
let spinner;
2023-04-24 10:46:06 +00:00
try {
2023-06-12 12:42:33 +00:00
let connectionsInDb = await models.organization.findAll({
where: {
isConnected: true,
companyGln: {
[Op.ne]: null
},
rfhRelationId: {
[Op.ne]: null
},
}
});
2023-04-24 10:46:06 +00:00
const connectionsInFloriday = (await vnRequest('GET', `${env.API_URL}/connections`, null, null, spinner)).data;
let isExists = false, connectionsToPut = [];
for (let connectionInDb of connectionsInDb) {
for (let connectionInFloriday of connectionsInFloriday)
if (connectionInFloriday == connectionInDb.organizationId) {
isExists = true;
break;
}
if (!isExists) connectionsToPut.push(connectionInDb.organizationId)
isExists = false;
}
if (connectionsToPut.length) spinner = ora(`Creating connections in Floriday...`).start();
let i = 1;
for (let connection of connectionsToPut) {
spinner.text = `Creating ${i++} of ${connectionsToPut.length} connections in Floriday...`
await vnRequest('PUT', `${env.API_URL}/connections/${connection}`, null, null, spinner);
2023-04-24 10:46:06 +00:00
}
if (spinner) spinner.succeed();
2023-04-24 10:46:06 +00:00
} catch (err) {
if (spinner) spinner.fail();
2023-04-24 10:46:06 +00:00
throw new Error(err);
}
2023-02-10 09:42:54 +00:00
}
/**
* Insert sequence number in the database.
*
* @param {String} model
* @param {Number} sequenceNumber
*/
export async function insertSequenceNumber(model, sequenceNumber) {
const tx = await models.sequelize.transaction();
try {
await models.sequenceNumber.upsert({
model: model,
maxSequenceNumber: sequenceNumber,
}, { transaction: tx });
await tx.commit();
} catch (err) {
await tx.rollback();
throw err;
}
}
/**
2023-05-19 11:47:36 +00:00
* Insert trade item and dependences in the database.
*
2023-05-19 06:47:32 +00:00
* @param {Array} tradeItem
*/
export async function insertTradeItem(tradeItem) {
2023-05-19 11:47:36 +00:00
const tx = await models.sequelize.transaction();
2023-04-24 10:46:06 +00:00
try {
2023-05-09 12:13:19 +00:00
// Upsert trade item
2023-04-24 10:46:06 +00:00
await models.tradeItem.upsert({
2023-05-09 12:13:19 +00:00
...tradeItem,
organizationId: tradeItem.supplierOrganizationId,
2023-05-15 12:19:43 +00:00
lastSync: moment(),
2023-05-09 12:13:19 +00:00
}, { transaction: tx });
2023-04-24 10:46:06 +00:00
2023-05-09 12:13:19 +00:00
// Upsert characteristics
if (tradeItem.characteristics)
2023-05-15 12:19:43 +00:00
if (tradeItem.characteristics.length)
for (const characteristic of tradeItem.characteristics) {
await models.characteristic.upsert({
tradeItemId: tradeItem.tradeItemId,
2023-05-19 11:47:36 +00:00
...characteristic,
2023-05-15 12:19:43 +00:00
}, { transaction: tx });
}
2023-05-09 12:13:19 +00:00
// Upsert seasonal periods
if (tradeItem.seasonalPeriods)
2023-05-15 12:19:43 +00:00
if (tradeItem.seasonalPeriods.length)
for (const seasonalPeriod of tradeItem.seasonalPeriods) {
await models.seasonalPeriod.upsert({
tradeItemId: tradeItem.tradeItemId,
2023-05-19 11:47:36 +00:00
...seasonalPeriod,
2023-05-15 12:19:43 +00:00
}, { transaction: tx });
}
2023-04-24 10:46:06 +00:00
2023-05-09 12:13:19 +00:00
// Upsert photos
if (tradeItem.photos)
2023-05-15 12:19:43 +00:00
if (tradeItem.photos.length)
for (const photo of tradeItem.photos) {
await models.photo.upsert({
...photo,
tradeItemId: tradeItem.tradeItemId,
}, { transaction: tx });
}
2023-04-24 10:46:06 +00:00
2023-05-09 12:13:19 +00:00
// Upsert packing configurations
if (tradeItem.packingConfigurations)
2023-05-15 12:19:43 +00:00
if (tradeItem.packingConfigurations.length)
for (const packingConfiguration of tradeItem.packingConfigurations) {
const uuid = uuidv4();
await models.packingConfiguration.upsert({
packingConfigurationId: uuid,
...packingConfiguration,
additionalPricePerPiece_currency: packingConfiguration.additionalPricePerPiece.currency,
additionalPricePerPiece_value: packingConfiguration.additionalPricePerPiece.value,
tradeItemId: tradeItem.tradeItemId,
}, { transaction: tx });
await models.package.upsert({
...packingConfiguration.package,
packingConfigurationId: uuid,
2023-05-15 12:19:43 +00:00
}, { transaction: tx });
}
2023-04-24 10:46:06 +00:00
2023-05-09 12:13:19 +00:00
// Upsert country of origin ISO codes
if (tradeItem.countryOfOriginIsoCodes)
2023-05-15 12:19:43 +00:00
if (tradeItem.countryOfOriginIsoCodes.length)
for (const isoCode of tradeItem.countryOfOriginIsoCodes || []) {
await models.countryOfOriginIsoCode.upsert({
isoCode,
tradeItemId: tradeItem.tradeItemId,
}, { transaction: tx });
}
2023-04-24 10:46:06 +00:00
2023-05-09 12:13:19 +00:00
// Upsert botanical names
if (tradeItem.botanicalNames)
2023-05-15 12:19:43 +00:00
if (tradeItem.botanicalNames.length)
for (const botanicalName of tradeItem.botanicalNames) {
await models.botanicalName.upsert({
botanicalNameId: uuidv4(),
2023-05-15 12:19:43 +00:00
name: botanicalName,
tradeItemId: tradeItem.tradeItemId,
}, { transaction: tx });
}
2023-04-24 10:46:06 +00:00
await tx.commit();
2023-05-09 12:13:19 +00:00
} catch (err) {
2023-04-24 10:46:06 +00:00
await tx.rollback();
throw err;
2023-04-24 10:46:06 +00:00
}
2023-02-14 12:34:54 +00:00
}
2023-05-30 09:22:39 +00:00
/**
* Insert clock presales supply in the database.
*
* @param {Array} clockPresaleSupply
2023-05-30 09:22:39 +00:00
*/
export async function insertClockPresalesSupply(clockPresaleSupply) {
2023-05-30 09:22:39 +00:00
const tx = await models.sequelize.transaction();
try {
await models.clockPresaleSupply.upsert({
...clockPresaleSupply,
pricePerPiece_currency: clockPresaleSupply.pricePerPiece.currency,
pricePerPiece_value: clockPresaleSupply.pricePerPiece.value,
organizationId: clockPresaleSupply.supplierOrganizationId,
}, { transaction: tx });
2023-05-30 09:22:39 +00:00
await tx.commit();
} catch (err) {
await tx.rollback();
throw err;
}
}
/**
2023-05-19 11:47:36 +00:00
* Insert warehouse in the database.
*
2023-05-19 06:47:32 +00:00
* @param {Array} warehouse
*/
export async function insertWarehouse(warehouse) {
2023-05-19 11:47:36 +00:00
const tx = await models.sequelize.transaction();
try {
await models.warehouse.upsert({
...warehouse,
location_gln: warehouse.location.gln,
location_address_addressLine: warehouse.location.address.addressLine,
location_address_city: warehouse.location.address.city,
location_address_countryCode: warehouse.location.address.countryCode,
location_address_postalCode: warehouse.location.address.postalCode,
location_address_stateOrProvince: warehouse.location.address.stateOrProvince,
lastSync: moment(),
}, { transaction: tx });
await tx.commit();
} catch (err) {
await tx.rollback();
throw err;
}
}
2023-05-18 12:06:11 +00:00
/**
2023-05-19 11:47:36 +00:00
* Insert organization in the database.
*
2023-05-19 06:47:32 +00:00
* @param {Array} organization
2023-05-18 12:06:11 +00:00
*/
export async function insertOrganization(organization) {
2023-05-19 11:47:36 +00:00
const tx = await models.sequelize.transaction();
2023-05-18 12:06:11 +00:00
try {
await models.organization.upsert({
...organization,
2023-05-19 11:47:36 +00:00
isConnected: JSON.parse(env.ORGS_ALWAYS_CONN),
2023-05-18 12:06:11 +00:00
lastSync: moment(),
}, { transaction: tx });
await tx.commit();
} catch (err) {
await tx.rollback();
throw err;
}
}
/**
* Insert supply line and dependences in the database.
*
* @param {Array} supplyLine
*/
export async function insertSupplyLine(supplyLine) {
const tx = await models.sequelize.transaction();
try {
2023-06-12 12:42:33 +00:00
// Check if the warehouse exists, and if it doesn't, create it
let warehouse = await models.warehouse.findOne({
2023-06-12 12:51:34 +00:00
where: { warehouseId: supplyLine.warehouseId }
2023-06-12 12:42:33 +00:00
});
if (!warehouse) {
2023-06-13 05:20:21 +00:00
let warehouse = (await vnRequest('GET', `${env.API_URL}/warehouses/${supplyLine.warehouseId}`, null, null, null)).data;
2023-06-12 12:42:33 +00:00
// Check if the organization exists, and if it doesn't, create it
let organization = await models.organization.findOne({
where: { organizationId: warehouse.organizationId }
}, { transaction: tx });
if (!organization) {
2023-06-13 05:20:21 +00:00
let organization = (await vnRequest('GET', `${env.API_URL}/organizations/${warehouse.organizationId}`, null, null, null)).data;
2023-06-12 12:42:33 +00:00
await insertOrganization(organization);
}
await insertWarehouse(warehouse);
}
// Check if the trade item exists, and if it doesn't, create it
let tradeItem = await models.tradeItem.findOne({
where: { tradeItemId: supplyLine.tradeItemId }
}, { transaction: tx });
if (!tradeItem) {
2023-06-13 05:20:21 +00:00
let tradeItem = (await vnRequest('GET', `${env.API_URL}/trade-items/${supplyLine.tradeItemId}`, null, null, null)).data;
2023-06-12 12:42:33 +00:00
await insertTradeItem(tradeItem);
}
await models.supplyLine.upsert({
...supplyLine,
organizationId: supplyLine.supplierOrganizationId,
deliveryPeriodStartDateTime: supplyLine.deliveryPeriod?.startDateTime ?? null,
deliveryPeriodEndDateTime: supplyLine.deliveryPeriod?.endDateTime ?? null,
orderPeriodStartDateTime: supplyLine.orderPeriod?.startDateTime ?? null,
orderPeriodEndDateTime: supplyLine.orderPeriod?.endDateTime ?? null,
agreementReference_code: supplyLine.agreementReference?.code ?? null,
agreementReference_description: supplyLine.agreementReference?.description ?? null,
lastSync: moment(),
}, { transaction: tx });
// Upsert packing configurations
if (supplyLine.packingConfigurations.length)
2023-06-12 12:42:33 +00:00
for (const packingConfiguration of supplyLine.packingConfigurations)
await models.supplyLinePackingConfiguration.upsert({
packingConfigurationId: uuidv4(),
...packingConfiguration,
packageVbnPackageCode: packingConfiguration.package.vbnPackageCode,
packageCustomPackageId: packingConfiguration.package.customPackageId,
additionalPricePerPieceCurrency: packingConfiguration.additionalPricePerPiece.currency,
additionalPricePerPieceValue: packingConfiguration.additionalPricePerPiece.value,
supplyLineId: supplyLine.supplyLineId,
}, { transaction: tx });
2023-06-12 12:42:33 +00:00
// Upsert volume price
for (let volumePrice of supplyLine.volumePrices)
await models.volumePrice.upsert({
supplyLineId: supplyLine.supplyLineId,
...volumePrice,
}, { transaction: tx });
2023-05-18 12:06:11 +00:00
await tx.commit();
} catch (err) {
await tx.rollback();
throw err;
}
}
/**
2023-05-19 11:47:36 +00:00
* Removes Floriday connections that we don't have in the database.
**/
export async function deleteConnections() {
let spinner;
try {
let i = 1;
const connectionsInFloriday = (await vnRequest('GET', `${env.API_URL}/connections`, null, null, spinner)).data;
const connectionsInDb = await models.organization.findAll({
attributes: ['organizationId'],
where: { isConnected: true }
});
let isExists = false, ghostConnections = [];
for (let connectionInFloriday of connectionsInFloriday) {
for (let connectionInDb of connectionsInDb)
if (connectionInFloriday == connectionInDb.organizationId) {
isExists = true;
break;
}
if (!isExists) ghostConnections.push(connectionInFloriday)
isExists = false;
}
2023-05-19 06:47:32 +00:00
if (ghostConnections.length) spinner = ora(`Deleting connections that aren't in the db...`).start();
for (let connection of ghostConnections) {
await vnRequest('DELETE', `${env.API_URL}/connections/${connection}`, null, null, spinner);
2023-06-12 12:42:33 +00:00
spinner.text = `Deleting ${i++} of ${ghostConnections.length} connections that aren't in the db...`
}
if (spinner) spinner.succeed();
} catch (err) {
if (spinner) spinner.fail();
criticalError(err);
}
}
/**
2023-05-19 11:47:36 +00:00
* Perform a REST request.
*
2023-05-19 06:47:32 +00:00
* @param {String} url
* @param {String} method
* @param {Array} body
* @param {Array} header
* @param {Array} spinner
2023-05-19 11:47:36 +00:00
*
2023-05-19 06:47:32 +00:00
* @return {Array}
**/
export async function vnRequest(method, url, data, headers, spinner) {
2023-05-17 08:59:27 +00:00
if (!headers)
headers = {
'Content-Type': 'application/json',
'Authorization': `Bearer ${await getCurrentToken()}`,
'X-Api-Key': process.env.API_KEY,
};
while(true) {
try {
2023-05-19 06:47:32 +00:00
return (['GET', 'DELETE'].includes(method))
? await axios({method, url, headers})
: await axios({method, url, data, headers});
} catch (err) {
switch (err.code) {
case 'ECONNRESET': // Client network socket TLS
case 'EAI_AGAIN': // getaddrinfo
2023-05-22 09:46:01 +00:00
if (spinner) spinner.warn();
warning(err);
await sleep(1000);
2023-05-22 09:46:01 +00:00
if (spinner) spinner.start();
break;
case 'ECONNABORTED':
case 'ECONNREFUSED':
case 'ERR_BAD_REQUEST':
switch (err.response.status) {
2023-05-30 09:22:39 +00:00
case 404: // Not found
return err;
case 504:
case 502:
if (spinner) spinner.warn();
warning(err);
await sleep(1000);
if (spinner) spinner.start();
break;
case 429: // Too Many Requests
if (spinner) spinner.warn();
warning(err);
2023-05-30 09:22:39 +00:00
await sleep(60000);
if (spinner) spinner.start();
break;
case 401: // Unauthorized
if (spinner) spinner.warn();
warning(err);
await requestToken(true);
headers.Authorization
? headers.Authorization = `Bearer ${await getCurrentToken()}`
: criticalError(err);
if (spinner) spinner.start();
break;
default:
if (spinner) spinner.warn();
warning(err);
await sleep(env.MS_RETRY_UNHANDLED_ERROR);
if (spinner) spinner.start();
break;
}
break;
default:
if (spinner) spinner.warn();
warning(err);
await sleep(env.MS_RETRY_UNHANDLED_ERROR);
if (spinner) spinner.start();
break;
}
2023-05-15 12:19:43 +00:00
}
2023-05-19 11:47:36 +00:00
}
}
/**
2023-05-19 11:47:36 +00:00
* Critical error.
*
* @param {err}
**/
export async function criticalError(err) {
2023-05-19 06:47:32 +00:00
console.log(chalk.red.bold(`[CRITICAL]`), chalk.red(err.message));
2023-04-24 10:46:06 +00:00
process.exit();
}
/**
2023-05-19 11:47:36 +00:00
* Warning.
*
* @param {err}
**/
export async function warning(err) {
(err.response?.status && err.response?.data?.message)
? (console.log(chalk.yellow.bold(`[WARNING]`), chalk.yellow(`${err.response.status} - ${err.response.data.message}`)))
: (console.log(chalk.yellow.bold(`[WARNING]`), chalk.yellow(err.message)));
}