@strapi/upgrade 5.0.0-beta.1 → 5.0.0-beta.3

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.
Files changed (58) hide show
  1. package/dist/cli.js +1452 -5
  2. package/dist/cli.js.map +1 -1
  3. package/dist/index.js +228 -92
  4. package/dist/index.js.map +1 -1
  5. package/dist/index.mjs +229 -93
  6. package/dist/index.mjs.map +1 -1
  7. package/dist/modules/codemod/codemod.d.ts +4 -2
  8. package/dist/modules/codemod/codemod.d.ts.map +1 -1
  9. package/dist/modules/codemod/types.d.ts +8 -1
  10. package/dist/modules/codemod/types.d.ts.map +1 -1
  11. package/dist/modules/codemod-repository/constants.d.ts.map +1 -1
  12. package/dist/modules/codemod-repository/repository.d.ts +5 -5
  13. package/dist/modules/codemod-repository/repository.d.ts.map +1 -1
  14. package/dist/modules/codemod-repository/types.d.ts +7 -3
  15. package/dist/modules/codemod-repository/types.d.ts.map +1 -1
  16. package/dist/modules/codemod-runner/codemod-runner.d.ts +6 -3
  17. package/dist/modules/codemod-runner/codemod-runner.d.ts.map +1 -1
  18. package/dist/modules/codemod-runner/index.d.ts +1 -0
  19. package/dist/modules/codemod-runner/index.d.ts.map +1 -1
  20. package/dist/modules/codemod-runner/types.d.ts +1 -0
  21. package/dist/modules/codemod-runner/types.d.ts.map +1 -1
  22. package/dist/modules/format/formats.d.ts +5 -0
  23. package/dist/modules/format/formats.d.ts.map +1 -1
  24. package/dist/modules/project/project.d.ts +1 -1
  25. package/dist/modules/project/project.d.ts.map +1 -1
  26. package/dist/modules/project/types.d.ts +1 -0
  27. package/dist/modules/project/types.d.ts.map +1 -1
  28. package/dist/modules/project/utils.d.ts +1 -1
  29. package/dist/modules/project/utils.d.ts.map +1 -1
  30. package/dist/modules/upgrader/upgrader.d.ts.map +1 -1
  31. package/dist/modules/version/range.d.ts +2 -0
  32. package/dist/modules/version/range.d.ts.map +1 -1
  33. package/dist/tasks/codemods/index.d.ts +2 -1
  34. package/dist/tasks/codemods/index.d.ts.map +1 -1
  35. package/dist/tasks/codemods/list-codemods.d.ts +3 -0
  36. package/dist/tasks/codemods/list-codemods.d.ts.map +1 -0
  37. package/dist/tasks/codemods/run-codemods.d.ts +3 -0
  38. package/dist/tasks/codemods/run-codemods.d.ts.map +1 -0
  39. package/dist/tasks/codemods/types.d.ts +9 -3
  40. package/dist/tasks/codemods/types.d.ts.map +1 -1
  41. package/dist/tasks/codemods/utils.d.ts +6 -0
  42. package/dist/tasks/codemods/utils.d.ts.map +1 -0
  43. package/dist/tasks/index.d.ts +1 -1
  44. package/dist/tasks/index.d.ts.map +1 -1
  45. package/package.json +7 -7
  46. package/resources/codemods/5.0.0/entity-service-document-service.code.ts +374 -0
  47. package/resources/codemods/5.0.0/strapi-public-interface.code.ts +126 -0
  48. package/resources/codemods/5.0.0/utils-public-interface.code.ts +320 -0
  49. package/dist/_chunks/codemod-runner-aVWS9EOj.js +0 -798
  50. package/dist/_chunks/codemod-runner-aVWS9EOj.js.map +0 -1
  51. package/dist/_chunks/codemods-FxCTNGki.js +0 -105
  52. package/dist/_chunks/codemods-FxCTNGki.js.map +0 -1
  53. package/dist/_chunks/index-qYtax-pz.js +0 -103
  54. package/dist/_chunks/index-qYtax-pz.js.map +0 -1
  55. package/dist/_chunks/upgrade-_IPNaAR-.js +0 -361
  56. package/dist/_chunks/upgrade-_IPNaAR-.js.map +0 -1
  57. package/dist/tasks/codemods/codemods.d.ts +0 -3
  58. package/dist/tasks/codemods/codemods.d.ts.map +0 -1
@@ -1,798 +0,0 @@
1
- "use strict";
2
- const semver = require("semver");
3
- const index = require("./index-qYtax-pz.js");
4
- const chalk = require("chalk");
5
- const simpleGit = require("simple-git");
6
- const path = require("node:path");
7
- const assert = require("node:assert");
8
- const fse = require("fs-extra");
9
- const glob = require("glob");
10
- const Runner = require("jscodeshift/src/Runner");
11
- const fp = require("lodash/fp");
12
- const node = require("esbuild-register/dist/node");
13
- const CliTable3 = require("cli-table3");
14
- const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
15
- const semver__default = /* @__PURE__ */ _interopDefault(semver);
16
- const chalk__default = /* @__PURE__ */ _interopDefault(chalk);
17
- const simpleGit__default = /* @__PURE__ */ _interopDefault(simpleGit);
18
- const path__default = /* @__PURE__ */ _interopDefault(path);
19
- const assert__default = /* @__PURE__ */ _interopDefault(assert);
20
- const fse__default = /* @__PURE__ */ _interopDefault(fse);
21
- const CliTable3__default = /* @__PURE__ */ _interopDefault(CliTable3);
22
- const rangeFactory = (range) => {
23
- return new semver__default.default.Range(range);
24
- };
25
- const rangeFromReleaseType = (current, identifier) => {
26
- switch (identifier) {
27
- case index.ReleaseType.Major: {
28
- const nextMajor = semver__default.default.inc(current, "major");
29
- return rangeFactory(`>${current.raw} <=${nextMajor}`);
30
- }
31
- case index.ReleaseType.Patch: {
32
- const minor = semver__default.default.inc(current, "minor");
33
- return rangeFactory(`>${current.raw} <${minor}`);
34
- }
35
- case index.ReleaseType.Minor: {
36
- const major = semver__default.default.inc(current, "major");
37
- return rangeFactory(`>${current.raw} <${major}`);
38
- }
39
- default: {
40
- throw new Error("Not implemented");
41
- }
42
- }
43
- };
44
- const rangeFromVersions = (currentVersion, target) => {
45
- if (index.isSemverInstance(target)) {
46
- return rangeFactory(`>${currentVersion.raw} <=${target.raw}`);
47
- }
48
- if (index.isSemVerReleaseType(target)) {
49
- return rangeFromReleaseType(currentVersion, target);
50
- }
51
- throw new Error(`Invalid target set: ${target}`);
52
- };
53
- class Logger {
54
- isDebug;
55
- isSilent;
56
- nbErrorsCalls;
57
- nbWarningsCalls;
58
- constructor(options = {}) {
59
- this.isDebug = options.debug ?? false;
60
- this.isSilent = options.silent ?? false;
61
- this.nbErrorsCalls = 0;
62
- this.nbWarningsCalls = 0;
63
- }
64
- get isNotSilent() {
65
- return !this.isSilent;
66
- }
67
- get errors() {
68
- return this.nbErrorsCalls;
69
- }
70
- get warnings() {
71
- return this.nbWarningsCalls;
72
- }
73
- get stdout() {
74
- return this.isSilent ? void 0 : process.stdout;
75
- }
76
- get stderr() {
77
- return this.isSilent ? void 0 : process.stderr;
78
- }
79
- setDebug(debug) {
80
- this.isDebug = debug;
81
- return this;
82
- }
83
- setSilent(silent) {
84
- this.isSilent = silent;
85
- return this;
86
- }
87
- debug(...args) {
88
- const isDebugEnabled = this.isNotSilent && this.isDebug;
89
- if (isDebugEnabled) {
90
- console.log(chalk__default.default.cyan(`[DEBUG] [${nowAsISO()}]`), ...args);
91
- }
92
- return this;
93
- }
94
- error(...args) {
95
- this.nbErrorsCalls += 1;
96
- if (this.isNotSilent) {
97
- console.error(chalk__default.default.red(`[ERROR] [${nowAsISO()}]`), ...args);
98
- }
99
- return this;
100
- }
101
- info(...args) {
102
- if (this.isNotSilent) {
103
- console.info(chalk__default.default.blue(`[INFO] [${(/* @__PURE__ */ new Date()).toISOString()}]`), ...args);
104
- }
105
- return this;
106
- }
107
- raw(...args) {
108
- if (this.isNotSilent) {
109
- console.log(...args);
110
- }
111
- return this;
112
- }
113
- warn(...args) {
114
- this.nbWarningsCalls += 1;
115
- if (this.isNotSilent) {
116
- console.warn(chalk__default.default.yellow(`[WARN] [${(/* @__PURE__ */ new Date()).toISOString()}]`), ...args);
117
- }
118
- return this;
119
- }
120
- }
121
- const nowAsISO = () => (/* @__PURE__ */ new Date()).toISOString();
122
- const loggerFactory = (options = {}) => new Logger(options);
123
- const handleError = (err, isSilent) => {
124
- if (!isSilent) {
125
- console.error(
126
- chalk__default.default.red(`[ERROR] [${(/* @__PURE__ */ new Date()).toISOString()}]`),
127
- err instanceof Error ? err.message : err
128
- );
129
- }
130
- process.exit(1);
131
- };
132
- class Requirement {
133
- isRequired;
134
- name;
135
- testCallback;
136
- children;
137
- constructor(name, testCallback, isRequired) {
138
- this.name = name;
139
- this.testCallback = testCallback;
140
- this.isRequired = isRequired ?? true;
141
- this.children = [];
142
- }
143
- setChildren(children) {
144
- this.children = children;
145
- return this;
146
- }
147
- addChild(child) {
148
- this.children.push(child);
149
- return this;
150
- }
151
- asOptional() {
152
- const newInstance = requirementFactory(this.name, this.testCallback, false);
153
- newInstance.setChildren(this.children);
154
- return newInstance;
155
- }
156
- asRequired() {
157
- const newInstance = requirementFactory(this.name, this.testCallback, true);
158
- newInstance.setChildren(this.children);
159
- return newInstance;
160
- }
161
- async test(context) {
162
- try {
163
- await this.testCallback?.(context);
164
- return ok();
165
- } catch (e) {
166
- if (e instanceof Error) {
167
- return errored(e);
168
- }
169
- if (typeof e === "string") {
170
- return errored(new Error(e));
171
- }
172
- return errored(new Error("Unknown error"));
173
- }
174
- }
175
- }
176
- const ok = () => ({ pass: true, error: null });
177
- const errored = (error) => ({ pass: false, error });
178
- const requirementFactory = (name, testCallback, isRequired) => new Requirement(name, testCallback, isRequired);
179
- const REQUIRE_GIT_CLEAN_REPOSITORY = requirementFactory(
180
- "REQUIRE_GIT_CLEAN_REPOSITORY",
181
- async (context) => {
182
- const git = simpleGit__default.default({ baseDir: context.project.cwd });
183
- const status = await git.status();
184
- if (!status.isClean()) {
185
- throw new Error(
186
- "Repository is not clean. Please commit or stash any changes before upgrading"
187
- );
188
- }
189
- }
190
- );
191
- const REQUIRE_GIT_REPOSITORY = requirementFactory(
192
- "REQUIRE_GIT_REPOSITORY",
193
- async (context) => {
194
- const git = simpleGit__default.default({ baseDir: context.project.cwd });
195
- const isRepo = await git.checkIsRepo();
196
- if (!isRepo) {
197
- throw new Error("Not a git repository (or any of the parent directories)");
198
- }
199
- }
200
- ).addChild(REQUIRE_GIT_CLEAN_REPOSITORY.asOptional());
201
- const REQUIRE_GIT_INSTALLED = requirementFactory(
202
- "REQUIRE_GIT_INSTALLED",
203
- async (context) => {
204
- const git = simpleGit__default.default({ baseDir: context.project.cwd });
205
- try {
206
- await git.version();
207
- } catch {
208
- throw new Error("Git is not installed");
209
- }
210
- }
211
- ).addChild(REQUIRE_GIT_REPOSITORY.asOptional());
212
- const REQUIRE_GIT = requirementFactory("REQUIRE_GIT", null).addChild(
213
- REQUIRE_GIT_INSTALLED.asOptional()
214
- );
215
- class Timer {
216
- interval;
217
- constructor() {
218
- this.reset();
219
- }
220
- get elapsedMs() {
221
- const { start, end } = this.interval;
222
- return end ? end - start : Date.now() - start;
223
- }
224
- get end() {
225
- return this.interval.end;
226
- }
227
- get start() {
228
- return this.interval.start;
229
- }
230
- stop() {
231
- this.interval.end = Date.now();
232
- return this.elapsedMs;
233
- }
234
- reset() {
235
- this.interval = { start: Date.now(), end: null };
236
- return this;
237
- }
238
- }
239
- const timerFactory = () => new Timer();
240
- const ONE_SECOND_MS = 1e3;
241
- class JSONTransformAPI {
242
- json;
243
- constructor(json) {
244
- this.json = fp.cloneDeep(json);
245
- }
246
- get(path2, defaultValue) {
247
- if (!path2) {
248
- return this.root();
249
- }
250
- return fp.cloneDeep(fp.get(path2, this.json) ?? defaultValue);
251
- }
252
- has(path2) {
253
- return fp.has(path2, this.json);
254
- }
255
- merge(other) {
256
- this.json = fp.merge(other, this.json);
257
- return this;
258
- }
259
- root() {
260
- return fp.cloneDeep(this.json);
261
- }
262
- set(path2, value) {
263
- this.json = fp.set(path2, value, this.json);
264
- return this;
265
- }
266
- remove(path2) {
267
- this.json = fp.omit(path2, this.json);
268
- return this;
269
- }
270
- }
271
- const createJSONTransformAPI = (object) => new JSONTransformAPI(object);
272
- const readJSON = async (path2) => {
273
- const buffer = await fse__default.default.readFile(path2);
274
- return JSON.parse(buffer.toString());
275
- };
276
- const saveJSON = async (path2, json) => {
277
- const jsonAsString = `${JSON.stringify(json, null, 2)}
278
- `;
279
- await fse__default.default.writeFile(path2, jsonAsString);
280
- };
281
- class FileScanner {
282
- cwd;
283
- constructor(cwd) {
284
- this.cwd = cwd;
285
- }
286
- scan(patterns) {
287
- const filenames = glob.glob.sync(patterns, { cwd: this.cwd });
288
- return filenames.map((filename) => path__default.default.join(this.cwd, filename));
289
- }
290
- }
291
- const fileScannerFactory = (cwd) => new FileScanner(cwd);
292
- class AbstractRunner {
293
- paths;
294
- configuration;
295
- constructor(paths, configuration) {
296
- this.paths = paths;
297
- this.configuration = configuration;
298
- }
299
- async run(codemod, configuration) {
300
- const isValidCodemod = this.valid(codemod);
301
- if (!isValidCodemod) {
302
- throw new Error(`Invalid codemod provided to the runner: ${codemod.filename}`);
303
- }
304
- const runConfiguration = { ...this.configuration, ...configuration };
305
- return this.runner(codemod.path, this.paths, runConfiguration);
306
- }
307
- }
308
- class CodeRunner extends AbstractRunner {
309
- runner = Runner.run;
310
- valid(codemod) {
311
- return codemod.kind === "code";
312
- }
313
- }
314
- const codeRunnerFactory = (paths, configuration) => {
315
- return new CodeRunner(paths, configuration);
316
- };
317
- const transformJSON = async (codemodPath, paths, config) => {
318
- const { dry } = config;
319
- const startTime = process.hrtime();
320
- const report = {
321
- ok: 0,
322
- nochange: 0,
323
- skip: 0,
324
- error: 0,
325
- timeElapsed: "",
326
- stats: {}
327
- };
328
- const esbuildOptions = { extensions: [".js", ".mjs", ".ts"] };
329
- const { unregister } = node.register(esbuildOptions);
330
- const module2 = require(codemodPath);
331
- unregister();
332
- const codemod = typeof module2.default === "function" ? module2.default : module2;
333
- assert__default.default(typeof codemod === "function", `Codemod must be a function. Found ${typeof codemod}`);
334
- for (const path2 of paths) {
335
- try {
336
- const json = await readJSON(path2);
337
- assert__default.default(typeof json === "object" && !Array.isArray(json) && json !== null);
338
- const file = { path: path2, json };
339
- const params = { cwd: config.cwd, json: createJSONTransformAPI };
340
- const out = await codemod(file, params);
341
- if (out === void 0) {
342
- report.error += 1;
343
- } else if (!fp.isEqual(json, out)) {
344
- if (!dry) {
345
- await saveJSON(path2, out);
346
- }
347
- report.ok += 1;
348
- } else {
349
- report.nochange += 1;
350
- }
351
- } catch {
352
- report.error += 1;
353
- }
354
- }
355
- const endTime = process.hrtime(startTime);
356
- report.timeElapsed = (endTime[0] + endTime[1] / 1e9).toFixed(3);
357
- return report;
358
- };
359
- class JSONRunner extends AbstractRunner {
360
- runner = transformJSON;
361
- valid(codemod) {
362
- return codemod.kind === "json";
363
- }
364
- }
365
- const jsonRunnerFactory = (paths, configuration) => {
366
- return new JSONRunner(paths, configuration);
367
- };
368
- const PROJECT_PACKAGE_JSON = "package.json";
369
- const PROJECT_DEFAULT_ALLOWED_ROOT_PATHS = ["src", "config", "public"];
370
- const PROJECT_DEFAULT_CODE_EXTENSIONS = [
371
- // Source files
372
- "js",
373
- "mjs",
374
- "ts",
375
- // React files
376
- "jsx",
377
- "tsx"
378
- ];
379
- const PROJECT_DEFAULT_JSON_EXTENSIONS = ["json"];
380
- const PROJECT_DEFAULT_ALLOWED_EXTENSIONS = [
381
- ...PROJECT_DEFAULT_CODE_EXTENSIONS,
382
- ...PROJECT_DEFAULT_JSON_EXTENSIONS
383
- ];
384
- const PROJECT_DEFAULT_PATTERNS = ["package.json"];
385
- const SCOPED_STRAPI_PACKAGE_PREFIX = "@strapi/";
386
- const STRAPI_DEPENDENCY_NAME = `${SCOPED_STRAPI_PACKAGE_PREFIX}strapi`;
387
- class Project {
388
- cwd;
389
- // The following properties are assigned during the .refresh() call in the constructor.
390
- files;
391
- packageJSONPath;
392
- packageJSON;
393
- constructor(cwd) {
394
- if (!fse__default.default.pathExistsSync(cwd)) {
395
- throw new Error(`ENOENT: no such file or directory, access '${cwd}'`);
396
- }
397
- this.cwd = cwd;
398
- this.refresh();
399
- }
400
- getFilesByExtensions(extensions) {
401
- return this.files.filter((filePath) => {
402
- const fileExtension = path__default.default.extname(filePath);
403
- return extensions.includes(fileExtension);
404
- });
405
- }
406
- refresh() {
407
- this.refreshPackageJSON();
408
- this.refreshProjectFiles();
409
- return this;
410
- }
411
- async runCodemods(codemods, options) {
412
- const runners = this.createProjectCodemodsRunners(options.dry);
413
- const reports2 = [];
414
- for (const codemod of codemods) {
415
- for (const runner of runners) {
416
- if (runner.valid(codemod)) {
417
- const report = await runner.run(codemod);
418
- reports2.push({ codemod, report });
419
- }
420
- }
421
- }
422
- return reports2;
423
- }
424
- createProjectCodemodsRunners(dry = false) {
425
- const jsonExtensions = PROJECT_DEFAULT_JSON_EXTENSIONS.map(
426
- (ext) => `.${ext}`
427
- );
428
- const codeExtensions = PROJECT_DEFAULT_CODE_EXTENSIONS.map(
429
- (ext) => `.${ext}`
430
- );
431
- const jsonFiles = this.getFilesByExtensions(jsonExtensions);
432
- const codeFiles = this.getFilesByExtensions(codeExtensions);
433
- const codeRunner = codeRunnerFactory(codeFiles, {
434
- dry,
435
- parser: "ts",
436
- runInBand: true,
437
- babel: true,
438
- extensions: PROJECT_DEFAULT_CODE_EXTENSIONS.join(","),
439
- // Don't output any log coming from the runner
440
- print: false,
441
- silent: true,
442
- verbose: 0
443
- });
444
- const jsonRunner = jsonRunnerFactory(jsonFiles, { dry, cwd: this.cwd });
445
- return [codeRunner, jsonRunner];
446
- }
447
- refreshPackageJSON() {
448
- const packageJSONPath = path__default.default.join(this.cwd, PROJECT_PACKAGE_JSON);
449
- try {
450
- fse__default.default.accessSync(packageJSONPath);
451
- } catch {
452
- throw new Error(`Could not find a ${PROJECT_PACKAGE_JSON} file in ${this.cwd}`);
453
- }
454
- const packageJSONBuffer = fse__default.default.readFileSync(packageJSONPath);
455
- this.packageJSONPath = packageJSONPath;
456
- this.packageJSON = JSON.parse(packageJSONBuffer.toString());
457
- }
458
- refreshProjectFiles() {
459
- const allowedRootPaths = formatGlobCollectionPattern(
460
- PROJECT_DEFAULT_ALLOWED_ROOT_PATHS
461
- );
462
- const allowedExtensions = formatGlobCollectionPattern(
463
- PROJECT_DEFAULT_ALLOWED_EXTENSIONS
464
- );
465
- const projectFilesPattern = `./${allowedRootPaths}/**/*.${allowedExtensions}`;
466
- const patterns = [projectFilesPattern, ...PROJECT_DEFAULT_PATTERNS];
467
- const scanner = fileScannerFactory(this.cwd);
468
- this.files = scanner.scan(patterns);
469
- }
470
- }
471
- class AppProject extends Project {
472
- strapiVersion;
473
- type = "app";
474
- constructor(cwd) {
475
- super(cwd);
476
- this.refreshStrapiVersion();
477
- }
478
- refresh() {
479
- super.refresh();
480
- this.refreshStrapiVersion();
481
- return this;
482
- }
483
- refreshStrapiVersion() {
484
- this.strapiVersion = // First try to get the strapi version from the package.json dependencies
485
- this.findStrapiVersionFromProjectPackageJSON() ?? // If the version found is not a valid SemVer, get the Strapi version from the installed package
486
- this.findLocallyInstalledStrapiVersion();
487
- }
488
- findStrapiVersionFromProjectPackageJSON() {
489
- const projectName = this.packageJSON.name;
490
- const version2 = this.packageJSON.dependencies?.[STRAPI_DEPENDENCY_NAME];
491
- if (version2 === void 0) {
492
- throw new Error(
493
- `No version of ${STRAPI_DEPENDENCY_NAME} was found in ${projectName}. Are you in a valid Strapi project?`
494
- );
495
- }
496
- const isValidSemVer2 = index.isLiteralSemVer(version2) && semver__default.default.valid(version2) === version2;
497
- return isValidSemVer2 ? index.semVerFactory(version2) : void 0;
498
- }
499
- findLocallyInstalledStrapiVersion() {
500
- const packageSearchText = `${STRAPI_DEPENDENCY_NAME}/package.json`;
501
- let strapiPackageJSONPath;
502
- let strapiPackageJSON;
503
- try {
504
- strapiPackageJSONPath = require.resolve(packageSearchText, { paths: [this.cwd] });
505
- strapiPackageJSON = require(strapiPackageJSONPath);
506
- assert__default.default(typeof strapiPackageJSON === "object");
507
- } catch {
508
- throw new Error(
509
- `Cannot resolve module "${STRAPI_DEPENDENCY_NAME}" from paths [${this.cwd}]`
510
- );
511
- }
512
- const strapiVersion = strapiPackageJSON.version;
513
- if (!index.isValidSemVer(strapiVersion)) {
514
- throw new Error(
515
- `Invalid ${STRAPI_DEPENDENCY_NAME} version found in ${strapiPackageJSONPath} (${strapiVersion})`
516
- );
517
- }
518
- return index.semVerFactory(strapiVersion);
519
- }
520
- }
521
- const formatGlobCollectionPattern = (collection) => {
522
- assert__default.default(
523
- collection.length > 0,
524
- "Invalid pattern provided, the given collection needs at least 1 element"
525
- );
526
- return collection.length === 1 ? collection[0] : `{${collection}}`;
527
- };
528
- class PluginProject extends Project {
529
- type = "plugin";
530
- }
531
- const isPlugin = (cwd) => {
532
- const packageJSONPath = path__default.default.join(cwd, PROJECT_PACKAGE_JSON);
533
- try {
534
- fse__default.default.accessSync(packageJSONPath);
535
- } catch {
536
- throw new Error(`Could not find a ${PROJECT_PACKAGE_JSON} file in ${cwd}`);
537
- }
538
- const packageJSONBuffer = fse__default.default.readFileSync(packageJSONPath);
539
- const packageJSON = JSON.parse(packageJSONBuffer.toString());
540
- return packageJSON?.strapi?.kind === "plugin";
541
- };
542
- const projectFactory = (cwd) => {
543
- fse__default.default.accessSync(cwd);
544
- if (isPlugin(cwd)) {
545
- return new PluginProject(cwd);
546
- }
547
- return new AppProject(cwd);
548
- };
549
- const isAppProject = (project) => {
550
- return project instanceof AppProject;
551
- };
552
- class UnexpectedError extends Error {
553
- constructor() {
554
- super("Unexpected Error");
555
- }
556
- }
557
- const unknownToError = (e) => {
558
- if (e instanceof Error) {
559
- return e;
560
- }
561
- if (typeof e === "string") {
562
- return new Error(e);
563
- }
564
- return new UnexpectedError();
565
- };
566
- const version = (version2) => {
567
- return chalk__default.default.italic.yellow(`v${version2}`);
568
- };
569
- const versionRange = (range) => chalk__default.default.italic.yellow(range);
570
- const highlight = (arg) => chalk__default.default.bold.underline(arg);
571
- const upgradeStep = (text, step) => {
572
- return chalk__default.default.bold(`(${step[0]}/${step[1]}) ${text}...`);
573
- };
574
- const reports = (reports2) => {
575
- const rows = reports2.map(({ codemod, report }, i) => {
576
- const fIndex = chalk__default.default.grey(i);
577
- const fVersion = chalk__default.default.magenta(codemod.version);
578
- const fKind = chalk__default.default.yellow(codemod.kind);
579
- const fFormattedTransformPath = chalk__default.default.cyan(codemod.format());
580
- const fTimeElapsed = i === 0 ? `${report.timeElapsed}s ${chalk__default.default.dim.italic("(cold start)")}` : `${report.timeElapsed}s`;
581
- const fAffected = report.ok > 0 ? chalk__default.default.green(report.ok) : chalk__default.default.grey(0);
582
- const fUnchanged = report.ok === 0 ? chalk__default.default.red(report.nochange) : chalk__default.default.grey(report.nochange);
583
- return [fIndex, fVersion, fKind, fFormattedTransformPath, fAffected, fUnchanged, fTimeElapsed];
584
- });
585
- const table = new CliTable3__default.default({
586
- style: { compact: true },
587
- head: [
588
- chalk__default.default.bold.grey("N°"),
589
- chalk__default.default.bold.magenta("Version"),
590
- chalk__default.default.bold.yellow("Kind"),
591
- chalk__default.default.bold.cyan("Name"),
592
- chalk__default.default.bold.green("Affected"),
593
- chalk__default.default.bold.red("Unchanged"),
594
- chalk__default.default.bold.blue("Duration")
595
- ]
596
- });
597
- table.push(...rows);
598
- return table.toString();
599
- };
600
- const durationMs = (elapsedMs) => {
601
- const elapsedSeconds = (elapsedMs / ONE_SECOND_MS).toFixed(3);
602
- return `${elapsedSeconds}s`;
603
- };
604
- const CODEMOD_CODE_SUFFIX = "code";
605
- const CODEMOD_JSON_SUFFIX = "json";
606
- const CODEMOD_ALLOWED_SUFFIXES = [CODEMOD_CODE_SUFFIX, CODEMOD_JSON_SUFFIX];
607
- const CODEMOD_EXTENSION = "ts";
608
- const CODEMOD_FILE_REGEXP = new RegExp(
609
- `^.+[.](${CODEMOD_ALLOWED_SUFFIXES.join("|")})[.]${CODEMOD_EXTENSION}$`
610
- );
611
- class Codemod {
612
- kind;
613
- version;
614
- baseDirectory;
615
- filename;
616
- path;
617
- constructor(options) {
618
- this.kind = options.kind;
619
- this.version = options.version;
620
- this.baseDirectory = options.baseDirectory;
621
- this.filename = options.filename;
622
- this.path = path__default.default.join(this.baseDirectory, this.version.raw, this.filename);
623
- }
624
- format() {
625
- return this.filename.replace(`.${CODEMOD_CODE_SUFFIX}.${CODEMOD_EXTENSION}`, "").replace(`.${CODEMOD_JSON_SUFFIX}.${CODEMOD_EXTENSION}`, "").replaceAll("-", " ");
626
- }
627
- }
628
- const codemodFactory = (options) => new Codemod(options);
629
- class CodemodRepository {
630
- groups;
631
- versions;
632
- cwd;
633
- constructor(cwd) {
634
- assert__default.default(fse__default.default.existsSync(cwd), `Invalid codemods directory provided "${cwd}"`);
635
- this.cwd = cwd;
636
- this.groups = {};
637
- this.versions = [];
638
- }
639
- refresh() {
640
- this.refreshAvailableVersions();
641
- this.refreshAvailableFiles();
642
- return this;
643
- }
644
- count(version2) {
645
- return this.findByVersion(version2).length;
646
- }
647
- countRange(range) {
648
- return this.findByRange(range).length;
649
- }
650
- exists(version2) {
651
- return version2.raw in this.groups;
652
- }
653
- findByRange(range) {
654
- const entries = Object.entries(this.groups);
655
- return entries.filter(([version2]) => range.test(version2)).map(([version2, codemods]) => ({
656
- version: index.semVerFactory(version2),
657
- codemods
658
- }));
659
- }
660
- findByVersion(version2) {
661
- const literalVersion = version2.raw;
662
- const codemods = this.groups[literalVersion];
663
- return codemods ?? [];
664
- }
665
- findAll() {
666
- const entries = Object.entries(this.groups);
667
- return entries.map(([version2, codemods]) => ({
668
- version: index.semVerFactory(version2),
669
- codemods
670
- }));
671
- }
672
- refreshAvailableVersions() {
673
- this.versions = fse__default.default.readdirSync(this.cwd).filter((filename) => fse__default.default.statSync(path__default.default.join(this.cwd, filename)).isDirectory()).filter((filename) => semver__default.default.valid(filename) !== null).map((version2) => index.semVerFactory(version2)).sort(semver__default.default.compare);
674
- return this;
675
- }
676
- refreshAvailableFiles() {
677
- this.groups = {};
678
- for (const version2 of this.versions) {
679
- this.refreshAvailableFilesForVersion(version2);
680
- }
681
- }
682
- refreshAvailableFilesForVersion(version2) {
683
- const literalVersion = version2.raw;
684
- const versionDirectory = path__default.default.join(this.cwd, literalVersion);
685
- if (!fse__default.default.existsSync(versionDirectory)) {
686
- return;
687
- }
688
- this.groups[literalVersion] = fse__default.default.readdirSync(versionDirectory).filter((filename) => fse__default.default.statSync(path__default.default.join(versionDirectory, filename)).isFile()).filter((filename) => CODEMOD_FILE_REGEXP.test(filename)).map((filename) => {
689
- const kind = parseCodemodKindFromFilename(filename);
690
- const baseDirectory = this.cwd;
691
- return codemodFactory({ kind, baseDirectory, version: version2, filename });
692
- });
693
- }
694
- }
695
- const parseCodemodKindFromFilename = (filename) => {
696
- const kind = filename.split(".").at(-2);
697
- assert__default.default(kind !== void 0);
698
- assert__default.default(CODEMOD_ALLOWED_SUFFIXES.includes(kind));
699
- return kind;
700
- };
701
- const codemodRepositoryFactory = (cwd) => new CodemodRepository(cwd);
702
- const INTERNAL_CODEMODS_DIRECTORY = path__default.default.join(
703
- __dirname,
704
- "..",
705
- "..",
706
- "resources",
707
- "codemods"
708
- );
709
- class CodemodRunner {
710
- project;
711
- range;
712
- isDry;
713
- logger;
714
- selectCodemodsCallback;
715
- constructor(project, range) {
716
- this.project = project;
717
- this.range = range;
718
- this.isDry = false;
719
- this.logger = null;
720
- this.selectCodemodsCallback = null;
721
- }
722
- setRange(range) {
723
- this.range = range;
724
- return this;
725
- }
726
- setLogger(logger) {
727
- this.logger = logger;
728
- return this;
729
- }
730
- onSelectCodemods(callback) {
731
- this.selectCodemodsCallback = callback;
732
- return this;
733
- }
734
- dry(enabled = true) {
735
- this.isDry = enabled;
736
- return this;
737
- }
738
- async run(codemodsDirectory) {
739
- const repository = codemodRepositoryFactory(
740
- codemodsDirectory ?? INTERNAL_CODEMODS_DIRECTORY
741
- );
742
- repository.refresh();
743
- const allVersionedCodemods = this.range ? repository.findByRange(this.range) : repository.findAll();
744
- const versionedCodemods = this.selectCodemodsCallback ? await this.selectCodemodsCallback(allVersionedCodemods) : allVersionedCodemods;
745
- const hasCodemodsToRun = versionedCodemods.length > 0;
746
- if (!hasCodemodsToRun) {
747
- if (this.range) {
748
- this.logger?.debug(`Found no codemods to run for ${versionRange(this.range)}`);
749
- } else {
750
- this.logger?.debug(`Found no codemods to run`);
751
- }
752
- return successReport();
753
- }
754
- if (this.range) {
755
- this.logger?.debug(
756
- `Found codemods for ${highlight(versionedCodemods.length)} version(s) using ${this.range}`
757
- );
758
- } else {
759
- this.logger?.debug(`Found codemods for ${highlight(versionedCodemods.length)} version(s)`);
760
- }
761
- versionedCodemods.forEach(
762
- ({ version: version$1, codemods: codemods2 }) => this.logger?.debug(`- ${version(version$1)} (${codemods2.length})`)
763
- );
764
- const codemods = versionedCodemods.map(({ codemods: codemods2 }) => codemods2).flat();
765
- try {
766
- const reports$1 = await this.project.runCodemods(codemods, { dry: this.isDry });
767
- this.logger?.raw(reports(reports$1));
768
- } catch (e) {
769
- return erroredReport(unknownToError(e));
770
- }
771
- return successReport();
772
- }
773
- }
774
- const codemodRunnerFactory = (project, range) => {
775
- return new CodemodRunner(project, range);
776
- };
777
- const successReport = () => ({ success: true, error: null });
778
- const erroredReport = (error) => ({ success: false, error });
779
- exports.REQUIRE_GIT = REQUIRE_GIT;
780
- exports.SCOPED_STRAPI_PACKAGE_PREFIX = SCOPED_STRAPI_PACKAGE_PREFIX;
781
- exports.codemodRunnerFactory = codemodRunnerFactory;
782
- exports.createJSONTransformAPI = createJSONTransformAPI;
783
- exports.durationMs = durationMs;
784
- exports.handleError = handleError;
785
- exports.highlight = highlight;
786
- exports.isAppProject = isAppProject;
787
- exports.loggerFactory = loggerFactory;
788
- exports.projectFactory = projectFactory;
789
- exports.rangeFactory = rangeFactory;
790
- exports.rangeFromVersions = rangeFromVersions;
791
- exports.requirementFactory = requirementFactory;
792
- exports.saveJSON = saveJSON;
793
- exports.timerFactory = timerFactory;
794
- exports.unknownToError = unknownToError;
795
- exports.upgradeStep = upgradeStep;
796
- exports.version = version;
797
- exports.versionRange = versionRange;
798
- //# sourceMappingURL=codemod-runner-aVWS9EOj.js.map