1- import { TRANSFORM_OPTIONS } from '../config'
2- import { join } from 'node:path'
3- import { getAllFiles } from '../utils/file'
1+ import { readFile } from 'node:fs/promises'
2+ import { join , resolve } from 'node:path'
3+ import type { Options } from 'jscodeshift'
4+ import { run as jscodeshift } from 'jscodeshift/src/Runner'
45import prompts from 'prompts'
5- import execa from 'execa'
6-
7- const jscodeshiftExecutable = require . resolve ( '.bin/jscodeshift' )
8-
6+ import { coerce , compare } from 'semver'
7+ import { TRANSFORM_OPTIONS } from '../config'
8+ import { onCancel } from '../utils/share'
99
1010const transformerDirectory = join ( __dirname , '../' , 'transforms' )
11- export function onCancel ( ) {
12- process . exit ( 1 )
13- }
14- export async function upgrade ( source : string ) : Promise < void > {
11+
12+ export async function upgrade ( source : string | undefined ) {
1513 let sourceSelected = source
1614
1715 if ( ! sourceSelected ) {
@@ -28,21 +26,62 @@ export async function upgrade(source: string): Promise<void> {
2826 sourceSelected = res . path
2927 }
3028
31- const files = await getAllFiles ( sourceSelected )
29+ try {
30+ const packageJsonPath = resolve ( sourceSelected || '' , 'package.json' )
31+ const packageJson = JSON . parse ( await readFile ( packageJsonPath , 'utf8' ) )
3232
33- const args : string [ ] = [ ]
33+ const codemods = suggestCodemods ( packageJson )
3434
35- args . push ( '--no-babel' )
36- args . push ( '--silent' )
37- args . push ( '--ignore-pattern=**/node_modules/**' )
38- args . push ( '--extensions=cts,mts,ts,js,mjs,cjs' )
39- args . push ( ...files . map ( ( file ) => file . toString ( ) ) )
35+ const { codemodsSelected } = await prompts (
36+ {
37+ type : 'multiselect' ,
38+ name : 'codemodsSelected' ,
39+ message : `The following 'codemods' are recommended for your upgrade. Select the ones to apply.` ,
40+ choices : codemods . map ( ( { description, value, version } ) => {
41+ return {
42+ title : `(v${ version } ) ${ value } ` ,
43+ description,
44+ value,
45+ selected : true ,
46+ }
47+ } ) ,
48+ } ,
49+ { onCancel } ,
50+ )
4051
52+ const args : Options = {
53+ dry : false ,
54+ babel : false ,
55+ ignorePattern : '**/node_modules/**' ,
56+ extensions : 'cts,mts,ts,js,mjs,cjs' ,
57+ }
58+ const results : object [ ] = [ ]
4159
42- for ( const { value } of TRANSFORM_OPTIONS ) {
43- const transformerPath = require . resolve ( `${ transformerDirectory } /${ value } .js` )
44- const jscodeshiftProcess = execa ( jscodeshiftExecutable , [ ...args , '--transform' , transformerPath ] )
45-
46- jscodeshiftProcess . stderr ?. pipe ( process . stderr )
60+ for ( const codemod of codemodsSelected ) {
61+ const transformerPath = require . resolve ( `${ transformerDirectory } /${ codemod } .js` )
62+ const jscodeshiftProcess = await jscodeshift ( transformerPath , [ sourceSelected || '' ] , args )
63+
64+ results . push ( jscodeshiftProcess )
65+ }
66+
67+ return results
68+ } catch ( err ) {
69+ console . log ( err )
4770 }
4871}
72+
73+ function suggestCodemods ( packageJson ) {
74+ const { dependencies } = packageJson
75+
76+ if ( dependencies ?. express == null ) {
77+ return [ ]
78+ }
79+
80+ const expressVersion = coerce ( dependencies . express ) ?. version ?? '4.0.0'
81+
82+ const codemodsSuggested = TRANSFORM_OPTIONS . filter ( ( a ) => {
83+ return compare ( a . version , expressVersion ) > 0
84+ } )
85+
86+ return codemodsSuggested
87+ }
0 commit comments