@strapi/upgrade 0.0.0-experimental.defd8568ae03ef8d52f86e1f3541979f953c3941 → 0.0.0-experimental.e14656d3b8681880212c13260b9a2b340c182f2d
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 +7 -3
- package/dist/cli.js.map +1 -1
- package/dist/index.js +6 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +6 -2
- package/dist/index.mjs.map +1 -1
- package/dist/modules/project/constants.d.ts.map +1 -1
- package/dist/modules/runner/json/transform.d.ts.map +1 -1
- package/package.json +7 -6
- 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-upgrade-react-and-react-dom.json.ts +67 -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 +68 -5
- package/resources/codemods/5.0.0/useRBAC-hook-import-change.code.ts +21 -0
- package/resources/utils/change-import.ts +96 -0
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import semver from 'semver';
|
|
3
|
+
|
|
4
|
+
import type { modules } from '../../../dist';
|
|
5
|
+
|
|
6
|
+
const REACT_DEP_NAME = 'react';
|
|
7
|
+
const REACT_DEP_PATH = `dependencies.${REACT_DEP_NAME}`;
|
|
8
|
+
|
|
9
|
+
const REACT_DOM_DEP_NAME = 'react-dom';
|
|
10
|
+
const REACT_DOM_DEP_PATH = `dependencies.${REACT_DOM_DEP_NAME}`;
|
|
11
|
+
|
|
12
|
+
const DEP_NEW_VERSION_RANGE = '^18.0.0';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Specifically targets the root package.json and updates the react and react-dom dependency version.
|
|
16
|
+
*
|
|
17
|
+
* We first check if the react and react-dom dependency is listed in the package.json. If the dependency is
|
|
18
|
+
* found, we verify its version.
|
|
19
|
+
*
|
|
20
|
+
* If the detected version does not satisfy the new version range, we replace it with the new one.
|
|
21
|
+
*
|
|
22
|
+
* Conversely, if no react or react-dom dependency is listed, we add it with the new version range.
|
|
23
|
+
*/
|
|
24
|
+
const transform: modules.runner.json.JSONTransform = (file, params) => {
|
|
25
|
+
const { cwd, json } = params;
|
|
26
|
+
|
|
27
|
+
const rootPackageJsonPath = path.join(cwd, 'package.json');
|
|
28
|
+
|
|
29
|
+
if (file.path !== rootPackageJsonPath) {
|
|
30
|
+
return file.json;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const j = json(file.json);
|
|
34
|
+
|
|
35
|
+
if (j.has(REACT_DEP_PATH) && j.has(REACT_DOM_DEP_PATH)) {
|
|
36
|
+
const currentReactVersion = j.get(REACT_DEP_PATH);
|
|
37
|
+
const currentReactDOMVersion = j.get(REACT_DOM_DEP_PATH);
|
|
38
|
+
|
|
39
|
+
// If the current version is not a string, then something is wrong, abort
|
|
40
|
+
if (typeof currentReactVersion !== 'string' || typeof currentReactDOMVersion !== 'string') {
|
|
41
|
+
return j.root();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const currentSatisfiesNew =
|
|
45
|
+
semver.satisfies(currentReactVersion, DEP_NEW_VERSION_RANGE) &&
|
|
46
|
+
semver.satisfies(currentReactDOMVersion, DEP_NEW_VERSION_RANGE);
|
|
47
|
+
|
|
48
|
+
// if the current version satisfies the new range, keep it as is and abort
|
|
49
|
+
if (currentSatisfiesNew) {
|
|
50
|
+
return j.root();
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// else, update the version with the new one
|
|
54
|
+
j.set(REACT_DEP_PATH, DEP_NEW_VERSION_RANGE);
|
|
55
|
+
j.set(REACT_DOM_DEP_PATH, DEP_NEW_VERSION_RANGE);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// If the dependency is not listed yet, add it
|
|
59
|
+
else {
|
|
60
|
+
j.set(REACT_DEP_PATH, DEP_NEW_VERSION_RANGE);
|
|
61
|
+
j.set(REACT_DOM_DEP_PATH, DEP_NEW_VERSION_RANGE);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return j.root();
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export default transform;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import semver from 'semver';
|
|
3
|
+
|
|
4
|
+
import type { modules } from '../../../dist';
|
|
5
|
+
|
|
6
|
+
const DEP_NAME = 'styled-components';
|
|
7
|
+
const DEP_PATH = `dependencies.${DEP_NAME}`;
|
|
8
|
+
|
|
9
|
+
const DEP_NEW_VERSION_RANGE = '^6.0.0';
|
|
10
|
+
|
|
11
|
+
const transform: modules.runner.json.JSONTransform = (file, params) => {
|
|
12
|
+
const { cwd, json } = params;
|
|
13
|
+
|
|
14
|
+
const rootPackageJsonPath = path.join(cwd, 'package.json');
|
|
15
|
+
|
|
16
|
+
if (file.path !== rootPackageJsonPath) {
|
|
17
|
+
return file.json;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const j = json(file.json);
|
|
21
|
+
|
|
22
|
+
if (j.has(DEP_PATH)) {
|
|
23
|
+
const currentVersion = j.get(DEP_PATH);
|
|
24
|
+
|
|
25
|
+
// If the current version is not a string, then something is wrong, abort
|
|
26
|
+
if (typeof currentVersion !== 'string') {
|
|
27
|
+
return j.root();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const currentSatisfiesNew = semver.satisfies(currentVersion, DEP_NEW_VERSION_RANGE);
|
|
31
|
+
|
|
32
|
+
// if the current version satisfies the new range, keep it as is and abort
|
|
33
|
+
if (currentSatisfiesNew) {
|
|
34
|
+
return j.root();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// else, update the version with the new one
|
|
38
|
+
j.set(DEP_PATH, DEP_NEW_VERSION_RANGE);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// If the dependency is not listed yet, add it
|
|
42
|
+
else {
|
|
43
|
+
j.set(DEP_PATH, DEP_NEW_VERSION_RANGE);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return j.root();
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export default transform;
|
|
@@ -142,12 +142,39 @@ const objectParam_10 = [...objectParam_10_2];
|
|
|
142
142
|
|
|
143
143
|
strapi.entityService.findOne(...[...objectParam_10]);
|
|
144
144
|
|
|
145
|
+
Case: find, create, update, delete with entityId as first argument
|
|
146
|
+
|
|
147
|
+
strapi.entityService.findMany(uid, {
|
|
148
|
+
fields: ["id", "name", "description"],
|
|
149
|
+
populate: ["author", "comments"],
|
|
150
|
+
publicationState: "preview",
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
strapi.entityService.create(uid, {
|
|
154
|
+
data: {
|
|
155
|
+
name: "John Doe",
|
|
156
|
+
age: 30,
|
|
157
|
+
},
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
strapi.entityService.update(uid, entityId, {
|
|
161
|
+
data: {
|
|
162
|
+
name: "John Doe",
|
|
163
|
+
age: 30,
|
|
164
|
+
},
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
strapi.entityService.delete(uid, entityId);
|
|
168
|
+
strapi.entityService.findOne(uid, entityId);
|
|
169
|
+
|
|
145
170
|
*/
|
|
146
171
|
|
|
147
|
-
const movedFunctions = ['findOne', '
|
|
172
|
+
const movedFunctions = ['findOne', 'findMany', 'count', 'create', 'update', 'delete'];
|
|
173
|
+
|
|
174
|
+
const functionsWithEntityId = ['findOne', 'update', 'delete'];
|
|
148
175
|
|
|
149
176
|
const transformDeclaration = (path: ASTPath<any>, name: any, j: JSCodeshift) => {
|
|
150
|
-
const declaration =
|
|
177
|
+
const declaration = findClosestDeclaration(path, name, j);
|
|
151
178
|
|
|
152
179
|
if (!declaration) {
|
|
153
180
|
return;
|
|
@@ -222,7 +249,7 @@ const transformObjectParam = (path: ASTPath<any>, expression: ObjectExpression,
|
|
|
222
249
|
break;
|
|
223
250
|
}
|
|
224
251
|
case j.Identifier.check(prop.value): {
|
|
225
|
-
const declaration =
|
|
252
|
+
const declaration = findClosestDeclaration(path, prop.value.name, j);
|
|
226
253
|
|
|
227
254
|
if (!declaration) {
|
|
228
255
|
return;
|
|
@@ -253,7 +280,7 @@ const transformObjectParam = (path: ASTPath<any>, expression: ObjectExpression,
|
|
|
253
280
|
});
|
|
254
281
|
};
|
|
255
282
|
|
|
256
|
-
const
|
|
283
|
+
const findClosestDeclaration = (path: ASTPath<any>, name: string, j) => {
|
|
257
284
|
// find Identifier declaration
|
|
258
285
|
const scope = path.scope.lookup(name);
|
|
259
286
|
|
|
@@ -318,7 +345,7 @@ const transform: Transform = (file, api) => {
|
|
|
318
345
|
case j.Identifier.check(arg.argument): {
|
|
319
346
|
const identifier = arg.argument;
|
|
320
347
|
|
|
321
|
-
const declaration =
|
|
348
|
+
const declaration = findClosestDeclaration(path, identifier.name, j);
|
|
322
349
|
|
|
323
350
|
if (!declaration) {
|
|
324
351
|
return arg;
|
|
@@ -351,6 +378,42 @@ const transform: Transform = (file, api) => {
|
|
|
351
378
|
|
|
352
379
|
const [docUID, ...rest] = resolvedArgs;
|
|
353
380
|
|
|
381
|
+
// function with entityId as first argument
|
|
382
|
+
if (
|
|
383
|
+
j.Identifier.check(path.value.callee.property) &&
|
|
384
|
+
functionsWithEntityId.includes(path.value.callee.property.name)
|
|
385
|
+
) {
|
|
386
|
+
rest.splice(0, 1);
|
|
387
|
+
|
|
388
|
+
// in case no extra params are passed in the function e.g delete(uid, entityId)
|
|
389
|
+
if (rest.length === 0) {
|
|
390
|
+
rest.push(
|
|
391
|
+
j.objectExpression.from({
|
|
392
|
+
properties: [],
|
|
393
|
+
})
|
|
394
|
+
);
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
const params = rest[0];
|
|
398
|
+
|
|
399
|
+
const placeholder = j.objectProperty(j.identifier('documentId'), j.literal('__TODO__'));
|
|
400
|
+
|
|
401
|
+
// add documentId to params with a placeholder
|
|
402
|
+
if (j.ObjectExpression.check(params)) {
|
|
403
|
+
params.properties.unshift(placeholder);
|
|
404
|
+
} else if (j.Identifier.check(params)) {
|
|
405
|
+
const declaration = findClosestDeclaration(path, params.name, j);
|
|
406
|
+
|
|
407
|
+
if (!declaration) {
|
|
408
|
+
return;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
if (j.ObjectExpression.check(declaration.init)) {
|
|
412
|
+
declaration.init.properties.unshift(placeholder);
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
|
|
354
417
|
path.value.arguments.forEach((arg) => {
|
|
355
418
|
transformElement(path, arg, j);
|
|
356
419
|
});
|
|
@@ -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
|
+
methodName: '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,96 @@
|
|
|
1
|
+
import type { ImportDeclaration, JSCodeshift, Collection } from 'jscodeshift';
|
|
2
|
+
|
|
3
|
+
export const changeImportSpecifier = (
|
|
4
|
+
root: Collection,
|
|
5
|
+
j: JSCodeshift,
|
|
6
|
+
options: { methodName: string; oldDependency: string; newDependency: string }
|
|
7
|
+
): void => {
|
|
8
|
+
const { methodName, oldDependency, newDependency } = options;
|
|
9
|
+
|
|
10
|
+
// Flag to check if the method was imported from the old dependency
|
|
11
|
+
let methodImportedFromOldDependency = false;
|
|
12
|
+
const methodAliases: string[] = [];
|
|
13
|
+
|
|
14
|
+
// Remove the method from the old dependency and check if it was imported
|
|
15
|
+
root
|
|
16
|
+
.find(j.ImportDeclaration)
|
|
17
|
+
.filter((path) => path.node.source.value === oldDependency)
|
|
18
|
+
.forEach((path) => {
|
|
19
|
+
const importDeclaration: ImportDeclaration = path.node;
|
|
20
|
+
|
|
21
|
+
// Check if the method is imported from the old dependency
|
|
22
|
+
const methodSpecifiers = importDeclaration.specifiers?.filter(
|
|
23
|
+
(specifier) =>
|
|
24
|
+
specifier.type === 'ImportSpecifier' && specifier.imported.name === methodName
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
if (methodSpecifiers && methodSpecifiers.length > 0) {
|
|
28
|
+
methodImportedFromOldDependency = true;
|
|
29
|
+
|
|
30
|
+
// Collect all aliases for the method
|
|
31
|
+
methodSpecifiers.forEach((specifier) => {
|
|
32
|
+
if (specifier.local && specifier.local.name !== methodName) {
|
|
33
|
+
methodAliases.push(specifier.local.name);
|
|
34
|
+
} else {
|
|
35
|
+
methodAliases.push(methodName);
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
// Remove the method specifiers from the old import
|
|
40
|
+
const updatedSpecifiers = importDeclaration.specifiers?.filter(
|
|
41
|
+
(specifier) =>
|
|
42
|
+
specifier.type !== 'ImportSpecifier' || specifier.imported.name !== methodName
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
if (updatedSpecifiers && updatedSpecifiers.length > 0) {
|
|
46
|
+
// Replace the import with the updated specifiers if there are other imports left
|
|
47
|
+
j(path).replaceWith(j.importDeclaration(updatedSpecifiers, j.literal(oldDependency)));
|
|
48
|
+
} else {
|
|
49
|
+
// Remove the entire import statement if the specified method was the only import
|
|
50
|
+
j(path).remove();
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
// Add new import dependency if the method was imported from the old dependency
|
|
56
|
+
if (methodImportedFromOldDependency) {
|
|
57
|
+
const dependencies = root
|
|
58
|
+
.find(j.ImportDeclaration)
|
|
59
|
+
.filter((path) => path.node.source.value === newDependency);
|
|
60
|
+
|
|
61
|
+
if (dependencies.length > 0) {
|
|
62
|
+
dependencies.forEach((path) => {
|
|
63
|
+
const importDeclaration: ImportDeclaration = path.node;
|
|
64
|
+
|
|
65
|
+
methodAliases.forEach((alias) => {
|
|
66
|
+
const newSpecifier = j.importSpecifier(j.identifier(methodName), j.identifier(alias));
|
|
67
|
+
const specifiersArray = importDeclaration.specifiers || [];
|
|
68
|
+
j(path).replaceWith(
|
|
69
|
+
j.importDeclaration([...specifiersArray, newSpecifier], j.literal(newDependency))
|
|
70
|
+
);
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
} else {
|
|
74
|
+
const newSpecifiers = methodAliases.map((alias) =>
|
|
75
|
+
j.importSpecifier(j.identifier(methodName), j.identifier(alias))
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
const newImportDeclaration = j.importDeclaration(newSpecifiers, j.literal(newDependency));
|
|
79
|
+
|
|
80
|
+
// Find the index of the first non-import declaration
|
|
81
|
+
const body = root.get().node.program.body;
|
|
82
|
+
const lastImportIndex = body.findIndex((node) => node.type !== 'ImportDeclaration');
|
|
83
|
+
|
|
84
|
+
if (lastImportIndex > -1) {
|
|
85
|
+
// Insert the new import declaration just before the first non-import node
|
|
86
|
+
body.splice(lastImportIndex, 0, newImportDeclaration);
|
|
87
|
+
} else {
|
|
88
|
+
// Check if 'use strict' exists at the beginning
|
|
89
|
+
const hasUseStrict =
|
|
90
|
+
body[0]?.type === 'ExpressionStatement' && body[0]?.expression?.value === 'use strict';
|
|
91
|
+
// Add the new import after 'use strict' if it exists, otherwise at the beginning
|
|
92
|
+
body.splice(hasUseStrict ? 1 : 0, 0, newImportDeclaration);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
};
|