UNPKG

@mason-api/cli

Version:

CLI assistant for Mason builder

148 lines (139 loc) 4.88 kB
import { getAPIKey } from './login'; import colors from 'colors/safe'; import fs from 'fs'; import { fetchDatasource, fetchProject } from '../utils'; import generate, { getDatasourceIds } from '@mason-api/generator'; import _ from 'lodash'; export const command = 'generate <format> <project> [component] [pages..]'; export const desc = 'Generate template out of a component page'; export const builder = (yargs) => { yargs .positional('format', { describe: 'Target file format for compilation', choices: ['html', 'ejs', 'pug', 'php', 'twig', 'erb', 'haml', 'handlebars', 'mustache'], }) .positional('project', { describe: 'ID of a project that contains the component', }) .positional('component', { describe: 'ID of a component (processes all components by default)', default: '*', }) .positional('pages', { describe: 'List of pages to generate (process all pages by default)', default: '*', }) .option('embed-data', { alias: 'e', type: 'array', describe: 'Unroll loops and fill interpolations', }) .option('data-prefix', { alias: 'p', describe: 'Prefix for all top level variables', }) .option('output', { alias: 'o', describe: 'Folder to output the file to', default: '.', }) .option('file', { alias: 'f', describe: 'File name of an output file (defaults to page name)', }); }; export const handler = async (argv) => { const apiKey = argv.k || await getAPIKey(); if (!apiKey) { return null; } const verbose = !!(argv.verbose || argv.f || argv.o); Object.assign(argv, _.mapKeys(argv, (value, key) => _.camelCase(key))); if (verbose) { console.log(` - Fetching project ${colors.bold(argv.project)}...`); } let json; try { json = await fetchProject(apiKey, argv.project, verbose, argv.verbose); } catch (e) { return console.log(colors.red(`Could not fetch project ${colors.bold(argv.project)} for api key ${colors.bold(apiKey)}`)); } if (verbose && argv.component !== '*') { console.log(` - Finding component ${colors.bold(argv.component)}...`); } const project = _.find(json.projects, ['id', argv.project]); const components = argv.component === '*' ? json.components : _.find(json.components, ['id', argv.component]); if (argv.component && !components.length) { return console.log(colors.red(`Could not fetch component ${colors.bold(argv.component)} in project ${colors.bold(argv.project)}`)); } const datasourceIds = []; _.forEach(components, (comp) => { _.forEach(_.get(comp, 'config.data'), (page, name) => { _.forEach(getDatasourceIds(comp.config, name), (datasourceId) => { if (!_.includes(datasourceIds, datasourceId)) { datasourceIds.push(datasourceId); } }); }); }); if (argv.embedData) { await Promise.all(_.map(datasourceIds, async (datasourceId) => { if (_.includes(argv.embedData, datasourceId)) { const datasource = _.find(project.datasources, ['id', datasourceId]); if (verbose) { console.log(` - Fetching datasource ${colors.bold(datasourceId)}...`); } datasource.data = await fetchDatasource(datasource, argv.verbose); } })); } _.forEach(components, (component) => { const pages = argv.pages[0] === '*' ? Object.keys(component.config.data) : argv.pages; return pages.map(async (page) => { if (verbose) { console.log(` - Generating ${colors.bold(argv.format)} template for ${colors.bold(page)} page of ${colors.bold(component.name)}...`); } let template; try { template = generate(component.config, page, { datasources: project.datasources, embedData: argv.format === 'html' ? true : argv.embedData, format: argv.format, }); } catch (e) { console.log('Failed to generate file'); if (verbose) { console.log(e); } else { console.log('Set -v option to see the details of exceptions'); } } if (argv.f || argv.o) { const dir = _.join(_.compact([ argv.o, argv.pages[0] === '*' ? _.snakeCase(component.name) : null, ]), '/'); const path = `${dir}/${argv.f || page}.${argv.format}`; if (verbose) { console.log(` - Writing file ${colors.bold(path)}...`); } mkdirRecursiveSync(dir); fs.writeFileSync(path, template, { encoding: 'utf8', flag: 'w' }); } }); }); }; function mkdirRecursiveSync(path) { const paths = path.split('/'); let fullPath = ''; paths.forEach((path) => { if (fullPath === '') { fullPath = path; } else { fullPath = `${fullPath}/${path}`; } if (!fs.existsSync(fullPath)) { fs.mkdirSync(fullPath); } }); }