@strapi/upgrade 0.0.0-experimental.e3e48deb89bd0a1b6cc69b698696566fa7854a95 → 0.0.0-experimental.e9122b401c96877b6707775c4f893660eab93ae3
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/LICENSE +19 -4
- package/dist/cli.js +1482 -5
- package/dist/cli.js.map +1 -1
- package/dist/index.js +366 -105
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +367 -106
- package/dist/index.mjs.map +1 -1
- package/dist/modules/codemod/codemod.d.ts +4 -2
- package/dist/modules/codemod/codemod.d.ts.map +1 -1
- package/dist/modules/codemod/types.d.ts +8 -1
- package/dist/modules/codemod/types.d.ts.map +1 -1
- package/dist/modules/codemod-repository/constants.d.ts.map +1 -1
- package/dist/modules/codemod-repository/repository.d.ts +6 -5
- package/dist/modules/codemod-repository/repository.d.ts.map +1 -1
- package/dist/modules/codemod-repository/types.d.ts +7 -3
- package/dist/modules/codemod-repository/types.d.ts.map +1 -1
- package/dist/modules/codemod-runner/codemod-runner.d.ts +3 -0
- package/dist/modules/codemod-runner/codemod-runner.d.ts.map +1 -1
- package/dist/modules/codemod-runner/index.d.ts +1 -0
- package/dist/modules/codemod-runner/index.d.ts.map +1 -1
- package/dist/modules/codemod-runner/types.d.ts +1 -0
- package/dist/modules/codemod-runner/types.d.ts.map +1 -1
- package/dist/modules/format/formats.d.ts +6 -0
- package/dist/modules/format/formats.d.ts.map +1 -1
- package/dist/modules/project/constants.d.ts +6 -3
- package/dist/modules/project/constants.d.ts.map +1 -1
- package/dist/modules/project/index.d.ts +2 -0
- package/dist/modules/project/index.d.ts.map +1 -1
- package/dist/modules/project/project.d.ts +27 -5
- package/dist/modules/project/project.d.ts.map +1 -1
- package/dist/modules/project/types.d.ts +3 -10
- package/dist/modules/project/types.d.ts.map +1 -1
- package/dist/modules/project/utils.d.ts +6 -0
- package/dist/modules/project/utils.d.ts.map +1 -0
- package/dist/modules/report/report.d.ts.map +1 -1
- package/dist/modules/requirement/types.d.ts +2 -2
- package/dist/modules/requirement/types.d.ts.map +1 -1
- package/dist/modules/runner/json/transform.d.ts.map +1 -1
- package/dist/modules/upgrader/upgrader.d.ts +3 -3
- package/dist/modules/upgrader/upgrader.d.ts.map +1 -1
- package/dist/modules/version/range.d.ts +2 -0
- package/dist/modules/version/range.d.ts.map +1 -1
- package/dist/tasks/codemods/index.d.ts +2 -1
- package/dist/tasks/codemods/index.d.ts.map +1 -1
- package/dist/tasks/codemods/list-codemods.d.ts +3 -0
- package/dist/tasks/codemods/list-codemods.d.ts.map +1 -0
- package/dist/tasks/codemods/run-codemods.d.ts +3 -0
- package/dist/tasks/codemods/run-codemods.d.ts.map +1 -0
- package/dist/tasks/codemods/types.d.ts +9 -3
- package/dist/tasks/codemods/types.d.ts.map +1 -1
- package/dist/tasks/codemods/utils.d.ts +6 -0
- package/dist/tasks/codemods/utils.d.ts.map +1 -0
- package/dist/tasks/index.d.ts +1 -1
- package/dist/tasks/index.d.ts.map +1 -1
- package/dist/tasks/upgrade/upgrade.d.ts.map +1 -1
- package/package.json +9 -8
- package/resources/codemods/5.0.0/change-useAPIErrorHandler-import.code.ts +21 -0
- package/resources/codemods/5.0.0/comment-out-lifecycle-files.code.ts +63 -0
- package/resources/codemods/5.0.0/dependency-remove-strapi-plugin-i18n.json.ts +31 -0
- package/resources/codemods/5.0.0/dependency-upgrade-react-and-react-dom.json.ts +67 -0
- package/resources/codemods/5.0.0/dependency-upgrade-react-router-dom.json.ts +59 -0
- package/resources/codemods/5.0.0/dependency-upgrade-styled-components.json.ts +49 -0
- package/resources/codemods/5.0.0/entity-service-document-service.code.ts +437 -0
- package/resources/codemods/5.0.0/nocontent-migrate-to-emptystatelayout.code.ts +30 -0
- package/resources/codemods/5.0.0/s3-keys-wrapped-in-credentials.code.ts +1 -1
- package/resources/codemods/5.0.0/sqlite3-to-better-sqlite3.json.ts +5 -2
- package/resources/codemods/5.0.0/strapi-public-interface.code.ts +126 -0
- package/resources/codemods/5.0.0/use-uid-for-config-namespace.code.ts +1 -1
- package/resources/codemods/5.0.0/useRBAC-hook-import-change.code.ts +21 -0
- package/resources/codemods/5.0.0/utils-public-interface.code.ts +320 -0
- package/resources/examples/console.log-to-console.info.code.ts +1 -1
- package/resources/examples/disable-jsx-buttons.code.ts +42 -0
- package/resources/utils/change-import.ts +105 -0
- package/resources/utils/replace-jsx.ts +49 -0
- package/dist/_chunks/codemod-runner-B5OeSMTQ.js +0 -730
- package/dist/_chunks/codemod-runner-B5OeSMTQ.js.map +0 -1
- package/dist/_chunks/codemods-10ZKewQx.js +0 -108
- package/dist/_chunks/codemods-10ZKewQx.js.map +0 -1
- package/dist/_chunks/index-uxCwtuH1.js +0 -103
- package/dist/_chunks/index-uxCwtuH1.js.map +0 -1
- package/dist/_chunks/upgrade-A4T1OWs5.js +0 -357
- package/dist/_chunks/upgrade-A4T1OWs5.js.map +0 -1
- package/dist/tasks/codemods/codemods.d.ts +0 -3
- package/dist/tasks/codemods/codemods.d.ts.map +0 -1
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { Transform, JSCodeshift, Collection } from 'jscodeshift';
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
This codemod transforms @strapi/strapi imports to use the new public interface.
|
|
5
|
+
|
|
6
|
+
ESM
|
|
7
|
+
Before:
|
|
8
|
+
|
|
9
|
+
import strapi from '@strapi/strapi';
|
|
10
|
+
strapi();
|
|
11
|
+
|
|
12
|
+
After:
|
|
13
|
+
|
|
14
|
+
import { createStrapi } from '@strapi/strapi'; // keeps the default import
|
|
15
|
+
createStrapi();
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
Common JS
|
|
20
|
+
Before:
|
|
21
|
+
|
|
22
|
+
const strapi = require('@strapi/strapi');
|
|
23
|
+
strapi();
|
|
24
|
+
|
|
25
|
+
After:
|
|
26
|
+
|
|
27
|
+
const strapi = require('@strapi/strapi');
|
|
28
|
+
strapi.createStrapi();
|
|
29
|
+
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
const transformStrapiImport = (root: Collection, j: JSCodeshift) => {
|
|
33
|
+
root.find(j.ImportDefaultSpecifier).forEach((path) => {
|
|
34
|
+
if (path.parent.value.source.value === '@strapi/strapi') {
|
|
35
|
+
const newSpecifiers = path.parent.value.specifiers.filter(
|
|
36
|
+
(specifier) => specifier.type !== 'ImportDefaultSpecifier'
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
j(path.parent).replaceWith(
|
|
40
|
+
j.importDeclaration(
|
|
41
|
+
[...newSpecifiers, j.importSpecifier(j.identifier('createStrapi'))],
|
|
42
|
+
j.literal('@strapi/strapi')
|
|
43
|
+
)
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
transformFunctionCalls(path.value.local.name, root, j);
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const transformRequireImport = (root: Collection, j: JSCodeshift) => {
|
|
52
|
+
root
|
|
53
|
+
.find(j.VariableDeclarator, {
|
|
54
|
+
init: {
|
|
55
|
+
callee: {
|
|
56
|
+
name: 'require',
|
|
57
|
+
},
|
|
58
|
+
arguments: [{ value: '@strapi/strapi' }],
|
|
59
|
+
},
|
|
60
|
+
})
|
|
61
|
+
.forEach((path) => {
|
|
62
|
+
if (path.value.id.type === 'Identifier') {
|
|
63
|
+
const identifier = path.value.id.name;
|
|
64
|
+
|
|
65
|
+
root
|
|
66
|
+
.find(j.CallExpression, {
|
|
67
|
+
callee: {
|
|
68
|
+
type: 'Identifier',
|
|
69
|
+
name: identifier,
|
|
70
|
+
},
|
|
71
|
+
})
|
|
72
|
+
.forEach((callExpressionPath) => {
|
|
73
|
+
j(callExpressionPath).replaceWith(
|
|
74
|
+
j.callExpression(
|
|
75
|
+
j.memberExpression(j.identifier(identifier), j.identifier('createStrapi')),
|
|
76
|
+
callExpressionPath.value.arguments
|
|
77
|
+
)
|
|
78
|
+
);
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const transformFunctionCalls = (identifier: string, root: Collection, j: JSCodeshift) => {
|
|
85
|
+
root
|
|
86
|
+
.find(j.CallExpression, {
|
|
87
|
+
callee: {
|
|
88
|
+
type: 'Identifier',
|
|
89
|
+
name: identifier,
|
|
90
|
+
},
|
|
91
|
+
})
|
|
92
|
+
.forEach((path) => {
|
|
93
|
+
// we a type guard again to avoid ts issues
|
|
94
|
+
if (path.value.callee.type === 'Identifier') {
|
|
95
|
+
path.value.callee.name = 'createStrapi';
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Transformations
|
|
102
|
+
*
|
|
103
|
+
* With ESM imports
|
|
104
|
+
*
|
|
105
|
+
* import strapi from '@strapi/strapi'; => import strapi, { createStrapi } from '@strapi/strapi';
|
|
106
|
+
* strapi() => createStrapi()
|
|
107
|
+
*
|
|
108
|
+
* With CJS imports
|
|
109
|
+
*
|
|
110
|
+
* const strapi = require('@strapi/strapi'); => no transform
|
|
111
|
+
* strapi() => strapi.createStrapi()
|
|
112
|
+
*/
|
|
113
|
+
const transform: Transform = (file, api) => {
|
|
114
|
+
const j = api.jscodeshift;
|
|
115
|
+
|
|
116
|
+
const root = j(file.source);
|
|
117
|
+
|
|
118
|
+
transformStrapiImport(root, j);
|
|
119
|
+
transformRequireImport(root, j);
|
|
120
|
+
|
|
121
|
+
return root.toSource();
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
export const parser = 'tsx';
|
|
125
|
+
|
|
126
|
+
export default transform;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Transform } from 'jscodeshift';
|
|
2
|
+
import { changeImportSpecifier } from '../../utils/change-import';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* change useRBAC import from '@strapi/helper-plugin' to '@strapi/strapi/admin'
|
|
6
|
+
*/
|
|
7
|
+
const transform: Transform = (file, api) => {
|
|
8
|
+
const { j } = api;
|
|
9
|
+
|
|
10
|
+
const root = j.withParser('tsx')(file.source);
|
|
11
|
+
|
|
12
|
+
changeImportSpecifier(root, j, {
|
|
13
|
+
oldMethodName: 'useRBAC',
|
|
14
|
+
oldDependency: '@strapi/helper-plugin',
|
|
15
|
+
newDependency: '@strapi/strapi/admin',
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
return root.toSource();
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export default transform;
|
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
import { Transform, JSCodeshift, Collection } from 'jscodeshift';
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
|
|
5
|
+
This codemod transforms @strapi/utils imports to change method calls to match the new public interface.
|
|
6
|
+
It will also warn about removed functions to avoid breaking user code.
|
|
7
|
+
|
|
8
|
+
ESM
|
|
9
|
+
|
|
10
|
+
Before:
|
|
11
|
+
|
|
12
|
+
import * as utils from '@strapi/utils';
|
|
13
|
+
|
|
14
|
+
utils.nameToSlug();
|
|
15
|
+
|
|
16
|
+
After:
|
|
17
|
+
|
|
18
|
+
import { strings } from '@strapi/utils';
|
|
19
|
+
|
|
20
|
+
strings.nameToSlug();
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
ESM
|
|
24
|
+
|
|
25
|
+
Before:
|
|
26
|
+
|
|
27
|
+
import { nameToSlug } from '@strapi/utils';
|
|
28
|
+
|
|
29
|
+
nameToSlug();
|
|
30
|
+
|
|
31
|
+
After:
|
|
32
|
+
|
|
33
|
+
import { strings } from '@strapi/utils';
|
|
34
|
+
|
|
35
|
+
strings.nameToSlug();
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
Common JS
|
|
40
|
+
|
|
41
|
+
Before:
|
|
42
|
+
|
|
43
|
+
const utils = require('@strapi/utils');
|
|
44
|
+
|
|
45
|
+
utils.nameToSlug();
|
|
46
|
+
|
|
47
|
+
After:
|
|
48
|
+
|
|
49
|
+
const { strings } = require('@strapi/utils');
|
|
50
|
+
|
|
51
|
+
strings.nameToSlug();
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
Common JS
|
|
55
|
+
|
|
56
|
+
Before:
|
|
57
|
+
|
|
58
|
+
const { nameToSlug } = require('@strapi/utils');
|
|
59
|
+
|
|
60
|
+
nameToSlug();
|
|
61
|
+
|
|
62
|
+
After:
|
|
63
|
+
|
|
64
|
+
const { strings } = require('@strapi/utils');
|
|
65
|
+
|
|
66
|
+
strings.nameToSlug();
|
|
67
|
+
|
|
68
|
+
*/
|
|
69
|
+
|
|
70
|
+
const changes = {
|
|
71
|
+
strings: {
|
|
72
|
+
nameToSlug: 'nameToSlug',
|
|
73
|
+
nameToCollectionName: 'nameToCollectionName',
|
|
74
|
+
stringEquals: 'isEqual',
|
|
75
|
+
isCamelCase: 'isCamelCase',
|
|
76
|
+
isKebabCase: 'isKebabCase',
|
|
77
|
+
toKebabCase: 'toKebabCase',
|
|
78
|
+
toRegressedEnumValue: 'toRegressedEnumValue',
|
|
79
|
+
startsWithANumber: 'startsWithANumber',
|
|
80
|
+
joinBy: 'joinBy',
|
|
81
|
+
},
|
|
82
|
+
arrays: {
|
|
83
|
+
stringIncludes: 'includesString',
|
|
84
|
+
},
|
|
85
|
+
objects: {
|
|
86
|
+
keysDeep: 'keysDeep',
|
|
87
|
+
},
|
|
88
|
+
dates: {
|
|
89
|
+
generateTimestampCode: 'timestampCode',
|
|
90
|
+
},
|
|
91
|
+
async: {
|
|
92
|
+
pipeAsync: 'pipe',
|
|
93
|
+
mapAsync: 'map',
|
|
94
|
+
reduceAsync: 'reduce',
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
const removed = [
|
|
99
|
+
'getCommonBeginning',
|
|
100
|
+
'templateConfiguration',
|
|
101
|
+
'removeUndefined',
|
|
102
|
+
'getConfigUrls',
|
|
103
|
+
'getAbsoluteAdminUrl',
|
|
104
|
+
'getAbsoluteServerUrl',
|
|
105
|
+
'forEachAsync',
|
|
106
|
+
];
|
|
107
|
+
|
|
108
|
+
const transformImports = (root: Collection, j: JSCodeshift) => {
|
|
109
|
+
root
|
|
110
|
+
.find(j.ImportDeclaration, {
|
|
111
|
+
source: { value: '@strapi/utils' },
|
|
112
|
+
})
|
|
113
|
+
.forEach((path) => {
|
|
114
|
+
if (!j.ImportDeclaration.check(path.value)) {
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
path.value.specifiers.forEach((specifier) => {
|
|
119
|
+
if (!j.ImportSpecifier.check(specifier)) {
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (removed.includes(specifier.imported.name)) {
|
|
124
|
+
console.warn(
|
|
125
|
+
`Function "${specifier.imported.name}" was removed. You will have to remove it from your code.`
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
for (const primitive of Object.keys(changes)) {
|
|
133
|
+
const functions = Object.keys(changes[primitive]);
|
|
134
|
+
|
|
135
|
+
const specifiersToRefactor = path.value.specifiers.filter((specifier) => {
|
|
136
|
+
return j.ImportSpecifier.check(specifier) && functions.includes(specifier.imported.name);
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
if (specifiersToRefactor.length > 0) {
|
|
140
|
+
path.value.specifiers.unshift(j.importSpecifier(j.identifier(primitive)));
|
|
141
|
+
|
|
142
|
+
specifiersToRefactor.forEach((specifier) => {
|
|
143
|
+
const index = path.value.specifiers.indexOf(specifier);
|
|
144
|
+
path.value.specifiers.splice(index, 1);
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
if (path.value.specifiers?.length === 0) {
|
|
150
|
+
j(path).remove();
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
root.find(j.ImportNamespaceSpecifier).forEach((specifierPath) => {
|
|
155
|
+
if (specifierPath.parent.value.source.value === '@strapi/utils') {
|
|
156
|
+
for (const primitive of Object.keys(changes)) {
|
|
157
|
+
const functions = Object.keys(changes[primitive]);
|
|
158
|
+
functions.forEach((funcName) => {
|
|
159
|
+
root
|
|
160
|
+
.find(j.CallExpression, {
|
|
161
|
+
callee: {
|
|
162
|
+
type: 'MemberExpression',
|
|
163
|
+
property: {
|
|
164
|
+
type: 'Identifier',
|
|
165
|
+
name: funcName,
|
|
166
|
+
},
|
|
167
|
+
object: {
|
|
168
|
+
type: 'Identifier',
|
|
169
|
+
name: specifierPath.value.local.name,
|
|
170
|
+
},
|
|
171
|
+
},
|
|
172
|
+
})
|
|
173
|
+
.replaceWith((path) => {
|
|
174
|
+
return j.callExpression(
|
|
175
|
+
j.memberExpression(
|
|
176
|
+
j.memberExpression(
|
|
177
|
+
j.identifier(specifierPath.value.local.name),
|
|
178
|
+
j.identifier(primitive)
|
|
179
|
+
),
|
|
180
|
+
j.identifier(changes[primitive][funcName])
|
|
181
|
+
),
|
|
182
|
+
path.value.arguments
|
|
183
|
+
);
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
root
|
|
191
|
+
.find(j.VariableDeclarator, {
|
|
192
|
+
init: {
|
|
193
|
+
callee: {
|
|
194
|
+
name: 'require',
|
|
195
|
+
},
|
|
196
|
+
arguments: [{ value: '@strapi/utils' }],
|
|
197
|
+
},
|
|
198
|
+
})
|
|
199
|
+
.forEach((path) => {
|
|
200
|
+
// destructured require
|
|
201
|
+
|
|
202
|
+
if (j.ObjectPattern.check(path.value.id)) {
|
|
203
|
+
const properties = path.value.id.properties;
|
|
204
|
+
|
|
205
|
+
properties?.forEach((property) => {
|
|
206
|
+
if (!j.ObjectProperty.check(property) || !j.Identifier.check(property.value)) {
|
|
207
|
+
return false;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
if (removed.includes(property.value.name)) {
|
|
211
|
+
console.warn(
|
|
212
|
+
`Function "${property.value.name}" was removed. You will have to remove it from your code.`
|
|
213
|
+
);
|
|
214
|
+
|
|
215
|
+
return false;
|
|
216
|
+
}
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
for (const primitive of Object.keys(changes)) {
|
|
220
|
+
const functions = Object.keys(changes[primitive]);
|
|
221
|
+
|
|
222
|
+
const propertiesToRefactor = properties?.filter((property) => {
|
|
223
|
+
return (
|
|
224
|
+
j.ObjectProperty.check(property) &&
|
|
225
|
+
j.Identifier.check(property.value) &&
|
|
226
|
+
functions.includes(property.value.name)
|
|
227
|
+
);
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
if (propertiesToRefactor?.length > 0) {
|
|
231
|
+
const identifier = j.identifier(primitive);
|
|
232
|
+
|
|
233
|
+
properties?.unshift(
|
|
234
|
+
j.objectProperty.from({
|
|
235
|
+
key: identifier,
|
|
236
|
+
value: identifier,
|
|
237
|
+
shorthand: true,
|
|
238
|
+
})
|
|
239
|
+
);
|
|
240
|
+
|
|
241
|
+
propertiesToRefactor.forEach((property) => {
|
|
242
|
+
const index = properties?.indexOf(property);
|
|
243
|
+
properties?.splice(index, 1);
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
if (path.value.id.properties?.length === 0) {
|
|
249
|
+
j(path).remove();
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// namespace require
|
|
254
|
+
if (path.value.id.type === 'Identifier') {
|
|
255
|
+
const identifier = path.value.id.name;
|
|
256
|
+
|
|
257
|
+
for (const primitive of Object.keys(changes)) {
|
|
258
|
+
const functions = Object.keys(changes[primitive]);
|
|
259
|
+
functions.forEach((funcName) => {
|
|
260
|
+
root
|
|
261
|
+
.find(j.CallExpression, {
|
|
262
|
+
callee: {
|
|
263
|
+
type: 'MemberExpression',
|
|
264
|
+
property: {
|
|
265
|
+
type: 'Identifier',
|
|
266
|
+
name: funcName,
|
|
267
|
+
},
|
|
268
|
+
object: {
|
|
269
|
+
type: 'Identifier',
|
|
270
|
+
name: identifier,
|
|
271
|
+
},
|
|
272
|
+
},
|
|
273
|
+
})
|
|
274
|
+
.replaceWith((path) => {
|
|
275
|
+
return j.callExpression(
|
|
276
|
+
j.memberExpression(
|
|
277
|
+
j.memberExpression(j.identifier(identifier), j.identifier(primitive)),
|
|
278
|
+
j.identifier(changes[primitive][funcName])
|
|
279
|
+
),
|
|
280
|
+
path.value.arguments
|
|
281
|
+
);
|
|
282
|
+
});
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
for (const primitive of Object.keys(changes)) {
|
|
289
|
+
const functions = Object.keys(changes[primitive]);
|
|
290
|
+
functions.forEach((funcName) => {
|
|
291
|
+
root
|
|
292
|
+
.find(j.CallExpression, {
|
|
293
|
+
callee: {
|
|
294
|
+
type: 'Identifier',
|
|
295
|
+
name: funcName,
|
|
296
|
+
},
|
|
297
|
+
})
|
|
298
|
+
.replaceWith((path) => {
|
|
299
|
+
if (j.Identifier.check(path.value.callee)) {
|
|
300
|
+
path.value.callee.name = changes[primitive][funcName];
|
|
301
|
+
return j.memberExpression(j.identifier(primitive), path.value);
|
|
302
|
+
}
|
|
303
|
+
});
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
};
|
|
307
|
+
|
|
308
|
+
const transform: Transform = (file, api) => {
|
|
309
|
+
const j = api.jscodeshift;
|
|
310
|
+
|
|
311
|
+
const root = j(file.source);
|
|
312
|
+
|
|
313
|
+
transformImports(root, j);
|
|
314
|
+
|
|
315
|
+
return root.toSource();
|
|
316
|
+
};
|
|
317
|
+
|
|
318
|
+
export const parser = 'tsx';
|
|
319
|
+
|
|
320
|
+
export default transform;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { Transform } from 'jscodeshift';
|
|
2
|
+
import { relative } from 'node:path';
|
|
3
|
+
|
|
4
|
+
const transform: Transform = (file, api) => {
|
|
5
|
+
const j = api.jscodeshift;
|
|
6
|
+
const root = j.withParser('JSX')(file.source);
|
|
7
|
+
|
|
8
|
+
const isReactFile = file.path.endsWith('.jsx') || file.path.endsWith('.tsx');
|
|
9
|
+
|
|
10
|
+
if (!isReactFile) {
|
|
11
|
+
return root.toSource();
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const fileName = relative(process.cwd(), file.path);
|
|
15
|
+
|
|
16
|
+
console.log(`Found React file: ${fileName}`);
|
|
17
|
+
|
|
18
|
+
const buttons = root.findJSXElements('Button');
|
|
19
|
+
|
|
20
|
+
console.log(`Found ${buttons.length} buttons in ${fileName}`);
|
|
21
|
+
|
|
22
|
+
buttons.forEach((button) => {
|
|
23
|
+
const { openingElement } = button.node;
|
|
24
|
+
const isDisabled = openingElement.attributes.some(
|
|
25
|
+
(attribute) => j.JSXAttribute.check(attribute) && attribute.name.name === 'disabled'
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
console.log(`Is disabled? ${isDisabled}`);
|
|
29
|
+
|
|
30
|
+
if (!isDisabled) {
|
|
31
|
+
openingElement.attributes.push(
|
|
32
|
+
j.jsxAttribute(j.jsxIdentifier('disabled'), j.jsxExpressionContainer(j.literal(true)))
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
console.log('Added the disabled attribute');
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
return root.toSource();
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export default transform;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import type { ImportDeclaration, JSCodeshift, Collection } from 'jscodeshift';
|
|
2
|
+
|
|
3
|
+
export const changeImportSpecifier = (
|
|
4
|
+
root: Collection,
|
|
5
|
+
j: JSCodeshift,
|
|
6
|
+
options: {
|
|
7
|
+
oldDependency: string;
|
|
8
|
+
newDependency: string;
|
|
9
|
+
oldMethodName: string;
|
|
10
|
+
newMethodName?: string;
|
|
11
|
+
}
|
|
12
|
+
): void => {
|
|
13
|
+
const { oldMethodName, newMethodName, oldDependency, newDependency } = options;
|
|
14
|
+
const methodNameToReplace = newMethodName ?? oldMethodName;
|
|
15
|
+
|
|
16
|
+
// Flag to check if the method was imported from the old dependency
|
|
17
|
+
let methodImportedFromOldDependency = false;
|
|
18
|
+
const methodAliases: string[] = [];
|
|
19
|
+
|
|
20
|
+
// Remove the method from the old dependency and check if it was imported
|
|
21
|
+
root
|
|
22
|
+
.find(j.ImportDeclaration)
|
|
23
|
+
.filter((path) => path.node.source.value === oldDependency)
|
|
24
|
+
.forEach((path) => {
|
|
25
|
+
const importDeclaration: ImportDeclaration = path.node;
|
|
26
|
+
|
|
27
|
+
// Check if the method is imported from the old dependency
|
|
28
|
+
const methodSpecifiers = importDeclaration.specifiers?.filter(
|
|
29
|
+
(specifier) =>
|
|
30
|
+
specifier.type === 'ImportSpecifier' && specifier.imported.name === oldMethodName
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
if (methodSpecifiers && methodSpecifiers.length > 0) {
|
|
34
|
+
methodImportedFromOldDependency = true;
|
|
35
|
+
|
|
36
|
+
// Collect all aliases for the method
|
|
37
|
+
methodSpecifiers.forEach((specifier) => {
|
|
38
|
+
if (specifier.local && specifier.local.name !== oldMethodName) {
|
|
39
|
+
methodAliases.push(specifier.local.name);
|
|
40
|
+
} else {
|
|
41
|
+
methodAliases.push(methodNameToReplace);
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
// Remove the method specifiers from the old import
|
|
46
|
+
const updatedSpecifiers = importDeclaration.specifiers?.filter(
|
|
47
|
+
(specifier) =>
|
|
48
|
+
specifier.type !== 'ImportSpecifier' || specifier.imported.name !== oldMethodName
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
if (updatedSpecifiers && updatedSpecifiers.length > 0) {
|
|
52
|
+
// Replace the import with the updated specifiers if there are other imports left
|
|
53
|
+
j(path).replaceWith(j.importDeclaration(updatedSpecifiers, j.literal(oldDependency)));
|
|
54
|
+
} else {
|
|
55
|
+
// Remove the entire import statement if the specified method was the only import
|
|
56
|
+
j(path).remove();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
// Add new import dependency if the method was imported from the old dependency
|
|
62
|
+
if (methodImportedFromOldDependency) {
|
|
63
|
+
const dependencies = root
|
|
64
|
+
.find(j.ImportDeclaration)
|
|
65
|
+
.filter((path) => path.node.source.value === newDependency);
|
|
66
|
+
|
|
67
|
+
if (dependencies.length > 0) {
|
|
68
|
+
dependencies.forEach((path) => {
|
|
69
|
+
const importDeclaration: ImportDeclaration = path.node;
|
|
70
|
+
|
|
71
|
+
methodAliases.forEach((alias) => {
|
|
72
|
+
const newSpecifier = j.importSpecifier(
|
|
73
|
+
j.identifier(methodNameToReplace),
|
|
74
|
+
j.identifier(alias)
|
|
75
|
+
);
|
|
76
|
+
const specifiersArray = importDeclaration.specifiers || [];
|
|
77
|
+
j(path).replaceWith(
|
|
78
|
+
j.importDeclaration([...specifiersArray, newSpecifier], j.literal(newDependency))
|
|
79
|
+
);
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
} else {
|
|
83
|
+
const newSpecifiers = methodAliases.map((alias) =>
|
|
84
|
+
j.importSpecifier(j.identifier(methodNameToReplace), j.identifier(alias))
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
const newImportDeclaration = j.importDeclaration(newSpecifiers, j.literal(newDependency));
|
|
88
|
+
|
|
89
|
+
// Find the index of the first non-import declaration
|
|
90
|
+
const body = root.get().node.program.body;
|
|
91
|
+
const lastImportIndex = body.findIndex((node) => node.type !== 'ImportDeclaration');
|
|
92
|
+
|
|
93
|
+
if (lastImportIndex > -1) {
|
|
94
|
+
// Insert the new import declaration just before the first non-import node
|
|
95
|
+
body.splice(lastImportIndex, 0, newImportDeclaration);
|
|
96
|
+
} else {
|
|
97
|
+
// Check if 'use strict' exists at the beginning
|
|
98
|
+
const hasUseStrict =
|
|
99
|
+
body[0]?.type === 'ExpressionStatement' && body[0]?.expression?.value === 'use strict';
|
|
100
|
+
// Add the new import after 'use strict' if it exists, otherwise at the beginning
|
|
101
|
+
body.splice(hasUseStrict ? 1 : 0, 0, newImportDeclaration);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { JSCodeshift, Collection } from 'jscodeshift';
|
|
2
|
+
|
|
3
|
+
export const replaceJSXElement = (
|
|
4
|
+
root: Collection,
|
|
5
|
+
j: JSCodeshift,
|
|
6
|
+
{
|
|
7
|
+
oldElementName,
|
|
8
|
+
newElementName,
|
|
9
|
+
oldDependency,
|
|
10
|
+
}: {
|
|
11
|
+
oldElementName: string;
|
|
12
|
+
newElementName: string;
|
|
13
|
+
oldDependency: string;
|
|
14
|
+
}
|
|
15
|
+
) => {
|
|
16
|
+
// Find the import declaration for the old dependency
|
|
17
|
+
const importDeclaration = root.find(j.ImportDeclaration, {
|
|
18
|
+
source: { value: oldDependency },
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
if (importDeclaration.size() === 0) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Get the local name of the imported element
|
|
26
|
+
const localName = importDeclaration
|
|
27
|
+
.find(j.ImportSpecifier, {
|
|
28
|
+
imported: { name: oldElementName },
|
|
29
|
+
})
|
|
30
|
+
.nodes()[0]?.local?.name;
|
|
31
|
+
|
|
32
|
+
if (!localName) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Replace JSX elements
|
|
37
|
+
root.findJSXElements(localName).forEach((path) => {
|
|
38
|
+
const openingElement = path.node.openingElement;
|
|
39
|
+
const closingElement = path.node.closingElement;
|
|
40
|
+
|
|
41
|
+
if (j.JSXIdentifier.check(openingElement.name)) {
|
|
42
|
+
openingElement.name.name = newElementName;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (closingElement && j.JSXIdentifier.check(closingElement.name)) {
|
|
46
|
+
closingElement.name.name = newElementName;
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
};
|