import { execSync } from 'child_process'; import * as path from 'path'; import * as resolve from 'resolve'; import { getProjectRoots, parseFiles } from './shared'; import { YargsAffectedOptions } from './affected'; import { getTouchedProjects } from './touched'; import { fileExists } from '../utils/fileutils'; export interface YargsFormatOptions extends YargsAffectedOptions { libsAndApps?: boolean; } const PRETTIER_EXTENSIONS = ['ts', 'js', 'scss', 'css', 'html', 'json', 'md']; export function format(command: 'check' | 'write', args: YargsFormatOptions) { let patterns: string[]; try { patterns = getPatterns(args); } catch (e) { printError(command, e); process.exit(1); } // Chunkify the patterns array to prevent crashing the windows terminal const chunkList: string[][] = chunkify(patterns, 70); switch (command) { case 'write': chunkList.forEach(chunk => write(chunk)); break; case 'check': chunkList.forEach(chunk => check(chunk)); break; } } function getPatterns(args: YargsAffectedOptions) { try { if (args.all) { return getPatternsWithPathPrefix(['{apps,libs,tools}']); } const p = parseFiles(args); let patterns = p.files .filter(f => fileExists(f)) .filter(f => PRETTIER_EXTENSIONS.map(ext => '.' + ext).includes(path.extname(f)) ); const libsAndApp = args.libsAndApps; return libsAndApp ? getPatternsFromApps(patterns) : patterns; } catch (e) { return getPatternsWithPathPrefix(['{apps,libs,tools}']); } } function getPatternsFromApps(affectedFiles: string[]): string[] { const roots = getProjectRoots(getTouchedProjects(affectedFiles)); return getPatternsWithPathPrefix(roots); } function chunkify(target: string[], size: number): string[][] { return target.reduce((current: string[][], value: string, index: number) => { if (index % size === 0) current.push([]); current[current.length - 1].push(value); return current; }, []); } function getPatternsWithPathPrefix(prefixes: string[]): string[] { return prefixes.map( prefix => `"${prefix}/**/*.{${PRETTIER_EXTENSIONS.join(',')}}"` ); } function printError(command: string, e: any) { console.error( `Pass the SHA range, as follows: npm run format:${command} -- SHA1 SHA2.` ); console.error( `Or pass the list of files, as follows: npm run format:${command} -- --files="libs/mylib/index.ts,libs/mylib2/index.ts".` ); console.error(e.message); } function write(patterns: string[]) { if (patterns.length > 0) { execSync(`node "${prettierPath()}" --write ${patterns.join(' ')}`, { stdio: [0, 1, 2] }); } } function check(patterns: string[]) { if (patterns.length > 0) { try { execSync( `node "${prettierPath()}" --list-different ${patterns.join(' ')}`, { stdio: [0, 1, 2] } ); } catch (e) { process.exit(1); } } } function prettierPath() { const basePath = path.dirname( resolve.sync('prettier', { basedir: __dirname }) ); return path.join(basePath, 'bin-prettier.js'); }