@strapi/upgrade 5.0.5 → 5.1.0
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/dist/cli.js +382 -293
- package/dist/cli.js.map +1 -1
- package/dist/index.js +392 -308
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +389 -305
- package/dist/index.mjs.map +1 -1
- package/dist/modules/error/utils.d.ts +8 -0
- package/dist/modules/error/utils.d.ts.map +1 -1
- package/dist/modules/upgrader/types.d.ts +6 -0
- package/dist/modules/upgrader/types.d.ts.map +1 -1
- package/dist/modules/upgrader/upgrader.d.ts +4 -0
- package/dist/modules/upgrader/upgrader.d.ts.map +1 -1
- package/dist/modules/version/range.d.ts.map +1 -1
- package/dist/modules/version/types.d.ts +2 -1
- package/dist/modules/version/types.d.ts.map +1 -1
- package/dist/tasks/codemods/utils.d.ts.map +1 -1
- package/dist/tasks/upgrade/prompts/index.d.ts +2 -0
- package/dist/tasks/upgrade/prompts/index.d.ts.map +1 -0
- package/dist/tasks/upgrade/prompts/latest.d.ts +9 -0
- package/dist/tasks/upgrade/prompts/latest.d.ts.map +1 -0
- package/dist/tasks/upgrade/requirements/major.d.ts.map +1 -1
- package/dist/tasks/upgrade/upgrade.d.ts.map +1 -1
- package/package.json +5 -5
package/dist/cli.js
CHANGED
|
@@ -5,26 +5,26 @@ const commander = require("commander");
|
|
|
5
5
|
const prompts = require("prompts");
|
|
6
6
|
const semver = require("semver");
|
|
7
7
|
const path$1 = require("node:path");
|
|
8
|
-
const
|
|
9
|
-
const utils = require("@strapi/utils");
|
|
10
|
-
const fp = require("lodash/fp");
|
|
11
|
-
const fse = require("fs-extra");
|
|
8
|
+
const CliTable3 = require("cli-table3");
|
|
12
9
|
const assert = require("node:assert");
|
|
10
|
+
const fse = require("fs-extra");
|
|
13
11
|
const fastglob = require("fast-glob");
|
|
14
12
|
const Runner = require("jscodeshift/src/Runner");
|
|
13
|
+
const fp = require("lodash/fp");
|
|
15
14
|
const node = require("esbuild-register/dist/node");
|
|
16
|
-
const
|
|
15
|
+
const utils = require("@strapi/utils");
|
|
16
|
+
const simpleGit = require("simple-git");
|
|
17
17
|
const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
|
|
18
18
|
const os__default = /* @__PURE__ */ _interopDefault(os);
|
|
19
19
|
const chalk__default = /* @__PURE__ */ _interopDefault(chalk);
|
|
20
20
|
const prompts__default = /* @__PURE__ */ _interopDefault(prompts);
|
|
21
21
|
const semver__default = /* @__PURE__ */ _interopDefault(semver);
|
|
22
22
|
const path__default = /* @__PURE__ */ _interopDefault(path$1);
|
|
23
|
-
const
|
|
24
|
-
const fse__default = /* @__PURE__ */ _interopDefault(fse);
|
|
23
|
+
const CliTable3__default = /* @__PURE__ */ _interopDefault(CliTable3);
|
|
25
24
|
const assert__default = /* @__PURE__ */ _interopDefault(assert);
|
|
25
|
+
const fse__default = /* @__PURE__ */ _interopDefault(fse);
|
|
26
26
|
const fastglob__default = /* @__PURE__ */ _interopDefault(fastglob);
|
|
27
|
-
const
|
|
27
|
+
const simpleGit__default = /* @__PURE__ */ _interopDefault(simpleGit);
|
|
28
28
|
class Logger {
|
|
29
29
|
isDebug;
|
|
30
30
|
isSilent;
|
|
@@ -99,6 +99,7 @@ var ReleaseType = /* @__PURE__ */ ((ReleaseType2) => {
|
|
|
99
99
|
ReleaseType2["Major"] = "major";
|
|
100
100
|
ReleaseType2["Minor"] = "minor";
|
|
101
101
|
ReleaseType2["Patch"] = "patch";
|
|
102
|
+
ReleaseType2["Latest"] = "latest";
|
|
102
103
|
return ReleaseType2;
|
|
103
104
|
})(ReleaseType || {});
|
|
104
105
|
const semVerFactory = (version2) => {
|
|
@@ -120,17 +121,20 @@ const rangeFactory = (range) => {
|
|
|
120
121
|
};
|
|
121
122
|
const rangeFromReleaseType = (current, identifier) => {
|
|
122
123
|
switch (identifier) {
|
|
123
|
-
case ReleaseType.
|
|
124
|
-
|
|
125
|
-
return rangeFactory(`>${current.raw} <=${nextMajor}`);
|
|
124
|
+
case ReleaseType.Latest: {
|
|
125
|
+
return rangeFactory(`>${current.raw}`);
|
|
126
126
|
}
|
|
127
|
-
case ReleaseType.
|
|
128
|
-
const
|
|
129
|
-
return rangeFactory(`>${current.raw}
|
|
127
|
+
case ReleaseType.Major: {
|
|
128
|
+
const nextMajor = semVerFactory(current.raw).inc("major");
|
|
129
|
+
return rangeFactory(`>${current.raw} <=${nextMajor.major}`);
|
|
130
130
|
}
|
|
131
131
|
case ReleaseType.Minor: {
|
|
132
|
-
const
|
|
133
|
-
return rangeFactory(`>${current.raw} <${
|
|
132
|
+
const nextMajor = semVerFactory(current.raw).inc("major");
|
|
133
|
+
return rangeFactory(`>${current.raw} <${nextMajor.raw}`);
|
|
134
|
+
}
|
|
135
|
+
case ReleaseType.Patch: {
|
|
136
|
+
const nextMinor = semVerFactory(current.raw).inc("minor");
|
|
137
|
+
return rangeFactory(`>${current.raw} <${nextMinor.raw}`);
|
|
134
138
|
}
|
|
135
139
|
default: {
|
|
136
140
|
throw new Error("Not implemented");
|
|
@@ -150,7 +154,36 @@ const isValidStringifiedRange = (str) => semver__default.default.validRange(str)
|
|
|
150
154
|
const isRangeInstance = (range) => {
|
|
151
155
|
return range instanceof semver__default.default.Range;
|
|
152
156
|
};
|
|
157
|
+
class UnexpectedError extends Error {
|
|
158
|
+
constructor() {
|
|
159
|
+
super("Unexpected Error");
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
class NPMCandidateNotFoundError extends Error {
|
|
163
|
+
target;
|
|
164
|
+
constructor(target, message = `Couldn't find a valid NPM candidate for "${target}"`) {
|
|
165
|
+
super(message);
|
|
166
|
+
this.target = target;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
class AbortedError extends Error {
|
|
170
|
+
constructor(message = "Upgrade aborted") {
|
|
171
|
+
super(message);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
const unknownToError = (e) => {
|
|
175
|
+
if (e instanceof Error) {
|
|
176
|
+
return e;
|
|
177
|
+
}
|
|
178
|
+
if (typeof e === "string") {
|
|
179
|
+
return new Error(e);
|
|
180
|
+
}
|
|
181
|
+
return new UnexpectedError();
|
|
182
|
+
};
|
|
153
183
|
const handleError = (err, isSilent) => {
|
|
184
|
+
if (err instanceof AbortedError) {
|
|
185
|
+
process.exit(0);
|
|
186
|
+
}
|
|
154
187
|
if (!isSilent) {
|
|
155
188
|
console.error(
|
|
156
189
|
chalk__default.default.red(`[ERROR] [${(/* @__PURE__ */ new Date()).toISOString()}]`),
|
|
@@ -159,115 +192,6 @@ const handleError = (err, isSilent) => {
|
|
|
159
192
|
}
|
|
160
193
|
process.exit(1);
|
|
161
194
|
};
|
|
162
|
-
class Requirement {
|
|
163
|
-
isRequired;
|
|
164
|
-
name;
|
|
165
|
-
testCallback;
|
|
166
|
-
children;
|
|
167
|
-
constructor(name, testCallback, isRequired) {
|
|
168
|
-
this.name = name;
|
|
169
|
-
this.testCallback = testCallback;
|
|
170
|
-
this.isRequired = isRequired ?? true;
|
|
171
|
-
this.children = [];
|
|
172
|
-
}
|
|
173
|
-
setChildren(children) {
|
|
174
|
-
this.children = children;
|
|
175
|
-
return this;
|
|
176
|
-
}
|
|
177
|
-
addChild(child) {
|
|
178
|
-
this.children.push(child);
|
|
179
|
-
return this;
|
|
180
|
-
}
|
|
181
|
-
asOptional() {
|
|
182
|
-
const newInstance = requirementFactory(this.name, this.testCallback, false);
|
|
183
|
-
newInstance.setChildren(this.children);
|
|
184
|
-
return newInstance;
|
|
185
|
-
}
|
|
186
|
-
asRequired() {
|
|
187
|
-
const newInstance = requirementFactory(this.name, this.testCallback, true);
|
|
188
|
-
newInstance.setChildren(this.children);
|
|
189
|
-
return newInstance;
|
|
190
|
-
}
|
|
191
|
-
async test(context) {
|
|
192
|
-
try {
|
|
193
|
-
await this.testCallback?.(context);
|
|
194
|
-
return ok();
|
|
195
|
-
} catch (e) {
|
|
196
|
-
if (e instanceof Error) {
|
|
197
|
-
return errored(e);
|
|
198
|
-
}
|
|
199
|
-
if (typeof e === "string") {
|
|
200
|
-
return errored(new Error(e));
|
|
201
|
-
}
|
|
202
|
-
return errored(new Error("Unknown error"));
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
const ok = () => ({ pass: true, error: null });
|
|
207
|
-
const errored = (error) => ({ pass: false, error });
|
|
208
|
-
const requirementFactory = (name, testCallback, isRequired) => new Requirement(name, testCallback, isRequired);
|
|
209
|
-
const REQUIRE_AVAILABLE_NEXT_MAJOR = requirementFactory(
|
|
210
|
-
"REQUIRE_AVAILABLE_NEXT_MAJOR",
|
|
211
|
-
(context) => {
|
|
212
|
-
const { project, target } = context;
|
|
213
|
-
const currentMajor = project.strapiVersion.major;
|
|
214
|
-
const targetedMajor = target.major;
|
|
215
|
-
if (targetedMajor === currentMajor) {
|
|
216
|
-
throw new Error(`You're already on the latest major version (v${currentMajor})`);
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
);
|
|
220
|
-
const REQUIRE_LATEST_FOR_CURRENT_MAJOR = requirementFactory(
|
|
221
|
-
"REQUIRE_LATEST_FOR_CURRENT_MAJOR",
|
|
222
|
-
(context) => {
|
|
223
|
-
const { project, target, npmVersionsMatches } = context;
|
|
224
|
-
if (npmVersionsMatches.length !== 1) {
|
|
225
|
-
const invalidVersions = npmVersionsMatches.slice(0, -1);
|
|
226
|
-
const invalidVersionsAsSemVer = invalidVersions.map((v) => v.version);
|
|
227
|
-
const nbInvalidVersions = npmVersionsMatches.length;
|
|
228
|
-
const currentMajor = project.strapiVersion.major;
|
|
229
|
-
throw new Error(
|
|
230
|
-
`Doing a major upgrade requires to be on the latest v${currentMajor} version, but found ${nbInvalidVersions} versions between the current one and ${target}: ${invalidVersionsAsSemVer}`
|
|
231
|
-
);
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
);
|
|
235
|
-
const REQUIRE_GIT_CLEAN_REPOSITORY = requirementFactory(
|
|
236
|
-
"REQUIRE_GIT_CLEAN_REPOSITORY",
|
|
237
|
-
async (context) => {
|
|
238
|
-
const git = simpleGit__default.default({ baseDir: context.project.cwd });
|
|
239
|
-
const status = await git.status();
|
|
240
|
-
if (!status.isClean()) {
|
|
241
|
-
throw new Error(
|
|
242
|
-
"Repository is not clean. Please commit or stash any changes before upgrading"
|
|
243
|
-
);
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
);
|
|
247
|
-
const REQUIRE_GIT_REPOSITORY = requirementFactory(
|
|
248
|
-
"REQUIRE_GIT_REPOSITORY",
|
|
249
|
-
async (context) => {
|
|
250
|
-
const git = simpleGit__default.default({ baseDir: context.project.cwd });
|
|
251
|
-
const isRepo = await git.checkIsRepo();
|
|
252
|
-
if (!isRepo) {
|
|
253
|
-
throw new Error("Not a git repository (or any of the parent directories)");
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
).addChild(REQUIRE_GIT_CLEAN_REPOSITORY.asOptional());
|
|
257
|
-
const REQUIRE_GIT_INSTALLED = requirementFactory(
|
|
258
|
-
"REQUIRE_GIT_INSTALLED",
|
|
259
|
-
async (context) => {
|
|
260
|
-
const git = simpleGit__default.default({ baseDir: context.project.cwd });
|
|
261
|
-
try {
|
|
262
|
-
await git.version();
|
|
263
|
-
} catch {
|
|
264
|
-
throw new Error("Git is not installed");
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
).addChild(REQUIRE_GIT_REPOSITORY.asOptional());
|
|
268
|
-
const REQUIRE_GIT = requirementFactory("REQUIRE_GIT", null).addChild(
|
|
269
|
-
REQUIRE_GIT_INSTALLED.asOptional()
|
|
270
|
-
);
|
|
271
195
|
class Timer {
|
|
272
196
|
interval;
|
|
273
197
|
constructor() {
|
|
@@ -294,46 +218,117 @@ class Timer {
|
|
|
294
218
|
}
|
|
295
219
|
const timerFactory = () => new Timer();
|
|
296
220
|
const ONE_SECOND_MS = 1e3;
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
221
|
+
const path = (path2) => chalk__default.default.blue(path2);
|
|
222
|
+
const version$1 = (version2) => {
|
|
223
|
+
return chalk__default.default.italic.yellow(`v${version2}`);
|
|
224
|
+
};
|
|
225
|
+
const codemodUID = (uid) => {
|
|
226
|
+
return chalk__default.default.bold.cyan(uid);
|
|
227
|
+
};
|
|
228
|
+
const projectDetails = (project) => {
|
|
229
|
+
return `Project: TYPE=${projectType(project.type)}; CWD=${path(project.cwd)}; PATHS=${project.paths.map(path)}`;
|
|
230
|
+
};
|
|
231
|
+
const projectType = (type) => chalk__default.default.cyan(type);
|
|
232
|
+
const versionRange = (range) => chalk__default.default.italic.yellow(range.raw);
|
|
233
|
+
const highlight = (arg) => chalk__default.default.bold.underline(arg);
|
|
234
|
+
const upgradeStep = (text, step) => {
|
|
235
|
+
return chalk__default.default.bold(`(${step[0]}/${step[1]}) ${text}...`);
|
|
236
|
+
};
|
|
237
|
+
const reports = (reports2) => {
|
|
238
|
+
const rows = reports2.map(({ codemod, report }, i) => {
|
|
239
|
+
const fIndex = chalk__default.default.grey(i);
|
|
240
|
+
const fVersion = chalk__default.default.magenta(codemod.version);
|
|
241
|
+
const fKind = chalk__default.default.yellow(codemod.kind);
|
|
242
|
+
const fFormattedTransformPath = chalk__default.default.cyan(codemod.format());
|
|
243
|
+
const fTimeElapsed = i === 0 ? `${report.timeElapsed}s ${chalk__default.default.dim.italic("(cold start)")}` : `${report.timeElapsed}s`;
|
|
244
|
+
const fAffected = report.ok > 0 ? chalk__default.default.green(report.ok) : chalk__default.default.grey(0);
|
|
245
|
+
const fUnchanged = report.ok === 0 ? chalk__default.default.red(report.nochange) : chalk__default.default.grey(report.nochange);
|
|
246
|
+
return [fIndex, fVersion, fKind, fFormattedTransformPath, fAffected, fUnchanged, fTimeElapsed];
|
|
247
|
+
});
|
|
248
|
+
const table = new CliTable3__default.default({
|
|
249
|
+
style: { compact: true },
|
|
250
|
+
head: [
|
|
251
|
+
chalk__default.default.bold.grey("N°"),
|
|
252
|
+
chalk__default.default.bold.magenta("Version"),
|
|
253
|
+
chalk__default.default.bold.yellow("Kind"),
|
|
254
|
+
chalk__default.default.bold.cyan("Name"),
|
|
255
|
+
chalk__default.default.bold.green("Affected"),
|
|
256
|
+
chalk__default.default.bold.red("Unchanged"),
|
|
257
|
+
chalk__default.default.bold.blue("Duration")
|
|
258
|
+
]
|
|
259
|
+
});
|
|
260
|
+
table.push(...rows);
|
|
261
|
+
return table.toString();
|
|
262
|
+
};
|
|
263
|
+
const codemodList = (codemods) => {
|
|
264
|
+
const rows = codemods.map((codemod, index) => {
|
|
265
|
+
const fIndex = chalk__default.default.grey(index);
|
|
266
|
+
const fVersion = chalk__default.default.magenta(codemod.version);
|
|
267
|
+
const fKind = chalk__default.default.yellow(codemod.kind);
|
|
268
|
+
const fName = chalk__default.default.blue(codemod.format());
|
|
269
|
+
const fUID = codemodUID(codemod.uid);
|
|
270
|
+
return [fIndex, fVersion, fKind, fName, fUID];
|
|
271
|
+
});
|
|
272
|
+
const table = new CliTable3__default.default({
|
|
273
|
+
style: { compact: true },
|
|
274
|
+
head: [
|
|
275
|
+
chalk__default.default.bold.grey("N°"),
|
|
276
|
+
chalk__default.default.bold.magenta("Version"),
|
|
277
|
+
chalk__default.default.bold.yellow("Kind"),
|
|
278
|
+
chalk__default.default.bold.blue("Name"),
|
|
279
|
+
chalk__default.default.bold.cyan("UID")
|
|
280
|
+
]
|
|
281
|
+
});
|
|
282
|
+
table.push(...rows);
|
|
283
|
+
return table.toString();
|
|
284
|
+
};
|
|
285
|
+
const durationMs = (elapsedMs) => {
|
|
286
|
+
const elapsedSeconds = (elapsedMs / ONE_SECOND_MS).toFixed(3);
|
|
287
|
+
return `${elapsedSeconds}s`;
|
|
288
|
+
};
|
|
289
|
+
const NPM_REGISTRY_URL = "https://registry.npmjs.org";
|
|
290
|
+
class Package {
|
|
291
|
+
name;
|
|
292
|
+
packageURL;
|
|
293
|
+
npmPackage;
|
|
294
|
+
constructor(name) {
|
|
295
|
+
this.name = name;
|
|
296
|
+
this.packageURL = `${NPM_REGISTRY_URL}/${name}`;
|
|
297
|
+
this.npmPackage = null;
|
|
301
298
|
}
|
|
302
|
-
get(
|
|
303
|
-
|
|
304
|
-
return this.root();
|
|
305
|
-
}
|
|
306
|
-
return fp.cloneDeep(fp.get(path2, this.json) ?? defaultValue);
|
|
299
|
+
get isLoaded() {
|
|
300
|
+
return this.npmPackage !== null;
|
|
307
301
|
}
|
|
308
|
-
|
|
309
|
-
|
|
302
|
+
assertPackageIsLoaded(npmPackage) {
|
|
303
|
+
assert__default.default(this.isLoaded, "The package is not loaded yet");
|
|
310
304
|
}
|
|
311
|
-
|
|
312
|
-
this.
|
|
313
|
-
return this;
|
|
305
|
+
getVersionsDict() {
|
|
306
|
+
this.assertPackageIsLoaded(this.npmPackage);
|
|
307
|
+
return this.npmPackage.versions;
|
|
314
308
|
}
|
|
315
|
-
|
|
316
|
-
|
|
309
|
+
getVersionsAsList() {
|
|
310
|
+
this.assertPackageIsLoaded(this.npmPackage);
|
|
311
|
+
return Object.values(this.npmPackage.versions);
|
|
317
312
|
}
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
return
|
|
313
|
+
findVersionsInRange(range) {
|
|
314
|
+
const versions = this.getVersionsAsList();
|
|
315
|
+
return versions.filter((v) => range.test(v.version)).filter((v) => isLiteralSemVer(v.version)).sort((v1, v2) => semver__default.default.compare(v1.version, v2.version));
|
|
321
316
|
}
|
|
322
|
-
|
|
323
|
-
|
|
317
|
+
findVersion(version2) {
|
|
318
|
+
const versions = this.getVersionsAsList();
|
|
319
|
+
return versions.find((npmVersion) => semver__default.default.eq(npmVersion.version, version2));
|
|
320
|
+
}
|
|
321
|
+
async refresh() {
|
|
322
|
+
const response = await fetch(this.packageURL);
|
|
323
|
+
assert__default.default(response.ok, `Request failed for ${this.packageURL}`);
|
|
324
|
+
this.npmPackage = await response.json();
|
|
324
325
|
return this;
|
|
325
326
|
}
|
|
327
|
+
versionExists(version2) {
|
|
328
|
+
return this.findVersion(version2) !== void 0;
|
|
329
|
+
}
|
|
326
330
|
}
|
|
327
|
-
const
|
|
328
|
-
const readJSON = async (path2) => {
|
|
329
|
-
const buffer = await fse__default.default.readFile(path2);
|
|
330
|
-
return JSON.parse(buffer.toString());
|
|
331
|
-
};
|
|
332
|
-
const saveJSON = async (path2, json) => {
|
|
333
|
-
const jsonAsString = `${JSON.stringify(json, null, 2)}
|
|
334
|
-
`;
|
|
335
|
-
await fse__default.default.writeFile(path2, jsonAsString);
|
|
336
|
-
};
|
|
331
|
+
const npmPackageFactory = (name) => new Package(name);
|
|
337
332
|
class FileScanner {
|
|
338
333
|
cwd;
|
|
339
334
|
constructor(cwd) {
|
|
@@ -362,15 +357,55 @@ class AbstractRunner {
|
|
|
362
357
|
const runConfiguration = { ...this.configuration, ...configuration };
|
|
363
358
|
return this.runner(codemod.path, this.paths, runConfiguration);
|
|
364
359
|
}
|
|
365
|
-
}
|
|
366
|
-
class CodeRunner extends AbstractRunner {
|
|
367
|
-
runner = Runner.run;
|
|
368
|
-
valid(codemod) {
|
|
369
|
-
return codemod.kind === "code";
|
|
360
|
+
}
|
|
361
|
+
class CodeRunner extends AbstractRunner {
|
|
362
|
+
runner = Runner.run;
|
|
363
|
+
valid(codemod) {
|
|
364
|
+
return codemod.kind === "code";
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
const codeRunnerFactory = (paths, configuration) => {
|
|
368
|
+
return new CodeRunner(paths, configuration);
|
|
369
|
+
};
|
|
370
|
+
class JSONTransformAPI {
|
|
371
|
+
json;
|
|
372
|
+
constructor(json) {
|
|
373
|
+
this.json = fp.cloneDeep(json);
|
|
374
|
+
}
|
|
375
|
+
get(path2, defaultValue) {
|
|
376
|
+
if (!path2) {
|
|
377
|
+
return this.root();
|
|
378
|
+
}
|
|
379
|
+
return fp.cloneDeep(fp.get(path2, this.json) ?? defaultValue);
|
|
380
|
+
}
|
|
381
|
+
has(path2) {
|
|
382
|
+
return fp.has(path2, this.json);
|
|
383
|
+
}
|
|
384
|
+
merge(other) {
|
|
385
|
+
this.json = fp.merge(other, this.json);
|
|
386
|
+
return this;
|
|
387
|
+
}
|
|
388
|
+
root() {
|
|
389
|
+
return fp.cloneDeep(this.json);
|
|
390
|
+
}
|
|
391
|
+
set(path2, value) {
|
|
392
|
+
this.json = fp.set(path2, value, this.json);
|
|
393
|
+
return this;
|
|
394
|
+
}
|
|
395
|
+
remove(path2) {
|
|
396
|
+
this.json = fp.omit(path2, this.json);
|
|
397
|
+
return this;
|
|
370
398
|
}
|
|
371
399
|
}
|
|
372
|
-
const
|
|
373
|
-
|
|
400
|
+
const createJSONTransformAPI = (object) => new JSONTransformAPI(object);
|
|
401
|
+
const readJSON = async (path2) => {
|
|
402
|
+
const buffer = await fse__default.default.readFile(path2);
|
|
403
|
+
return JSON.parse(buffer.toString());
|
|
404
|
+
};
|
|
405
|
+
const saveJSON = async (path2, json) => {
|
|
406
|
+
const jsonAsString = `${JSON.stringify(json, null, 2)}
|
|
407
|
+
`;
|
|
408
|
+
await fse__default.default.writeFile(path2, jsonAsString);
|
|
374
409
|
};
|
|
375
410
|
const transformJSON = async (codemodPath, paths, config) => {
|
|
376
411
|
const { dry } = config;
|
|
@@ -637,88 +672,6 @@ const projectFactory = (cwd) => {
|
|
|
637
672
|
const isApplicationProject = (project) => {
|
|
638
673
|
return project instanceof AppProject;
|
|
639
674
|
};
|
|
640
|
-
class UnexpectedError extends Error {
|
|
641
|
-
constructor() {
|
|
642
|
-
super("Unexpected Error");
|
|
643
|
-
}
|
|
644
|
-
}
|
|
645
|
-
const unknownToError = (e) => {
|
|
646
|
-
if (e instanceof Error) {
|
|
647
|
-
return e;
|
|
648
|
-
}
|
|
649
|
-
if (typeof e === "string") {
|
|
650
|
-
return new Error(e);
|
|
651
|
-
}
|
|
652
|
-
return new UnexpectedError();
|
|
653
|
-
};
|
|
654
|
-
const path = (path2) => chalk__default.default.blue(path2);
|
|
655
|
-
const version$1 = (version2) => {
|
|
656
|
-
return chalk__default.default.italic.yellow(`v${version2}`);
|
|
657
|
-
};
|
|
658
|
-
const codemodUID = (uid) => {
|
|
659
|
-
return chalk__default.default.bold.cyan(uid);
|
|
660
|
-
};
|
|
661
|
-
const projectDetails = (project) => {
|
|
662
|
-
return `Project: TYPE=${projectType(project.type)}; CWD=${path(project.cwd)}; PATHS=${project.paths.map(path)}`;
|
|
663
|
-
};
|
|
664
|
-
const projectType = (type) => chalk__default.default.cyan(type);
|
|
665
|
-
const versionRange = (range) => chalk__default.default.italic.yellow(range.raw);
|
|
666
|
-
const highlight = (arg) => chalk__default.default.bold.underline(arg);
|
|
667
|
-
const upgradeStep = (text, step) => {
|
|
668
|
-
return chalk__default.default.bold(`(${step[0]}/${step[1]}) ${text}...`);
|
|
669
|
-
};
|
|
670
|
-
const reports = (reports2) => {
|
|
671
|
-
const rows = reports2.map(({ codemod, report }, i) => {
|
|
672
|
-
const fIndex = chalk__default.default.grey(i);
|
|
673
|
-
const fVersion = chalk__default.default.magenta(codemod.version);
|
|
674
|
-
const fKind = chalk__default.default.yellow(codemod.kind);
|
|
675
|
-
const fFormattedTransformPath = chalk__default.default.cyan(codemod.format());
|
|
676
|
-
const fTimeElapsed = i === 0 ? `${report.timeElapsed}s ${chalk__default.default.dim.italic("(cold start)")}` : `${report.timeElapsed}s`;
|
|
677
|
-
const fAffected = report.ok > 0 ? chalk__default.default.green(report.ok) : chalk__default.default.grey(0);
|
|
678
|
-
const fUnchanged = report.ok === 0 ? chalk__default.default.red(report.nochange) : chalk__default.default.grey(report.nochange);
|
|
679
|
-
return [fIndex, fVersion, fKind, fFormattedTransformPath, fAffected, fUnchanged, fTimeElapsed];
|
|
680
|
-
});
|
|
681
|
-
const table = new CliTable3__default.default({
|
|
682
|
-
style: { compact: true },
|
|
683
|
-
head: [
|
|
684
|
-
chalk__default.default.bold.grey("N°"),
|
|
685
|
-
chalk__default.default.bold.magenta("Version"),
|
|
686
|
-
chalk__default.default.bold.yellow("Kind"),
|
|
687
|
-
chalk__default.default.bold.cyan("Name"),
|
|
688
|
-
chalk__default.default.bold.green("Affected"),
|
|
689
|
-
chalk__default.default.bold.red("Unchanged"),
|
|
690
|
-
chalk__default.default.bold.blue("Duration")
|
|
691
|
-
]
|
|
692
|
-
});
|
|
693
|
-
table.push(...rows);
|
|
694
|
-
return table.toString();
|
|
695
|
-
};
|
|
696
|
-
const codemodList = (codemods) => {
|
|
697
|
-
const rows = codemods.map((codemod, index) => {
|
|
698
|
-
const fIndex = chalk__default.default.grey(index);
|
|
699
|
-
const fVersion = chalk__default.default.magenta(codemod.version);
|
|
700
|
-
const fKind = chalk__default.default.yellow(codemod.kind);
|
|
701
|
-
const fName = chalk__default.default.blue(codemod.format());
|
|
702
|
-
const fUID = codemodUID(codemod.uid);
|
|
703
|
-
return [fIndex, fVersion, fKind, fName, fUID];
|
|
704
|
-
});
|
|
705
|
-
const table = new CliTable3__default.default({
|
|
706
|
-
style: { compact: true },
|
|
707
|
-
head: [
|
|
708
|
-
chalk__default.default.bold.grey("N°"),
|
|
709
|
-
chalk__default.default.bold.magenta("Version"),
|
|
710
|
-
chalk__default.default.bold.yellow("Kind"),
|
|
711
|
-
chalk__default.default.bold.blue("Name"),
|
|
712
|
-
chalk__default.default.bold.cyan("UID")
|
|
713
|
-
]
|
|
714
|
-
});
|
|
715
|
-
table.push(...rows);
|
|
716
|
-
return table.toString();
|
|
717
|
-
};
|
|
718
|
-
const durationMs = (elapsedMs) => {
|
|
719
|
-
const elapsedSeconds = (elapsedMs / ONE_SECOND_MS).toFixed(3);
|
|
720
|
-
return `${elapsedSeconds}s`;
|
|
721
|
-
};
|
|
722
675
|
const CODEMOD_CODE_SUFFIX = "code";
|
|
723
676
|
const CODEMOD_JSON_SUFFIX = "json";
|
|
724
677
|
const CODEMOD_ALLOWED_SUFFIXES = [CODEMOD_CODE_SUFFIX, CODEMOD_JSON_SUFFIX];
|
|
@@ -974,6 +927,15 @@ class Upgrader {
|
|
|
974
927
|
this.logger = null;
|
|
975
928
|
this.confirmationCallback = null;
|
|
976
929
|
}
|
|
930
|
+
getNPMPackage() {
|
|
931
|
+
return this.npmPackage;
|
|
932
|
+
}
|
|
933
|
+
getProject() {
|
|
934
|
+
return this.project;
|
|
935
|
+
}
|
|
936
|
+
getTarget() {
|
|
937
|
+
return semVerFactory(this.target.raw);
|
|
938
|
+
}
|
|
977
939
|
setRequirements(requirements) {
|
|
978
940
|
this.requirements = requirements;
|
|
979
941
|
return this;
|
|
@@ -1055,6 +1017,12 @@ class Upgrader {
|
|
|
1055
1017
|
}
|
|
1056
1018
|
return successReport();
|
|
1057
1019
|
}
|
|
1020
|
+
async confirm(message) {
|
|
1021
|
+
if (typeof this.confirmationCallback !== "function") {
|
|
1022
|
+
return true;
|
|
1023
|
+
}
|
|
1024
|
+
return this.confirmationCallback(message);
|
|
1025
|
+
}
|
|
1058
1026
|
async checkRequirements(requirements, context) {
|
|
1059
1027
|
for (const requirement of requirements) {
|
|
1060
1028
|
const { pass, error } = await requirement.test(context);
|
|
@@ -1126,7 +1094,7 @@ class Upgrader {
|
|
|
1126
1094
|
const packageManagerName = await utils.packageManager.getPreferred(projectPath);
|
|
1127
1095
|
this.logger?.debug?.(`Using ${highlight(packageManagerName)} as package manager`);
|
|
1128
1096
|
if (this.isDry) {
|
|
1129
|
-
this.logger?.debug?.(`Skipping dependencies installation (${chalk__default.default.italic("dry mode")}`);
|
|
1097
|
+
this.logger?.debug?.(`Skipping dependencies installation (${chalk__default.default.italic("dry mode")})`);
|
|
1130
1098
|
return;
|
|
1131
1099
|
}
|
|
1132
1100
|
await utils.packageManager.installDependencies(projectPath, packageManagerName, {
|
|
@@ -1145,72 +1113,175 @@ class Upgrader {
|
|
|
1145
1113
|
}
|
|
1146
1114
|
const resolveNPMTarget = (project, target, npmPackage) => {
|
|
1147
1115
|
if (isSemverInstance(target)) {
|
|
1148
|
-
|
|
1116
|
+
const version2 = npmPackage.findVersion(target);
|
|
1117
|
+
if (!version2) {
|
|
1118
|
+
throw new NPMCandidateNotFoundError(target);
|
|
1119
|
+
}
|
|
1120
|
+
return version2;
|
|
1149
1121
|
}
|
|
1150
1122
|
if (isSemVerReleaseType(target)) {
|
|
1151
1123
|
const range = rangeFromVersions(project.strapiVersion, target);
|
|
1152
1124
|
const npmVersionsMatches = npmPackage.findVersionsInRange(range);
|
|
1153
|
-
|
|
1125
|
+
const version2 = npmVersionsMatches.at(-1);
|
|
1126
|
+
if (!version2) {
|
|
1127
|
+
throw new NPMCandidateNotFoundError(range, `The project is already up-to-date (${target})`);
|
|
1128
|
+
}
|
|
1129
|
+
return version2;
|
|
1154
1130
|
}
|
|
1155
|
-
|
|
1131
|
+
throw new NPMCandidateNotFoundError(target);
|
|
1156
1132
|
};
|
|
1157
1133
|
const upgraderFactory = (project, target, npmPackage) => {
|
|
1158
|
-
const
|
|
1159
|
-
|
|
1160
|
-
throw new Error(`Couldn't find a matching version in the NPM registry for "${target}"`);
|
|
1161
|
-
}
|
|
1162
|
-
const semverTarget = semVerFactory(targetedNPMVersion.version);
|
|
1134
|
+
const npmTarget = resolveNPMTarget(project, target, npmPackage);
|
|
1135
|
+
const semverTarget = semVerFactory(npmTarget.version);
|
|
1163
1136
|
if (semver__default.default.eq(semverTarget, project.strapiVersion)) {
|
|
1164
|
-
throw new Error(`The project is already
|
|
1137
|
+
throw new Error(`The project is already using v${semverTarget}`);
|
|
1165
1138
|
}
|
|
1166
1139
|
return new Upgrader(project, semverTarget, npmPackage);
|
|
1167
1140
|
};
|
|
1168
1141
|
const successReport = () => ({ success: true, error: null });
|
|
1169
1142
|
const erroredReport = (error) => ({ success: false, error });
|
|
1170
1143
|
const STRAPI_PACKAGE_NAME = "@strapi/strapi";
|
|
1171
|
-
|
|
1172
|
-
|
|
1144
|
+
class Requirement {
|
|
1145
|
+
isRequired;
|
|
1173
1146
|
name;
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
constructor(name) {
|
|
1147
|
+
testCallback;
|
|
1148
|
+
children;
|
|
1149
|
+
constructor(name, testCallback, isRequired) {
|
|
1177
1150
|
this.name = name;
|
|
1178
|
-
this.
|
|
1179
|
-
this.
|
|
1151
|
+
this.testCallback = testCallback;
|
|
1152
|
+
this.isRequired = isRequired ?? true;
|
|
1153
|
+
this.children = [];
|
|
1180
1154
|
}
|
|
1181
|
-
|
|
1182
|
-
|
|
1155
|
+
setChildren(children) {
|
|
1156
|
+
this.children = children;
|
|
1157
|
+
return this;
|
|
1183
1158
|
}
|
|
1184
|
-
|
|
1185
|
-
|
|
1159
|
+
addChild(child) {
|
|
1160
|
+
this.children.push(child);
|
|
1161
|
+
return this;
|
|
1186
1162
|
}
|
|
1187
|
-
|
|
1188
|
-
this.
|
|
1189
|
-
|
|
1163
|
+
asOptional() {
|
|
1164
|
+
const newInstance = requirementFactory(this.name, this.testCallback, false);
|
|
1165
|
+
newInstance.setChildren(this.children);
|
|
1166
|
+
return newInstance;
|
|
1190
1167
|
}
|
|
1191
|
-
|
|
1192
|
-
this.
|
|
1193
|
-
|
|
1168
|
+
asRequired() {
|
|
1169
|
+
const newInstance = requirementFactory(this.name, this.testCallback, true);
|
|
1170
|
+
newInstance.setChildren(this.children);
|
|
1171
|
+
return newInstance;
|
|
1194
1172
|
}
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1173
|
+
async test(context) {
|
|
1174
|
+
try {
|
|
1175
|
+
await this.testCallback?.(context);
|
|
1176
|
+
return ok();
|
|
1177
|
+
} catch (e) {
|
|
1178
|
+
if (e instanceof Error) {
|
|
1179
|
+
return errored(e);
|
|
1180
|
+
}
|
|
1181
|
+
if (typeof e === "string") {
|
|
1182
|
+
return errored(new Error(e));
|
|
1183
|
+
}
|
|
1184
|
+
return errored(new Error("Unknown error"));
|
|
1185
|
+
}
|
|
1198
1186
|
}
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1187
|
+
}
|
|
1188
|
+
const ok = () => ({ pass: true, error: null });
|
|
1189
|
+
const errored = (error) => ({ pass: false, error });
|
|
1190
|
+
const requirementFactory = (name, testCallback, isRequired) => new Requirement(name, testCallback, isRequired);
|
|
1191
|
+
const REQUIRE_AVAILABLE_NEXT_MAJOR = requirementFactory(
|
|
1192
|
+
"REQUIRE_AVAILABLE_NEXT_MAJOR",
|
|
1193
|
+
(context) => {
|
|
1194
|
+
const { project, target } = context;
|
|
1195
|
+
const currentMajor = project.strapiVersion.major;
|
|
1196
|
+
const targetedMajor = target.major;
|
|
1197
|
+
if (targetedMajor === currentMajor) {
|
|
1198
|
+
throw new Error(`You're already on the latest major version (v${currentMajor})`);
|
|
1199
|
+
}
|
|
1202
1200
|
}
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1201
|
+
);
|
|
1202
|
+
const REQUIRE_LATEST_FOR_CURRENT_MAJOR = requirementFactory(
|
|
1203
|
+
"REQUIRE_LATEST_FOR_CURRENT_MAJOR",
|
|
1204
|
+
(context) => {
|
|
1205
|
+
const { project, target, npmVersionsMatches } = context;
|
|
1206
|
+
const { major: currentMajor } = project.strapiVersion;
|
|
1207
|
+
const invalidMatches = npmVersionsMatches.filter(
|
|
1208
|
+
(match) => semVerFactory(match.version).major === currentMajor
|
|
1209
|
+
);
|
|
1210
|
+
if (invalidMatches.length > 0) {
|
|
1211
|
+
const invalidVersions = invalidMatches.map((match) => match.version);
|
|
1212
|
+
const invalidVersionsCount = invalidVersions.length;
|
|
1213
|
+
throw new Error(
|
|
1214
|
+
`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.`
|
|
1215
|
+
);
|
|
1216
|
+
}
|
|
1208
1217
|
}
|
|
1209
|
-
|
|
1210
|
-
|
|
1218
|
+
);
|
|
1219
|
+
const REQUIRE_GIT_CLEAN_REPOSITORY = requirementFactory(
|
|
1220
|
+
"REQUIRE_GIT_CLEAN_REPOSITORY",
|
|
1221
|
+
async (context) => {
|
|
1222
|
+
const git = simpleGit__default.default({ baseDir: context.project.cwd });
|
|
1223
|
+
const status = await git.status();
|
|
1224
|
+
if (!status.isClean()) {
|
|
1225
|
+
throw new Error(
|
|
1226
|
+
"Repository is not clean. Please commit or stash any changes before upgrading"
|
|
1227
|
+
);
|
|
1228
|
+
}
|
|
1211
1229
|
}
|
|
1212
|
-
|
|
1213
|
-
const
|
|
1230
|
+
);
|
|
1231
|
+
const REQUIRE_GIT_REPOSITORY = requirementFactory(
|
|
1232
|
+
"REQUIRE_GIT_REPOSITORY",
|
|
1233
|
+
async (context) => {
|
|
1234
|
+
const git = simpleGit__default.default({ baseDir: context.project.cwd });
|
|
1235
|
+
const isRepo = await git.checkIsRepo();
|
|
1236
|
+
if (!isRepo) {
|
|
1237
|
+
throw new Error("Not a git repository (or any of the parent directories)");
|
|
1238
|
+
}
|
|
1239
|
+
}
|
|
1240
|
+
).addChild(REQUIRE_GIT_CLEAN_REPOSITORY.asOptional());
|
|
1241
|
+
const REQUIRE_GIT_INSTALLED = requirementFactory(
|
|
1242
|
+
"REQUIRE_GIT_INSTALLED",
|
|
1243
|
+
async (context) => {
|
|
1244
|
+
const git = simpleGit__default.default({ baseDir: context.project.cwd });
|
|
1245
|
+
try {
|
|
1246
|
+
await git.version();
|
|
1247
|
+
} catch {
|
|
1248
|
+
throw new Error("Git is not installed");
|
|
1249
|
+
}
|
|
1250
|
+
}
|
|
1251
|
+
).addChild(REQUIRE_GIT_REPOSITORY.asOptional());
|
|
1252
|
+
const REQUIRE_GIT = requirementFactory("REQUIRE_GIT", null).addChild(
|
|
1253
|
+
REQUIRE_GIT_INSTALLED.asOptional()
|
|
1254
|
+
);
|
|
1255
|
+
const latest = async (upgrader, options) => {
|
|
1256
|
+
if (options.target !== ReleaseType.Latest) {
|
|
1257
|
+
return;
|
|
1258
|
+
}
|
|
1259
|
+
const npmPackage = upgrader.getNPMPackage();
|
|
1260
|
+
const target = upgrader.getTarget();
|
|
1261
|
+
const project = upgrader.getProject();
|
|
1262
|
+
const { strapiVersion: current } = project;
|
|
1263
|
+
const fTargetMajor = highlight(`v${target.major}`);
|
|
1264
|
+
const fCurrentMajor = highlight(`v${current.major}`);
|
|
1265
|
+
const fTarget = version$1(target);
|
|
1266
|
+
const fCurrent = version$1(current);
|
|
1267
|
+
const isMajorUpgrade = target.major > current.major;
|
|
1268
|
+
if (isMajorUpgrade) {
|
|
1269
|
+
options.logger.warn(
|
|
1270
|
+
`Detected a major upgrade for the "${highlight(ReleaseType.Latest)}" tag: ${fCurrent} > ${fTarget}`
|
|
1271
|
+
);
|
|
1272
|
+
const newerPackageRelease = npmPackage.findVersionsInRange(rangeFactory(`>${current.raw} <${target.major}`)).at(-1);
|
|
1273
|
+
if (newerPackageRelease) {
|
|
1274
|
+
const fLatest = version$1(semVerFactory(newerPackageRelease.version));
|
|
1275
|
+
options.logger.warn(
|
|
1276
|
+
`It's recommended to first upgrade to the latest version of ${fCurrentMajor} (${fLatest}) before upgrading to ${fTargetMajor}.`
|
|
1277
|
+
);
|
|
1278
|
+
}
|
|
1279
|
+
const proceedAnyway = await upgrader.confirm(`I know what I'm doing. Proceed anyway!`);
|
|
1280
|
+
if (!proceedAnyway) {
|
|
1281
|
+
throw new AbortedError();
|
|
1282
|
+
}
|
|
1283
|
+
}
|
|
1284
|
+
};
|
|
1214
1285
|
const upgrade$1 = async (options) => {
|
|
1215
1286
|
const timer = timerFactory();
|
|
1216
1287
|
const { logger, codemodsTarget } = options;
|
|
@@ -1222,22 +1293,34 @@ const upgrade$1 = async (options) => {
|
|
|
1222
1293
|
`The "${options.target}" upgrade can only be run on a Strapi project; for plugins, please use "codemods".`
|
|
1223
1294
|
);
|
|
1224
1295
|
}
|
|
1296
|
+
logger.debug(
|
|
1297
|
+
`Application: VERSION=${version$1(project.packageJSON.version)}; STRAPI_VERSION=${version$1(project.strapiVersion)}`
|
|
1298
|
+
);
|
|
1225
1299
|
const npmPackage = npmPackageFactory(STRAPI_PACKAGE_NAME);
|
|
1226
1300
|
await npmPackage.refresh();
|
|
1227
1301
|
const upgrader = upgraderFactory(project, options.target, npmPackage).dry(options.dry ?? false).onConfirm(options.confirm ?? null).setLogger(logger);
|
|
1228
1302
|
if (codemodsTarget !== void 0) {
|
|
1229
1303
|
upgrader.overrideCodemodsTarget(codemodsTarget);
|
|
1230
1304
|
}
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
}
|
|
1234
|
-
upgrader.addRequirement(REQUIRE_GIT.asOptional());
|
|
1305
|
+
await runUpgradePrompts(upgrader, options);
|
|
1306
|
+
addUpgradeRequirements(upgrader, options);
|
|
1235
1307
|
const upgradeReport = await upgrader.upgrade();
|
|
1236
1308
|
if (!upgradeReport.success) {
|
|
1237
1309
|
throw upgradeReport.error;
|
|
1238
1310
|
}
|
|
1239
1311
|
timer.stop();
|
|
1240
|
-
logger.info(`Completed in ${durationMs(timer.elapsedMs)}`);
|
|
1312
|
+
logger.info(`Completed in ${durationMs(timer.elapsedMs)}ms`);
|
|
1313
|
+
};
|
|
1314
|
+
const runUpgradePrompts = async (upgrader, options) => {
|
|
1315
|
+
if (options.target === ReleaseType.Latest) {
|
|
1316
|
+
await latest(upgrader, options);
|
|
1317
|
+
}
|
|
1318
|
+
};
|
|
1319
|
+
const addUpgradeRequirements = (upgrader, options) => {
|
|
1320
|
+
if (options.target === ReleaseType.Major) {
|
|
1321
|
+
upgrader.addRequirement(REQUIRE_AVAILABLE_NEXT_MAJOR).addRequirement(REQUIRE_LATEST_FOR_CURRENT_MAJOR);
|
|
1322
|
+
}
|
|
1323
|
+
upgrader.addRequirement(REQUIRE_GIT.asOptional());
|
|
1241
1324
|
};
|
|
1242
1325
|
const resolvePath = (cwd) => path__default.default.resolve(cwd ?? process.cwd());
|
|
1243
1326
|
const getRangeFromTarget = (currentVersion, target) => {
|
|
@@ -1246,6 +1329,8 @@ const getRangeFromTarget = (currentVersion, target) => {
|
|
|
1246
1329
|
}
|
|
1247
1330
|
const { major, minor, patch } = currentVersion;
|
|
1248
1331
|
switch (target) {
|
|
1332
|
+
case ReleaseType.Latest:
|
|
1333
|
+
throw new Error("Can't use <latest> to create a codemods range: not implemented");
|
|
1249
1334
|
case ReleaseType.Major:
|
|
1250
1335
|
return rangeFactory(`${major}`);
|
|
1251
1336
|
case ReleaseType.Minor:
|
|
@@ -1365,6 +1450,10 @@ const register$1 = (program) => {
|
|
|
1365
1450
|
return upgrade({ ...options, target: releaseType });
|
|
1366
1451
|
});
|
|
1367
1452
|
};
|
|
1453
|
+
addReleaseUpgradeCommand(
|
|
1454
|
+
ReleaseType.Latest,
|
|
1455
|
+
"Upgrade to the latest available version of Strapi"
|
|
1456
|
+
);
|
|
1368
1457
|
addReleaseUpgradeCommand(
|
|
1369
1458
|
ReleaseType.Major,
|
|
1370
1459
|
"Upgrade to the next available major version of Strapi"
|
|
@@ -1477,7 +1566,7 @@ When executed on a Strapi plugin project, it shows every codemods.
|
|
|
1477
1566
|
return listCodemods(options);
|
|
1478
1567
|
});
|
|
1479
1568
|
};
|
|
1480
|
-
const version = "5.0
|
|
1569
|
+
const version = "5.1.0";
|
|
1481
1570
|
register$1(commander.program);
|
|
1482
1571
|
register(commander.program);
|
|
1483
1572
|
commander.program.usage("<command> [options]").on("command:*", ([invalidCmd]) => {
|