From 84bd641cf2b405a17e21d94c27b7ebc3f8a545fa Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 5 Oct 2021 12:29:17 +0200 Subject: [PATCH] Database migrations --- CHANGELOG.md | 3 + client/.env | 2 +- db.js | 32 ------ db/index.js | 51 ++++++++++ db/migrations/00_initial.js | 189 ++++++++++++++++++++++++++++++++++++ models/Config.js | 44 +++++---- package-lock.json | 13 +++ package.json | 1 + 8 files changed, 282 insertions(+), 53 deletions(-) delete mode 100644 db.js create mode 100644 db/index.js create mode 100644 db/migrations/00_initial.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a372a7..0ab36d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +### v1.6.8 (2021-10-05) +- Implemented migration system for database + ### v1.6.7 (2021-10-04) - Add multiple labels to Docker Compose ([#90](https://github.com/pawelmalak/flame/issues/90)) - Custom icons via Docker Compose labels ([#91](https://github.com/pawelmalak/flame/issues/91)) diff --git a/client/.env b/client/.env index 482555e..afab507 100644 --- a/client/.env +++ b/client/.env @@ -1 +1 @@ -REACT_APP_VERSION=1.6.7 \ No newline at end of file +REACT_APP_VERSION=1.6.8 \ No newline at end of file diff --git a/db.js b/db.js deleted file mode 100644 index 6c1eb7c..0000000 --- a/db.js +++ /dev/null @@ -1,32 +0,0 @@ -const { Sequelize } = require('sequelize'); -const Logger = require('./utils/Logger'); -const logger = new Logger(); - -const sequelize = new Sequelize({ - dialect: 'sqlite', - storage: './data/db.sqlite', - logging: false, -}); - -const connectDB = async () => { - try { - await sequelize.authenticate(); - logger.log('Connected to database'); - - const syncModels = true; - - if (syncModels) { - logger.log('Starting model synchronization'); - await sequelize.sync({ alter: true }); - logger.log('All models were synchronized'); - } - } catch (error) { - logger.log(`Unable to connect to the database: ${error.message}`, 'ERROR'); - process.exit(1); - } -}; - -module.exports = { - connectDB, - sequelize, -}; diff --git a/db/index.js b/db/index.js new file mode 100644 index 0000000..fbff66d --- /dev/null +++ b/db/index.js @@ -0,0 +1,51 @@ +const { Sequelize } = require('sequelize'); +const { join } = require('path'); +const fs = require('fs'); +const Umzug = require('umzug'); + +const Logger = require('../utils/Logger'); +const logger = new Logger(); + +const sequelize = new Sequelize({ + dialect: 'sqlite', + storage: './data/db.sqlite', + logging: false, +}); + +const umzug = new Umzug({ + migrations: { + path: join(__dirname, './migrations'), + params: [sequelize.getQueryInterface()], + }, + storage: 'sequelize', + storageOptions: { + sequelize, + }, +}); + +const connectDB = async () => { + try { + if (fs.existsSync('data/db.sqlite')) { + fs.copyFileSync('data/db.sqlite', 'data/backup_db.sqlite'); + } + + await sequelize.authenticate(); + logger.log('Connected to database'); + + // migrations + const pendingMigrations = await umzug.pending(); + + if (pendingMigrations.length > 0) { + logger.log('Executing pending migrations'); + await umzug.up(); + } + } catch (error) { + logger.log(`Unable to connect to the database: ${error.message}`, 'ERROR'); + process.exit(1); + } +}; + +module.exports = { + connectDB, + sequelize, +}; diff --git a/db/migrations/00_initial.js b/db/migrations/00_initial.js new file mode 100644 index 0000000..e6d7b13 --- /dev/null +++ b/db/migrations/00_initial.js @@ -0,0 +1,189 @@ +const { DataTypes } = require('sequelize'); +const { INTEGER, DATE, STRING, TINYINT, FLOAT, TEXT } = DataTypes; + +const up = async (query) => { + // CONFIG TABLE + await query.createTable('config', { + id: { + type: INTEGER, + autoIncrement: true, + primaryKey: true, + }, + key: { + type: STRING, + allowNull: false, + unique: true, + }, + value: { + type: STRING, + allowNull: false, + }, + valueType: { + type: STRING, + allowNull: false, + }, + isLocked: { + type: TINYINT, + defaultValue: 0, + }, + createdAt: { + type: DATE, + allowNull: false, + }, + updatedAt: { + type: DATE, + allowNull: false, + }, + }); + + // WEATHER TABLE + await query.createTable('weather', { + id: { + type: INTEGER, + autoIncrement: true, + primaryKey: true, + }, + externalLastUpdate: { + type: STRING, + }, + tempC: { + type: FLOAT, + }, + tempF: { + type: FLOAT, + }, + isDay: { + type: INTEGER, + }, + cloud: { + type: INTEGER, + }, + conditionText: { + type: TEXT, + }, + conditionCode: { + type: INTEGER, + }, + createdAt: { + type: DATE, + allowNull: false, + }, + updatedAt: { + type: DATE, + allowNull: false, + }, + }); + + // CATEGORIES TABLE + await query.createTable('categories', { + id: { + type: INTEGER, + autoIncrement: true, + primaryKey: true, + }, + name: { + type: STRING, + allowNull: false, + }, + isPinned: { + type: TINYINT, + defaultValue: 0, + }, + createdAt: { + type: DATE, + allowNull: false, + }, + updatedAt: { + type: DATE, + allowNull: false, + }, + orderId: { + type: INTEGER, + defaultValue: null, + }, + }); + + // BOOKMARKS TABLE + await query.createTable('bookmarks', { + id: { + type: INTEGER, + autoIncrement: true, + primaryKey: true, + }, + name: { + type: STRING, + allowNull: false, + }, + url: { + type: STRING, + allowNull: false, + }, + categoryId: { + type: INTEGER, + allowNull: false, + }, + icon: { + type: STRING, + defaultValue: '', + }, + createdAt: { + type: DATE, + allowNull: false, + }, + updatedAt: { + type: DATE, + allowNull: false, + }, + }); + + // APPS TABLE + await query.createTable('apps', { + id: { + type: INTEGER, + autoIncrement: true, + primaryKey: true, + }, + name: { + type: STRING, + allowNull: false, + }, + url: { + type: STRING, + allowNull: false, + }, + icon: { + type: STRING, + allowNull: false, + defaultValue: 'cancel', + }, + isPinned: { + type: TINYINT, + defaultValue: 0, + }, + createdAt: { + type: DATE, + allowNull: false, + }, + updatedAt: { + type: DATE, + allowNull: false, + }, + orderId: { + type: INTEGER, + defaultValue: null, + }, + }); +}; + +const down = async (query) => { + await query.dropTable('config'); + await query.dropTable('weather'); + await query.dropTable('categories'); + await query.dropTable('bookmarks'); + await query.dropTable('apps'); +}; + +module.exports = { + up, + down, +}; diff --git a/models/Config.js b/models/Config.js index 3919f3f..675aaa8 100644 --- a/models/Config.js +++ b/models/Config.js @@ -1,26 +1,30 @@ const { DataTypes } = require('sequelize'); const { sequelize } = require('../db'); -const Config = sequelize.define('Config', { - key: { - type: DataTypes.STRING, - allowNull: false, - unique: true +const Config = sequelize.define( + 'Config', + { + key: { + type: DataTypes.STRING, + allowNull: false, + unique: true, + }, + value: { + type: DataTypes.STRING, + allowNull: false, + }, + valueType: { + type: DataTypes.STRING, + allowNull: false, + }, + isLocked: { + type: DataTypes.TINYINT, + defaultValue: 0, + }, }, - value: { - type: DataTypes.STRING, - allowNull: false - }, - valueType: { - type: DataTypes.STRING, - allowNull: false - }, - isLocked: { - type: DataTypes.BOOLEAN, - defaultValue: false + { + tableName: 'config', } -}, { - tableName: 'config' -}); +); -module.exports = Config; \ No newline at end of file +module.exports = Config; diff --git a/package-lock.json b/package-lock.json index a7183e8..dab2464 100644 --- a/package-lock.json +++ b/package-lock.json @@ -525,6 +525,11 @@ "inherits": "~2.0.0" } }, + "bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" + }, "body-parser": { "version": "1.19.0", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", @@ -3240,6 +3245,14 @@ "is-typedarray": "^1.0.0" } }, + "umzug": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/umzug/-/umzug-2.3.0.tgz", + "integrity": "sha512-Z274K+e8goZK8QJxmbRPhl89HPO1K+ORFtm6rySPhFKfKc5GHhqdzD0SGhSWHkzoXasqJuItdhorSvY7/Cgflw==", + "requires": { + "bluebird": "^3.7.2" + } + }, "undefsafe": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.3.tgz", diff --git a/package.json b/package.json index 40f1646..dbeb5ee 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "node-schedule": "^2.0.0", "sequelize": "^6.6.2", "sqlite3": "^5.0.2", + "umzug": "^2.3.0", "ws": "^7.4.6" }, "devDependencies": {