@mui/x-codemod 6.0.0-alpha.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,94 @@
1
+ # @mui/x-codemod
2
+
3
+ > Codemod scripts for MUI X
4
+
5
+ [![npm version](https://img.shields.io/npm/v/@mui/x-codemod.svg?style=flat-square)](https://www.npmjs.com/package/@mui/x-codemod)
6
+ [![npm downloads](https://img.shields.io/npm/dm/@mui/x-codemod.svg?style=flat-square)](https://www.npmjs.com/package/@mui/x-codemod)
7
+
8
+ This repository contains a collection of codemod scripts based for use with
9
+ [jscodeshift](https://github.com/facebook/jscodeshift) that help update MUI X APIs.
10
+
11
+ ## Setup & run
12
+
13
+ <!-- #default-branch-switch -->
14
+
15
+ ```bash
16
+ npx @mui/x-codemod <codemod> <paths...>
17
+
18
+ Applies a `@mui/x-codemod` to the specified paths
19
+
20
+ Positionals:
21
+ codemod The name of the codemod [string]
22
+ paths Paths forwarded to `jscodeshift` [string]
23
+
24
+ Options:
25
+ --version Show version number [boolean]
26
+ --help Show help [boolean]
27
+ --parser which parser for jscodeshift to use.
28
+ [string] [default: 'tsx']
29
+ --jscodeshift Pass options directly to jscodeshift [array]
30
+
31
+ Examples:
32
+ npx @mui/x-codemod v6.0.0/preset-safe src
33
+ npx @mui/x-codemod v6.0.0/component-rename-prop src --
34
+ --component=DataGrid --from=prop --to=newProp
35
+ ```
36
+
37
+ ### `jscodeshift` options
38
+
39
+ To pass more options directly to jscodeshift, use `--jscodeshift=...`. For example:
40
+
41
+ ```sh
42
+ // single option
43
+ npx @mui/x-codemod --jscodeshift=--run-in-band
44
+ // multiple options
45
+ npx @mui/x-codemod --jscodeshift=--cpus=1 --jscodeshift=--print --jscodeshift=--dry --jscodeshift=--verbose=2
46
+ ```
47
+
48
+ See all available options [here](https://github.com/facebook/jscodeshift#usage-cli).
49
+
50
+ ### `Recast` Options
51
+
52
+ Options to [recast](https://github.com/benjamn/recast)'s printer can be provided
53
+ through jscodeshift's `printOptions` command line argument
54
+
55
+ ```sh
56
+ npx @mui/x-codemod <transform> <path> --jscodeshift="--printOptions='{\"quote\":\"double\"}'"
57
+ ```
58
+
59
+ ## Included scripts
60
+
61
+ ### v6.0.0
62
+
63
+ #### 🚀 `preset-safe`
64
+
65
+ A combination of all important transformers for migrating v5 to v6. ⚠️ This codemod should be run only once.
66
+
67
+ ```sh
68
+ npx @mui/x-codemod v6.0.0/preset-safe <path|folder>
69
+ ```
70
+
71
+ The list includes these transformers
72
+
73
+ - [`localization-provider-rename-locale`](#localization-provider-rename-locale)
74
+
75
+ #### `localization-provider-rename-locale`
76
+
77
+ Renames `locale` into `adapterLocale` (or `LocalizationProvider`)
78
+
79
+ ```diff
80
+ <LocalizationProvider
81
+ dateAdapter={AdapterDayjs}
82
+ - locale="fr"
83
+ + adapterLocale="fr"
84
+ >
85
+ {children}
86
+ </LocalizationProvider
87
+
88
+ ```
89
+
90
+ ```sh
91
+ npx @mui/x-codemod v6.0.0/localization-provider-rename-locale <path>
92
+ ```
93
+
94
+ You can find more details about this breaking change in [the migration guide](https://next.mui.com/x/migration/migration-pickers-v5/#rename-the-locale-prop-on-localizationprovider).
package/codemod.js ADDED
@@ -0,0 +1,80 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+
4
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
5
+ var _child_process = _interopRequireDefault(require("child_process"));
6
+ var _fs = require("fs");
7
+ var _path = _interopRequireDefault(require("path"));
8
+ var _yargs = _interopRequireDefault(require("yargs"));
9
+ const jscodeshiftPackage = require('jscodeshift/package.json');
10
+ const jscodeshiftDirectory = _path.default.dirname(require.resolve('jscodeshift'));
11
+ const jscodeshiftExecutable = _path.default.join(jscodeshiftDirectory, jscodeshiftPackage.bin.jscodeshift);
12
+ async function runTransform(transform, files, flags, codemodFlags) {
13
+ const transformerSrcPath = _path.default.resolve(__dirname, './src', transform);
14
+ const transformerBuildPath = _path.default.resolve(__dirname, transform);
15
+ let transformerPath;
16
+ try {
17
+ await _fs.promises.stat(transformerSrcPath);
18
+ transformerPath = transformerSrcPath;
19
+ } catch (srcPathError) {
20
+ try {
21
+ await _fs.promises.stat(transformerBuildPath);
22
+ transformerPath = transformerBuildPath;
23
+ } catch (buildPathError) {
24
+ if (buildPathError.code === 'ENOENT') {
25
+ throw new Error(`Transform '${transform}' not found. Check out ${_path.default.resolve(__dirname, './README.md for a list of available codemods.')}`);
26
+ }
27
+ throw buildPathError;
28
+ }
29
+ }
30
+ const args = [
31
+ // can't directly spawn `jscodeshiftExecutable` due to https://github.com/facebook/jscodeshift/issues/424
32
+ jscodeshiftExecutable, '--transform', transformerPath, ...codemodFlags, '--extensions', 'js,ts,jsx,tsx', '--parser', flags.parser || 'tsx', '--ignore-pattern', '**/node_modules/**', ...flags.jscodeshift];
33
+ args.push(...files);
34
+
35
+ // eslint-disable-next-line no-console -- debug information
36
+ console.log(`Executing command: jscodeshift ${args.join(' ')}`);
37
+ const jscodeshiftProcess = _child_process.default.spawnSync('node', args, {
38
+ stdio: 'inherit'
39
+ });
40
+ if (jscodeshiftProcess.error) {
41
+ throw jscodeshiftProcess.error;
42
+ }
43
+ }
44
+ function run(argv) {
45
+ const {
46
+ codemod,
47
+ paths,
48
+ _: other,
49
+ jscodeshift,
50
+ parser
51
+ } = argv;
52
+ return runTransform(codemod, paths.map(filePath => _path.default.resolve(filePath)), {
53
+ jscodeshift,
54
+ parser
55
+ }, other || []);
56
+ }
57
+ _yargs.default.command({
58
+ command: '$0 <codemod> <paths...>',
59
+ describe: 'Applies a `@mui/x-codemod` to the specified paths',
60
+ // @ts-expect-error
61
+ builder: command => {
62
+ return command.positional('codemod', {
63
+ description: 'The name of the codemod',
64
+ type: 'string'
65
+ }).positional('paths', {
66
+ array: true,
67
+ description: 'Paths forwarded to `jscodeshift`',
68
+ type: 'string'
69
+ }).option('parser', {
70
+ description: 'which parser for jscodeshift to use',
71
+ default: 'tsx',
72
+ type: 'string'
73
+ }).option('jscodeshift', {
74
+ description: '(Advanced) Pass options directly to jscodeshift',
75
+ default: [],
76
+ type: 'array'
77
+ });
78
+ },
79
+ handler: run
80
+ }).scriptName('npx @mui/x-codemod').example('$0 v6.0.0/localization-provider-rename-locale src', 'Run "localization-provider-rename-locale" codemod on "src" path').example('$0 v6.0.0/component-rename-prop src -- --component=DataGrid --from=prop --to=newProp', 'Run "component-rename-prop" codemod in "src" path on "DataGrid" component with custom "from" and "to" arguments').help().parse();
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "@mui/x-codemod",
3
+ "version": "6.0.0-alpha.9",
4
+ "bin": "./codemod.js",
5
+ "private": false,
6
+ "author": "MUI Team",
7
+ "description": "Codemod scripts for MUI X.",
8
+ "keywords": [
9
+ "react",
10
+ "react-component",
11
+ "mui",
12
+ "codemod",
13
+ "jscodeshift"
14
+ ],
15
+ "scripts": {
16
+ "test": "cd ../../ && cross-env NODE_ENV=test mocha 'packages/x-codemod/**/*.test.ts'",
17
+ "typescript": "tsc -p tsconfig.json",
18
+ "prebuild": "rimraf build",
19
+ "copy-files": "cpy README.md build && cpy package.json build",
20
+ "build": "node ../../scripts/build.mjs node --ignore 'src/types.ts' && yarn copy-files"
21
+ },
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "https://github.com/mui/mui-x.git",
25
+ "directory": "packages/x-codemod"
26
+ },
27
+ "license": "MIT",
28
+ "homepage": "https://github.com/mui/mui-x/tree/next/packages/x-codemod",
29
+ "funding": {
30
+ "type": "opencollective",
31
+ "url": "https://opencollective.com/mui"
32
+ },
33
+ "dependencies": {
34
+ "@babel/core": "^7.20.2",
35
+ "@babel/runtime": "^7.20.1",
36
+ "@babel/traverse": "^7.20.1",
37
+ "jscodeshift": "0.13.1",
38
+ "jscodeshift-add-imports": "^1.0.10",
39
+ "yargs": "^17.6.2"
40
+ },
41
+ "devDependencies": {
42
+ "@types/jscodeshift": "^0.11.5"
43
+ },
44
+ "sideEffects": false,
45
+ "publishConfig": {
46
+ "access": "public"
47
+ },
48
+ "engines": {
49
+ "node": ">=14.0.0"
50
+ }
51
+ }
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = propsToObject;
7
+ function propsToObject({
8
+ j,
9
+ root,
10
+ componentName,
11
+ aliasName,
12
+ propName,
13
+ props
14
+ }) {
15
+ function buildObject(node, value) {
16
+ const shorthand = node.value.expression && node.value.expression.name === node.name.name;
17
+ const property = j.objectProperty(j.identifier(node.name.name), node.value.expression ? node.value.expression : node.value);
18
+ property.shorthand = shorthand;
19
+ value.push(property);
20
+ return value;
21
+ }
22
+ const result = aliasName ? root.find(j.JSXElement, {
23
+ openingElement: {
24
+ name: {
25
+ property: {
26
+ name: componentName
27
+ }
28
+ }
29
+ }
30
+ }) : root.findJSXElements(componentName);
31
+ return result.forEach(path => {
32
+ // @ts-expect-error
33
+ if (!aliasName || aliasName && path.node.openingElement.name.object.name === aliasName) {
34
+ let propValue = [];
35
+ const attributes = path.node.openingElement.attributes;
36
+ attributes?.forEach((node, index) => {
37
+ // Only transform whitelisted props
38
+ if (node.type === 'JSXAttribute' && props.includes(node.name.name)) {
39
+ propValue = buildObject(node, propValue);
40
+ delete attributes[index];
41
+ }
42
+ });
43
+ if (propValue.length > 0) {
44
+ const propNameAttr = attributes?.find(attr => attr.type === 'JSXAttribute' && attr.name.name === propName);
45
+ if (propNameAttr && propNameAttr.type === 'JSXAttribute') {
46
+ // @ts-expect-error
47
+ (propNameAttr.value.expression?.properties || []).push(...j.objectExpression(propValue).properties);
48
+ } else {
49
+ attributes?.push(j.jsxAttribute(j.jsxIdentifier(propName), j.jsxExpressionContainer(j.objectExpression(propValue))));
50
+ }
51
+ }
52
+ }
53
+ });
54
+ }
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.default = readFile;
8
+ var _fs = _interopRequireDefault(require("fs"));
9
+ var _os = require("os");
10
+ function readFile(filePath) {
11
+ const fileContents = _fs.default.readFileSync(filePath, 'utf8').toString();
12
+ if (_os.EOL !== '\n') {
13
+ return fileContents.replace(/\n/g, _os.EOL);
14
+ }
15
+ return fileContents;
16
+ }
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = renameClassKey;
7
+ function renameClassKey({
8
+ root,
9
+ componentName,
10
+ classes,
11
+ printOptions
12
+ }) {
13
+ const source = root.findJSXElements(componentName).forEach(path => {
14
+ path.node.openingElement.attributes?.forEach(node => {
15
+ if (node.type === 'JSXAttribute' && node.name.name === 'classes') {
16
+ // @ts-expect-error
17
+ node.value?.expression?.properties?.forEach(subNode => {
18
+ if (Object.keys(classes).includes(subNode.key.name)) {
19
+ subNode.key.name = classes[subNode.key.name];
20
+ }
21
+ });
22
+ }
23
+ });
24
+ }).toSource(printOptions);
25
+ return Object.entries(classes).reduce((result, [currentKey, newKey]) => {
26
+ const regex = new RegExp(`.Mui${componentName}-${currentKey}`, 'gm');
27
+ return result.replace(regex, `.Mui${componentName}-${newKey}`);
28
+ }, source);
29
+ }
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = renameProps;
7
+ function renameProps({
8
+ root,
9
+ componentName,
10
+ props
11
+ }) {
12
+ return root.findJSXElements(componentName).forEach(path => {
13
+ path.node.openingElement.attributes?.forEach(node => {
14
+ if (node.type === 'JSXAttribute' && Object.keys(props).includes(node.name.name)) {
15
+ node.name.name = props[node.name.name];
16
+ }
17
+ });
18
+ });
19
+ }
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.default = transformer;
8
+ var _renameProps = _interopRequireDefault(require("../../util/renameProps"));
9
+ function transformer(file, api, options) {
10
+ const j = api.jscodeshift;
11
+ const root = j(file.source);
12
+ const printOptions = options.printOptions;
13
+ return (0, _renameProps.default)({
14
+ root,
15
+ componentName: options.component,
16
+ props: {
17
+ [options.from]: options.to
18
+ }
19
+ }).toSource(printOptions);
20
+ }
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.default = transformer;
8
+ var _renameProps = _interopRequireDefault(require("../../util/renameProps"));
9
+ function transformer(file, api, options) {
10
+ const j = api.jscodeshift;
11
+ const root = j(file.source);
12
+ const printOptions = options.printOptions;
13
+ return (0, _renameProps.default)({
14
+ root,
15
+ componentName: 'LocalizationProvider',
16
+ props: {
17
+ locale: 'adapterLocale'
18
+ }
19
+ }).toSource(printOptions);
20
+ }
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.default = transformer;
8
+ var _localizationProviderRenameLocale = _interopRequireDefault(require("../localization-provider-rename-locale"));
9
+ function transformer(file, api, options) {
10
+ file.source = (0, _localizationProviderRenameLocale.default)(file, api, options);
11
+ return file.source;
12
+ }