@strapi/upgrade 5.0.0-rc.10 → 5.0.0-rc.12

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@strapi/upgrade",
3
- "version": "5.0.0-rc.10",
3
+ "version": "5.0.0-rc.12",
4
4
  "description": "CLI to upgrade Strapi applications effortless",
5
5
  "keywords": [
6
6
  "strapi",
@@ -59,7 +59,7 @@
59
59
  "watch": "pack-up watch"
60
60
  },
61
61
  "dependencies": {
62
- "@strapi/utils": "5.0.0-rc.10",
62
+ "@strapi/utils": "5.0.0-rc.12",
63
63
  "chalk": "4.1.2",
64
64
  "cli-table3": "0.6.2",
65
65
  "commander": "8.3.0",
@@ -76,15 +76,15 @@
76
76
  },
77
77
  "devDependencies": {
78
78
  "@strapi/pack-up": "5.0.0",
79
- "@strapi/types": "5.0.0-rc.10",
79
+ "@strapi/types": "5.0.0-rc.12",
80
80
  "@types/fs-extra": "11.0.4",
81
81
  "@types/jscodeshift": "0.11.10",
82
- "eslint-config-custom": "5.0.0-rc.10",
82
+ "eslint-config-custom": "5.0.0-rc.12",
83
83
  "rimraf": "5.0.5"
84
84
  },
85
85
  "engines": {
86
86
  "node": ">=18.0.0 <=20.x.x",
87
87
  "npm": ">=6.0.0"
88
88
  },
89
- "gitHead": "4f54945deb1266d47424b46aa1462f66e4e32e58"
89
+ "gitHead": "18f223b8357a308e33cd62e07c2173784535bf4e"
90
90
  }
@@ -0,0 +1,21 @@
1
+ import type { Transform } from 'jscodeshift';
2
+ import { changeImportSpecifier } from '../../utils/change-import';
3
+
4
+ /**
5
+ * change useAPIErrorHandler 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: 'useAPIErrorHandler',
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,63 @@
1
+ import { Transform } from 'jscodeshift';
2
+
3
+ /**
4
+ * comments out lifecycles.js/ts files and adds a description for the reason at the top
5
+ */
6
+ const transform: Transform = (file, api) => {
7
+ const j = api.jscodeshift;
8
+ const root = j(file.source);
9
+
10
+ // check if file path follows this pattern `content-types/[content-type-name]/lifecycles`
11
+ if (/content-types\/[^/]+\/lifecycles\.(js|ts)$/.test(file.path)) {
12
+ // Get the entire source code as a string
13
+ const sourceCode = root.toSource();
14
+
15
+ // Split the source code into lines and prepend // to each line
16
+ // we are using line comments instead of block comments so we don't face issues with existing block comments
17
+ const commentedCode = sourceCode
18
+ .split('\n')
19
+ .map((line) => `// ${line}`)
20
+ .join('\n');
21
+
22
+ // Add a header comment at the top to explain why the file is commented out
23
+ const headerComment = `
24
+ /*
25
+ *
26
+ * ============================================================
27
+ * WARNING: THIS FILE HAS BEEN COMMENTED OUT
28
+ * ============================================================
29
+ *
30
+ * CONTEXT:
31
+ *
32
+ * The lifecycles.js file has been commented out to prevent unintended side effects when starting Strapi 5 for the first time after migrating to the document service.
33
+ *
34
+ * STRAPI 5 introduces a new document service that handles lifecycles differently compared to previous versions. Without migrating your lifecycles to document service middlewares, you may experience issues such as:
35
+ *
36
+ * - \`unpublish\` actions triggering \`delete\` lifecycles for every locale with a published entity, which differs from the expected behavior in v4.
37
+ * - \`discardDraft\` actions triggering both \`create\` and \`delete\` lifecycles, leading to potential confusion.
38
+ *
39
+ * MIGRATION GUIDE:
40
+ *
41
+ * For a thorough guide on migrating your lifecycles to document service middlewares, please refer to the following link:
42
+ * [Document Services Middlewares Migration Guide](https://docs.strapi.io/dev-docs/migration/v4-to-v5/breaking-changes/lifecycle-hooks-document-service)
43
+ *
44
+ * IMPORTANT:
45
+ *
46
+ * Simply uncommenting this file without following the migration guide may result in unexpected behavior and inconsistencies. Ensure that you have completed the migration process before re-enabling this file.
47
+ *
48
+ * ============================================================
49
+ */
50
+ `;
51
+
52
+ // Combine the header comment with the commented-out code
53
+ const finalCode = `${headerComment}\n${commentedCode}`;
54
+
55
+ return finalCode;
56
+ }
57
+
58
+ return root.toSource();
59
+ };
60
+
61
+ export const parser = 'tsx';
62
+
63
+ 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
+ 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
+ };