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
JavaScript
;
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