UNPKG

ryuu

Version:

Domo App Dev Studio CLI, The main tool used to create, edit, and publish app designs to Domo

203 lines 9.92 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const _ = require('lodash'); const isValidJSName_1 = __importDefault(require("../util/isValidJSName")); const slug_1 = __importDefault(require("slug")); const chalk = require('chalk'); const shelljs_1 = require("shelljs"); const async_1 = require("async"); const fs = require("fs-extra"); const path = require("path"); const log_1 = require("../util/log"); const templates_1 = require("../models/templates"); const prompts_1 = require("../util/prompts"); //import { init, initOptions } from '../models'; const commander_1 = require("commander"); module.exports = (program) => { program .command('init') .option('-n, --design_name <value>', 'Name of the design') .addOption(new commander_1.Option('-t, --template <value>', 'Name of the starter kit').choices([ templates_1.TemplateName.HELLO_WORLD, templates_1.TemplateName.MANIFEST_ONLY, templates_1.TemplateName.BASIC_CHART, templates_1.TemplateName.MAP_CHART, templates_1.TemplateName.SUGARFORCE, ])) .option('--no-datasets', 'Skip dataset prompting (use with -i and -a to include specific datasets without prompting)') .option('-i, --dataset-id [value...]', 'Give dataset ids as multiple arguments after the flag instead of using the prompt') .option('-a, --dataset-alias [value...]', 'Give dataset aliases as multiple arguments after the flag instead of using the prompt') .description('initialize a new Custom App design') .action(async (options) => { // Handle prompts with enquirer let answers = {}; if (!options.design_name) { answers.name = await (0, prompts_1.createInput)('design name'); } else { answers.name = options.design_name; } if (!options.template) { answers.starter = await (0, prompts_1.createSelect)('select a starter', Object.values(templates_1.TEMPLATES).map(template => template.name)); } else { answers.starter = options.template; } answers.datasources = options.datasetId && options.datasetAlias ? options.datasetId.map((item, i) => { return { id: item, alias: options.datasetAlias[i] }; }) : []; askDatasource(answers, options); }); }; // recursively ask user to enter all their datasources const askDatasource = async (currentAnswers, options) => { // Commander automatically sets 'datasets' to false when --no-datasets is provided if (options['datasets'] !== false) { const shouldAddDatasource = await (0, prompts_1.createConfirm)(currentAnswers.datasources.length > 0 ? 'add another dataset?' : 'would you like to connect to any datasets?', true); if (shouldAddDatasource) { try { const combinedAnswers = await addDatasource(_.merge(currentAnswers, { askDatasource: shouldAddDatasource })); // ask for more datasources (recursive call) void askDatasource(combinedAnswers, options); } catch (err) { console.log('why' + err); } } else { // all done with datasources, continue on. void initiate(_.merge(currentAnswers, { askDatasource: shouldAddDatasource })); } } else { const answers = { askDatasource: false, }; void initiate(_.merge(currentAnswers, answers)); } }; const addDatasource = async (currentAnswers) => { const id = await (0, prompts_1.createInput)('dataset id'); const alias = await (0, prompts_1.createInput)('dataset alias', '', (name) => { if (!(0, isValidJSName_1.default)(name)) return 'Alias must be a valid JavaScript property'; return true; }); const datasource = { id, alias }; currentAnswers.datasources.push(datasource); return currentAnswers; }; const writeFilesIfNonexistent = (files, dirs, allAnswers, callback) => { (0, async_1.reduce)(files, [], (filesThatExist, file, reduceCallback) => { fs.open(file, 'r', (err, fd) => { const fileExists = !err; if (fileExists) { fs.closeSync(fd); filesThatExist.push(file); } reduceCallback(null, filesThatExist); }); }, (err, filesThatExist) => { if (filesThatExist.length > 0) { callback(null, filesThatExist); } else { _.zip(files, dirs).forEach(writeTemplateFile.bind(this, allAnswers)); callback(null, files); } }); }; const writeTemplateFile = (allAnswers, filedir) => { const templateFileExt = ['.js', '.css', '.html', '.json']; const file = filedir[0]; const dir = filedir[1] || __dirname + '/../templates/'; const filePath = path.resolve(dir + file); const destPath = path.parse(path.resolve(process.cwd(), file)); let data; if (templateFileExt.some(ext => file.endsWith(ext))) { data = fs.readFileSync(filePath, 'utf8'); data = _.template(data)(allAnswers); } else { data = fs.readFileSync(filePath); } fs.writeFileSync(path.resolve(destPath.dir, destPath.base), data); }; const initiate = (allAnswers) => { let files; let dirs; let step = 0; const stepNumber = () => { step++; return `${step}.`; }; let nextStepsMessage = 'Next steps: \n'; const dirname = (0, slug_1.default)(allAnswers.name, { lower: false }); if (allAnswers.starter === 'manifest only') { files = ['manifest.json']; dirs = [null]; (0, shelljs_1.mkdir)('-p', dirname); process.chdir(path.resolve(dirname)); } else if (allAnswers.starter === templates_1.TemplateName.HELLO_WORLD) { files = (0, templates_1.getTemplateFiles)(templates_1.TemplateName.HELLO_WORLD); const templateDir = path.join(__dirname, '/../templates/', templates_1.TemplateName.HELLO_WORLD + '/'); dirs = [...new Array(files.length)].map(_ => templateDir); // eslint-disable-line @typescript-eslint/no-unused-vars nextStepsMessage += `${stepNumber()} ${chalk.cyan('cd')} into the ${chalk.green(dirname)} directory\n`; (0, shelljs_1.mkdir)('-p', dirname); process.chdir(path.resolve(dirname)); } else if (allAnswers.starter === templates_1.TemplateName.BASIC_CHART) { files = (0, templates_1.getTemplateFiles)(templates_1.TemplateName.BASIC_CHART); const customChartTemplateDir = path.join(__dirname, '/../templates/', templates_1.TemplateName.BASIC_CHART + '/'); dirs = [...new Array(files.length)].map(_ => customChartTemplateDir); // eslint-disable-line @typescript-eslint/no-unused-vars nextStepsMessage += `${stepNumber()} ${chalk.cyan('cd')} into the ${chalk.green(dirname)} directory\n`; (0, shelljs_1.mkdir)('-p', dirname); process.chdir(path.resolve(dirname)); } else if (allAnswers.starter === templates_1.TemplateName.MAP_CHART) { files = (0, templates_1.getTemplateFiles)(templates_1.TemplateName.MAP_CHART); const customChartTemplateDir = path.join(__dirname, '/../templates/', templates_1.TemplateName.MAP_CHART + '/'); dirs = [...new Array(files.length)].map(_ => customChartTemplateDir); // eslint-disable-line @typescript-eslint/no-unused-vars nextStepsMessage += `${stepNumber()} ${chalk.cyan('cd')} into the ${chalk.green(dirname)} directory\n`; (0, shelljs_1.mkdir)('-p', dirname); process.chdir(path.resolve(dirname)); } else if (allAnswers.starter === templates_1.TemplateName.SUGARFORCE) { files = (0, templates_1.getTemplateFiles)(templates_1.TemplateName.SUGARFORCE); const customChartTemplateDir = path.join(__dirname, '/../templates/', templates_1.TemplateName.SUGARFORCE + '/'); dirs = [...new Array(files.length)].map(_ => customChartTemplateDir); // eslint-disable-line @typescript-eslint/no-unused-vars nextStepsMessage += `${stepNumber()} ${chalk.cyan('cd')} into the ${chalk.green(dirname)} directory\n`; (0, shelljs_1.mkdir)('-p', dirname); (0, shelljs_1.mkdir)('-p', path.join(dirname, 'styles')); (0, shelljs_1.mkdir)('-p', path.join(dirname, 'components')); (0, shelljs_1.mkdir)('-p', path.join(dirname, 'js')); (0, shelljs_1.mkdir)('-p', path.join(dirname, 'views')); process.chdir(path.resolve(dirname)); } // populate and write out the template files writeFilesIfNonexistent(files, dirs, allAnswers, (err) => { const dirname = (0, slug_1.default)(allAnswers.name, { lower: false }); if (err) { log_1.log.fail('Cannot initialize new design. Doing so would overwrite existing files:' + err); } else { nextStepsMessage += `${stepNumber()} Edit the files that were just generated. \n${stepNumber()} Run ${chalk.yellow('domo login')} if you haven't already. \n${stepNumber()} Run ${chalk.yellow('domo publish')} to finish initializiation and whenever you make changes. \n${stepNumber()} Run ${chalk.yellow('domo dev')} to see what your app will look like and locally develop\n${stepNumber()} Add a Custom App card from the design published to any page in Domo. `; log_1.log.ok(`New design initialized in the ${chalk.green(dirname || 'current')} directory`, nextStepsMessage); } if (allAnswers.starter === 'hello world') { fs.remove('node_modules'); } process.exit(); }); }; //# sourceMappingURL=init.js.map