UNPKG

coppa

Version:

🏇 A CLI tool for local development of google cloud functions

86 lines (72 loc) 2.96 kB
#!/usr/bin/env node const fs = require('fs') const cors = require('cors') const path = require('path') const program = require('commander') const express = require('express') const morgan = require('morgan') const bodyParser = require('body-parser') const yaml = require('js-yaml') const quantor = require('quantor') const { Ok, Err, encaseRes } = require('pratica') const readServerlessYaml = (filePath, stage) => encaseRes(() => yaml.safeLoad(fs.readFileSync(filePath, 'utf8'))) .mapErr(err => `Error reading yaml file: ${filePath}, \nError: ${err}`) .chain(yml => yml.functions ? Ok(yml) : Err(`No functions declared in yaml file: ${config}`)) .map(({ functions, service }) => Object.keys(functions).map(key => ({ name: stage ? `/${service}-${stage}-${key}` : `/${service}-${key}`, display: functions[key].name, description: functions[key].description, handler: functions[key].handler }))) const readFunctionsJs = filePath => encaseRes(() => require(path.resolve(filePath))) .mapErr(err => `Could not read main functions module: ${filePath}, \nError: ${err}`) const sanitizeFuncs = ({ handlers, funcsMod }) => handlers .map(({ name, display, description, handler }) => ({ name, display, description, handler: funcsMod[handler] })) .filter(({ handler }) => !!handler) const createServer = port => funcs => { const app = express() app.use(bodyParser.urlencoded({ extended: true })) app.use(bodyParser.json()) app.use(morgan('dev')) app.use(cors()) funcs.map(({ name, handler }) => console.log(name) || app.use(name, handler)) app.get('/', (req, res) => quantor({ title: 'Coppa Server', endpoints: funcs.map(({ name, display, description }) => ({ name, description: description || 'No description provided...', display: display || 'No name provided...', handlers: { GET: {}, POST: {}, PUT: {}, DELETE: {} } })) })(html => res.send(html))) app.listen(port, () => console.log(`Coppa listening on port ${port}!`)) } const start = opts => { const port = opts.port || 8080 const config = opts.config || './serverless.yml' const entry = opts.entry || './index.js' const stage = opts.stage readServerlessYaml(config, stage) .chain(handlers => readFunctionsJs(entry).map(funcsMod => ({ handlers, funcsMod }))) .map(sanitizeFuncs) .cata({ Ok: createServer(port), Err: msg => { console.error(msg) process.exit(1) } }) } // --- CLI PROGRAM --- // program.version('1.0.0') program .command('start') .description('Start the Coppa dev server') .option('-c, --config [path]', 'Path to serverless config file (default: ./serverless.yml)') .option('-e, --entry [path]', 'Path to JS entry point file (default: ./index.js)') .option('-s, --stage [stage]', 'Stage to be used') .option('-p, --port [port]', 'Port for server to use (default: 8080)') .action(start) program.parse(process.argv)