Skip to content

Commit 1b64d63

Browse files
Merge pull request #125 from CodeshiftCommunity/prompt
Adds default prompt
2 parents b732f5c + c24d9e9 commit 1b64d63

File tree

11 files changed

+237
-26
lines changed

11 files changed

+237
-26
lines changed

.changeset/tasty-pigs-own.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@codeshift/cli': minor
3+
'@codeshift/fetcher': minor
4+
---
5+
6+
CLI now prompts users with codemods from their local codeshift.config.js files.

package.json

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@
2222
"types:check": "tsc --noEmit --skipLibCheck",
2323
"monorepo:check": "manypkg check",
2424
"monorepo:fix": "manypkg fix && preconstruct fix",
25-
"cli:start": "node packages/cli/bin/codeshift-cli.js",
26-
"cli:validate": "node packages/cli/bin/codeshift-cli.js validate",
27-
"cli:init": "node packages/cli/bin/codeshift-cli.js init",
28-
"cli:list": "node packages/cli/bin/codeshift-cli.js list",
25+
"cli:start": "ts-node packages/cli/bin/codeshift-cli.js",
26+
"cli:validate": "ts-node packages/cli/bin/codeshift-cli.js validate",
27+
"cli:init": "ts-node packages/cli/bin/codeshift-cli.js init",
28+
"cli:list": "ts-node packages/cli/bin/codeshift-cli.js list",
2929
"community:init": "ts-node scripts/initialize.ts",
3030
"community:validate": "ts-node scripts/validate.ts ./community",
3131
"community:release": "ts-node scripts/publish.ts ./community .tmp",
@@ -42,6 +42,7 @@
4242
"@changesets/cli": "^2.6.2",
4343
"@manypkg/cli": "^0.11.1",
4444
"@preconstruct/cli": "^2.0.0",
45+
"@types/inquirer": "^8.2.1",
4546
"@types/jest": "^26.0.15",
4647
"@types/jscodeshift": "^0.11.0",
4748
"@types/tar": "^4.0.4",

packages/cli/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@
2121
"@codeshift/validator": "^0.4.0",
2222
"chalk": "^4.1.0",
2323
"commander": "^8.2.0",
24+
"find-up": "^5.0.0",
2425
"fs-extra": "^9.1.0",
26+
"inquirer": "^8.2.4",
2527
"jscodeshift": "^0.13.1",
2628
"live-plugin-manager": "^0.15.1",
2729
"lodash": "^4.17.21",

packages/cli/src/fetch-package.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,25 +29,25 @@ export async function fetchPackageConfig(
2929
);
3030
spinner.succeed(
3131
`${chalk.green(
32-
`Found CodeshiftCommunity package: `,
32+
'Found CodeshiftCommunity package:',
3333
)} ${getCodeshiftPackageName(packageName)}`,
3434
);
3535
} catch (error) {
3636
spinner.warn(
3737
`${chalk.yellow(
38-
`Unable to locate CodeshiftCommunity package: `,
38+
`Unable to locate CodeshiftCommunity package:`,
3939
)} ${getCodeshiftPackageName(packageName)}`,
4040
);
4141
}
4242

4343
try {
4444
remoteConfig = await fetchRemotePackage(packageName, packageManager);
4545
spinner.succeed(
46-
`${chalk.green(`Found codeshift package: `)} ${packageName}`,
46+
`${chalk.green('Found codeshift package:')} ${packageName}`,
4747
);
4848
} catch (error) {
4949
spinner.warn(
50-
`${chalk.yellow(`Unable to locate codeshift package: `)} ${packageName}`,
50+
`${chalk.yellow('Unable to locate codeshift package:')} ${packageName}`,
5151
);
5252
}
5353

@@ -62,7 +62,7 @@ Make sure the package name "${packageName}" is correct and try again.`,
6262

6363
if (!isValidConfig(config)) {
6464
throw new Error(
65-
`Unable to locate a valid codeshift.config in package ${packageName}`,
65+
`Unable to locate a valid codeshift.config in package: ${packageName}`,
6666
);
6767
}
6868

packages/cli/src/index.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,10 @@ Examples:
7272
$ codeshift --sequence --packages @mylib/[email protected],@mylib/[email protected] /project/src
7373
7474
# Run the "my-custom-transform" transform
75-
$ codeshift -t path/to/my-custom-transform /project/src`,
75+
$ codeshift -t path/to/my-custom-transform /project/src
76+
77+
# Display a prompt with a list of codemods from my local \`codeshift.config.js\` file(s).
78+
$ codeshift /project/src`,
7679
)
7780
.action((path, options) => main(path, options));
7881

packages/cli/src/main.spec.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
jest.mock('globby');
22
jest.mock('live-plugin-manager');
3+
jest.mock('find-up');
34
jest.mock('jscodeshift/src/Runner', () => ({
45
run: jest.fn().mockImplementation(() => Promise.resolve()),
56
}));
@@ -34,7 +35,7 @@ describe('main', () => {
3435
}
3536
});
3637

37-
it('should exit early if nether a package or transform is supplied', async () => {
38+
it('should throw if nether a package or transform is supplied and unable to find local config', async () => {
3839
expect.assertions(1);
3940

4041
try {

packages/cli/src/main.ts

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
11
import path from 'path';
22
import semver from 'semver';
33
import chalk from 'chalk';
4-
import { PluginManager } from 'live-plugin-manager';
4+
import findUp from 'find-up';
5+
import inquirer from 'inquirer';
56

7+
import { fetchConfigAtPath } from '@codeshift/fetcher';
8+
import { PluginManager } from 'live-plugin-manager';
69
// @ts-ignore Run transform(s) on path https://github.com/facebook/jscodeshift/issues/398
710
import * as jscodeshift from 'jscodeshift/src/Runner';
811

912
import { Flags } from './types';
1013
import { InvalidUserInputError } from './errors';
1114
import { fetchPackageConfig } from './fetch-package';
15+
import { getTransformPrompt } from './prompt';
1216

1317
export default async function main(paths: string[], flags: Flags) {
1418
const packageManager = new PluginManager({
@@ -18,9 +22,43 @@ export default async function main(paths: string[], flags: Flags) {
1822
let transforms: string[] = [];
1923

2024
if (!flags.transform && !flags.packages) {
21-
throw new InvalidUserInputError(
22-
'No transform provided, please specify a transform with either the --transform or --packages flags',
25+
console.log(
26+
chalk.green(
27+
'No transforms specified, attempting to find local codeshift.config file',
28+
),
29+
);
30+
31+
const configFilePath = await findUp([
32+
'codeshift.config.js',
33+
'codeshift.config.ts',
34+
'codeshift.config.tsx',
35+
'src/codeshift.config.js',
36+
'src/codeshift.config.ts',
37+
'src/codeshift.config.tsx',
38+
'codemods/codeshift.config.js',
39+
'codemods/codeshift.config.ts',
40+
'codemods/codeshift.config.tsx',
41+
]);
42+
43+
if (!configFilePath) {
44+
throw new InvalidUserInputError(
45+
'No transform provided, please specify a transform with either the --transform or --packages flags',
46+
);
47+
}
48+
49+
console.log(
50+
chalk.green('Found local codeshift.config file at:'),
51+
configFilePath,
2352
);
53+
54+
const config = await fetchConfigAtPath(configFilePath);
55+
const answers = await inquirer.prompt([getTransformPrompt(config)]);
56+
57+
if (config.transforms && config.transforms[answers.transform]) {
58+
transforms.push(config.transforms[answers.transform]);
59+
} else if (config.presets && config.presets[answers.transform]) {
60+
transforms.push(config.presets[answers.transform]);
61+
}
2462
}
2563

2664
if (paths.length === 0) {

packages/cli/src/prompt.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import inquirer from 'inquirer';
2+
3+
import { CodeshiftConfig } from '@codeshift/types';
4+
5+
export const getTransformPrompt = (config: CodeshiftConfig) => {
6+
const transforms = Object.keys(config.transforms || {});
7+
const presets = Object.keys(config.presets || {});
8+
9+
const choices = [
10+
transforms.length ? new inquirer.Separator('Transforms') : undefined,
11+
...transforms,
12+
presets.length ? new inquirer.Separator('Presets') : undefined,
13+
...presets,
14+
].filter(item => item !== undefined);
15+
16+
return {
17+
type: 'list',
18+
name: 'transform',
19+
message: 'Which transform would you like to run?',
20+
choices,
21+
};
22+
};

packages/fetcher/src/index.ts

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,18 @@ function resolveConfigExport(pkg: any): CodeshiftConfig {
99
return pkg.default ? pkg.default : pkg;
1010
}
1111

12+
function requireConfig(filePath: string, resolvedPath: string) {
13+
try {
14+
// eslint-disable-next-line @typescript-eslint/no-var-requires
15+
const pkg = require(resolvedPath);
16+
return resolveConfigExport(pkg);
17+
} catch (e) {
18+
throw new Error(
19+
`Found config file "${filePath}" but was unable to parse it. This can be caused when transform or preset paths are incorrect.`,
20+
);
21+
}
22+
}
23+
1224
export async function fetchConfig(
1325
filePath: string,
1426
): Promise<CodeshiftConfig | undefined> {
@@ -24,20 +36,25 @@ export async function fetchConfig(
2436

2537
if (!exists) continue;
2638

27-
try {
28-
// eslint-disable-next-line @typescript-eslint/no-var-requires
29-
const pkg = require(resolvedMatchedPath);
30-
return resolveConfigExport(pkg);
31-
} catch (e) {
32-
throw new Error(
33-
`Found config file "${matchedPath}" but was unable to parse it. This can be caused when transform or preset paths are incorrect.`,
34-
);
35-
}
39+
return requireConfig(matchedPath, resolvedMatchedPath);
3640
}
3741

3842
return undefined;
3943
}
4044

45+
export async function fetchConfigAtPath(
46+
filePath: string,
47+
): Promise<CodeshiftConfig> {
48+
const resolvedFilePath = path.resolve(filePath);
49+
const exists = fs.existsSync(resolvedFilePath);
50+
51+
if (!exists) {
52+
throw new Error(`Unable to find config at path: ${filePath}`);
53+
}
54+
55+
return requireConfig(filePath, resolvedFilePath);
56+
}
57+
4158
export async function fetchPackage(
4259
packageName: string,
4360
packageManager: PluginManager,

website/docs/api/codeshift-cli.mdx

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,44 @@ and run with:
3131

3232
`$ codeshift` or `$ codeshift-cli`
3333

34-
## Options
34+
## default
35+
36+
The default CLI command (when no subcommand is specified,) will attempt to download and run transform(s) against the specified file path.
37+
38+
In the majority of cases you want to be sure to either provide the `--packages` flag for running remote codemods, or the `--transform, -t` flag to run a local transform file.
39+
40+
For running codemods as an end-user it's recommend to use the `--packages` flag, which accepts the following format: `--packages [package-name]@[semver-version]`. For example, running the codemod to migrate your codebase to `react` version `18.0.0` you would specify the following `--packages [email protected]`.
41+
42+
In special cases, codeshift package authors may choose to also expose codemod "presets", which can be considered as utility codemods for that package. Presets are also run via the `--packages` flag like so: `--packages react#remove-spread-props`.
43+
Notice that we have switched to a hash `#` here to denote that we want to run a preset.
44+
45+
Codeshift will then attempt to locate codemods from both the [community folder](https://github.com/CodeshiftCommunity/CodeshiftCommunity/tree/main/community) and the primary npm package ie [React – NPM](https://www.npmjs.com/package/react).
46+
(Note: Some packages wont have any codemods, you can use the [list](#list) subcommand to check if they exist.)
47+
48+
Lastly, when authoring a package, it's possible to test your transforms by omitting both the `--packages` and `--transform` flags. In this interactive mode, the `codeshift/cli` will attempt to locate
49+
a local `codeshift.config.js` from the current or parent directories and present an interactive prompt for you to choose from.
50+
51+
**example:**
52+
53+
Run a transform for "@mylib/button" version 3.0.0 only
54+
55+
- `$ codeshift --packages @mylib/[email protected] /project/src`
56+
57+
Run a transform for "@mylib/button" preset `foo-bar` only
58+
59+
- `$ codeshift --packages @mylib/button#foo-bar /project/src`
60+
61+
Run all transforms for "@mylib/button" greater than version 3.0.0 and @mylib/range greater than 4.0.0
62+
63+
- `$ codeshift --sequence --packages @mylib/[email protected],@mylib/[email protected] /project/src`
64+
65+
Run the "my-custom-transform" transform
66+
67+
- `$ codeshift -t path/to/my-custom-transform /project/src`
68+
69+
Display a prompt with a list of codemods from my local `codeshift.config.js` file(s).
70+
71+
- `$ codeshift /project/src`
3572

3673
### --transform, -t
3774

0 commit comments

Comments
 (0)