import async from "async"; import config from "config"; import mongoose from "mongoose"; import bluebird from "bluebird"; import fs from "fs"; import { fileURLToPath } from "url"; import path from "path"; import CoreClass from "../../core"; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); let MigrationModule; mongoose.Promise = bluebird; class _MigrationModule extends CoreClass { // eslint-disable-next-line require-jsdoc constructor() { super("migration"); MigrationModule = this; } /** * Initialises the migration module * * @returns {Promise} - returns promise (reject, resolve) */ initialize() { return new Promise((resolve, reject) => { this.models = {}; const { user, password, host, port, database } = config.get("mongo"); mongoose .connect(`mongodb://${user}:${password}@${host}:${port}/${database}`, { useNewUrlParser: true, useUnifiedTopology: true }) .then(async () => { mongoose.connection.on("error", err => this.log("ERROR", err)); mongoose.connection.on("disconnected", () => { this.log("ERROR", "Disconnected, going to try to reconnect..."); this.setStatus("RECONNECTING"); }); mongoose.connection.on("reconnected", () => { this.log("INFO", "Reconnected."); this.setStatus("READY"); }); mongoose.connection.on("reconnectFailed", () => { this.log("INFO", "Reconnect failed, stopping reconnecting."); this.setStatus("FAILED"); }); this.models = { song: mongoose.model("song", new mongoose.Schema({}, { strict: false })), queueSong: mongoose.model("queueSong", new mongoose.Schema({}, { strict: false })), station: mongoose.model("station", new mongoose.Schema({}, { strict: false })), user: mongoose.model("user", new mongoose.Schema({}, { strict: false })), activity: mongoose.model("activity", new mongoose.Schema({}, { strict: false })), playlist: mongoose.model("playlist", new mongoose.Schema({}, { strict: false })), news: mongoose.model("news", new mongoose.Schema({}, { strict: false })), report: mongoose.model("report", new mongoose.Schema({}, { strict: false })), punishment: mongoose.model("punishment", new mongoose.Schema({}, { strict: false })), ratings: mongoose.model("ratings", new mongoose.Schema({}, { strict: false })), stationHistory: mongoose.model("stationHistory", new mongoose.Schema({}, { strict: false })) }; const files = fs.readdirSync(path.join(__dirname, "migrations")); const migrations = files.length; async.timesLimit( migrations, 1, (index, next) => { MigrationModule.runJob("RUN_MIGRATION", { index: index + 1 }, null, -1) .then(() => next()) .catch(err => next(err)); }, err => { if (err) console.log("Migration error", err); else console.log("Migration completed"); } ); resolve(); }) .catch(err => { this.log("ERROR", err); reject(err); }); }); } /** * Returns a database model * * @param {object} payload - object containing the payload * @param {object} payload.modelName - name of the model to get * @returns {Promise} - returns promise (reject, resolve) */ GET_MODEL(payload) { return new Promise(resolve => { resolve(MigrationModule.models[payload.modelName]); }); } /** * Runs migrations * * @param {object} payload - object containing the payload * @param {object} payload.index - migration index * @returns {Promise} - returns promise (reject, resolve) */ RUN_MIGRATION(payload) { return new Promise((resolve, reject) => { import(`./migrations/migration${payload.index}`).then(module => { this.log("INFO", `Running migration ${payload.index}`); module.default .apply(this, [MigrationModule]) .then(response => { resolve(response); }) .catch(err => { reject(err); }); }); }); } } export default new _MigrationModule();