@strapi/upgrade 0.0.0-experimental.d362bf200f5f9359a4bbd4a549603de5ee1f04ca → 0.0.0-experimental.d834c9e658d1fb037e6da1105150593521c667cc

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 (68) hide show
  1. package/LICENSE +19 -4
  2. package/dist/cli.js +1456 -5
  3. package/dist/cli.js.map +1 -1
  4. package/dist/index.js +234 -94
  5. package/dist/index.js.map +1 -1
  6. package/dist/index.mjs +235 -95
  7. package/dist/index.mjs.map +1 -1
  8. package/dist/modules/codemod/codemod.d.ts +4 -2
  9. package/dist/modules/codemod/codemod.d.ts.map +1 -1
  10. package/dist/modules/codemod/types.d.ts +8 -1
  11. package/dist/modules/codemod/types.d.ts.map +1 -1
  12. package/dist/modules/codemod-repository/constants.d.ts.map +1 -1
  13. package/dist/modules/codemod-repository/repository.d.ts +5 -5
  14. package/dist/modules/codemod-repository/repository.d.ts.map +1 -1
  15. package/dist/modules/codemod-repository/types.d.ts +7 -3
  16. package/dist/modules/codemod-repository/types.d.ts.map +1 -1
  17. package/dist/modules/codemod-runner/codemod-runner.d.ts +6 -3
  18. package/dist/modules/codemod-runner/codemod-runner.d.ts.map +1 -1
  19. package/dist/modules/codemod-runner/index.d.ts +1 -0
  20. package/dist/modules/codemod-runner/index.d.ts.map +1 -1
  21. package/dist/modules/codemod-runner/types.d.ts +1 -0
  22. package/dist/modules/codemod-runner/types.d.ts.map +1 -1
  23. package/dist/modules/format/formats.d.ts +5 -0
  24. package/dist/modules/format/formats.d.ts.map +1 -1
  25. package/dist/modules/project/constants.d.ts.map +1 -1
  26. package/dist/modules/project/project.d.ts +1 -1
  27. package/dist/modules/project/project.d.ts.map +1 -1
  28. package/dist/modules/project/types.d.ts +1 -0
  29. package/dist/modules/project/types.d.ts.map +1 -1
  30. package/dist/modules/project/utils.d.ts +1 -1
  31. package/dist/modules/project/utils.d.ts.map +1 -1
  32. package/dist/modules/report/report.d.ts.map +1 -1
  33. package/dist/modules/runner/json/transform.d.ts.map +1 -1
  34. package/dist/modules/upgrader/upgrader.d.ts.map +1 -1
  35. package/dist/modules/version/range.d.ts +2 -0
  36. package/dist/modules/version/range.d.ts.map +1 -1
  37. package/dist/tasks/codemods/index.d.ts +2 -1
  38. package/dist/tasks/codemods/index.d.ts.map +1 -1
  39. package/dist/tasks/codemods/list-codemods.d.ts +3 -0
  40. package/dist/tasks/codemods/list-codemods.d.ts.map +1 -0
  41. package/dist/tasks/codemods/run-codemods.d.ts +3 -0
  42. package/dist/tasks/codemods/run-codemods.d.ts.map +1 -0
  43. package/dist/tasks/codemods/types.d.ts +9 -3
  44. package/dist/tasks/codemods/types.d.ts.map +1 -1
  45. package/dist/tasks/codemods/utils.d.ts +6 -0
  46. package/dist/tasks/codemods/utils.d.ts.map +1 -0
  47. package/dist/tasks/index.d.ts +1 -1
  48. package/dist/tasks/index.d.ts.map +1 -1
  49. package/package.json +9 -8
  50. package/resources/codemods/5.0.0/change-useAPIErrorHandler-import.code.ts +21 -0
  51. package/resources/codemods/5.0.0/comment-out-lifecycle-files.code.ts +63 -0
  52. package/resources/codemods/5.0.0/dependency-upgrade-react-and-react-dom.json.ts +67 -0
  53. package/resources/codemods/5.0.0/dependency-upgrade-styled-components.json.ts +49 -0
  54. package/resources/codemods/5.0.0/entity-service-document-service.code.ts +437 -0
  55. package/resources/codemods/5.0.0/strapi-public-interface.code.ts +126 -0
  56. package/resources/codemods/5.0.0/useRBAC-hook-import-change.code.ts +21 -0
  57. package/resources/codemods/5.0.0/utils-public-interface.code.ts +320 -0
  58. package/resources/utils/change-import.ts +96 -0
  59. package/dist/_chunks/codemod-runner-mXNzVpHm.js +0 -798
  60. package/dist/_chunks/codemod-runner-mXNzVpHm.js.map +0 -1
  61. package/dist/_chunks/codemods-S4mNX9Qg.js +0 -105
  62. package/dist/_chunks/codemods-S4mNX9Qg.js.map +0 -1
  63. package/dist/_chunks/index-Pt-TU9MN.js +0 -103
  64. package/dist/_chunks/index-Pt-TU9MN.js.map +0 -1
  65. package/dist/_chunks/upgrade-aWNYibWB.js +0 -361
  66. package/dist/_chunks/upgrade-aWNYibWB.js.map +0 -1
  67. package/dist/tasks/codemods/codemods.d.ts +0 -3
  68. package/dist/tasks/codemods/codemods.d.ts.map +0 -1
package/dist/index.mjs CHANGED
@@ -3,7 +3,7 @@ import simpleGit from "simple-git";
3
3
  import chalk from "chalk";
4
4
  import semver from "semver";
5
5
  import { packageManager } from "@strapi/utils";
6
- import { cloneDeep, get, has, merge, set, omit, isEqual } from "lodash/fp";
6
+ import { cloneDeep, get, has, merge, set, omit, isEqual, groupBy, size } from "lodash/fp";
7
7
  import fse from "fs-extra";
8
8
  import assert from "node:assert";
9
9
  import { glob } from "glob";
@@ -253,13 +253,19 @@ const rangeFromVersions = (currentVersion, target) => {
253
253
  }
254
254
  throw new Error(`Invalid target set: ${target}`);
255
255
  };
256
+ const isValidStringifiedRange = (str) => semver.validRange(str) !== null;
257
+ const isRangeInstance = (range) => {
258
+ return range instanceof semver.Range;
259
+ };
256
260
  const index$e = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
257
261
  __proto__: null,
258
262
  Version: types,
259
263
  isLiteralSemVer,
264
+ isRangeInstance,
260
265
  isSemVerReleaseType,
261
266
  isSemverInstance,
262
267
  isValidSemVer,
268
+ isValidStringifiedRange,
263
269
  rangeFactory,
264
270
  rangeFromReleaseType,
265
271
  rangeFromVersions,
@@ -320,7 +326,11 @@ const transformJSON = async (codemodPath, paths, config) => {
320
326
  timeElapsed: "",
321
327
  stats: {}
322
328
  };
323
- const esbuildOptions = { extensions: [".js", ".mjs", ".ts"] };
329
+ const esbuildOptions = {
330
+ extensions: [".js", ".mjs", ".ts"],
331
+ hookIgnoreNodeModules: false,
332
+ hookMatcher: isEqual(codemodPath)
333
+ };
324
334
  const { unregister } = register(esbuildOptions);
325
335
  const module = require(codemodPath);
326
336
  unregister();
@@ -365,7 +375,7 @@ const index$b = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePrope
365
375
  jsonRunnerFactory
366
376
  }, Symbol.toStringTag, { value: "Module" }));
367
377
  const PROJECT_PACKAGE_JSON = "package.json";
368
- const PROJECT_DEFAULT_ALLOWED_ROOT_PATHS = ["src", "config", "public"];
378
+ const PROJECT_DEFAULT_ALLOWED_ROOT_PATHS = ["src", "config", "public", "admin", "server"];
369
379
  const PROJECT_DEFAULT_CODE_EXTENSIONS = [
370
380
  // Source files
371
381
  "js",
@@ -418,10 +428,10 @@ class Project {
418
428
  this.refreshProjectFiles();
419
429
  return this;
420
430
  }
421
- async runCodemods(codemods2, options) {
431
+ async runCodemods(codemods, options) {
422
432
  const runners = this.createProjectCodemodsRunners(options.dry);
423
433
  const reports2 = [];
424
- for (const codemod of codemods2) {
434
+ for (const codemod of codemods) {
425
435
  for (const runner of runners) {
426
436
  if (runner.valid(codemod)) {
427
437
  const report = await runner.run(codemod);
@@ -480,7 +490,7 @@ class Project {
480
490
  }
481
491
  class AppProject extends Project {
482
492
  strapiVersion;
483
- type = "app";
493
+ type = "application";
484
494
  constructor(cwd) {
485
495
  super(cwd);
486
496
  this.refreshStrapiVersion();
@@ -564,12 +574,12 @@ function assertPluginProject(project) {
564
574
  throw new Error("Project is not a plugin");
565
575
  }
566
576
  }
567
- const isAppProject = (project) => {
577
+ const isApplicationProject = (project) => {
568
578
  return project instanceof AppProject;
569
579
  };
570
580
  function assertAppProject(project) {
571
- if (!isAppProject(project)) {
572
- throw new Error("Project is not an app");
581
+ if (!isApplicationProject(project)) {
582
+ throw new Error("Project is not an application");
573
583
  }
574
584
  }
575
585
  const index$a = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
@@ -577,7 +587,7 @@ const index$a = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePrope
577
587
  assertAppProject,
578
588
  assertPluginProject,
579
589
  constants: constants$3,
580
- isAppProject,
590
+ isApplicationProject,
581
591
  isPluginProject,
582
592
  projectFactory
583
593
  }, Symbol.toStringTag, { value: "Module" }));
@@ -604,7 +614,11 @@ const path = (path2) => chalk.blue(path2);
604
614
  const version = (version2) => {
605
615
  return chalk.italic.yellow(`v${version2}`);
606
616
  };
607
- const versionRange = (range) => chalk.italic.yellow(range);
617
+ const codemodUID = (uid) => {
618
+ return chalk.bold.cyan(uid);
619
+ };
620
+ const projectType = (type) => chalk.cyan(type);
621
+ const versionRange = (range) => chalk.italic.yellow(range.raw);
608
622
  const transform = (transformFilePath) => chalk.cyan(transformFilePath);
609
623
  const highlight = (arg) => chalk.bold.underline(arg);
610
624
  const upgradeStep = (text, step) => {
@@ -636,15 +650,40 @@ const reports = (reports2) => {
636
650
  table.push(...rows);
637
651
  return table.toString();
638
652
  };
653
+ const codemodList = (codemods) => {
654
+ const rows = codemods.map((codemod, index2) => {
655
+ const fIndex = chalk.grey(index2);
656
+ const fVersion = chalk.magenta(codemod.version);
657
+ const fKind = chalk.yellow(codemod.kind);
658
+ const fName = chalk.blue(codemod.format());
659
+ const fUID = codemodUID(codemod.uid);
660
+ return [fIndex, fVersion, fKind, fName, fUID];
661
+ });
662
+ const table = new CliTable3({
663
+ style: { compact: true },
664
+ head: [
665
+ chalk.bold.grey("N°"),
666
+ chalk.bold.magenta("Version"),
667
+ chalk.bold.yellow("Kind"),
668
+ chalk.bold.blue("Name"),
669
+ chalk.bold.cyan("UID")
670
+ ]
671
+ });
672
+ table.push(...rows);
673
+ return table.toString();
674
+ };
639
675
  const durationMs = (elapsedMs) => {
640
676
  const elapsedSeconds = (elapsedMs / ONE_SECOND_MS).toFixed(3);
641
677
  return `${elapsedSeconds}s`;
642
678
  };
643
679
  const index$8 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
644
680
  __proto__: null,
681
+ codemodList,
682
+ codemodUID,
645
683
  durationMs,
646
684
  highlight,
647
685
  path,
686
+ projectType,
648
687
  reports,
649
688
  transform,
650
689
  upgradeStep,
@@ -667,6 +706,7 @@ const constants$2 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineP
667
706
  CODEMOD_JSON_SUFFIX
668
707
  }, Symbol.toStringTag, { value: "Module" }));
669
708
  class Codemod {
709
+ uid;
670
710
  kind;
671
711
  version;
672
712
  baseDirectory;
@@ -678,9 +718,27 @@ class Codemod {
678
718
  this.baseDirectory = options.baseDirectory;
679
719
  this.filename = options.filename;
680
720
  this.path = path$1.join(this.baseDirectory, this.version.raw, this.filename);
681
- }
682
- format() {
683
- return this.filename.replace(`.${CODEMOD_CODE_SUFFIX}.${CODEMOD_EXTENSION}`, "").replace(`.${CODEMOD_JSON_SUFFIX}.${CODEMOD_EXTENSION}`, "").replaceAll("-", " ");
721
+ this.uid = this.createUID();
722
+ }
723
+ createUID() {
724
+ const name = this.format({ stripExtension: true, stripKind: true, stripHyphens: false });
725
+ const kind = this.kind;
726
+ const version2 = this.version.raw;
727
+ return `${version2}-${name}-${kind}`;
728
+ }
729
+ format(options) {
730
+ const { stripExtension = true, stripKind = true, stripHyphens = true } = options ?? {};
731
+ let formatted = this.filename;
732
+ if (stripExtension) {
733
+ formatted = formatted.replace(new RegExp(`\\.${CODEMOD_EXTENSION}$`, "i"), "");
734
+ }
735
+ if (stripKind) {
736
+ formatted = formatted.replace(`.${CODEMOD_CODE_SUFFIX}`, "").replace(`.${CODEMOD_JSON_SUFFIX}`, "");
737
+ }
738
+ if (stripHyphens) {
739
+ formatted = formatted.replaceAll("-", " ");
740
+ }
741
+ return formatted;
684
742
  }
685
743
  }
686
744
  const codemodFactory = (options) => new Codemod(options);
@@ -689,6 +747,20 @@ const index$7 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePrope
689
747
  codemodFactory,
690
748
  constants: constants$2
691
749
  }, Symbol.toStringTag, { value: "Module" }));
750
+ const INTERNAL_CODEMODS_DIRECTORY = path$1.join(
751
+ __dirname,
752
+ // upgrade/dist
753
+ "..",
754
+ // upgrade
755
+ "resources",
756
+ // upgrade/resources
757
+ "codemods"
758
+ // upgrade/resources/codemods
759
+ );
760
+ const constants$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
761
+ __proto__: null,
762
+ INTERNAL_CODEMODS_DIRECTORY
763
+ }, Symbol.toStringTag, { value: "Module" }));
692
764
  class CodemodRepository {
693
765
  groups;
694
766
  versions;
@@ -707,29 +779,47 @@ class CodemodRepository {
707
779
  count(version2) {
708
780
  return this.findByVersion(version2).length;
709
781
  }
710
- countRange(range) {
711
- return this.findByRange(range).length;
712
- }
713
- exists(version2) {
782
+ versionExists(version2) {
714
783
  return version2.raw in this.groups;
715
784
  }
716
- findByRange(range) {
785
+ has(uid) {
786
+ const result = this.find({ uids: [uid] });
787
+ if (result.length !== 1) {
788
+ return false;
789
+ }
790
+ const { codemods } = result[0];
791
+ return codemods.length === 1 && codemods[0].uid === uid;
792
+ }
793
+ find(q) {
717
794
  const entries = Object.entries(this.groups);
718
- return entries.filter(([version2]) => range.test(version2)).map(([version2, codemods2]) => ({
795
+ return entries.filter(maybeFilterByRange).map(([version2, codemods]) => ({
719
796
  version: semVerFactory(version2),
720
- codemods: codemods2
721
- }));
797
+ // Filter by UID if provided in the query
798
+ codemods: codemods.filter(maybeFilterByUIDs)
799
+ })).filter(({ codemods }) => codemods.length > 0);
800
+ function maybeFilterByRange([version2]) {
801
+ if (!isRangeInstance(q.range)) {
802
+ return true;
803
+ }
804
+ return q.range.test(version2);
805
+ }
806
+ function maybeFilterByUIDs(codemod) {
807
+ if (q.uids === void 0) {
808
+ return true;
809
+ }
810
+ return q.uids.includes(codemod.uid);
811
+ }
722
812
  }
723
813
  findByVersion(version2) {
724
814
  const literalVersion = version2.raw;
725
- const codemods2 = this.groups[literalVersion];
726
- return codemods2 ?? [];
815
+ const codemods = this.groups[literalVersion];
816
+ return codemods ?? [];
727
817
  }
728
818
  findAll() {
729
819
  const entries = Object.entries(this.groups);
730
- return entries.map(([version2, codemods2]) => ({
820
+ return entries.map(([version2, codemods]) => ({
731
821
  version: semVerFactory(version2),
732
- codemods: codemods2
822
+ codemods
733
823
  }));
734
824
  }
735
825
  refreshAvailableVersions() {
@@ -761,18 +851,9 @@ const parseCodemodKindFromFilename = (filename) => {
761
851
  assert(CODEMOD_ALLOWED_SUFFIXES.includes(kind));
762
852
  return kind;
763
853
  };
764
- const codemodRepositoryFactory = (cwd) => new CodemodRepository(cwd);
765
- const INTERNAL_CODEMODS_DIRECTORY = path$1.join(
766
- __dirname,
767
- "..",
768
- "..",
769
- "resources",
770
- "codemods"
771
- );
772
- const constants$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
773
- __proto__: null,
774
- INTERNAL_CODEMODS_DIRECTORY
775
- }, Symbol.toStringTag, { value: "Module" }));
854
+ const codemodRepositoryFactory = (cwd = INTERNAL_CODEMODS_DIRECTORY) => {
855
+ return new CodemodRepository(cwd);
856
+ };
776
857
  const index$6 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
777
858
  __proto__: null,
778
859
  codemodRepositoryFactory,
@@ -807,40 +888,59 @@ class CodemodRunner {
807
888
  this.isDry = enabled;
808
889
  return this;
809
890
  }
810
- async run(codemodsDirectory) {
891
+ createRepository(codemodsDirectory) {
811
892
  const repository = codemodRepositoryFactory(
812
893
  codemodsDirectory ?? INTERNAL_CODEMODS_DIRECTORY
813
894
  );
814
895
  repository.refresh();
815
- const allVersionedCodemods = this.range ? repository.findByRange(this.range) : repository.findAll();
816
- const versionedCodemods = this.selectCodemodsCallback ? await this.selectCodemodsCallback(allVersionedCodemods) : allVersionedCodemods;
817
- const hasCodemodsToRun = versionedCodemods.length > 0;
818
- if (!hasCodemodsToRun) {
819
- if (this.range) {
820
- this.logger?.debug(`Found no codemods to run for ${versionRange(this.range)}`);
821
- } else {
822
- this.logger?.debug(`Found no codemods to run`);
823
- }
824
- return successReport$1();
825
- }
826
- if (this.range) {
827
- this.logger?.debug(
828
- `Found codemods for ${highlight(versionedCodemods.length)} version(s) using ${this.range}`
896
+ return repository;
897
+ }
898
+ async safeRunAndReport(codemods) {
899
+ if (this.isDry) {
900
+ this.logger?.warn?.(
901
+ "Running the codemods in dry mode. No files will be modified during the process."
829
902
  );
830
- } else {
831
- this.logger?.debug(`Found codemods for ${highlight(versionedCodemods.length)} version(s)`);
832
903
  }
833
- versionedCodemods.forEach(
834
- ({ version: version$1, codemods: codemods22 }) => this.logger?.debug(`- ${version(version$1)} (${codemods22.length})`)
835
- );
836
- const codemods2 = versionedCodemods.map(({ codemods: codemods22 }) => codemods22).flat();
837
904
  try {
838
- const reports$1 = await this.project.runCodemods(codemods2, { dry: this.isDry });
839
- this.logger?.raw(reports(reports$1));
905
+ const reports$1 = await this.project.runCodemods(codemods, { dry: this.isDry });
906
+ this.logger?.raw?.(reports(reports$1));
907
+ if (!this.isDry) {
908
+ const nbAffectedTotal = reports$1.flatMap((report) => report.report.ok).reduce((acc, nb) => acc + nb, 0);
909
+ this.logger?.debug?.(
910
+ `Successfully ran ${highlight(codemods.length)} codemod(s), ${highlight(nbAffectedTotal)} change(s) have been detected`
911
+ );
912
+ }
913
+ return successReport$1();
840
914
  } catch (e) {
841
915
  return erroredReport$1(unknownToError(e));
842
916
  }
843
- return successReport$1();
917
+ }
918
+ async runByUID(uid, codemodsDirectory) {
919
+ const repository = this.createRepository(codemodsDirectory);
920
+ if (!repository.has(uid)) {
921
+ throw new Error(`Unknown codemod UID provided: ${uid}`);
922
+ }
923
+ const codemods = repository.find({ uids: [uid] }).flatMap(({ codemods: codemods2 }) => codemods2);
924
+ return this.safeRunAndReport(codemods);
925
+ }
926
+ async run(codemodsDirectory) {
927
+ const repository = this.createRepository(codemodsDirectory);
928
+ const codemodsInRange = repository.find({ range: this.range });
929
+ const selectedCodemods = this.selectCodemodsCallback ? await this.selectCodemodsCallback(codemodsInRange) : codemodsInRange;
930
+ if (selectedCodemods.length === 0) {
931
+ this.logger?.debug?.(`Found no codemods to run for ${versionRange(this.range)}`);
932
+ return successReport$1();
933
+ }
934
+ const codemods = selectedCodemods.flatMap(({ codemods: codemods2 }) => codemods2);
935
+ const codemodsByVersion = groupBy("version", codemods);
936
+ const fRange = versionRange(this.range);
937
+ this.logger?.debug?.(
938
+ `Found ${highlight(codemods.length)} codemods for ${highlight(size(codemodsByVersion))} version(s) using ${fRange}`
939
+ );
940
+ for (const [version$1, codemods2] of Object.entries(codemodsByVersion)) {
941
+ this.logger?.debug?.(`- ${version(semVerFactory(version$1))} (${codemods2.length})`);
942
+ }
943
+ return this.safeRunAndReport(codemods);
844
944
  }
845
945
  }
846
946
  const codemodRunnerFactory = (project, range) => {
@@ -879,7 +979,7 @@ class Upgrader {
879
979
  this.codemodsTarget = semVerFactory(
880
980
  `${this.target.major}.${this.target.minor}.${this.target.patch}`
881
981
  );
882
- this.logger?.debug(
982
+ this.logger?.debug?.(
883
983
  `The codemods target has been synced with the upgrade target. The codemod runner will now look for ${version(
884
984
  this.codemodsTarget
885
985
  )}`
@@ -888,7 +988,7 @@ class Upgrader {
888
988
  }
889
989
  overrideCodemodsTarget(target) {
890
990
  this.codemodsTarget = target;
891
- this.logger?.debug(
991
+ this.logger?.debug?.(
892
992
  `Overriding the codemods target. The codemod runner will now look for ${version(target)}`
893
993
  );
894
994
  return this;
@@ -908,40 +1008,40 @@ class Upgrader {
908
1008
  addRequirement(requirement) {
909
1009
  this.requirements.push(requirement);
910
1010
  const fRequired = requirement.isRequired ? "(required)" : "(optional)";
911
- this.logger?.debug(
1011
+ this.logger?.debug?.(
912
1012
  `Added a new requirement to the upgrade: ${highlight(requirement.name)} ${fRequired}`
913
1013
  );
914
1014
  return this;
915
1015
  }
916
1016
  async upgrade() {
917
- this.logger?.info(
1017
+ this.logger?.info?.(
918
1018
  `Upgrading from ${version(this.project.strapiVersion)} to ${version(this.target)}`
919
1019
  );
920
1020
  if (this.isDry) {
921
- this.logger?.warn(
1021
+ this.logger?.warn?.(
922
1022
  "Running the upgrade in dry mode. No files will be modified during the process."
923
1023
  );
924
1024
  }
925
1025
  const range = rangeFromVersions(this.project.strapiVersion, this.target);
926
1026
  const codemodsRange = rangeFromVersions(this.project.strapiVersion, this.codemodsTarget);
927
1027
  const npmVersionsMatches = this.npmPackage?.findVersionsInRange(range) ?? [];
928
- this.logger?.debug(
1028
+ this.logger?.debug?.(
929
1029
  `Found ${highlight(npmVersionsMatches.length)} versions satisfying ${versionRange(range)}`
930
1030
  );
931
1031
  try {
932
- this.logger?.info(upgradeStep("Checking requirement", [1, 4]));
1032
+ this.logger?.info?.(upgradeStep("Checking requirement", [1, 4]));
933
1033
  await this.checkRequirements(this.requirements, {
934
1034
  npmVersionsMatches,
935
1035
  project: this.project,
936
1036
  target: this.target
937
1037
  });
938
- this.logger?.info(upgradeStep("Applying the latest code modifications", [2, 4]));
1038
+ this.logger?.info?.(upgradeStep("Applying the latest code modifications", [2, 4]));
939
1039
  await this.runCodemods(codemodsRange);
940
- this.logger?.debug("Refreshing project information...");
1040
+ this.logger?.debug?.("Refreshing project information...");
941
1041
  this.project.refresh();
942
- this.logger?.info(upgradeStep("Upgrading Strapi dependencies", [3, 4]));
1042
+ this.logger?.info?.(upgradeStep("Upgrading Strapi dependencies", [3, 4]));
943
1043
  await this.updateDependencies();
944
- this.logger?.info(upgradeStep("Installing dependencies", [4, 4]));
1044
+ this.logger?.info?.(upgradeStep("Installing dependencies", [4, 4]));
945
1045
  await this.installDependencies();
946
1046
  } catch (e) {
947
1047
  return erroredReport(unknownToError(e));
@@ -974,7 +1074,7 @@ class Upgrader {
974
1074
  if (requirement.isRequired) {
975
1075
  throw error;
976
1076
  }
977
- this.logger?.warn(warningMessage);
1077
+ this.logger?.warn?.(warningMessage);
978
1078
  const response = await this.confirmationCallback?.(confirmationMessage);
979
1079
  if (!response) {
980
1080
  throw error;
@@ -985,9 +1085,11 @@ class Upgrader {
985
1085
  const json = createJSONTransformAPI(packageJSON);
986
1086
  const dependencies = json.get("dependencies", {});
987
1087
  const strapiDependencies = this.getScopedStrapiDependencies(dependencies);
988
- this.logger?.debug(`Found ${highlight(strapiDependencies.length)} dependency(ies) to update`);
1088
+ this.logger?.debug?.(
1089
+ `Found ${highlight(strapiDependencies.length)} dependency(ies) to update`
1090
+ );
989
1091
  strapiDependencies.forEach(
990
- (dependency) => this.logger?.debug(`- ${dependency[0]} (${dependency[1]} -> ${this.target})`)
1092
+ (dependency) => this.logger?.debug?.(`- ${dependency[0]} (${dependency[1]} -> ${this.target})`)
991
1093
  );
992
1094
  if (strapiDependencies.length === 0) {
993
1095
  return;
@@ -995,7 +1097,7 @@ class Upgrader {
995
1097
  strapiDependencies.forEach(([name]) => json.set(`dependencies.${name}`, this.target.raw));
996
1098
  const updatedPackageJSON = json.root();
997
1099
  if (this.isDry) {
998
- this.logger?.debug(`Skipping dependencies update (${chalk.italic("dry mode")})`);
1100
+ this.logger?.debug?.(`Skipping dependencies update (${chalk.italic("dry mode")})`);
999
1101
  return;
1000
1102
  }
1001
1103
  await saveJSON(packageJSONPath, updatedPackageJSON);
@@ -1015,9 +1117,9 @@ class Upgrader {
1015
1117
  async installDependencies() {
1016
1118
  const projectPath = this.project.cwd;
1017
1119
  const packageManagerName = await packageManager.getPreferred(projectPath);
1018
- this.logger?.debug(`Using ${highlight(packageManagerName)} as package manager`);
1120
+ this.logger?.debug?.(`Using ${highlight(packageManagerName)} as package manager`);
1019
1121
  if (this.isDry) {
1020
- this.logger?.debug(`Skipping dependencies installation (${chalk.italic("dry mode")}`);
1122
+ this.logger?.debug?.(`Skipping dependencies installation (${chalk.italic("dry mode")}`);
1021
1123
  return;
1022
1124
  }
1023
1125
  await packageManager.installDependencies(projectPath, packageManagerName, {
@@ -1116,7 +1218,7 @@ const upgrade = async (options) => {
1116
1218
  const { logger, codemodsTarget } = options;
1117
1219
  const cwd = path$1.resolve(options.cwd ?? process.cwd());
1118
1220
  const project = projectFactory(cwd);
1119
- if (!isAppProject(project)) {
1221
+ if (!isApplicationProject(project)) {
1120
1222
  throw new Error(
1121
1223
  `The "${options.target}" upgrade can only be run on a Strapi project; for plugins, please use "codemods".`
1122
1224
  );
@@ -1138,20 +1240,7 @@ const upgrade = async (options) => {
1138
1240
  timer.stop();
1139
1241
  logger.info(`Completed in ${durationMs(timer.elapsedMs)}`);
1140
1242
  };
1141
- const codemods = async (options) => {
1142
- const timer = timerFactory();
1143
- const { logger } = options;
1144
- const cwd = path$1.resolve(options.cwd ?? process.cwd());
1145
- const project = projectFactory(cwd);
1146
- const range = isAppProject(project) ? getRangeFromTarget(project.strapiVersion, options.target) : void 0;
1147
- const codemodRunner = codemodRunnerFactory(project, range).dry(options.dry ?? false).onSelectCodemods(options.selectCodemods ?? null).setLogger(logger);
1148
- const executionReport = await codemodRunner.run();
1149
- if (!executionReport.success) {
1150
- throw executionReport.error;
1151
- }
1152
- timer.stop();
1153
- logger.info(`Completed in ${timer.elapsedMs}`);
1154
- };
1243
+ const resolvePath = (cwd) => path$1.resolve(cwd ?? process.cwd());
1155
1244
  const getRangeFromTarget = (currentVersion, target) => {
1156
1245
  if (isSemverInstance(target)) {
1157
1246
  return rangeFactory(target);
@@ -1168,9 +1257,60 @@ const getRangeFromTarget = (currentVersion, target) => {
1168
1257
  throw new Error(`Invalid target set: ${target}`);
1169
1258
  }
1170
1259
  };
1260
+ const findRangeFromTarget = (project, target) => {
1261
+ if (isRangeInstance(target)) {
1262
+ return target;
1263
+ }
1264
+ if (isApplicationProject(project)) {
1265
+ return getRangeFromTarget(project.strapiVersion, target);
1266
+ }
1267
+ return rangeFactory("*");
1268
+ };
1269
+ const runCodemods = async (options) => {
1270
+ const timer = timerFactory();
1271
+ const { logger, uid } = options;
1272
+ const cwd = resolvePath(options.cwd);
1273
+ const project = projectFactory(cwd);
1274
+ const range = findRangeFromTarget(project, options.target);
1275
+ logger.debug(`Project: ${projectType(project.type)} found in ${path(cwd)}`);
1276
+ logger.debug(`Range: set to ${versionRange(range)}`);
1277
+ const codemodRunner = codemodRunnerFactory(project, range).dry(options.dry ?? false).onSelectCodemods(options.selectCodemods ?? null).setLogger(logger);
1278
+ let report;
1279
+ if (uid !== void 0) {
1280
+ logger.debug(`Running a single codemod: ${codemodUID(uid)}`);
1281
+ report = await codemodRunner.runByUID(uid);
1282
+ } else {
1283
+ report = await codemodRunner.run();
1284
+ }
1285
+ if (!report.success) {
1286
+ throw report.error;
1287
+ }
1288
+ timer.stop();
1289
+ logger.info(`Completed in ${timer.elapsedMs}`);
1290
+ };
1291
+ const listCodemods = async (options) => {
1292
+ const { logger, target } = options;
1293
+ const cwd = resolvePath(options.cwd);
1294
+ const project = projectFactory(cwd);
1295
+ const range = findRangeFromTarget(project, target);
1296
+ logger.debug(`Project: ${projectType(project.type)} found in ${path(cwd)}`);
1297
+ logger.debug(`Range: set to ${versionRange(range)}`);
1298
+ const repo = codemodRepositoryFactory();
1299
+ repo.refresh();
1300
+ const groups = repo.find({ range });
1301
+ const codemods = groups.flatMap((collection) => collection.codemods);
1302
+ logger.debug(`Found ${highlight(codemods.length)} codemods`);
1303
+ if (codemods.length === 0) {
1304
+ logger.info(`Found no codemods matching ${versionRange(range)}`);
1305
+ return;
1306
+ }
1307
+ const fCodemods = codemodList(codemods);
1308
+ logger.raw(fCodemods);
1309
+ };
1171
1310
  const index$4 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
1172
1311
  __proto__: null,
1173
- codemods,
1312
+ listCodemods,
1313
+ runCodemods,
1174
1314
  upgrade
1175
1315
  }, Symbol.toStringTag, { value: "Module" }));
1176
1316
  class Logger {