@strapi/upgrade 0.0.0-experimental.d362bf200f5f9359a4bbd4a549603de5ee1f04ca → 0.0.0-experimental.d3cdf79a0d5f803dfeb6d0f055bb2f3b913bb015
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 +671 -412
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +667 -409
- 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 +5 -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 +6 -3
- 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 -5
- package/dist/modules/project/constants.d.ts.map +1 -1
- package/dist/modules/project/project.d.ts +17 -3
- package/dist/modules/project/project.d.ts.map +1 -1
- package/dist/modules/project/types.d.ts +4 -0
- package/dist/modules/project/types.d.ts.map +1 -1
- package/dist/modules/project/utils.d.ts +1 -1
- package/dist/modules/project/utils.d.ts.map +1 -1
- package/dist/modules/report/report.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 +4 -0
- 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 -11
- 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/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/sqlite3-to-better-sqlite3.json.ts +0 -1
- package/resources/codemods/5.0.0/strapi-public-interface.code.ts +126 -0
- 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/utils/change-import.ts +118 -0
- package/resources/utils/replace-jsx.ts +49 -0
- package/dist/_chunks/codemod-runner-mXNzVpHm.js +0 -798
- package/dist/_chunks/codemod-runner-mXNzVpHm.js.map +0 -1
- package/dist/_chunks/codemods-S4mNX9Qg.js +0 -105
- package/dist/_chunks/codemods-S4mNX9Qg.js.map +0 -1
- package/dist/_chunks/index-Pt-TU9MN.js +0 -103
- package/dist/_chunks/index-Pt-TU9MN.js.map +0 -1
- package/dist/_chunks/upgrade-aWNYibWB.js +0 -361
- package/dist/_chunks/upgrade-aWNYibWB.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}...`);
|
|
210
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`;
|
|
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,8 +406,10 @@ 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
|
|
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 = [
|
|
380
413
|
// Source files
|
|
381
414
|
"js",
|
|
382
415
|
"mjs",
|
|
@@ -385,22 +418,19 @@ const PROJECT_DEFAULT_CODE_EXTENSIONS = [
|
|
|
385
418
|
"jsx",
|
|
386
419
|
"tsx"
|
|
387
420
|
];
|
|
388
|
-
const
|
|
389
|
-
const
|
|
390
|
-
...PROJECT_DEFAULT_CODE_EXTENSIONS,
|
|
391
|
-
...PROJECT_DEFAULT_JSON_EXTENSIONS
|
|
392
|
-
];
|
|
393
|
-
const PROJECT_DEFAULT_PATTERNS = ["package.json"];
|
|
421
|
+
const PROJECT_JSON_EXTENSIONS = ["json"];
|
|
422
|
+
const PROJECT_ALLOWED_EXTENSIONS = [...PROJECT_CODE_EXTENSIONS, ...PROJECT_JSON_EXTENSIONS];
|
|
394
423
|
const SCOPED_STRAPI_PACKAGE_PREFIX = "@strapi/";
|
|
395
424
|
const STRAPI_DEPENDENCY_NAME = `${SCOPED_STRAPI_PACKAGE_PREFIX}strapi`;
|
|
396
425
|
const constants$3 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
397
426
|
__proto__: null,
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
PROJECT_DEFAULT_PATTERNS,
|
|
427
|
+
PROJECT_ALLOWED_EXTENSIONS,
|
|
428
|
+
PROJECT_APP_ALLOWED_ROOT_PATHS,
|
|
429
|
+
PROJECT_CODE_EXTENSIONS,
|
|
430
|
+
PROJECT_JSON_EXTENSIONS,
|
|
403
431
|
PROJECT_PACKAGE_JSON,
|
|
432
|
+
PROJECT_PLUGIN_ALLOWED_ROOT_PATHS,
|
|
433
|
+
PROJECT_PLUGIN_ROOT_FILES,
|
|
404
434
|
SCOPED_STRAPI_PACKAGE_PREFIX,
|
|
405
435
|
STRAPI_DEPENDENCY_NAME
|
|
406
436
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
@@ -410,11 +440,13 @@ class Project {
|
|
|
410
440
|
files;
|
|
411
441
|
packageJSONPath;
|
|
412
442
|
packageJSON;
|
|
413
|
-
|
|
443
|
+
paths;
|
|
444
|
+
constructor(cwd, config) {
|
|
414
445
|
if (!fse__default.default.pathExistsSync(cwd)) {
|
|
415
446
|
throw new Error(`ENOENT: no such file or directory, access '${cwd}'`);
|
|
416
447
|
}
|
|
417
448
|
this.cwd = cwd;
|
|
449
|
+
this.paths = config.paths;
|
|
418
450
|
this.refresh();
|
|
419
451
|
}
|
|
420
452
|
getFilesByExtensions(extensions) {
|
|
@@ -428,10 +460,10 @@ class Project {
|
|
|
428
460
|
this.refreshProjectFiles();
|
|
429
461
|
return this;
|
|
430
462
|
}
|
|
431
|
-
async runCodemods(
|
|
463
|
+
async runCodemods(codemods, options) {
|
|
432
464
|
const runners = this.createProjectCodemodsRunners(options.dry);
|
|
433
465
|
const reports2 = [];
|
|
434
|
-
for (const codemod of
|
|
466
|
+
for (const codemod of codemods) {
|
|
435
467
|
for (const runner of runners) {
|
|
436
468
|
if (runner.valid(codemod)) {
|
|
437
469
|
const report = await runner.run(codemod);
|
|
@@ -442,12 +474,8 @@ class Project {
|
|
|
442
474
|
return reports2;
|
|
443
475
|
}
|
|
444
476
|
createProjectCodemodsRunners(dry = false) {
|
|
445
|
-
const jsonExtensions =
|
|
446
|
-
|
|
447
|
-
);
|
|
448
|
-
const codeExtensions = PROJECT_DEFAULT_CODE_EXTENSIONS.map(
|
|
449
|
-
(ext) => `.${ext}`
|
|
450
|
-
);
|
|
477
|
+
const jsonExtensions = PROJECT_JSON_EXTENSIONS.map((ext) => `.${ext}`);
|
|
478
|
+
const codeExtensions = PROJECT_CODE_EXTENSIONS.map((ext) => `.${ext}`);
|
|
451
479
|
const jsonFiles = this.getFilesByExtensions(jsonExtensions);
|
|
452
480
|
const codeFiles = this.getFilesByExtensions(codeExtensions);
|
|
453
481
|
const codeRunner = codeRunnerFactory(codeFiles, {
|
|
@@ -455,7 +483,7 @@ class Project {
|
|
|
455
483
|
parser: "ts",
|
|
456
484
|
runInBand: true,
|
|
457
485
|
babel: true,
|
|
458
|
-
extensions:
|
|
486
|
+
extensions: PROJECT_CODE_EXTENSIONS.join(","),
|
|
459
487
|
// Don't output any log coming from the runner
|
|
460
488
|
print: false,
|
|
461
489
|
silent: true,
|
|
@@ -476,23 +504,32 @@ class Project {
|
|
|
476
504
|
this.packageJSON = JSON.parse(packageJSONBuffer.toString());
|
|
477
505
|
}
|
|
478
506
|
refreshProjectFiles() {
|
|
479
|
-
const allowedRootPaths = formatGlobCollectionPattern(
|
|
480
|
-
PROJECT_DEFAULT_ALLOWED_ROOT_PATHS
|
|
481
|
-
);
|
|
482
|
-
const allowedExtensions = formatGlobCollectionPattern(
|
|
483
|
-
PROJECT_DEFAULT_ALLOWED_EXTENSIONS
|
|
484
|
-
);
|
|
485
|
-
const projectFilesPattern = `./${allowedRootPaths}/**/*.${allowedExtensions}`;
|
|
486
|
-
const patterns = [projectFilesPattern, ...PROJECT_DEFAULT_PATTERNS];
|
|
487
507
|
const scanner = fileScannerFactory(this.cwd);
|
|
488
|
-
this.files = scanner.scan(
|
|
508
|
+
this.files = scanner.scan(this.paths);
|
|
489
509
|
}
|
|
490
510
|
}
|
|
491
511
|
class AppProject extends Project {
|
|
492
512
|
strapiVersion;
|
|
493
|
-
type = "
|
|
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
|
+
}
|
|
494
531
|
constructor(cwd) {
|
|
495
|
-
super(cwd);
|
|
532
|
+
super(cwd, { paths: AppProject.paths });
|
|
496
533
|
this.refreshStrapiVersion();
|
|
497
534
|
}
|
|
498
535
|
refresh() {
|
|
@@ -547,6 +584,30 @@ const formatGlobCollectionPattern = (collection) => {
|
|
|
547
584
|
};
|
|
548
585
|
class PluginProject extends Project {
|
|
549
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
|
+
}
|
|
550
611
|
}
|
|
551
612
|
const isPlugin = (cwd) => {
|
|
552
613
|
const packageJSONPath = path__default.default.join(cwd, PROJECT_PACKAGE_JSON);
|
|
@@ -561,10 +622,7 @@ const isPlugin = (cwd) => {
|
|
|
561
622
|
};
|
|
562
623
|
const projectFactory = (cwd) => {
|
|
563
624
|
fse__default.default.accessSync(cwd);
|
|
564
|
-
|
|
565
|
-
return new PluginProject(cwd);
|
|
566
|
-
}
|
|
567
|
-
return new AppProject(cwd);
|
|
625
|
+
return isPlugin(cwd) ? new PluginProject(cwd) : new AppProject(cwd);
|
|
568
626
|
};
|
|
569
627
|
const isPluginProject = (project) => {
|
|
570
628
|
return project instanceof PluginProject;
|
|
@@ -574,12 +632,12 @@ function assertPluginProject(project) {
|
|
|
574
632
|
throw new Error("Project is not a plugin");
|
|
575
633
|
}
|
|
576
634
|
}
|
|
577
|
-
const
|
|
635
|
+
const isApplicationProject = (project) => {
|
|
578
636
|
return project instanceof AppProject;
|
|
579
637
|
};
|
|
580
638
|
function assertAppProject(project) {
|
|
581
|
-
if (!
|
|
582
|
-
throw new Error("Project is not an
|
|
639
|
+
if (!isApplicationProject(project)) {
|
|
640
|
+
throw new Error("Project is not an application");
|
|
583
641
|
}
|
|
584
642
|
}
|
|
585
643
|
const index$a = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
@@ -587,7 +645,7 @@ const index$a = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePrope
|
|
|
587
645
|
assertAppProject,
|
|
588
646
|
assertPluginProject,
|
|
589
647
|
constants: constants$3,
|
|
590
|
-
|
|
648
|
+
isApplicationProject,
|
|
591
649
|
isPluginProject,
|
|
592
650
|
projectFactory
|
|
593
651
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
@@ -596,70 +654,33 @@ class UnexpectedError extends Error {
|
|
|
596
654
|
super("Unexpected Error");
|
|
597
655
|
}
|
|
598
656
|
}
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
const highlight = (arg) => chalk__default.default.bold.underline(arg);
|
|
620
|
-
const upgradeStep = (text, step) => {
|
|
621
|
-
return chalk__default.default.bold(`(${step[0]}/${step[1]}) ${text}...`);
|
|
622
|
-
};
|
|
623
|
-
const reports = (reports2) => {
|
|
624
|
-
const rows = reports2.map(({ codemod, report }, i) => {
|
|
625
|
-
const fIndex = chalk__default.default.grey(i);
|
|
626
|
-
const fVersion = chalk__default.default.magenta(codemod.version);
|
|
627
|
-
const fKind = chalk__default.default.yellow(codemod.kind);
|
|
628
|
-
const fFormattedTransformPath = chalk__default.default.cyan(codemod.format());
|
|
629
|
-
const fTimeElapsed = i === 0 ? `${report.timeElapsed}s ${chalk__default.default.dim.italic("(cold start)")}` : `${report.timeElapsed}s`;
|
|
630
|
-
const fAffected = report.ok > 0 ? chalk__default.default.green(report.ok) : chalk__default.default.grey(0);
|
|
631
|
-
const fUnchanged = report.ok === 0 ? chalk__default.default.red(report.nochange) : chalk__default.default.grey(report.nochange);
|
|
632
|
-
return [fIndex, fVersion, fKind, fFormattedTransformPath, fAffected, fUnchanged, fTimeElapsed];
|
|
633
|
-
});
|
|
634
|
-
const table = new CliTable3__default.default({
|
|
635
|
-
style: { compact: true },
|
|
636
|
-
head: [
|
|
637
|
-
chalk__default.default.bold.grey("N°"),
|
|
638
|
-
chalk__default.default.bold.magenta("Version"),
|
|
639
|
-
chalk__default.default.bold.yellow("Kind"),
|
|
640
|
-
chalk__default.default.bold.cyan("Name"),
|
|
641
|
-
chalk__default.default.bold.green("Affected"),
|
|
642
|
-
chalk__default.default.bold.red("Unchanged"),
|
|
643
|
-
chalk__default.default.bold.blue("Duration")
|
|
644
|
-
]
|
|
645
|
-
});
|
|
646
|
-
table.push(...rows);
|
|
647
|
-
return table.toString();
|
|
648
|
-
};
|
|
649
|
-
const durationMs = (elapsedMs) => {
|
|
650
|
-
const elapsedSeconds = (elapsedMs / ONE_SECOND_MS).toFixed(3);
|
|
651
|
-
return `${elapsedSeconds}s`;
|
|
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;
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
class AbortedError extends Error {
|
|
665
|
+
constructor(message = "Upgrade aborted") {
|
|
666
|
+
super(message);
|
|
667
|
+
}
|
|
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();
|
|
652
677
|
};
|
|
653
|
-
const index$
|
|
678
|
+
const index$9 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
654
679
|
__proto__: null,
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
transform,
|
|
660
|
-
upgradeStep,
|
|
661
|
-
version,
|
|
662
|
-
versionRange
|
|
680
|
+
AbortedError,
|
|
681
|
+
NPMCandidateNotFoundError,
|
|
682
|
+
UnexpectedError,
|
|
683
|
+
unknownToError
|
|
663
684
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
664
685
|
const CODEMOD_CODE_SUFFIX = "code";
|
|
665
686
|
const CODEMOD_JSON_SUFFIX = "json";
|
|
@@ -677,6 +698,7 @@ const constants$2 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineP
|
|
|
677
698
|
CODEMOD_JSON_SUFFIX
|
|
678
699
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
679
700
|
class Codemod {
|
|
701
|
+
uid;
|
|
680
702
|
kind;
|
|
681
703
|
version;
|
|
682
704
|
baseDirectory;
|
|
@@ -688,17 +710,49 @@ class Codemod {
|
|
|
688
710
|
this.baseDirectory = options.baseDirectory;
|
|
689
711
|
this.filename = options.filename;
|
|
690
712
|
this.path = path__default.default.join(this.baseDirectory, this.version.raw, this.filename);
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
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;
|
|
694
734
|
}
|
|
695
735
|
}
|
|
696
736
|
const codemodFactory = (options) => new Codemod(options);
|
|
697
|
-
const index$
|
|
737
|
+
const index$8 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
698
738
|
__proto__: null,
|
|
699
739
|
codemodFactory,
|
|
700
740
|
constants: constants$2
|
|
701
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" }));
|
|
702
756
|
class CodemodRepository {
|
|
703
757
|
groups;
|
|
704
758
|
versions;
|
|
@@ -717,29 +771,47 @@ class CodemodRepository {
|
|
|
717
771
|
count(version2) {
|
|
718
772
|
return this.findByVersion(version2).length;
|
|
719
773
|
}
|
|
720
|
-
|
|
721
|
-
return this.findByRange(range).length;
|
|
722
|
-
}
|
|
723
|
-
exists(version2) {
|
|
774
|
+
versionExists(version2) {
|
|
724
775
|
return version2.raw in this.groups;
|
|
725
776
|
}
|
|
726
|
-
|
|
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) {
|
|
727
786
|
const entries = Object.entries(this.groups);
|
|
728
|
-
return entries.filter(
|
|
787
|
+
return entries.filter(maybeFilterByRange).map(([version2, codemods]) => ({
|
|
729
788
|
version: semVerFactory(version2),
|
|
730
|
-
|
|
731
|
-
|
|
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
|
+
}
|
|
732
804
|
}
|
|
733
805
|
findByVersion(version2) {
|
|
734
806
|
const literalVersion = version2.raw;
|
|
735
|
-
const
|
|
736
|
-
return
|
|
807
|
+
const codemods = this.groups[literalVersion];
|
|
808
|
+
return codemods ?? [];
|
|
737
809
|
}
|
|
738
810
|
findAll() {
|
|
739
811
|
const entries = Object.entries(this.groups);
|
|
740
|
-
return entries.map(([version2,
|
|
812
|
+
return entries.map(([version2, codemods]) => ({
|
|
741
813
|
version: semVerFactory(version2),
|
|
742
|
-
codemods
|
|
814
|
+
codemods
|
|
743
815
|
}));
|
|
744
816
|
}
|
|
745
817
|
refreshAvailableVersions() {
|
|
@@ -771,19 +843,10 @@ const parseCodemodKindFromFilename = (filename) => {
|
|
|
771
843
|
assert__default.default(CODEMOD_ALLOWED_SUFFIXES.includes(kind));
|
|
772
844
|
return kind;
|
|
773
845
|
};
|
|
774
|
-
const codemodRepositoryFactory = (cwd) =>
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
"..",
|
|
779
|
-
"resources",
|
|
780
|
-
"codemods"
|
|
781
|
-
);
|
|
782
|
-
const constants$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
783
|
-
__proto__: null,
|
|
784
|
-
INTERNAL_CODEMODS_DIRECTORY
|
|
785
|
-
}, Symbol.toStringTag, { value: "Module" }));
|
|
786
|
-
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({
|
|
787
850
|
__proto__: null,
|
|
788
851
|
codemodRepositoryFactory,
|
|
789
852
|
constants: constants$1
|
|
@@ -817,40 +880,59 @@ class CodemodRunner {
|
|
|
817
880
|
this.isDry = enabled;
|
|
818
881
|
return this;
|
|
819
882
|
}
|
|
820
|
-
|
|
883
|
+
createRepository(codemodsDirectory) {
|
|
821
884
|
const repository = codemodRepositoryFactory(
|
|
822
885
|
codemodsDirectory ?? INTERNAL_CODEMODS_DIRECTORY
|
|
823
886
|
);
|
|
824
887
|
repository.refresh();
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
if (
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
} else {
|
|
832
|
-
this.logger?.debug(`Found no codemods to run`);
|
|
833
|
-
}
|
|
834
|
-
return successReport$1();
|
|
835
|
-
}
|
|
836
|
-
if (this.range) {
|
|
837
|
-
this.logger?.debug(
|
|
838
|
-
`Found codemods for ${highlight(versionedCodemods.length)} version(s) using ${this.range}`
|
|
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."
|
|
839
894
|
);
|
|
840
|
-
} else {
|
|
841
|
-
this.logger?.debug(`Found codemods for ${highlight(versionedCodemods.length)} version(s)`);
|
|
842
895
|
}
|
|
843
|
-
versionedCodemods.forEach(
|
|
844
|
-
({ version: version$1, codemods: codemods22 }) => this.logger?.debug(`- ${version(version$1)} (${codemods22.length})`)
|
|
845
|
-
);
|
|
846
|
-
const codemods2 = versionedCodemods.map(({ codemods: codemods22 }) => codemods22).flat();
|
|
847
896
|
try {
|
|
848
|
-
const reports$1 = await this.project.runCodemods(
|
|
849
|
-
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();
|
|
850
906
|
} catch (e) {
|
|
851
907
|
return erroredReport$1(unknownToError(e));
|
|
852
908
|
}
|
|
853
|
-
|
|
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);
|
|
854
936
|
}
|
|
855
937
|
}
|
|
856
938
|
const codemodRunnerFactory = (project, range) => {
|
|
@@ -877,6 +959,15 @@ class Upgrader {
|
|
|
877
959
|
this.logger = null;
|
|
878
960
|
this.confirmationCallback = null;
|
|
879
961
|
}
|
|
962
|
+
getNPMPackage() {
|
|
963
|
+
return this.npmPackage;
|
|
964
|
+
}
|
|
965
|
+
getProject() {
|
|
966
|
+
return this.project;
|
|
967
|
+
}
|
|
968
|
+
getTarget() {
|
|
969
|
+
return semVerFactory(this.target.raw);
|
|
970
|
+
}
|
|
880
971
|
setRequirements(requirements) {
|
|
881
972
|
this.requirements = requirements;
|
|
882
973
|
return this;
|
|
@@ -889,7 +980,7 @@ class Upgrader {
|
|
|
889
980
|
this.codemodsTarget = semVerFactory(
|
|
890
981
|
`${this.target.major}.${this.target.minor}.${this.target.patch}`
|
|
891
982
|
);
|
|
892
|
-
this.logger?.debug(
|
|
983
|
+
this.logger?.debug?.(
|
|
893
984
|
`The codemods target has been synced with the upgrade target. The codemod runner will now look for ${version(
|
|
894
985
|
this.codemodsTarget
|
|
895
986
|
)}`
|
|
@@ -898,7 +989,7 @@ class Upgrader {
|
|
|
898
989
|
}
|
|
899
990
|
overrideCodemodsTarget(target) {
|
|
900
991
|
this.codemodsTarget = target;
|
|
901
|
-
this.logger?.debug(
|
|
992
|
+
this.logger?.debug?.(
|
|
902
993
|
`Overriding the codemods target. The codemod runner will now look for ${version(target)}`
|
|
903
994
|
);
|
|
904
995
|
return this;
|
|
@@ -918,46 +1009,52 @@ class Upgrader {
|
|
|
918
1009
|
addRequirement(requirement) {
|
|
919
1010
|
this.requirements.push(requirement);
|
|
920
1011
|
const fRequired = requirement.isRequired ? "(required)" : "(optional)";
|
|
921
|
-
this.logger?.debug(
|
|
1012
|
+
this.logger?.debug?.(
|
|
922
1013
|
`Added a new requirement to the upgrade: ${highlight(requirement.name)} ${fRequired}`
|
|
923
1014
|
);
|
|
924
1015
|
return this;
|
|
925
1016
|
}
|
|
926
1017
|
async upgrade() {
|
|
927
|
-
this.logger?.info(
|
|
1018
|
+
this.logger?.info?.(
|
|
928
1019
|
`Upgrading from ${version(this.project.strapiVersion)} to ${version(this.target)}`
|
|
929
1020
|
);
|
|
930
1021
|
if (this.isDry) {
|
|
931
|
-
this.logger?.warn(
|
|
1022
|
+
this.logger?.warn?.(
|
|
932
1023
|
"Running the upgrade in dry mode. No files will be modified during the process."
|
|
933
1024
|
);
|
|
934
1025
|
}
|
|
935
1026
|
const range = rangeFromVersions(this.project.strapiVersion, this.target);
|
|
936
1027
|
const codemodsRange = rangeFromVersions(this.project.strapiVersion, this.codemodsTarget);
|
|
937
1028
|
const npmVersionsMatches = this.npmPackage?.findVersionsInRange(range) ?? [];
|
|
938
|
-
this.logger?.debug(
|
|
1029
|
+
this.logger?.debug?.(
|
|
939
1030
|
`Found ${highlight(npmVersionsMatches.length)} versions satisfying ${versionRange(range)}`
|
|
940
1031
|
);
|
|
941
1032
|
try {
|
|
942
|
-
this.logger?.info(upgradeStep("Checking requirement", [1, 4]));
|
|
1033
|
+
this.logger?.info?.(upgradeStep("Checking requirement", [1, 4]));
|
|
943
1034
|
await this.checkRequirements(this.requirements, {
|
|
944
1035
|
npmVersionsMatches,
|
|
945
1036
|
project: this.project,
|
|
946
1037
|
target: this.target
|
|
947
1038
|
});
|
|
948
|
-
this.logger?.info(upgradeStep("Applying the latest code modifications", [2, 4]));
|
|
1039
|
+
this.logger?.info?.(upgradeStep("Applying the latest code modifications", [2, 4]));
|
|
949
1040
|
await this.runCodemods(codemodsRange);
|
|
950
|
-
this.logger?.debug("Refreshing project information...");
|
|
1041
|
+
this.logger?.debug?.("Refreshing project information...");
|
|
951
1042
|
this.project.refresh();
|
|
952
|
-
this.logger?.info(upgradeStep("Upgrading Strapi dependencies", [3, 4]));
|
|
1043
|
+
this.logger?.info?.(upgradeStep("Upgrading Strapi dependencies", [3, 4]));
|
|
953
1044
|
await this.updateDependencies();
|
|
954
|
-
this.logger?.info(upgradeStep("Installing dependencies", [4, 4]));
|
|
1045
|
+
this.logger?.info?.(upgradeStep("Installing dependencies", [4, 4]));
|
|
955
1046
|
await this.installDependencies();
|
|
956
1047
|
} catch (e) {
|
|
957
1048
|
return erroredReport(unknownToError(e));
|
|
958
1049
|
}
|
|
959
1050
|
return successReport();
|
|
960
1051
|
}
|
|
1052
|
+
async confirm(message) {
|
|
1053
|
+
if (typeof this.confirmationCallback !== "function") {
|
|
1054
|
+
return true;
|
|
1055
|
+
}
|
|
1056
|
+
return this.confirmationCallback(message);
|
|
1057
|
+
}
|
|
961
1058
|
async checkRequirements(requirements, context) {
|
|
962
1059
|
for (const requirement of requirements) {
|
|
963
1060
|
const { pass, error } = await requirement.test(context);
|
|
@@ -984,7 +1081,7 @@ class Upgrader {
|
|
|
984
1081
|
if (requirement.isRequired) {
|
|
985
1082
|
throw error;
|
|
986
1083
|
}
|
|
987
|
-
this.logger?.warn(warningMessage);
|
|
1084
|
+
this.logger?.warn?.(warningMessage);
|
|
988
1085
|
const response = await this.confirmationCallback?.(confirmationMessage);
|
|
989
1086
|
if (!response) {
|
|
990
1087
|
throw error;
|
|
@@ -995,9 +1092,11 @@ class Upgrader {
|
|
|
995
1092
|
const json = createJSONTransformAPI(packageJSON);
|
|
996
1093
|
const dependencies = json.get("dependencies", {});
|
|
997
1094
|
const strapiDependencies = this.getScopedStrapiDependencies(dependencies);
|
|
998
|
-
this.logger?.debug(
|
|
1095
|
+
this.logger?.debug?.(
|
|
1096
|
+
`Found ${highlight(strapiDependencies.length)} dependency(ies) to update`
|
|
1097
|
+
);
|
|
999
1098
|
strapiDependencies.forEach(
|
|
1000
|
-
(dependency) => this.logger?.debug(`- ${dependency[0]} (${dependency[1]} -> ${this.target})`)
|
|
1099
|
+
(dependency) => this.logger?.debug?.(`- ${dependency[0]} (${dependency[1]} -> ${this.target})`)
|
|
1001
1100
|
);
|
|
1002
1101
|
if (strapiDependencies.length === 0) {
|
|
1003
1102
|
return;
|
|
@@ -1005,7 +1104,7 @@ class Upgrader {
|
|
|
1005
1104
|
strapiDependencies.forEach(([name]) => json.set(`dependencies.${name}`, this.target.raw));
|
|
1006
1105
|
const updatedPackageJSON = json.root();
|
|
1007
1106
|
if (this.isDry) {
|
|
1008
|
-
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")})`);
|
|
1009
1108
|
return;
|
|
1010
1109
|
}
|
|
1011
1110
|
await saveJSON(packageJSONPath, updatedPackageJSON);
|
|
@@ -1025,9 +1124,9 @@ class Upgrader {
|
|
|
1025
1124
|
async installDependencies() {
|
|
1026
1125
|
const projectPath = this.project.cwd;
|
|
1027
1126
|
const packageManagerName = await utils.packageManager.getPreferred(projectPath);
|
|
1028
|
-
this.logger?.debug(`Using ${highlight(packageManagerName)} as package manager`);
|
|
1127
|
+
this.logger?.debug?.(`Using ${highlight(packageManagerName)} as package manager`);
|
|
1029
1128
|
if (this.isDry) {
|
|
1030
|
-
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")})`);
|
|
1031
1130
|
return;
|
|
1032
1131
|
}
|
|
1033
1132
|
await utils.packageManager.installDependencies(projectPath, packageManagerName, {
|
|
@@ -1046,23 +1145,28 @@ class Upgrader {
|
|
|
1046
1145
|
}
|
|
1047
1146
|
const resolveNPMTarget = (project, target, npmPackage) => {
|
|
1048
1147
|
if (isSemverInstance(target)) {
|
|
1049
|
-
|
|
1148
|
+
const version2 = npmPackage.findVersion(target);
|
|
1149
|
+
if (!version2) {
|
|
1150
|
+
throw new NPMCandidateNotFoundError(target);
|
|
1151
|
+
}
|
|
1152
|
+
return version2;
|
|
1050
1153
|
}
|
|
1051
1154
|
if (isSemVerReleaseType(target)) {
|
|
1052
1155
|
const range = rangeFromVersions(project.strapiVersion, target);
|
|
1053
1156
|
const npmVersionsMatches = npmPackage.findVersionsInRange(range);
|
|
1054
|
-
|
|
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;
|
|
1055
1162
|
}
|
|
1056
|
-
|
|
1163
|
+
throw new NPMCandidateNotFoundError(target);
|
|
1057
1164
|
};
|
|
1058
1165
|
const upgraderFactory = (project, target, npmPackage) => {
|
|
1059
|
-
const
|
|
1060
|
-
|
|
1061
|
-
throw new Error(`Couldn't find a matching version in the NPM registry for "${target}"`);
|
|
1062
|
-
}
|
|
1063
|
-
const semverTarget = semVerFactory(targetedNPMVersion.version);
|
|
1166
|
+
const npmTarget = resolveNPMTarget(project, target, npmPackage);
|
|
1167
|
+
const semverTarget = semVerFactory(npmTarget.version);
|
|
1064
1168
|
if (semver__default.default.eq(semverTarget, project.strapiVersion)) {
|
|
1065
|
-
throw new Error(`The project is already
|
|
1169
|
+
throw new Error(`The project is already using v${semverTarget}`);
|
|
1066
1170
|
}
|
|
1067
1171
|
return new Upgrader(project, semverTarget, npmPackage);
|
|
1068
1172
|
};
|
|
@@ -1073,101 +1177,205 @@ const constants = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePro
|
|
|
1073
1177
|
__proto__: null,
|
|
1074
1178
|
STRAPI_PACKAGE_NAME
|
|
1075
1179
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
1076
|
-
const index$
|
|
1180
|
+
const index$6 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
1077
1181
|
__proto__: null,
|
|
1078
1182
|
constants,
|
|
1079
1183
|
upgraderFactory
|
|
1080
1184
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
1081
|
-
|
|
1082
|
-
|
|
1185
|
+
class Requirement {
|
|
1186
|
+
isRequired;
|
|
1083
1187
|
name;
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
constructor(name) {
|
|
1188
|
+
testCallback;
|
|
1189
|
+
children;
|
|
1190
|
+
constructor(name, testCallback, isRequired) {
|
|
1087
1191
|
this.name = name;
|
|
1088
|
-
this.
|
|
1089
|
-
this.
|
|
1192
|
+
this.testCallback = testCallback;
|
|
1193
|
+
this.isRequired = isRequired ?? true;
|
|
1194
|
+
this.children = [];
|
|
1090
1195
|
}
|
|
1091
|
-
|
|
1092
|
-
|
|
1196
|
+
setChildren(children) {
|
|
1197
|
+
this.children = children;
|
|
1198
|
+
return this;
|
|
1093
1199
|
}
|
|
1094
|
-
|
|
1095
|
-
|
|
1200
|
+
addChild(child) {
|
|
1201
|
+
this.children.push(child);
|
|
1202
|
+
return this;
|
|
1096
1203
|
}
|
|
1097
|
-
|
|
1098
|
-
this.
|
|
1099
|
-
|
|
1204
|
+
asOptional() {
|
|
1205
|
+
const newInstance = requirementFactory(this.name, this.testCallback, false);
|
|
1206
|
+
newInstance.setChildren(this.children);
|
|
1207
|
+
return newInstance;
|
|
1100
1208
|
}
|
|
1101
|
-
|
|
1102
|
-
this.
|
|
1103
|
-
|
|
1209
|
+
asRequired() {
|
|
1210
|
+
const newInstance = requirementFactory(this.name, this.testCallback, true);
|
|
1211
|
+
newInstance.setChildren(this.children);
|
|
1212
|
+
return newInstance;
|
|
1104
1213
|
}
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
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
|
+
}
|
|
1108
1227
|
}
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
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
|
+
}
|
|
1112
1245
|
}
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
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
|
+
}
|
|
1118
1262
|
}
|
|
1119
|
-
|
|
1120
|
-
|
|
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
|
+
}
|
|
1121
1274
|
}
|
|
1122
|
-
|
|
1123
|
-
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
|
+
};
|
|
1124
1330
|
const upgrade = async (options) => {
|
|
1125
1331
|
const timer = timerFactory();
|
|
1126
1332
|
const { logger, codemodsTarget } = options;
|
|
1127
1333
|
const cwd = path__default.default.resolve(options.cwd ?? process.cwd());
|
|
1128
1334
|
const project = projectFactory(cwd);
|
|
1129
|
-
|
|
1335
|
+
logger.debug(projectDetails(project));
|
|
1336
|
+
if (!isApplicationProject(project)) {
|
|
1130
1337
|
throw new Error(
|
|
1131
1338
|
`The "${options.target}" upgrade can only be run on a Strapi project; for plugins, please use "codemods".`
|
|
1132
1339
|
);
|
|
1133
1340
|
}
|
|
1341
|
+
logger.debug(
|
|
1342
|
+
`Application: VERSION=${version(project.packageJSON.version)}; STRAPI_VERSION=${version(project.strapiVersion)}`
|
|
1343
|
+
);
|
|
1134
1344
|
const npmPackage = npmPackageFactory(STRAPI_PACKAGE_NAME);
|
|
1135
1345
|
await npmPackage.refresh();
|
|
1136
1346
|
const upgrader = upgraderFactory(project, options.target, npmPackage).dry(options.dry ?? false).onConfirm(options.confirm ?? null).setLogger(logger);
|
|
1137
1347
|
if (codemodsTarget !== void 0) {
|
|
1138
1348
|
upgrader.overrideCodemodsTarget(codemodsTarget);
|
|
1139
1349
|
}
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
}
|
|
1143
|
-
upgrader.addRequirement(REQUIRE_GIT.asOptional());
|
|
1350
|
+
await runUpgradePrompts(upgrader, options);
|
|
1351
|
+
addUpgradeRequirements(upgrader, options);
|
|
1144
1352
|
const upgradeReport = await upgrader.upgrade();
|
|
1145
1353
|
if (!upgradeReport.success) {
|
|
1146
1354
|
throw upgradeReport.error;
|
|
1147
1355
|
}
|
|
1148
1356
|
timer.stop();
|
|
1149
|
-
logger.info(`Completed in ${durationMs(timer.elapsedMs)}`);
|
|
1357
|
+
logger.info(`Completed in ${durationMs(timer.elapsedMs)}ms`);
|
|
1150
1358
|
};
|
|
1151
|
-
const
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
const cwd = path__default.default.resolve(options.cwd ?? process.cwd());
|
|
1155
|
-
const project = projectFactory(cwd);
|
|
1156
|
-
const range = isAppProject(project) ? getRangeFromTarget(project.strapiVersion, options.target) : void 0;
|
|
1157
|
-
const codemodRunner = codemodRunnerFactory(project, range).dry(options.dry ?? false).onSelectCodemods(options.selectCodemods ?? null).setLogger(logger);
|
|
1158
|
-
const executionReport = await codemodRunner.run();
|
|
1159
|
-
if (!executionReport.success) {
|
|
1160
|
-
throw executionReport.error;
|
|
1359
|
+
const runUpgradePrompts = async (upgrader, options) => {
|
|
1360
|
+
if (options.target === ReleaseType.Latest) {
|
|
1361
|
+
await latest(upgrader, options);
|
|
1161
1362
|
}
|
|
1162
|
-
timer.stop();
|
|
1163
|
-
logger.info(`Completed in ${timer.elapsedMs}`);
|
|
1164
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());
|
|
1165
1371
|
const getRangeFromTarget = (currentVersion, target) => {
|
|
1166
1372
|
if (isSemverInstance(target)) {
|
|
1167
1373
|
return rangeFactory(target);
|
|
1168
1374
|
}
|
|
1169
1375
|
const { major, minor, patch } = currentVersion;
|
|
1170
1376
|
switch (target) {
|
|
1377
|
+
case ReleaseType.Latest:
|
|
1378
|
+
throw new Error("Can't use <latest> to create a codemods range: not implemented");
|
|
1171
1379
|
case ReleaseType.Major:
|
|
1172
1380
|
return rangeFactory(`${major}`);
|
|
1173
1381
|
case ReleaseType.Minor:
|
|
@@ -1178,9 +1386,60 @@ const getRangeFromTarget = (currentVersion, target) => {
|
|
|
1178
1386
|
throw new Error(`Invalid target set: ${target}`);
|
|
1179
1387
|
}
|
|
1180
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
|
+
};
|
|
1181
1439
|
const index$4 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
1182
1440
|
__proto__: null,
|
|
1183
|
-
|
|
1441
|
+
listCodemods,
|
|
1442
|
+
runCodemods,
|
|
1184
1443
|
upgrade
|
|
1185
1444
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
1186
1445
|
class Logger {
|
|
@@ -1274,18 +1533,18 @@ const index$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePrope
|
|
|
1274
1533
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
1275
1534
|
const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
1276
1535
|
__proto__: null,
|
|
1277
|
-
codemod: index$
|
|
1278
|
-
codemodRepository: index$
|
|
1536
|
+
codemod: index$8,
|
|
1537
|
+
codemodRepository: index$7,
|
|
1279
1538
|
error: index$9,
|
|
1280
|
-
f: index$
|
|
1539
|
+
f: index$f,
|
|
1281
1540
|
fileScanner: index$d,
|
|
1282
1541
|
logger: index$3,
|
|
1283
1542
|
project: index$a,
|
|
1284
1543
|
report: index$2,
|
|
1285
|
-
requirement: index$
|
|
1544
|
+
requirement: index$5,
|
|
1286
1545
|
runner: index$1,
|
|
1287
|
-
timer: index$
|
|
1288
|
-
upgrader: index$
|
|
1546
|
+
timer: index$g,
|
|
1547
|
+
upgrader: index$6,
|
|
1289
1548
|
version: index$e
|
|
1290
1549
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
1291
1550
|
exports.modules = index;
|