UNPKG

keppler

Version:

Real time code sharing for your lectures and presentations

331 lines (296 loc) 9.53 kB
// Depedencies const ip = require('ip') const Site = require('./site.js') const Watcher = require('./watcher.js') const Projects = require('./projects.js') const socketIo = require('socket.io') const util = require('util') const fs = require('fs') const path = require('path') const chalk = require('chalk') const gradientString = require('gradient-string') const packageJson = require('../package.json') /** * App class */ class App { /** * Constructor */ constructor() { console.log() console.log(`${gradientString.pastel('----------------------')} ${chalk.white.bold('keppler')} ${chalk.white.bold(packageJson.version)} ${gradientString.pastel('----------------------')}`) console.log() this.setConfig() // If host is not specified // Start the server if(!this.config.host) { this.setServer() } // If not started as a server // Start watching files if(!this.config.server) { this.setWatcher() } } /** * Set config */ setConfig() { const config = {} // From arguments const args = require('yargs') .option('debug', { alias: 'd', describe: 'Debug level', default: 1, type: 'number' }) .option('name', { alias: 'n', describe: 'Project name', default: '', type: 'string' }) .option('port', { alias: 'p', describe: 'Server port', default: 1571, type: 'number' }) .option('exclude', { alias: 'e', describe: 'Files to exclude (glob pattern)', default: [ '**/.DS_Store', '**/node_modules/**', '**/vendor/**', '**/.git', '**/.vscode', '**/.env', '**/.log', '.idea/**', '**/*___jb_old___', '**/*___jb_tmp___' ], type: 'array' }) .option('open', { alias: 'o', describe: 'Open in default browser', default: true, type: 'boolean' }) .option('test', { alias: 't', describe: 'Start a test project', default: false, type: 'boolean' }) .option('limit', { alias: 'l', describe: 'Limit of files above which nothing will be sent at start', default: 99, type: 'number' }) .option('max-file-size', { alias: 'm', describe: 'Maximum file size in octets', default: 99999, type: 'number' }) .option('server', { alias: 's', describe: 'Start keppler has server', default: false, type: 'boolean' }) .option('host', { alias: 'h', describe: 'Host, in case it\'s not a local', default: '', type: 'string' }) .argv config.debug = args.debug config.name = args.name config.port = args.port config.exclude = args.exclude config.open = args.open config.test = args.test config.limit = args.limit config.maxFileSize = args['max-file-size'] config.server = args.server config.host = args.host if(config.limit === -1) { config.limit = Infinity } if(config.name === '') { if(args._.length > 0 && typeof args._[0] === 'string' && args._[0] !== '') { config.name = args._[0] } } if(config.host === '') { config.host = false } // Custom config.domain = `http://${config.host ? config.host : ip.address()}${config.port !== 80 ? ':' + config.port : ''}` // Save this.config = config // Debug if(this.config.debug >= 1) { for(const _configKey in this.config) { const _configValue = '' + this.config[_configKey] console.log(`${chalk.green.bold('app > config')} - ${chalk.cyan(_configKey)} - ${chalk.cyan(_configValue)}`) } } } /** * Set server * Insitantiate the site and when the site is ready, instantiate the socket connexion and projects */ setServer() { this.setSite( () => { this.setSocket() this.setProjects() }, () => { console.log(chalk.red('error')) console.log(`${chalk.green.bold('app')} - ${chalk.cyan('keppler seems to be running already')}`) } ) } /** * Set site * Instantiate site */ setSite(_success, _error) { this.site = new Site(this.config, _success, _error) } /** * Set socket * Instantiate socket with socket io and associate it with the express server * /app socket is used to communicate between watchers and app (because multiple watchers can co-exist) */ setSocket() { this.config.socket = socketIo.listen(this.site.server) // Create a socket for the watcher const watcherSocket = this.config.socket.of('/watcher') watcherSocket.on('connection', (socket) => { // Set up let project = null // Debug if(this.config.debug >= 1) { console.log(`${chalk.green.bold('app > socket')} - ${chalk.cyan('connect')} - ${chalk.cyan(socket.id)}`) } // Start project socket.on('start_project', (data) => { data.watcherSocket = socket // Add watcher socket project = this.projects.createProject(data) this.site.createProjectRoute(project) // Debug if(this.config.debug >= 1) { console.log(`${chalk.green.bold('app > socket')} - ${chalk.cyan('start_project')} - ${chalk.cyan(project.slug)}`) } if(this.config.debug >= 2) { console.log(util.inspect(project.files.describe(), { depth: null, colors: true })) } socket.emit('started') }) // Update file socket.on('update_file', (data) => { project.files.createVersion(data.path, data.content) project.zipNeedsUpdate = true // Debug if(this.config.debug >= 1) { console.log(`${chalk.green.bold('app > socket')} - ${chalk.cyan('update_file')} - ${chalk.cyan(data.path)}`) } if(this.config.debug >= 2) { console.log(util.inspect(project.files.describe(), { depth: null, colors: true })) } }) // Create file socket.on('create_file', (data) => { project.files.create(data.path, data.content) project.zipNeedsUpdate = true // Debug if(this.config.debug >= 1) { console.log(`${chalk.green.bold('app > socket')} - ${chalk.cyan('create_file')} - ${chalk.cyan(data.path)}`) } if(this.config.debug >= 2) { console.log(util.inspect(project.files.describe(), { depth: null, colors: true })) } }) // Delete file socket.on('delete_file', (data) => { project.files.delete(data.path) project.zipNeedsUpdate = true // Debug if(this.config.debug >= 1) { console.log(`${chalk.green.bold('app > socket')} - ${chalk.cyan('delete_file')} - ${chalk.cyan(data.path)}`) } if(this.config.debug >= 2) { console.log(util.inspect(project.files.describe(), { depth: null, colors: true })) } }) // Disconnect socket.on('disconnect', () => { this.projects.deleteProject(project.slug) // Debug if(this.config.debug >= 1) { console.log(`${chalk.green.bold('app > socket')} - ${chalk.cyan('disconnect')} - ${chalk.cyan(socket.id)}`) } }) }) } /** * Set projects */ setProjects() { this.projects = new Projects(this.config) } /** * Set watcher * Instantiate watcher */ setWatcher() { this.watcher = new Watcher(this.config) } } module.exports = App