diff --git a/README.md b/README.md index b979823..6df6755 100644 --- a/README.md +++ b/README.md @@ -56,8 +56,12 @@ SYNC_SUPPLIER = true SYNC_CONN = true SYNC_TRADEITEM = true MAX_REQUEST_RETRIES = 3 + +#DEV OPTIONS +SUPPLIERS_ALWAYS_CONN = false ``` + ## Guidelines - In case a new model is created, it should follow the following structure: diff --git a/floriday.js b/floriday.js index dd95689..d087fca 100644 --- a/floriday.js +++ b/floriday.js @@ -1,4 +1,4 @@ -import { models, checkConn, closeConn } from './models/sequelize.js'; +import { checkConn, closeConn } from './models/sequelize.js'; import * as utils from './utils.js'; import moment from 'moment'; import chalk from 'chalk'; @@ -10,7 +10,7 @@ class Floriday { async start() { try { await utils.checkConfig(); - this.tokenExpirationDate = await utils.requestToken(models); + await utils.requestToken(); if (JSON.parse(env.SYNC_SEQUENCE)) await utils.syncSequence(); if (JSON.parse(env.SYNC_SUPPLIER)) await utils.syncSuppliers(); if (JSON.parse(env.SYNC_CONN)) await utils.syncConn(); @@ -36,8 +36,8 @@ class Floriday { const intervalTime = JSON.parse(env.IS_PRODUCTION) ? env.MS_PRODUCTION_SCHEDULE : env.MS_TEST_SCHEDULE; - - while (true) { + this.continueSchedule = true; + while (this.continueSchedule) { try { await this.trunk(); await new Promise(resolve => setTimeout(resolve, intervalTime)); @@ -64,6 +64,7 @@ class Floriday { } async stop() { + this.continueSchedule = false; await utils.deleteConnections(); await closeConn(); console.warn(chalk.dim('Bye, come back soon 👋')) diff --git a/models/supplier/connections.js b/models/supplier/connections.js index 936d9f8..9d45e34 100644 --- a/models/supplier/connections.js +++ b/models/supplier/connections.js @@ -10,7 +10,7 @@ const connections = { export default (sequelize) => { const connection = sequelize.define( - 'connections', + 'supplier_connections', connections, { timestamps: false, diff --git a/models/supplier/supplier.js b/models/supplier/supplier.js index ff3a699..cfcb745 100644 --- a/models/supplier/supplier.js +++ b/models/supplier/supplier.js @@ -1,59 +1,71 @@ import { Sequelize } from 'sequelize'; const suppliers = { - supplierOrganizationId: { - type: Sequelize.STRING, - allowNull: false, - primaryKey: true, - }, - sequenceNumber: { - type: Sequelize.INTEGER, - allowNull: false, - primaryKey: true, - }, - companyGln: { - type: Sequelize.STRING, - }, - name: { - type: Sequelize.STRING, - }, - commercialName: { - type: Sequelize.STRING, - }, - email: { - type: Sequelize.STRING, - }, - phone: { - type: Sequelize.STRING, - }, - website: { - type: Sequelize.STRING, - }, - rfhRelationId: { - type: Sequelize.INTEGER, - }, - paymentProviders: { - type: Sequelize.STRING, - }, - endDate: { - type: Sequelize.DATE, - }, - mailingAddress: { - type: Sequelize.JSON, - }, - physicalAddress: { - type: Sequelize.JSON, - }, - isConnected: { - type: Sequelize.BOOLEAN, - defaultValue: false, - }, + supplierOrganizationId: { + type: Sequelize.STRING, + allowNull: false, + primaryKey: true, + }, + sequenceNumber: { + type: Sequelize.INTEGER, + allowNull: false, + }, + companyGln: { + type: Sequelize.STRING, + }, + name: { + type: Sequelize.STRING, + }, + commercialName: { + type: Sequelize.STRING, + }, + email: { + type: Sequelize.STRING, + }, + phone: { + type: Sequelize.STRING, + }, + website: { + type: Sequelize.STRING, + }, + rfhRelationId: { + type: Sequelize.INTEGER, + }, + paymentProviders: { + type: Sequelize.JSON, + }, + endDate: { + type: Sequelize.DATE, + }, + mailingAddress: { + type: Sequelize.JSON, + }, + physicalAddress: { + type: Sequelize.JSON, + }, + isConnected: { + type: Sequelize.BOOLEAN, + defaultValue: false, + }, + lastSync: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: Sequelize.NOW, + }, + created: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: Sequelize.NOW, + }, }; export default (sequelize) => { - const Suppliers = sequelize.define('supplier', suppliers, { - timestamps: false, - freezeTableName: true, - }); - return Suppliers; + const Suppliers = sequelize.define( + 'supplier', + suppliers, { + timestamps: false, + freezeTableName: true, + } + ); + return Suppliers; }; \ No newline at end of file diff --git a/models/supplyLine/supplyLine.js b/models/supplyLine/supplyLine.js index c391c00..5c32a7a 100644 --- a/models/supplyLine/supplyLine.js +++ b/models/supplyLine/supplyLine.js @@ -55,15 +55,32 @@ const supplyLine = { }, isCustomerSpecific: { type: Sequelize.BOOLEAN, - } + }, + tradeItemId : { + type: Sequelize.STRING, + }, + supplierOrganizationId : { + type: Sequelize.STRING, + }, + lastSync: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: Sequelize.NOW, + }, + created: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: Sequelize.NOW, + }, }; - - export default (sequelize) => { - const SupplyLine = sequelize.define('supplyLine', supplyLine, { - timestamps: false, - freezeTableName: true, - }); - return SupplyLine; + const SupplyLine = sequelize.define( + 'supplyLine', + supplyLine, { + timestamps: false, + freezeTableName: true, + } + ); + return SupplyLine; }; \ No newline at end of file diff --git a/models/supplyLine/volumePrices.js b/models/supplyLine/volumePrices.js index 4b70bf5..f814848 100644 --- a/models/supplyLine/volumePrices.js +++ b/models/supplyLine/volumePrices.js @@ -1,24 +1,27 @@ import { Sequelize } from 'sequelize'; const volumePrices = { - supplyLineId: { - type: Sequelize.STRING, - primaryKey: true, - }, - unit: { - type: Sequelize.STRING, - primaryKey: true, - }, - pricePerPiece: { - type: Sequelize.DECIMAL(10,2), - primaryKey: true, - }, + supplyLineId: { + type: Sequelize.STRING, + primaryKey: true, + }, + unit: { + type: Sequelize.STRING, + primaryKey: true, + }, + pricePerPiece: { + type: Sequelize.DECIMAL(10,2), + primaryKey: true, + }, }; export default (sequelize) => { - const VolumePrices = sequelize.define('volumePrices', volumePrices, { - timestamps: false, - freezeTableName: true, - }); - return VolumePrices; + const VolumePrices = sequelize.define( + 'supplyLine_volumePrices', + volumePrices, { + timestamps: false, + freezeTableName: true, + } + ); + return VolumePrices; }; \ No newline at end of file diff --git a/models/tradeItem/botanicalNames.js b/models/tradeItem/botanicalNames.js index 478c4b4..cd795d7 100644 --- a/models/tradeItem/botanicalNames.js +++ b/models/tradeItem/botanicalNames.js @@ -1,15 +1,18 @@ import { Sequelize } from 'sequelize'; const botanicalNames = { - name: { - type: Sequelize.STRING, - }, + name: { + type: Sequelize.STRING, + }, }; export default (sequelize) => { - const BotanicalNames = sequelize.define('botanicalNames', botanicalNames, { - timestamps: false, - freezeTableName: true, - }); - return BotanicalNames; -}; + const BotanicalNames = sequelize.define( + 'tradeItem_botanicalNames', + botanicalNames, { + timestamps: false, + freezeTableName: true, + } + ); + return BotanicalNames; +}; \ No newline at end of file diff --git a/models/tradeItem/characteristics.js b/models/tradeItem/characteristics.js index f5c9d36..08e2b6f 100644 --- a/models/tradeItem/characteristics.js +++ b/models/tradeItem/characteristics.js @@ -11,7 +11,7 @@ const characteristics = { export default (sequelize) => { const Characteristics = sequelize.define( - 'characteristics', + 'tradeItem_characteristics', characteristics, { timestamps: false, diff --git a/models/tradeItem/countryOfOriginIsoCodes.js b/models/tradeItem/countryOfOriginIsoCodes.js index c4bfbfc..32f88e3 100644 --- a/models/tradeItem/countryOfOriginIsoCodes.js +++ b/models/tradeItem/countryOfOriginIsoCodes.js @@ -8,7 +8,7 @@ const countryOfOriginIsoCodes = { export default (sequelize) => { const CountryOfOriginIsoCodes = sequelize.define( - 'countryOfOriginIsoCodes', + 'tradeItem_countryOfOriginIsoCodes', countryOfOriginIsoCodes, { timestamps: false, diff --git a/models/tradeItem/packingConfigurations.js b/models/tradeItem/packingConfigurations.js index 3f1fc47..6660101 100644 --- a/models/tradeItem/packingConfigurations.js +++ b/models/tradeItem/packingConfigurations.js @@ -20,7 +20,10 @@ const packingConfigurations = { layersPerLoadCarrier: { type: Sequelize.INTEGER, }, - additionalPricePerPiece: { + additionalPricePerPiece_currency: { + type: Sequelize.STRING, + }, + additionalPricePerPiece_value: { type: Sequelize.STRING, }, transportHeightInCm: { @@ -36,7 +39,7 @@ const packingConfigurations = { export default (sequelize) => { const PackingConfigurations = sequelize.define( - 'packingConfig', + 'tradeItem_packingConfigurations', packingConfigurations, { timestamps: false, diff --git a/models/tradeItem/photos.js b/models/tradeItem/photos.js index 0d5ff16..8599f88 100644 --- a/models/tradeItem/photos.js +++ b/models/tradeItem/photos.js @@ -17,7 +17,7 @@ const photos = { }; export default (sequelize) => { - const Photos = sequelize.define('photos', photos, { + const Photos = sequelize.define('tradeItem_photos', photos, { timestamps: false, freezeTableName: true, }); diff --git a/models/tradeItem/seasonalPeriod.js b/models/tradeItem/seasonalPeriod.js index 5df00df..2cec803 100644 --- a/models/tradeItem/seasonalPeriod.js +++ b/models/tradeItem/seasonalPeriod.js @@ -15,7 +15,7 @@ const seasonalPeriod = { }; export default (sequelize) => { - const SeasonalPeriod = sequelize.define('seasonalPeriod', seasonalPeriod, { + const SeasonalPeriod = sequelize.define('tradeItem_seasonalPeriod', seasonalPeriod, { timestamps: false, freezeTableName: true, }); diff --git a/models/tradeItem/tradeItem.js b/models/tradeItem/tradeItem.js index daa48f2..4e34e0e 100644 --- a/models/tradeItem/tradeItem.js +++ b/models/tradeItem/tradeItem.js @@ -5,9 +5,6 @@ const tradeItem = { type: Sequelize.STRING, primaryKey: true, }, - supplierOrganizationId: { - type: Sequelize.STRING - }, code: { type: Sequelize.STRING }, @@ -34,7 +31,20 @@ const tradeItem = { }, isHiddenInCatalog: { type: Sequelize.BOOLEAN, - } + }, + supplierOrganizationId: { + type: Sequelize.STRING + }, + lastSync: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: Sequelize.NOW, + }, + created: { + type: Sequelize.DATE, + allowNull: false, + defaultValue: Sequelize.NOW, + }, }; export default (sequelize) => { diff --git a/utils.js b/utils.js index f8d5a33..be6ce19 100644 --- a/utils.js +++ b/utils.js @@ -8,12 +8,11 @@ import ora from 'ora'; const env = process.env; /** - * Gets the Access Token from the client config table + * Gets the Access Token * - * @param {sequelize.models} models - * @returns {Date} tokenExpirationDate formated as YYYY-MM-DD HH:mm:ss + * @param {Boolean} isForce Force to request new token */ -export async function requestToken() { +export async function requestToken(isForce = false) { let spinner = ora(`Requesting new token...`).start(); try { const clientConfigData = await models.clientConfig.findOne(); @@ -23,8 +22,8 @@ export async function requestToken() { token = clientConfigData.currentToken; tokenExpirationDate = clientConfigData.tokenExpiration; } - - if (!token || !tokenExpirationDate || moment().isAfter(tokenExpirationDate)) { + + if (isForce || !token || !tokenExpirationDate || moment().isAfter(tokenExpirationDate)) { let clientId, clientSecret if (JSON.parse(env.USE_SECRETS_DB)) { clientId = clientConfigData.clientId; @@ -45,11 +44,9 @@ export async function requestToken() { .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(data[key])}`) .join('&') - const headers = { - 'Content-Type': 'application/x-www-form-urlencoded', - } + const headers = { 'Content-Type': 'application/x-www-form-urlencoded' }; - const response = (await vnRequest('GET', env.API_ENDPOINT, data, headers)).data; + const response = (await vnRequest('POST', env.API_ENDPOINT, data, headers)).data; if (response.statusText = 'OK') spinner.succeed(); @@ -67,13 +64,8 @@ export async function requestToken() { response.access_token, tokenExpirationDate ); - - return tokenExpirationDate; - } else { - spinner.text = 'Using stored token...' - spinner.succeed(); - return tokenExpirationDate; - } + } else + spinner.succeed('Using stored token...'); } catch (err) { spinner.fail(); throw err; @@ -86,10 +78,7 @@ export async function requestToken() { * @returns {string} */ export async function getCurrentToken() { - if (moment().isAfter(await getCurrentTokenExpiration())) - return await requestToken(models); - else - return (await models.clientConfig.findOne()).currentToken; + return (await models.clientConfig.findOne()).currentToken; } /** @@ -289,19 +278,10 @@ export async function syncSuppliers(){ if (timeFinish) spinner.text = spinner.text + ` (${timeLeft})` await models.supplier.upsert({ + ...supplier, supplierOrganizationId: supplier.organizationId, - sequenceNumber: supplier.sequenceNumber, - companyGln: supplier.companyGln ? supplier.companyGln : null, - name: supplier.name ? supplier.name : null, - commercialName: supplier.commercialName ? supplier.commercialName : null, - email: supplier.email ? supplier.email : null, - phone: supplier.phone ? supplier.phone : null, - website: supplier.website ? supplier.website : null, - rfhRelationId: supplier.rfhRelationId ? supplier.rfhRelationId : null, - paymentProviders: supplier.paymentProviders.length ? `${supplier.paymentProviders}` : null, - endDate: supplier.endDate ? supplier.endDate : null, - mailingAddress: supplier.mailingAddress ? supplier.mailingAddress : null, - physicalAddress: supplier.physicalAddress ? supplier.physicalAddress : null, + isConnected: JSON.parse(env.SUPPLIERS_ALWAYS_CONN), + lastSync: moment(), }); }; await syncSequence(curSequenceNumber, 'supplier', maxSequenceNumber); @@ -337,7 +317,7 @@ export async function syncConn(){ let i = 1; for (let connection of connections){ - spinner.text = `Creating ${i++} connections...` + spinner.text = `Creating ${i++} of ${connections.length} connections...` let remoteConnection = remoteConnections.find(remoteConnection => remoteConnection == connection.supplierOrganizationId); if (!remoteConnection){ @@ -378,8 +358,7 @@ export async function syncTradeItems(){ const suppliers = await models.supplier.findAll({ where: { isConnected: true } }); - let i = 0; - let x = 0; + let i = 0, x = 1; for (let supplier of suppliers) { let headers = { 'Content-Type': 'application/json', @@ -394,7 +373,7 @@ export async function syncTradeItems(){ for (let tradeItem of tradeItems) { await insertItem(tradeItem); - spinner.text = `Syncing ${i++} trade items of [${x++}|${suppliers.length}] suppliers...` + spinner.text = `Syncing ${i++} trade items of [${x}|${suppliers.length}] suppliers...` }; } catch (err) { spinner.fail(); @@ -452,8 +431,6 @@ export async function syncSupplyLines(){ resolve(supplyLines); } catch (err) { - if (err.message = 'Request failed with status code 429') - console.log('Request failed with status code 429 - Too many request'); resolve([]); } }); @@ -505,26 +482,8 @@ export async function syncSupplyLines(){ } await models.supplyLine.upsert({ - supplyLineId: line.supplyLineId, - status: line.status, - supplierOrganizationId: line.supplierOrganizationId, - pricePerPiece_currency: line.pricePerPiece.currency, - pricePerPiece_value: line.pricePerPiece.value, - numberOfPieces: line.numberOfPieces, - deliveryPeriod_startDateTime: line.deliveryPeriod.startDateTime, - deliveryPeriod_endDateTime: line.deliveryPeriod.endDateTime, - orderPeriod_startDateTime: line.orderPeriod.startDateTime, - orderPeriod_endDateTime: line.orderPeriod.endDateTime, - warehouseId: line.warehouseId, - sequenceNumber: line.sequenceNumber, - type: line.type, - isDeleted: line.isDeleted, - salesUnit: line.salesUnit, - agreementReference_code: line.agreementReference.code ? line.agreementReference.code : null, - agreementReference_description: line.agreementReference.description ? line.agreementReference.description : null, - isLimited: line.isLimited, - isCustomerSpecific: line.isCustomerSpecific, - tradeItemId: line.tradeItemId, + ...supplyLine, + lastSync: moment(), }); for (let volumePrice of line.volumePrices) @@ -574,17 +533,46 @@ export async function newSyncSupplyLines() { }); }).map(supplier => supplier.supplierOrganizationId); - let i = 1; + let i = 0, x = 1; for (let supplier of suppliers) { - spinner.text = `(NEW) Syncing ${i++} supply lines...` + spinner.text = `(NEW) Syncing ${i} supply lines of [${x++}|${suppliers.length}] suppliers...` const params = new URLSearchParams({ supplierOrganizationId: supplier, }).toString(); let supplyLines = (await vnRequest('GET',`${env.API_URL}/supply-lines?${params}`, null, headers)).data; if (!supplyLines.length) continue - for (let supplyLine of supplyLines) - console.log(supplyLine) + for (let supplyLine of supplyLines) { + + let tradeItem = await models.tradeItem.findOne({ + where: { tradeItemId: supplyLine.tradeItemId } + }); + + if (!tradeItem) { + let tradeItem = (await vnRequest('GET', `${env.API_URL}/trade-items?tradeItemIds=${supplyLine.tradeItemId}`, null, headers)).data; + insertItem(tradeItem[0]) + } + + spinner.text = `(NEW) Syncing ${i++} supply lines of [${x}|${suppliers.length}] suppliers...` + await models.supplyLine.upsert({ + ...supplyLine, + pricePerPiece_currency: supplyLine.pricePerPiece ? supplyLine.pricePerPiece.currency : null, + pricePerPiece_value: supplyLine.pricePerPiece ? supplyLine.pricePerPiece.value : null, + deliveryPeriod_startDateTime: supplyLine.deliveryPeriod ? supplyLine.deliveryPeriod.startDateTime : null, + deliveryPeriod_endDateTime: supplyLine.deliveryPeriod ? supplyLine.deliveryPeriod.endDateTime : null, + orderPeriod_startDateTime: supplyLine.orderPeriod ? supplyLine.orderPeriod.startDateTime : null, + orderPeriod_endDateTime: supplyLine.orderPeriod ? supplyLine.orderPeriod.endDateTime : null, + agreementReference_code: supplyLine.agreementReference ? supplyLine.agreementReference.code : null, + agreementReference_description: supplyLine.agreementReference ? supplyLine.agreementReference.description : null, + lastSync: moment(), + }); + + for (let volumePrice of supplyLine.volumePrices) + await models.volumePrices.upsert({ + ...volumePrice, + supplyLineId: supplyLine.supplyLineId, + }); + } } spinner.succeed(); } @@ -612,72 +600,77 @@ export async function insertItem(tradeItem) { // Upsert trade item await models.tradeItem.upsert({ ...tradeItem, - isDeleted: tradeItem.isDeleted, - isCustomerSpecific: tradeItem.isCustomerSpecific, - isHiddenInCatalog: tradeItem.isHiddenInCatalog, + lastSync: moment(), }, { transaction: tx }); // Upsert characteristics if (tradeItem.characteristics) - for (const characteristic of tradeItem.characteristics) { - await models.characteristic.upsert({ - ...characteristic, - tradeItemId: tradeItem.tradeItemId, - }, { transaction: tx }); - } + if (tradeItem.characteristics.length) + for (const characteristic of tradeItem.characteristics) { + await models.characteristic.upsert({ + ...characteristic, + tradeItemId: tradeItem.tradeItemId, + }, { transaction: tx }); + } // Upsert seasonal periods if (tradeItem.seasonalPeriods) - for (const seasonalPeriod of tradeItem.seasonalPeriods) { - await models.seasonalPeriod.upsert({ - ...seasonalPeriod, - tradeItemId: tradeItem.tradeItemId, - }, { transaction: tx }); - } + if (tradeItem.seasonalPeriods.length) + for (const seasonalPeriod of tradeItem.seasonalPeriods) { + await models.seasonalPeriod.upsert({ + ...seasonalPeriod, + tradeItemId: tradeItem.tradeItemId, + }, { transaction: tx }); + } // Upsert photos if (tradeItem.photos) - for (const photo of tradeItem.photos) { - await models.photo.upsert({ - ...photo, - tradeItemId: tradeItem.tradeItemId, - }, { transaction: tx }); - } + if (tradeItem.photos.length) + for (const photo of tradeItem.photos) { + await models.photo.upsert({ + ...photo, + tradeItemId: tradeItem.tradeItemId, + }, { transaction: tx }); + } // Upsert packing configurations if (tradeItem.packingConfigurations) - for (const packingConfiguration of tradeItem.packingConfigurations) { - const uuid = uuidv4(); + if (tradeItem.packingConfigurations.length) + for (const packingConfiguration of tradeItem.packingConfigurations) { + const uuid = uuidv4(); - await models.packingConfiguration.upsert({ - packingConfigurationId: uuid, - ...packingConfiguration, - additionalPricePerPiece: JSON.stringify(packingConfiguration.additionalPricePerPiece), - tradeItemId: tradeItem.tradeItemId, - }, { transaction: tx }); + 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, - packingConfigurationFk: uuid, - }, { transaction: tx }); - } + await models.package.upsert({ + ...packingConfiguration.package, + packingConfigurationFk: uuid, + }, { transaction: tx }); + } // Upsert country of origin ISO codes if (tradeItem.countryOfOriginIsoCodes) - for (const isoCode of tradeItem.countryOfOriginIsoCodes || []) { - await models.countryOfOriginIsoCode.upsert({ - isoCode, - tradeItemId: tradeItem.tradeItemId, - }, { transaction: tx }); - } + if (tradeItem.countryOfOriginIsoCodes.length) + for (const isoCode of tradeItem.countryOfOriginIsoCodes || []) { + await models.countryOfOriginIsoCode.upsert({ + isoCode, + tradeItemId: tradeItem.tradeItemId, + }, { transaction: tx }); + } // Upsert botanical names if (tradeItem.botanicalNames) - for (const botanicalName of tradeItem.botanicalNames) { - await models.botanicalName.upsert({ - ...botanicalName, - tradeItemId: tradeItem.tradeItemId, - }, { transaction: tx }); - } + if (tradeItem.botanicalNames.length) + for (const botanicalName of tradeItem.botanicalNames) { + await models.botanicalName.upsert({ + name: botanicalName, + tradeItemId: tradeItem.tradeItemId, + }, { transaction: tx }); + } await tx.commit(); } catch (err) { @@ -720,24 +713,42 @@ export async function deleteConnections() { * * @return {array} **/ -export async function vnRequest(method = 'GET', url, data = null, headers = {}) { - let response; +export async function vnRequest(method, url, data, headers) { for(let i = 0; i < env.MAX_REQUEST_RETRIES; i++) { try { if (['GET', 'DELETE'].includes(method)) - response = await axios({method, url, headers}); + return await axios({method, url, headers}); else - response = await axios({method, url, data, headers}); - break; + return await axios({method, url, data, headers}); } catch (err) { - if (err.code == 'ECONNRESET') - warning(err) - else - criticalError(err) - await sleep(1000) + switch (err.code) { + case 'ECONNRESET': // Client network socket TLS + warning(err); + await sleep(1000); + break; + case 'ECONNABORTED': + case 'ECONNREFUSED': + case 'ERR_BAD_REQUEST': + switch (err.response.status) { + case 429: // Too Many Requests + warning(err); + await sleep(3400); // Stipulated by floryday + case 401: // Unauthorized + warning(err); + await requestToken(true); + headers.Authorization ? + headers.Authorization = `Bearer ${await getCurrentToken()}` : + criticalError(err); + break; + default: + criticalError(err); + } + break; + default: + criticalError(err); + } } } - return response; } /**