commit 40ab45d1d13598024ea0adb8157b6f3605cc371c Author: Pau Navarro Date: Mon Dec 5 13:53:30 2022 +0100 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..30bc162 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/node_modules \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..033f3d6 --- /dev/null +++ b/README.md @@ -0,0 +1,25 @@ +# floriday + +Requires [Node.js](https://nodejs.org/en/) v14.x.x or higher. + +The Floriday service project should perform the following tasks: + +1. Create / mantain the table structure to allow the storage of the data provided by the Floriday API. + This is done using the [Sequelize](https://sequelize.org/) ORM. +2. Query the Floriday API and store the data in the database. + This is done using the [Axios](https://axios-http.com/) module. + 2.1. The data is requested every minute, but only the data that has changed is stored in the database. + This is done using the [Sequelize](https://sequelize.org/) ORM and storing the data as it is received from the API, + so it can be compared with the previous data. + +To install dependencies: + +```bash +npm install +``` + +To run: + +```bash +npm start +``` diff --git a/index.js b/index.js new file mode 100644 index 0000000..13eff3d --- /dev/null +++ b/index.js @@ -0,0 +1,278 @@ +import { Sequelize } from "sequelize"; +import TradeItem from "./models/tradeItem.js"; +import Characteristics from "./models/characteristics.js"; +import SeasonalPeriod from "./models/seasonalPeriod.js"; +import Photos from "./models/photos.js"; +import PackagingConfigurations from "./models/packagingConfigurations.js"; +import Package from "./models/package.js"; +import AdditionalPricePerPiece from "./models/additionalPricePerPiece.js"; +import BotanicalNames from "./models/botanicalNames.js"; +import CountryOfOriginIsoCodes from "./models/countryOfOriginIsoCodes.js"; + +let sequelize = new Sequelize("edi", "root", "root", { + host: "localhost", + dialect: "mariadb", + logging: false, +}); + +const tradeItemModel = TradeItem(sequelize); +const characteristicsModel = Characteristics(sequelize); +const seasonalPeriodModel = SeasonalPeriod(sequelize); +const photosModel = Photos(sequelize); +const packagingConfigurationsModel = PackagingConfigurations(sequelize); +const packageModel = Package(sequelize); +const additionalPricePerPieceModel = AdditionalPricePerPiece(sequelize); +const botanicalNamesModel = BotanicalNames(sequelize); +const countryOfOriginIsoCodesModel = CountryOfOriginIsoCodes(sequelize); + +try { + // Just there to hide the mock data insertion + characteristicsModel.belongsTo(tradeItemModel, { + foreignKey: "tradeItemFk", + targetKey: "id", + onDelete: "CASCADE", + onUpdate: "CASCADE", + }); + seasonalPeriodModel.belongsTo(tradeItemModel, { + foreignKey: "tradeItemFk", + targetKey: "id", + onDelete: "CASCADE", + onUpdate: "CASCADE", + }); + photosModel.belongsTo(tradeItemModel, { + foreignKey: "tradeItemFk", + targetKey: "id", + onDelete: "CASCADE", + onUpdate: "CASCADE", + }); + photosModel.belongsTo(seasonalPeriodModel, { + foreignKey: "seasonalPeriodFk", + targetKey: "id", + onDelete: "CASCADE", + onUpdate: "CASCADE", + }); + packagingConfigurationsModel.belongsTo(tradeItemModel, { + foreignKey: "tradeItemFk", + targetKey: "id", + onDelete: "CASCADE", + onUpdate: "CASCADE", + }); + packageModel.belongsTo(packagingConfigurationsModel, { + foreignKey: "packingConfigurationsFk", + targetKey: "id", + onDelete: "CASCADE", + onUpdate: "CASCADE", + }); + additionalPricePerPieceModel.belongsTo(packagingConfigurationsModel, { + foreignKey: "packingConfigurationsFk", + targetKey: "id", + onDelete: "CASCADE", + onUpdate: "CASCADE", + }); + botanicalNamesModel.belongsTo(tradeItemModel, { + foreignKey: "tradeItemFk", + targetKey: "id", + onDelete: "CASCADE", + onUpdate: "CASCADE", + }); + countryOfOriginIsoCodesModel.belongsTo(tradeItemModel, { + foreignKey: "tradeItemFk", + targetKey: "id", + onDelete: "CASCADE", + onUpdate: "CASCADE", + }); + + await sequelize.sync({ + // alter: true, + force: true, + }); + + const tradeItem = await tradeItemModel.create({ + tradeItemId: "123", + supplierOrganizationId: "123", + code: "123", + gtin: "123", + vbnProductCode: "123", + name: "123", + isDeleted: false, + sequenceNumber: 1, + tradeItemVersion: 1, + isCustomerSpecific: false, + isHiddenInCatalog: false, + }); + const characteristics1 = await characteristicsModel.create({ + tradeItemFk: tradeItem.id, + vnbCode: "123", + vnbValueCode: "123", + }); + const characteristics2 = await characteristicsModel.create({ + tradeItemFk: tradeItem.id, + vnbCode: "234", + vnbValueCode: "234", + }); + const seasonalPeriod1 = await seasonalPeriodModel.create({ + tradeItemFk: tradeItem.id, + startWeek: "40", + endWeek: "42", + }); + const seasonalPeriod2 = await seasonalPeriodModel.create({ + tradeItemFk: tradeItem.id, + startWeek: "43", + endWeek: "45", + }); + const photos1 = await photosModel.create({ + tradeItemFk: tradeItem.id, + seasonalPeriodFk: seasonalPeriod1.id, + photoId: "123", + url: "123", + type: "123", + primary: false, + }); + const photos2 = await photosModel.create({ + tradeItemFk: tradeItem.id, + seasonalPeriodFk: seasonalPeriod2.id, + photoId: "234", + url: "234", + type: "234", + primary: false, + }); + const packagingConfigurations1 = await packagingConfigurationsModel.create({ + tradeItemFk: tradeItem.id, + piecesPerPackage: 1, + bunchesPerPackage: 1, + photoUrl: photos1.url, + }); + const packagingConfigurations2 = await packagingConfigurationsModel.create({ + tradeItemFk: tradeItem.id, + piecesPerPackage: 2, + bunchesPerPackage: 2, + photoUrl: photos2.url, + }); + const package1 = await packageModel.create({ + packingConfigurationsFk: packagingConfigurations1.id, + vbnPackageCode: "123", + customPackageId: "123", + }); + const package2 = await packageModel.create({ + packingConfigurationsFk: packagingConfigurations2.id, + vbnPackageCode: "234", + customPackageId: "234", + }); + const additionalPricePerPiece1 = await additionalPricePerPieceModel.create({ + packingConfigurationsFk: packagingConfigurations1.id, + value: 1, + currency: "EUR", + }); + const additionalPricePerPiece2 = await additionalPricePerPieceModel.create({ + packingConfigurationsFk: packagingConfigurations2.id, + value: 2, + currency: "USD", + }); + const botanicalNames1 = await botanicalNamesModel.create({ + tradeItemFk: tradeItem.id, + name: "test123", + }); + const botanicalNames2 = await botanicalNamesModel.create({ + tradeItemFk: tradeItem.id, + name: "test234", + }); + const countryOfOriginIsoCodes1 = await countryOfOriginIsoCodesModel.create({ + tradeItemFk: tradeItem.id, + isoCode: "ES", + }); + const countryOfOriginIsoCodes2 = await countryOfOriginIsoCodesModel.create({ + tradeItemFk: tradeItem.id, + isoCode: "DE", + }); +} catch (error) { + console.log(error); +} + +try { + // Every 30 sec query the database + setInterval(async () => { + console.log("Querying the API to check for new data..."); + + const query = tradeItemModel.findAll({ + include: [ + { + model: characteristicsModel, + association: tradeItemModel.hasMany(characteristicsModel, { + foreignKey: "tradeItemFk", + sourceKey: "id", + }), + as: "characteristics", + }, + { + model: photosModel, + association: tradeItemModel.hasMany(photosModel, { + foreignKey: "tradeItemFk", + sourceKey: "id", + }), + as: "photos", + include: [ + { + model: seasonalPeriodModel, + association: photosModel.hasOne(seasonalPeriodModel, { + foreignKey: "id", + sourceKey: "seasonalPeriodFk", + }), + as: "seasonalPeriod", + }, + ], + }, + { + model: packagingConfigurationsModel, + association: tradeItemModel.hasMany(packagingConfigurationsModel, { + foreignKey: "tradeItemFk", + sourceKey: "id", + }), + as: "packagingConfigurations", + include: [ + { + model: packageModel, + association: packagingConfigurationsModel.hasOne(packageModel, { + foreignKey: "packingConfigurationsFk", + sourceKey: "id", + }), + as: "package", + }, + { + model: additionalPricePerPieceModel, + association: packagingConfigurationsModel.hasOne( + additionalPricePerPieceModel, + { + foreignKey: "packingConfigurationsFk", + sourceKey: "id", + } + ), + as: "additionalPricePerPiece", + }, + ], + }, + { + model: botanicalNamesModel, + association: tradeItemModel.hasMany(botanicalNamesModel, { + foreignKey: "tradeItemFk", + sourceKey: "id", + }), + as: "botanicalNames", + }, + { + model: countryOfOriginIsoCodesModel, + association: tradeItemModel.hasMany(countryOfOriginIsoCodesModel, { + foreignKey: "tradeItemFk", + sourceKey: "id", + }), + as: "countryOfOriginIsoCodes", + }, + ], + }); + + const result = await query; + + console.log(JSON.stringify(result, null, 2)); + }, 30000); +} catch (error) { + console.error("Unable to connect to the database:", error); +} diff --git a/models/additionalPricePerPiece.js b/models/additionalPricePerPiece.js new file mode 100644 index 0000000..a4e7cb5 --- /dev/null +++ b/models/additionalPricePerPiece.js @@ -0,0 +1,31 @@ +import { Sequelize } from "sequelize"; + +const additionalPricePerPiece = { + id: { + type: Sequelize.INTEGER, + primaryKey: true, + autoIncrement: true, + }, + packingConfigurationsFk: { + type: Sequelize.INTEGER, + }, + currency: { + type: Sequelize.STRING, + defaultValue: "EUR", + }, + value: { + type: Sequelize.DECIMAL(10, 2), + }, +}; + +export default (sequelize) => { + const AdditionalPricePerPiece = sequelize.define( + "FDadditionalPricePerPiece", + additionalPricePerPiece, + { + timestamps: false, + freezeTableName: true, + } + ); + return AdditionalPricePerPiece; +}; diff --git a/models/botanicalNames.js b/models/botanicalNames.js new file mode 100644 index 0000000..77338a7 --- /dev/null +++ b/models/botanicalNames.js @@ -0,0 +1,18 @@ +import { Sequelize } from "sequelize"; + +const botanicalNames = { + tradeItemFk: { + type: Sequelize.INTEGER, + }, + name: { + type: Sequelize.STRING, + }, +}; + +export default (sequelize) => { + const BotanicalNames = sequelize.define("FDbotanicalNames", botanicalNames, { + timestamps: false, + freezeTableName: true, + }); + return BotanicalNames; +}; diff --git a/models/characteristics.js b/models/characteristics.js new file mode 100644 index 0000000..d123e7d --- /dev/null +++ b/models/characteristics.js @@ -0,0 +1,25 @@ +import { Sequelize } from "sequelize"; + +const characteristics = { + tradeItemFk: { + type: Sequelize.INTEGER, + }, + vnbCode: { + type: Sequelize.STRING, + }, + vnbValueCode: { + type: Sequelize.STRING, + }, +}; + +export default (sequelize) => { + const Characteristics = sequelize.define( + "FDcharacteristics", + characteristics, + { + timestamps: false, + freezeTableName: true, + } + ); + return Characteristics; +}; diff --git a/models/countryOfOriginIsoCodes.js b/models/countryOfOriginIsoCodes.js new file mode 100644 index 0000000..b84ac5e --- /dev/null +++ b/models/countryOfOriginIsoCodes.js @@ -0,0 +1,22 @@ +import { Sequelize } from "sequelize"; + +const countryOfOriginIsoCodes = { + tradeItemFk: { + type: Sequelize.INTEGER, + }, + isoCode: { + type: Sequelize.STRING, + }, +}; + +export default (sequelize) => { + const CountryOfOriginIsoCodes = sequelize.define( + "FDcountryOfOriginIsoCodes", + countryOfOriginIsoCodes, + { + timestamps: false, + freezeTableName: true, + } + ); + return CountryOfOriginIsoCodes; +}; diff --git a/models/package.js b/models/package.js new file mode 100644 index 0000000..4214da8 --- /dev/null +++ b/models/package.js @@ -0,0 +1,26 @@ +import { Sequelize } from "sequelize"; + +const PackageModel = { + id: { + type: Sequelize.INTEGER, + primaryKey: true, + autoIncrement: true, + }, + packingConfigurationsFk: { + type: Sequelize.INTEGER, + }, + vbnPackageCode: { + type: Sequelize.INTEGER, + }, + customPackageId: { + type: Sequelize.UUID, + }, +}; + +export default (sequelize) => { + const Package = sequelize.define("FDpackage", PackageModel, { + timestamps: false, + freezeTableName: true, + }); + return Package; +} diff --git a/models/packagingConfigurations.js b/models/packagingConfigurations.js new file mode 100644 index 0000000..6c65fef --- /dev/null +++ b/models/packagingConfigurations.js @@ -0,0 +1,48 @@ +import { Sequelize } from "sequelize"; + +const packingConfigurations = { + id: { + type: Sequelize.INTEGER, + primaryKey: true, + autoIncrement: true, + }, + tradeItemFk: { + type: Sequelize.INTEGER, + }, + piecesPerPackage: { + type: Sequelize.INTEGER, + }, + bunchesPerPackage: { + type: Sequelize.INTEGER, + }, + photoUrl: { + type: Sequelize.STRING, + }, + packagesPerLayer: { + type: Sequelize.INTEGER, + }, + layersPerLoadCarrier: { + type: Sequelize.INTEGER, + }, + transportHeightInCm: { + type: Sequelize.INTEGER, + }, + loadCarrierType: { + type: Sequelize.STRING, + }, + isPrimary: { + type: Sequelize.BOOLEAN, + }, +}; + +export default (sequelize) => { + const PackingConfigurations = sequelize.define( + "FDpackingConfigurations", + packingConfigurations, + { + timestamps: false, + freezeTableName: true, + } + ); + return PackingConfigurations; +}; diff --git a/models/photos.js b/models/photos.js new file mode 100644 index 0000000..9e6fded --- /dev/null +++ b/models/photos.js @@ -0,0 +1,27 @@ +import { Sequelize } from "sequelize"; + +const photos = { + tradeItemFk: { + type: Sequelize.INTEGER, + }, + photoId: { + type: Sequelize.UUID, + }, + url: { + type: Sequelize.STRING, + }, + type: { + type: Sequelize.STRING, + }, + primary: { + type: Sequelize.BOOLEAN, + }, +}; + +export default (sequelize) => { + const Photos = sequelize.define("FDphotos", photos, { + timestamps: false, + freezeTableName: true, + }); + return Photos; +} diff --git a/models/seasonalPeriod.js b/models/seasonalPeriod.js new file mode 100644 index 0000000..0380a91 --- /dev/null +++ b/models/seasonalPeriod.js @@ -0,0 +1,26 @@ +import { Sequelize } from "sequelize"; + +const seasonalPeriod = { + id: { + type: Sequelize.INTEGER, + primaryKey: true, + autoIncrement: true, + }, + tradeItemFk: { + type: Sequelize.INTEGER, + }, + startWeek: { + type: Sequelize.INTEGER, + }, + endWeek: { + type: Sequelize.INTEGER, + }, +}; + +export default (sequelize) => { + const SeasonalPeriod = sequelize.define("FDseasonalPeriod", seasonalPeriod, { + timestamps: false, + freezeTableName: true, + }); + return SeasonalPeriod; +}; diff --git a/models/tradeItem.js b/models/tradeItem.js new file mode 100644 index 0000000..a826ccc --- /dev/null +++ b/models/tradeItem.js @@ -0,0 +1,50 @@ +import { Sequelize } from "sequelize"; + +const tradeItem = { + id: { + type: Sequelize.INTEGER, + primaryKey: true, + autoIncrement: true, + }, + tradeItemId: { + type: Sequelize.UUID + }, + supplierOrganizationId: { + type: Sequelize.UUID + }, + code: { + type: Sequelize.STRING + }, + gtin: { + type: Sequelize.STRING + }, + vbnProductCode: { + type: Sequelize.STRING + }, + name: { + type: Sequelize.STRING + }, + isDeleted: { + type: Sequelize.BOOLEAN, + }, + sequenceNumber: { + type: Sequelize.INTEGER, + }, + tradeItemVersion: { + type: Sequelize.INTEGER, + }, + isCustomerSpecific: { + type: Sequelize.BOOLEAN, + }, + isHiddenInCatalog: { + type: Sequelize.BOOLEAN, + } +}; + +export default (sequelize) => { + const TradeItem = sequelize.define("FDtradeItem", tradeItem, { + timestamps: false, + freezeTableName: true, + }); + return TradeItem; +}; \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..aff690b --- /dev/null +++ b/package-lock.json @@ -0,0 +1,378 @@ +{ + "name": "floriday", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "floriday", + "dependencies": { + "axios": "^1.2.0", + "mariadb": "^3.0.2", + "moment": "^2.29.4", + "sequelize": "^6.26.0" + } + }, + "node_modules/@types/debug": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.7.tgz", + "integrity": "sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg==", + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/geojson": { + "version": "7946.0.10", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.10.tgz", + "integrity": "sha512-Nmh0K3iWQJzniTuPRcJn5hxXkfB1T1pgB89SBig5PlJQU5yocazeu4jATJlaA0GYFKWMqDdvYemoSnF2pXgLVA==" + }, + "node_modules/@types/ms": { + "version": "0.7.31", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", + "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" + }, + "node_modules/@types/node": { + "version": "17.0.45", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.45.tgz", + "integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==" + }, + "node_modules/@types/validator": { + "version": "13.7.10", + "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.7.10.tgz", + "integrity": "sha512-t1yxFAR2n0+VO6hd/FJ9F2uezAZVWHLmpmlJzm1eX03+H7+HsuTAp7L8QJs+2pQCfWkP1+EXsGK9Z9v7o/qPVQ==" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/axios": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.2.0.tgz", + "integrity": "sha512-zT7wZyNYu3N5Bu0wuZ6QccIf93Qk1eV8LOewxgjOZFd2DenOs98cJ7+Y6703d0wkaXGY6/nZd4EweJaHz9uzQw==", + "dependencies": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/denque": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/dottie": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.2.tgz", + "integrity": "sha512-fmrwR04lsniq/uSr8yikThDTrM7epXHBAAjH9TbeH3rEA8tdCO7mRzB9hdmdGyJCxF8KERo9CITcm3kGuoyMhg==" + }, + "node_modules/follow-redirects": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inflection": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.13.4.tgz", + "integrity": "sha512-6I/HUDeYFfuNCVS3td055BaXBwKYuzw7K3ExVMStBowKo9oOAMJIXIHvdyR3iboTCp1b+1i5DSkIZTcwIktuDw==", + "engines": [ + "node >= 0.4.0" + ] + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lru-cache": { + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.14.1.tgz", + "integrity": "sha512-ysxwsnTKdAx96aTRdhDOCQfDgbHnt8SK0KY8SEjO0wHinhWOFTESbjVCMPbU1uGXg/ch4lifqx0wfjOawU2+WA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/mariadb": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mariadb/-/mariadb-3.0.2.tgz", + "integrity": "sha512-dVjiQZ6RW0IXFnX+T/ZEmnqs724DgkQsXqfCyInXn0XxVfO2Px6KbS4M3Ny6UiBg0zJ93SHHvfVBgYO4ZnFvvw==", + "dependencies": { + "@types/geojson": "^7946.0.10", + "@types/node": "^17.0.45", + "denque": "^2.1.0", + "iconv-lite": "^0.6.3", + "lru-cache": "^7.14.0", + "moment-timezone": "^0.5.38" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/moment": { + "version": "2.29.4", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", + "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", + "engines": { + "node": "*" + } + }, + "node_modules/moment-timezone": { + "version": "0.5.39", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.39.tgz", + "integrity": "sha512-hoB6suq4ISDj7BDgctiOy6zljBsdYT0++0ZzZm9rtxIvJhIbQ3nmbgSWe7dNFGurl6/7b1OUkHlmN9JWgXVz7w==", + "dependencies": { + "moment": ">= 2.9.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/pg-connection-string": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.5.0.tgz", + "integrity": "sha512-r5o/V/ORTA6TmUnyWZR9nCj1klXCO2CEKNRlVuJptZe85QuhFayC7WeMic7ndayT5IRIR0S0xFxFi2ousartlQ==" + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, + "node_modules/retry-as-promised": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-6.1.0.tgz", + "integrity": "sha512-Hj/jY+wFC+SB9SDlIIFWiGOHnNG0swYbGYsOj2BJ8u2HKUaobNKab0OIC0zOLYzDy0mb7A4xA5BMo4LMz5YtEA==" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/sequelize": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-6.26.0.tgz", + "integrity": "sha512-Xv82z1FdSn/qwB1IObSxIHV519cFk/vSD28vWs8Y0VucQLn7pK2x2jYjf2Qg/rBUQbCVprDdU7RPf+55rrkc0A==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/sequelize" + } + ], + "dependencies": { + "@types/debug": "^4.1.7", + "@types/validator": "^13.7.1", + "debug": "^4.3.3", + "dottie": "^2.0.2", + "inflection": "^1.13.2", + "lodash": "^4.17.21", + "moment": "^2.29.1", + "moment-timezone": "^0.5.34", + "pg-connection-string": "^2.5.0", + "retry-as-promised": "^6.1.0", + "semver": "^7.3.5", + "sequelize-pool": "^7.1.0", + "toposort-class": "^1.0.1", + "uuid": "^8.3.2", + "validator": "^13.7.0", + "wkx": "^0.5.0" + }, + "engines": { + "node": ">=10.0.0" + }, + "peerDependenciesMeta": { + "ibm_db": { + "optional": true + }, + "mariadb": { + "optional": true + }, + "mysql2": { + "optional": true + }, + "oracledb": { + "optional": true + }, + "pg": { + "optional": true + }, + "pg-hstore": { + "optional": true + }, + "snowflake-sdk": { + "optional": true + }, + "sqlite3": { + "optional": true + }, + "tedious": { + "optional": true + } + } + }, + "node_modules/sequelize-pool": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-7.1.0.tgz", + "integrity": "sha512-G9c0qlIWQSK29pR/5U2JF5dDQeqqHRragoyahj/Nx4KOOQ3CPPfzxnfqFPCSB7x5UgjOgnZ61nSxz+fjDpRlJg==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/toposort-class": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz", + "integrity": "sha512-OsLcGGbYF3rMjPUf8oKktyvCiUxSbqMMS39m33MAjLTC1DVIH6x3WSt63/M77ihI09+Sdfk1AXvfhCEeUmC7mg==" + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/validator": { + "version": "13.7.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.7.0.tgz", + "integrity": "sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/wkx": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/wkx/-/wkx-0.5.0.tgz", + "integrity": "sha512-Xng/d4Ichh8uN4l0FToV/258EjMGU9MGcA0HV2d9B/ZpZB3lqQm7nkOdZdm5GhKtLLhAE7PiVQwN4eN+2YJJUg==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..2d23928 --- /dev/null +++ b/package.json @@ -0,0 +1,14 @@ +{ + "name": "floriday", + "module": "index.ts", + "type": "module", + "scripts": { + "start": "node index.js" + }, + "dependencies": { + "axios": "^1.2.0", + "mariadb": "^3.0.2", + "moment": "^2.29.4", + "sequelize": "^6.26.0" + } +}