@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/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;
|
|
@@ -121,16 +121,16 @@ const rangeFactory = (range) => {
|
|
|
121
121
|
const rangeFromReleaseType = (current, identifier) => {
|
|
122
122
|
switch (identifier) {
|
|
123
123
|
case ReleaseType.Major: {
|
|
124
|
-
const nextMajor =
|
|
125
|
-
return rangeFactory(`>${current.raw} <=${nextMajor}`);
|
|
126
|
-
}
|
|
127
|
-
case ReleaseType.Patch: {
|
|
128
|
-
const minor = semver__default.default.inc(current, "minor");
|
|
129
|
-
return rangeFactory(`>${current.raw} <${minor}`);
|
|
124
|
+
const nextMajor = semVerFactory(current.raw).inc("major");
|
|
125
|
+
return rangeFactory(`>${current.raw} <=${nextMajor.major}`);
|
|
130
126
|
}
|
|
131
127
|
case ReleaseType.Minor: {
|
|
132
|
-
const
|
|
133
|
-
return rangeFactory(`>${current.raw} <${
|
|
128
|
+
const nextMajor = semVerFactory(current.raw).inc("major");
|
|
129
|
+
return rangeFactory(`>${current.raw} <${nextMajor.raw}`);
|
|
130
|
+
}
|
|
131
|
+
case ReleaseType.Patch: {
|
|
132
|
+
const nextMinor = semVerFactory(current.raw).inc("minor");
|
|
133
|
+
return rangeFactory(`>${current.raw} <${nextMinor.raw}`);
|
|
134
134
|
}
|
|
135
135
|
default: {
|
|
136
136
|
throw new Error("Not implemented");
|
|
@@ -159,115 +159,6 @@ const handleError = (err, isSilent) => {
|
|
|
159
159
|
}
|
|
160
160
|
process.exit(1);
|
|
161
161
|
};
|
|
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
162
|
class Timer {
|
|
272
163
|
interval;
|
|
273
164
|
constructor() {
|
|
@@ -294,46 +185,117 @@ class Timer {
|
|
|
294
185
|
}
|
|
295
186
|
const timerFactory = () => new Timer();
|
|
296
187
|
const ONE_SECOND_MS = 1e3;
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
188
|
+
const path = (path2) => chalk__default.default.blue(path2);
|
|
189
|
+
const version$1 = (version2) => {
|
|
190
|
+
return chalk__default.default.italic.yellow(`v${version2}`);
|
|
191
|
+
};
|
|
192
|
+
const codemodUID = (uid) => {
|
|
193
|
+
return chalk__default.default.bold.cyan(uid);
|
|
194
|
+
};
|
|
195
|
+
const projectDetails = (project) => {
|
|
196
|
+
return `Project: TYPE=${projectType(project.type)}; CWD=${path(project.cwd)}; PATHS=${project.paths.map(path)}`;
|
|
197
|
+
};
|
|
198
|
+
const projectType = (type) => chalk__default.default.cyan(type);
|
|
199
|
+
const versionRange = (range) => chalk__default.default.italic.yellow(range.raw);
|
|
200
|
+
const highlight = (arg) => chalk__default.default.bold.underline(arg);
|
|
201
|
+
const upgradeStep = (text, step) => {
|
|
202
|
+
return chalk__default.default.bold(`(${step[0]}/${step[1]}) ${text}...`);
|
|
203
|
+
};
|
|
204
|
+
const reports = (reports2) => {
|
|
205
|
+
const rows = reports2.map(({ codemod, report }, i) => {
|
|
206
|
+
const fIndex = chalk__default.default.grey(i);
|
|
207
|
+
const fVersion = chalk__default.default.magenta(codemod.version);
|
|
208
|
+
const fKind = chalk__default.default.yellow(codemod.kind);
|
|
209
|
+
const fFormattedTransformPath = chalk__default.default.cyan(codemod.format());
|
|
210
|
+
const fTimeElapsed = i === 0 ? `${report.timeElapsed}s ${chalk__default.default.dim.italic("(cold start)")}` : `${report.timeElapsed}s`;
|
|
211
|
+
const fAffected = report.ok > 0 ? chalk__default.default.green(report.ok) : chalk__default.default.grey(0);
|
|
212
|
+
const fUnchanged = report.ok === 0 ? chalk__default.default.red(report.nochange) : chalk__default.default.grey(report.nochange);
|
|
213
|
+
return [fIndex, fVersion, fKind, fFormattedTransformPath, fAffected, fUnchanged, fTimeElapsed];
|
|
214
|
+
});
|
|
215
|
+
const table = new CliTable3__default.default({
|
|
216
|
+
style: { compact: true },
|
|
217
|
+
head: [
|
|
218
|
+
chalk__default.default.bold.grey("N°"),
|
|
219
|
+
chalk__default.default.bold.magenta("Version"),
|
|
220
|
+
chalk__default.default.bold.yellow("Kind"),
|
|
221
|
+
chalk__default.default.bold.cyan("Name"),
|
|
222
|
+
chalk__default.default.bold.green("Affected"),
|
|
223
|
+
chalk__default.default.bold.red("Unchanged"),
|
|
224
|
+
chalk__default.default.bold.blue("Duration")
|
|
225
|
+
]
|
|
226
|
+
});
|
|
227
|
+
table.push(...rows);
|
|
228
|
+
return table.toString();
|
|
229
|
+
};
|
|
230
|
+
const codemodList = (codemods) => {
|
|
231
|
+
const rows = codemods.map((codemod, index) => {
|
|
232
|
+
const fIndex = chalk__default.default.grey(index);
|
|
233
|
+
const fVersion = chalk__default.default.magenta(codemod.version);
|
|
234
|
+
const fKind = chalk__default.default.yellow(codemod.kind);
|
|
235
|
+
const fName = chalk__default.default.blue(codemod.format());
|
|
236
|
+
const fUID = codemodUID(codemod.uid);
|
|
237
|
+
return [fIndex, fVersion, fKind, fName, fUID];
|
|
238
|
+
});
|
|
239
|
+
const table = new CliTable3__default.default({
|
|
240
|
+
style: { compact: true },
|
|
241
|
+
head: [
|
|
242
|
+
chalk__default.default.bold.grey("N°"),
|
|
243
|
+
chalk__default.default.bold.magenta("Version"),
|
|
244
|
+
chalk__default.default.bold.yellow("Kind"),
|
|
245
|
+
chalk__default.default.bold.blue("Name"),
|
|
246
|
+
chalk__default.default.bold.cyan("UID")
|
|
247
|
+
]
|
|
248
|
+
});
|
|
249
|
+
table.push(...rows);
|
|
250
|
+
return table.toString();
|
|
251
|
+
};
|
|
252
|
+
const durationMs = (elapsedMs) => {
|
|
253
|
+
const elapsedSeconds = (elapsedMs / ONE_SECOND_MS).toFixed(3);
|
|
254
|
+
return `${elapsedSeconds}s`;
|
|
255
|
+
};
|
|
256
|
+
const NPM_REGISTRY_URL = "https://registry.npmjs.org";
|
|
257
|
+
class Package {
|
|
258
|
+
name;
|
|
259
|
+
packageURL;
|
|
260
|
+
npmPackage;
|
|
261
|
+
constructor(name) {
|
|
262
|
+
this.name = name;
|
|
263
|
+
this.packageURL = `${NPM_REGISTRY_URL}/${name}`;
|
|
264
|
+
this.npmPackage = null;
|
|
301
265
|
}
|
|
302
|
-
get(
|
|
303
|
-
|
|
304
|
-
return this.root();
|
|
305
|
-
}
|
|
306
|
-
return fp.cloneDeep(fp.get(path2, this.json) ?? defaultValue);
|
|
266
|
+
get isLoaded() {
|
|
267
|
+
return this.npmPackage !== null;
|
|
307
268
|
}
|
|
308
|
-
|
|
309
|
-
|
|
269
|
+
assertPackageIsLoaded(npmPackage) {
|
|
270
|
+
assert__default.default(this.isLoaded, "The package is not loaded yet");
|
|
310
271
|
}
|
|
311
|
-
|
|
312
|
-
this.
|
|
313
|
-
return this;
|
|
272
|
+
getVersionsDict() {
|
|
273
|
+
this.assertPackageIsLoaded(this.npmPackage);
|
|
274
|
+
return this.npmPackage.versions;
|
|
314
275
|
}
|
|
315
|
-
|
|
316
|
-
|
|
276
|
+
getVersionsAsList() {
|
|
277
|
+
this.assertPackageIsLoaded(this.npmPackage);
|
|
278
|
+
return Object.values(this.npmPackage.versions);
|
|
317
279
|
}
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
return
|
|
280
|
+
findVersionsInRange(range) {
|
|
281
|
+
const versions = this.getVersionsAsList();
|
|
282
|
+
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
283
|
}
|
|
322
|
-
|
|
323
|
-
|
|
284
|
+
findVersion(version2) {
|
|
285
|
+
const versions = this.getVersionsAsList();
|
|
286
|
+
return versions.find((npmVersion) => semver__default.default.eq(npmVersion.version, version2));
|
|
287
|
+
}
|
|
288
|
+
async refresh() {
|
|
289
|
+
const response = await fetch(this.packageURL);
|
|
290
|
+
assert__default.default(response.ok, `Request failed for ${this.packageURL}`);
|
|
291
|
+
this.npmPackage = await response.json();
|
|
324
292
|
return this;
|
|
325
293
|
}
|
|
294
|
+
versionExists(version2) {
|
|
295
|
+
return this.findVersion(version2) !== void 0;
|
|
296
|
+
}
|
|
326
297
|
}
|
|
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
|
-
};
|
|
298
|
+
const npmPackageFactory = (name) => new Package(name);
|
|
337
299
|
class FileScanner {
|
|
338
300
|
cwd;
|
|
339
301
|
constructor(cwd) {
|
|
@@ -372,6 +334,46 @@ class CodeRunner extends AbstractRunner {
|
|
|
372
334
|
const codeRunnerFactory = (paths, configuration) => {
|
|
373
335
|
return new CodeRunner(paths, configuration);
|
|
374
336
|
};
|
|
337
|
+
class JSONTransformAPI {
|
|
338
|
+
json;
|
|
339
|
+
constructor(json) {
|
|
340
|
+
this.json = fp.cloneDeep(json);
|
|
341
|
+
}
|
|
342
|
+
get(path2, defaultValue) {
|
|
343
|
+
if (!path2) {
|
|
344
|
+
return this.root();
|
|
345
|
+
}
|
|
346
|
+
return fp.cloneDeep(fp.get(path2, this.json) ?? defaultValue);
|
|
347
|
+
}
|
|
348
|
+
has(path2) {
|
|
349
|
+
return fp.has(path2, this.json);
|
|
350
|
+
}
|
|
351
|
+
merge(other) {
|
|
352
|
+
this.json = fp.merge(other, this.json);
|
|
353
|
+
return this;
|
|
354
|
+
}
|
|
355
|
+
root() {
|
|
356
|
+
return fp.cloneDeep(this.json);
|
|
357
|
+
}
|
|
358
|
+
set(path2, value) {
|
|
359
|
+
this.json = fp.set(path2, value, this.json);
|
|
360
|
+
return this;
|
|
361
|
+
}
|
|
362
|
+
remove(path2) {
|
|
363
|
+
this.json = fp.omit(path2, this.json);
|
|
364
|
+
return this;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
const createJSONTransformAPI = (object) => new JSONTransformAPI(object);
|
|
368
|
+
const readJSON = async (path2) => {
|
|
369
|
+
const buffer = await fse__default.default.readFile(path2);
|
|
370
|
+
return JSON.parse(buffer.toString());
|
|
371
|
+
};
|
|
372
|
+
const saveJSON = async (path2, json) => {
|
|
373
|
+
const jsonAsString = `${JSON.stringify(json, null, 2)}
|
|
374
|
+
`;
|
|
375
|
+
await fse__default.default.writeFile(path2, jsonAsString);
|
|
376
|
+
};
|
|
375
377
|
const transformJSON = async (codemodPath, paths, config) => {
|
|
376
378
|
const { dry } = config;
|
|
377
379
|
const startTime = process.hrtime();
|
|
@@ -642,6 +644,13 @@ class UnexpectedError extends Error {
|
|
|
642
644
|
super("Unexpected Error");
|
|
643
645
|
}
|
|
644
646
|
}
|
|
647
|
+
class NPMCandidateNotFoundError extends Error {
|
|
648
|
+
target;
|
|
649
|
+
constructor(target, message = `Couldn't find a valid NPM candidate for "${target}"`) {
|
|
650
|
+
super(message);
|
|
651
|
+
this.target = target;
|
|
652
|
+
}
|
|
653
|
+
}
|
|
645
654
|
const unknownToError = (e) => {
|
|
646
655
|
if (e instanceof Error) {
|
|
647
656
|
return e;
|
|
@@ -651,74 +660,6 @@ const unknownToError = (e) => {
|
|
|
651
660
|
}
|
|
652
661
|
return new UnexpectedError();
|
|
653
662
|
};
|
|
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
663
|
const CODEMOD_CODE_SUFFIX = "code";
|
|
723
664
|
const CODEMOD_JSON_SUFFIX = "json";
|
|
724
665
|
const CODEMOD_ALLOWED_SUFFIXES = [CODEMOD_CODE_SUFFIX, CODEMOD_JSON_SUFFIX];
|
|
@@ -1126,7 +1067,7 @@ class Upgrader {
|
|
|
1126
1067
|
const packageManagerName = await utils.packageManager.getPreferred(projectPath);
|
|
1127
1068
|
this.logger?.debug?.(`Using ${highlight(packageManagerName)} as package manager`);
|
|
1128
1069
|
if (this.isDry) {
|
|
1129
|
-
this.logger?.debug?.(`Skipping dependencies installation (${chalk__default.default.italic("dry mode")}`);
|
|
1070
|
+
this.logger?.debug?.(`Skipping dependencies installation (${chalk__default.default.italic("dry mode")})`);
|
|
1130
1071
|
return;
|
|
1131
1072
|
}
|
|
1132
1073
|
await utils.packageManager.installDependencies(projectPath, packageManagerName, {
|
|
@@ -1145,72 +1086,145 @@ class Upgrader {
|
|
|
1145
1086
|
}
|
|
1146
1087
|
const resolveNPMTarget = (project, target, npmPackage) => {
|
|
1147
1088
|
if (isSemverInstance(target)) {
|
|
1148
|
-
|
|
1089
|
+
const version2 = npmPackage.findVersion(target);
|
|
1090
|
+
if (!version2) {
|
|
1091
|
+
throw new NPMCandidateNotFoundError(target);
|
|
1092
|
+
}
|
|
1093
|
+
return version2;
|
|
1149
1094
|
}
|
|
1150
1095
|
if (isSemVerReleaseType(target)) {
|
|
1151
1096
|
const range = rangeFromVersions(project.strapiVersion, target);
|
|
1152
1097
|
const npmVersionsMatches = npmPackage.findVersionsInRange(range);
|
|
1153
|
-
|
|
1098
|
+
const version2 = npmVersionsMatches.at(-1);
|
|
1099
|
+
if (!version2) {
|
|
1100
|
+
throw new NPMCandidateNotFoundError(range, `The project is already up-to-date (${target})`);
|
|
1101
|
+
}
|
|
1102
|
+
return version2;
|
|
1154
1103
|
}
|
|
1155
|
-
|
|
1104
|
+
throw new NPMCandidateNotFoundError(target);
|
|
1156
1105
|
};
|
|
1157
1106
|
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);
|
|
1107
|
+
const npmTarget = resolveNPMTarget(project, target, npmPackage);
|
|
1108
|
+
const semverTarget = semVerFactory(npmTarget.version);
|
|
1163
1109
|
if (semver__default.default.eq(semverTarget, project.strapiVersion)) {
|
|
1164
|
-
throw new Error(`The project is already
|
|
1110
|
+
throw new Error(`The project is already using v${semverTarget}`);
|
|
1165
1111
|
}
|
|
1166
1112
|
return new Upgrader(project, semverTarget, npmPackage);
|
|
1167
1113
|
};
|
|
1168
1114
|
const successReport = () => ({ success: true, error: null });
|
|
1169
1115
|
const erroredReport = (error) => ({ success: false, error });
|
|
1170
1116
|
const STRAPI_PACKAGE_NAME = "@strapi/strapi";
|
|
1171
|
-
|
|
1172
|
-
|
|
1117
|
+
class Requirement {
|
|
1118
|
+
isRequired;
|
|
1173
1119
|
name;
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
constructor(name) {
|
|
1120
|
+
testCallback;
|
|
1121
|
+
children;
|
|
1122
|
+
constructor(name, testCallback, isRequired) {
|
|
1177
1123
|
this.name = name;
|
|
1178
|
-
this.
|
|
1179
|
-
this.
|
|
1124
|
+
this.testCallback = testCallback;
|
|
1125
|
+
this.isRequired = isRequired ?? true;
|
|
1126
|
+
this.children = [];
|
|
1180
1127
|
}
|
|
1181
|
-
|
|
1182
|
-
|
|
1128
|
+
setChildren(children) {
|
|
1129
|
+
this.children = children;
|
|
1130
|
+
return this;
|
|
1183
1131
|
}
|
|
1184
|
-
|
|
1185
|
-
|
|
1132
|
+
addChild(child) {
|
|
1133
|
+
this.children.push(child);
|
|
1134
|
+
return this;
|
|
1186
1135
|
}
|
|
1187
|
-
|
|
1188
|
-
this.
|
|
1189
|
-
|
|
1136
|
+
asOptional() {
|
|
1137
|
+
const newInstance = requirementFactory(this.name, this.testCallback, false);
|
|
1138
|
+
newInstance.setChildren(this.children);
|
|
1139
|
+
return newInstance;
|
|
1190
1140
|
}
|
|
1191
|
-
|
|
1192
|
-
this.
|
|
1193
|
-
|
|
1141
|
+
asRequired() {
|
|
1142
|
+
const newInstance = requirementFactory(this.name, this.testCallback, true);
|
|
1143
|
+
newInstance.setChildren(this.children);
|
|
1144
|
+
return newInstance;
|
|
1194
1145
|
}
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1146
|
+
async test(context) {
|
|
1147
|
+
try {
|
|
1148
|
+
await this.testCallback?.(context);
|
|
1149
|
+
return ok();
|
|
1150
|
+
} catch (e) {
|
|
1151
|
+
if (e instanceof Error) {
|
|
1152
|
+
return errored(e);
|
|
1153
|
+
}
|
|
1154
|
+
if (typeof e === "string") {
|
|
1155
|
+
return errored(new Error(e));
|
|
1156
|
+
}
|
|
1157
|
+
return errored(new Error("Unknown error"));
|
|
1158
|
+
}
|
|
1198
1159
|
}
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1160
|
+
}
|
|
1161
|
+
const ok = () => ({ pass: true, error: null });
|
|
1162
|
+
const errored = (error) => ({ pass: false, error });
|
|
1163
|
+
const requirementFactory = (name, testCallback, isRequired) => new Requirement(name, testCallback, isRequired);
|
|
1164
|
+
const REQUIRE_AVAILABLE_NEXT_MAJOR = requirementFactory(
|
|
1165
|
+
"REQUIRE_AVAILABLE_NEXT_MAJOR",
|
|
1166
|
+
(context) => {
|
|
1167
|
+
const { project, target } = context;
|
|
1168
|
+
const currentMajor = project.strapiVersion.major;
|
|
1169
|
+
const targetedMajor = target.major;
|
|
1170
|
+
if (targetedMajor === currentMajor) {
|
|
1171
|
+
throw new Error(`You're already on the latest major version (v${currentMajor})`);
|
|
1172
|
+
}
|
|
1202
1173
|
}
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1174
|
+
);
|
|
1175
|
+
const REQUIRE_LATEST_FOR_CURRENT_MAJOR = requirementFactory(
|
|
1176
|
+
"REQUIRE_LATEST_FOR_CURRENT_MAJOR",
|
|
1177
|
+
(context) => {
|
|
1178
|
+
const { project, target, npmVersionsMatches } = context;
|
|
1179
|
+
const { major: currentMajor } = project.strapiVersion;
|
|
1180
|
+
const invalidMatches = npmVersionsMatches.filter(
|
|
1181
|
+
(match) => semVerFactory(match.version).major === currentMajor
|
|
1182
|
+
);
|
|
1183
|
+
if (invalidMatches.length > 0) {
|
|
1184
|
+
const invalidVersions = invalidMatches.map((match) => match.version);
|
|
1185
|
+
const invalidVersionsCount = invalidVersions.length;
|
|
1186
|
+
throw new Error(
|
|
1187
|
+
`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.`
|
|
1188
|
+
);
|
|
1189
|
+
}
|
|
1208
1190
|
}
|
|
1209
|
-
|
|
1210
|
-
|
|
1191
|
+
);
|
|
1192
|
+
const REQUIRE_GIT_CLEAN_REPOSITORY = requirementFactory(
|
|
1193
|
+
"REQUIRE_GIT_CLEAN_REPOSITORY",
|
|
1194
|
+
async (context) => {
|
|
1195
|
+
const git = simpleGit__default.default({ baseDir: context.project.cwd });
|
|
1196
|
+
const status = await git.status();
|
|
1197
|
+
if (!status.isClean()) {
|
|
1198
|
+
throw new Error(
|
|
1199
|
+
"Repository is not clean. Please commit or stash any changes before upgrading"
|
|
1200
|
+
);
|
|
1201
|
+
}
|
|
1211
1202
|
}
|
|
1212
|
-
|
|
1213
|
-
const
|
|
1203
|
+
);
|
|
1204
|
+
const REQUIRE_GIT_REPOSITORY = requirementFactory(
|
|
1205
|
+
"REQUIRE_GIT_REPOSITORY",
|
|
1206
|
+
async (context) => {
|
|
1207
|
+
const git = simpleGit__default.default({ baseDir: context.project.cwd });
|
|
1208
|
+
const isRepo = await git.checkIsRepo();
|
|
1209
|
+
if (!isRepo) {
|
|
1210
|
+
throw new Error("Not a git repository (or any of the parent directories)");
|
|
1211
|
+
}
|
|
1212
|
+
}
|
|
1213
|
+
).addChild(REQUIRE_GIT_CLEAN_REPOSITORY.asOptional());
|
|
1214
|
+
const REQUIRE_GIT_INSTALLED = requirementFactory(
|
|
1215
|
+
"REQUIRE_GIT_INSTALLED",
|
|
1216
|
+
async (context) => {
|
|
1217
|
+
const git = simpleGit__default.default({ baseDir: context.project.cwd });
|
|
1218
|
+
try {
|
|
1219
|
+
await git.version();
|
|
1220
|
+
} catch {
|
|
1221
|
+
throw new Error("Git is not installed");
|
|
1222
|
+
}
|
|
1223
|
+
}
|
|
1224
|
+
).addChild(REQUIRE_GIT_REPOSITORY.asOptional());
|
|
1225
|
+
const REQUIRE_GIT = requirementFactory("REQUIRE_GIT", null).addChild(
|
|
1226
|
+
REQUIRE_GIT_INSTALLED.asOptional()
|
|
1227
|
+
);
|
|
1214
1228
|
const upgrade$1 = async (options) => {
|
|
1215
1229
|
const timer = timerFactory();
|
|
1216
1230
|
const { logger, codemodsTarget } = options;
|
|
@@ -1222,6 +1236,9 @@ const upgrade$1 = async (options) => {
|
|
|
1222
1236
|
`The "${options.target}" upgrade can only be run on a Strapi project; for plugins, please use "codemods".`
|
|
1223
1237
|
);
|
|
1224
1238
|
}
|
|
1239
|
+
logger.debug(
|
|
1240
|
+
`Application: VERSION=${version$1(project.packageJSON.version)}; STRAPI_VERSION=${version$1(project.strapiVersion)}`
|
|
1241
|
+
);
|
|
1225
1242
|
const npmPackage = npmPackageFactory(STRAPI_PACKAGE_NAME);
|
|
1226
1243
|
await npmPackage.refresh();
|
|
1227
1244
|
const upgrader = upgraderFactory(project, options.target, npmPackage).dry(options.dry ?? false).onConfirm(options.confirm ?? null).setLogger(logger);
|
|
@@ -1237,7 +1254,7 @@ const upgrade$1 = async (options) => {
|
|
|
1237
1254
|
throw upgradeReport.error;
|
|
1238
1255
|
}
|
|
1239
1256
|
timer.stop();
|
|
1240
|
-
logger.info(`Completed in ${durationMs(timer.elapsedMs)}`);
|
|
1257
|
+
logger.info(`Completed in ${durationMs(timer.elapsedMs)}ms`);
|
|
1241
1258
|
};
|
|
1242
1259
|
const resolvePath = (cwd) => path__default.default.resolve(cwd ?? process.cwd());
|
|
1243
1260
|
const getRangeFromTarget = (currentVersion, target) => {
|
|
@@ -1477,7 +1494,7 @@ When executed on a Strapi plugin project, it shows every codemods.
|
|
|
1477
1494
|
return listCodemods(options);
|
|
1478
1495
|
});
|
|
1479
1496
|
};
|
|
1480
|
-
const version = "0.0.0-
|
|
1497
|
+
const version = "0.0.0-next.3c5400321681b66eb35ab84c11113a78c1d9386e";
|
|
1481
1498
|
register$1(commander.program);
|
|
1482
1499
|
register(commander.program);
|
|
1483
1500
|
commander.program.usage("<command> [options]").on("command:*", ([invalidCmd]) => {
|