@strapi/upgrade 0.0.0-experimental.e60ec1829240dae21c1e1d29076681c322288813 → 0.0.0-experimental.eba25ec571b091c6bde1104eb6c753debdf15462
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 +7 -7
- 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.mjs
CHANGED
|
@@ -1,128 +1,15 @@
|
|
|
1
1
|
import path$1 from "node:path";
|
|
2
|
-
import
|
|
2
|
+
import CliTable3 from "cli-table3";
|
|
3
3
|
import chalk from "chalk";
|
|
4
|
+
import assert from "node:assert";
|
|
4
5
|
import semver from "semver";
|
|
5
|
-
import { packageManager } from "@strapi/utils";
|
|
6
|
-
import { cloneDeep, get, has, merge, set, omit, isEqual, groupBy, size } from "lodash/fp";
|
|
7
6
|
import fse from "fs-extra";
|
|
8
|
-
import
|
|
9
|
-
import { glob } from "glob";
|
|
7
|
+
import fastglob from "fast-glob";
|
|
10
8
|
import { run } from "jscodeshift/src/Runner";
|
|
9
|
+
import { cloneDeep, get, has, merge, set, omit, isEqual, groupBy, size } from "lodash/fp";
|
|
11
10
|
import { register } from "esbuild-register/dist/node";
|
|
12
|
-
import
|
|
13
|
-
|
|
14
|
-
isRequired;
|
|
15
|
-
name;
|
|
16
|
-
testCallback;
|
|
17
|
-
children;
|
|
18
|
-
constructor(name, testCallback, isRequired) {
|
|
19
|
-
this.name = name;
|
|
20
|
-
this.testCallback = testCallback;
|
|
21
|
-
this.isRequired = isRequired ?? true;
|
|
22
|
-
this.children = [];
|
|
23
|
-
}
|
|
24
|
-
setChildren(children) {
|
|
25
|
-
this.children = children;
|
|
26
|
-
return this;
|
|
27
|
-
}
|
|
28
|
-
addChild(child) {
|
|
29
|
-
this.children.push(child);
|
|
30
|
-
return this;
|
|
31
|
-
}
|
|
32
|
-
asOptional() {
|
|
33
|
-
const newInstance = requirementFactory(this.name, this.testCallback, false);
|
|
34
|
-
newInstance.setChildren(this.children);
|
|
35
|
-
return newInstance;
|
|
36
|
-
}
|
|
37
|
-
asRequired() {
|
|
38
|
-
const newInstance = requirementFactory(this.name, this.testCallback, true);
|
|
39
|
-
newInstance.setChildren(this.children);
|
|
40
|
-
return newInstance;
|
|
41
|
-
}
|
|
42
|
-
async test(context) {
|
|
43
|
-
try {
|
|
44
|
-
await this.testCallback?.(context);
|
|
45
|
-
return ok();
|
|
46
|
-
} catch (e) {
|
|
47
|
-
if (e instanceof Error) {
|
|
48
|
-
return errored(e);
|
|
49
|
-
}
|
|
50
|
-
if (typeof e === "string") {
|
|
51
|
-
return errored(new Error(e));
|
|
52
|
-
}
|
|
53
|
-
return errored(new Error("Unknown error"));
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
const ok = () => ({ pass: true, error: null });
|
|
58
|
-
const errored = (error) => ({ pass: false, error });
|
|
59
|
-
const requirementFactory = (name, testCallback, isRequired) => new Requirement(name, testCallback, isRequired);
|
|
60
|
-
const index$g = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
61
|
-
__proto__: null,
|
|
62
|
-
requirementFactory
|
|
63
|
-
}, Symbol.toStringTag, { value: "Module" }));
|
|
64
|
-
const REQUIRE_AVAILABLE_NEXT_MAJOR = requirementFactory(
|
|
65
|
-
"REQUIRE_AVAILABLE_NEXT_MAJOR",
|
|
66
|
-
(context) => {
|
|
67
|
-
const { project, target } = context;
|
|
68
|
-
const currentMajor = project.strapiVersion.major;
|
|
69
|
-
const targetedMajor = target.major;
|
|
70
|
-
if (targetedMajor === currentMajor) {
|
|
71
|
-
throw new Error(`You're already on the latest major version (v${currentMajor})`);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
);
|
|
75
|
-
const REQUIRE_LATEST_FOR_CURRENT_MAJOR = requirementFactory(
|
|
76
|
-
"REQUIRE_LATEST_FOR_CURRENT_MAJOR",
|
|
77
|
-
(context) => {
|
|
78
|
-
const { project, target, npmVersionsMatches } = context;
|
|
79
|
-
if (npmVersionsMatches.length !== 1) {
|
|
80
|
-
const invalidVersions = npmVersionsMatches.slice(0, -1);
|
|
81
|
-
const invalidVersionsAsSemVer = invalidVersions.map((v) => v.version);
|
|
82
|
-
const nbInvalidVersions = npmVersionsMatches.length;
|
|
83
|
-
const currentMajor = project.strapiVersion.major;
|
|
84
|
-
throw new Error(
|
|
85
|
-
`Doing a major upgrade requires to be on the latest v${currentMajor} version, but found ${nbInvalidVersions} versions between the current one and ${target}: ${invalidVersionsAsSemVer}`
|
|
86
|
-
);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
);
|
|
90
|
-
const REQUIRE_GIT_CLEAN_REPOSITORY = requirementFactory(
|
|
91
|
-
"REQUIRE_GIT_CLEAN_REPOSITORY",
|
|
92
|
-
async (context) => {
|
|
93
|
-
const git = simpleGit({ baseDir: context.project.cwd });
|
|
94
|
-
const status = await git.status();
|
|
95
|
-
if (!status.isClean()) {
|
|
96
|
-
throw new Error(
|
|
97
|
-
"Repository is not clean. Please commit or stash any changes before upgrading"
|
|
98
|
-
);
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
);
|
|
102
|
-
const REQUIRE_GIT_REPOSITORY = requirementFactory(
|
|
103
|
-
"REQUIRE_GIT_REPOSITORY",
|
|
104
|
-
async (context) => {
|
|
105
|
-
const git = simpleGit({ baseDir: context.project.cwd });
|
|
106
|
-
const isRepo = await git.checkIsRepo();
|
|
107
|
-
if (!isRepo) {
|
|
108
|
-
throw new Error("Not a git repository (or any of the parent directories)");
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
).addChild(REQUIRE_GIT_CLEAN_REPOSITORY.asOptional());
|
|
112
|
-
const REQUIRE_GIT_INSTALLED = requirementFactory(
|
|
113
|
-
"REQUIRE_GIT_INSTALLED",
|
|
114
|
-
async (context) => {
|
|
115
|
-
const git = simpleGit({ baseDir: context.project.cwd });
|
|
116
|
-
try {
|
|
117
|
-
await git.version();
|
|
118
|
-
} catch {
|
|
119
|
-
throw new Error("Git is not installed");
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
).addChild(REQUIRE_GIT_REPOSITORY.asOptional());
|
|
123
|
-
const REQUIRE_GIT = requirementFactory("REQUIRE_GIT", null).addChild(
|
|
124
|
-
REQUIRE_GIT_INSTALLED.asOptional()
|
|
125
|
-
);
|
|
11
|
+
import { packageManager } from "@strapi/utils";
|
|
12
|
+
import simpleGit from "simple-git";
|
|
126
13
|
class Timer {
|
|
127
14
|
interval;
|
|
128
15
|
constructor() {
|
|
@@ -153,55 +40,101 @@ const constants$4 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineP
|
|
|
153
40
|
__proto__: null,
|
|
154
41
|
ONE_SECOND_MS
|
|
155
42
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
156
|
-
const index$
|
|
43
|
+
const index$g = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
157
44
|
__proto__: null,
|
|
158
45
|
constants: constants$4,
|
|
159
46
|
timerFactory
|
|
160
47
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
this.json = cloneDeep(json);
|
|
165
|
-
}
|
|
166
|
-
get(path2, defaultValue) {
|
|
167
|
-
if (!path2) {
|
|
168
|
-
return this.root();
|
|
169
|
-
}
|
|
170
|
-
return cloneDeep(get(path2, this.json) ?? defaultValue);
|
|
171
|
-
}
|
|
172
|
-
has(path2) {
|
|
173
|
-
return has(path2, this.json);
|
|
174
|
-
}
|
|
175
|
-
merge(other) {
|
|
176
|
-
this.json = merge(other, this.json);
|
|
177
|
-
return this;
|
|
178
|
-
}
|
|
179
|
-
root() {
|
|
180
|
-
return cloneDeep(this.json);
|
|
181
|
-
}
|
|
182
|
-
set(path2, value) {
|
|
183
|
-
this.json = set(path2, value, this.json);
|
|
184
|
-
return this;
|
|
185
|
-
}
|
|
186
|
-
remove(path2) {
|
|
187
|
-
this.json = omit(path2, this.json);
|
|
188
|
-
return this;
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
const createJSONTransformAPI = (object) => new JSONTransformAPI(object);
|
|
192
|
-
const readJSON = async (path2) => {
|
|
193
|
-
const buffer = await fse.readFile(path2);
|
|
194
|
-
return JSON.parse(buffer.toString());
|
|
48
|
+
const path = (path2) => chalk.blue(path2);
|
|
49
|
+
const version = (version2) => {
|
|
50
|
+
return chalk.italic.yellow(`v${version2}`);
|
|
195
51
|
};
|
|
196
|
-
const
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
52
|
+
const codemodUID = (uid) => {
|
|
53
|
+
return chalk.bold.cyan(uid);
|
|
54
|
+
};
|
|
55
|
+
const projectDetails = (project) => {
|
|
56
|
+
return `Project: TYPE=${projectType(project.type)}; CWD=${path(project.cwd)}; PATHS=${project.paths.map(path)}`;
|
|
57
|
+
};
|
|
58
|
+
const projectType = (type) => chalk.cyan(type);
|
|
59
|
+
const versionRange = (range) => chalk.italic.yellow(range.raw);
|
|
60
|
+
const transform = (transformFilePath) => chalk.cyan(transformFilePath);
|
|
61
|
+
const highlight = (arg) => chalk.bold.underline(arg);
|
|
62
|
+
const upgradeStep = (text, step) => {
|
|
63
|
+
return chalk.bold(`(${step[0]}/${step[1]}) ${text}...`);
|
|
64
|
+
};
|
|
65
|
+
const reports = (reports2) => {
|
|
66
|
+
const rows = reports2.map(({ codemod, report }, i) => {
|
|
67
|
+
const fIndex = chalk.grey(i);
|
|
68
|
+
const fVersion = chalk.magenta(codemod.version);
|
|
69
|
+
const fKind = chalk.yellow(codemod.kind);
|
|
70
|
+
const fFormattedTransformPath = chalk.cyan(codemod.format());
|
|
71
|
+
const fTimeElapsed = i === 0 ? `${report.timeElapsed}s ${chalk.dim.italic("(cold start)")}` : `${report.timeElapsed}s`;
|
|
72
|
+
const fAffected = report.ok > 0 ? chalk.green(report.ok) : chalk.grey(0);
|
|
73
|
+
const fUnchanged = report.ok === 0 ? chalk.red(report.nochange) : chalk.grey(report.nochange);
|
|
74
|
+
return [fIndex, fVersion, fKind, fFormattedTransformPath, fAffected, fUnchanged, fTimeElapsed];
|
|
75
|
+
});
|
|
76
|
+
const table = new CliTable3({
|
|
77
|
+
style: { compact: true },
|
|
78
|
+
head: [
|
|
79
|
+
chalk.bold.grey("N°"),
|
|
80
|
+
chalk.bold.magenta("Version"),
|
|
81
|
+
chalk.bold.yellow("Kind"),
|
|
82
|
+
chalk.bold.cyan("Name"),
|
|
83
|
+
chalk.bold.green("Affected"),
|
|
84
|
+
chalk.bold.red("Unchanged"),
|
|
85
|
+
chalk.bold.blue("Duration")
|
|
86
|
+
]
|
|
87
|
+
});
|
|
88
|
+
table.push(...rows);
|
|
89
|
+
return table.toString();
|
|
90
|
+
};
|
|
91
|
+
const codemodList = (codemods) => {
|
|
92
|
+
const rows = codemods.map((codemod, index2) => {
|
|
93
|
+
const fIndex = chalk.grey(index2);
|
|
94
|
+
const fVersion = chalk.magenta(codemod.version);
|
|
95
|
+
const fKind = chalk.yellow(codemod.kind);
|
|
96
|
+
const fName = chalk.blue(codemod.format());
|
|
97
|
+
const fUID = codemodUID(codemod.uid);
|
|
98
|
+
return [fIndex, fVersion, fKind, fName, fUID];
|
|
99
|
+
});
|
|
100
|
+
const table = new CliTable3({
|
|
101
|
+
style: { compact: true },
|
|
102
|
+
head: [
|
|
103
|
+
chalk.bold.grey("N°"),
|
|
104
|
+
chalk.bold.magenta("Version"),
|
|
105
|
+
chalk.bold.yellow("Kind"),
|
|
106
|
+
chalk.bold.blue("Name"),
|
|
107
|
+
chalk.bold.cyan("UID")
|
|
108
|
+
]
|
|
109
|
+
});
|
|
110
|
+
table.push(...rows);
|
|
111
|
+
return table.toString();
|
|
200
112
|
};
|
|
113
|
+
const durationMs = (elapsedMs) => {
|
|
114
|
+
const elapsedSeconds = (elapsedMs / ONE_SECOND_MS).toFixed(3);
|
|
115
|
+
return `${elapsedSeconds}s`;
|
|
116
|
+
};
|
|
117
|
+
const index$f = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
118
|
+
__proto__: null,
|
|
119
|
+
codemodList,
|
|
120
|
+
codemodUID,
|
|
121
|
+
durationMs,
|
|
122
|
+
highlight,
|
|
123
|
+
path,
|
|
124
|
+
projectDetails,
|
|
125
|
+
projectType,
|
|
126
|
+
reports,
|
|
127
|
+
transform,
|
|
128
|
+
upgradeStep,
|
|
129
|
+
version,
|
|
130
|
+
versionRange
|
|
131
|
+
}, Symbol.toStringTag, { value: "Module" }));
|
|
132
|
+
const NPM_REGISTRY_URL = "https://registry.npmjs.org";
|
|
201
133
|
var ReleaseType = /* @__PURE__ */ ((ReleaseType2) => {
|
|
202
134
|
ReleaseType2["Major"] = "major";
|
|
203
135
|
ReleaseType2["Minor"] = "minor";
|
|
204
136
|
ReleaseType2["Patch"] = "patch";
|
|
137
|
+
ReleaseType2["Latest"] = "latest";
|
|
205
138
|
return ReleaseType2;
|
|
206
139
|
})(ReleaseType || {});
|
|
207
140
|
const types = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
@@ -227,17 +160,20 @@ const rangeFactory = (range) => {
|
|
|
227
160
|
};
|
|
228
161
|
const rangeFromReleaseType = (current, identifier) => {
|
|
229
162
|
switch (identifier) {
|
|
230
|
-
case ReleaseType.
|
|
231
|
-
|
|
232
|
-
return rangeFactory(`>${current.raw} <=${nextMajor}`);
|
|
163
|
+
case ReleaseType.Latest: {
|
|
164
|
+
return rangeFactory(`>${current.raw}`);
|
|
233
165
|
}
|
|
234
|
-
case ReleaseType.
|
|
235
|
-
const
|
|
236
|
-
return rangeFactory(`>${current.raw}
|
|
166
|
+
case ReleaseType.Major: {
|
|
167
|
+
const nextMajor = semVerFactory(current.raw).inc("major");
|
|
168
|
+
return rangeFactory(`>${current.raw} <=${nextMajor.major}`);
|
|
237
169
|
}
|
|
238
170
|
case ReleaseType.Minor: {
|
|
239
|
-
const
|
|
240
|
-
return rangeFactory(`>${current.raw} <${
|
|
171
|
+
const nextMajor = semVerFactory(current.raw).inc("major");
|
|
172
|
+
return rangeFactory(`>${current.raw} <${nextMajor.raw}`);
|
|
173
|
+
}
|
|
174
|
+
case ReleaseType.Patch: {
|
|
175
|
+
const nextMinor = semVerFactory(current.raw).inc("minor");
|
|
176
|
+
return rangeFactory(`>${current.raw} <${nextMinor.raw}`);
|
|
241
177
|
}
|
|
242
178
|
default: {
|
|
243
179
|
throw new Error("Not implemented");
|
|
@@ -271,13 +207,57 @@ const index$e = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePrope
|
|
|
271
207
|
rangeFromVersions,
|
|
272
208
|
semVerFactory
|
|
273
209
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
210
|
+
class Package {
|
|
211
|
+
name;
|
|
212
|
+
packageURL;
|
|
213
|
+
npmPackage;
|
|
214
|
+
constructor(name) {
|
|
215
|
+
this.name = name;
|
|
216
|
+
this.packageURL = `${NPM_REGISTRY_URL}/${name}`;
|
|
217
|
+
this.npmPackage = null;
|
|
218
|
+
}
|
|
219
|
+
get isLoaded() {
|
|
220
|
+
return this.npmPackage !== null;
|
|
221
|
+
}
|
|
222
|
+
assertPackageIsLoaded(npmPackage) {
|
|
223
|
+
assert(this.isLoaded, "The package is not loaded yet");
|
|
224
|
+
}
|
|
225
|
+
getVersionsDict() {
|
|
226
|
+
this.assertPackageIsLoaded(this.npmPackage);
|
|
227
|
+
return this.npmPackage.versions;
|
|
228
|
+
}
|
|
229
|
+
getVersionsAsList() {
|
|
230
|
+
this.assertPackageIsLoaded(this.npmPackage);
|
|
231
|
+
return Object.values(this.npmPackage.versions);
|
|
232
|
+
}
|
|
233
|
+
findVersionsInRange(range) {
|
|
234
|
+
const versions = this.getVersionsAsList();
|
|
235
|
+
return versions.filter((v) => range.test(v.version)).filter((v) => isLiteralSemVer(v.version)).sort((v1, v2) => semver.compare(v1.version, v2.version));
|
|
236
|
+
}
|
|
237
|
+
findVersion(version2) {
|
|
238
|
+
const versions = this.getVersionsAsList();
|
|
239
|
+
return versions.find((npmVersion) => semver.eq(npmVersion.version, version2));
|
|
240
|
+
}
|
|
241
|
+
async refresh() {
|
|
242
|
+
const response = await fetch(this.packageURL);
|
|
243
|
+
assert(response.ok, `Request failed for ${this.packageURL}`);
|
|
244
|
+
this.npmPackage = await response.json();
|
|
245
|
+
return this;
|
|
246
|
+
}
|
|
247
|
+
versionExists(version2) {
|
|
248
|
+
return this.findVersion(version2) !== void 0;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
const npmPackageFactory = (name) => new Package(name);
|
|
274
252
|
class FileScanner {
|
|
275
253
|
cwd;
|
|
276
254
|
constructor(cwd) {
|
|
277
255
|
this.cwd = cwd;
|
|
278
256
|
}
|
|
279
257
|
scan(patterns) {
|
|
280
|
-
const filenames =
|
|
258
|
+
const filenames = fastglob.sync(patterns, {
|
|
259
|
+
cwd: this.cwd
|
|
260
|
+
});
|
|
281
261
|
return filenames.map((filename) => path$1.join(this.cwd, filename));
|
|
282
262
|
}
|
|
283
263
|
}
|
|
@@ -315,6 +295,46 @@ const index$c = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePrope
|
|
|
315
295
|
__proto__: null,
|
|
316
296
|
codeRunnerFactory
|
|
317
297
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
298
|
+
class JSONTransformAPI {
|
|
299
|
+
json;
|
|
300
|
+
constructor(json) {
|
|
301
|
+
this.json = cloneDeep(json);
|
|
302
|
+
}
|
|
303
|
+
get(path2, defaultValue) {
|
|
304
|
+
if (!path2) {
|
|
305
|
+
return this.root();
|
|
306
|
+
}
|
|
307
|
+
return cloneDeep(get(path2, this.json) ?? defaultValue);
|
|
308
|
+
}
|
|
309
|
+
has(path2) {
|
|
310
|
+
return has(path2, this.json);
|
|
311
|
+
}
|
|
312
|
+
merge(other) {
|
|
313
|
+
this.json = merge(other, this.json);
|
|
314
|
+
return this;
|
|
315
|
+
}
|
|
316
|
+
root() {
|
|
317
|
+
return cloneDeep(this.json);
|
|
318
|
+
}
|
|
319
|
+
set(path2, value) {
|
|
320
|
+
this.json = set(path2, value, this.json);
|
|
321
|
+
return this;
|
|
322
|
+
}
|
|
323
|
+
remove(path2) {
|
|
324
|
+
this.json = omit(path2, this.json);
|
|
325
|
+
return this;
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
const createJSONTransformAPI = (object) => new JSONTransformAPI(object);
|
|
329
|
+
const readJSON = async (path2) => {
|
|
330
|
+
const buffer = await fse.readFile(path2);
|
|
331
|
+
return JSON.parse(buffer.toString());
|
|
332
|
+
};
|
|
333
|
+
const saveJSON = async (path2, json) => {
|
|
334
|
+
const jsonAsString = `${JSON.stringify(json, null, 2)}
|
|
335
|
+
`;
|
|
336
|
+
await fse.writeFile(path2, jsonAsString);
|
|
337
|
+
};
|
|
318
338
|
const transformJSON = async (codemodPath, paths, config) => {
|
|
319
339
|
const { dry } = config;
|
|
320
340
|
const startTime = process.hrtime();
|
|
@@ -326,7 +346,11 @@ const transformJSON = async (codemodPath, paths, config) => {
|
|
|
326
346
|
timeElapsed: "",
|
|
327
347
|
stats: {}
|
|
328
348
|
};
|
|
329
|
-
const esbuildOptions = {
|
|
349
|
+
const esbuildOptions = {
|
|
350
|
+
extensions: [".js", ".mjs", ".ts"],
|
|
351
|
+
hookIgnoreNodeModules: false,
|
|
352
|
+
hookMatcher: isEqual(codemodPath)
|
|
353
|
+
};
|
|
330
354
|
const { unregister } = register(esbuildOptions);
|
|
331
355
|
const module = require(codemodPath);
|
|
332
356
|
unregister();
|
|
@@ -371,8 +395,10 @@ const index$b = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePrope
|
|
|
371
395
|
jsonRunnerFactory
|
|
372
396
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
373
397
|
const PROJECT_PACKAGE_JSON = "package.json";
|
|
374
|
-
const
|
|
375
|
-
const
|
|
398
|
+
const PROJECT_APP_ALLOWED_ROOT_PATHS = ["src", "config", "public"];
|
|
399
|
+
const PROJECT_PLUGIN_ALLOWED_ROOT_PATHS = ["admin", "server"];
|
|
400
|
+
const PROJECT_PLUGIN_ROOT_FILES = ["strapi-admin.js", "strapi-server.js"];
|
|
401
|
+
const PROJECT_CODE_EXTENSIONS = [
|
|
376
402
|
// Source files
|
|
377
403
|
"js",
|
|
378
404
|
"mjs",
|
|
@@ -381,22 +407,19 @@ const PROJECT_DEFAULT_CODE_EXTENSIONS = [
|
|
|
381
407
|
"jsx",
|
|
382
408
|
"tsx"
|
|
383
409
|
];
|
|
384
|
-
const
|
|
385
|
-
const
|
|
386
|
-
...PROJECT_DEFAULT_CODE_EXTENSIONS,
|
|
387
|
-
...PROJECT_DEFAULT_JSON_EXTENSIONS
|
|
388
|
-
];
|
|
389
|
-
const PROJECT_DEFAULT_PATTERNS = ["package.json"];
|
|
410
|
+
const PROJECT_JSON_EXTENSIONS = ["json"];
|
|
411
|
+
const PROJECT_ALLOWED_EXTENSIONS = [...PROJECT_CODE_EXTENSIONS, ...PROJECT_JSON_EXTENSIONS];
|
|
390
412
|
const SCOPED_STRAPI_PACKAGE_PREFIX = "@strapi/";
|
|
391
413
|
const STRAPI_DEPENDENCY_NAME = `${SCOPED_STRAPI_PACKAGE_PREFIX}strapi`;
|
|
392
414
|
const constants$3 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
393
415
|
__proto__: null,
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
PROJECT_DEFAULT_PATTERNS,
|
|
416
|
+
PROJECT_ALLOWED_EXTENSIONS,
|
|
417
|
+
PROJECT_APP_ALLOWED_ROOT_PATHS,
|
|
418
|
+
PROJECT_CODE_EXTENSIONS,
|
|
419
|
+
PROJECT_JSON_EXTENSIONS,
|
|
399
420
|
PROJECT_PACKAGE_JSON,
|
|
421
|
+
PROJECT_PLUGIN_ALLOWED_ROOT_PATHS,
|
|
422
|
+
PROJECT_PLUGIN_ROOT_FILES,
|
|
400
423
|
SCOPED_STRAPI_PACKAGE_PREFIX,
|
|
401
424
|
STRAPI_DEPENDENCY_NAME
|
|
402
425
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
@@ -406,11 +429,13 @@ class Project {
|
|
|
406
429
|
files;
|
|
407
430
|
packageJSONPath;
|
|
408
431
|
packageJSON;
|
|
409
|
-
|
|
432
|
+
paths;
|
|
433
|
+
constructor(cwd, config) {
|
|
410
434
|
if (!fse.pathExistsSync(cwd)) {
|
|
411
435
|
throw new Error(`ENOENT: no such file or directory, access '${cwd}'`);
|
|
412
436
|
}
|
|
413
437
|
this.cwd = cwd;
|
|
438
|
+
this.paths = config.paths;
|
|
414
439
|
this.refresh();
|
|
415
440
|
}
|
|
416
441
|
getFilesByExtensions(extensions) {
|
|
@@ -438,12 +463,8 @@ class Project {
|
|
|
438
463
|
return reports2;
|
|
439
464
|
}
|
|
440
465
|
createProjectCodemodsRunners(dry = false) {
|
|
441
|
-
const jsonExtensions =
|
|
442
|
-
|
|
443
|
-
);
|
|
444
|
-
const codeExtensions = PROJECT_DEFAULT_CODE_EXTENSIONS.map(
|
|
445
|
-
(ext) => `.${ext}`
|
|
446
|
-
);
|
|
466
|
+
const jsonExtensions = PROJECT_JSON_EXTENSIONS.map((ext) => `.${ext}`);
|
|
467
|
+
const codeExtensions = PROJECT_CODE_EXTENSIONS.map((ext) => `.${ext}`);
|
|
447
468
|
const jsonFiles = this.getFilesByExtensions(jsonExtensions);
|
|
448
469
|
const codeFiles = this.getFilesByExtensions(codeExtensions);
|
|
449
470
|
const codeRunner = codeRunnerFactory(codeFiles, {
|
|
@@ -451,7 +472,7 @@ class Project {
|
|
|
451
472
|
parser: "ts",
|
|
452
473
|
runInBand: true,
|
|
453
474
|
babel: true,
|
|
454
|
-
extensions:
|
|
475
|
+
extensions: PROJECT_CODE_EXTENSIONS.join(","),
|
|
455
476
|
// Don't output any log coming from the runner
|
|
456
477
|
print: false,
|
|
457
478
|
silent: true,
|
|
@@ -472,23 +493,32 @@ class Project {
|
|
|
472
493
|
this.packageJSON = JSON.parse(packageJSONBuffer.toString());
|
|
473
494
|
}
|
|
474
495
|
refreshProjectFiles() {
|
|
475
|
-
const allowedRootPaths = formatGlobCollectionPattern(
|
|
476
|
-
PROJECT_DEFAULT_ALLOWED_ROOT_PATHS
|
|
477
|
-
);
|
|
478
|
-
const allowedExtensions = formatGlobCollectionPattern(
|
|
479
|
-
PROJECT_DEFAULT_ALLOWED_EXTENSIONS
|
|
480
|
-
);
|
|
481
|
-
const projectFilesPattern = `./${allowedRootPaths}/**/*.${allowedExtensions}`;
|
|
482
|
-
const patterns = [projectFilesPattern, ...PROJECT_DEFAULT_PATTERNS];
|
|
483
496
|
const scanner = fileScannerFactory(this.cwd);
|
|
484
|
-
this.files = scanner.scan(
|
|
497
|
+
this.files = scanner.scan(this.paths);
|
|
485
498
|
}
|
|
486
499
|
}
|
|
487
500
|
class AppProject extends Project {
|
|
488
501
|
strapiVersion;
|
|
489
502
|
type = "application";
|
|
503
|
+
/**
|
|
504
|
+
* Returns an array of allowed file paths for a Strapi application
|
|
505
|
+
*
|
|
506
|
+
* The resulting paths include app default files and the root package.json file.
|
|
507
|
+
*/
|
|
508
|
+
static get paths() {
|
|
509
|
+
const allowedRootPaths = formatGlobCollectionPattern(PROJECT_APP_ALLOWED_ROOT_PATHS);
|
|
510
|
+
const allowedExtensions = formatGlobCollectionPattern(PROJECT_ALLOWED_EXTENSIONS);
|
|
511
|
+
return [
|
|
512
|
+
// App default files
|
|
513
|
+
`./${allowedRootPaths}/**/*.${allowedExtensions}`,
|
|
514
|
+
`!./**/node_modules/**/*`,
|
|
515
|
+
`!./**/dist/**/*`,
|
|
516
|
+
// Root package.json file
|
|
517
|
+
PROJECT_PACKAGE_JSON
|
|
518
|
+
];
|
|
519
|
+
}
|
|
490
520
|
constructor(cwd) {
|
|
491
|
-
super(cwd);
|
|
521
|
+
super(cwd, { paths: AppProject.paths });
|
|
492
522
|
this.refreshStrapiVersion();
|
|
493
523
|
}
|
|
494
524
|
refresh() {
|
|
@@ -543,6 +573,30 @@ const formatGlobCollectionPattern = (collection) => {
|
|
|
543
573
|
};
|
|
544
574
|
class PluginProject extends Project {
|
|
545
575
|
type = "plugin";
|
|
576
|
+
/**
|
|
577
|
+
* Returns an array of allowed file paths for a Strapi plugin
|
|
578
|
+
*
|
|
579
|
+
* The resulting paths include plugin default files, the root package.json file, and plugin-specific files.
|
|
580
|
+
*/
|
|
581
|
+
static get paths() {
|
|
582
|
+
const allowedRootPaths = formatGlobCollectionPattern(
|
|
583
|
+
PROJECT_PLUGIN_ALLOWED_ROOT_PATHS
|
|
584
|
+
);
|
|
585
|
+
const allowedExtensions = formatGlobCollectionPattern(PROJECT_ALLOWED_EXTENSIONS);
|
|
586
|
+
return [
|
|
587
|
+
// Plugin default files
|
|
588
|
+
`./${allowedRootPaths}/**/*.${allowedExtensions}`,
|
|
589
|
+
`!./**/node_modules/**/*`,
|
|
590
|
+
`!./**/dist/**/*`,
|
|
591
|
+
// Root package.json file
|
|
592
|
+
PROJECT_PACKAGE_JSON,
|
|
593
|
+
// Plugin root files
|
|
594
|
+
...PROJECT_PLUGIN_ROOT_FILES
|
|
595
|
+
];
|
|
596
|
+
}
|
|
597
|
+
constructor(cwd) {
|
|
598
|
+
super(cwd, { paths: PluginProject.paths });
|
|
599
|
+
}
|
|
546
600
|
}
|
|
547
601
|
const isPlugin = (cwd) => {
|
|
548
602
|
const packageJSONPath = path$1.join(cwd, PROJECT_PACKAGE_JSON);
|
|
@@ -557,10 +611,7 @@ const isPlugin = (cwd) => {
|
|
|
557
611
|
};
|
|
558
612
|
const projectFactory = (cwd) => {
|
|
559
613
|
fse.accessSync(cwd);
|
|
560
|
-
|
|
561
|
-
return new PluginProject(cwd);
|
|
562
|
-
}
|
|
563
|
-
return new AppProject(cwd);
|
|
614
|
+
return isPlugin(cwd) ? new PluginProject(cwd) : new AppProject(cwd);
|
|
564
615
|
};
|
|
565
616
|
const isPluginProject = (project) => {
|
|
566
617
|
return project instanceof PluginProject;
|
|
@@ -592,6 +643,18 @@ class UnexpectedError extends Error {
|
|
|
592
643
|
super("Unexpected Error");
|
|
593
644
|
}
|
|
594
645
|
}
|
|
646
|
+
class NPMCandidateNotFoundError extends Error {
|
|
647
|
+
target;
|
|
648
|
+
constructor(target, message = `Couldn't find a valid NPM candidate for "${target}"`) {
|
|
649
|
+
super(message);
|
|
650
|
+
this.target = target;
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
class AbortedError extends Error {
|
|
654
|
+
constructor(message = "Upgrade aborted") {
|
|
655
|
+
super(message);
|
|
656
|
+
}
|
|
657
|
+
}
|
|
595
658
|
const unknownToError = (e) => {
|
|
596
659
|
if (e instanceof Error) {
|
|
597
660
|
return e;
|
|
@@ -603,89 +666,11 @@ const unknownToError = (e) => {
|
|
|
603
666
|
};
|
|
604
667
|
const index$9 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
605
668
|
__proto__: null,
|
|
669
|
+
AbortedError,
|
|
670
|
+
NPMCandidateNotFoundError,
|
|
606
671
|
UnexpectedError,
|
|
607
672
|
unknownToError
|
|
608
673
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
609
|
-
const path = (path2) => chalk.blue(path2);
|
|
610
|
-
const version = (version2) => {
|
|
611
|
-
return chalk.italic.yellow(`v${version2}`);
|
|
612
|
-
};
|
|
613
|
-
const codemodUID = (uid) => {
|
|
614
|
-
return chalk.bold.cyan(uid);
|
|
615
|
-
};
|
|
616
|
-
const projectType = (type) => chalk.cyan(type);
|
|
617
|
-
const versionRange = (range) => chalk.italic.yellow(range.raw);
|
|
618
|
-
const transform = (transformFilePath) => chalk.cyan(transformFilePath);
|
|
619
|
-
const highlight = (arg) => chalk.bold.underline(arg);
|
|
620
|
-
const upgradeStep = (text, step) => {
|
|
621
|
-
return chalk.bold(`(${step[0]}/${step[1]}) ${text}...`);
|
|
622
|
-
};
|
|
623
|
-
const reports = (reports2) => {
|
|
624
|
-
const rows = reports2.map(({ codemod, report }, i) => {
|
|
625
|
-
const fIndex = chalk.grey(i);
|
|
626
|
-
const fVersion = chalk.magenta(codemod.version);
|
|
627
|
-
const fKind = chalk.yellow(codemod.kind);
|
|
628
|
-
const fFormattedTransformPath = chalk.cyan(codemod.format());
|
|
629
|
-
const fTimeElapsed = i === 0 ? `${report.timeElapsed}s ${chalk.dim.italic("(cold start)")}` : `${report.timeElapsed}s`;
|
|
630
|
-
const fAffected = report.ok > 0 ? chalk.green(report.ok) : chalk.grey(0);
|
|
631
|
-
const fUnchanged = report.ok === 0 ? chalk.red(report.nochange) : chalk.grey(report.nochange);
|
|
632
|
-
return [fIndex, fVersion, fKind, fFormattedTransformPath, fAffected, fUnchanged, fTimeElapsed];
|
|
633
|
-
});
|
|
634
|
-
const table = new CliTable3({
|
|
635
|
-
style: { compact: true },
|
|
636
|
-
head: [
|
|
637
|
-
chalk.bold.grey("N°"),
|
|
638
|
-
chalk.bold.magenta("Version"),
|
|
639
|
-
chalk.bold.yellow("Kind"),
|
|
640
|
-
chalk.bold.cyan("Name"),
|
|
641
|
-
chalk.bold.green("Affected"),
|
|
642
|
-
chalk.bold.red("Unchanged"),
|
|
643
|
-
chalk.bold.blue("Duration")
|
|
644
|
-
]
|
|
645
|
-
});
|
|
646
|
-
table.push(...rows);
|
|
647
|
-
return table.toString();
|
|
648
|
-
};
|
|
649
|
-
const codemodList = (codemods) => {
|
|
650
|
-
const rows = codemods.map((codemod, index2) => {
|
|
651
|
-
const fIndex = chalk.grey(index2);
|
|
652
|
-
const fVersion = chalk.magenta(codemod.version);
|
|
653
|
-
const fKind = chalk.yellow(codemod.kind);
|
|
654
|
-
const fName = chalk.blue(codemod.format());
|
|
655
|
-
const fUID = codemodUID(codemod.uid);
|
|
656
|
-
return [fIndex, fVersion, fKind, fName, fUID];
|
|
657
|
-
});
|
|
658
|
-
const table = new CliTable3({
|
|
659
|
-
style: { compact: true },
|
|
660
|
-
head: [
|
|
661
|
-
chalk.bold.grey("N°"),
|
|
662
|
-
chalk.bold.magenta("Version"),
|
|
663
|
-
chalk.bold.yellow("Kind"),
|
|
664
|
-
chalk.bold.blue("Name"),
|
|
665
|
-
chalk.bold.cyan("UID")
|
|
666
|
-
]
|
|
667
|
-
});
|
|
668
|
-
table.push(...rows);
|
|
669
|
-
return table.toString();
|
|
670
|
-
};
|
|
671
|
-
const durationMs = (elapsedMs) => {
|
|
672
|
-
const elapsedSeconds = (elapsedMs / ONE_SECOND_MS).toFixed(3);
|
|
673
|
-
return `${elapsedSeconds}s`;
|
|
674
|
-
};
|
|
675
|
-
const index$8 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
676
|
-
__proto__: null,
|
|
677
|
-
codemodList,
|
|
678
|
-
codemodUID,
|
|
679
|
-
durationMs,
|
|
680
|
-
highlight,
|
|
681
|
-
path,
|
|
682
|
-
projectType,
|
|
683
|
-
reports,
|
|
684
|
-
transform,
|
|
685
|
-
upgradeStep,
|
|
686
|
-
version,
|
|
687
|
-
versionRange
|
|
688
|
-
}, Symbol.toStringTag, { value: "Module" }));
|
|
689
674
|
const CODEMOD_CODE_SUFFIX = "code";
|
|
690
675
|
const CODEMOD_JSON_SUFFIX = "json";
|
|
691
676
|
const CODEMOD_ALLOWED_SUFFIXES = [CODEMOD_CODE_SUFFIX, CODEMOD_JSON_SUFFIX];
|
|
@@ -738,7 +723,7 @@ class Codemod {
|
|
|
738
723
|
}
|
|
739
724
|
}
|
|
740
725
|
const codemodFactory = (options) => new Codemod(options);
|
|
741
|
-
const index$
|
|
726
|
+
const index$8 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
742
727
|
__proto__: null,
|
|
743
728
|
codemodFactory,
|
|
744
729
|
constants: constants$2
|
|
@@ -850,7 +835,7 @@ const parseCodemodKindFromFilename = (filename) => {
|
|
|
850
835
|
const codemodRepositoryFactory = (cwd = INTERNAL_CODEMODS_DIRECTORY) => {
|
|
851
836
|
return new CodemodRepository(cwd);
|
|
852
837
|
};
|
|
853
|
-
const index$
|
|
838
|
+
const index$7 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
854
839
|
__proto__: null,
|
|
855
840
|
codemodRepositoryFactory,
|
|
856
841
|
constants: constants$1
|
|
@@ -963,6 +948,15 @@ class Upgrader {
|
|
|
963
948
|
this.logger = null;
|
|
964
949
|
this.confirmationCallback = null;
|
|
965
950
|
}
|
|
951
|
+
getNPMPackage() {
|
|
952
|
+
return this.npmPackage;
|
|
953
|
+
}
|
|
954
|
+
getProject() {
|
|
955
|
+
return this.project;
|
|
956
|
+
}
|
|
957
|
+
getTarget() {
|
|
958
|
+
return semVerFactory(this.target.raw);
|
|
959
|
+
}
|
|
966
960
|
setRequirements(requirements) {
|
|
967
961
|
this.requirements = requirements;
|
|
968
962
|
return this;
|
|
@@ -1044,6 +1038,12 @@ class Upgrader {
|
|
|
1044
1038
|
}
|
|
1045
1039
|
return successReport();
|
|
1046
1040
|
}
|
|
1041
|
+
async confirm(message) {
|
|
1042
|
+
if (typeof this.confirmationCallback !== "function") {
|
|
1043
|
+
return true;
|
|
1044
|
+
}
|
|
1045
|
+
return this.confirmationCallback(message);
|
|
1046
|
+
}
|
|
1047
1047
|
async checkRequirements(requirements, context) {
|
|
1048
1048
|
for (const requirement of requirements) {
|
|
1049
1049
|
const { pass, error } = await requirement.test(context);
|
|
@@ -1115,7 +1115,7 @@ class Upgrader {
|
|
|
1115
1115
|
const packageManagerName = await packageManager.getPreferred(projectPath);
|
|
1116
1116
|
this.logger?.debug?.(`Using ${highlight(packageManagerName)} as package manager`);
|
|
1117
1117
|
if (this.isDry) {
|
|
1118
|
-
this.logger?.debug?.(`Skipping dependencies installation (${chalk.italic("dry mode")}`);
|
|
1118
|
+
this.logger?.debug?.(`Skipping dependencies installation (${chalk.italic("dry mode")})`);
|
|
1119
1119
|
return;
|
|
1120
1120
|
}
|
|
1121
1121
|
await packageManager.installDependencies(projectPath, packageManagerName, {
|
|
@@ -1134,23 +1134,28 @@ class Upgrader {
|
|
|
1134
1134
|
}
|
|
1135
1135
|
const resolveNPMTarget = (project, target, npmPackage) => {
|
|
1136
1136
|
if (isSemverInstance(target)) {
|
|
1137
|
-
|
|
1137
|
+
const version2 = npmPackage.findVersion(target);
|
|
1138
|
+
if (!version2) {
|
|
1139
|
+
throw new NPMCandidateNotFoundError(target);
|
|
1140
|
+
}
|
|
1141
|
+
return version2;
|
|
1138
1142
|
}
|
|
1139
1143
|
if (isSemVerReleaseType(target)) {
|
|
1140
1144
|
const range = rangeFromVersions(project.strapiVersion, target);
|
|
1141
1145
|
const npmVersionsMatches = npmPackage.findVersionsInRange(range);
|
|
1142
|
-
|
|
1146
|
+
const version2 = npmVersionsMatches.at(-1);
|
|
1147
|
+
if (!version2) {
|
|
1148
|
+
throw new NPMCandidateNotFoundError(range, `The project is already up-to-date (${target})`);
|
|
1149
|
+
}
|
|
1150
|
+
return version2;
|
|
1143
1151
|
}
|
|
1144
|
-
|
|
1152
|
+
throw new NPMCandidateNotFoundError(target);
|
|
1145
1153
|
};
|
|
1146
1154
|
const upgraderFactory = (project, target, npmPackage) => {
|
|
1147
|
-
const
|
|
1148
|
-
|
|
1149
|
-
throw new Error(`Couldn't find a matching version in the NPM registry for "${target}"`);
|
|
1150
|
-
}
|
|
1151
|
-
const semverTarget = semVerFactory(targetedNPMVersion.version);
|
|
1155
|
+
const npmTarget = resolveNPMTarget(project, target, npmPackage);
|
|
1156
|
+
const semverTarget = semVerFactory(npmTarget.version);
|
|
1152
1157
|
if (semver.eq(semverTarget, project.strapiVersion)) {
|
|
1153
|
-
throw new Error(`The project is already
|
|
1158
|
+
throw new Error(`The project is already using v${semverTarget}`);
|
|
1154
1159
|
}
|
|
1155
1160
|
return new Upgrader(project, semverTarget, npmPackage);
|
|
1156
1161
|
};
|
|
@@ -1161,80 +1166,195 @@ const constants = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePro
|
|
|
1161
1166
|
__proto__: null,
|
|
1162
1167
|
STRAPI_PACKAGE_NAME
|
|
1163
1168
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
1164
|
-
const index$
|
|
1169
|
+
const index$6 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
1165
1170
|
__proto__: null,
|
|
1166
1171
|
constants,
|
|
1167
1172
|
upgraderFactory
|
|
1168
1173
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
1169
|
-
|
|
1170
|
-
|
|
1174
|
+
class Requirement {
|
|
1175
|
+
isRequired;
|
|
1171
1176
|
name;
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
constructor(name) {
|
|
1177
|
+
testCallback;
|
|
1178
|
+
children;
|
|
1179
|
+
constructor(name, testCallback, isRequired) {
|
|
1175
1180
|
this.name = name;
|
|
1176
|
-
this.
|
|
1177
|
-
this.
|
|
1181
|
+
this.testCallback = testCallback;
|
|
1182
|
+
this.isRequired = isRequired ?? true;
|
|
1183
|
+
this.children = [];
|
|
1178
1184
|
}
|
|
1179
|
-
|
|
1180
|
-
|
|
1185
|
+
setChildren(children) {
|
|
1186
|
+
this.children = children;
|
|
1187
|
+
return this;
|
|
1181
1188
|
}
|
|
1182
|
-
|
|
1183
|
-
|
|
1189
|
+
addChild(child) {
|
|
1190
|
+
this.children.push(child);
|
|
1191
|
+
return this;
|
|
1184
1192
|
}
|
|
1185
|
-
|
|
1186
|
-
this.
|
|
1187
|
-
|
|
1193
|
+
asOptional() {
|
|
1194
|
+
const newInstance = requirementFactory(this.name, this.testCallback, false);
|
|
1195
|
+
newInstance.setChildren(this.children);
|
|
1196
|
+
return newInstance;
|
|
1188
1197
|
}
|
|
1189
|
-
|
|
1190
|
-
this.
|
|
1191
|
-
|
|
1198
|
+
asRequired() {
|
|
1199
|
+
const newInstance = requirementFactory(this.name, this.testCallback, true);
|
|
1200
|
+
newInstance.setChildren(this.children);
|
|
1201
|
+
return newInstance;
|
|
1192
1202
|
}
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1203
|
+
async test(context) {
|
|
1204
|
+
try {
|
|
1205
|
+
await this.testCallback?.(context);
|
|
1206
|
+
return ok();
|
|
1207
|
+
} catch (e) {
|
|
1208
|
+
if (e instanceof Error) {
|
|
1209
|
+
return errored(e);
|
|
1210
|
+
}
|
|
1211
|
+
if (typeof e === "string") {
|
|
1212
|
+
return errored(new Error(e));
|
|
1213
|
+
}
|
|
1214
|
+
return errored(new Error("Unknown error"));
|
|
1215
|
+
}
|
|
1196
1216
|
}
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1217
|
+
}
|
|
1218
|
+
const ok = () => ({ pass: true, error: null });
|
|
1219
|
+
const errored = (error) => ({ pass: false, error });
|
|
1220
|
+
const requirementFactory = (name, testCallback, isRequired) => new Requirement(name, testCallback, isRequired);
|
|
1221
|
+
const index$5 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
1222
|
+
__proto__: null,
|
|
1223
|
+
requirementFactory
|
|
1224
|
+
}, Symbol.toStringTag, { value: "Module" }));
|
|
1225
|
+
const REQUIRE_AVAILABLE_NEXT_MAJOR = requirementFactory(
|
|
1226
|
+
"REQUIRE_AVAILABLE_NEXT_MAJOR",
|
|
1227
|
+
(context) => {
|
|
1228
|
+
const { project, target } = context;
|
|
1229
|
+
const currentMajor = project.strapiVersion.major;
|
|
1230
|
+
const targetedMajor = target.major;
|
|
1231
|
+
if (targetedMajor === currentMajor) {
|
|
1232
|
+
throw new Error(`You're already on the latest major version (v${currentMajor})`);
|
|
1233
|
+
}
|
|
1200
1234
|
}
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1235
|
+
);
|
|
1236
|
+
const REQUIRE_LATEST_FOR_CURRENT_MAJOR = requirementFactory(
|
|
1237
|
+
"REQUIRE_LATEST_FOR_CURRENT_MAJOR",
|
|
1238
|
+
(context) => {
|
|
1239
|
+
const { project, target, npmVersionsMatches } = context;
|
|
1240
|
+
const { major: currentMajor } = project.strapiVersion;
|
|
1241
|
+
const invalidMatches = npmVersionsMatches.filter(
|
|
1242
|
+
(match) => semVerFactory(match.version).major === currentMajor
|
|
1243
|
+
);
|
|
1244
|
+
if (invalidMatches.length > 0) {
|
|
1245
|
+
const invalidVersions = invalidMatches.map((match) => match.version);
|
|
1246
|
+
const invalidVersionsCount = invalidVersions.length;
|
|
1247
|
+
throw new Error(
|
|
1248
|
+
`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.`
|
|
1249
|
+
);
|
|
1250
|
+
}
|
|
1206
1251
|
}
|
|
1207
|
-
|
|
1208
|
-
|
|
1252
|
+
);
|
|
1253
|
+
const REQUIRE_GIT_CLEAN_REPOSITORY = requirementFactory(
|
|
1254
|
+
"REQUIRE_GIT_CLEAN_REPOSITORY",
|
|
1255
|
+
async (context) => {
|
|
1256
|
+
const git = simpleGit({ baseDir: context.project.cwd });
|
|
1257
|
+
const status = await git.status();
|
|
1258
|
+
if (!status.isClean()) {
|
|
1259
|
+
throw new Error(
|
|
1260
|
+
"Repository is not clean. Please commit or stash any changes before upgrading"
|
|
1261
|
+
);
|
|
1262
|
+
}
|
|
1209
1263
|
}
|
|
1210
|
-
|
|
1211
|
-
const
|
|
1264
|
+
);
|
|
1265
|
+
const REQUIRE_GIT_REPOSITORY = requirementFactory(
|
|
1266
|
+
"REQUIRE_GIT_REPOSITORY",
|
|
1267
|
+
async (context) => {
|
|
1268
|
+
const git = simpleGit({ baseDir: context.project.cwd });
|
|
1269
|
+
const isRepo = await git.checkIsRepo();
|
|
1270
|
+
if (!isRepo) {
|
|
1271
|
+
throw new Error("Not a git repository (or any of the parent directories)");
|
|
1272
|
+
}
|
|
1273
|
+
}
|
|
1274
|
+
).addChild(REQUIRE_GIT_CLEAN_REPOSITORY.asOptional());
|
|
1275
|
+
const REQUIRE_GIT_INSTALLED = requirementFactory(
|
|
1276
|
+
"REQUIRE_GIT_INSTALLED",
|
|
1277
|
+
async (context) => {
|
|
1278
|
+
const git = simpleGit({ baseDir: context.project.cwd });
|
|
1279
|
+
try {
|
|
1280
|
+
await git.version();
|
|
1281
|
+
} catch {
|
|
1282
|
+
throw new Error("Git is not installed");
|
|
1283
|
+
}
|
|
1284
|
+
}
|
|
1285
|
+
).addChild(REQUIRE_GIT_REPOSITORY.asOptional());
|
|
1286
|
+
const REQUIRE_GIT = requirementFactory("REQUIRE_GIT", null).addChild(
|
|
1287
|
+
REQUIRE_GIT_INSTALLED.asOptional()
|
|
1288
|
+
);
|
|
1289
|
+
const latest = async (upgrader, options) => {
|
|
1290
|
+
if (options.target !== ReleaseType.Latest) {
|
|
1291
|
+
return;
|
|
1292
|
+
}
|
|
1293
|
+
const npmPackage = upgrader.getNPMPackage();
|
|
1294
|
+
const target = upgrader.getTarget();
|
|
1295
|
+
const project = upgrader.getProject();
|
|
1296
|
+
const { strapiVersion: current } = project;
|
|
1297
|
+
const fTargetMajor = highlight(`v${target.major}`);
|
|
1298
|
+
const fCurrentMajor = highlight(`v${current.major}`);
|
|
1299
|
+
const fTarget = version(target);
|
|
1300
|
+
const fCurrent = version(current);
|
|
1301
|
+
const isMajorUpgrade = target.major > current.major;
|
|
1302
|
+
if (isMajorUpgrade) {
|
|
1303
|
+
options.logger.warn(
|
|
1304
|
+
`Detected a major upgrade for the "${highlight(ReleaseType.Latest)}" tag: ${fCurrent} > ${fTarget}`
|
|
1305
|
+
);
|
|
1306
|
+
const newerPackageRelease = npmPackage.findVersionsInRange(rangeFactory(`>${current.raw} <${target.major}`)).at(-1);
|
|
1307
|
+
if (newerPackageRelease) {
|
|
1308
|
+
const fLatest = version(semVerFactory(newerPackageRelease.version));
|
|
1309
|
+
options.logger.warn(
|
|
1310
|
+
`It's recommended to first upgrade to the latest version of ${fCurrentMajor} (${fLatest}) before upgrading to ${fTargetMajor}.`
|
|
1311
|
+
);
|
|
1312
|
+
}
|
|
1313
|
+
const proceedAnyway = await upgrader.confirm(`I know what I'm doing. Proceed anyway!`);
|
|
1314
|
+
if (!proceedAnyway) {
|
|
1315
|
+
throw new AbortedError();
|
|
1316
|
+
}
|
|
1317
|
+
}
|
|
1318
|
+
};
|
|
1212
1319
|
const upgrade = async (options) => {
|
|
1213
1320
|
const timer = timerFactory();
|
|
1214
1321
|
const { logger, codemodsTarget } = options;
|
|
1215
1322
|
const cwd = path$1.resolve(options.cwd ?? process.cwd());
|
|
1216
1323
|
const project = projectFactory(cwd);
|
|
1324
|
+
logger.debug(projectDetails(project));
|
|
1217
1325
|
if (!isApplicationProject(project)) {
|
|
1218
1326
|
throw new Error(
|
|
1219
1327
|
`The "${options.target}" upgrade can only be run on a Strapi project; for plugins, please use "codemods".`
|
|
1220
1328
|
);
|
|
1221
1329
|
}
|
|
1330
|
+
logger.debug(
|
|
1331
|
+
`Application: VERSION=${version(project.packageJSON.version)}; STRAPI_VERSION=${version(project.strapiVersion)}`
|
|
1332
|
+
);
|
|
1222
1333
|
const npmPackage = npmPackageFactory(STRAPI_PACKAGE_NAME);
|
|
1223
1334
|
await npmPackage.refresh();
|
|
1224
1335
|
const upgrader = upgraderFactory(project, options.target, npmPackage).dry(options.dry ?? false).onConfirm(options.confirm ?? null).setLogger(logger);
|
|
1225
1336
|
if (codemodsTarget !== void 0) {
|
|
1226
1337
|
upgrader.overrideCodemodsTarget(codemodsTarget);
|
|
1227
1338
|
}
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
}
|
|
1231
|
-
upgrader.addRequirement(REQUIRE_GIT.asOptional());
|
|
1339
|
+
await runUpgradePrompts(upgrader, options);
|
|
1340
|
+
addUpgradeRequirements(upgrader, options);
|
|
1232
1341
|
const upgradeReport = await upgrader.upgrade();
|
|
1233
1342
|
if (!upgradeReport.success) {
|
|
1234
1343
|
throw upgradeReport.error;
|
|
1235
1344
|
}
|
|
1236
1345
|
timer.stop();
|
|
1237
|
-
logger.info(`Completed in ${durationMs(timer.elapsedMs)}`);
|
|
1346
|
+
logger.info(`Completed in ${durationMs(timer.elapsedMs)}ms`);
|
|
1347
|
+
};
|
|
1348
|
+
const runUpgradePrompts = async (upgrader, options) => {
|
|
1349
|
+
if (options.target === ReleaseType.Latest) {
|
|
1350
|
+
await latest(upgrader, options);
|
|
1351
|
+
}
|
|
1352
|
+
};
|
|
1353
|
+
const addUpgradeRequirements = (upgrader, options) => {
|
|
1354
|
+
if (options.target === ReleaseType.Major) {
|
|
1355
|
+
upgrader.addRequirement(REQUIRE_AVAILABLE_NEXT_MAJOR).addRequirement(REQUIRE_LATEST_FOR_CURRENT_MAJOR);
|
|
1356
|
+
}
|
|
1357
|
+
upgrader.addRequirement(REQUIRE_GIT.asOptional());
|
|
1238
1358
|
};
|
|
1239
1359
|
const resolvePath = (cwd) => path$1.resolve(cwd ?? process.cwd());
|
|
1240
1360
|
const getRangeFromTarget = (currentVersion, target) => {
|
|
@@ -1243,6 +1363,8 @@ const getRangeFromTarget = (currentVersion, target) => {
|
|
|
1243
1363
|
}
|
|
1244
1364
|
const { major, minor, patch } = currentVersion;
|
|
1245
1365
|
switch (target) {
|
|
1366
|
+
case ReleaseType.Latest:
|
|
1367
|
+
throw new Error("Can't use <latest> to create a codemods range: not implemented");
|
|
1246
1368
|
case ReleaseType.Major:
|
|
1247
1369
|
return rangeFactory(`${major}`);
|
|
1248
1370
|
case ReleaseType.Minor:
|
|
@@ -1268,7 +1390,7 @@ const runCodemods = async (options) => {
|
|
|
1268
1390
|
const cwd = resolvePath(options.cwd);
|
|
1269
1391
|
const project = projectFactory(cwd);
|
|
1270
1392
|
const range = findRangeFromTarget(project, options.target);
|
|
1271
|
-
logger.debug(
|
|
1393
|
+
logger.debug(projectDetails(project));
|
|
1272
1394
|
logger.debug(`Range: set to ${versionRange(range)}`);
|
|
1273
1395
|
const codemodRunner = codemodRunnerFactory(project, range).dry(options.dry ?? false).onSelectCodemods(options.selectCodemods ?? null).setLogger(logger);
|
|
1274
1396
|
let report;
|
|
@@ -1289,7 +1411,7 @@ const listCodemods = async (options) => {
|
|
|
1289
1411
|
const cwd = resolvePath(options.cwd);
|
|
1290
1412
|
const project = projectFactory(cwd);
|
|
1291
1413
|
const range = findRangeFromTarget(project, target);
|
|
1292
|
-
logger.debug(
|
|
1414
|
+
logger.debug(projectDetails(project));
|
|
1293
1415
|
logger.debug(`Range: set to ${versionRange(range)}`);
|
|
1294
1416
|
const repo = codemodRepositoryFactory();
|
|
1295
1417
|
repo.refresh();
|
|
@@ -1400,18 +1522,18 @@ const index$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePrope
|
|
|
1400
1522
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
1401
1523
|
const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
1402
1524
|
__proto__: null,
|
|
1403
|
-
codemod: index$
|
|
1404
|
-
codemodRepository: index$
|
|
1525
|
+
codemod: index$8,
|
|
1526
|
+
codemodRepository: index$7,
|
|
1405
1527
|
error: index$9,
|
|
1406
|
-
f: index$
|
|
1528
|
+
f: index$f,
|
|
1407
1529
|
fileScanner: index$d,
|
|
1408
1530
|
logger: index$3,
|
|
1409
1531
|
project: index$a,
|
|
1410
1532
|
report: index$2,
|
|
1411
|
-
requirement: index$
|
|
1533
|
+
requirement: index$5,
|
|
1412
1534
|
runner: index$1,
|
|
1413
|
-
timer: index$
|
|
1414
|
-
upgrader: index$
|
|
1535
|
+
timer: index$g,
|
|
1536
|
+
upgrader: index$6,
|
|
1415
1537
|
version: index$e
|
|
1416
1538
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
1417
1539
|
export {
|