UNPKG

templates-mo

Version:

Templates is a scaffolding framework that makes code generation simple, dynamic, and reusable. Generate files, parts of your app, or whole project structures—without the repetitive copy-pasting

177 lines (152 loc) • 4.44 kB
import fs from 'fs'; import { MAIN_DIR, TPS_FOLDER, USER_HOME } from '@tps/utilities/constants'; import { CommandModule } from 'yargs'; import Templates from '@tps/templates'; import logger from '@tps/utilities/logger'; import path from 'path'; import { flatten, unique } from '@tps/utilities/helpers'; interface ListArgv { global: boolean; local: boolean; default: boolean; nodeModules: boolean; } const removeConfigFileNames = (arr: string[]) => { const configFilesMap = Templates.tpsrcConfigNames.reduce< Record<string, boolean> >((mapping, name) => { // eslint-disable-next-line no-param-reassign -- adding to object not reassigning mapping[name] = true; return mapping; }, {}); return arr.filter((item) => { // if item is not a config file return !configFilesMap[item]; }); }; export const BANNED_TEMPLATES: string[] = [ 'init', 'new-template', 'new-test', 'tps-docs', ]; export default { command: ['list', 'ls'], description: 'Show all available templates', builder: { global: { type: 'boolean', description: 'List out global files', alias: 'g', default: true, }, local: { type: 'boolean', description: 'List out local files', alias: 'l', default: true, }, default: { type: 'boolean', description: 'List out default templates', alias: 'd', default: true, }, nodeModules: { type: 'boolean', description: 'List out 3rd party templates', alias: 'n', default: true, }, }, async handler(argv) { const { local, default: defaultTemplates, global, nodeModules } = argv; logger.cli.info('Args: %n', { local, default: defaultTemplates, global, nodeModules, }); /** * All template locations */ const templateLocations = Templates.getTemplateLocations(); logger.cli.info('Template locations: %n', templateLocations); /** * Filter out local, global, default, 3rd party templates depending * on what the user supplies */ const filteredTemplates = templateLocations.filter((dir) => { const isDefaultTemplate = dir.startsWith(path.join(MAIN_DIR, TPS_FOLDER)); const isNodeModulesTemplate = path.parse(dir).base === 'node_modules'; const isGlobalTemplates = dir.startsWith(path.join(USER_HOME, TPS_FOLDER)) || dir.startsWith(path.join(USER_HOME, 'node_modules')); const isLocalTemplate = !isDefaultTemplate && !isGlobalTemplates; logger.cli.info('%s %n', dir, { isDefaultTemplate, isGlobalTemplates, isLocalTemplate, isNodeModulesTemplate, }); if (!defaultTemplates && isDefaultTemplate) return false; if (!global && isGlobalTemplates) return false; if (!nodeModules && isNodeModulesTemplate) return false; if (!local && isLocalTemplate) return false; return true; }); logger.cli.info('Templates after filter: %n\n', filteredTemplates); /** * Fetch templates in each directories still present */ const templatesNested = await Promise.all( filteredTemplates.map(async (templateDir) => { let directoryTemplates: string[] = []; try { /** * readdir throws error when not present. To prevent * making multiple call (existence, readdir) for each directory * well just return empty array here. */ directoryTemplates = await fs.promises.readdir(templateDir, {}); } catch (err) { /** * log any errors that dont have to do with the directory existing */ if (err?.code !== 'ENOENT') { logger.cli.error('Template readdir error %n', { templateDir, err, }); } return []; } if (path.parse(templateDir).base === 'node_modules') { /** * Only print out packages that start with `tps` */ directoryTemplates = directoryTemplates.filter((template) => { return template.startsWith('tps-'); }); } if (templateDir.startsWith(path.join(MAIN_DIR))) { /** * Removed banned templates. Banned templates are * this repos internal templates */ directoryTemplates = directoryTemplates.filter((template) => { return !BANNED_TEMPLATES.includes(template); }); } /** * Remove `.tpsrc` file */ return removeConfigFileNames(directoryTemplates); }), ); const templates = unique(flatten(templatesNested)); templates.forEach((template) => { console.log(template.replace(/^tps-/, '')); }); }, } as CommandModule<object, ListArgv>;