@strapi/upgrade 0.0.0-experimental.fdacf4285d1cada9d94ab4dcd756c5362cba1b54 → 0.0.0-next.3c5400321681b66eb35ab84c11113a78c1d9386e
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/README.md +1 -1
- package/dist/cli.js +285 -268
- package/dist/cli.js.map +1 -1
- package/dist/index.js +333 -315
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +330 -312
- package/dist/index.mjs.map +1 -1
- package/dist/modules/error/utils.d.ts +5 -0
- package/dist/modules/error/utils.d.ts.map +1 -1
- package/dist/modules/project/project.d.ts.map +1 -1
- package/dist/modules/upgrader/upgrader.d.ts.map +1 -1
- package/dist/modules/version/range.d.ts.map +1 -1
- package/dist/tasks/upgrade/requirements/major.d.ts.map +1 -1
- package/dist/tasks/upgrade/upgrade.d.ts.map +1 -1
- package/package.json +6 -6
- package/resources/codemods/5.0.0/deprecate-helper-plugin.code.ts +7 -1
- 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/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 assert from "node:assert";
|
|
9
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,51 +40,96 @@ 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";
|
|
@@ -228,16 +160,16 @@ const rangeFactory = (range) => {
|
|
|
228
160
|
const rangeFromReleaseType = (current, identifier) => {
|
|
229
161
|
switch (identifier) {
|
|
230
162
|
case ReleaseType.Major: {
|
|
231
|
-
const nextMajor =
|
|
232
|
-
return rangeFactory(`>${current.raw} <=${nextMajor}`);
|
|
233
|
-
}
|
|
234
|
-
case ReleaseType.Patch: {
|
|
235
|
-
const minor = semver.inc(current, "minor");
|
|
236
|
-
return rangeFactory(`>${current.raw} <${minor}`);
|
|
163
|
+
const nextMajor = semVerFactory(current.raw).inc("major");
|
|
164
|
+
return rangeFactory(`>${current.raw} <=${nextMajor.major}`);
|
|
237
165
|
}
|
|
238
166
|
case ReleaseType.Minor: {
|
|
239
|
-
const
|
|
240
|
-
return rangeFactory(`>${current.raw} <${
|
|
167
|
+
const nextMajor = semVerFactory(current.raw).inc("major");
|
|
168
|
+
return rangeFactory(`>${current.raw} <${nextMajor.raw}`);
|
|
169
|
+
}
|
|
170
|
+
case ReleaseType.Patch: {
|
|
171
|
+
const nextMinor = semVerFactory(current.raw).inc("minor");
|
|
172
|
+
return rangeFactory(`>${current.raw} <${nextMinor.raw}`);
|
|
241
173
|
}
|
|
242
174
|
default: {
|
|
243
175
|
throw new Error("Not implemented");
|
|
@@ -271,6 +203,48 @@ const index$e = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePrope
|
|
|
271
203
|
rangeFromVersions,
|
|
272
204
|
semVerFactory
|
|
273
205
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
206
|
+
class Package {
|
|
207
|
+
name;
|
|
208
|
+
packageURL;
|
|
209
|
+
npmPackage;
|
|
210
|
+
constructor(name) {
|
|
211
|
+
this.name = name;
|
|
212
|
+
this.packageURL = `${NPM_REGISTRY_URL}/${name}`;
|
|
213
|
+
this.npmPackage = null;
|
|
214
|
+
}
|
|
215
|
+
get isLoaded() {
|
|
216
|
+
return this.npmPackage !== null;
|
|
217
|
+
}
|
|
218
|
+
assertPackageIsLoaded(npmPackage) {
|
|
219
|
+
assert(this.isLoaded, "The package is not loaded yet");
|
|
220
|
+
}
|
|
221
|
+
getVersionsDict() {
|
|
222
|
+
this.assertPackageIsLoaded(this.npmPackage);
|
|
223
|
+
return this.npmPackage.versions;
|
|
224
|
+
}
|
|
225
|
+
getVersionsAsList() {
|
|
226
|
+
this.assertPackageIsLoaded(this.npmPackage);
|
|
227
|
+
return Object.values(this.npmPackage.versions);
|
|
228
|
+
}
|
|
229
|
+
findVersionsInRange(range) {
|
|
230
|
+
const versions = this.getVersionsAsList();
|
|
231
|
+
return versions.filter((v) => range.test(v.version)).filter((v) => isLiteralSemVer(v.version)).sort((v1, v2) => semver.compare(v1.version, v2.version));
|
|
232
|
+
}
|
|
233
|
+
findVersion(version2) {
|
|
234
|
+
const versions = this.getVersionsAsList();
|
|
235
|
+
return versions.find((npmVersion) => semver.eq(npmVersion.version, version2));
|
|
236
|
+
}
|
|
237
|
+
async refresh() {
|
|
238
|
+
const response = await fetch(this.packageURL);
|
|
239
|
+
assert(response.ok, `Request failed for ${this.packageURL}`);
|
|
240
|
+
this.npmPackage = await response.json();
|
|
241
|
+
return this;
|
|
242
|
+
}
|
|
243
|
+
versionExists(version2) {
|
|
244
|
+
return this.findVersion(version2) !== void 0;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
const npmPackageFactory = (name) => new Package(name);
|
|
274
248
|
class FileScanner {
|
|
275
249
|
cwd;
|
|
276
250
|
constructor(cwd) {
|
|
@@ -303,20 +277,60 @@ class AbstractRunner {
|
|
|
303
277
|
const runConfiguration = { ...this.configuration, ...configuration };
|
|
304
278
|
return this.runner(codemod.path, this.paths, runConfiguration);
|
|
305
279
|
}
|
|
306
|
-
}
|
|
307
|
-
class CodeRunner extends AbstractRunner {
|
|
308
|
-
runner = run;
|
|
309
|
-
valid(codemod) {
|
|
310
|
-
return codemod.kind === "code";
|
|
280
|
+
}
|
|
281
|
+
class CodeRunner extends AbstractRunner {
|
|
282
|
+
runner = run;
|
|
283
|
+
valid(codemod) {
|
|
284
|
+
return codemod.kind === "code";
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
const codeRunnerFactory = (paths, configuration) => {
|
|
288
|
+
return new CodeRunner(paths, configuration);
|
|
289
|
+
};
|
|
290
|
+
const index$c = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
291
|
+
__proto__: null,
|
|
292
|
+
codeRunnerFactory
|
|
293
|
+
}, Symbol.toStringTag, { value: "Module" }));
|
|
294
|
+
class JSONTransformAPI {
|
|
295
|
+
json;
|
|
296
|
+
constructor(json) {
|
|
297
|
+
this.json = cloneDeep(json);
|
|
298
|
+
}
|
|
299
|
+
get(path2, defaultValue) {
|
|
300
|
+
if (!path2) {
|
|
301
|
+
return this.root();
|
|
302
|
+
}
|
|
303
|
+
return cloneDeep(get(path2, this.json) ?? defaultValue);
|
|
304
|
+
}
|
|
305
|
+
has(path2) {
|
|
306
|
+
return has(path2, this.json);
|
|
307
|
+
}
|
|
308
|
+
merge(other) {
|
|
309
|
+
this.json = merge(other, this.json);
|
|
310
|
+
return this;
|
|
311
|
+
}
|
|
312
|
+
root() {
|
|
313
|
+
return cloneDeep(this.json);
|
|
314
|
+
}
|
|
315
|
+
set(path2, value) {
|
|
316
|
+
this.json = set(path2, value, this.json);
|
|
317
|
+
return this;
|
|
318
|
+
}
|
|
319
|
+
remove(path2) {
|
|
320
|
+
this.json = omit(path2, this.json);
|
|
321
|
+
return this;
|
|
311
322
|
}
|
|
312
323
|
}
|
|
313
|
-
const
|
|
314
|
-
|
|
324
|
+
const createJSONTransformAPI = (object) => new JSONTransformAPI(object);
|
|
325
|
+
const readJSON = async (path2) => {
|
|
326
|
+
const buffer = await fse.readFile(path2);
|
|
327
|
+
return JSON.parse(buffer.toString());
|
|
328
|
+
};
|
|
329
|
+
const saveJSON = async (path2, json) => {
|
|
330
|
+
const jsonAsString = `${JSON.stringify(json, null, 2)}
|
|
331
|
+
`;
|
|
332
|
+
await fse.writeFile(path2, jsonAsString);
|
|
315
333
|
};
|
|
316
|
-
const index$c = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
317
|
-
__proto__: null,
|
|
318
|
-
codeRunnerFactory
|
|
319
|
-
}, Symbol.toStringTag, { value: "Module" }));
|
|
320
334
|
const transformJSON = async (codemodPath, paths, config) => {
|
|
321
335
|
const { dry } = config;
|
|
322
336
|
const startTime = process.hrtime();
|
|
@@ -625,6 +639,13 @@ class UnexpectedError extends Error {
|
|
|
625
639
|
super("Unexpected Error");
|
|
626
640
|
}
|
|
627
641
|
}
|
|
642
|
+
class NPMCandidateNotFoundError extends Error {
|
|
643
|
+
target;
|
|
644
|
+
constructor(target, message = `Couldn't find a valid NPM candidate for "${target}"`) {
|
|
645
|
+
super(message);
|
|
646
|
+
this.target = target;
|
|
647
|
+
}
|
|
648
|
+
}
|
|
628
649
|
const unknownToError = (e) => {
|
|
629
650
|
if (e instanceof Error) {
|
|
630
651
|
return e;
|
|
@@ -636,93 +657,10 @@ const unknownToError = (e) => {
|
|
|
636
657
|
};
|
|
637
658
|
const index$9 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
638
659
|
__proto__: null,
|
|
660
|
+
NPMCandidateNotFoundError,
|
|
639
661
|
UnexpectedError,
|
|
640
662
|
unknownToError
|
|
641
663
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
642
|
-
const path = (path2) => chalk.blue(path2);
|
|
643
|
-
const version = (version2) => {
|
|
644
|
-
return chalk.italic.yellow(`v${version2}`);
|
|
645
|
-
};
|
|
646
|
-
const codemodUID = (uid) => {
|
|
647
|
-
return chalk.bold.cyan(uid);
|
|
648
|
-
};
|
|
649
|
-
const projectDetails = (project) => {
|
|
650
|
-
return `Project: TYPE=${projectType(project.type)}; CWD=${path(project.cwd)}; PATHS=${project.paths.map(path)}`;
|
|
651
|
-
};
|
|
652
|
-
const projectType = (type) => chalk.cyan(type);
|
|
653
|
-
const versionRange = (range) => chalk.italic.yellow(range.raw);
|
|
654
|
-
const transform = (transformFilePath) => chalk.cyan(transformFilePath);
|
|
655
|
-
const highlight = (arg) => chalk.bold.underline(arg);
|
|
656
|
-
const upgradeStep = (text, step) => {
|
|
657
|
-
return chalk.bold(`(${step[0]}/${step[1]}) ${text}...`);
|
|
658
|
-
};
|
|
659
|
-
const reports = (reports2) => {
|
|
660
|
-
const rows = reports2.map(({ codemod, report }, i) => {
|
|
661
|
-
const fIndex = chalk.grey(i);
|
|
662
|
-
const fVersion = chalk.magenta(codemod.version);
|
|
663
|
-
const fKind = chalk.yellow(codemod.kind);
|
|
664
|
-
const fFormattedTransformPath = chalk.cyan(codemod.format());
|
|
665
|
-
const fTimeElapsed = i === 0 ? `${report.timeElapsed}s ${chalk.dim.italic("(cold start)")}` : `${report.timeElapsed}s`;
|
|
666
|
-
const fAffected = report.ok > 0 ? chalk.green(report.ok) : chalk.grey(0);
|
|
667
|
-
const fUnchanged = report.ok === 0 ? chalk.red(report.nochange) : chalk.grey(report.nochange);
|
|
668
|
-
return [fIndex, fVersion, fKind, fFormattedTransformPath, fAffected, fUnchanged, fTimeElapsed];
|
|
669
|
-
});
|
|
670
|
-
const table = new CliTable3({
|
|
671
|
-
style: { compact: true },
|
|
672
|
-
head: [
|
|
673
|
-
chalk.bold.grey("N°"),
|
|
674
|
-
chalk.bold.magenta("Version"),
|
|
675
|
-
chalk.bold.yellow("Kind"),
|
|
676
|
-
chalk.bold.cyan("Name"),
|
|
677
|
-
chalk.bold.green("Affected"),
|
|
678
|
-
chalk.bold.red("Unchanged"),
|
|
679
|
-
chalk.bold.blue("Duration")
|
|
680
|
-
]
|
|
681
|
-
});
|
|
682
|
-
table.push(...rows);
|
|
683
|
-
return table.toString();
|
|
684
|
-
};
|
|
685
|
-
const codemodList = (codemods) => {
|
|
686
|
-
const rows = codemods.map((codemod, index2) => {
|
|
687
|
-
const fIndex = chalk.grey(index2);
|
|
688
|
-
const fVersion = chalk.magenta(codemod.version);
|
|
689
|
-
const fKind = chalk.yellow(codemod.kind);
|
|
690
|
-
const fName = chalk.blue(codemod.format());
|
|
691
|
-
const fUID = codemodUID(codemod.uid);
|
|
692
|
-
return [fIndex, fVersion, fKind, fName, fUID];
|
|
693
|
-
});
|
|
694
|
-
const table = new CliTable3({
|
|
695
|
-
style: { compact: true },
|
|
696
|
-
head: [
|
|
697
|
-
chalk.bold.grey("N°"),
|
|
698
|
-
chalk.bold.magenta("Version"),
|
|
699
|
-
chalk.bold.yellow("Kind"),
|
|
700
|
-
chalk.bold.blue("Name"),
|
|
701
|
-
chalk.bold.cyan("UID")
|
|
702
|
-
]
|
|
703
|
-
});
|
|
704
|
-
table.push(...rows);
|
|
705
|
-
return table.toString();
|
|
706
|
-
};
|
|
707
|
-
const durationMs = (elapsedMs) => {
|
|
708
|
-
const elapsedSeconds = (elapsedMs / ONE_SECOND_MS).toFixed(3);
|
|
709
|
-
return `${elapsedSeconds}s`;
|
|
710
|
-
};
|
|
711
|
-
const index$8 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
712
|
-
__proto__: null,
|
|
713
|
-
codemodList,
|
|
714
|
-
codemodUID,
|
|
715
|
-
durationMs,
|
|
716
|
-
highlight,
|
|
717
|
-
path,
|
|
718
|
-
projectDetails,
|
|
719
|
-
projectType,
|
|
720
|
-
reports,
|
|
721
|
-
transform,
|
|
722
|
-
upgradeStep,
|
|
723
|
-
version,
|
|
724
|
-
versionRange
|
|
725
|
-
}, Symbol.toStringTag, { value: "Module" }));
|
|
726
664
|
const CODEMOD_CODE_SUFFIX = "code";
|
|
727
665
|
const CODEMOD_JSON_SUFFIX = "json";
|
|
728
666
|
const CODEMOD_ALLOWED_SUFFIXES = [CODEMOD_CODE_SUFFIX, CODEMOD_JSON_SUFFIX];
|
|
@@ -775,7 +713,7 @@ class Codemod {
|
|
|
775
713
|
}
|
|
776
714
|
}
|
|
777
715
|
const codemodFactory = (options) => new Codemod(options);
|
|
778
|
-
const index$
|
|
716
|
+
const index$8 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
779
717
|
__proto__: null,
|
|
780
718
|
codemodFactory,
|
|
781
719
|
constants: constants$2
|
|
@@ -887,7 +825,7 @@ const parseCodemodKindFromFilename = (filename) => {
|
|
|
887
825
|
const codemodRepositoryFactory = (cwd = INTERNAL_CODEMODS_DIRECTORY) => {
|
|
888
826
|
return new CodemodRepository(cwd);
|
|
889
827
|
};
|
|
890
|
-
const index$
|
|
828
|
+
const index$7 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
891
829
|
__proto__: null,
|
|
892
830
|
codemodRepositoryFactory,
|
|
893
831
|
constants: constants$1
|
|
@@ -1152,7 +1090,7 @@ class Upgrader {
|
|
|
1152
1090
|
const packageManagerName = await packageManager.getPreferred(projectPath);
|
|
1153
1091
|
this.logger?.debug?.(`Using ${highlight(packageManagerName)} as package manager`);
|
|
1154
1092
|
if (this.isDry) {
|
|
1155
|
-
this.logger?.debug?.(`Skipping dependencies installation (${chalk.italic("dry mode")}`);
|
|
1093
|
+
this.logger?.debug?.(`Skipping dependencies installation (${chalk.italic("dry mode")})`);
|
|
1156
1094
|
return;
|
|
1157
1095
|
}
|
|
1158
1096
|
await packageManager.installDependencies(projectPath, packageManagerName, {
|
|
@@ -1171,23 +1109,28 @@ class Upgrader {
|
|
|
1171
1109
|
}
|
|
1172
1110
|
const resolveNPMTarget = (project, target, npmPackage) => {
|
|
1173
1111
|
if (isSemverInstance(target)) {
|
|
1174
|
-
|
|
1112
|
+
const version2 = npmPackage.findVersion(target);
|
|
1113
|
+
if (!version2) {
|
|
1114
|
+
throw new NPMCandidateNotFoundError(target);
|
|
1115
|
+
}
|
|
1116
|
+
return version2;
|
|
1175
1117
|
}
|
|
1176
1118
|
if (isSemVerReleaseType(target)) {
|
|
1177
1119
|
const range = rangeFromVersions(project.strapiVersion, target);
|
|
1178
1120
|
const npmVersionsMatches = npmPackage.findVersionsInRange(range);
|
|
1179
|
-
|
|
1121
|
+
const version2 = npmVersionsMatches.at(-1);
|
|
1122
|
+
if (!version2) {
|
|
1123
|
+
throw new NPMCandidateNotFoundError(range, `The project is already up-to-date (${target})`);
|
|
1124
|
+
}
|
|
1125
|
+
return version2;
|
|
1180
1126
|
}
|
|
1181
|
-
|
|
1127
|
+
throw new NPMCandidateNotFoundError(target);
|
|
1182
1128
|
};
|
|
1183
1129
|
const upgraderFactory = (project, target, npmPackage) => {
|
|
1184
|
-
const
|
|
1185
|
-
|
|
1186
|
-
throw new Error(`Couldn't find a matching version in the NPM registry for "${target}"`);
|
|
1187
|
-
}
|
|
1188
|
-
const semverTarget = semVerFactory(targetedNPMVersion.version);
|
|
1130
|
+
const npmTarget = resolveNPMTarget(project, target, npmPackage);
|
|
1131
|
+
const semverTarget = semVerFactory(npmTarget.version);
|
|
1189
1132
|
if (semver.eq(semverTarget, project.strapiVersion)) {
|
|
1190
|
-
throw new Error(`The project is already
|
|
1133
|
+
throw new Error(`The project is already using v${semverTarget}`);
|
|
1191
1134
|
}
|
|
1192
1135
|
return new Upgrader(project, semverTarget, npmPackage);
|
|
1193
1136
|
};
|
|
@@ -1198,54 +1141,126 @@ const constants = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePro
|
|
|
1198
1141
|
__proto__: null,
|
|
1199
1142
|
STRAPI_PACKAGE_NAME
|
|
1200
1143
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
1201
|
-
const index$
|
|
1144
|
+
const index$6 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
1202
1145
|
__proto__: null,
|
|
1203
1146
|
constants,
|
|
1204
1147
|
upgraderFactory
|
|
1205
1148
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
1206
|
-
|
|
1207
|
-
|
|
1149
|
+
class Requirement {
|
|
1150
|
+
isRequired;
|
|
1208
1151
|
name;
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
constructor(name) {
|
|
1152
|
+
testCallback;
|
|
1153
|
+
children;
|
|
1154
|
+
constructor(name, testCallback, isRequired) {
|
|
1212
1155
|
this.name = name;
|
|
1213
|
-
this.
|
|
1214
|
-
this.
|
|
1156
|
+
this.testCallback = testCallback;
|
|
1157
|
+
this.isRequired = isRequired ?? true;
|
|
1158
|
+
this.children = [];
|
|
1215
1159
|
}
|
|
1216
|
-
|
|
1217
|
-
|
|
1160
|
+
setChildren(children) {
|
|
1161
|
+
this.children = children;
|
|
1162
|
+
return this;
|
|
1218
1163
|
}
|
|
1219
|
-
|
|
1220
|
-
|
|
1164
|
+
addChild(child) {
|
|
1165
|
+
this.children.push(child);
|
|
1166
|
+
return this;
|
|
1221
1167
|
}
|
|
1222
|
-
|
|
1223
|
-
this.
|
|
1224
|
-
|
|
1168
|
+
asOptional() {
|
|
1169
|
+
const newInstance = requirementFactory(this.name, this.testCallback, false);
|
|
1170
|
+
newInstance.setChildren(this.children);
|
|
1171
|
+
return newInstance;
|
|
1225
1172
|
}
|
|
1226
|
-
|
|
1227
|
-
this.
|
|
1228
|
-
|
|
1173
|
+
asRequired() {
|
|
1174
|
+
const newInstance = requirementFactory(this.name, this.testCallback, true);
|
|
1175
|
+
newInstance.setChildren(this.children);
|
|
1176
|
+
return newInstance;
|
|
1229
1177
|
}
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1178
|
+
async test(context) {
|
|
1179
|
+
try {
|
|
1180
|
+
await this.testCallback?.(context);
|
|
1181
|
+
return ok();
|
|
1182
|
+
} catch (e) {
|
|
1183
|
+
if (e instanceof Error) {
|
|
1184
|
+
return errored(e);
|
|
1185
|
+
}
|
|
1186
|
+
if (typeof e === "string") {
|
|
1187
|
+
return errored(new Error(e));
|
|
1188
|
+
}
|
|
1189
|
+
return errored(new Error("Unknown error"));
|
|
1190
|
+
}
|
|
1233
1191
|
}
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1192
|
+
}
|
|
1193
|
+
const ok = () => ({ pass: true, error: null });
|
|
1194
|
+
const errored = (error) => ({ pass: false, error });
|
|
1195
|
+
const requirementFactory = (name, testCallback, isRequired) => new Requirement(name, testCallback, isRequired);
|
|
1196
|
+
const index$5 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
1197
|
+
__proto__: null,
|
|
1198
|
+
requirementFactory
|
|
1199
|
+
}, Symbol.toStringTag, { value: "Module" }));
|
|
1200
|
+
const REQUIRE_AVAILABLE_NEXT_MAJOR = requirementFactory(
|
|
1201
|
+
"REQUIRE_AVAILABLE_NEXT_MAJOR",
|
|
1202
|
+
(context) => {
|
|
1203
|
+
const { project, target } = context;
|
|
1204
|
+
const currentMajor = project.strapiVersion.major;
|
|
1205
|
+
const targetedMajor = target.major;
|
|
1206
|
+
if (targetedMajor === currentMajor) {
|
|
1207
|
+
throw new Error(`You're already on the latest major version (v${currentMajor})`);
|
|
1208
|
+
}
|
|
1237
1209
|
}
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1210
|
+
);
|
|
1211
|
+
const REQUIRE_LATEST_FOR_CURRENT_MAJOR = requirementFactory(
|
|
1212
|
+
"REQUIRE_LATEST_FOR_CURRENT_MAJOR",
|
|
1213
|
+
(context) => {
|
|
1214
|
+
const { project, target, npmVersionsMatches } = context;
|
|
1215
|
+
const { major: currentMajor } = project.strapiVersion;
|
|
1216
|
+
const invalidMatches = npmVersionsMatches.filter(
|
|
1217
|
+
(match) => semVerFactory(match.version).major === currentMajor
|
|
1218
|
+
);
|
|
1219
|
+
if (invalidMatches.length > 0) {
|
|
1220
|
+
const invalidVersions = invalidMatches.map((match) => match.version);
|
|
1221
|
+
const invalidVersionsCount = invalidVersions.length;
|
|
1222
|
+
throw new Error(
|
|
1223
|
+
`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.`
|
|
1224
|
+
);
|
|
1225
|
+
}
|
|
1243
1226
|
}
|
|
1244
|
-
|
|
1245
|
-
|
|
1227
|
+
);
|
|
1228
|
+
const REQUIRE_GIT_CLEAN_REPOSITORY = requirementFactory(
|
|
1229
|
+
"REQUIRE_GIT_CLEAN_REPOSITORY",
|
|
1230
|
+
async (context) => {
|
|
1231
|
+
const git = simpleGit({ baseDir: context.project.cwd });
|
|
1232
|
+
const status = await git.status();
|
|
1233
|
+
if (!status.isClean()) {
|
|
1234
|
+
throw new Error(
|
|
1235
|
+
"Repository is not clean. Please commit or stash any changes before upgrading"
|
|
1236
|
+
);
|
|
1237
|
+
}
|
|
1246
1238
|
}
|
|
1247
|
-
|
|
1248
|
-
const
|
|
1239
|
+
);
|
|
1240
|
+
const REQUIRE_GIT_REPOSITORY = requirementFactory(
|
|
1241
|
+
"REQUIRE_GIT_REPOSITORY",
|
|
1242
|
+
async (context) => {
|
|
1243
|
+
const git = simpleGit({ baseDir: context.project.cwd });
|
|
1244
|
+
const isRepo = await git.checkIsRepo();
|
|
1245
|
+
if (!isRepo) {
|
|
1246
|
+
throw new Error("Not a git repository (or any of the parent directories)");
|
|
1247
|
+
}
|
|
1248
|
+
}
|
|
1249
|
+
).addChild(REQUIRE_GIT_CLEAN_REPOSITORY.asOptional());
|
|
1250
|
+
const REQUIRE_GIT_INSTALLED = requirementFactory(
|
|
1251
|
+
"REQUIRE_GIT_INSTALLED",
|
|
1252
|
+
async (context) => {
|
|
1253
|
+
const git = simpleGit({ baseDir: context.project.cwd });
|
|
1254
|
+
try {
|
|
1255
|
+
await git.version();
|
|
1256
|
+
} catch {
|
|
1257
|
+
throw new Error("Git is not installed");
|
|
1258
|
+
}
|
|
1259
|
+
}
|
|
1260
|
+
).addChild(REQUIRE_GIT_REPOSITORY.asOptional());
|
|
1261
|
+
const REQUIRE_GIT = requirementFactory("REQUIRE_GIT", null).addChild(
|
|
1262
|
+
REQUIRE_GIT_INSTALLED.asOptional()
|
|
1263
|
+
);
|
|
1249
1264
|
const upgrade = async (options) => {
|
|
1250
1265
|
const timer = timerFactory();
|
|
1251
1266
|
const { logger, codemodsTarget } = options;
|
|
@@ -1257,6 +1272,9 @@ const upgrade = async (options) => {
|
|
|
1257
1272
|
`The "${options.target}" upgrade can only be run on a Strapi project; for plugins, please use "codemods".`
|
|
1258
1273
|
);
|
|
1259
1274
|
}
|
|
1275
|
+
logger.debug(
|
|
1276
|
+
`Application: VERSION=${version(project.packageJSON.version)}; STRAPI_VERSION=${version(project.strapiVersion)}`
|
|
1277
|
+
);
|
|
1260
1278
|
const npmPackage = npmPackageFactory(STRAPI_PACKAGE_NAME);
|
|
1261
1279
|
await npmPackage.refresh();
|
|
1262
1280
|
const upgrader = upgraderFactory(project, options.target, npmPackage).dry(options.dry ?? false).onConfirm(options.confirm ?? null).setLogger(logger);
|
|
@@ -1272,7 +1290,7 @@ const upgrade = async (options) => {
|
|
|
1272
1290
|
throw upgradeReport.error;
|
|
1273
1291
|
}
|
|
1274
1292
|
timer.stop();
|
|
1275
|
-
logger.info(`Completed in ${durationMs(timer.elapsedMs)}`);
|
|
1293
|
+
logger.info(`Completed in ${durationMs(timer.elapsedMs)}ms`);
|
|
1276
1294
|
};
|
|
1277
1295
|
const resolvePath = (cwd) => path$1.resolve(cwd ?? process.cwd());
|
|
1278
1296
|
const getRangeFromTarget = (currentVersion, target) => {
|
|
@@ -1438,18 +1456,18 @@ const index$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePrope
|
|
|
1438
1456
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
1439
1457
|
const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
1440
1458
|
__proto__: null,
|
|
1441
|
-
codemod: index$
|
|
1442
|
-
codemodRepository: index$
|
|
1459
|
+
codemod: index$8,
|
|
1460
|
+
codemodRepository: index$7,
|
|
1443
1461
|
error: index$9,
|
|
1444
|
-
f: index$
|
|
1462
|
+
f: index$f,
|
|
1445
1463
|
fileScanner: index$d,
|
|
1446
1464
|
logger: index$3,
|
|
1447
1465
|
project: index$a,
|
|
1448
1466
|
report: index$2,
|
|
1449
|
-
requirement: index$
|
|
1467
|
+
requirement: index$5,
|
|
1450
1468
|
runner: index$1,
|
|
1451
|
-
timer: index$
|
|
1452
|
-
upgrader: index$
|
|
1469
|
+
timer: index$g,
|
|
1470
|
+
upgrader: index$6,
|
|
1453
1471
|
version: index$e
|
|
1454
1472
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
1455
1473
|
export {
|