HEX
Server: Microsoft-IIS/8.5
System: Windows NT YDAWBH120 6.3 build 9600 (Windows Server 2012 R2 Standard Edition) AMD64
User: tentjecom_web (0)
PHP: 7.4.14
Disabled: NONE
Upload Files
File: D:/HostingSpaces/SBogers10/momsecurity.komma.nl/kommandline.js
//Require stuff
const readline = require('readline').createInterface({
    input: process.stdin,
    output: process.stdout
});
const { spawn, exec } = require('child_process');
const path = require('path');

/**
 * The main menu
 */
class Menu {
    /**
     * Clear the screen
     */
    static clear() {
        readline.write('\u001B[2J\u001B[0;0f');
    }

    /**
     * Show the main menu
     */
    static mainMenu() {
        let menuChoice = new Promise((resolve, reject) => {
            let prompt = function() {
                Menu.clear();
                readline.write('Welcome to the Kommandline!\nWhat would you like to do? \n');
                readline.write('\n');
                readline.write('1. Setup database\n');
                readline.write('2. Setup testing database\n');
                readline.write('3. Kill artisan serve on port 8000\n');
                readline.write('4. Exit\n');
                readline.write('\n');
                readline.question(`What would you like to do? `, (what) => {
                    let legitOptions = ['1', '2', '3', '4', '5'];

                    if(!legitOptions.includes(what)) {
                        readline.write('That is not a valid option. Try again.\n\n');
                        prompt();
                    }
                    else resolve(what);
                });
            };
            prompt();
        });

        /**
         * Triggered when a choice was made in the main menu
         *
         * @param choice
         */
        function mainMenuCallback(choice) {
            let databaseName;
            switch (choice) {
                case '1':
                    Menu.setupDatabaseMenu().then(() => {
                        readline.write('\n\n\n\n\n');
                        Menu.mainMenu()
                    });
                    break;
                case '2':
                    Menu.setupDatabaseMenu('testing').then(() => {
                        readline.write('\n\n\n\n\n');
                        Menu.mainMenu()
                    });
                    break;
                case '3':
                    Process.killArtisans().then(() => {
                        Menu.mainMenu()
                    }).catch(err => readline.write('\n'+err));
                    break;
                default:
                case '4':
                    process.exit(0);
                    readline.close();
                    break;
            }
        }

        menuChoice.then(mainMenuCallback);
    }

    /**
     * Show a menu to setup the testing or regular database
     * @return {Promise|Promise|Promise}
     */
    static setupDatabaseMenu(databasename = '') {
        return new Promise((resolve, reject) => {
            let prompt = function() {
                Menu.clear();
                readline.write(`These commands wil be executed in order. Is this ok?\n`);
                readline.write(`    php artisan migrate:fresh `+(databasename === 'testing' ? '--env=testing' : '')+`\n`);
                readline.write(`    php artisan kms:seed `+(databasename === 'testing' ? '--env=testing' : '')+`\n`);
                readline.write(`    php artisan db:seed `+(databasename === 'testing' ? '--env=testing' : '')+`\n`);

                readline.write('\n');
                readline.write('1. Yes\n');
                readline.write('2. No\n');
                readline.question(``, (what) => {
                    let legitOptions = ['1', '2'];

                    if(!legitOptions.includes(what)) {
                        Menu.clear();
                        readline.write('That is not a valid option. Try again.\n\n');
                        prompt();
                    }
                    else {
                        if(what === '1') {
                            if (databasename === 'testing') Process.setupTestDatabase().then(() => {
                                Menu.clear();
                                resolve();
                            }).catch(reject);
                            else Process.setupDatabase().then(() => {
                                Menu.clear();
                                resolve()
                            }).catch(reject);
                        } else {
                            resolve();
                        }
                    }
                });
            };
            prompt();
        })
    }

    static getErrorHandler(afterTimeout, showErrorDuration = 5000) {
        return function(error) {
            readline.write('An error occurred\n\n');
            console.error(error);
            setTimeout(afterTimeout, showErrorDuration)
        }
    }
}

/**
 * Knows how to start and handle system processes
 */
class Process {
    /**
     * Truncates the test database. And runs some laravel artisan commands to set it up again.
     * Also does seed the database
     *
     * @return {Promise|Promise|Promise}
     */
    static setupTestDatabase() {
        return Process.setupDatabase(['--env=testing'])
    }

    /**
     * Truncates the database. And runs some laravel artisan commands to set it up again.
     * Also does seed the database
     *
     * @return {Promise|Promise|Promise}
     */
    static setupDatabase(commandlineOptions) {
        commandlineOptions = commandlineOptions || [];

        return new Promise((resolve, reject) => {
            Menu.clear();

            let currentCommandLineOptions = ['artisan', 'migrate:fresh'].concat(commandlineOptions);
            readline.write('\nRunning: php '+currentCommandLineOptions.join(' ')+'\n');
            const migrateCommand = spawn('php', currentCommandLineOptions);
            this.handle(migrateCommand, null, () => {
                currentCommandLineOptions = ['artisan', 'kms:seed'].concat(commandlineOptions);
                readline.write('\nRunning: php '+currentCommandLineOptions.join(' ')+'\n');
                const kmsSeedCommand = spawn('php', currentCommandLineOptions);
                this.handle(kmsSeedCommand, null, () => {
                    currentCommandLineOptions = ['artisan', 'db:seed'].concat(commandlineOptions);
                    readline.write('\nRunning: php '+currentCommandLineOptions.join(' ')+'\n');
                    const seedCommand = spawn('php', currentCommandLineOptions);
                    this.handle(seedCommand, null, resolve, reject)
                }, reject);
            }, reject);
        });
    }

    /**
     * Kill a process on port 8000. Usually php with the artisan serve script
     *
     * @return {Promise|Promise|Promise}
     */
    static killArtisans() {
        return new Promise((resolve, reject) => {
            Menu.clear();
            readline.write('\nStopping everything on port 8000....\n');
            const command = exec('lsof -t -i tcp:8000 | xargs kill');
            this.handle(command, null, () => {
                readline.write('\n\nDone.');
                setTimeout(() => {
                    Menu.clear();
                    resolve()
                }, 2000);
            },reject);
        });
    }

    /**
     * Attaches "listeners" to a process standard in and output streams and
     * a "listener" for when the process closes it.
     *
     * @param process
     * @param name
     * @param closeCallback
     * @param errorCallback
     * @param dataCallback
     */
    static handle(process, name, closeCallback, errorCallback, dataCallback = null) {
        process.stdout.on('data', this.onOutput(name, dataCallback));
        process.stderr.on('data', this.onError(name, errorCallback));
        process.on('close', this.onClose(name, closeCallback));
    }

    /**
     * Returns a function where a process can log to.
     * Readline logs it to the CLI with the name of that process.
     *
     * @param name
     * @param dataCallback
     * @return {Function}
     */
    static onOutput(name, dataCallback) {
        return (outputData) => {
            readline.write((name ? name+':' : '') +' '+outputData+'');
            if(dataCallback) dataCallback(outputData);
        }
    }

    /**
     * Returns a function where a process can log errors to.
     * Readline logs it to the CLI with the name of that process.
     *
     * @param name
     * @param errorCallback
     * @return {Function}
     */
    static onError(name, errorCallback) {
        return (errorData) => {
            readline.write((name ? name+':' : '') +' '+errorData+'');
            if(errorCallback) errorCallback(errorData);
        }
    }

    /**
     * Returns a function where a process can log to when it exits.
     * Readline logs it to the CLI with the name of that process.
     *
     * @param name
     * @param closeCallback
     * @return {Function}
     */
    static onClose(name, closeCallback) {
        return (exitCode) => {
            readline.write((name ? name+':' : '') +' stopped with exit code '+exitCode+'\n');
            if(closeCallback) closeCallback(exitCode);
        }
    }
}



//Show the main menu
Menu.mainMenu();