From 33fc72e5ce47a0669072d173e6f95e6e3661f516 Mon Sep 17 00:00:00 2001 From: Jan Tuomi Date: Thu, 12 Jul 2018 12:22:15 +0300 Subject: Initial commit --- cli.js | 232 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 232 insertions(+) create mode 100755 cli.js (limited to 'cli.js') diff --git a/cli.js b/cli.js new file mode 100755 index 0000000..6319e4c --- /dev/null +++ b/cli.js @@ -0,0 +1,232 @@ +#!/usr/bin/env node +const path = require('path'); +const fs = require('fs'); +const monk = require('monk'); +const express = require('express'); +let serverInstance; +const requireFromString = require('require-from-string'); + +const userConfigPath = path.join(process.env.HOME, '.faas.config'); +require('dotenv').config({ + path: userConfigPath, +}); +let mongoURL = process.env.MONGO_URL; + +const chalk = require('chalk'); + +const vorpal = require('vorpal')(); +vorpal.delimiter(chalk.blue('faas $')); + +const showMongoNotSetError = v => { + v.log(chalk.red('MongoDB URL is not set or is invalid. The URL is needed to authorize the CLI.')); + v.log(chalk.red('Please use the command "authorize " to set the URL.')); +} + +const checkConnection = async (url, v) => { + return new Promise((resolve, reject) => { + let db; + try { + db = monk(url); + } catch (err) { + v.log(chalk.red('Failed to authorize the CLI! Please review the Mongo URL.')); + v.log(chalk.red(String(err))); + reject(err); + } + + db.then(async () => { + models = require('./models')(db); + await models.endpoints.stats(); + resolve(); + }).catch(err => { + v.log(chalk.red('Failed to authorize the CLI! Please review the Mongo URL.')); + v.log(chalk.red(String(err))); + reject(err); + }); + }); +} + +let db, models; + +(async function() { + try { + await checkConnection(mongoURL, vorpal); + db = monk(mongoURL); + models = require('./models')(db); + } catch (err) { + showMongoNotSetError(vorpal); + } +})(); + +vorpal + .command('authorize ', 'Set the MongoDB URL to authorize the CLI.') + .action(async function(args, callback) { + if (!args.url) { + this.log('Please give the Mongo URL.'); + return callback(); + } + + const row = `MONGO_URL=${args.url}`; + fs.writeFileSync(userConfigPath, row); + + try { + await checkConnection(args.url, this); + this.log(chalk.green('CLI successfully authorized!')); + mongoURL = args.url; + } catch (err) { + mongoURL = null; + } + }); + +vorpal + .command('create ', 'Create new endpoint called "name".') + .action(async function(args, callback) { + try { + await checkConnection(mongoURL, this); + } catch (err) { + showMongoNotSetError(vorpal); + return callback(); + } + + if (!args.name) { + this.log('Please give a name for the endpoint.'); + return callback(); + } + try { + await models.endpoints.insert({ + name: args.name, + code: `module.exports = function (req, res) { res.send('Hello ${args.name}!') }`, + }); + this.log(`Created endpoint ${args.name}.`); + } catch (err) { + this.log(chalk.red('Failed to create endpoint.')); + if (String(err).includes('E11000')) { + this.log('Endpoint names must be unique.'); + } else { + this.log(String(err)); + } + } + callback(); + }); + +vorpal + .command('remove ', 'Remove endpoint called "name".') + .action(async function(args, callback) { + try { + await checkConnection(mongoURL, this); + } catch (err) { + showMongoNotSetError(vorpal); + return callback(); + } + + if (!args.name) { + this.log('Please give a name for the endpoint.'); + return callback(); + } + try { + await models.endpoints.remove({ + name: args.name, + }); + } catch (err) { + this.log(chalk.red(`Failed to remove endpoint ${args.name}!`)); + this.log(chalk.red(String(err))); + } + this.log(`Removed endpoint ${args.name}.`); + callback(); + }); + +vorpal + .command('list', 'List all endpoints.') + .action(async function(args, callback) { + try { + await checkConnection(mongoURL, this); + } catch (err) { + showMongoNotSetError(vorpal); + return callback(); + } + + const endpoints = await models.endpoints.find({}); + endpoints.forEach(endpoint => { + this.log(`${chalk(endpoint.name)}`); + }) + callback(); + }); + +vorpal + .command('upload ', 'Upload "file" to endpoint "endpoint".') + .action(async function(args, callback) { + try { + await checkConnection(mongoURL, this); + } catch (err) { + showMongoNotSetError(vorpal); + return callback(); + } + + if (!args.file || !args.endpoint) { + this.log('Please provide both "file" and "endpoint" as arguments.'); + return callback(); + } + + const existing = await models.endpoints.findOne({ name: args.endpoint }); + if (!existing) { + this.log(chalk.red(`Endpoint ${args.endpoint} doesn't exist!`)); + return callback(); + } + + try { + this.log(chalk.yellow(`Uploading function from file "${args.file}"...`)); + const data = fs.readFileSync(path.join(process.cwd(), args.file), 'utf-8'); + await models.endpoints.update( + { name: args.endpoint }, + { code: data, name: args.endpoint }, + { upsert: true }); + this.log(chalk.green(`Uploaded function successfully to endpoint ${args.endpoint}!`)); + } catch (err) { + this.log(chalk.red(`Failed to upload to endpoint ${args.endpoint}!`)); + this.log(chalk.red(String(err))); + } + callback(); + }); + +vorpal + .command('start dev ', 'Run a function locally for development purposes.') + .action(async function(args, callback) { + if (!args.file ) { + this.log('Please provide the "file" to run.'); + return callback(); + } + const code = fs.readFileSync(path.join(process.cwd(), args.file), 'utf-8'); + if (serverInstance) { + serverInstance.close(); + } + const app = express(); + const func = requireFromString(code); + app.all('*', async (req, res) => { + func(req, res); + }); + const port = 1337; + serverInstance = app.listen(port, () => + console.log(`${chalk.blue('debug server')} listening on port ${port}! URL: ${chalk.yellow(`http://localhost:${port}`)}`) + ); + callback(); + }); + +vorpal + .command('stop dev', 'Stop the development server.') + .action(async function(args, callback) { + if (serverInstance) { + serverInstance.close(); + this.log(chalk.green('Server stopped.')); + } else { + this.log(chalk.red('Server is not running.')); + } + callback(); + }); + +vorpal + .command('info', 'Show information about the session') + .action(async function(args, callback) { + this.log('Mongo URL: ' + chalk.yellow(mongoURL)); + callback(); + }); + +vorpal.show(); -- cgit v1.3