@strapi/upgrade 0.0.0-experimental.d362bf200f5f9359a4bbd4a549603de5ee1f04ca → 0.0.0-experimental.d3cdf79a0d5f803dfeb6d0f055bb2f3b913bb015
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +19 -4
- package/README.md +1 -1
- package/dist/cli.js +1578 -5
- package/dist/cli.js.map +1 -1
- package/dist/index.js +671 -412
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +667 -409
- package/dist/index.mjs.map +1 -1
- package/dist/modules/codemod/codemod.d.ts +4 -2
- package/dist/modules/codemod/codemod.d.ts.map +1 -1
- package/dist/modules/codemod/types.d.ts +8 -1
- package/dist/modules/codemod/types.d.ts.map +1 -1
- package/dist/modules/codemod-repository/constants.d.ts.map +1 -1
- package/dist/modules/codemod-repository/repository.d.ts +5 -5
- package/dist/modules/codemod-repository/repository.d.ts.map +1 -1
- package/dist/modules/codemod-repository/types.d.ts +7 -3
- package/dist/modules/codemod-repository/types.d.ts.map +1 -1
- package/dist/modules/codemod-runner/codemod-runner.d.ts +6 -3
- package/dist/modules/codemod-runner/codemod-runner.d.ts.map +1 -1
- package/dist/modules/codemod-runner/index.d.ts +1 -0
- package/dist/modules/codemod-runner/index.d.ts.map +1 -1
- package/dist/modules/codemod-runner/types.d.ts +1 -0
- package/dist/modules/codemod-runner/types.d.ts.map +1 -1
- package/dist/modules/error/utils.d.ts +8 -0
- package/dist/modules/error/utils.d.ts.map +1 -1
- package/dist/modules/file-scanner/scanner.d.ts.map +1 -1
- package/dist/modules/format/formats.d.ts +6 -0
- package/dist/modules/format/formats.d.ts.map +1 -1
- package/dist/modules/project/constants.d.ts +6 -5
- package/dist/modules/project/constants.d.ts.map +1 -1
- package/dist/modules/project/project.d.ts +17 -3
- package/dist/modules/project/project.d.ts.map +1 -1
- package/dist/modules/project/types.d.ts +4 -0
- package/dist/modules/project/types.d.ts.map +1 -1
- package/dist/modules/project/utils.d.ts +1 -1
- package/dist/modules/project/utils.d.ts.map +1 -1
- package/dist/modules/report/report.d.ts.map +1 -1
- package/dist/modules/runner/json/transform.d.ts.map +1 -1
- package/dist/modules/upgrader/types.d.ts +6 -0
- package/dist/modules/upgrader/types.d.ts.map +1 -1
- package/dist/modules/upgrader/upgrader.d.ts +4 -0
- package/dist/modules/upgrader/upgrader.d.ts.map +1 -1
- package/dist/modules/version/range.d.ts +2 -0
- package/dist/modules/version/range.d.ts.map +1 -1
- package/dist/modules/version/types.d.ts +2 -1
- package/dist/modules/version/types.d.ts.map +1 -1
- package/dist/tasks/codemods/index.d.ts +2 -1
- package/dist/tasks/codemods/index.d.ts.map +1 -1
- package/dist/tasks/codemods/list-codemods.d.ts +3 -0
- package/dist/tasks/codemods/list-codemods.d.ts.map +1 -0
- package/dist/tasks/codemods/run-codemods.d.ts +3 -0
- package/dist/tasks/codemods/run-codemods.d.ts.map +1 -0
- package/dist/tasks/codemods/types.d.ts +9 -3
- package/dist/tasks/codemods/types.d.ts.map +1 -1
- package/dist/tasks/codemods/utils.d.ts +6 -0
- package/dist/tasks/codemods/utils.d.ts.map +1 -0
- package/dist/tasks/index.d.ts +1 -1
- package/dist/tasks/index.d.ts.map +1 -1
- package/dist/tasks/upgrade/prompts/index.d.ts +2 -0
- package/dist/tasks/upgrade/prompts/index.d.ts.map +1 -0
- package/dist/tasks/upgrade/prompts/latest.d.ts +9 -0
- package/dist/tasks/upgrade/prompts/latest.d.ts.map +1 -0
- package/dist/tasks/upgrade/requirements/major.d.ts.map +1 -1
- package/dist/tasks/upgrade/upgrade.d.ts.map +1 -1
- package/package.json +11 -11
- package/resources/codemods/5.0.0/comment-out-lifecycle-files.code.ts +63 -0
- package/resources/codemods/5.0.0/dependency-upgrade-react-and-react-dom.json.ts +67 -0
- package/resources/codemods/5.0.0/dependency-upgrade-styled-components.json.ts +49 -0
- package/resources/codemods/5.0.0/deprecate-helper-plugin.code.ts +192 -0
- package/resources/codemods/5.0.0/entity-service-document-service.code.ts +437 -0
- package/resources/codemods/5.0.0/sqlite3-to-better-sqlite3.json.ts +0 -1
- package/resources/codemods/5.0.0/strapi-public-interface.code.ts +126 -0
- package/resources/codemods/5.0.0/utils-public-interface.code.ts +320 -0
- package/resources/codemods/5.1.0/dependency-better-sqlite3.json.ts +48 -0
- package/resources/utils/change-import.ts +118 -0
- package/resources/utils/replace-jsx.ts +49 -0
- package/dist/_chunks/codemod-runner-mXNzVpHm.js +0 -798
- package/dist/_chunks/codemod-runner-mXNzVpHm.js.map +0 -1
- package/dist/_chunks/codemods-S4mNX9Qg.js +0 -105
- package/dist/_chunks/codemods-S4mNX9Qg.js.map +0 -1
- package/dist/_chunks/index-Pt-TU9MN.js +0 -103
- package/dist/_chunks/index-Pt-TU9MN.js.map +0 -1
- package/dist/_chunks/upgrade-aWNYibWB.js +0 -361
- package/dist/_chunks/upgrade-aWNYibWB.js.map +0 -1
- package/dist/tasks/codemods/codemods.d.ts +0 -3
- package/dist/tasks/codemods/codemods.d.ts.map +0 -1
package/dist/index.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 } 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();
|
|
200
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();
|
|
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");
|
|
@@ -253,25 +189,75 @@ const rangeFromVersions = (currentVersion, target) => {
|
|
|
253
189
|
}
|
|
254
190
|
throw new Error(`Invalid target set: ${target}`);
|
|
255
191
|
};
|
|
192
|
+
const isValidStringifiedRange = (str) => semver.validRange(str) !== null;
|
|
193
|
+
const isRangeInstance = (range) => {
|
|
194
|
+
return range instanceof semver.Range;
|
|
195
|
+
};
|
|
256
196
|
const index$e = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
257
197
|
__proto__: null,
|
|
258
198
|
Version: types,
|
|
259
199
|
isLiteralSemVer,
|
|
200
|
+
isRangeInstance,
|
|
260
201
|
isSemVerReleaseType,
|
|
261
202
|
isSemverInstance,
|
|
262
203
|
isValidSemVer,
|
|
204
|
+
isValidStringifiedRange,
|
|
263
205
|
rangeFactory,
|
|
264
206
|
rangeFromReleaseType,
|
|
265
207
|
rangeFromVersions,
|
|
266
208
|
semVerFactory
|
|
267
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);
|
|
268
252
|
class FileScanner {
|
|
269
253
|
cwd;
|
|
270
254
|
constructor(cwd) {
|
|
271
255
|
this.cwd = cwd;
|
|
272
256
|
}
|
|
273
257
|
scan(patterns) {
|
|
274
|
-
const filenames =
|
|
258
|
+
const filenames = fastglob.sync(patterns, {
|
|
259
|
+
cwd: this.cwd
|
|
260
|
+
});
|
|
275
261
|
return filenames.map((filename) => path$1.join(this.cwd, filename));
|
|
276
262
|
}
|
|
277
263
|
}
|
|
@@ -309,6 +295,46 @@ const index$c = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePrope
|
|
|
309
295
|
__proto__: null,
|
|
310
296
|
codeRunnerFactory
|
|
311
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
|
+
};
|
|
312
338
|
const transformJSON = async (codemodPath, paths, config) => {
|
|
313
339
|
const { dry } = config;
|
|
314
340
|
const startTime = process.hrtime();
|
|
@@ -320,7 +346,11 @@ const transformJSON = async (codemodPath, paths, config) => {
|
|
|
320
346
|
timeElapsed: "",
|
|
321
347
|
stats: {}
|
|
322
348
|
};
|
|
323
|
-
const esbuildOptions = {
|
|
349
|
+
const esbuildOptions = {
|
|
350
|
+
extensions: [".js", ".mjs", ".ts"],
|
|
351
|
+
hookIgnoreNodeModules: false,
|
|
352
|
+
hookMatcher: isEqual(codemodPath)
|
|
353
|
+
};
|
|
324
354
|
const { unregister } = register(esbuildOptions);
|
|
325
355
|
const module = require(codemodPath);
|
|
326
356
|
unregister();
|
|
@@ -365,8 +395,10 @@ const index$b = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePrope
|
|
|
365
395
|
jsonRunnerFactory
|
|
366
396
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
367
397
|
const PROJECT_PACKAGE_JSON = "package.json";
|
|
368
|
-
const
|
|
369
|
-
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 = [
|
|
370
402
|
// Source files
|
|
371
403
|
"js",
|
|
372
404
|
"mjs",
|
|
@@ -375,22 +407,19 @@ const PROJECT_DEFAULT_CODE_EXTENSIONS = [
|
|
|
375
407
|
"jsx",
|
|
376
408
|
"tsx"
|
|
377
409
|
];
|
|
378
|
-
const
|
|
379
|
-
const
|
|
380
|
-
...PROJECT_DEFAULT_CODE_EXTENSIONS,
|
|
381
|
-
...PROJECT_DEFAULT_JSON_EXTENSIONS
|
|
382
|
-
];
|
|
383
|
-
const PROJECT_DEFAULT_PATTERNS = ["package.json"];
|
|
410
|
+
const PROJECT_JSON_EXTENSIONS = ["json"];
|
|
411
|
+
const PROJECT_ALLOWED_EXTENSIONS = [...PROJECT_CODE_EXTENSIONS, ...PROJECT_JSON_EXTENSIONS];
|
|
384
412
|
const SCOPED_STRAPI_PACKAGE_PREFIX = "@strapi/";
|
|
385
413
|
const STRAPI_DEPENDENCY_NAME = `${SCOPED_STRAPI_PACKAGE_PREFIX}strapi`;
|
|
386
414
|
const constants$3 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
387
415
|
__proto__: null,
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
PROJECT_DEFAULT_PATTERNS,
|
|
416
|
+
PROJECT_ALLOWED_EXTENSIONS,
|
|
417
|
+
PROJECT_APP_ALLOWED_ROOT_PATHS,
|
|
418
|
+
PROJECT_CODE_EXTENSIONS,
|
|
419
|
+
PROJECT_JSON_EXTENSIONS,
|
|
393
420
|
PROJECT_PACKAGE_JSON,
|
|
421
|
+
PROJECT_PLUGIN_ALLOWED_ROOT_PATHS,
|
|
422
|
+
PROJECT_PLUGIN_ROOT_FILES,
|
|
394
423
|
SCOPED_STRAPI_PACKAGE_PREFIX,
|
|
395
424
|
STRAPI_DEPENDENCY_NAME
|
|
396
425
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
@@ -400,11 +429,13 @@ class Project {
|
|
|
400
429
|
files;
|
|
401
430
|
packageJSONPath;
|
|
402
431
|
packageJSON;
|
|
403
|
-
|
|
432
|
+
paths;
|
|
433
|
+
constructor(cwd, config) {
|
|
404
434
|
if (!fse.pathExistsSync(cwd)) {
|
|
405
435
|
throw new Error(`ENOENT: no such file or directory, access '${cwd}'`);
|
|
406
436
|
}
|
|
407
437
|
this.cwd = cwd;
|
|
438
|
+
this.paths = config.paths;
|
|
408
439
|
this.refresh();
|
|
409
440
|
}
|
|
410
441
|
getFilesByExtensions(extensions) {
|
|
@@ -418,10 +449,10 @@ class Project {
|
|
|
418
449
|
this.refreshProjectFiles();
|
|
419
450
|
return this;
|
|
420
451
|
}
|
|
421
|
-
async runCodemods(
|
|
452
|
+
async runCodemods(codemods, options) {
|
|
422
453
|
const runners = this.createProjectCodemodsRunners(options.dry);
|
|
423
454
|
const reports2 = [];
|
|
424
|
-
for (const codemod of
|
|
455
|
+
for (const codemod of codemods) {
|
|
425
456
|
for (const runner of runners) {
|
|
426
457
|
if (runner.valid(codemod)) {
|
|
427
458
|
const report = await runner.run(codemod);
|
|
@@ -432,12 +463,8 @@ class Project {
|
|
|
432
463
|
return reports2;
|
|
433
464
|
}
|
|
434
465
|
createProjectCodemodsRunners(dry = false) {
|
|
435
|
-
const jsonExtensions =
|
|
436
|
-
|
|
437
|
-
);
|
|
438
|
-
const codeExtensions = PROJECT_DEFAULT_CODE_EXTENSIONS.map(
|
|
439
|
-
(ext) => `.${ext}`
|
|
440
|
-
);
|
|
466
|
+
const jsonExtensions = PROJECT_JSON_EXTENSIONS.map((ext) => `.${ext}`);
|
|
467
|
+
const codeExtensions = PROJECT_CODE_EXTENSIONS.map((ext) => `.${ext}`);
|
|
441
468
|
const jsonFiles = this.getFilesByExtensions(jsonExtensions);
|
|
442
469
|
const codeFiles = this.getFilesByExtensions(codeExtensions);
|
|
443
470
|
const codeRunner = codeRunnerFactory(codeFiles, {
|
|
@@ -445,7 +472,7 @@ class Project {
|
|
|
445
472
|
parser: "ts",
|
|
446
473
|
runInBand: true,
|
|
447
474
|
babel: true,
|
|
448
|
-
extensions:
|
|
475
|
+
extensions: PROJECT_CODE_EXTENSIONS.join(","),
|
|
449
476
|
// Don't output any log coming from the runner
|
|
450
477
|
print: false,
|
|
451
478
|
silent: true,
|
|
@@ -466,23 +493,32 @@ class Project {
|
|
|
466
493
|
this.packageJSON = JSON.parse(packageJSONBuffer.toString());
|
|
467
494
|
}
|
|
468
495
|
refreshProjectFiles() {
|
|
469
|
-
const allowedRootPaths = formatGlobCollectionPattern(
|
|
470
|
-
PROJECT_DEFAULT_ALLOWED_ROOT_PATHS
|
|
471
|
-
);
|
|
472
|
-
const allowedExtensions = formatGlobCollectionPattern(
|
|
473
|
-
PROJECT_DEFAULT_ALLOWED_EXTENSIONS
|
|
474
|
-
);
|
|
475
|
-
const projectFilesPattern = `./${allowedRootPaths}/**/*.${allowedExtensions}`;
|
|
476
|
-
const patterns = [projectFilesPattern, ...PROJECT_DEFAULT_PATTERNS];
|
|
477
496
|
const scanner = fileScannerFactory(this.cwd);
|
|
478
|
-
this.files = scanner.scan(
|
|
497
|
+
this.files = scanner.scan(this.paths);
|
|
479
498
|
}
|
|
480
499
|
}
|
|
481
500
|
class AppProject extends Project {
|
|
482
501
|
strapiVersion;
|
|
483
|
-
type = "
|
|
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
|
+
}
|
|
484
520
|
constructor(cwd) {
|
|
485
|
-
super(cwd);
|
|
521
|
+
super(cwd, { paths: AppProject.paths });
|
|
486
522
|
this.refreshStrapiVersion();
|
|
487
523
|
}
|
|
488
524
|
refresh() {
|
|
@@ -537,6 +573,30 @@ const formatGlobCollectionPattern = (collection) => {
|
|
|
537
573
|
};
|
|
538
574
|
class PluginProject extends Project {
|
|
539
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
|
+
}
|
|
540
600
|
}
|
|
541
601
|
const isPlugin = (cwd) => {
|
|
542
602
|
const packageJSONPath = path$1.join(cwd, PROJECT_PACKAGE_JSON);
|
|
@@ -551,10 +611,7 @@ const isPlugin = (cwd) => {
|
|
|
551
611
|
};
|
|
552
612
|
const projectFactory = (cwd) => {
|
|
553
613
|
fse.accessSync(cwd);
|
|
554
|
-
|
|
555
|
-
return new PluginProject(cwd);
|
|
556
|
-
}
|
|
557
|
-
return new AppProject(cwd);
|
|
614
|
+
return isPlugin(cwd) ? new PluginProject(cwd) : new AppProject(cwd);
|
|
558
615
|
};
|
|
559
616
|
const isPluginProject = (project) => {
|
|
560
617
|
return project instanceof PluginProject;
|
|
@@ -564,12 +621,12 @@ function assertPluginProject(project) {
|
|
|
564
621
|
throw new Error("Project is not a plugin");
|
|
565
622
|
}
|
|
566
623
|
}
|
|
567
|
-
const
|
|
624
|
+
const isApplicationProject = (project) => {
|
|
568
625
|
return project instanceof AppProject;
|
|
569
626
|
};
|
|
570
627
|
function assertAppProject(project) {
|
|
571
|
-
if (!
|
|
572
|
-
throw new Error("Project is not an
|
|
628
|
+
if (!isApplicationProject(project)) {
|
|
629
|
+
throw new Error("Project is not an application");
|
|
573
630
|
}
|
|
574
631
|
}
|
|
575
632
|
const index$a = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
@@ -577,7 +634,7 @@ const index$a = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePrope
|
|
|
577
634
|
assertAppProject,
|
|
578
635
|
assertPluginProject,
|
|
579
636
|
constants: constants$3,
|
|
580
|
-
|
|
637
|
+
isApplicationProject,
|
|
581
638
|
isPluginProject,
|
|
582
639
|
projectFactory
|
|
583
640
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
@@ -586,70 +643,33 @@ class UnexpectedError extends Error {
|
|
|
586
643
|
super("Unexpected Error");
|
|
587
644
|
}
|
|
588
645
|
}
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
const highlight = (arg) => chalk.bold.underline(arg);
|
|
610
|
-
const upgradeStep = (text, step) => {
|
|
611
|
-
return chalk.bold(`(${step[0]}/${step[1]}) ${text}...`);
|
|
612
|
-
};
|
|
613
|
-
const reports = (reports2) => {
|
|
614
|
-
const rows = reports2.map(({ codemod, report }, i) => {
|
|
615
|
-
const fIndex = chalk.grey(i);
|
|
616
|
-
const fVersion = chalk.magenta(codemod.version);
|
|
617
|
-
const fKind = chalk.yellow(codemod.kind);
|
|
618
|
-
const fFormattedTransformPath = chalk.cyan(codemod.format());
|
|
619
|
-
const fTimeElapsed = i === 0 ? `${report.timeElapsed}s ${chalk.dim.italic("(cold start)")}` : `${report.timeElapsed}s`;
|
|
620
|
-
const fAffected = report.ok > 0 ? chalk.green(report.ok) : chalk.grey(0);
|
|
621
|
-
const fUnchanged = report.ok === 0 ? chalk.red(report.nochange) : chalk.grey(report.nochange);
|
|
622
|
-
return [fIndex, fVersion, fKind, fFormattedTransformPath, fAffected, fUnchanged, fTimeElapsed];
|
|
623
|
-
});
|
|
624
|
-
const table = new CliTable3({
|
|
625
|
-
style: { compact: true },
|
|
626
|
-
head: [
|
|
627
|
-
chalk.bold.grey("N°"),
|
|
628
|
-
chalk.bold.magenta("Version"),
|
|
629
|
-
chalk.bold.yellow("Kind"),
|
|
630
|
-
chalk.bold.cyan("Name"),
|
|
631
|
-
chalk.bold.green("Affected"),
|
|
632
|
-
chalk.bold.red("Unchanged"),
|
|
633
|
-
chalk.bold.blue("Duration")
|
|
634
|
-
]
|
|
635
|
-
});
|
|
636
|
-
table.push(...rows);
|
|
637
|
-
return table.toString();
|
|
638
|
-
};
|
|
639
|
-
const durationMs = (elapsedMs) => {
|
|
640
|
-
const elapsedSeconds = (elapsedMs / ONE_SECOND_MS).toFixed(3);
|
|
641
|
-
return `${elapsedSeconds}s`;
|
|
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
|
+
}
|
|
658
|
+
const unknownToError = (e) => {
|
|
659
|
+
if (e instanceof Error) {
|
|
660
|
+
return e;
|
|
661
|
+
}
|
|
662
|
+
if (typeof e === "string") {
|
|
663
|
+
return new Error(e);
|
|
664
|
+
}
|
|
665
|
+
return new UnexpectedError();
|
|
642
666
|
};
|
|
643
|
-
const index$
|
|
667
|
+
const index$9 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
644
668
|
__proto__: null,
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
transform,
|
|
650
|
-
upgradeStep,
|
|
651
|
-
version,
|
|
652
|
-
versionRange
|
|
669
|
+
AbortedError,
|
|
670
|
+
NPMCandidateNotFoundError,
|
|
671
|
+
UnexpectedError,
|
|
672
|
+
unknownToError
|
|
653
673
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
654
674
|
const CODEMOD_CODE_SUFFIX = "code";
|
|
655
675
|
const CODEMOD_JSON_SUFFIX = "json";
|
|
@@ -667,6 +687,7 @@ const constants$2 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineP
|
|
|
667
687
|
CODEMOD_JSON_SUFFIX
|
|
668
688
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
669
689
|
class Codemod {
|
|
690
|
+
uid;
|
|
670
691
|
kind;
|
|
671
692
|
version;
|
|
672
693
|
baseDirectory;
|
|
@@ -678,17 +699,49 @@ class Codemod {
|
|
|
678
699
|
this.baseDirectory = options.baseDirectory;
|
|
679
700
|
this.filename = options.filename;
|
|
680
701
|
this.path = path$1.join(this.baseDirectory, this.version.raw, this.filename);
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
702
|
+
this.uid = this.createUID();
|
|
703
|
+
}
|
|
704
|
+
createUID() {
|
|
705
|
+
const name = this.format({ stripExtension: true, stripKind: true, stripHyphens: false });
|
|
706
|
+
const kind = this.kind;
|
|
707
|
+
const version2 = this.version.raw;
|
|
708
|
+
return `${version2}-${name}-${kind}`;
|
|
709
|
+
}
|
|
710
|
+
format(options) {
|
|
711
|
+
const { stripExtension = true, stripKind = true, stripHyphens = true } = options ?? {};
|
|
712
|
+
let formatted = this.filename;
|
|
713
|
+
if (stripExtension) {
|
|
714
|
+
formatted = formatted.replace(new RegExp(`\\.${CODEMOD_EXTENSION}$`, "i"), "");
|
|
715
|
+
}
|
|
716
|
+
if (stripKind) {
|
|
717
|
+
formatted = formatted.replace(`.${CODEMOD_CODE_SUFFIX}`, "").replace(`.${CODEMOD_JSON_SUFFIX}`, "");
|
|
718
|
+
}
|
|
719
|
+
if (stripHyphens) {
|
|
720
|
+
formatted = formatted.replaceAll("-", " ");
|
|
721
|
+
}
|
|
722
|
+
return formatted;
|
|
684
723
|
}
|
|
685
724
|
}
|
|
686
725
|
const codemodFactory = (options) => new Codemod(options);
|
|
687
|
-
const index$
|
|
726
|
+
const index$8 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
688
727
|
__proto__: null,
|
|
689
728
|
codemodFactory,
|
|
690
729
|
constants: constants$2
|
|
691
730
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
731
|
+
const INTERNAL_CODEMODS_DIRECTORY = path$1.join(
|
|
732
|
+
__dirname,
|
|
733
|
+
// upgrade/dist
|
|
734
|
+
"..",
|
|
735
|
+
// upgrade
|
|
736
|
+
"resources",
|
|
737
|
+
// upgrade/resources
|
|
738
|
+
"codemods"
|
|
739
|
+
// upgrade/resources/codemods
|
|
740
|
+
);
|
|
741
|
+
const constants$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
742
|
+
__proto__: null,
|
|
743
|
+
INTERNAL_CODEMODS_DIRECTORY
|
|
744
|
+
}, Symbol.toStringTag, { value: "Module" }));
|
|
692
745
|
class CodemodRepository {
|
|
693
746
|
groups;
|
|
694
747
|
versions;
|
|
@@ -707,29 +760,47 @@ class CodemodRepository {
|
|
|
707
760
|
count(version2) {
|
|
708
761
|
return this.findByVersion(version2).length;
|
|
709
762
|
}
|
|
710
|
-
|
|
711
|
-
return this.findByRange(range).length;
|
|
712
|
-
}
|
|
713
|
-
exists(version2) {
|
|
763
|
+
versionExists(version2) {
|
|
714
764
|
return version2.raw in this.groups;
|
|
715
765
|
}
|
|
716
|
-
|
|
766
|
+
has(uid) {
|
|
767
|
+
const result = this.find({ uids: [uid] });
|
|
768
|
+
if (result.length !== 1) {
|
|
769
|
+
return false;
|
|
770
|
+
}
|
|
771
|
+
const { codemods } = result[0];
|
|
772
|
+
return codemods.length === 1 && codemods[0].uid === uid;
|
|
773
|
+
}
|
|
774
|
+
find(q) {
|
|
717
775
|
const entries = Object.entries(this.groups);
|
|
718
|
-
return entries.filter(
|
|
776
|
+
return entries.filter(maybeFilterByRange).map(([version2, codemods]) => ({
|
|
719
777
|
version: semVerFactory(version2),
|
|
720
|
-
|
|
721
|
-
|
|
778
|
+
// Filter by UID if provided in the query
|
|
779
|
+
codemods: codemods.filter(maybeFilterByUIDs)
|
|
780
|
+
})).filter(({ codemods }) => codemods.length > 0);
|
|
781
|
+
function maybeFilterByRange([version2]) {
|
|
782
|
+
if (!isRangeInstance(q.range)) {
|
|
783
|
+
return true;
|
|
784
|
+
}
|
|
785
|
+
return q.range.test(version2);
|
|
786
|
+
}
|
|
787
|
+
function maybeFilterByUIDs(codemod) {
|
|
788
|
+
if (q.uids === void 0) {
|
|
789
|
+
return true;
|
|
790
|
+
}
|
|
791
|
+
return q.uids.includes(codemod.uid);
|
|
792
|
+
}
|
|
722
793
|
}
|
|
723
794
|
findByVersion(version2) {
|
|
724
795
|
const literalVersion = version2.raw;
|
|
725
|
-
const
|
|
726
|
-
return
|
|
796
|
+
const codemods = this.groups[literalVersion];
|
|
797
|
+
return codemods ?? [];
|
|
727
798
|
}
|
|
728
799
|
findAll() {
|
|
729
800
|
const entries = Object.entries(this.groups);
|
|
730
|
-
return entries.map(([version2,
|
|
801
|
+
return entries.map(([version2, codemods]) => ({
|
|
731
802
|
version: semVerFactory(version2),
|
|
732
|
-
codemods
|
|
803
|
+
codemods
|
|
733
804
|
}));
|
|
734
805
|
}
|
|
735
806
|
refreshAvailableVersions() {
|
|
@@ -761,19 +832,10 @@ const parseCodemodKindFromFilename = (filename) => {
|
|
|
761
832
|
assert(CODEMOD_ALLOWED_SUFFIXES.includes(kind));
|
|
762
833
|
return kind;
|
|
763
834
|
};
|
|
764
|
-
const codemodRepositoryFactory = (cwd) =>
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
"..",
|
|
769
|
-
"resources",
|
|
770
|
-
"codemods"
|
|
771
|
-
);
|
|
772
|
-
const constants$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
773
|
-
__proto__: null,
|
|
774
|
-
INTERNAL_CODEMODS_DIRECTORY
|
|
775
|
-
}, Symbol.toStringTag, { value: "Module" }));
|
|
776
|
-
const index$6 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
835
|
+
const codemodRepositoryFactory = (cwd = INTERNAL_CODEMODS_DIRECTORY) => {
|
|
836
|
+
return new CodemodRepository(cwd);
|
|
837
|
+
};
|
|
838
|
+
const index$7 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
777
839
|
__proto__: null,
|
|
778
840
|
codemodRepositoryFactory,
|
|
779
841
|
constants: constants$1
|
|
@@ -807,40 +869,59 @@ class CodemodRunner {
|
|
|
807
869
|
this.isDry = enabled;
|
|
808
870
|
return this;
|
|
809
871
|
}
|
|
810
|
-
|
|
872
|
+
createRepository(codemodsDirectory) {
|
|
811
873
|
const repository = codemodRepositoryFactory(
|
|
812
874
|
codemodsDirectory ?? INTERNAL_CODEMODS_DIRECTORY
|
|
813
875
|
);
|
|
814
876
|
repository.refresh();
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
if (
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
} else {
|
|
822
|
-
this.logger?.debug(`Found no codemods to run`);
|
|
823
|
-
}
|
|
824
|
-
return successReport$1();
|
|
825
|
-
}
|
|
826
|
-
if (this.range) {
|
|
827
|
-
this.logger?.debug(
|
|
828
|
-
`Found codemods for ${highlight(versionedCodemods.length)} version(s) using ${this.range}`
|
|
877
|
+
return repository;
|
|
878
|
+
}
|
|
879
|
+
async safeRunAndReport(codemods) {
|
|
880
|
+
if (this.isDry) {
|
|
881
|
+
this.logger?.warn?.(
|
|
882
|
+
"Running the codemods in dry mode. No files will be modified during the process."
|
|
829
883
|
);
|
|
830
|
-
} else {
|
|
831
|
-
this.logger?.debug(`Found codemods for ${highlight(versionedCodemods.length)} version(s)`);
|
|
832
884
|
}
|
|
833
|
-
versionedCodemods.forEach(
|
|
834
|
-
({ version: version$1, codemods: codemods22 }) => this.logger?.debug(`- ${version(version$1)} (${codemods22.length})`)
|
|
835
|
-
);
|
|
836
|
-
const codemods2 = versionedCodemods.map(({ codemods: codemods22 }) => codemods22).flat();
|
|
837
885
|
try {
|
|
838
|
-
const reports$1 = await this.project.runCodemods(
|
|
839
|
-
this.logger?.raw(reports(reports$1));
|
|
886
|
+
const reports$1 = await this.project.runCodemods(codemods, { dry: this.isDry });
|
|
887
|
+
this.logger?.raw?.(reports(reports$1));
|
|
888
|
+
if (!this.isDry) {
|
|
889
|
+
const nbAffectedTotal = reports$1.flatMap((report) => report.report.ok).reduce((acc, nb) => acc + nb, 0);
|
|
890
|
+
this.logger?.debug?.(
|
|
891
|
+
`Successfully ran ${highlight(codemods.length)} codemod(s), ${highlight(nbAffectedTotal)} change(s) have been detected`
|
|
892
|
+
);
|
|
893
|
+
}
|
|
894
|
+
return successReport$1();
|
|
840
895
|
} catch (e) {
|
|
841
896
|
return erroredReport$1(unknownToError(e));
|
|
842
897
|
}
|
|
843
|
-
|
|
898
|
+
}
|
|
899
|
+
async runByUID(uid, codemodsDirectory) {
|
|
900
|
+
const repository = this.createRepository(codemodsDirectory);
|
|
901
|
+
if (!repository.has(uid)) {
|
|
902
|
+
throw new Error(`Unknown codemod UID provided: ${uid}`);
|
|
903
|
+
}
|
|
904
|
+
const codemods = repository.find({ uids: [uid] }).flatMap(({ codemods: codemods2 }) => codemods2);
|
|
905
|
+
return this.safeRunAndReport(codemods);
|
|
906
|
+
}
|
|
907
|
+
async run(codemodsDirectory) {
|
|
908
|
+
const repository = this.createRepository(codemodsDirectory);
|
|
909
|
+
const codemodsInRange = repository.find({ range: this.range });
|
|
910
|
+
const selectedCodemods = this.selectCodemodsCallback ? await this.selectCodemodsCallback(codemodsInRange) : codemodsInRange;
|
|
911
|
+
if (selectedCodemods.length === 0) {
|
|
912
|
+
this.logger?.debug?.(`Found no codemods to run for ${versionRange(this.range)}`);
|
|
913
|
+
return successReport$1();
|
|
914
|
+
}
|
|
915
|
+
const codemods = selectedCodemods.flatMap(({ codemods: codemods2 }) => codemods2);
|
|
916
|
+
const codemodsByVersion = groupBy("version", codemods);
|
|
917
|
+
const fRange = versionRange(this.range);
|
|
918
|
+
this.logger?.debug?.(
|
|
919
|
+
`Found ${highlight(codemods.length)} codemods for ${highlight(size(codemodsByVersion))} version(s) using ${fRange}`
|
|
920
|
+
);
|
|
921
|
+
for (const [version$1, codemods2] of Object.entries(codemodsByVersion)) {
|
|
922
|
+
this.logger?.debug?.(`- ${version(semVerFactory(version$1))} (${codemods2.length})`);
|
|
923
|
+
}
|
|
924
|
+
return this.safeRunAndReport(codemods);
|
|
844
925
|
}
|
|
845
926
|
}
|
|
846
927
|
const codemodRunnerFactory = (project, range) => {
|
|
@@ -867,6 +948,15 @@ class Upgrader {
|
|
|
867
948
|
this.logger = null;
|
|
868
949
|
this.confirmationCallback = null;
|
|
869
950
|
}
|
|
951
|
+
getNPMPackage() {
|
|
952
|
+
return this.npmPackage;
|
|
953
|
+
}
|
|
954
|
+
getProject() {
|
|
955
|
+
return this.project;
|
|
956
|
+
}
|
|
957
|
+
getTarget() {
|
|
958
|
+
return semVerFactory(this.target.raw);
|
|
959
|
+
}
|
|
870
960
|
setRequirements(requirements) {
|
|
871
961
|
this.requirements = requirements;
|
|
872
962
|
return this;
|
|
@@ -879,7 +969,7 @@ class Upgrader {
|
|
|
879
969
|
this.codemodsTarget = semVerFactory(
|
|
880
970
|
`${this.target.major}.${this.target.minor}.${this.target.patch}`
|
|
881
971
|
);
|
|
882
|
-
this.logger?.debug(
|
|
972
|
+
this.logger?.debug?.(
|
|
883
973
|
`The codemods target has been synced with the upgrade target. The codemod runner will now look for ${version(
|
|
884
974
|
this.codemodsTarget
|
|
885
975
|
)}`
|
|
@@ -888,7 +978,7 @@ class Upgrader {
|
|
|
888
978
|
}
|
|
889
979
|
overrideCodemodsTarget(target) {
|
|
890
980
|
this.codemodsTarget = target;
|
|
891
|
-
this.logger?.debug(
|
|
981
|
+
this.logger?.debug?.(
|
|
892
982
|
`Overriding the codemods target. The codemod runner will now look for ${version(target)}`
|
|
893
983
|
);
|
|
894
984
|
return this;
|
|
@@ -908,46 +998,52 @@ class Upgrader {
|
|
|
908
998
|
addRequirement(requirement) {
|
|
909
999
|
this.requirements.push(requirement);
|
|
910
1000
|
const fRequired = requirement.isRequired ? "(required)" : "(optional)";
|
|
911
|
-
this.logger?.debug(
|
|
1001
|
+
this.logger?.debug?.(
|
|
912
1002
|
`Added a new requirement to the upgrade: ${highlight(requirement.name)} ${fRequired}`
|
|
913
1003
|
);
|
|
914
1004
|
return this;
|
|
915
1005
|
}
|
|
916
1006
|
async upgrade() {
|
|
917
|
-
this.logger?.info(
|
|
1007
|
+
this.logger?.info?.(
|
|
918
1008
|
`Upgrading from ${version(this.project.strapiVersion)} to ${version(this.target)}`
|
|
919
1009
|
);
|
|
920
1010
|
if (this.isDry) {
|
|
921
|
-
this.logger?.warn(
|
|
1011
|
+
this.logger?.warn?.(
|
|
922
1012
|
"Running the upgrade in dry mode. No files will be modified during the process."
|
|
923
1013
|
);
|
|
924
1014
|
}
|
|
925
1015
|
const range = rangeFromVersions(this.project.strapiVersion, this.target);
|
|
926
1016
|
const codemodsRange = rangeFromVersions(this.project.strapiVersion, this.codemodsTarget);
|
|
927
1017
|
const npmVersionsMatches = this.npmPackage?.findVersionsInRange(range) ?? [];
|
|
928
|
-
this.logger?.debug(
|
|
1018
|
+
this.logger?.debug?.(
|
|
929
1019
|
`Found ${highlight(npmVersionsMatches.length)} versions satisfying ${versionRange(range)}`
|
|
930
1020
|
);
|
|
931
1021
|
try {
|
|
932
|
-
this.logger?.info(upgradeStep("Checking requirement", [1, 4]));
|
|
1022
|
+
this.logger?.info?.(upgradeStep("Checking requirement", [1, 4]));
|
|
933
1023
|
await this.checkRequirements(this.requirements, {
|
|
934
1024
|
npmVersionsMatches,
|
|
935
1025
|
project: this.project,
|
|
936
1026
|
target: this.target
|
|
937
1027
|
});
|
|
938
|
-
this.logger?.info(upgradeStep("Applying the latest code modifications", [2, 4]));
|
|
1028
|
+
this.logger?.info?.(upgradeStep("Applying the latest code modifications", [2, 4]));
|
|
939
1029
|
await this.runCodemods(codemodsRange);
|
|
940
|
-
this.logger?.debug("Refreshing project information...");
|
|
1030
|
+
this.logger?.debug?.("Refreshing project information...");
|
|
941
1031
|
this.project.refresh();
|
|
942
|
-
this.logger?.info(upgradeStep("Upgrading Strapi dependencies", [3, 4]));
|
|
1032
|
+
this.logger?.info?.(upgradeStep("Upgrading Strapi dependencies", [3, 4]));
|
|
943
1033
|
await this.updateDependencies();
|
|
944
|
-
this.logger?.info(upgradeStep("Installing dependencies", [4, 4]));
|
|
1034
|
+
this.logger?.info?.(upgradeStep("Installing dependencies", [4, 4]));
|
|
945
1035
|
await this.installDependencies();
|
|
946
1036
|
} catch (e) {
|
|
947
1037
|
return erroredReport(unknownToError(e));
|
|
948
1038
|
}
|
|
949
1039
|
return successReport();
|
|
950
1040
|
}
|
|
1041
|
+
async confirm(message) {
|
|
1042
|
+
if (typeof this.confirmationCallback !== "function") {
|
|
1043
|
+
return true;
|
|
1044
|
+
}
|
|
1045
|
+
return this.confirmationCallback(message);
|
|
1046
|
+
}
|
|
951
1047
|
async checkRequirements(requirements, context) {
|
|
952
1048
|
for (const requirement of requirements) {
|
|
953
1049
|
const { pass, error } = await requirement.test(context);
|
|
@@ -974,7 +1070,7 @@ class Upgrader {
|
|
|
974
1070
|
if (requirement.isRequired) {
|
|
975
1071
|
throw error;
|
|
976
1072
|
}
|
|
977
|
-
this.logger?.warn(warningMessage);
|
|
1073
|
+
this.logger?.warn?.(warningMessage);
|
|
978
1074
|
const response = await this.confirmationCallback?.(confirmationMessage);
|
|
979
1075
|
if (!response) {
|
|
980
1076
|
throw error;
|
|
@@ -985,9 +1081,11 @@ class Upgrader {
|
|
|
985
1081
|
const json = createJSONTransformAPI(packageJSON);
|
|
986
1082
|
const dependencies = json.get("dependencies", {});
|
|
987
1083
|
const strapiDependencies = this.getScopedStrapiDependencies(dependencies);
|
|
988
|
-
this.logger?.debug(
|
|
1084
|
+
this.logger?.debug?.(
|
|
1085
|
+
`Found ${highlight(strapiDependencies.length)} dependency(ies) to update`
|
|
1086
|
+
);
|
|
989
1087
|
strapiDependencies.forEach(
|
|
990
|
-
(dependency) => this.logger?.debug(`- ${dependency[0]} (${dependency[1]} -> ${this.target})`)
|
|
1088
|
+
(dependency) => this.logger?.debug?.(`- ${dependency[0]} (${dependency[1]} -> ${this.target})`)
|
|
991
1089
|
);
|
|
992
1090
|
if (strapiDependencies.length === 0) {
|
|
993
1091
|
return;
|
|
@@ -995,7 +1093,7 @@ class Upgrader {
|
|
|
995
1093
|
strapiDependencies.forEach(([name]) => json.set(`dependencies.${name}`, this.target.raw));
|
|
996
1094
|
const updatedPackageJSON = json.root();
|
|
997
1095
|
if (this.isDry) {
|
|
998
|
-
this.logger?.debug(`Skipping dependencies update (${chalk.italic("dry mode")})`);
|
|
1096
|
+
this.logger?.debug?.(`Skipping dependencies update (${chalk.italic("dry mode")})`);
|
|
999
1097
|
return;
|
|
1000
1098
|
}
|
|
1001
1099
|
await saveJSON(packageJSONPath, updatedPackageJSON);
|
|
@@ -1015,9 +1113,9 @@ class Upgrader {
|
|
|
1015
1113
|
async installDependencies() {
|
|
1016
1114
|
const projectPath = this.project.cwd;
|
|
1017
1115
|
const packageManagerName = await packageManager.getPreferred(projectPath);
|
|
1018
|
-
this.logger?.debug(`Using ${highlight(packageManagerName)} as package manager`);
|
|
1116
|
+
this.logger?.debug?.(`Using ${highlight(packageManagerName)} as package manager`);
|
|
1019
1117
|
if (this.isDry) {
|
|
1020
|
-
this.logger?.debug(`Skipping dependencies installation (${chalk.italic("dry mode")}`);
|
|
1118
|
+
this.logger?.debug?.(`Skipping dependencies installation (${chalk.italic("dry mode")})`);
|
|
1021
1119
|
return;
|
|
1022
1120
|
}
|
|
1023
1121
|
await packageManager.installDependencies(projectPath, packageManagerName, {
|
|
@@ -1036,23 +1134,28 @@ class Upgrader {
|
|
|
1036
1134
|
}
|
|
1037
1135
|
const resolveNPMTarget = (project, target, npmPackage) => {
|
|
1038
1136
|
if (isSemverInstance(target)) {
|
|
1039
|
-
|
|
1137
|
+
const version2 = npmPackage.findVersion(target);
|
|
1138
|
+
if (!version2) {
|
|
1139
|
+
throw new NPMCandidateNotFoundError(target);
|
|
1140
|
+
}
|
|
1141
|
+
return version2;
|
|
1040
1142
|
}
|
|
1041
1143
|
if (isSemVerReleaseType(target)) {
|
|
1042
1144
|
const range = rangeFromVersions(project.strapiVersion, target);
|
|
1043
1145
|
const npmVersionsMatches = npmPackage.findVersionsInRange(range);
|
|
1044
|
-
|
|
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;
|
|
1045
1151
|
}
|
|
1046
|
-
|
|
1152
|
+
throw new NPMCandidateNotFoundError(target);
|
|
1047
1153
|
};
|
|
1048
1154
|
const upgraderFactory = (project, target, npmPackage) => {
|
|
1049
|
-
const
|
|
1050
|
-
|
|
1051
|
-
throw new Error(`Couldn't find a matching version in the NPM registry for "${target}"`);
|
|
1052
|
-
}
|
|
1053
|
-
const semverTarget = semVerFactory(targetedNPMVersion.version);
|
|
1155
|
+
const npmTarget = resolveNPMTarget(project, target, npmPackage);
|
|
1156
|
+
const semverTarget = semVerFactory(npmTarget.version);
|
|
1054
1157
|
if (semver.eq(semverTarget, project.strapiVersion)) {
|
|
1055
|
-
throw new Error(`The project is already
|
|
1158
|
+
throw new Error(`The project is already using v${semverTarget}`);
|
|
1056
1159
|
}
|
|
1057
1160
|
return new Upgrader(project, semverTarget, npmPackage);
|
|
1058
1161
|
};
|
|
@@ -1063,101 +1166,205 @@ const constants = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePro
|
|
|
1063
1166
|
__proto__: null,
|
|
1064
1167
|
STRAPI_PACKAGE_NAME
|
|
1065
1168
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
1066
|
-
const index$
|
|
1169
|
+
const index$6 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
1067
1170
|
__proto__: null,
|
|
1068
1171
|
constants,
|
|
1069
1172
|
upgraderFactory
|
|
1070
1173
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
1071
|
-
|
|
1072
|
-
|
|
1174
|
+
class Requirement {
|
|
1175
|
+
isRequired;
|
|
1073
1176
|
name;
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
constructor(name) {
|
|
1177
|
+
testCallback;
|
|
1178
|
+
children;
|
|
1179
|
+
constructor(name, testCallback, isRequired) {
|
|
1077
1180
|
this.name = name;
|
|
1078
|
-
this.
|
|
1079
|
-
this.
|
|
1181
|
+
this.testCallback = testCallback;
|
|
1182
|
+
this.isRequired = isRequired ?? true;
|
|
1183
|
+
this.children = [];
|
|
1080
1184
|
}
|
|
1081
|
-
|
|
1082
|
-
|
|
1185
|
+
setChildren(children) {
|
|
1186
|
+
this.children = children;
|
|
1187
|
+
return this;
|
|
1083
1188
|
}
|
|
1084
|
-
|
|
1085
|
-
|
|
1189
|
+
addChild(child) {
|
|
1190
|
+
this.children.push(child);
|
|
1191
|
+
return this;
|
|
1086
1192
|
}
|
|
1087
|
-
|
|
1088
|
-
this.
|
|
1089
|
-
|
|
1193
|
+
asOptional() {
|
|
1194
|
+
const newInstance = requirementFactory(this.name, this.testCallback, false);
|
|
1195
|
+
newInstance.setChildren(this.children);
|
|
1196
|
+
return newInstance;
|
|
1090
1197
|
}
|
|
1091
|
-
|
|
1092
|
-
this.
|
|
1093
|
-
|
|
1198
|
+
asRequired() {
|
|
1199
|
+
const newInstance = requirementFactory(this.name, this.testCallback, true);
|
|
1200
|
+
newInstance.setChildren(this.children);
|
|
1201
|
+
return newInstance;
|
|
1094
1202
|
}
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
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
|
+
}
|
|
1098
1216
|
}
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
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
|
+
}
|
|
1102
1234
|
}
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
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
|
+
}
|
|
1108
1251
|
}
|
|
1109
|
-
|
|
1110
|
-
|
|
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
|
+
}
|
|
1111
1263
|
}
|
|
1112
|
-
|
|
1113
|
-
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
|
+
};
|
|
1114
1319
|
const upgrade = async (options) => {
|
|
1115
1320
|
const timer = timerFactory();
|
|
1116
1321
|
const { logger, codemodsTarget } = options;
|
|
1117
1322
|
const cwd = path$1.resolve(options.cwd ?? process.cwd());
|
|
1118
1323
|
const project = projectFactory(cwd);
|
|
1119
|
-
|
|
1324
|
+
logger.debug(projectDetails(project));
|
|
1325
|
+
if (!isApplicationProject(project)) {
|
|
1120
1326
|
throw new Error(
|
|
1121
1327
|
`The "${options.target}" upgrade can only be run on a Strapi project; for plugins, please use "codemods".`
|
|
1122
1328
|
);
|
|
1123
1329
|
}
|
|
1330
|
+
logger.debug(
|
|
1331
|
+
`Application: VERSION=${version(project.packageJSON.version)}; STRAPI_VERSION=${version(project.strapiVersion)}`
|
|
1332
|
+
);
|
|
1124
1333
|
const npmPackage = npmPackageFactory(STRAPI_PACKAGE_NAME);
|
|
1125
1334
|
await npmPackage.refresh();
|
|
1126
1335
|
const upgrader = upgraderFactory(project, options.target, npmPackage).dry(options.dry ?? false).onConfirm(options.confirm ?? null).setLogger(logger);
|
|
1127
1336
|
if (codemodsTarget !== void 0) {
|
|
1128
1337
|
upgrader.overrideCodemodsTarget(codemodsTarget);
|
|
1129
1338
|
}
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
}
|
|
1133
|
-
upgrader.addRequirement(REQUIRE_GIT.asOptional());
|
|
1339
|
+
await runUpgradePrompts(upgrader, options);
|
|
1340
|
+
addUpgradeRequirements(upgrader, options);
|
|
1134
1341
|
const upgradeReport = await upgrader.upgrade();
|
|
1135
1342
|
if (!upgradeReport.success) {
|
|
1136
1343
|
throw upgradeReport.error;
|
|
1137
1344
|
}
|
|
1138
1345
|
timer.stop();
|
|
1139
|
-
logger.info(`Completed in ${durationMs(timer.elapsedMs)}`);
|
|
1346
|
+
logger.info(`Completed in ${durationMs(timer.elapsedMs)}ms`);
|
|
1140
1347
|
};
|
|
1141
|
-
const
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
const cwd = path$1.resolve(options.cwd ?? process.cwd());
|
|
1145
|
-
const project = projectFactory(cwd);
|
|
1146
|
-
const range = isAppProject(project) ? getRangeFromTarget(project.strapiVersion, options.target) : void 0;
|
|
1147
|
-
const codemodRunner = codemodRunnerFactory(project, range).dry(options.dry ?? false).onSelectCodemods(options.selectCodemods ?? null).setLogger(logger);
|
|
1148
|
-
const executionReport = await codemodRunner.run();
|
|
1149
|
-
if (!executionReport.success) {
|
|
1150
|
-
throw executionReport.error;
|
|
1348
|
+
const runUpgradePrompts = async (upgrader, options) => {
|
|
1349
|
+
if (options.target === ReleaseType.Latest) {
|
|
1350
|
+
await latest(upgrader, options);
|
|
1151
1351
|
}
|
|
1152
|
-
timer.stop();
|
|
1153
|
-
logger.info(`Completed in ${timer.elapsedMs}`);
|
|
1154
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());
|
|
1358
|
+
};
|
|
1359
|
+
const resolvePath = (cwd) => path$1.resolve(cwd ?? process.cwd());
|
|
1155
1360
|
const getRangeFromTarget = (currentVersion, target) => {
|
|
1156
1361
|
if (isSemverInstance(target)) {
|
|
1157
1362
|
return rangeFactory(target);
|
|
1158
1363
|
}
|
|
1159
1364
|
const { major, minor, patch } = currentVersion;
|
|
1160
1365
|
switch (target) {
|
|
1366
|
+
case ReleaseType.Latest:
|
|
1367
|
+
throw new Error("Can't use <latest> to create a codemods range: not implemented");
|
|
1161
1368
|
case ReleaseType.Major:
|
|
1162
1369
|
return rangeFactory(`${major}`);
|
|
1163
1370
|
case ReleaseType.Minor:
|
|
@@ -1168,9 +1375,60 @@ const getRangeFromTarget = (currentVersion, target) => {
|
|
|
1168
1375
|
throw new Error(`Invalid target set: ${target}`);
|
|
1169
1376
|
}
|
|
1170
1377
|
};
|
|
1378
|
+
const findRangeFromTarget = (project, target) => {
|
|
1379
|
+
if (isRangeInstance(target)) {
|
|
1380
|
+
return target;
|
|
1381
|
+
}
|
|
1382
|
+
if (isApplicationProject(project)) {
|
|
1383
|
+
return getRangeFromTarget(project.strapiVersion, target);
|
|
1384
|
+
}
|
|
1385
|
+
return rangeFactory("*");
|
|
1386
|
+
};
|
|
1387
|
+
const runCodemods = async (options) => {
|
|
1388
|
+
const timer = timerFactory();
|
|
1389
|
+
const { logger, uid } = options;
|
|
1390
|
+
const cwd = resolvePath(options.cwd);
|
|
1391
|
+
const project = projectFactory(cwd);
|
|
1392
|
+
const range = findRangeFromTarget(project, options.target);
|
|
1393
|
+
logger.debug(projectDetails(project));
|
|
1394
|
+
logger.debug(`Range: set to ${versionRange(range)}`);
|
|
1395
|
+
const codemodRunner = codemodRunnerFactory(project, range).dry(options.dry ?? false).onSelectCodemods(options.selectCodemods ?? null).setLogger(logger);
|
|
1396
|
+
let report;
|
|
1397
|
+
if (uid !== void 0) {
|
|
1398
|
+
logger.debug(`Running a single codemod: ${codemodUID(uid)}`);
|
|
1399
|
+
report = await codemodRunner.runByUID(uid);
|
|
1400
|
+
} else {
|
|
1401
|
+
report = await codemodRunner.run();
|
|
1402
|
+
}
|
|
1403
|
+
if (!report.success) {
|
|
1404
|
+
throw report.error;
|
|
1405
|
+
}
|
|
1406
|
+
timer.stop();
|
|
1407
|
+
logger.info(`Completed in ${timer.elapsedMs}`);
|
|
1408
|
+
};
|
|
1409
|
+
const listCodemods = async (options) => {
|
|
1410
|
+
const { logger, target } = options;
|
|
1411
|
+
const cwd = resolvePath(options.cwd);
|
|
1412
|
+
const project = projectFactory(cwd);
|
|
1413
|
+
const range = findRangeFromTarget(project, target);
|
|
1414
|
+
logger.debug(projectDetails(project));
|
|
1415
|
+
logger.debug(`Range: set to ${versionRange(range)}`);
|
|
1416
|
+
const repo = codemodRepositoryFactory();
|
|
1417
|
+
repo.refresh();
|
|
1418
|
+
const groups = repo.find({ range });
|
|
1419
|
+
const codemods = groups.flatMap((collection) => collection.codemods);
|
|
1420
|
+
logger.debug(`Found ${highlight(codemods.length)} codemods`);
|
|
1421
|
+
if (codemods.length === 0) {
|
|
1422
|
+
logger.info(`Found no codemods matching ${versionRange(range)}`);
|
|
1423
|
+
return;
|
|
1424
|
+
}
|
|
1425
|
+
const fCodemods = codemodList(codemods);
|
|
1426
|
+
logger.raw(fCodemods);
|
|
1427
|
+
};
|
|
1171
1428
|
const index$4 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
1172
1429
|
__proto__: null,
|
|
1173
|
-
|
|
1430
|
+
listCodemods,
|
|
1431
|
+
runCodemods,
|
|
1174
1432
|
upgrade
|
|
1175
1433
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
1176
1434
|
class Logger {
|
|
@@ -1264,18 +1522,18 @@ const index$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePrope
|
|
|
1264
1522
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
1265
1523
|
const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
1266
1524
|
__proto__: null,
|
|
1267
|
-
codemod: index$
|
|
1268
|
-
codemodRepository: index$
|
|
1525
|
+
codemod: index$8,
|
|
1526
|
+
codemodRepository: index$7,
|
|
1269
1527
|
error: index$9,
|
|
1270
|
-
f: index$
|
|
1528
|
+
f: index$f,
|
|
1271
1529
|
fileScanner: index$d,
|
|
1272
1530
|
logger: index$3,
|
|
1273
1531
|
project: index$a,
|
|
1274
1532
|
report: index$2,
|
|
1275
|
-
requirement: index$
|
|
1533
|
+
requirement: index$5,
|
|
1276
1534
|
runner: index$1,
|
|
1277
|
-
timer: index$
|
|
1278
|
-
upgrader: index$
|
|
1535
|
+
timer: index$g,
|
|
1536
|
+
upgrader: index$6,
|
|
1279
1537
|
version: index$e
|
|
1280
1538
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
1281
1539
|
export {
|