1
1
import path from 'path' ;
2
- import semver from 'semver' ;
3
2
import chalk from 'chalk' ;
4
- import findUp from 'find-up' ;
5
- import inquirer from 'inquirer' ;
6
3
import { PluginManager , PluginManagerOptions } from 'live-plugin-manager' ;
7
4
8
5
import * as core from '@hypermod/core' ;
9
- import {
10
- type ModuleLoader as MdlLoader ,
11
- fetchConfigAtPath ,
12
- } from '@hypermod/fetcher' ;
6
+ import { type ModuleLoader as MdlLoader } from '@hypermod/fetcher' ;
13
7
14
8
import { InvalidUserInputError } from './errors' ;
15
- import { fetchPackages } from './utils/fetch-package' ;
16
- import { mergeConfigs } from './utils/merge-configs' ;
17
- import { fetchConfigsForWorkspaces , getPackageJson } from './utils/file-system' ;
18
9
import ModuleLoader from './utils/module-loader' ;
19
- import { getConfigPrompt , getMultiConfigPrompt } from './prompt' ;
10
+ import { resolveLocalTransforms } from './resolvers/local' ;
11
+ import { resolveNpmTransforms } from './resolvers/npm' ;
12
+ import { resolveAppTransforms } from './resolvers/app' ;
13
+
14
+ const CLI_DIR = path . join ( __dirname , '..' , 'node_modules' ) ;
20
15
21
16
export default async function main (
22
17
paths : string [ ] ,
@@ -29,7 +24,7 @@ export default async function main(
29
24
}
30
25
31
26
const pluginManagerConfig : Partial < PluginManagerOptions > = {
32
- pluginsPath : path . join ( __dirname , '..' , 'node_modules' ) ,
27
+ pluginsPath : CLI_DIR ,
33
28
} ;
34
29
35
30
// If a registry is provided in the CLI flags, use it for the pluginManagers configuration.
@@ -53,122 +48,22 @@ export default async function main(
53
48
54
49
let transforms : string [ ] = [ ] ;
55
50
51
+ /**
52
+ * If no transforms are provided, attempt to find codemods in the local hypermod.config file
53
+ * or in the local package.json file.
54
+ */
56
55
if ( ! flags . transform && ! flags . packages ) {
57
56
console . log (
58
57
chalk . green (
59
58
'No transforms specified, attempting to find local hypermod.config file(s)' ,
60
59
) ,
61
60
) ;
62
61
63
- /**
64
- * Attempt to locate a root package.json with a workspaces config.
65
- * If found, show a prompt with all available codemods
66
- */
67
- const localPackageJson = await getPackageJson ( ) ;
68
-
69
- if ( localPackageJson && localPackageJson . workspaces ) {
70
- const configs = await fetchConfigsForWorkspaces (
71
- localPackageJson . workspaces ,
72
- ) ;
73
- const answers = await inquirer . prompt ( [ getMultiConfigPrompt ( configs ) ] ) ;
74
- const selectedConfig = configs . find (
75
- ( { filePath } ) => answers . codemod . filePath === filePath ,
76
- ) ;
77
-
78
- if ( ! selectedConfig ) {
79
- throw new Error (
80
- `Unable to locate config at: ${ answers . codemod . filePath } ` ,
81
- ) ;
82
- }
83
-
84
- if (
85
- selectedConfig . config . transforms &&
86
- selectedConfig . config . transforms [ answers . codemod . selection ]
87
- ) {
88
- if ( flags . sequence ) {
89
- Object . entries (
90
- selectedConfig . config . transforms as Record < string , string > ,
91
- )
92
- . filter ( ( [ key ] ) =>
93
- semver . satisfies ( key , `>=${ answers . codemod . selection } ` ) ,
94
- )
95
- . forEach ( ( [ , path ] ) => transforms . push ( path ) ) ;
96
- } else {
97
- transforms . push (
98
- selectedConfig . config . transforms [ answers . codemod . selection ] ,
99
- ) ;
100
- }
101
- } else if (
102
- selectedConfig . config . presets &&
103
- selectedConfig . config . presets [ answers . codemod . selection ]
104
- ) {
105
- transforms . push (
106
- selectedConfig . config . presets [ answers . codemod . selection ] ,
107
- ) ;
108
- }
109
- } else {
110
- /**
111
- * Otherwise, locate any config files in parent directories
112
- */
113
- const configFilePath = await findUp ( [
114
- 'hypermod.config.js' ,
115
- 'hypermod.config.mjs' ,
116
- 'hypermod.config.cjs' ,
117
- 'hypermod.config.ts' ,
118
- 'hypermod.config.tsx' ,
119
- 'src/hypermod.config.js' ,
120
- 'src/hypermod.config.mjs' ,
121
- 'src/hypermod.config.cjs' ,
122
- 'src/hypermod.config.ts' ,
123
- 'src/hypermod.config.tsx' ,
124
- 'codemods/hypermod.config.js' ,
125
- 'codemods/hypermod.config.mjs' ,
126
- 'codemods/hypermod.config.cjs' ,
127
- 'codemods/hypermod.config.ts' ,
128
- 'codemods/hypermod.config.tsx' ,
129
- 'codeshift.config.js' ,
130
- 'codeshift.config.mjs' ,
131
- 'codeshift.config.cjs' ,
132
- 'codeshift.config.ts' ,
133
- 'codeshift.config.tsx' ,
134
- 'src/codeshift.config.js' ,
135
- 'src/codeshift.config.mjs' ,
136
- 'src/codeshift.config.cjs' ,
137
- 'src/codeshift.config.ts' ,
138
- 'src/codeshift.config.tsx' ,
139
- 'codemods/codeshift.config.js' ,
140
- 'codemods/codeshift.config.mjs' ,
141
- 'codemods/codeshift.config.cjs' ,
142
- 'codemods/codeshift.config.ts' ,
143
- 'codemods/codeshift.config.tsx' ,
144
- ] ) ;
145
-
146
- if ( ! configFilePath ) {
147
- throw new InvalidUserInputError (
148
- 'No transform provided, please specify a transform with either the --transform or --packages flags' ,
149
- ) ;
150
- }
151
-
152
- console . log (
153
- chalk . green ( 'Found local hypermod.config file at:' ) ,
154
- configFilePath ,
155
- ) ;
156
-
157
- const config = await fetchConfigAtPath ( configFilePath ) ;
158
- const answers = await inquirer . prompt ( [ getConfigPrompt ( config ) ] ) ;
159
-
160
- if ( config . transforms && config . transforms [ answers . codemod ] ) {
161
- Object . entries ( config . transforms )
162
- . filter ( ( [ key ] ) => semver . satisfies ( key , `>=${ answers . codemod } ` ) )
163
- . forEach ( ( [ , codemod ] ) =>
164
- transforms . push ( `${ configFilePath } @${ codemod } ` ) ,
165
- ) ;
166
- } else if ( config . presets && config . presets [ answers . codemod ] ) {
167
- transforms . push ( `${ configFilePath } #${ answers . codemod } ` ) ;
168
- }
169
- }
62
+ const localTransforms = await resolveLocalTransforms ( flags ) ;
63
+ transforms . push ( ...localTransforms ) ;
170
64
}
171
65
66
+ // If a direct path to a transform is provided, use it
172
67
if ( flags . transform ) {
173
68
if ( flags . transform . includes ( ',' ) ) {
174
69
flags . transform . split ( ',' ) . forEach ( t => transforms . push ( t . trim ( ) ) ) ;
@@ -177,91 +72,32 @@ export default async function main(
177
72
}
178
73
}
179
74
75
+ // If a package name is provided, fetch the community and remote configs
76
+ // and merge them to get the transforms
180
77
if ( flags . packages ) {
181
- const pkgs = flags . packages . split ( ',' ) . filter ( pkg => ! ! pkg ) ;
78
+ const pkgs = flags . packages ! . split ( ',' ) . filter ( pkg => ! ! pkg ) ;
182
79
183
80
for ( const pkg of pkgs ) {
184
- const shouldPrependAtSymbol = pkg . startsWith ( '@' ) ? '@' : '' ;
185
- const pkgName =
186
- shouldPrependAtSymbol + pkg . split ( / [ @ # ] / ) . filter ( str => ! ! str ) [ 0 ] ;
187
-
188
- const rawTransformIds = pkg . split ( / (? = [ @ # ] ) / ) . filter ( str => ! ! str ) ;
189
- rawTransformIds . shift ( ) ;
190
-
191
- const transformIds = rawTransformIds
192
- . filter ( id => id . startsWith ( '@' ) )
193
- . map ( id => id . substring ( 1 ) )
194
- . sort ( ( idA , idB ) => {
195
- if ( semver . lt ( idA , idB ) ) return - 1 ;
196
- if ( semver . gt ( idA , idB ) ) return 1 ;
197
- return 0 ;
198
- } ) ;
199
-
200
- const presetIds = rawTransformIds
201
- . filter ( id => id . startsWith ( '#' ) )
202
- . map ( id => id . substring ( 1 ) ) ;
81
+ /**
82
+ * If the package name starts with "hm-", it is a Hypermod transform.
83
+ * We need to fetch the transform from the Hypermod API and add it to the transforms array.
84
+ */
85
+ if ( pkg . startsWith ( 'hm-' ) ) {
86
+ const hmTransform = await resolveAppTransforms ( pkg , CLI_DIR ) ;
87
+ transforms . push ( hmTransform ) ;
88
+ continue ;
89
+ }
203
90
204
- const { community, remote } = await fetchPackages (
205
- pkgName ,
91
+ /**
92
+ * We need to fetch the transform from the npm registry and add it to the transforms array.
93
+ */
94
+ const npmTransforms = await resolveNpmTransforms (
95
+ flags ,
96
+ pkg ,
206
97
packageManager ,
207
98
) ;
208
99
209
- const config = mergeConfigs ( community , remote ) ;
210
-
211
- // Validate transforms/presets
212
- transformIds . forEach ( id => {
213
- if ( ! semver . valid ( semver . coerce ( id . substring ( 1 ) ) ) ) {
214
- throw new InvalidUserInputError (
215
- `Invalid version provided to the --packages flag. Unable to resolve version "${ id } " for package "${ pkgName } ". Please try: "[scope]/[package]@[version]" for example @mylib/[email protected] ` ,
216
- ) ;
217
- }
218
-
219
- if ( ! config . transforms || ! config . transforms [ id ] ) {
220
- throw new InvalidUserInputError (
221
- `Invalid version provided to the --packages flag. Unable to resolve version "${ id } " for package "${ pkgName } "` ,
222
- ) ;
223
- }
224
- } ) ;
225
-
226
- presetIds . forEach ( id => {
227
- if ( ! config . presets || ! config . presets [ id ] ) {
228
- throw new InvalidUserInputError (
229
- `Invalid preset provided to the --packages flag. Unable to resolve preset "${ id } " for package "${ pkgName } "` ,
230
- ) ;
231
- }
232
- } ) ;
233
-
234
- if ( presetIds . length === 0 && transformIds . length === 0 ) {
235
- const res : { codemod : string } = await inquirer . prompt ( [
236
- getConfigPrompt ( config ) ,
237
- ] ) ;
238
-
239
- if ( semver . valid ( semver . coerce ( res . codemod ) ) ) {
240
- transformIds . push ( res . codemod ) ;
241
- } else {
242
- presetIds . push ( res . codemod ) ;
243
- }
244
- }
245
-
246
- // Get transform file paths
247
- if ( config . transforms ) {
248
- if ( flags . sequence ) {
249
- Object . entries ( config . transforms )
250
- . filter ( ( [ key ] ) => semver . satisfies ( key , `>=${ transformIds [ 0 ] } ` ) )
251
- . forEach ( ( [ , path ] ) => transforms . push ( path ) ) ;
252
- } else {
253
- Object . entries ( config . transforms )
254
- . filter ( ( [ id ] ) => transformIds . includes ( id ) )
255
- . forEach ( ( [ , path ] ) => transforms . push ( path ) ) ;
256
- }
257
- }
258
-
259
- // Get preset file paths
260
- if ( config . presets ) {
261
- Object . entries ( config . presets )
262
- . filter ( ( [ id ] ) => presetIds . includes ( id ) )
263
- . forEach ( ( [ , path ] ) => transforms . push ( path ) ) ;
264
- }
100
+ transforms . push ( ...npmTransforms ) ;
265
101
}
266
102
}
267
103
0 commit comments