@strapi/upgrade 0.0.0-experimental.e3e48deb89bd0a1b6cc69b698696566fa7854a95 → 0.0.0-experimental.e8d8fc824d0f6a695b2a9ebaa4680ed21c3645ca
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/README.md +1 -1
- package/dist/cli.js +1578 -5
- package/dist/cli.js.map +1 -1
- package/dist/index.js +739 -387
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +735 -384
- 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/error/utils.d.ts +8 -0
- package/dist/modules/error/utils.d.ts.map +1 -1
- package/dist/modules/file-scanner/scanner.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/types.d.ts +6 -0
- package/dist/modules/upgrader/types.d.ts.map +1 -1
- package/dist/modules/upgrader/upgrader.d.ts +7 -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/modules/version/types.d.ts +2 -1
- package/dist/modules/version/types.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/prompts/index.d.ts +2 -0
- package/dist/tasks/upgrade/prompts/index.d.ts.map +1 -0
- package/dist/tasks/upgrade/prompts/latest.d.ts +9 -0
- package/dist/tasks/upgrade/prompts/latest.d.ts.map +1 -0
- package/dist/tasks/upgrade/requirements/major.d.ts.map +1 -1
- package/dist/tasks/upgrade/upgrade.d.ts.map +1 -1
- package/package.json +11 -10
- 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/deprecate-helper-plugin.code.ts +192 -0
- package/resources/codemods/5.0.0/entity-service-document-service.code.ts +437 -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 -3
- 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/utils-public-interface.code.ts +320 -0
- package/resources/codemods/5.1.0/dependency-better-sqlite3.json.ts +48 -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 +118 -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
package/dist/index.js
CHANGED
|
@@ -1,138 +1,26 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const path$1 = require("node:path");
|
|
4
|
-
const
|
|
4
|
+
const CliTable3 = require("cli-table3");
|
|
5
5
|
const chalk = require("chalk");
|
|
6
|
+
const assert = require("node:assert");
|
|
6
7
|
const semver = require("semver");
|
|
7
|
-
const utils = require("@strapi/utils");
|
|
8
|
-
const fp = require("lodash/fp");
|
|
9
8
|
const fse = require("fs-extra");
|
|
10
|
-
const
|
|
11
|
-
const glob = require("glob");
|
|
9
|
+
const fastglob = require("fast-glob");
|
|
12
10
|
const Runner = require("jscodeshift/src/Runner");
|
|
11
|
+
const fp = require("lodash/fp");
|
|
13
12
|
const node = require("esbuild-register/dist/node");
|
|
14
|
-
const
|
|
13
|
+
const utils = require("@strapi/utils");
|
|
14
|
+
const simpleGit = require("simple-git");
|
|
15
15
|
const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
|
|
16
16
|
const path__default = /* @__PURE__ */ _interopDefault(path$1);
|
|
17
|
-
const
|
|
17
|
+
const CliTable3__default = /* @__PURE__ */ _interopDefault(CliTable3);
|
|
18
18
|
const chalk__default = /* @__PURE__ */ _interopDefault(chalk);
|
|
19
|
+
const assert__default = /* @__PURE__ */ _interopDefault(assert);
|
|
19
20
|
const semver__default = /* @__PURE__ */ _interopDefault(semver);
|
|
20
21
|
const fse__default = /* @__PURE__ */ _interopDefault(fse);
|
|
21
|
-
const
|
|
22
|
-
const
|
|
23
|
-
class Requirement {
|
|
24
|
-
isRequired;
|
|
25
|
-
name;
|
|
26
|
-
testCallback;
|
|
27
|
-
children;
|
|
28
|
-
constructor(name, testCallback, isRequired) {
|
|
29
|
-
this.name = name;
|
|
30
|
-
this.testCallback = testCallback;
|
|
31
|
-
this.isRequired = isRequired ?? true;
|
|
32
|
-
this.children = [];
|
|
33
|
-
}
|
|
34
|
-
setChildren(children) {
|
|
35
|
-
this.children = children;
|
|
36
|
-
return this;
|
|
37
|
-
}
|
|
38
|
-
addChild(child) {
|
|
39
|
-
this.children.push(child);
|
|
40
|
-
return this;
|
|
41
|
-
}
|
|
42
|
-
asOptional() {
|
|
43
|
-
const newInstance = requirementFactory(this.name, this.testCallback, false);
|
|
44
|
-
newInstance.setChildren(this.children);
|
|
45
|
-
return newInstance;
|
|
46
|
-
}
|
|
47
|
-
asRequired() {
|
|
48
|
-
const newInstance = requirementFactory(this.name, this.testCallback, true);
|
|
49
|
-
newInstance.setChildren(this.children);
|
|
50
|
-
return newInstance;
|
|
51
|
-
}
|
|
52
|
-
async test(context) {
|
|
53
|
-
try {
|
|
54
|
-
await this.testCallback?.(context);
|
|
55
|
-
return ok();
|
|
56
|
-
} catch (e) {
|
|
57
|
-
if (e instanceof Error) {
|
|
58
|
-
return errored(e);
|
|
59
|
-
}
|
|
60
|
-
if (typeof e === "string") {
|
|
61
|
-
return errored(new Error(e));
|
|
62
|
-
}
|
|
63
|
-
return errored(new Error("Unknown error"));
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
const ok = () => ({ pass: true, error: null });
|
|
68
|
-
const errored = (error) => ({ pass: false, error });
|
|
69
|
-
const requirementFactory = (name, testCallback, isRequired) => new Requirement(name, testCallback, isRequired);
|
|
70
|
-
const index$g = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
71
|
-
__proto__: null,
|
|
72
|
-
requirementFactory
|
|
73
|
-
}, Symbol.toStringTag, { value: "Module" }));
|
|
74
|
-
const REQUIRE_AVAILABLE_NEXT_MAJOR = requirementFactory(
|
|
75
|
-
"REQUIRE_AVAILABLE_NEXT_MAJOR",
|
|
76
|
-
(context) => {
|
|
77
|
-
const { project, target } = context;
|
|
78
|
-
const currentMajor = project.strapiVersion.major;
|
|
79
|
-
const targetedMajor = target.major;
|
|
80
|
-
if (targetedMajor === currentMajor) {
|
|
81
|
-
throw new Error(`You're already on the latest major version (v${currentMajor})`);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
);
|
|
85
|
-
const REQUIRE_LATEST_FOR_CURRENT_MAJOR = requirementFactory(
|
|
86
|
-
"REQUIRE_LATEST_FOR_CURRENT_MAJOR",
|
|
87
|
-
(context) => {
|
|
88
|
-
const { project, target, npmVersionsMatches } = context;
|
|
89
|
-
if (npmVersionsMatches.length !== 1) {
|
|
90
|
-
const invalidVersions = npmVersionsMatches.slice(0, -1);
|
|
91
|
-
const invalidVersionsAsSemVer = invalidVersions.map((v) => v.version);
|
|
92
|
-
const nbInvalidVersions = npmVersionsMatches.length;
|
|
93
|
-
const currentMajor = project.strapiVersion.major;
|
|
94
|
-
throw new Error(
|
|
95
|
-
`Doing a major upgrade requires to be on the latest v${currentMajor} version, but found ${nbInvalidVersions} versions between the current one and ${target}: ${invalidVersionsAsSemVer}`
|
|
96
|
-
);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
);
|
|
100
|
-
const REQUIRE_GIT_CLEAN_REPOSITORY = requirementFactory(
|
|
101
|
-
"REQUIRE_GIT_CLEAN_REPOSITORY",
|
|
102
|
-
async (context) => {
|
|
103
|
-
const git = simpleGit__default.default({ baseDir: context.project.cwd });
|
|
104
|
-
const status = await git.status();
|
|
105
|
-
if (!status.isClean()) {
|
|
106
|
-
throw new Error(
|
|
107
|
-
"Repository is not clean. Please commit or stash any changes before upgrading"
|
|
108
|
-
);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
);
|
|
112
|
-
const REQUIRE_GIT_REPOSITORY = requirementFactory(
|
|
113
|
-
"REQUIRE_GIT_REPOSITORY",
|
|
114
|
-
async (context) => {
|
|
115
|
-
const git = simpleGit__default.default({ baseDir: context.project.cwd });
|
|
116
|
-
const isRepo = await git.checkIsRepo();
|
|
117
|
-
if (!isRepo) {
|
|
118
|
-
throw new Error("Not a git repository (or any of the parent directories)");
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
).addChild(REQUIRE_GIT_CLEAN_REPOSITORY.asOptional());
|
|
122
|
-
const REQUIRE_GIT_INSTALLED = requirementFactory(
|
|
123
|
-
"REQUIRE_GIT_INSTALLED",
|
|
124
|
-
async (context) => {
|
|
125
|
-
const git = simpleGit__default.default({ baseDir: context.project.cwd });
|
|
126
|
-
try {
|
|
127
|
-
await git.version();
|
|
128
|
-
} catch {
|
|
129
|
-
throw new Error("Git is not installed");
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
).addChild(REQUIRE_GIT_REPOSITORY.asOptional());
|
|
133
|
-
const REQUIRE_GIT = requirementFactory("REQUIRE_GIT", null).addChild(
|
|
134
|
-
REQUIRE_GIT_INSTALLED.asOptional()
|
|
135
|
-
);
|
|
22
|
+
const fastglob__default = /* @__PURE__ */ _interopDefault(fastglob);
|
|
23
|
+
const simpleGit__default = /* @__PURE__ */ _interopDefault(simpleGit);
|
|
136
24
|
class Timer {
|
|
137
25
|
interval;
|
|
138
26
|
constructor() {
|
|
@@ -163,55 +51,101 @@ const constants$4 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineP
|
|
|
163
51
|
__proto__: null,
|
|
164
52
|
ONE_SECOND_MS
|
|
165
53
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
166
|
-
const index$
|
|
54
|
+
const index$g = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
167
55
|
__proto__: null,
|
|
168
56
|
constants: constants$4,
|
|
169
57
|
timerFactory
|
|
170
58
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
this.json = fp.cloneDeep(json);
|
|
175
|
-
}
|
|
176
|
-
get(path2, defaultValue) {
|
|
177
|
-
if (!path2) {
|
|
178
|
-
return this.root();
|
|
179
|
-
}
|
|
180
|
-
return fp.cloneDeep(fp.get(path2, this.json) ?? defaultValue);
|
|
181
|
-
}
|
|
182
|
-
has(path2) {
|
|
183
|
-
return fp.has(path2, this.json);
|
|
184
|
-
}
|
|
185
|
-
merge(other) {
|
|
186
|
-
this.json = fp.merge(other, this.json);
|
|
187
|
-
return this;
|
|
188
|
-
}
|
|
189
|
-
root() {
|
|
190
|
-
return fp.cloneDeep(this.json);
|
|
191
|
-
}
|
|
192
|
-
set(path2, value) {
|
|
193
|
-
this.json = fp.set(path2, value, this.json);
|
|
194
|
-
return this;
|
|
195
|
-
}
|
|
196
|
-
remove(path2) {
|
|
197
|
-
this.json = fp.omit(path2, this.json);
|
|
198
|
-
return this;
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
const createJSONTransformAPI = (object) => new JSONTransformAPI(object);
|
|
202
|
-
const readJSON = async (path2) => {
|
|
203
|
-
const buffer = await fse__default.default.readFile(path2);
|
|
204
|
-
return JSON.parse(buffer.toString());
|
|
59
|
+
const path = (path2) => chalk__default.default.blue(path2);
|
|
60
|
+
const version = (version2) => {
|
|
61
|
+
return chalk__default.default.italic.yellow(`v${version2}`);
|
|
205
62
|
};
|
|
206
|
-
const
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
63
|
+
const codemodUID = (uid) => {
|
|
64
|
+
return chalk__default.default.bold.cyan(uid);
|
|
65
|
+
};
|
|
66
|
+
const projectDetails = (project) => {
|
|
67
|
+
return `Project: TYPE=${projectType(project.type)}; CWD=${path(project.cwd)}; PATHS=${project.paths.map(path)}`;
|
|
68
|
+
};
|
|
69
|
+
const projectType = (type) => chalk__default.default.cyan(type);
|
|
70
|
+
const versionRange = (range) => chalk__default.default.italic.yellow(range.raw);
|
|
71
|
+
const transform = (transformFilePath) => chalk__default.default.cyan(transformFilePath);
|
|
72
|
+
const highlight = (arg) => chalk__default.default.bold.underline(arg);
|
|
73
|
+
const upgradeStep = (text, step) => {
|
|
74
|
+
return chalk__default.default.bold(`(${step[0]}/${step[1]}) ${text}...`);
|
|
75
|
+
};
|
|
76
|
+
const reports = (reports2) => {
|
|
77
|
+
const rows = reports2.map(({ codemod, report }, i) => {
|
|
78
|
+
const fIndex = chalk__default.default.grey(i);
|
|
79
|
+
const fVersion = chalk__default.default.magenta(codemod.version);
|
|
80
|
+
const fKind = chalk__default.default.yellow(codemod.kind);
|
|
81
|
+
const fFormattedTransformPath = chalk__default.default.cyan(codemod.format());
|
|
82
|
+
const fTimeElapsed = i === 0 ? `${report.timeElapsed}s ${chalk__default.default.dim.italic("(cold start)")}` : `${report.timeElapsed}s`;
|
|
83
|
+
const fAffected = report.ok > 0 ? chalk__default.default.green(report.ok) : chalk__default.default.grey(0);
|
|
84
|
+
const fUnchanged = report.ok === 0 ? chalk__default.default.red(report.nochange) : chalk__default.default.grey(report.nochange);
|
|
85
|
+
return [fIndex, fVersion, fKind, fFormattedTransformPath, fAffected, fUnchanged, fTimeElapsed];
|
|
86
|
+
});
|
|
87
|
+
const table = new CliTable3__default.default({
|
|
88
|
+
style: { compact: true },
|
|
89
|
+
head: [
|
|
90
|
+
chalk__default.default.bold.grey("N°"),
|
|
91
|
+
chalk__default.default.bold.magenta("Version"),
|
|
92
|
+
chalk__default.default.bold.yellow("Kind"),
|
|
93
|
+
chalk__default.default.bold.cyan("Name"),
|
|
94
|
+
chalk__default.default.bold.green("Affected"),
|
|
95
|
+
chalk__default.default.bold.red("Unchanged"),
|
|
96
|
+
chalk__default.default.bold.blue("Duration")
|
|
97
|
+
]
|
|
98
|
+
});
|
|
99
|
+
table.push(...rows);
|
|
100
|
+
return table.toString();
|
|
101
|
+
};
|
|
102
|
+
const codemodList = (codemods) => {
|
|
103
|
+
const rows = codemods.map((codemod, index2) => {
|
|
104
|
+
const fIndex = chalk__default.default.grey(index2);
|
|
105
|
+
const fVersion = chalk__default.default.magenta(codemod.version);
|
|
106
|
+
const fKind = chalk__default.default.yellow(codemod.kind);
|
|
107
|
+
const fName = chalk__default.default.blue(codemod.format());
|
|
108
|
+
const fUID = codemodUID(codemod.uid);
|
|
109
|
+
return [fIndex, fVersion, fKind, fName, fUID];
|
|
110
|
+
});
|
|
111
|
+
const table = new CliTable3__default.default({
|
|
112
|
+
style: { compact: true },
|
|
113
|
+
head: [
|
|
114
|
+
chalk__default.default.bold.grey("N°"),
|
|
115
|
+
chalk__default.default.bold.magenta("Version"),
|
|
116
|
+
chalk__default.default.bold.yellow("Kind"),
|
|
117
|
+
chalk__default.default.bold.blue("Name"),
|
|
118
|
+
chalk__default.default.bold.cyan("UID")
|
|
119
|
+
]
|
|
120
|
+
});
|
|
121
|
+
table.push(...rows);
|
|
122
|
+
return table.toString();
|
|
123
|
+
};
|
|
124
|
+
const durationMs = (elapsedMs) => {
|
|
125
|
+
const elapsedSeconds = (elapsedMs / ONE_SECOND_MS).toFixed(3);
|
|
126
|
+
return `${elapsedSeconds}s`;
|
|
210
127
|
};
|
|
128
|
+
const index$f = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
129
|
+
__proto__: null,
|
|
130
|
+
codemodList,
|
|
131
|
+
codemodUID,
|
|
132
|
+
durationMs,
|
|
133
|
+
highlight,
|
|
134
|
+
path,
|
|
135
|
+
projectDetails,
|
|
136
|
+
projectType,
|
|
137
|
+
reports,
|
|
138
|
+
transform,
|
|
139
|
+
upgradeStep,
|
|
140
|
+
version,
|
|
141
|
+
versionRange
|
|
142
|
+
}, Symbol.toStringTag, { value: "Module" }));
|
|
143
|
+
const NPM_REGISTRY_URL = "https://registry.npmjs.org";
|
|
211
144
|
var ReleaseType = /* @__PURE__ */ ((ReleaseType2) => {
|
|
212
145
|
ReleaseType2["Major"] = "major";
|
|
213
146
|
ReleaseType2["Minor"] = "minor";
|
|
214
147
|
ReleaseType2["Patch"] = "patch";
|
|
148
|
+
ReleaseType2["Latest"] = "latest";
|
|
215
149
|
return ReleaseType2;
|
|
216
150
|
})(ReleaseType || {});
|
|
217
151
|
const types = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
@@ -237,17 +171,20 @@ const rangeFactory = (range) => {
|
|
|
237
171
|
};
|
|
238
172
|
const rangeFromReleaseType = (current, identifier) => {
|
|
239
173
|
switch (identifier) {
|
|
240
|
-
case ReleaseType.
|
|
241
|
-
|
|
242
|
-
return rangeFactory(`>${current.raw} <=${nextMajor}`);
|
|
174
|
+
case ReleaseType.Latest: {
|
|
175
|
+
return rangeFactory(`>${current.raw}`);
|
|
243
176
|
}
|
|
244
|
-
case ReleaseType.
|
|
245
|
-
const
|
|
246
|
-
return rangeFactory(`>${current.raw}
|
|
177
|
+
case ReleaseType.Major: {
|
|
178
|
+
const nextMajor = semVerFactory(current.raw).inc("major");
|
|
179
|
+
return rangeFactory(`>${current.raw} <=${nextMajor.major}`);
|
|
247
180
|
}
|
|
248
181
|
case ReleaseType.Minor: {
|
|
249
|
-
const
|
|
250
|
-
return rangeFactory(`>${current.raw} <${
|
|
182
|
+
const nextMajor = semVerFactory(current.raw).inc("major");
|
|
183
|
+
return rangeFactory(`>${current.raw} <${nextMajor.raw}`);
|
|
184
|
+
}
|
|
185
|
+
case ReleaseType.Patch: {
|
|
186
|
+
const nextMinor = semVerFactory(current.raw).inc("minor");
|
|
187
|
+
return rangeFactory(`>${current.raw} <${nextMinor.raw}`);
|
|
251
188
|
}
|
|
252
189
|
default: {
|
|
253
190
|
throw new Error("Not implemented");
|
|
@@ -263,25 +200,75 @@ const rangeFromVersions = (currentVersion, target) => {
|
|
|
263
200
|
}
|
|
264
201
|
throw new Error(`Invalid target set: ${target}`);
|
|
265
202
|
};
|
|
203
|
+
const isValidStringifiedRange = (str) => semver__default.default.validRange(str) !== null;
|
|
204
|
+
const isRangeInstance = (range) => {
|
|
205
|
+
return range instanceof semver__default.default.Range;
|
|
206
|
+
};
|
|
266
207
|
const index$e = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
267
208
|
__proto__: null,
|
|
268
209
|
Version: types,
|
|
269
210
|
isLiteralSemVer,
|
|
211
|
+
isRangeInstance,
|
|
270
212
|
isSemVerReleaseType,
|
|
271
213
|
isSemverInstance,
|
|
272
214
|
isValidSemVer,
|
|
215
|
+
isValidStringifiedRange,
|
|
273
216
|
rangeFactory,
|
|
274
217
|
rangeFromReleaseType,
|
|
275
218
|
rangeFromVersions,
|
|
276
219
|
semVerFactory
|
|
277
220
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
221
|
+
class Package {
|
|
222
|
+
name;
|
|
223
|
+
packageURL;
|
|
224
|
+
npmPackage;
|
|
225
|
+
constructor(name) {
|
|
226
|
+
this.name = name;
|
|
227
|
+
this.packageURL = `${NPM_REGISTRY_URL}/${name}`;
|
|
228
|
+
this.npmPackage = null;
|
|
229
|
+
}
|
|
230
|
+
get isLoaded() {
|
|
231
|
+
return this.npmPackage !== null;
|
|
232
|
+
}
|
|
233
|
+
assertPackageIsLoaded(npmPackage) {
|
|
234
|
+
assert__default.default(this.isLoaded, "The package is not loaded yet");
|
|
235
|
+
}
|
|
236
|
+
getVersionsDict() {
|
|
237
|
+
this.assertPackageIsLoaded(this.npmPackage);
|
|
238
|
+
return this.npmPackage.versions;
|
|
239
|
+
}
|
|
240
|
+
getVersionsAsList() {
|
|
241
|
+
this.assertPackageIsLoaded(this.npmPackage);
|
|
242
|
+
return Object.values(this.npmPackage.versions);
|
|
243
|
+
}
|
|
244
|
+
findVersionsInRange(range) {
|
|
245
|
+
const versions = this.getVersionsAsList();
|
|
246
|
+
return versions.filter((v) => range.test(v.version)).filter((v) => isLiteralSemVer(v.version)).sort((v1, v2) => semver__default.default.compare(v1.version, v2.version));
|
|
247
|
+
}
|
|
248
|
+
findVersion(version2) {
|
|
249
|
+
const versions = this.getVersionsAsList();
|
|
250
|
+
return versions.find((npmVersion) => semver__default.default.eq(npmVersion.version, version2));
|
|
251
|
+
}
|
|
252
|
+
async refresh() {
|
|
253
|
+
const response = await fetch(this.packageURL);
|
|
254
|
+
assert__default.default(response.ok, `Request failed for ${this.packageURL}`);
|
|
255
|
+
this.npmPackage = await response.json();
|
|
256
|
+
return this;
|
|
257
|
+
}
|
|
258
|
+
versionExists(version2) {
|
|
259
|
+
return this.findVersion(version2) !== void 0;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
const npmPackageFactory = (name) => new Package(name);
|
|
278
263
|
class FileScanner {
|
|
279
264
|
cwd;
|
|
280
265
|
constructor(cwd) {
|
|
281
266
|
this.cwd = cwd;
|
|
282
267
|
}
|
|
283
268
|
scan(patterns) {
|
|
284
|
-
const filenames =
|
|
269
|
+
const filenames = fastglob__default.default.sync(patterns, {
|
|
270
|
+
cwd: this.cwd
|
|
271
|
+
});
|
|
285
272
|
return filenames.map((filename) => path__default.default.join(this.cwd, filename));
|
|
286
273
|
}
|
|
287
274
|
}
|
|
@@ -319,6 +306,46 @@ const index$c = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePrope
|
|
|
319
306
|
__proto__: null,
|
|
320
307
|
codeRunnerFactory
|
|
321
308
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
309
|
+
class JSONTransformAPI {
|
|
310
|
+
json;
|
|
311
|
+
constructor(json) {
|
|
312
|
+
this.json = fp.cloneDeep(json);
|
|
313
|
+
}
|
|
314
|
+
get(path2, defaultValue) {
|
|
315
|
+
if (!path2) {
|
|
316
|
+
return this.root();
|
|
317
|
+
}
|
|
318
|
+
return fp.cloneDeep(fp.get(path2, this.json) ?? defaultValue);
|
|
319
|
+
}
|
|
320
|
+
has(path2) {
|
|
321
|
+
return fp.has(path2, this.json);
|
|
322
|
+
}
|
|
323
|
+
merge(other) {
|
|
324
|
+
this.json = fp.merge(other, this.json);
|
|
325
|
+
return this;
|
|
326
|
+
}
|
|
327
|
+
root() {
|
|
328
|
+
return fp.cloneDeep(this.json);
|
|
329
|
+
}
|
|
330
|
+
set(path2, value) {
|
|
331
|
+
this.json = fp.set(path2, value, this.json);
|
|
332
|
+
return this;
|
|
333
|
+
}
|
|
334
|
+
remove(path2) {
|
|
335
|
+
this.json = fp.omit(path2, this.json);
|
|
336
|
+
return this;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
const createJSONTransformAPI = (object) => new JSONTransformAPI(object);
|
|
340
|
+
const readJSON = async (path2) => {
|
|
341
|
+
const buffer = await fse__default.default.readFile(path2);
|
|
342
|
+
return JSON.parse(buffer.toString());
|
|
343
|
+
};
|
|
344
|
+
const saveJSON = async (path2, json) => {
|
|
345
|
+
const jsonAsString = `${JSON.stringify(json, null, 2)}
|
|
346
|
+
`;
|
|
347
|
+
await fse__default.default.writeFile(path2, jsonAsString);
|
|
348
|
+
};
|
|
322
349
|
const transformJSON = async (codemodPath, paths, config) => {
|
|
323
350
|
const { dry } = config;
|
|
324
351
|
const startTime = process.hrtime();
|
|
@@ -330,7 +357,11 @@ const transformJSON = async (codemodPath, paths, config) => {
|
|
|
330
357
|
timeElapsed: "",
|
|
331
358
|
stats: {}
|
|
332
359
|
};
|
|
333
|
-
const esbuildOptions = {
|
|
360
|
+
const esbuildOptions = {
|
|
361
|
+
extensions: [".js", ".mjs", ".ts"],
|
|
362
|
+
hookIgnoreNodeModules: false,
|
|
363
|
+
hookMatcher: fp.isEqual(codemodPath)
|
|
364
|
+
};
|
|
334
365
|
const { unregister } = node.register(esbuildOptions);
|
|
335
366
|
const module2 = require(codemodPath);
|
|
336
367
|
unregister();
|
|
@@ -375,17 +406,31 @@ const index$b = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePrope
|
|
|
375
406
|
jsonRunnerFactory
|
|
376
407
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
377
408
|
const PROJECT_PACKAGE_JSON = "package.json";
|
|
378
|
-
const
|
|
379
|
-
const
|
|
380
|
-
const
|
|
409
|
+
const PROJECT_APP_ALLOWED_ROOT_PATHS = ["src", "config", "public"];
|
|
410
|
+
const PROJECT_PLUGIN_ALLOWED_ROOT_PATHS = ["admin", "server"];
|
|
411
|
+
const PROJECT_PLUGIN_ROOT_FILES = ["strapi-admin.js", "strapi-server.js"];
|
|
412
|
+
const PROJECT_CODE_EXTENSIONS = [
|
|
413
|
+
// Source files
|
|
414
|
+
"js",
|
|
415
|
+
"mjs",
|
|
416
|
+
"ts",
|
|
417
|
+
// React files
|
|
418
|
+
"jsx",
|
|
419
|
+
"tsx"
|
|
420
|
+
];
|
|
421
|
+
const PROJECT_JSON_EXTENSIONS = ["json"];
|
|
422
|
+
const PROJECT_ALLOWED_EXTENSIONS = [...PROJECT_CODE_EXTENSIONS, ...PROJECT_JSON_EXTENSIONS];
|
|
381
423
|
const SCOPED_STRAPI_PACKAGE_PREFIX = "@strapi/";
|
|
382
424
|
const STRAPI_DEPENDENCY_NAME = `${SCOPED_STRAPI_PACKAGE_PREFIX}strapi`;
|
|
383
425
|
const constants$3 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
384
426
|
__proto__: null,
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
427
|
+
PROJECT_ALLOWED_EXTENSIONS,
|
|
428
|
+
PROJECT_APP_ALLOWED_ROOT_PATHS,
|
|
429
|
+
PROJECT_CODE_EXTENSIONS,
|
|
430
|
+
PROJECT_JSON_EXTENSIONS,
|
|
388
431
|
PROJECT_PACKAGE_JSON,
|
|
432
|
+
PROJECT_PLUGIN_ALLOWED_ROOT_PATHS,
|
|
433
|
+
PROJECT_PLUGIN_ROOT_FILES,
|
|
389
434
|
SCOPED_STRAPI_PACKAGE_PREFIX,
|
|
390
435
|
STRAPI_DEPENDENCY_NAME
|
|
391
436
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
@@ -395,12 +440,13 @@ class Project {
|
|
|
395
440
|
files;
|
|
396
441
|
packageJSONPath;
|
|
397
442
|
packageJSON;
|
|
398
|
-
|
|
399
|
-
constructor(cwd) {
|
|
443
|
+
paths;
|
|
444
|
+
constructor(cwd, config) {
|
|
400
445
|
if (!fse__default.default.pathExistsSync(cwd)) {
|
|
401
446
|
throw new Error(`ENOENT: no such file or directory, access '${cwd}'`);
|
|
402
447
|
}
|
|
403
448
|
this.cwd = cwd;
|
|
449
|
+
this.paths = config.paths;
|
|
404
450
|
this.refresh();
|
|
405
451
|
}
|
|
406
452
|
getFilesByExtensions(extensions) {
|
|
@@ -411,14 +457,13 @@ class Project {
|
|
|
411
457
|
}
|
|
412
458
|
refresh() {
|
|
413
459
|
this.refreshPackageJSON();
|
|
414
|
-
this.refreshStrapiVersion();
|
|
415
460
|
this.refreshProjectFiles();
|
|
416
461
|
return this;
|
|
417
462
|
}
|
|
418
|
-
async runCodemods(
|
|
463
|
+
async runCodemods(codemods, options) {
|
|
419
464
|
const runners = this.createProjectCodemodsRunners(options.dry);
|
|
420
465
|
const reports2 = [];
|
|
421
|
-
for (const codemod of
|
|
466
|
+
for (const codemod of codemods) {
|
|
422
467
|
for (const runner of runners) {
|
|
423
468
|
if (runner.valid(codemod)) {
|
|
424
469
|
const report = await runner.run(codemod);
|
|
@@ -429,17 +474,20 @@ class Project {
|
|
|
429
474
|
return reports2;
|
|
430
475
|
}
|
|
431
476
|
createProjectCodemodsRunners(dry = false) {
|
|
432
|
-
const
|
|
433
|
-
const
|
|
477
|
+
const jsonExtensions = PROJECT_JSON_EXTENSIONS.map((ext) => `.${ext}`);
|
|
478
|
+
const codeExtensions = PROJECT_CODE_EXTENSIONS.map((ext) => `.${ext}`);
|
|
479
|
+
const jsonFiles = this.getFilesByExtensions(jsonExtensions);
|
|
480
|
+
const codeFiles = this.getFilesByExtensions(codeExtensions);
|
|
434
481
|
const codeRunner = codeRunnerFactory(codeFiles, {
|
|
435
482
|
dry,
|
|
436
|
-
|
|
437
|
-
silent: true,
|
|
438
|
-
extensions: "js,ts",
|
|
483
|
+
parser: "ts",
|
|
439
484
|
runInBand: true,
|
|
440
|
-
verbose: 0,
|
|
441
485
|
babel: true,
|
|
442
|
-
|
|
486
|
+
extensions: PROJECT_CODE_EXTENSIONS.join(","),
|
|
487
|
+
// Don't output any log coming from the runner
|
|
488
|
+
print: false,
|
|
489
|
+
silent: true,
|
|
490
|
+
verbose: 0
|
|
443
491
|
});
|
|
444
492
|
const jsonRunner = jsonRunnerFactory(jsonFiles, { dry, cwd: this.cwd });
|
|
445
493
|
return [codeRunner, jsonRunner];
|
|
@@ -456,16 +504,38 @@ class Project {
|
|
|
456
504
|
this.packageJSON = JSON.parse(packageJSONBuffer.toString());
|
|
457
505
|
}
|
|
458
506
|
refreshProjectFiles() {
|
|
459
|
-
const allowedRootPaths = formatGlobCollectionPattern(
|
|
460
|
-
PROJECT_DEFAULT_ALLOWED_ROOT_PATHS
|
|
461
|
-
);
|
|
462
|
-
const allowedExtensions = formatGlobCollectionPattern(
|
|
463
|
-
PROJECT_DEFAULT_ALLOWED_EXTENSIONS
|
|
464
|
-
);
|
|
465
|
-
const projectFilesPattern = `./${allowedRootPaths}/**/*.${allowedExtensions}`;
|
|
466
|
-
const patterns = [projectFilesPattern, ...PROJECT_DEFAULT_PATTERNS];
|
|
467
507
|
const scanner = fileScannerFactory(this.cwd);
|
|
468
|
-
this.files = scanner.scan(
|
|
508
|
+
this.files = scanner.scan(this.paths);
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
class AppProject extends Project {
|
|
512
|
+
strapiVersion;
|
|
513
|
+
type = "application";
|
|
514
|
+
/**
|
|
515
|
+
* Returns an array of allowed file paths for a Strapi application
|
|
516
|
+
*
|
|
517
|
+
* The resulting paths include app default files and the root package.json file.
|
|
518
|
+
*/
|
|
519
|
+
static get paths() {
|
|
520
|
+
const allowedRootPaths = formatGlobCollectionPattern(PROJECT_APP_ALLOWED_ROOT_PATHS);
|
|
521
|
+
const allowedExtensions = formatGlobCollectionPattern(PROJECT_ALLOWED_EXTENSIONS);
|
|
522
|
+
return [
|
|
523
|
+
// App default files
|
|
524
|
+
`./${allowedRootPaths}/**/*.${allowedExtensions}`,
|
|
525
|
+
`!./**/node_modules/**/*`,
|
|
526
|
+
`!./**/dist/**/*`,
|
|
527
|
+
// Root package.json file
|
|
528
|
+
PROJECT_PACKAGE_JSON
|
|
529
|
+
];
|
|
530
|
+
}
|
|
531
|
+
constructor(cwd) {
|
|
532
|
+
super(cwd, { paths: AppProject.paths });
|
|
533
|
+
this.refreshStrapiVersion();
|
|
534
|
+
}
|
|
535
|
+
refresh() {
|
|
536
|
+
super.refresh();
|
|
537
|
+
this.refreshStrapiVersion();
|
|
538
|
+
return this;
|
|
469
539
|
}
|
|
470
540
|
refreshStrapiVersion() {
|
|
471
541
|
this.strapiVersion = // First try to get the strapi version from the package.json dependencies
|
|
@@ -512,10 +582,71 @@ const formatGlobCollectionPattern = (collection) => {
|
|
|
512
582
|
);
|
|
513
583
|
return collection.length === 1 ? collection[0] : `{${collection}}`;
|
|
514
584
|
};
|
|
515
|
-
|
|
585
|
+
class PluginProject extends Project {
|
|
586
|
+
type = "plugin";
|
|
587
|
+
/**
|
|
588
|
+
* Returns an array of allowed file paths for a Strapi plugin
|
|
589
|
+
*
|
|
590
|
+
* The resulting paths include plugin default files, the root package.json file, and plugin-specific files.
|
|
591
|
+
*/
|
|
592
|
+
static get paths() {
|
|
593
|
+
const allowedRootPaths = formatGlobCollectionPattern(
|
|
594
|
+
PROJECT_PLUGIN_ALLOWED_ROOT_PATHS
|
|
595
|
+
);
|
|
596
|
+
const allowedExtensions = formatGlobCollectionPattern(PROJECT_ALLOWED_EXTENSIONS);
|
|
597
|
+
return [
|
|
598
|
+
// Plugin default files
|
|
599
|
+
`./${allowedRootPaths}/**/*.${allowedExtensions}`,
|
|
600
|
+
`!./**/node_modules/**/*`,
|
|
601
|
+
`!./**/dist/**/*`,
|
|
602
|
+
// Root package.json file
|
|
603
|
+
PROJECT_PACKAGE_JSON,
|
|
604
|
+
// Plugin root files
|
|
605
|
+
...PROJECT_PLUGIN_ROOT_FILES
|
|
606
|
+
];
|
|
607
|
+
}
|
|
608
|
+
constructor(cwd) {
|
|
609
|
+
super(cwd, { paths: PluginProject.paths });
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
const isPlugin = (cwd) => {
|
|
613
|
+
const packageJSONPath = path__default.default.join(cwd, PROJECT_PACKAGE_JSON);
|
|
614
|
+
try {
|
|
615
|
+
fse__default.default.accessSync(packageJSONPath);
|
|
616
|
+
} catch {
|
|
617
|
+
throw new Error(`Could not find a ${PROJECT_PACKAGE_JSON} file in ${cwd}`);
|
|
618
|
+
}
|
|
619
|
+
const packageJSONBuffer = fse__default.default.readFileSync(packageJSONPath);
|
|
620
|
+
const packageJSON = JSON.parse(packageJSONBuffer.toString());
|
|
621
|
+
return packageJSON?.strapi?.kind === "plugin";
|
|
622
|
+
};
|
|
623
|
+
const projectFactory = (cwd) => {
|
|
624
|
+
fse__default.default.accessSync(cwd);
|
|
625
|
+
return isPlugin(cwd) ? new PluginProject(cwd) : new AppProject(cwd);
|
|
626
|
+
};
|
|
627
|
+
const isPluginProject = (project) => {
|
|
628
|
+
return project instanceof PluginProject;
|
|
629
|
+
};
|
|
630
|
+
function assertPluginProject(project) {
|
|
631
|
+
if (!isPluginProject(project)) {
|
|
632
|
+
throw new Error("Project is not a plugin");
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
const isApplicationProject = (project) => {
|
|
636
|
+
return project instanceof AppProject;
|
|
637
|
+
};
|
|
638
|
+
function assertAppProject(project) {
|
|
639
|
+
if (!isApplicationProject(project)) {
|
|
640
|
+
throw new Error("Project is not an application");
|
|
641
|
+
}
|
|
642
|
+
}
|
|
516
643
|
const index$a = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
517
644
|
__proto__: null,
|
|
645
|
+
assertAppProject,
|
|
646
|
+
assertPluginProject,
|
|
518
647
|
constants: constants$3,
|
|
648
|
+
isApplicationProject,
|
|
649
|
+
isPluginProject,
|
|
519
650
|
projectFactory
|
|
520
651
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
521
652
|
class UnexpectedError extends Error {
|
|
@@ -523,70 +654,33 @@ class UnexpectedError extends Error {
|
|
|
523
654
|
super("Unexpected Error");
|
|
524
655
|
}
|
|
525
656
|
}
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
657
|
+
class NPMCandidateNotFoundError extends Error {
|
|
658
|
+
target;
|
|
659
|
+
constructor(target, message = `Couldn't find a valid NPM candidate for "${target}"`) {
|
|
660
|
+
super(message);
|
|
661
|
+
this.target = target;
|
|
529
662
|
}
|
|
530
|
-
|
|
531
|
-
|
|
663
|
+
}
|
|
664
|
+
class AbortedError extends Error {
|
|
665
|
+
constructor(message = "Upgrade aborted") {
|
|
666
|
+
super(message);
|
|
532
667
|
}
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
return chalk__default.default.italic.yellow(`v${version2}`);
|
|
543
|
-
};
|
|
544
|
-
const versionRange = (range) => chalk__default.default.italic.yellow(range);
|
|
545
|
-
const transform = (transformFilePath) => chalk__default.default.cyan(transformFilePath);
|
|
546
|
-
const highlight = (arg) => chalk__default.default.bold.underline(arg);
|
|
547
|
-
const upgradeStep = (text, step) => {
|
|
548
|
-
return chalk__default.default.bold(`(${step[0]}/${step[1]}) ${text}...`);
|
|
549
|
-
};
|
|
550
|
-
const reports = (reports2) => {
|
|
551
|
-
const rows = reports2.map(({ codemod, report }, i) => {
|
|
552
|
-
const fIndex = chalk__default.default.grey(i);
|
|
553
|
-
const fVersion = chalk__default.default.magenta(codemod.version);
|
|
554
|
-
const fKind = chalk__default.default.yellow(codemod.kind);
|
|
555
|
-
const fFormattedTransformPath = chalk__default.default.cyan(codemod.format());
|
|
556
|
-
const fTimeElapsed = i === 0 ? `${report.timeElapsed}s ${chalk__default.default.dim.italic("(cold start)")}` : `${report.timeElapsed}s`;
|
|
557
|
-
const fAffected = report.ok > 0 ? chalk__default.default.green(report.ok) : chalk__default.default.grey(0);
|
|
558
|
-
const fUnchanged = report.ok === 0 ? chalk__default.default.red(report.nochange) : chalk__default.default.grey(report.nochange);
|
|
559
|
-
return [fIndex, fVersion, fKind, fFormattedTransformPath, fAffected, fUnchanged, fTimeElapsed];
|
|
560
|
-
});
|
|
561
|
-
const table = new CliTable3__default.default({
|
|
562
|
-
style: { compact: true },
|
|
563
|
-
head: [
|
|
564
|
-
chalk__default.default.bold.grey("N°"),
|
|
565
|
-
chalk__default.default.bold.magenta("Version"),
|
|
566
|
-
chalk__default.default.bold.yellow("Kind"),
|
|
567
|
-
chalk__default.default.bold.cyan("Name"),
|
|
568
|
-
chalk__default.default.bold.green("Affected"),
|
|
569
|
-
chalk__default.default.bold.red("Unchanged"),
|
|
570
|
-
chalk__default.default.bold.blue("Duration")
|
|
571
|
-
]
|
|
572
|
-
});
|
|
573
|
-
table.push(...rows);
|
|
574
|
-
return table.toString();
|
|
575
|
-
};
|
|
576
|
-
const durationMs = (elapsedMs) => {
|
|
577
|
-
const elapsedSeconds = (elapsedMs / ONE_SECOND_MS).toFixed(3);
|
|
578
|
-
return `${elapsedSeconds}s`;
|
|
668
|
+
}
|
|
669
|
+
const unknownToError = (e) => {
|
|
670
|
+
if (e instanceof Error) {
|
|
671
|
+
return e;
|
|
672
|
+
}
|
|
673
|
+
if (typeof e === "string") {
|
|
674
|
+
return new Error(e);
|
|
675
|
+
}
|
|
676
|
+
return new UnexpectedError();
|
|
579
677
|
};
|
|
580
|
-
const index$
|
|
678
|
+
const index$9 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
581
679
|
__proto__: null,
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
transform,
|
|
587
|
-
upgradeStep,
|
|
588
|
-
version,
|
|
589
|
-
versionRange
|
|
680
|
+
AbortedError,
|
|
681
|
+
NPMCandidateNotFoundError,
|
|
682
|
+
UnexpectedError,
|
|
683
|
+
unknownToError
|
|
590
684
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
591
685
|
const CODEMOD_CODE_SUFFIX = "code";
|
|
592
686
|
const CODEMOD_JSON_SUFFIX = "json";
|
|
@@ -604,6 +698,7 @@ const constants$2 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineP
|
|
|
604
698
|
CODEMOD_JSON_SUFFIX
|
|
605
699
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
606
700
|
class Codemod {
|
|
701
|
+
uid;
|
|
607
702
|
kind;
|
|
608
703
|
version;
|
|
609
704
|
baseDirectory;
|
|
@@ -615,17 +710,49 @@ class Codemod {
|
|
|
615
710
|
this.baseDirectory = options.baseDirectory;
|
|
616
711
|
this.filename = options.filename;
|
|
617
712
|
this.path = path__default.default.join(this.baseDirectory, this.version.raw, this.filename);
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
713
|
+
this.uid = this.createUID();
|
|
714
|
+
}
|
|
715
|
+
createUID() {
|
|
716
|
+
const name = this.format({ stripExtension: true, stripKind: true, stripHyphens: false });
|
|
717
|
+
const kind = this.kind;
|
|
718
|
+
const version2 = this.version.raw;
|
|
719
|
+
return `${version2}-${name}-${kind}`;
|
|
720
|
+
}
|
|
721
|
+
format(options) {
|
|
722
|
+
const { stripExtension = true, stripKind = true, stripHyphens = true } = options ?? {};
|
|
723
|
+
let formatted = this.filename;
|
|
724
|
+
if (stripExtension) {
|
|
725
|
+
formatted = formatted.replace(new RegExp(`\\.${CODEMOD_EXTENSION}$`, "i"), "");
|
|
726
|
+
}
|
|
727
|
+
if (stripKind) {
|
|
728
|
+
formatted = formatted.replace(`.${CODEMOD_CODE_SUFFIX}`, "").replace(`.${CODEMOD_JSON_SUFFIX}`, "");
|
|
729
|
+
}
|
|
730
|
+
if (stripHyphens) {
|
|
731
|
+
formatted = formatted.replaceAll("-", " ");
|
|
732
|
+
}
|
|
733
|
+
return formatted;
|
|
621
734
|
}
|
|
622
735
|
}
|
|
623
736
|
const codemodFactory = (options) => new Codemod(options);
|
|
624
|
-
const index$
|
|
737
|
+
const index$8 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
625
738
|
__proto__: null,
|
|
626
739
|
codemodFactory,
|
|
627
740
|
constants: constants$2
|
|
628
741
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
742
|
+
const INTERNAL_CODEMODS_DIRECTORY = path__default.default.join(
|
|
743
|
+
__dirname,
|
|
744
|
+
// upgrade/dist
|
|
745
|
+
"..",
|
|
746
|
+
// upgrade
|
|
747
|
+
"resources",
|
|
748
|
+
// upgrade/resources
|
|
749
|
+
"codemods"
|
|
750
|
+
// upgrade/resources/codemods
|
|
751
|
+
);
|
|
752
|
+
const constants$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
753
|
+
__proto__: null,
|
|
754
|
+
INTERNAL_CODEMODS_DIRECTORY
|
|
755
|
+
}, Symbol.toStringTag, { value: "Module" }));
|
|
629
756
|
class CodemodRepository {
|
|
630
757
|
groups;
|
|
631
758
|
versions;
|
|
@@ -644,23 +771,48 @@ class CodemodRepository {
|
|
|
644
771
|
count(version2) {
|
|
645
772
|
return this.findByVersion(version2).length;
|
|
646
773
|
}
|
|
647
|
-
|
|
648
|
-
return this.findByRange(range).length;
|
|
649
|
-
}
|
|
650
|
-
exists(version2) {
|
|
774
|
+
versionExists(version2) {
|
|
651
775
|
return version2.raw in this.groups;
|
|
652
776
|
}
|
|
653
|
-
|
|
777
|
+
has(uid) {
|
|
778
|
+
const result = this.find({ uids: [uid] });
|
|
779
|
+
if (result.length !== 1) {
|
|
780
|
+
return false;
|
|
781
|
+
}
|
|
782
|
+
const { codemods } = result[0];
|
|
783
|
+
return codemods.length === 1 && codemods[0].uid === uid;
|
|
784
|
+
}
|
|
785
|
+
find(q) {
|
|
654
786
|
const entries = Object.entries(this.groups);
|
|
655
|
-
return entries.filter(
|
|
787
|
+
return entries.filter(maybeFilterByRange).map(([version2, codemods]) => ({
|
|
656
788
|
version: semVerFactory(version2),
|
|
657
|
-
|
|
658
|
-
|
|
789
|
+
// Filter by UID if provided in the query
|
|
790
|
+
codemods: codemods.filter(maybeFilterByUIDs)
|
|
791
|
+
})).filter(({ codemods }) => codemods.length > 0);
|
|
792
|
+
function maybeFilterByRange([version2]) {
|
|
793
|
+
if (!isRangeInstance(q.range)) {
|
|
794
|
+
return true;
|
|
795
|
+
}
|
|
796
|
+
return q.range.test(version2);
|
|
797
|
+
}
|
|
798
|
+
function maybeFilterByUIDs(codemod) {
|
|
799
|
+
if (q.uids === void 0) {
|
|
800
|
+
return true;
|
|
801
|
+
}
|
|
802
|
+
return q.uids.includes(codemod.uid);
|
|
803
|
+
}
|
|
659
804
|
}
|
|
660
805
|
findByVersion(version2) {
|
|
661
806
|
const literalVersion = version2.raw;
|
|
662
|
-
const
|
|
663
|
-
return
|
|
807
|
+
const codemods = this.groups[literalVersion];
|
|
808
|
+
return codemods ?? [];
|
|
809
|
+
}
|
|
810
|
+
findAll() {
|
|
811
|
+
const entries = Object.entries(this.groups);
|
|
812
|
+
return entries.map(([version2, codemods]) => ({
|
|
813
|
+
version: semVerFactory(version2),
|
|
814
|
+
codemods
|
|
815
|
+
}));
|
|
664
816
|
}
|
|
665
817
|
refreshAvailableVersions() {
|
|
666
818
|
this.versions = fse__default.default.readdirSync(this.cwd).filter((filename) => fse__default.default.statSync(path__default.default.join(this.cwd, filename)).isDirectory()).filter((filename) => semver__default.default.valid(filename) !== null).map((version2) => semVerFactory(version2)).sort(semver__default.default.compare);
|
|
@@ -691,19 +843,10 @@ const parseCodemodKindFromFilename = (filename) => {
|
|
|
691
843
|
assert__default.default(CODEMOD_ALLOWED_SUFFIXES.includes(kind));
|
|
692
844
|
return kind;
|
|
693
845
|
};
|
|
694
|
-
const codemodRepositoryFactory = (cwd) =>
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
"..",
|
|
699
|
-
"resources",
|
|
700
|
-
"codemods"
|
|
701
|
-
);
|
|
702
|
-
const constants$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
703
|
-
__proto__: null,
|
|
704
|
-
INTERNAL_CODEMODS_DIRECTORY
|
|
705
|
-
}, Symbol.toStringTag, { value: "Module" }));
|
|
706
|
-
const index$6 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
846
|
+
const codemodRepositoryFactory = (cwd = INTERNAL_CODEMODS_DIRECTORY) => {
|
|
847
|
+
return new CodemodRepository(cwd);
|
|
848
|
+
};
|
|
849
|
+
const index$7 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
707
850
|
__proto__: null,
|
|
708
851
|
codemodRepositoryFactory,
|
|
709
852
|
constants: constants$1
|
|
@@ -737,34 +880,59 @@ class CodemodRunner {
|
|
|
737
880
|
this.isDry = enabled;
|
|
738
881
|
return this;
|
|
739
882
|
}
|
|
740
|
-
|
|
883
|
+
createRepository(codemodsDirectory) {
|
|
741
884
|
const repository = codemodRepositoryFactory(
|
|
742
885
|
codemodsDirectory ?? INTERNAL_CODEMODS_DIRECTORY
|
|
743
886
|
);
|
|
744
887
|
repository.refresh();
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
if (
|
|
749
|
-
this.logger?.
|
|
750
|
-
|
|
888
|
+
return repository;
|
|
889
|
+
}
|
|
890
|
+
async safeRunAndReport(codemods) {
|
|
891
|
+
if (this.isDry) {
|
|
892
|
+
this.logger?.warn?.(
|
|
893
|
+
"Running the codemods in dry mode. No files will be modified during the process."
|
|
894
|
+
);
|
|
751
895
|
}
|
|
752
|
-
this.logger?.debug(
|
|
753
|
-
`Found codemods for ${highlight(
|
|
754
|
-
versionedCodemods.length
|
|
755
|
-
)} version(s) using ${versionRange(this.range)}`
|
|
756
|
-
);
|
|
757
|
-
versionedCodemods.forEach(
|
|
758
|
-
({ version: version$1, codemods: codemods22 }) => this.logger?.debug(`- ${version(version$1)} (${codemods22.length})`)
|
|
759
|
-
);
|
|
760
|
-
const codemods2 = versionedCodemods.map(({ codemods: codemods22 }) => codemods22).flat();
|
|
761
896
|
try {
|
|
762
|
-
const reports$1 = await this.project.runCodemods(
|
|
763
|
-
this.logger?.raw(reports(reports$1));
|
|
897
|
+
const reports$1 = await this.project.runCodemods(codemods, { dry: this.isDry });
|
|
898
|
+
this.logger?.raw?.(reports(reports$1));
|
|
899
|
+
if (!this.isDry) {
|
|
900
|
+
const nbAffectedTotal = reports$1.flatMap((report) => report.report.ok).reduce((acc, nb) => acc + nb, 0);
|
|
901
|
+
this.logger?.debug?.(
|
|
902
|
+
`Successfully ran ${highlight(codemods.length)} codemod(s), ${highlight(nbAffectedTotal)} change(s) have been detected`
|
|
903
|
+
);
|
|
904
|
+
}
|
|
905
|
+
return successReport$1();
|
|
764
906
|
} catch (e) {
|
|
765
907
|
return erroredReport$1(unknownToError(e));
|
|
766
908
|
}
|
|
767
|
-
|
|
909
|
+
}
|
|
910
|
+
async runByUID(uid, codemodsDirectory) {
|
|
911
|
+
const repository = this.createRepository(codemodsDirectory);
|
|
912
|
+
if (!repository.has(uid)) {
|
|
913
|
+
throw new Error(`Unknown codemod UID provided: ${uid}`);
|
|
914
|
+
}
|
|
915
|
+
const codemods = repository.find({ uids: [uid] }).flatMap(({ codemods: codemods2 }) => codemods2);
|
|
916
|
+
return this.safeRunAndReport(codemods);
|
|
917
|
+
}
|
|
918
|
+
async run(codemodsDirectory) {
|
|
919
|
+
const repository = this.createRepository(codemodsDirectory);
|
|
920
|
+
const codemodsInRange = repository.find({ range: this.range });
|
|
921
|
+
const selectedCodemods = this.selectCodemodsCallback ? await this.selectCodemodsCallback(codemodsInRange) : codemodsInRange;
|
|
922
|
+
if (selectedCodemods.length === 0) {
|
|
923
|
+
this.logger?.debug?.(`Found no codemods to run for ${versionRange(this.range)}`);
|
|
924
|
+
return successReport$1();
|
|
925
|
+
}
|
|
926
|
+
const codemods = selectedCodemods.flatMap(({ codemods: codemods2 }) => codemods2);
|
|
927
|
+
const codemodsByVersion = fp.groupBy("version", codemods);
|
|
928
|
+
const fRange = versionRange(this.range);
|
|
929
|
+
this.logger?.debug?.(
|
|
930
|
+
`Found ${highlight(codemods.length)} codemods for ${highlight(fp.size(codemodsByVersion))} version(s) using ${fRange}`
|
|
931
|
+
);
|
|
932
|
+
for (const [version$1, codemods2] of Object.entries(codemodsByVersion)) {
|
|
933
|
+
this.logger?.debug?.(`- ${version(semVerFactory(version$1))} (${codemods2.length})`);
|
|
934
|
+
}
|
|
935
|
+
return this.safeRunAndReport(codemods);
|
|
768
936
|
}
|
|
769
937
|
}
|
|
770
938
|
const codemodRunnerFactory = (project, range) => {
|
|
@@ -791,6 +959,15 @@ class Upgrader {
|
|
|
791
959
|
this.logger = null;
|
|
792
960
|
this.confirmationCallback = null;
|
|
793
961
|
}
|
|
962
|
+
getNPMPackage() {
|
|
963
|
+
return this.npmPackage;
|
|
964
|
+
}
|
|
965
|
+
getProject() {
|
|
966
|
+
return this.project;
|
|
967
|
+
}
|
|
968
|
+
getTarget() {
|
|
969
|
+
return semVerFactory(this.target.raw);
|
|
970
|
+
}
|
|
794
971
|
setRequirements(requirements) {
|
|
795
972
|
this.requirements = requirements;
|
|
796
973
|
return this;
|
|
@@ -803,7 +980,7 @@ class Upgrader {
|
|
|
803
980
|
this.codemodsTarget = semVerFactory(
|
|
804
981
|
`${this.target.major}.${this.target.minor}.${this.target.patch}`
|
|
805
982
|
);
|
|
806
|
-
this.logger?.debug(
|
|
983
|
+
this.logger?.debug?.(
|
|
807
984
|
`The codemods target has been synced with the upgrade target. The codemod runner will now look for ${version(
|
|
808
985
|
this.codemodsTarget
|
|
809
986
|
)}`
|
|
@@ -812,7 +989,7 @@ class Upgrader {
|
|
|
812
989
|
}
|
|
813
990
|
overrideCodemodsTarget(target) {
|
|
814
991
|
this.codemodsTarget = target;
|
|
815
|
-
this.logger?.debug(
|
|
992
|
+
this.logger?.debug?.(
|
|
816
993
|
`Overriding the codemods target. The codemod runner will now look for ${version(target)}`
|
|
817
994
|
);
|
|
818
995
|
return this;
|
|
@@ -832,44 +1009,52 @@ class Upgrader {
|
|
|
832
1009
|
addRequirement(requirement) {
|
|
833
1010
|
this.requirements.push(requirement);
|
|
834
1011
|
const fRequired = requirement.isRequired ? "(required)" : "(optional)";
|
|
835
|
-
this.logger?.debug(
|
|
1012
|
+
this.logger?.debug?.(
|
|
836
1013
|
`Added a new requirement to the upgrade: ${highlight(requirement.name)} ${fRequired}`
|
|
837
1014
|
);
|
|
838
1015
|
return this;
|
|
839
1016
|
}
|
|
840
1017
|
async upgrade() {
|
|
841
|
-
this.logger?.info(
|
|
1018
|
+
this.logger?.info?.(
|
|
842
1019
|
`Upgrading from ${version(this.project.strapiVersion)} to ${version(this.target)}`
|
|
843
1020
|
);
|
|
844
1021
|
if (this.isDry) {
|
|
845
|
-
this.logger?.warn(
|
|
1022
|
+
this.logger?.warn?.(
|
|
846
1023
|
"Running the upgrade in dry mode. No files will be modified during the process."
|
|
847
1024
|
);
|
|
848
1025
|
}
|
|
849
1026
|
const range = rangeFromVersions(this.project.strapiVersion, this.target);
|
|
850
1027
|
const codemodsRange = rangeFromVersions(this.project.strapiVersion, this.codemodsTarget);
|
|
851
1028
|
const npmVersionsMatches = this.npmPackage?.findVersionsInRange(range) ?? [];
|
|
852
|
-
this.logger?.debug(
|
|
1029
|
+
this.logger?.debug?.(
|
|
853
1030
|
`Found ${highlight(npmVersionsMatches.length)} versions satisfying ${versionRange(range)}`
|
|
854
1031
|
);
|
|
855
1032
|
try {
|
|
856
|
-
this.logger?.info(upgradeStep("Checking requirement", [1, 4]));
|
|
1033
|
+
this.logger?.info?.(upgradeStep("Checking requirement", [1, 4]));
|
|
857
1034
|
await this.checkRequirements(this.requirements, {
|
|
858
1035
|
npmVersionsMatches,
|
|
859
1036
|
project: this.project,
|
|
860
1037
|
target: this.target
|
|
861
1038
|
});
|
|
862
|
-
this.logger?.info(upgradeStep("Applying the latest code modifications", [2, 4]));
|
|
1039
|
+
this.logger?.info?.(upgradeStep("Applying the latest code modifications", [2, 4]));
|
|
863
1040
|
await this.runCodemods(codemodsRange);
|
|
864
|
-
this.logger?.
|
|
1041
|
+
this.logger?.debug?.("Refreshing project information...");
|
|
1042
|
+
this.project.refresh();
|
|
1043
|
+
this.logger?.info?.(upgradeStep("Upgrading Strapi dependencies", [3, 4]));
|
|
865
1044
|
await this.updateDependencies();
|
|
866
|
-
this.logger?.info(upgradeStep("Installing dependencies", [4, 4]));
|
|
1045
|
+
this.logger?.info?.(upgradeStep("Installing dependencies", [4, 4]));
|
|
867
1046
|
await this.installDependencies();
|
|
868
1047
|
} catch (e) {
|
|
869
1048
|
return erroredReport(unknownToError(e));
|
|
870
1049
|
}
|
|
871
1050
|
return successReport();
|
|
872
1051
|
}
|
|
1052
|
+
async confirm(message) {
|
|
1053
|
+
if (typeof this.confirmationCallback !== "function") {
|
|
1054
|
+
return true;
|
|
1055
|
+
}
|
|
1056
|
+
return this.confirmationCallback(message);
|
|
1057
|
+
}
|
|
873
1058
|
async checkRequirements(requirements, context) {
|
|
874
1059
|
for (const requirement of requirements) {
|
|
875
1060
|
const { pass, error } = await requirement.test(context);
|
|
@@ -896,7 +1081,7 @@ class Upgrader {
|
|
|
896
1081
|
if (requirement.isRequired) {
|
|
897
1082
|
throw error;
|
|
898
1083
|
}
|
|
899
|
-
this.logger?.warn(warningMessage);
|
|
1084
|
+
this.logger?.warn?.(warningMessage);
|
|
900
1085
|
const response = await this.confirmationCallback?.(confirmationMessage);
|
|
901
1086
|
if (!response) {
|
|
902
1087
|
throw error;
|
|
@@ -907,9 +1092,11 @@ class Upgrader {
|
|
|
907
1092
|
const json = createJSONTransformAPI(packageJSON);
|
|
908
1093
|
const dependencies = json.get("dependencies", {});
|
|
909
1094
|
const strapiDependencies = this.getScopedStrapiDependencies(dependencies);
|
|
910
|
-
this.logger?.debug(
|
|
1095
|
+
this.logger?.debug?.(
|
|
1096
|
+
`Found ${highlight(strapiDependencies.length)} dependency(ies) to update`
|
|
1097
|
+
);
|
|
911
1098
|
strapiDependencies.forEach(
|
|
912
|
-
(dependency) => this.logger?.debug(`- ${dependency[0]} (${dependency[1]} -> ${this.target})`)
|
|
1099
|
+
(dependency) => this.logger?.debug?.(`- ${dependency[0]} (${dependency[1]} -> ${this.target})`)
|
|
913
1100
|
);
|
|
914
1101
|
if (strapiDependencies.length === 0) {
|
|
915
1102
|
return;
|
|
@@ -917,7 +1104,7 @@ class Upgrader {
|
|
|
917
1104
|
strapiDependencies.forEach(([name]) => json.set(`dependencies.${name}`, this.target.raw));
|
|
918
1105
|
const updatedPackageJSON = json.root();
|
|
919
1106
|
if (this.isDry) {
|
|
920
|
-
this.logger?.debug(`Skipping dependencies update (${chalk__default.default.italic("dry mode")})`);
|
|
1107
|
+
this.logger?.debug?.(`Skipping dependencies update (${chalk__default.default.italic("dry mode")})`);
|
|
921
1108
|
return;
|
|
922
1109
|
}
|
|
923
1110
|
await saveJSON(packageJSONPath, updatedPackageJSON);
|
|
@@ -937,9 +1124,9 @@ class Upgrader {
|
|
|
937
1124
|
async installDependencies() {
|
|
938
1125
|
const projectPath = this.project.cwd;
|
|
939
1126
|
const packageManagerName = await utils.packageManager.getPreferred(projectPath);
|
|
940
|
-
this.logger?.debug(`Using ${highlight(packageManagerName)} as package manager`);
|
|
1127
|
+
this.logger?.debug?.(`Using ${highlight(packageManagerName)} as package manager`);
|
|
941
1128
|
if (this.isDry) {
|
|
942
|
-
this.logger?.debug(`Skipping dependencies installation (${chalk__default.default.italic("dry mode")}`);
|
|
1129
|
+
this.logger?.debug?.(`Skipping dependencies installation (${chalk__default.default.italic("dry mode")})`);
|
|
943
1130
|
return;
|
|
944
1131
|
}
|
|
945
1132
|
await utils.packageManager.installDependencies(projectPath, packageManagerName, {
|
|
@@ -958,23 +1145,28 @@ class Upgrader {
|
|
|
958
1145
|
}
|
|
959
1146
|
const resolveNPMTarget = (project, target, npmPackage) => {
|
|
960
1147
|
if (isSemverInstance(target)) {
|
|
961
|
-
|
|
1148
|
+
const version2 = npmPackage.findVersion(target);
|
|
1149
|
+
if (!version2) {
|
|
1150
|
+
throw new NPMCandidateNotFoundError(target);
|
|
1151
|
+
}
|
|
1152
|
+
return version2;
|
|
962
1153
|
}
|
|
963
1154
|
if (isSemVerReleaseType(target)) {
|
|
964
1155
|
const range = rangeFromVersions(project.strapiVersion, target);
|
|
965
1156
|
const npmVersionsMatches = npmPackage.findVersionsInRange(range);
|
|
966
|
-
|
|
1157
|
+
const version2 = npmVersionsMatches.at(-1);
|
|
1158
|
+
if (!version2) {
|
|
1159
|
+
throw new NPMCandidateNotFoundError(range, `The project is already up-to-date (${target})`);
|
|
1160
|
+
}
|
|
1161
|
+
return version2;
|
|
967
1162
|
}
|
|
968
|
-
|
|
1163
|
+
throw new NPMCandidateNotFoundError(target);
|
|
969
1164
|
};
|
|
970
1165
|
const upgraderFactory = (project, target, npmPackage) => {
|
|
971
|
-
const
|
|
972
|
-
|
|
973
|
-
throw new Error(`Couldn't find a matching version in the NPM registry for "${target}"`);
|
|
974
|
-
}
|
|
975
|
-
const semverTarget = semVerFactory(targetedNPMVersion.version);
|
|
1166
|
+
const npmTarget = resolveNPMTarget(project, target, npmPackage);
|
|
1167
|
+
const semverTarget = semVerFactory(npmTarget.version);
|
|
976
1168
|
if (semver__default.default.eq(semverTarget, project.strapiVersion)) {
|
|
977
|
-
throw new Error(`The project is already
|
|
1169
|
+
throw new Error(`The project is already using v${semverTarget}`);
|
|
978
1170
|
}
|
|
979
1171
|
return new Upgrader(project, semverTarget, npmPackage);
|
|
980
1172
|
};
|
|
@@ -985,96 +1177,205 @@ const constants = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePro
|
|
|
985
1177
|
__proto__: null,
|
|
986
1178
|
STRAPI_PACKAGE_NAME
|
|
987
1179
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
988
|
-
const index$
|
|
1180
|
+
const index$6 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
989
1181
|
__proto__: null,
|
|
990
1182
|
constants,
|
|
991
1183
|
upgraderFactory
|
|
992
1184
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
993
|
-
|
|
994
|
-
|
|
1185
|
+
class Requirement {
|
|
1186
|
+
isRequired;
|
|
995
1187
|
name;
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
constructor(name) {
|
|
1188
|
+
testCallback;
|
|
1189
|
+
children;
|
|
1190
|
+
constructor(name, testCallback, isRequired) {
|
|
999
1191
|
this.name = name;
|
|
1000
|
-
this.
|
|
1001
|
-
this.
|
|
1192
|
+
this.testCallback = testCallback;
|
|
1193
|
+
this.isRequired = isRequired ?? true;
|
|
1194
|
+
this.children = [];
|
|
1002
1195
|
}
|
|
1003
|
-
|
|
1004
|
-
|
|
1196
|
+
setChildren(children) {
|
|
1197
|
+
this.children = children;
|
|
1198
|
+
return this;
|
|
1005
1199
|
}
|
|
1006
|
-
|
|
1007
|
-
|
|
1200
|
+
addChild(child) {
|
|
1201
|
+
this.children.push(child);
|
|
1202
|
+
return this;
|
|
1008
1203
|
}
|
|
1009
|
-
|
|
1010
|
-
this.
|
|
1011
|
-
|
|
1204
|
+
asOptional() {
|
|
1205
|
+
const newInstance = requirementFactory(this.name, this.testCallback, false);
|
|
1206
|
+
newInstance.setChildren(this.children);
|
|
1207
|
+
return newInstance;
|
|
1012
1208
|
}
|
|
1013
|
-
|
|
1014
|
-
this.
|
|
1015
|
-
|
|
1209
|
+
asRequired() {
|
|
1210
|
+
const newInstance = requirementFactory(this.name, this.testCallback, true);
|
|
1211
|
+
newInstance.setChildren(this.children);
|
|
1212
|
+
return newInstance;
|
|
1016
1213
|
}
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1214
|
+
async test(context) {
|
|
1215
|
+
try {
|
|
1216
|
+
await this.testCallback?.(context);
|
|
1217
|
+
return ok();
|
|
1218
|
+
} catch (e) {
|
|
1219
|
+
if (e instanceof Error) {
|
|
1220
|
+
return errored(e);
|
|
1221
|
+
}
|
|
1222
|
+
if (typeof e === "string") {
|
|
1223
|
+
return errored(new Error(e));
|
|
1224
|
+
}
|
|
1225
|
+
return errored(new Error("Unknown error"));
|
|
1226
|
+
}
|
|
1020
1227
|
}
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1228
|
+
}
|
|
1229
|
+
const ok = () => ({ pass: true, error: null });
|
|
1230
|
+
const errored = (error) => ({ pass: false, error });
|
|
1231
|
+
const requirementFactory = (name, testCallback, isRequired) => new Requirement(name, testCallback, isRequired);
|
|
1232
|
+
const index$5 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
1233
|
+
__proto__: null,
|
|
1234
|
+
requirementFactory
|
|
1235
|
+
}, Symbol.toStringTag, { value: "Module" }));
|
|
1236
|
+
const REQUIRE_AVAILABLE_NEXT_MAJOR = requirementFactory(
|
|
1237
|
+
"REQUIRE_AVAILABLE_NEXT_MAJOR",
|
|
1238
|
+
(context) => {
|
|
1239
|
+
const { project, target } = context;
|
|
1240
|
+
const currentMajor = project.strapiVersion.major;
|
|
1241
|
+
const targetedMajor = target.major;
|
|
1242
|
+
if (targetedMajor === currentMajor) {
|
|
1243
|
+
throw new Error(`You're already on the latest major version (v${currentMajor})`);
|
|
1244
|
+
}
|
|
1024
1245
|
}
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1246
|
+
);
|
|
1247
|
+
const REQUIRE_LATEST_FOR_CURRENT_MAJOR = requirementFactory(
|
|
1248
|
+
"REQUIRE_LATEST_FOR_CURRENT_MAJOR",
|
|
1249
|
+
(context) => {
|
|
1250
|
+
const { project, target, npmVersionsMatches } = context;
|
|
1251
|
+
const { major: currentMajor } = project.strapiVersion;
|
|
1252
|
+
const invalidMatches = npmVersionsMatches.filter(
|
|
1253
|
+
(match) => semVerFactory(match.version).major === currentMajor
|
|
1254
|
+
);
|
|
1255
|
+
if (invalidMatches.length > 0) {
|
|
1256
|
+
const invalidVersions = invalidMatches.map((match) => match.version);
|
|
1257
|
+
const invalidVersionsCount = invalidVersions.length;
|
|
1258
|
+
throw new Error(
|
|
1259
|
+
`Doing a major upgrade requires to be on the latest v${currentMajor} version, but found ${invalidVersionsCount} versions between the current one and ${target}. Please upgrade to ${invalidVersions.at(-1)} and try again.`
|
|
1260
|
+
);
|
|
1261
|
+
}
|
|
1030
1262
|
}
|
|
1031
|
-
|
|
1032
|
-
|
|
1263
|
+
);
|
|
1264
|
+
const REQUIRE_GIT_CLEAN_REPOSITORY = requirementFactory(
|
|
1265
|
+
"REQUIRE_GIT_CLEAN_REPOSITORY",
|
|
1266
|
+
async (context) => {
|
|
1267
|
+
const git = simpleGit__default.default({ baseDir: context.project.cwd });
|
|
1268
|
+
const status = await git.status();
|
|
1269
|
+
if (!status.isClean()) {
|
|
1270
|
+
throw new Error(
|
|
1271
|
+
"Repository is not clean. Please commit or stash any changes before upgrading"
|
|
1272
|
+
);
|
|
1273
|
+
}
|
|
1033
1274
|
}
|
|
1034
|
-
|
|
1035
|
-
const
|
|
1275
|
+
);
|
|
1276
|
+
const REQUIRE_GIT_REPOSITORY = requirementFactory(
|
|
1277
|
+
"REQUIRE_GIT_REPOSITORY",
|
|
1278
|
+
async (context) => {
|
|
1279
|
+
const git = simpleGit__default.default({ baseDir: context.project.cwd });
|
|
1280
|
+
const isRepo = await git.checkIsRepo();
|
|
1281
|
+
if (!isRepo) {
|
|
1282
|
+
throw new Error("Not a git repository (or any of the parent directories)");
|
|
1283
|
+
}
|
|
1284
|
+
}
|
|
1285
|
+
).addChild(REQUIRE_GIT_CLEAN_REPOSITORY.asOptional());
|
|
1286
|
+
const REQUIRE_GIT_INSTALLED = requirementFactory(
|
|
1287
|
+
"REQUIRE_GIT_INSTALLED",
|
|
1288
|
+
async (context) => {
|
|
1289
|
+
const git = simpleGit__default.default({ baseDir: context.project.cwd });
|
|
1290
|
+
try {
|
|
1291
|
+
await git.version();
|
|
1292
|
+
} catch {
|
|
1293
|
+
throw new Error("Git is not installed");
|
|
1294
|
+
}
|
|
1295
|
+
}
|
|
1296
|
+
).addChild(REQUIRE_GIT_REPOSITORY.asOptional());
|
|
1297
|
+
const REQUIRE_GIT = requirementFactory("REQUIRE_GIT", null).addChild(
|
|
1298
|
+
REQUIRE_GIT_INSTALLED.asOptional()
|
|
1299
|
+
);
|
|
1300
|
+
const latest = async (upgrader, options) => {
|
|
1301
|
+
if (options.target !== ReleaseType.Latest) {
|
|
1302
|
+
return;
|
|
1303
|
+
}
|
|
1304
|
+
const npmPackage = upgrader.getNPMPackage();
|
|
1305
|
+
const target = upgrader.getTarget();
|
|
1306
|
+
const project = upgrader.getProject();
|
|
1307
|
+
const { strapiVersion: current } = project;
|
|
1308
|
+
const fTargetMajor = highlight(`v${target.major}`);
|
|
1309
|
+
const fCurrentMajor = highlight(`v${current.major}`);
|
|
1310
|
+
const fTarget = version(target);
|
|
1311
|
+
const fCurrent = version(current);
|
|
1312
|
+
const isMajorUpgrade = target.major > current.major;
|
|
1313
|
+
if (isMajorUpgrade) {
|
|
1314
|
+
options.logger.warn(
|
|
1315
|
+
`Detected a major upgrade for the "${highlight(ReleaseType.Latest)}" tag: ${fCurrent} > ${fTarget}`
|
|
1316
|
+
);
|
|
1317
|
+
const newerPackageRelease = npmPackage.findVersionsInRange(rangeFactory(`>${current.raw} <${target.major}`)).at(-1);
|
|
1318
|
+
if (newerPackageRelease) {
|
|
1319
|
+
const fLatest = version(semVerFactory(newerPackageRelease.version));
|
|
1320
|
+
options.logger.warn(
|
|
1321
|
+
`It's recommended to first upgrade to the latest version of ${fCurrentMajor} (${fLatest}) before upgrading to ${fTargetMajor}.`
|
|
1322
|
+
);
|
|
1323
|
+
}
|
|
1324
|
+
const proceedAnyway = await upgrader.confirm(`I know what I'm doing. Proceed anyway!`);
|
|
1325
|
+
if (!proceedAnyway) {
|
|
1326
|
+
throw new AbortedError();
|
|
1327
|
+
}
|
|
1328
|
+
}
|
|
1329
|
+
};
|
|
1036
1330
|
const upgrade = async (options) => {
|
|
1037
1331
|
const timer = timerFactory();
|
|
1038
1332
|
const { logger, codemodsTarget } = options;
|
|
1039
1333
|
const cwd = path__default.default.resolve(options.cwd ?? process.cwd());
|
|
1040
1334
|
const project = projectFactory(cwd);
|
|
1335
|
+
logger.debug(projectDetails(project));
|
|
1336
|
+
if (!isApplicationProject(project)) {
|
|
1337
|
+
throw new Error(
|
|
1338
|
+
`The "${options.target}" upgrade can only be run on a Strapi project; for plugins, please use "codemods".`
|
|
1339
|
+
);
|
|
1340
|
+
}
|
|
1341
|
+
logger.debug(
|
|
1342
|
+
`Application: VERSION=${version(project.packageJSON.version)}; STRAPI_VERSION=${version(project.strapiVersion)}`
|
|
1343
|
+
);
|
|
1041
1344
|
const npmPackage = npmPackageFactory(STRAPI_PACKAGE_NAME);
|
|
1042
1345
|
await npmPackage.refresh();
|
|
1043
1346
|
const upgrader = upgraderFactory(project, options.target, npmPackage).dry(options.dry ?? false).onConfirm(options.confirm ?? null).setLogger(logger);
|
|
1044
1347
|
if (codemodsTarget !== void 0) {
|
|
1045
1348
|
upgrader.overrideCodemodsTarget(codemodsTarget);
|
|
1046
1349
|
}
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
}
|
|
1050
|
-
upgrader.addRequirement(REQUIRE_GIT.asOptional());
|
|
1350
|
+
await runUpgradePrompts(upgrader, options);
|
|
1351
|
+
addUpgradeRequirements(upgrader, options);
|
|
1051
1352
|
const upgradeReport = await upgrader.upgrade();
|
|
1052
1353
|
if (!upgradeReport.success) {
|
|
1053
1354
|
throw upgradeReport.error;
|
|
1054
1355
|
}
|
|
1055
1356
|
timer.stop();
|
|
1056
|
-
logger.info(`Completed in ${durationMs(timer.elapsedMs)}`);
|
|
1357
|
+
logger.info(`Completed in ${durationMs(timer.elapsedMs)}ms`);
|
|
1057
1358
|
};
|
|
1058
|
-
const
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
const cwd = path__default.default.resolve(options.cwd ?? process.cwd());
|
|
1062
|
-
const project = projectFactory(cwd);
|
|
1063
|
-
const range = getRangeFromTarget(project.strapiVersion, options.target);
|
|
1064
|
-
const codemodRunner = codemodRunnerFactory(project, range).dry(options.dry ?? false).onSelectCodemods(options.selectCodemods ?? null).setLogger(logger);
|
|
1065
|
-
const executionReport = await codemodRunner.run();
|
|
1066
|
-
if (!executionReport.success) {
|
|
1067
|
-
throw executionReport.error;
|
|
1359
|
+
const runUpgradePrompts = async (upgrader, options) => {
|
|
1360
|
+
if (options.target === ReleaseType.Latest) {
|
|
1361
|
+
await latest(upgrader, options);
|
|
1068
1362
|
}
|
|
1069
|
-
timer.stop();
|
|
1070
|
-
logger.info(`Completed in ${timer.elapsedMs}`);
|
|
1071
1363
|
};
|
|
1364
|
+
const addUpgradeRequirements = (upgrader, options) => {
|
|
1365
|
+
if (options.target === ReleaseType.Major) {
|
|
1366
|
+
upgrader.addRequirement(REQUIRE_AVAILABLE_NEXT_MAJOR).addRequirement(REQUIRE_LATEST_FOR_CURRENT_MAJOR);
|
|
1367
|
+
}
|
|
1368
|
+
upgrader.addRequirement(REQUIRE_GIT.asOptional());
|
|
1369
|
+
};
|
|
1370
|
+
const resolvePath = (cwd) => path__default.default.resolve(cwd ?? process.cwd());
|
|
1072
1371
|
const getRangeFromTarget = (currentVersion, target) => {
|
|
1073
1372
|
if (isSemverInstance(target)) {
|
|
1074
1373
|
return rangeFactory(target);
|
|
1075
1374
|
}
|
|
1076
1375
|
const { major, minor, patch } = currentVersion;
|
|
1077
1376
|
switch (target) {
|
|
1377
|
+
case ReleaseType.Latest:
|
|
1378
|
+
throw new Error("Can't use <latest> to create a codemods range: not implemented");
|
|
1078
1379
|
case ReleaseType.Major:
|
|
1079
1380
|
return rangeFactory(`${major}`);
|
|
1080
1381
|
case ReleaseType.Minor:
|
|
@@ -1085,9 +1386,60 @@ const getRangeFromTarget = (currentVersion, target) => {
|
|
|
1085
1386
|
throw new Error(`Invalid target set: ${target}`);
|
|
1086
1387
|
}
|
|
1087
1388
|
};
|
|
1389
|
+
const findRangeFromTarget = (project, target) => {
|
|
1390
|
+
if (isRangeInstance(target)) {
|
|
1391
|
+
return target;
|
|
1392
|
+
}
|
|
1393
|
+
if (isApplicationProject(project)) {
|
|
1394
|
+
return getRangeFromTarget(project.strapiVersion, target);
|
|
1395
|
+
}
|
|
1396
|
+
return rangeFactory("*");
|
|
1397
|
+
};
|
|
1398
|
+
const runCodemods = async (options) => {
|
|
1399
|
+
const timer = timerFactory();
|
|
1400
|
+
const { logger, uid } = options;
|
|
1401
|
+
const cwd = resolvePath(options.cwd);
|
|
1402
|
+
const project = projectFactory(cwd);
|
|
1403
|
+
const range = findRangeFromTarget(project, options.target);
|
|
1404
|
+
logger.debug(projectDetails(project));
|
|
1405
|
+
logger.debug(`Range: set to ${versionRange(range)}`);
|
|
1406
|
+
const codemodRunner = codemodRunnerFactory(project, range).dry(options.dry ?? false).onSelectCodemods(options.selectCodemods ?? null).setLogger(logger);
|
|
1407
|
+
let report;
|
|
1408
|
+
if (uid !== void 0) {
|
|
1409
|
+
logger.debug(`Running a single codemod: ${codemodUID(uid)}`);
|
|
1410
|
+
report = await codemodRunner.runByUID(uid);
|
|
1411
|
+
} else {
|
|
1412
|
+
report = await codemodRunner.run();
|
|
1413
|
+
}
|
|
1414
|
+
if (!report.success) {
|
|
1415
|
+
throw report.error;
|
|
1416
|
+
}
|
|
1417
|
+
timer.stop();
|
|
1418
|
+
logger.info(`Completed in ${timer.elapsedMs}`);
|
|
1419
|
+
};
|
|
1420
|
+
const listCodemods = async (options) => {
|
|
1421
|
+
const { logger, target } = options;
|
|
1422
|
+
const cwd = resolvePath(options.cwd);
|
|
1423
|
+
const project = projectFactory(cwd);
|
|
1424
|
+
const range = findRangeFromTarget(project, target);
|
|
1425
|
+
logger.debug(projectDetails(project));
|
|
1426
|
+
logger.debug(`Range: set to ${versionRange(range)}`);
|
|
1427
|
+
const repo = codemodRepositoryFactory();
|
|
1428
|
+
repo.refresh();
|
|
1429
|
+
const groups = repo.find({ range });
|
|
1430
|
+
const codemods = groups.flatMap((collection) => collection.codemods);
|
|
1431
|
+
logger.debug(`Found ${highlight(codemods.length)} codemods`);
|
|
1432
|
+
if (codemods.length === 0) {
|
|
1433
|
+
logger.info(`Found no codemods matching ${versionRange(range)}`);
|
|
1434
|
+
return;
|
|
1435
|
+
}
|
|
1436
|
+
const fCodemods = codemodList(codemods);
|
|
1437
|
+
logger.raw(fCodemods);
|
|
1438
|
+
};
|
|
1088
1439
|
const index$4 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
1089
1440
|
__proto__: null,
|
|
1090
|
-
|
|
1441
|
+
listCodemods,
|
|
1442
|
+
runCodemods,
|
|
1091
1443
|
upgrade
|
|
1092
1444
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
1093
1445
|
class Logger {
|
|
@@ -1181,18 +1533,18 @@ const index$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePrope
|
|
|
1181
1533
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
1182
1534
|
const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
1183
1535
|
__proto__: null,
|
|
1184
|
-
codemod: index$
|
|
1185
|
-
codemodRepository: index$
|
|
1536
|
+
codemod: index$8,
|
|
1537
|
+
codemodRepository: index$7,
|
|
1186
1538
|
error: index$9,
|
|
1187
|
-
f: index$
|
|
1539
|
+
f: index$f,
|
|
1188
1540
|
fileScanner: index$d,
|
|
1189
1541
|
logger: index$3,
|
|
1190
1542
|
project: index$a,
|
|
1191
1543
|
report: index$2,
|
|
1192
|
-
requirement: index$
|
|
1544
|
+
requirement: index$5,
|
|
1193
1545
|
runner: index$1,
|
|
1194
|
-
timer: index$
|
|
1195
|
-
upgrader: index$
|
|
1546
|
+
timer: index$g,
|
|
1547
|
+
upgrader: index$6,
|
|
1196
1548
|
version: index$e
|
|
1197
1549
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
1198
1550
|
exports.modules = index;
|