import path from 'path' ; import { isBinaryFile } from 'isbinaryfile' ; import { createDebug , info } from './log' ; import { findAllPathsCategorized , findProjectPath , expandDirectoryPaths , readFile , writeFile , updateSourcePath , } from './path' ; import { validate , createMovePaths , DEFAULT , JS_EXTENSIONS } from './options' ; import type { MoveOptions , PathMap } from './options' ; import type { ParsedOptions } from './transform' ; import Runner from 'jscodeshift/src/Runner' ; const debug = createDebug ( __filename ) ; type TransformOptions = { parser ? : string ; recastOptions ? : { [ k ] : string ; } ; ignorePattern : Array < string > ; } ; type NormalizedOptions = { expandedPaths : PathMap ; } & TransformOptions ; async function promiseObject < T > ( object ) { const obj = await Promise . all ( Object . entries ( object ) . map ( ( entry ) => Promise . all ( entry ) ) ) . then ( ( entries ) => entries . reduce < any > ( ( acc , [ k , v ] ) => { acc [ k ] = v ; return acc ; } , { } ) ) ; return obj as Promise < T > ; } async function genericTransform ( paths , options ) { for await ( const { _path , content } of paths . map ( ( p ) => promiseObject ( { _path : p , content : readFile ( p ) } ) ) ) { const isFileBinary = await isBinaryFile ( content ) ; if ( isFileBinary ) { continue ; } const transformedContent = String ( content ) . replace ( /(['"])([\t ]*\.\.?\/[^\1\t ]*?)[\t ]*\1/g , ( _ , quote , filePath ) => { const context = { file : { path : _path , source : '' } , options , } ; return `${ quote }${ updateSourcePath ( context , filePath . trim ( ) ) }${ quote }` ; } ) ; await writeFile ( _path , transformedContent , 'utf-8' ) ; } } export async function executeTransform ( options ) { const { expandedPaths , ignorePattern } = options ; debug ( 'expandedPaths' , JSON . stringify ( expandedPaths , null , 2 ) ) ; const projectPath = await findProjectPath ( ) ; info ( `Detected project path: ${ projectPath }` ) ; const recastOptions = { ... DEFAULT . recast , ... options . recastOptions } ; if ( options . recastOptions ) { info ( `Recast options:\n${ JSON . stringify ( recastOptions , null , 2 ) }` ) ; } const { js : allJSPaths , others : allOtherPaths , } = await findAllPathsCategorized ( projectPath , { ignorePattern } ) ; debug ( 'Detected js paths' , `\n  ${ allJSPaths . join ( '\n  ' ) }` ) ; const transformOptions = { expandedPaths , recastOptions , } ; await Promise . all ( [ genericTransform ( allOtherPaths , transformOptions ) , Runner . run ( path . join ( __dirname , 'transform.js' ) , allJSPaths , { silent : true , verbose : 0 , extensions : Array . from ( JS_EXTENSIONS ) . join ( ',' ) , parser : options . parser || DEFAULT . parser , options : transformOptions , } ) , ] ) ; } type Options = MoveOptions & TransformOptions ; export async function transform ( options ) { const expandedPaths = await expandDirectoryPaths ( await createMovePaths ( await validate ( options ) ) ) ; await executeTransform ( { ... options , expandedPaths , } ) ; }