refs #4823 Library colors to chalk and more

This commit is contained in:
Guillermo Bonet 2023-04-05 14:46:25 +02:00
parent 76029cda3c
commit 69227f3853
8 changed files with 160 additions and 203 deletions

34
floriday.js Normal file
View File

@ -0,0 +1,34 @@
import * as vnUtils from './utils.js';
import { models } from './models/index.js';
import moment from 'moment';
// Añade la hora a todos los console.log
// console.log = (...args) => console.info(`${new moment().format('HH:mm:ss')} -`, ...args);
const env = process.env;
class Floriday {
async start() {
try {
this.tokenExpirationDate = await vnUtils.getClientToken(models);
if (JSON.parse(env.SYNC_SEQUENCE)) await vnUtils.syncSequence()
if (JSON.parse(env.SYNC_SUPPLIER)) await vnUtils.syncSuppliers();
await vnUtils.syncConnections();
if (JSON.parse(env.SYNC_TRADEITEM)) await vnUtils.syncTradeItems();
} catch (err) {
vnUtils.criticalError(err);
}
}
async schedule() {
try{
if (moment().isAfter(await vnUtils.getCurrentTokenExpiration())) {
this.tokenExpirationDate = await vnUtils.getClientToken(models);
}
await vnUtils.syncSupplyLines();
} catch (err) {
throw(err);
}
}
}
export default Floriday;

70
main.js
View File

@ -1,60 +1,20 @@
import * as vnUtils from './utils.js';
import { models } from './models/index.js';
import moment from 'moment';
// Añade la hora a todos los console.log
// console.log = (...args) => console.info(`${new moment().format('HH:mm:ss')} -`, ...args);
import Floriday from './floriday.js';
const env = process.env;
async function main() {
try {
const env = process.env;
let tokenExpirationDate = await vnUtils.getClientToken(models);
const floriday = new Floriday();
if (JSON.parse(env.SYNC_SEQUENCE)) await vnUtils.syncSequence()
if (JSON.parse(env.SYNC_SUPPLIER)) await vnUtils.syncSuppliers();
await vnUtils.syncConnections();
await floriday.start();
process.on('SIGINT', async function() {
console.log('\nBye <3')
process.exit();
});
if (JSON.parse(env.SYNC_TRADEITEM)) await vnUtils.syncTradeItems();
console.log('Synced trade items');
try {
while (true) {
try{
console.log('Querying the API to check for new data...');
if (moment().isAfter(tokenExpirationDate)) {
console.log('Token expired, getting a new one...');
tokenExpirationDate = await vnUtils.getClientToken(models);
}
await vnUtils.syncSupplyLines();
} catch (err) {
console.error(err);
}
if (JSON.parse(env.IS_PRODUCTION))
await vnUtils.sleep(300000);
else
await vnUtils.sleep(120000);
}
} catch (err) {
myErr(err);
}
} catch (err) {
myErr(err);
}
await floriday.schedule()
const intervalTime = JSON.parse(env.IS_PRODUCTION) ? 300000 : 5000;
setInterval(async () => {
await floriday.schedule();
}, intervalTime);
}
/**
* Creates the connection to the database.
*
* @param {err}
**/
function myErr(err) {
console.log(`[ERROR]`.red.bold, `${err.name}: ${err.message}`.red);
process.exit();
}
main()
main();

View File

@ -1,19 +1,20 @@
import { Sequelize } from 'sequelize';
import dotenv from 'dotenv';
import colors from 'colors';
import chalk from 'chalk';
import ora from 'ora';
import { criticalError } from './../utils.js';
dotenv.config();
console.clear()
console.log(
console.log(chalk.hex('#06c581')(
`
`.green
)
`
))
let sequelize = createConnection();
const conSpinner = ora('Creating connection...').start();
@ -22,7 +23,7 @@ try {
conSpinner.succeed();
} catch (err) {
conSpinner.fail();
myErr(err);
criticalError(err);
}
// Supply Line Models
@ -188,17 +189,7 @@ try {
}
catch (err) {
modSpinner.fail();
myErr(err);
}
/**
* Creates the connection to the database.
*
* @param {err}
**/
function myErr(err) {
console.log(`[ERROR]`.red.bold, `${err.name}: ${err.message}`.red);
process.exit();
criticalError(err);
}
/**

61
package-lock.json generated
View File

@ -6,7 +6,7 @@
"": {
"name": "floriday",
"dependencies": {
"colors": "^1.4.0",
"chalk": "^5.2.0",
"dotenv": "^16.0.3",
"mariadb": "^3.0.2",
"moment": "^2.29.4",
@ -283,16 +283,11 @@
}
},
"node_modules/chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dev": true,
"dependencies": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
},
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz",
"integrity": "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==",
"engines": {
"node": ">=10"
"node": "^12.17.0 || ^14.13 || >=16.0.0"
},
"funding": {
"url": "https://github.com/chalk/chalk?sponsor=1"
@ -349,14 +344,6 @@
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"node_modules/colors": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz",
"integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==",
"engines": {
"node": ">=0.1.90"
}
},
"node_modules/concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@ -568,6 +555,22 @@
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
}
},
"node_modules/eslint/node_modules/chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dev": true,
"dependencies": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/chalk/chalk?sponsor=1"
}
},
"node_modules/espree": {
"version": "9.4.1",
"resolved": "https://registry.npmjs.org/espree/-/espree-9.4.1.tgz",
@ -1035,17 +1038,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/log-symbols/node_modules/chalk": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz",
"integrity": "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==",
"engines": {
"node": "^12.17.0 || ^14.13 || >=16.0.0"
},
"funding": {
"url": "https://github.com/chalk/chalk?sponsor=1"
}
},
"node_modules/lru-cache": {
"version": "7.14.1",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.14.1.tgz",
@ -1228,17 +1220,6 @@
"url": "https://github.com/chalk/ansi-regex?sponsor=1"
}
},
"node_modules/ora/node_modules/chalk": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz",
"integrity": "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==",
"engines": {
"node": "^12.17.0 || ^14.13 || >=16.0.0"
},
"funding": {
"url": "https://github.com/chalk/chalk?sponsor=1"
}
},
"node_modules/ora/node_modules/strip-ansi": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz",

View File

@ -3,7 +3,7 @@
"module": "index.ts",
"type": "module",
"dependencies": {
"colors": "^1.4.0",
"chalk": "^5.2.0",
"dotenv": "^16.0.3",
"mariadb": "^3.0.2",
"moment": "^2.29.4",

View File

@ -1,9 +0,0 @@
let floraholland = [
8713783893456,
8713782539218,
8713782545820,
8718288004970,
];
export default {floraholland};

View File

@ -1,29 +0,0 @@
{
"commercialName": "Viveros Las Cunas",
"email": null,
"phone": null,
"website": null,
"mailingAddress": {
"addressLine": "Carretera 0A-352",
"city": "Vera - Almeria",
"countryCode": "ES",
"postalCode": "04620",
"stateOrProvince": null
},
"physicalAddress": {
"addressLine": "Carretera 0A-352",
"city": "Vera - Almeria",
"countryCode": "ES",
"postalCode": "04620",
"stateOrProvince": null
},
"phytosanitaryNumber": null,
"sequenceNumber": 195803,
"organizationId": "ebc1894a-c3be-3a19-9de2-40b2e691cc9f",
"companyGln": "8718288089847",
"name": "Viveros Las Cunas",
"endDate": null,
"rfhRelationId": 0,
"organizationType": "SUPPLIER",
"paymentProviders": []
}

135
utils.js
View File

@ -2,7 +2,7 @@ import moment from 'moment';
import fetch from 'node-fetch';
import { models } from './models/index.js';
import { v4 as uuidv4 } from 'uuid';
import colors from 'colors';
import chalk from 'chalk';
import ora from 'ora';
// The Endpoint where the Token is requested
@ -17,37 +17,45 @@ const url = 'https://api.staging.floriday.io/customers-api/2022v2';
* @param {sequelize.models} models
* @returns {Date} tokenExpirationDate formated as YYYY-MM-DD HH:mm:ss
*/
async function getClientToken() {
const clientConfigData = await models.clientConfig.findAll();
export async function getClientToken() {
const clientConfigData = await models.clientConfig.findOne();
if (!clientConfigData[0])
throw colors.red.bold('No data found in the configuration table, ',
'if you have configured the .env file, declare the variable SECRET as true')
if (!clientConfigData)
throw new Error('No data found in the client config table')
const spinner = ora(`Requesting token...`).start();
const now = moment().format('YYYY-MM-DD HH:mm:ss');
const tokenExpirationDate = clientConfigData[0].tokenExpiration;
const spinner = ora(`Requesting new token...`).start();
const tokenExpirationDate = clientConfigData.tokenExpiration;
if (clientConfigData[0].tokenExpiration == null || moment(now).isAfter(tokenExpirationDate)) {
let clientId = clientConfigData[0].clientId;
let clientSecret = clientConfigData[0].clientSecret;
if (clientConfigData.tokenExpiration == null || moment().isAfter(tokenExpirationDate)) {
let clientId = clientConfigData.clientId;
let clientSecret = clientConfigData.clientSecret;
const data = {
grant_type: 'client_credentials',
client_id: clientId,
client_secret: clientSecret,
scope: 'role:app catalog:read supply:read organization:read network:write network:read'
};
const body = Object.keys(data)
.map(key => `${encodeURIComponent(key)}=${encodeURIComponent(data[key])}`)
.join('&');
const tokenRequest = await fetch(tokenEndpoint, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: `grant_type=client_credentials&client_id=${clientId}&client_secret=${clientSecret}&scope=role:app catalog:read supply:read organization:read network:write network:read`,
body,
});
const tokenResponse = await tokenRequest.json();
if (tokenRequest.status === 200) {
if (tokenRequest.ok) {
spinner.succeed();
} else {
spinner.fail();
throw new Error(`Token request failed with status: ${tokenRequest.status} - ${tokenRequest.statusText}`);
criticalError(new Error(`Token request failed with status: ${tokenRequest.status} - ${tokenRequest.statusText}`));
}
const accessToken = tokenResponse.access_token;
@ -72,6 +80,17 @@ async function getClientToken() {
}
}
export async function getCurrentToken() {
let data = await models.clientConfig.findOne().currentToken;
return data.currentToken;
}
export async function getCurrentTokenExpiration() {
let data = await models.clientConfig.findOne();
return data.tokenExpiration;
}
/**
* Updates the Access Token in the client config table
*
@ -81,9 +100,9 @@ async function getClientToken() {
* @param {String} accessToken
* @param {String} tokenExpirationDate
*/
async function updateClientConfig(clientId, clientSecret, accessToken, tokenExpirationDate) {
export async function updateClientConfig(clientId, clientSecret, accessToken, tokenExpirationDate) {
try {
const spinner = ora(`Updating config...`).start();
const spinner = ora(`Updating token...`).start();
await models.clientConfig.upsert({
id: 1,
clientId: clientId,
@ -105,7 +124,7 @@ async function updateClientConfig(clientId, clientSecret, accessToken, tokenExpi
*
* @returns
*/
async function getJWT() {
export async function getJWT() {
const clientConfigData = await models.clientConfig.findAll();
return clientConfigData[0].currentToken;
}
@ -116,7 +135,7 @@ async function getJWT() {
* @param {integer} ms
* @returns A promise that resolves after ms milliseconds.
*/
async function sleep(ms) {
export async function sleep(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
@ -129,7 +148,7 @@ async function sleep(ms) {
* @param {Number} concurrency
* @returns
*/
async function asyncQueue(fnArray, concurrency = 1) {
export async function asyncQueue(fnArray, concurrency = 1) {
const results = []; // 1
@ -168,7 +187,7 @@ async function asyncQueue(fnArray, concurrency = 1) {
* @param {Number} maximumSequenceNumber - maximum sequence number
* @returns
*/
async function syncSequence(current = 0, model = null , maximumSequenceNumber = 0){
export async function syncSequence(current = 0, model = null , maximumSequenceNumber = 0){
if (model == null && current == 0){
try {
let mockModels = [
@ -224,9 +243,9 @@ async function syncSequence(current = 0, model = null , maximumSequenceNumber =
}
}
async function syncSuppliers(){
export async function syncSuppliers(){
let spinner = ora('Preparing to load suppliers...').start();
try {
const spinner = ora('Preparing to load suppliers...').start();
let headers = {
'Content-Type': 'application/json',
'Authorization': `Bearer ${await getJWT()}`,
@ -235,7 +254,7 @@ async function syncSuppliers(){
const response = await fetch(`${url}/organizations/current-max-sequence`, {
method: 'GET',
headers: headers
headers
});
const maxSequenceNumber = await response.json();
let timeFinish, timeToGoSec, timeToGoMin, timeLeft;
@ -245,14 +264,14 @@ async function syncSuppliers(){
let query = `${url}/organizations/sync/${curSequenceNumber}?organizationType=SUPPLIER`;
let response = await fetch(query, {
method: 'GET',
headers: headers
headers
});
let data = await response.json();
let suppliers = data.results;
for (let supplier of suppliers) {
curSequenceNumber = supplier.sequenceNumber;
spinner.text = `Loading suppliers, ${maxSequenceNumber - curSequenceNumber} are missing`
spinner.text = `Syncing suppliers, ${maxSequenceNumber - curSequenceNumber} are missing`
if (timeFinish)
spinner.text = spinner.text + ` (${timeLeft})`
await models.supplier.upsert({
@ -290,7 +309,7 @@ async function syncSuppliers(){
}
}
async function syncConnections(){
export async function syncConnections(){
let connections = await models.connection.findAll();
let headers = {
@ -301,7 +320,7 @@ async function syncConnections(){
let remoteConnections = await fetch(`${url}/connections`, {
method: 'GET',
headers: headers
headers
});
remoteConnections = await remoteConnections.json();
@ -317,7 +336,7 @@ async function syncConnections(){
console.log('Creating remote connection');
await fetch(`${url}/connections/${connection.organizationId}`, {
method: 'PUT',
headers: headers
headers
});
await models.connection.update({ isConnected: true }, {
where: {
@ -347,18 +366,15 @@ async function syncConnections(){
}
async function syncTradeItems(){
export async function syncTradeItems(){
const spinner = ora(`Syncing trade items...`).start();
const suppliers = await models.supplier.findAll();
let i = 0;
console.log('Syncing trade items');
for (let supplier of suppliers) {
i++;
if (!supplier.isConnected){
console.log('Supplier: ', supplier.commercialName, 'is not connected');
console.log('Skipping supplier', supplier.commercialName, '(', i, '/', suppliers.length, ')');
continue;
}
if (!supplier.isConnected) continue;
let query = `${url}/trade-items?supplierOrganizationId=${supplier.organizationId}`;
let headers = {
'Content-Type': 'application/json',
@ -369,12 +385,12 @@ async function syncTradeItems(){
let request = await fetch(query, {
method: 'GET',
headers: headers
headers
});
let tradeItems = await request.json();
if (tradeItems.length == 0) {
if (!tradeItems.length) {
console.log('No trade items for supplier: ', supplier.commercialName);
continue;
}
@ -389,18 +405,20 @@ async function syncTradeItems(){
console.log('Remaining suppliers: ', suppliers.length - i, 'of', suppliers.length);
console.log('Total trade items: ', tradeItems.length);
} catch (error) {
spinner.fail();
console.log('Error while syncing trade items for: ', supplier.commercialName);
console.log(error);
}
}
spinner.succeed()
}
/**
* Syncs the supply lines for suppliers that are connected
* to do this, it fetches all the supply lines for every tradeitem of the suppliers
*/
async function syncSupplyLines(){
export async function syncSupplyLines(){
let currentSequenceNumber = await models.sequenceNumber.findOne({
where: {
@ -408,7 +426,7 @@ async function syncSupplyLines(){
}
});
console.log('Syncing supply lines');
const spinner = ora(`Syncing trade items...`).start();
let suppliers = await models.supplier.findAll({
where: {
isConnected: true
@ -421,8 +439,6 @@ async function syncSupplyLines(){
}
});
console.log('Found', suppliers.length, 'connected suppliers');
let promises = [];
let headers = {
@ -438,12 +454,17 @@ async function syncSupplyLines(){
// eslint-disable-next-line no-async-promise-executor
let promise = new Promise(async (resolve) => {
try {
let url = `${url}/supply-lines/sync/0`
const params = new URLSearchParams({
supplierOrganizationId: supplier.organizationId,
tradeItemId: tradeItem.tradeItemId,
postFilterSelectedTradeItems: false
});
url.search = params;
let url = `${url}/supply-lines/sync/0?supplierOrganizationId=${supplier.organizationId}&tradeItemId=${tradeItem.tradeItemId}&limit=100&postFilterSelectedTradeItems=false`;
let request = await fetch(url, {
let request = await fetch(url.toString(), {
method: 'GET',
headers: headers
headers
});
let supplyLines = await request.json();
@ -490,7 +511,7 @@ async function syncSupplyLines(){
let queryTradeItem = await fetch(urlTradeItem, {
method: 'GET',
headers: headers
headers
});
let tradeItem = await queryTradeItem.json();
@ -547,17 +568,18 @@ async function syncSupplyLines(){
}
} catch (error) {
spinner.fail();
console.log('Error while syncing supply lines - ' + supplyLine.results[0].tradeItemId);
console.log(error);
}
}
console.log('Synced supply lines');
spinner.succeed();
console.log('Found', suppliers.length, 'connected suppliers');
await syncSequence(currentSequenceNumber,'supplyLines' ,maximumSequenceNumber);
}
async function insertItem(tradeItem, supplier) {
export async function insertItem(tradeItem, supplier) {
let tx = await models.sequelize.transaction();
@ -688,5 +710,12 @@ async function insertItem(tradeItem, supplier) {
}
export { getClientToken, updateClientConfig, getJWT, sleep, asyncQueue, syncSequence, syncSuppliers, syncTradeItems, syncConnections, syncSupplyLines };
/**
* Throw critical error
*
* @param {err}
**/
export async function criticalError(err) {
console.log(chalk.red.bold(`[ERROR]`), chalk.red(`${err.name}: ${err.message}`));
process.exit();
}