const input = require("input") const fs = require("fs") const path = require("path") const { Umzug, SequelizeStorage } = require("umzug") const { Sequelize } = require("sequelize") const argon2 = require("argon2") const { production: config } = require("../config/config.json") const { User } = require("../models") const axios = require("axios") const os = require("os") console.log("Troplo/Colubrina CLI") console.log("Colubrina version", require("../../package.json").version) async function checkForUpdates() { await axios .get("https://services.troplo.com/api/v1/state", { headers: { "X-Troplo-Project": "colubrina" }, timeout: 800 }) .then((res) => { if (require("../../package.json").version !== res.data.latestVersion) { console.log("A new version of Colubrina is available!") console.log("Latest version:", res.data.latestVersion) } else { console.log("Colubrina is up to date.") } }) .catch(() => { console.log( "Failed to check for updates, ensure you are connected to the internet, and services.troplo.com is whitelisted behind any potential firewalls." ) }) } let state = { db: { host: "localhost", port: 3306, username: "colubrina", password: null, database: "colubrina", storage: "./storage.db" }, dbConfig: {} } async function doSetupDB() { const dialect = await input.select( "What database dialect do you want to use? (MariaDB tested, recommended)", ["mariadb", "postgres", "sqlite"] ) const host = await input.text("What is the host?", { default: state.db.host || "localhost" }) const port = await input.text("What is the port?", { default: state.db.port || 3306 }) const username = await input.text("What is the username?", { default: state.db.username || "colubrina" }) const password = await input.text("What is the password?", { default: state.db.password ? "Enter for cached password" : "Please specify" }) const database = await input.text("What is the database name?", { default: state.db.database || "colubrina" }) let storage if (dialect === "sqlite") { storage = await input.text( "What is the path to the storage file (SQLite only)?", { default: state.db.storage || "./storage.db" } ) } state.db = { username: username, password: password, database: database, host: host, dialect: dialect, port: port, logging: false } state.dbConfig = { development: { username: username, password: password, database: database, host: host, dialect: dialect, port: port, storage: dialect === "sqlite" ? storage : null, logging: false }, test: { username: username, password: password, database: database, host: host, dialect: dialect, port: port, logging: false }, production: { username: username, password: password, database: database, host: host, dialect: dialect, port: port, logging: false } } await testDB() } async function testDB() { try { const sequelize = new Sequelize(state.db) await sequelize.authenticate() console.log("Connection to database has been established successfully.") } catch (error) { console.error("Unable to connect to the database:", error) await doSetupDB() } } async function dbSetup() { await doSetupDB() fs.writeFileSync( path.join(__dirname, "../config/config.json"), JSON.stringify(state.dbConfig) ) console.log("config/config.json overwritten") } async function runMigrations() { console.log("Running migrations") const config = require("../config/config.json").production const sequelize = new Sequelize(config) const umzug = new Umzug({ migrations: { glob: "../migrations/*.js" }, context: sequelize.getQueryInterface(), storage: new SequelizeStorage({ sequelize }), logger: console, logging: true }) await (async () => { await umzug.up() })() console.log("Migrations applied") } async function createUser() { const user = { username: await input.text("Username", { default: "admin" }), password: await argon2.hash(await input.text("Password", {})), email: await input.text("Email", { default: "troplo@troplo.com" }), admin: JSON.parse( await input.confirm("Admin (true/false)", { default: false }) ) } await User.create(user) console.log("User created") } async function configureDotEnv() { function setEnvValue(key, value) { const ENV_VARS = fs.readFileSync("../.env", "utf8").split(os.EOL) // find the env we want based on the key const target = ENV_VARS.indexOf( ENV_VARS.find((line) => { // (? { init() })