diff --git a/bin/cli.js b/bin/cli.js index 70c825d..ce2b32e 100755 --- a/bin/cli.js +++ b/bin/cli.js @@ -4,19 +4,24 @@ const program = require('commander') const spawn = require('child_process').spawn; const package = require('../package.json'); const chalk = require('chalk'); +const yargs = require('yargs'); +const fs = require('fs'); const build = require('./build'); const deploy = require('./deploy'); const create = require('./create'); -const yargsCli = require('yargs'); +const genTrigger = require('./gen-trigger'); +const hlp = require('./helper'); + +IS_FIREFUNC_PROJECT = hlp.is_project; program .version(package.version) .usage('') .parse(process.argv); -yargsCli - .command('new', 'create new FireFunctions project', (yargs) => { +yargs + .command(['new', 'n'], 'create new FireFunctions project', (yargs) => { yargs.usage('Usage: $0 new [name]') }, (argv) => { spawn(create(argv._[1]), { @@ -24,7 +29,7 @@ yargsCli stdio: 'inherit' }); }) - .command('build', 'build your FireFunctions project', (yargs) => { + .command(['build', 'b'], 'build your FireFunctions project', (yargs) => { yargs .usage('Usage: $0 build') .option('env', { @@ -39,7 +44,7 @@ yargsCli stdio: 'inherit' }); }) - .command('deploy', 'deploy your FireFunctions project to Firebase', (yargs) => { + .command(['deploy', 'd'], 'deploy your FireFunctions project to Firebase', (yargs) => { yargs.usage('Usage: $0 deploy') }, (argv) => { spawn(build(), { @@ -51,31 +56,28 @@ yargsCli stdio: 'inherit' }); }) - .command(['g', 'generate'], 'generate new FireFunctions project files', (yargs) => { - yargs - .usage('Usage: $0 generate') - .option('tigger', { - describe: 'add new triggers', - type: 'string', - alias: 't' - }) - .option('angular', { - describe: 'add new Angular app', - type: 'string', - alias: 'a' - }) - .option('react', { - describe: 'add new React app', - type: 'string', - alias: 'r' - }) - .option('graphql', { - describe: 'add new GraphQL app', - type: 'string', - alias: 'gpql' - }) + .command(['generate', 'g'], 'generate new FireFunctions project files', (yargs) => { + if (IS_FIREFUNC_PROJECT) { + yargs + .usage('Usage: $0 generate [options]') + .command(['trigger', 't'], 'add new triggers', (yargs) => {}, (argv) => { + // console.log(argv); + // console.log(chalk.blue.bold('Generate functionality coming soon!')); + spawn(genTrigger(argv._[2]), { + shell: true, + stdio: 'inherit' + }); + }) + .command(['angular', 'a'], 'add new Angular app', (yargs) => {}, (argv) => {}) + .command(['react', 'r'], 'add new React app', (yargs) => {}, (argv) => {}) + .command(['graphql', 'gpql'], 'add new GraphQL app', (yargs) => {}, (argv) => {}) + } else { + console.log(chalk.red.bold('Invalid Command: This is not a FireFunctions project')); + } }, (argv) => { - console.log(chalk.yellow.bold('Generate functionality coming soon!')); + if (argv[1] == null) { + // console.log(chalk.yellow.bold('Generate functionality coming soon!')); + } }) .usage('Usage: $0 [options]') .help('h') diff --git a/bin/gen-trigger.js b/bin/gen-trigger.js new file mode 100755 index 0000000..f855daa --- /dev/null +++ b/bin/gen-trigger.js @@ -0,0 +1,112 @@ +#!/usr/bin/env node + +require('shelljs/global'); +const path = require('path'); +const fs = require('fs'); +const figlet = require('figlet'); +const chalk = require('chalk'); +const execSync = require('child_process').execSync; +const spawn = require('cross-spawn'); +const jsonQuery = require('json-query'); +const hlp = require('./helper'); + +const triggerBasePath = hlp.getFromCliConfig('workspace.triggerSource') + '/'; + +function shouldUseYarn() { + try { + execSync('yarnpkg --version', { + stdio: 'ignore' + }); + return true; + } catch (e) { + return false; + } +} + +const installPackages = () => { + console.log(chalk.white.bold('Installing Packages')); + return new Promise((resolve, reject) => { + let command; + let args = ['install']; + + if (shouldUseYarn()) { + command = 'yarn'; + } else { + command = 'npm'; + } + + const child = spawn(command, args, { + stdio: 'inherit' + }); + child.on('close', code => { + if (code !== 0) { + reject({ + command: `${command} ${args.join(' ')}` + }); + return; + } + resolve(); + }) + }) +} + +const getTodayDate = () => { + var date = new Date(); + var dd = date.getDate(); + var mm = date.getMonth()+1; //January is 0! + var yyyy = date.getFullYear(); + if(dd<10) { + dd = '0'+dd + } + if(mm<10) { + mm = '0'+mm + } + today = dd + '/' + mm + '/' + yyyy; + return today; +} + +const readCliConfig = (query) => { + var jsonData = JSON.parse(fs.readFileSync('./.firefunctions-cli.json', 'utf8')); + return jsonQuery(query, { data: jsonData }).value; +} + +const replaceInFile = (file, triggerName) => { + fs.readFile(file, 'utf8', function (err, data) { + if (err) { + return console.log(err); + } + var result = data.replace(/<>/g, triggerName); + result = result.replace(/<>/g, hlp.getFromCliConfig('project.author')); + result = result.replace(/<>/g, getTodayDate()); + + fs.writeFile(file, result, 'utf8', function (err) { + if (err) return console.log(err); + }); + }); +} + +const genTrigger = (triggerName) => { + const newTriggerName = triggerName + '.ts'; + const newTriggerPath = triggerBasePath + newTriggerName; + if(!fs.existsSync(newTriggerPath)) { + console.log(chalk.grey(`Generating ${triggerName} trigger...`)) + cp('-r', __dirname + '/../blueprints/trigger.ts', newTriggerPath); + replaceInFile(newTriggerPath, triggerName); + console.log(chalk.green(`Generated new trigger: ${newTriggerPath}`)); + console.log(chalk.white.bold('Let\'s Setup')); + console.log(chalk.grey('------------------------------------------------------------------------------------')); + console.log(''); + console.log(chalk.green.bold(' Step 1: '), chalk.green('Add '), chalk.blue.bold(` " import { ${triggerName} } from './triggers/${triggerName}' " `), chalk.green('to your project\'s main index.ts')); + console.log(''); + console.log(chalk.grey('------------------------------------------------------------------------------------')); + console.log(''); + console.log(chalk.green.bold(' Step 2: '), chalk.green(`Now, Add "${triggerName}" to export in main index.ts with your other exports `), chalk.blue.bold(` " export { ${triggerName} } " `)); + console.log(''); + console.log(chalk.grey('------------------------------------------------------------------------------------')); + } else { + console.log(chalk.red(`Trigger with same exist: ${newTriggerPath}`)); + } +} + + +module.exports = genTrigger; \ No newline at end of file diff --git a/bin/helper.js b/bin/helper.js new file mode 100644 index 0000000..2f8f4f2 --- /dev/null +++ b/bin/helper.js @@ -0,0 +1,34 @@ +const path = require('path'); +const fs = require('fs'); +const jsonQuery = require('json-query'); + +const projectFile = () => { + if (fs.existsSync('./.firefunctions-cli.json')) { + return './.firefunctions-cli.json' + } else if (fs.existsSync('../.firefunctions-cli.json')) { + return '../.firefunctions-cli.json' + } else { + return '' + } +} +exports.getFromCliConfig = (query) => { + var file = projectFile() + if (file != '') { + var jsonData = JSON.parse(fs.readFileSync(file, 'utf8')); + return jsonQuery(query, { + data: jsonData + }).value; + } else { + return '' + } +} + +exports.is_project = () => { + if (fs.existsSync('./.firefunctions-cli.json')) { + return true + } else { + return false + } +} + +// module.exports = readCliConfig; \ No newline at end of file diff --git a/blueprints/trigger.ts b/blueprints/trigger.ts new file mode 100644 index 0000000..7a18d46 --- /dev/null +++ b/blueprints/trigger.ts @@ -0,0 +1,21 @@ +/* +* FILE NAME: <>.ts +* FILE PATH: './triggers/' +* AUTHOR: <> +* CREATED ON: <> +* DESCRIPTION: <> TRIGGER. +*/ + +/* +* IMPORT LIBRARY HERE +*/ +import * as functions from 'firebase-functions' +import * as admin from 'firebase-admin' + +/* + * Below you can write your triggers + */ + +export const <> = functions.database.ref('').onWrite(event => { + +}); \ No newline at end of file diff --git a/src/.firefunctions-cli.json b/src/.firefunctions-cli.json new file mode 100644 index 0000000..b805039 --- /dev/null +++ b/src/.firefunctions-cli.json @@ -0,0 +1,18 @@ +{ + "project": { + "name": "firestarter", + "author": "" + }, + "workspace": { + "root": "firefunctions", + "outDir": "functions", + "environmentSource": "firefunctions/environments/environment.ts", + "environments": { + "dev": "firefunctions/environments/environment.ts", + "prod": "firefunctions/environments/environment.prod.ts" + }, + "triggerSource": "./firefunctions/triggers", + "modelSource": "./firefunctions/models", + "apiSource": "./firefunctions/api" + } +} \ No newline at end of file