@strapi/upgrade 0.0.0-experimental.e60ec1829240dae21c1e1d29076681c322288813 → 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 +444 -318
- package/dist/cli.js.map +1 -1
- package/dist/index.js +467 -344
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +463 -341
- package/dist/index.mjs.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 +2 -1
- 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 +16 -2
- package/dist/modules/project/project.d.ts.map +1 -1
- package/dist/modules/project/types.d.ts +3 -0
- package/dist/modules/project/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 +4 -0
- package/dist/modules/upgrader/upgrader.d.ts.map +1 -1
- 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/utils.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 +8 -8
- 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/sqlite3-to-better-sqlite3.json.ts +0 -1
- 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/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");
|
|
@@ -281,13 +218,57 @@ const index$e = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePrope
|
|
|
281
218
|
rangeFromVersions,
|
|
282
219
|
semVerFactory
|
|
283
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);
|
|
284
263
|
class FileScanner {
|
|
285
264
|
cwd;
|
|
286
265
|
constructor(cwd) {
|
|
287
266
|
this.cwd = cwd;
|
|
288
267
|
}
|
|
289
268
|
scan(patterns) {
|
|
290
|
-
const filenames =
|
|
269
|
+
const filenames = fastglob__default.default.sync(patterns, {
|
|
270
|
+
cwd: this.cwd
|
|
271
|
+
});
|
|
291
272
|
return filenames.map((filename) => path__default.default.join(this.cwd, filename));
|
|
292
273
|
}
|
|
293
274
|
}
|
|
@@ -325,6 +306,46 @@ const index$c = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePrope
|
|
|
325
306
|
__proto__: null,
|
|
326
307
|
codeRunnerFactory
|
|
327
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
|
+
};
|
|
328
349
|
const transformJSON = async (codemodPath, paths, config) => {
|
|
329
350
|
const { dry } = config;
|
|
330
351
|
const startTime = process.hrtime();
|
|
@@ -336,7 +357,11 @@ const transformJSON = async (codemodPath, paths, config) => {
|
|
|
336
357
|
timeElapsed: "",
|
|
337
358
|
stats: {}
|
|
338
359
|
};
|
|
339
|
-
const esbuildOptions = {
|
|
360
|
+
const esbuildOptions = {
|
|
361
|
+
extensions: [".js", ".mjs", ".ts"],
|
|
362
|
+
hookIgnoreNodeModules: false,
|
|
363
|
+
hookMatcher: fp.isEqual(codemodPath)
|
|
364
|
+
};
|
|
340
365
|
const { unregister } = node.register(esbuildOptions);
|
|
341
366
|
const module2 = require(codemodPath);
|
|
342
367
|
unregister();
|
|
@@ -381,8 +406,10 @@ const index$b = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePrope
|
|
|
381
406
|
jsonRunnerFactory
|
|
382
407
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
383
408
|
const PROJECT_PACKAGE_JSON = "package.json";
|
|
384
|
-
const
|
|
385
|
-
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 = [
|
|
386
413
|
// Source files
|
|
387
414
|
"js",
|
|
388
415
|
"mjs",
|
|
@@ -391,22 +418,19 @@ const PROJECT_DEFAULT_CODE_EXTENSIONS = [
|
|
|
391
418
|
"jsx",
|
|
392
419
|
"tsx"
|
|
393
420
|
];
|
|
394
|
-
const
|
|
395
|
-
const
|
|
396
|
-
...PROJECT_DEFAULT_CODE_EXTENSIONS,
|
|
397
|
-
...PROJECT_DEFAULT_JSON_EXTENSIONS
|
|
398
|
-
];
|
|
399
|
-
const PROJECT_DEFAULT_PATTERNS = ["package.json"];
|
|
421
|
+
const PROJECT_JSON_EXTENSIONS = ["json"];
|
|
422
|
+
const PROJECT_ALLOWED_EXTENSIONS = [...PROJECT_CODE_EXTENSIONS, ...PROJECT_JSON_EXTENSIONS];
|
|
400
423
|
const SCOPED_STRAPI_PACKAGE_PREFIX = "@strapi/";
|
|
401
424
|
const STRAPI_DEPENDENCY_NAME = `${SCOPED_STRAPI_PACKAGE_PREFIX}strapi`;
|
|
402
425
|
const constants$3 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
403
426
|
__proto__: null,
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
PROJECT_DEFAULT_PATTERNS,
|
|
427
|
+
PROJECT_ALLOWED_EXTENSIONS,
|
|
428
|
+
PROJECT_APP_ALLOWED_ROOT_PATHS,
|
|
429
|
+
PROJECT_CODE_EXTENSIONS,
|
|
430
|
+
PROJECT_JSON_EXTENSIONS,
|
|
409
431
|
PROJECT_PACKAGE_JSON,
|
|
432
|
+
PROJECT_PLUGIN_ALLOWED_ROOT_PATHS,
|
|
433
|
+
PROJECT_PLUGIN_ROOT_FILES,
|
|
410
434
|
SCOPED_STRAPI_PACKAGE_PREFIX,
|
|
411
435
|
STRAPI_DEPENDENCY_NAME
|
|
412
436
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
@@ -416,11 +440,13 @@ class Project {
|
|
|
416
440
|
files;
|
|
417
441
|
packageJSONPath;
|
|
418
442
|
packageJSON;
|
|
419
|
-
|
|
443
|
+
paths;
|
|
444
|
+
constructor(cwd, config) {
|
|
420
445
|
if (!fse__default.default.pathExistsSync(cwd)) {
|
|
421
446
|
throw new Error(`ENOENT: no such file or directory, access '${cwd}'`);
|
|
422
447
|
}
|
|
423
448
|
this.cwd = cwd;
|
|
449
|
+
this.paths = config.paths;
|
|
424
450
|
this.refresh();
|
|
425
451
|
}
|
|
426
452
|
getFilesByExtensions(extensions) {
|
|
@@ -448,12 +474,8 @@ class Project {
|
|
|
448
474
|
return reports2;
|
|
449
475
|
}
|
|
450
476
|
createProjectCodemodsRunners(dry = false) {
|
|
451
|
-
const jsonExtensions =
|
|
452
|
-
|
|
453
|
-
);
|
|
454
|
-
const codeExtensions = PROJECT_DEFAULT_CODE_EXTENSIONS.map(
|
|
455
|
-
(ext) => `.${ext}`
|
|
456
|
-
);
|
|
477
|
+
const jsonExtensions = PROJECT_JSON_EXTENSIONS.map((ext) => `.${ext}`);
|
|
478
|
+
const codeExtensions = PROJECT_CODE_EXTENSIONS.map((ext) => `.${ext}`);
|
|
457
479
|
const jsonFiles = this.getFilesByExtensions(jsonExtensions);
|
|
458
480
|
const codeFiles = this.getFilesByExtensions(codeExtensions);
|
|
459
481
|
const codeRunner = codeRunnerFactory(codeFiles, {
|
|
@@ -461,7 +483,7 @@ class Project {
|
|
|
461
483
|
parser: "ts",
|
|
462
484
|
runInBand: true,
|
|
463
485
|
babel: true,
|
|
464
|
-
extensions:
|
|
486
|
+
extensions: PROJECT_CODE_EXTENSIONS.join(","),
|
|
465
487
|
// Don't output any log coming from the runner
|
|
466
488
|
print: false,
|
|
467
489
|
silent: true,
|
|
@@ -482,23 +504,32 @@ class Project {
|
|
|
482
504
|
this.packageJSON = JSON.parse(packageJSONBuffer.toString());
|
|
483
505
|
}
|
|
484
506
|
refreshProjectFiles() {
|
|
485
|
-
const allowedRootPaths = formatGlobCollectionPattern(
|
|
486
|
-
PROJECT_DEFAULT_ALLOWED_ROOT_PATHS
|
|
487
|
-
);
|
|
488
|
-
const allowedExtensions = formatGlobCollectionPattern(
|
|
489
|
-
PROJECT_DEFAULT_ALLOWED_EXTENSIONS
|
|
490
|
-
);
|
|
491
|
-
const projectFilesPattern = `./${allowedRootPaths}/**/*.${allowedExtensions}`;
|
|
492
|
-
const patterns = [projectFilesPattern, ...PROJECT_DEFAULT_PATTERNS];
|
|
493
507
|
const scanner = fileScannerFactory(this.cwd);
|
|
494
|
-
this.files = scanner.scan(
|
|
508
|
+
this.files = scanner.scan(this.paths);
|
|
495
509
|
}
|
|
496
510
|
}
|
|
497
511
|
class AppProject extends Project {
|
|
498
512
|
strapiVersion;
|
|
499
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
|
+
}
|
|
500
531
|
constructor(cwd) {
|
|
501
|
-
super(cwd);
|
|
532
|
+
super(cwd, { paths: AppProject.paths });
|
|
502
533
|
this.refreshStrapiVersion();
|
|
503
534
|
}
|
|
504
535
|
refresh() {
|
|
@@ -553,6 +584,30 @@ const formatGlobCollectionPattern = (collection) => {
|
|
|
553
584
|
};
|
|
554
585
|
class PluginProject extends Project {
|
|
555
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
|
+
}
|
|
556
611
|
}
|
|
557
612
|
const isPlugin = (cwd) => {
|
|
558
613
|
const packageJSONPath = path__default.default.join(cwd, PROJECT_PACKAGE_JSON);
|
|
@@ -567,10 +622,7 @@ const isPlugin = (cwd) => {
|
|
|
567
622
|
};
|
|
568
623
|
const projectFactory = (cwd) => {
|
|
569
624
|
fse__default.default.accessSync(cwd);
|
|
570
|
-
|
|
571
|
-
return new PluginProject(cwd);
|
|
572
|
-
}
|
|
573
|
-
return new AppProject(cwd);
|
|
625
|
+
return isPlugin(cwd) ? new PluginProject(cwd) : new AppProject(cwd);
|
|
574
626
|
};
|
|
575
627
|
const isPluginProject = (project) => {
|
|
576
628
|
return project instanceof PluginProject;
|
|
@@ -602,6 +654,18 @@ class UnexpectedError extends Error {
|
|
|
602
654
|
super("Unexpected Error");
|
|
603
655
|
}
|
|
604
656
|
}
|
|
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
|
+
}
|
|
605
669
|
const unknownToError = (e) => {
|
|
606
670
|
if (e instanceof Error) {
|
|
607
671
|
return e;
|
|
@@ -613,89 +677,11 @@ const unknownToError = (e) => {
|
|
|
613
677
|
};
|
|
614
678
|
const index$9 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
615
679
|
__proto__: null,
|
|
680
|
+
AbortedError,
|
|
681
|
+
NPMCandidateNotFoundError,
|
|
616
682
|
UnexpectedError,
|
|
617
683
|
unknownToError
|
|
618
684
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
619
|
-
const path = (path2) => chalk__default.default.blue(path2);
|
|
620
|
-
const version = (version2) => {
|
|
621
|
-
return chalk__default.default.italic.yellow(`v${version2}`);
|
|
622
|
-
};
|
|
623
|
-
const codemodUID = (uid) => {
|
|
624
|
-
return chalk__default.default.bold.cyan(uid);
|
|
625
|
-
};
|
|
626
|
-
const projectType = (type) => chalk__default.default.cyan(type);
|
|
627
|
-
const versionRange = (range) => chalk__default.default.italic.yellow(range.raw);
|
|
628
|
-
const transform = (transformFilePath) => chalk__default.default.cyan(transformFilePath);
|
|
629
|
-
const highlight = (arg) => chalk__default.default.bold.underline(arg);
|
|
630
|
-
const upgradeStep = (text, step) => {
|
|
631
|
-
return chalk__default.default.bold(`(${step[0]}/${step[1]}) ${text}...`);
|
|
632
|
-
};
|
|
633
|
-
const reports = (reports2) => {
|
|
634
|
-
const rows = reports2.map(({ codemod, report }, i) => {
|
|
635
|
-
const fIndex = chalk__default.default.grey(i);
|
|
636
|
-
const fVersion = chalk__default.default.magenta(codemod.version);
|
|
637
|
-
const fKind = chalk__default.default.yellow(codemod.kind);
|
|
638
|
-
const fFormattedTransformPath = chalk__default.default.cyan(codemod.format());
|
|
639
|
-
const fTimeElapsed = i === 0 ? `${report.timeElapsed}s ${chalk__default.default.dim.italic("(cold start)")}` : `${report.timeElapsed}s`;
|
|
640
|
-
const fAffected = report.ok > 0 ? chalk__default.default.green(report.ok) : chalk__default.default.grey(0);
|
|
641
|
-
const fUnchanged = report.ok === 0 ? chalk__default.default.red(report.nochange) : chalk__default.default.grey(report.nochange);
|
|
642
|
-
return [fIndex, fVersion, fKind, fFormattedTransformPath, fAffected, fUnchanged, fTimeElapsed];
|
|
643
|
-
});
|
|
644
|
-
const table = new CliTable3__default.default({
|
|
645
|
-
style: { compact: true },
|
|
646
|
-
head: [
|
|
647
|
-
chalk__default.default.bold.grey("N°"),
|
|
648
|
-
chalk__default.default.bold.magenta("Version"),
|
|
649
|
-
chalk__default.default.bold.yellow("Kind"),
|
|
650
|
-
chalk__default.default.bold.cyan("Name"),
|
|
651
|
-
chalk__default.default.bold.green("Affected"),
|
|
652
|
-
chalk__default.default.bold.red("Unchanged"),
|
|
653
|
-
chalk__default.default.bold.blue("Duration")
|
|
654
|
-
]
|
|
655
|
-
});
|
|
656
|
-
table.push(...rows);
|
|
657
|
-
return table.toString();
|
|
658
|
-
};
|
|
659
|
-
const codemodList = (codemods) => {
|
|
660
|
-
const rows = codemods.map((codemod, index2) => {
|
|
661
|
-
const fIndex = chalk__default.default.grey(index2);
|
|
662
|
-
const fVersion = chalk__default.default.magenta(codemod.version);
|
|
663
|
-
const fKind = chalk__default.default.yellow(codemod.kind);
|
|
664
|
-
const fName = chalk__default.default.blue(codemod.format());
|
|
665
|
-
const fUID = codemodUID(codemod.uid);
|
|
666
|
-
return [fIndex, fVersion, fKind, fName, fUID];
|
|
667
|
-
});
|
|
668
|
-
const table = new CliTable3__default.default({
|
|
669
|
-
style: { compact: true },
|
|
670
|
-
head: [
|
|
671
|
-
chalk__default.default.bold.grey("N°"),
|
|
672
|
-
chalk__default.default.bold.magenta("Version"),
|
|
673
|
-
chalk__default.default.bold.yellow("Kind"),
|
|
674
|
-
chalk__default.default.bold.blue("Name"),
|
|
675
|
-
chalk__default.default.bold.cyan("UID")
|
|
676
|
-
]
|
|
677
|
-
});
|
|
678
|
-
table.push(...rows);
|
|
679
|
-
return table.toString();
|
|
680
|
-
};
|
|
681
|
-
const durationMs = (elapsedMs) => {
|
|
682
|
-
const elapsedSeconds = (elapsedMs / ONE_SECOND_MS).toFixed(3);
|
|
683
|
-
return `${elapsedSeconds}s`;
|
|
684
|
-
};
|
|
685
|
-
const index$8 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
686
|
-
__proto__: null,
|
|
687
|
-
codemodList,
|
|
688
|
-
codemodUID,
|
|
689
|
-
durationMs,
|
|
690
|
-
highlight,
|
|
691
|
-
path,
|
|
692
|
-
projectType,
|
|
693
|
-
reports,
|
|
694
|
-
transform,
|
|
695
|
-
upgradeStep,
|
|
696
|
-
version,
|
|
697
|
-
versionRange
|
|
698
|
-
}, Symbol.toStringTag, { value: "Module" }));
|
|
699
685
|
const CODEMOD_CODE_SUFFIX = "code";
|
|
700
686
|
const CODEMOD_JSON_SUFFIX = "json";
|
|
701
687
|
const CODEMOD_ALLOWED_SUFFIXES = [CODEMOD_CODE_SUFFIX, CODEMOD_JSON_SUFFIX];
|
|
@@ -748,7 +734,7 @@ class Codemod {
|
|
|
748
734
|
}
|
|
749
735
|
}
|
|
750
736
|
const codemodFactory = (options) => new Codemod(options);
|
|
751
|
-
const index$
|
|
737
|
+
const index$8 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
752
738
|
__proto__: null,
|
|
753
739
|
codemodFactory,
|
|
754
740
|
constants: constants$2
|
|
@@ -860,7 +846,7 @@ const parseCodemodKindFromFilename = (filename) => {
|
|
|
860
846
|
const codemodRepositoryFactory = (cwd = INTERNAL_CODEMODS_DIRECTORY) => {
|
|
861
847
|
return new CodemodRepository(cwd);
|
|
862
848
|
};
|
|
863
|
-
const index$
|
|
849
|
+
const index$7 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
864
850
|
__proto__: null,
|
|
865
851
|
codemodRepositoryFactory,
|
|
866
852
|
constants: constants$1
|
|
@@ -973,6 +959,15 @@ class Upgrader {
|
|
|
973
959
|
this.logger = null;
|
|
974
960
|
this.confirmationCallback = null;
|
|
975
961
|
}
|
|
962
|
+
getNPMPackage() {
|
|
963
|
+
return this.npmPackage;
|
|
964
|
+
}
|
|
965
|
+
getProject() {
|
|
966
|
+
return this.project;
|
|
967
|
+
}
|
|
968
|
+
getTarget() {
|
|
969
|
+
return semVerFactory(this.target.raw);
|
|
970
|
+
}
|
|
976
971
|
setRequirements(requirements) {
|
|
977
972
|
this.requirements = requirements;
|
|
978
973
|
return this;
|
|
@@ -1054,6 +1049,12 @@ class Upgrader {
|
|
|
1054
1049
|
}
|
|
1055
1050
|
return successReport();
|
|
1056
1051
|
}
|
|
1052
|
+
async confirm(message) {
|
|
1053
|
+
if (typeof this.confirmationCallback !== "function") {
|
|
1054
|
+
return true;
|
|
1055
|
+
}
|
|
1056
|
+
return this.confirmationCallback(message);
|
|
1057
|
+
}
|
|
1057
1058
|
async checkRequirements(requirements, context) {
|
|
1058
1059
|
for (const requirement of requirements) {
|
|
1059
1060
|
const { pass, error } = await requirement.test(context);
|
|
@@ -1125,7 +1126,7 @@ class Upgrader {
|
|
|
1125
1126
|
const packageManagerName = await utils.packageManager.getPreferred(projectPath);
|
|
1126
1127
|
this.logger?.debug?.(`Using ${highlight(packageManagerName)} as package manager`);
|
|
1127
1128
|
if (this.isDry) {
|
|
1128
|
-
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")})`);
|
|
1129
1130
|
return;
|
|
1130
1131
|
}
|
|
1131
1132
|
await utils.packageManager.installDependencies(projectPath, packageManagerName, {
|
|
@@ -1144,23 +1145,28 @@ class Upgrader {
|
|
|
1144
1145
|
}
|
|
1145
1146
|
const resolveNPMTarget = (project, target, npmPackage) => {
|
|
1146
1147
|
if (isSemverInstance(target)) {
|
|
1147
|
-
|
|
1148
|
+
const version2 = npmPackage.findVersion(target);
|
|
1149
|
+
if (!version2) {
|
|
1150
|
+
throw new NPMCandidateNotFoundError(target);
|
|
1151
|
+
}
|
|
1152
|
+
return version2;
|
|
1148
1153
|
}
|
|
1149
1154
|
if (isSemVerReleaseType(target)) {
|
|
1150
1155
|
const range = rangeFromVersions(project.strapiVersion, target);
|
|
1151
1156
|
const npmVersionsMatches = npmPackage.findVersionsInRange(range);
|
|
1152
|
-
|
|
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;
|
|
1153
1162
|
}
|
|
1154
|
-
|
|
1163
|
+
throw new NPMCandidateNotFoundError(target);
|
|
1155
1164
|
};
|
|
1156
1165
|
const upgraderFactory = (project, target, npmPackage) => {
|
|
1157
|
-
const
|
|
1158
|
-
|
|
1159
|
-
throw new Error(`Couldn't find a matching version in the NPM registry for "${target}"`);
|
|
1160
|
-
}
|
|
1161
|
-
const semverTarget = semVerFactory(targetedNPMVersion.version);
|
|
1166
|
+
const npmTarget = resolveNPMTarget(project, target, npmPackage);
|
|
1167
|
+
const semverTarget = semVerFactory(npmTarget.version);
|
|
1162
1168
|
if (semver__default.default.eq(semverTarget, project.strapiVersion)) {
|
|
1163
|
-
throw new Error(`The project is already
|
|
1169
|
+
throw new Error(`The project is already using v${semverTarget}`);
|
|
1164
1170
|
}
|
|
1165
1171
|
return new Upgrader(project, semverTarget, npmPackage);
|
|
1166
1172
|
};
|
|
@@ -1171,80 +1177,195 @@ const constants = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePro
|
|
|
1171
1177
|
__proto__: null,
|
|
1172
1178
|
STRAPI_PACKAGE_NAME
|
|
1173
1179
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
1174
|
-
const index$
|
|
1180
|
+
const index$6 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
1175
1181
|
__proto__: null,
|
|
1176
1182
|
constants,
|
|
1177
1183
|
upgraderFactory
|
|
1178
1184
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
1179
|
-
|
|
1180
|
-
|
|
1185
|
+
class Requirement {
|
|
1186
|
+
isRequired;
|
|
1181
1187
|
name;
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
constructor(name) {
|
|
1188
|
+
testCallback;
|
|
1189
|
+
children;
|
|
1190
|
+
constructor(name, testCallback, isRequired) {
|
|
1185
1191
|
this.name = name;
|
|
1186
|
-
this.
|
|
1187
|
-
this.
|
|
1192
|
+
this.testCallback = testCallback;
|
|
1193
|
+
this.isRequired = isRequired ?? true;
|
|
1194
|
+
this.children = [];
|
|
1188
1195
|
}
|
|
1189
|
-
|
|
1190
|
-
|
|
1196
|
+
setChildren(children) {
|
|
1197
|
+
this.children = children;
|
|
1198
|
+
return this;
|
|
1191
1199
|
}
|
|
1192
|
-
|
|
1193
|
-
|
|
1200
|
+
addChild(child) {
|
|
1201
|
+
this.children.push(child);
|
|
1202
|
+
return this;
|
|
1194
1203
|
}
|
|
1195
|
-
|
|
1196
|
-
this.
|
|
1197
|
-
|
|
1204
|
+
asOptional() {
|
|
1205
|
+
const newInstance = requirementFactory(this.name, this.testCallback, false);
|
|
1206
|
+
newInstance.setChildren(this.children);
|
|
1207
|
+
return newInstance;
|
|
1198
1208
|
}
|
|
1199
|
-
|
|
1200
|
-
this.
|
|
1201
|
-
|
|
1209
|
+
asRequired() {
|
|
1210
|
+
const newInstance = requirementFactory(this.name, this.testCallback, true);
|
|
1211
|
+
newInstance.setChildren(this.children);
|
|
1212
|
+
return newInstance;
|
|
1202
1213
|
}
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
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
|
+
}
|
|
1206
1227
|
}
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
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
|
+
}
|
|
1210
1245
|
}
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
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
|
+
}
|
|
1216
1262
|
}
|
|
1217
|
-
|
|
1218
|
-
|
|
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
|
+
}
|
|
1219
1274
|
}
|
|
1220
|
-
|
|
1221
|
-
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
|
+
};
|
|
1222
1330
|
const upgrade = async (options) => {
|
|
1223
1331
|
const timer = timerFactory();
|
|
1224
1332
|
const { logger, codemodsTarget } = options;
|
|
1225
1333
|
const cwd = path__default.default.resolve(options.cwd ?? process.cwd());
|
|
1226
1334
|
const project = projectFactory(cwd);
|
|
1335
|
+
logger.debug(projectDetails(project));
|
|
1227
1336
|
if (!isApplicationProject(project)) {
|
|
1228
1337
|
throw new Error(
|
|
1229
1338
|
`The "${options.target}" upgrade can only be run on a Strapi project; for plugins, please use "codemods".`
|
|
1230
1339
|
);
|
|
1231
1340
|
}
|
|
1341
|
+
logger.debug(
|
|
1342
|
+
`Application: VERSION=${version(project.packageJSON.version)}; STRAPI_VERSION=${version(project.strapiVersion)}`
|
|
1343
|
+
);
|
|
1232
1344
|
const npmPackage = npmPackageFactory(STRAPI_PACKAGE_NAME);
|
|
1233
1345
|
await npmPackage.refresh();
|
|
1234
1346
|
const upgrader = upgraderFactory(project, options.target, npmPackage).dry(options.dry ?? false).onConfirm(options.confirm ?? null).setLogger(logger);
|
|
1235
1347
|
if (codemodsTarget !== void 0) {
|
|
1236
1348
|
upgrader.overrideCodemodsTarget(codemodsTarget);
|
|
1237
1349
|
}
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
}
|
|
1241
|
-
upgrader.addRequirement(REQUIRE_GIT.asOptional());
|
|
1350
|
+
await runUpgradePrompts(upgrader, options);
|
|
1351
|
+
addUpgradeRequirements(upgrader, options);
|
|
1242
1352
|
const upgradeReport = await upgrader.upgrade();
|
|
1243
1353
|
if (!upgradeReport.success) {
|
|
1244
1354
|
throw upgradeReport.error;
|
|
1245
1355
|
}
|
|
1246
1356
|
timer.stop();
|
|
1247
|
-
logger.info(`Completed in ${durationMs(timer.elapsedMs)}`);
|
|
1357
|
+
logger.info(`Completed in ${durationMs(timer.elapsedMs)}ms`);
|
|
1358
|
+
};
|
|
1359
|
+
const runUpgradePrompts = async (upgrader, options) => {
|
|
1360
|
+
if (options.target === ReleaseType.Latest) {
|
|
1361
|
+
await latest(upgrader, options);
|
|
1362
|
+
}
|
|
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());
|
|
1248
1369
|
};
|
|
1249
1370
|
const resolvePath = (cwd) => path__default.default.resolve(cwd ?? process.cwd());
|
|
1250
1371
|
const getRangeFromTarget = (currentVersion, target) => {
|
|
@@ -1253,6 +1374,8 @@ const getRangeFromTarget = (currentVersion, target) => {
|
|
|
1253
1374
|
}
|
|
1254
1375
|
const { major, minor, patch } = currentVersion;
|
|
1255
1376
|
switch (target) {
|
|
1377
|
+
case ReleaseType.Latest:
|
|
1378
|
+
throw new Error("Can't use <latest> to create a codemods range: not implemented");
|
|
1256
1379
|
case ReleaseType.Major:
|
|
1257
1380
|
return rangeFactory(`${major}`);
|
|
1258
1381
|
case ReleaseType.Minor:
|
|
@@ -1278,7 +1401,7 @@ const runCodemods = async (options) => {
|
|
|
1278
1401
|
const cwd = resolvePath(options.cwd);
|
|
1279
1402
|
const project = projectFactory(cwd);
|
|
1280
1403
|
const range = findRangeFromTarget(project, options.target);
|
|
1281
|
-
logger.debug(
|
|
1404
|
+
logger.debug(projectDetails(project));
|
|
1282
1405
|
logger.debug(`Range: set to ${versionRange(range)}`);
|
|
1283
1406
|
const codemodRunner = codemodRunnerFactory(project, range).dry(options.dry ?? false).onSelectCodemods(options.selectCodemods ?? null).setLogger(logger);
|
|
1284
1407
|
let report;
|
|
@@ -1299,7 +1422,7 @@ const listCodemods = async (options) => {
|
|
|
1299
1422
|
const cwd = resolvePath(options.cwd);
|
|
1300
1423
|
const project = projectFactory(cwd);
|
|
1301
1424
|
const range = findRangeFromTarget(project, target);
|
|
1302
|
-
logger.debug(
|
|
1425
|
+
logger.debug(projectDetails(project));
|
|
1303
1426
|
logger.debug(`Range: set to ${versionRange(range)}`);
|
|
1304
1427
|
const repo = codemodRepositoryFactory();
|
|
1305
1428
|
repo.refresh();
|
|
@@ -1410,18 +1533,18 @@ const index$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePrope
|
|
|
1410
1533
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
1411
1534
|
const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
1412
1535
|
__proto__: null,
|
|
1413
|
-
codemod: index$
|
|
1414
|
-
codemodRepository: index$
|
|
1536
|
+
codemod: index$8,
|
|
1537
|
+
codemodRepository: index$7,
|
|
1415
1538
|
error: index$9,
|
|
1416
|
-
f: index$
|
|
1539
|
+
f: index$f,
|
|
1417
1540
|
fileScanner: index$d,
|
|
1418
1541
|
logger: index$3,
|
|
1419
1542
|
project: index$a,
|
|
1420
1543
|
report: index$2,
|
|
1421
|
-
requirement: index$
|
|
1544
|
+
requirement: index$5,
|
|
1422
1545
|
runner: index$1,
|
|
1423
|
-
timer: index$
|
|
1424
|
-
upgrader: index$
|
|
1546
|
+
timer: index$g,
|
|
1547
|
+
upgrader: index$6,
|
|
1425
1548
|
version: index$e
|
|
1426
1549
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
1427
1550
|
exports.modules = index;
|