1import chalk from 'chalk'; 2import path from 'path'; 3 4import { VERSIONED_RN_IOS_DIR } from '../../../Constants'; 5 6export type TransformConfig = { 7 pipeline: TransformPipeline; 8 targetPath: string; 9 input: string; 10}; 11 12export type TransformPattern = { 13 paths?: string | string[]; 14 replace: RegExp | string; 15 with: string; 16}; 17 18export type TransformPipeline = { 19 logHeader?: (filePath: string) => void; 20 transforms: TransformPattern[]; 21}; 22 23export async function runTransformPipelineAsync({ pipeline, targetPath, input }: TransformConfig) { 24 let output = input; 25 const matches: { value: string; line: number; replacedWith: string }[] = []; 26 27 if (!Array.isArray(pipeline.transforms)) { 28 throw new Error("Pipeline's transformations must be an array of transformation patterns."); 29 } 30 31 pipeline.transforms 32 .filter((transform) => pathMatchesTransformPaths(targetPath, transform.paths)) 33 .forEach((transform) => { 34 output = output.replace(transform.replace, (match, ...args) => { 35 const { leftContext } = RegExp as unknown as { leftContext: string }; 36 const result = transform.with.replace(/\$[1-9]/g, (m) => args[parseInt(m[1], 10) - 1]); 37 38 matches.push({ 39 value: match, 40 line: leftContext.split(/\n/g).length, 41 replacedWith: result, 42 }); 43 44 return result; 45 }); 46 }); 47 48 if (matches.length > 0) { 49 if (pipeline.logHeader) { 50 pipeline.logHeader(path.relative(VERSIONED_RN_IOS_DIR, targetPath)); 51 } 52 53 for (const match of matches) { 54 console.log( 55 `${chalk.gray(String(match.line))}:`, 56 chalk.red('-'), 57 chalk.red(match.value.trimRight()) 58 ); 59 console.log( 60 `${chalk.gray(String(match.line))}:`, 61 chalk.green('+'), 62 chalk.green(match.replacedWith.trimRight()) 63 ); 64 } 65 console.log(); 66 } 67 68 return output; 69} 70 71function pathMatchesTransformPaths(filePath: string, transformPaths?: string | string[]): boolean { 72 if (typeof transformPaths === 'string') { 73 return filePath.includes(transformPaths); 74 } 75 if (Array.isArray(transformPaths)) { 76 return transformPaths.some((transformPath) => filePath.includes(transformPath)); 77 } 78 return true; 79} 80