@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
package/dist/index.js CHANGED
@@ -263,13 +263,19 @@ const rangeFromVersions = (currentVersion, target) => {
263
263
  }
264
264
  throw new Error(`Invalid target set: ${target}`);
265
265
  };
266
+ const isValidStringifiedRange = (str) => semver__default.default.validRange(str) !== null;
267
+ const isRangeInstance = (range) => {
268
+ return range instanceof semver__default.default.Range;
269
+ };
266
270
  const index$e = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
267
271
  __proto__: null,
268
272
  Version: types,
269
273
  isLiteralSemVer,
274
+ isRangeInstance,
270
275
  isSemVerReleaseType,
271
276
  isSemverInstance,
272
277
  isValidSemVer,
278
+ isValidStringifiedRange,
273
279
  rangeFactory,
274
280
  rangeFromReleaseType,
275
281
  rangeFromVersions,
@@ -428,10 +434,10 @@ class Project {
428
434
  this.refreshProjectFiles();
429
435
  return this;
430
436
  }
431
- async runCodemods(codemods2, options) {
437
+ async runCodemods(codemods, options) {
432
438
  const runners = this.createProjectCodemodsRunners(options.dry);
433
439
  const reports2 = [];
434
- for (const codemod of codemods2) {
440
+ for (const codemod of codemods) {
435
441
  for (const runner of runners) {
436
442
  if (runner.valid(codemod)) {
437
443
  const report = await runner.run(codemod);
@@ -490,7 +496,7 @@ class Project {
490
496
  }
491
497
  class AppProject extends Project {
492
498
  strapiVersion;
493
- type = "app";
499
+ type = "application";
494
500
  constructor(cwd) {
495
501
  super(cwd);
496
502
  this.refreshStrapiVersion();
@@ -574,12 +580,12 @@ function assertPluginProject(project) {
574
580
  throw new Error("Project is not a plugin");
575
581
  }
576
582
  }
577
- const isAppProject = (project) => {
583
+ const isApplicationProject = (project) => {
578
584
  return project instanceof AppProject;
579
585
  };
580
586
  function assertAppProject(project) {
581
- if (!isAppProject(project)) {
582
- throw new Error("Project is not an app");
587
+ if (!isApplicationProject(project)) {
588
+ throw new Error("Project is not an application");
583
589
  }
584
590
  }
585
591
  const index$a = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
@@ -587,7 +593,7 @@ const index$a = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePrope
587
593
  assertAppProject,
588
594
  assertPluginProject,
589
595
  constants: constants$3,
590
- isAppProject,
596
+ isApplicationProject,
591
597
  isPluginProject,
592
598
  projectFactory
593
599
  }, Symbol.toStringTag, { value: "Module" }));
@@ -614,7 +620,11 @@ const path = (path2) => chalk__default.default.blue(path2);
614
620
  const version = (version2) => {
615
621
  return chalk__default.default.italic.yellow(`v${version2}`);
616
622
  };
617
- const versionRange = (range) => chalk__default.default.italic.yellow(range);
623
+ const codemodUID = (uid) => {
624
+ return chalk__default.default.bold.cyan(uid);
625
+ };
626
+ const projectType = (type) => chalk__default.default.cyan(type);
627
+ const versionRange = (range) => chalk__default.default.italic.yellow(range.raw);
618
628
  const transform = (transformFilePath) => chalk__default.default.cyan(transformFilePath);
619
629
  const highlight = (arg) => chalk__default.default.bold.underline(arg);
620
630
  const upgradeStep = (text, step) => {
@@ -646,15 +656,40 @@ const reports = (reports2) => {
646
656
  table.push(...rows);
647
657
  return table.toString();
648
658
  };
659
+ const codemodList = (codemods) => {
660
+ const rows = codemods.map((codemod, index2) => {
661
+ const fIndex = chalk__default.default.grey(index2);
662
+ const fVersion = chalk__default.default.magenta(codemod.version);
663
+ const fKind = chalk__default.default.yellow(codemod.kind);
664
+ const fName = chalk__default.default.blue(codemod.format());
665
+ const fUID = codemodUID(codemod.uid);
666
+ return [fIndex, fVersion, fKind, fName, fUID];
667
+ });
668
+ const table = new CliTable3__default.default({
669
+ style: { compact: true },
670
+ head: [
671
+ chalk__default.default.bold.grey("N°"),
672
+ chalk__default.default.bold.magenta("Version"),
673
+ chalk__default.default.bold.yellow("Kind"),
674
+ chalk__default.default.bold.blue("Name"),
675
+ chalk__default.default.bold.cyan("UID")
676
+ ]
677
+ });
678
+ table.push(...rows);
679
+ return table.toString();
680
+ };
649
681
  const durationMs = (elapsedMs) => {
650
682
  const elapsedSeconds = (elapsedMs / ONE_SECOND_MS).toFixed(3);
651
683
  return `${elapsedSeconds}s`;
652
684
  };
653
685
  const index$8 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
654
686
  __proto__: null,
687
+ codemodList,
688
+ codemodUID,
655
689
  durationMs,
656
690
  highlight,
657
691
  path,
692
+ projectType,
658
693
  reports,
659
694
  transform,
660
695
  upgradeStep,
@@ -677,6 +712,7 @@ const constants$2 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineP
677
712
  CODEMOD_JSON_SUFFIX
678
713
  }, Symbol.toStringTag, { value: "Module" }));
679
714
  class Codemod {
715
+ uid;
680
716
  kind;
681
717
  version;
682
718
  baseDirectory;
@@ -688,9 +724,27 @@ class Codemod {
688
724
  this.baseDirectory = options.baseDirectory;
689
725
  this.filename = options.filename;
690
726
  this.path = path__default.default.join(this.baseDirectory, this.version.raw, this.filename);
691
- }
692
- format() {
693
- return this.filename.replace(`.${CODEMOD_CODE_SUFFIX}.${CODEMOD_EXTENSION}`, "").replace(`.${CODEMOD_JSON_SUFFIX}.${CODEMOD_EXTENSION}`, "").replaceAll("-", " ");
727
+ this.uid = this.createUID();
728
+ }
729
+ createUID() {
730
+ const name = this.format({ stripExtension: true, stripKind: true, stripHyphens: false });
731
+ const kind = this.kind;
732
+ const version2 = this.version.raw;
733
+ return `${version2}-${name}-${kind}`;
734
+ }
735
+ format(options) {
736
+ const { stripExtension = true, stripKind = true, stripHyphens = true } = options ?? {};
737
+ let formatted = this.filename;
738
+ if (stripExtension) {
739
+ formatted = formatted.replace(new RegExp(`\\.${CODEMOD_EXTENSION}$`, "i"), "");
740
+ }
741
+ if (stripKind) {
742
+ formatted = formatted.replace(`.${CODEMOD_CODE_SUFFIX}`, "").replace(`.${CODEMOD_JSON_SUFFIX}`, "");
743
+ }
744
+ if (stripHyphens) {
745
+ formatted = formatted.replaceAll("-", " ");
746
+ }
747
+ return formatted;
694
748
  }
695
749
  }
696
750
  const codemodFactory = (options) => new Codemod(options);
@@ -699,6 +753,20 @@ const index$7 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePrope
699
753
  codemodFactory,
700
754
  constants: constants$2
701
755
  }, Symbol.toStringTag, { value: "Module" }));
756
+ const INTERNAL_CODEMODS_DIRECTORY = path__default.default.join(
757
+ __dirname,
758
+ // upgrade/dist
759
+ "..",
760
+ // upgrade
761
+ "resources",
762
+ // upgrade/resources
763
+ "codemods"
764
+ // upgrade/resources/codemods
765
+ );
766
+ const constants$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
767
+ __proto__: null,
768
+ INTERNAL_CODEMODS_DIRECTORY
769
+ }, Symbol.toStringTag, { value: "Module" }));
702
770
  class CodemodRepository {
703
771
  groups;
704
772
  versions;
@@ -717,29 +785,47 @@ class CodemodRepository {
717
785
  count(version2) {
718
786
  return this.findByVersion(version2).length;
719
787
  }
720
- countRange(range) {
721
- return this.findByRange(range).length;
722
- }
723
- exists(version2) {
788
+ versionExists(version2) {
724
789
  return version2.raw in this.groups;
725
790
  }
726
- findByRange(range) {
791
+ has(uid) {
792
+ const result = this.find({ uids: [uid] });
793
+ if (result.length !== 1) {
794
+ return false;
795
+ }
796
+ const { codemods } = result[0];
797
+ return codemods.length === 1 && codemods[0].uid === uid;
798
+ }
799
+ find(q) {
727
800
  const entries = Object.entries(this.groups);
728
- return entries.filter(([version2]) => range.test(version2)).map(([version2, codemods2]) => ({
801
+ return entries.filter(maybeFilterByRange).map(([version2, codemods]) => ({
729
802
  version: semVerFactory(version2),
730
- codemods: codemods2
731
- }));
803
+ // Filter by UID if provided in the query
804
+ codemods: codemods.filter(maybeFilterByUIDs)
805
+ })).filter(({ codemods }) => codemods.length > 0);
806
+ function maybeFilterByRange([version2]) {
807
+ if (!isRangeInstance(q.range)) {
808
+ return true;
809
+ }
810
+ return q.range.test(version2);
811
+ }
812
+ function maybeFilterByUIDs(codemod) {
813
+ if (q.uids === void 0) {
814
+ return true;
815
+ }
816
+ return q.uids.includes(codemod.uid);
817
+ }
732
818
  }
733
819
  findByVersion(version2) {
734
820
  const literalVersion = version2.raw;
735
- const codemods2 = this.groups[literalVersion];
736
- return codemods2 ?? [];
821
+ const codemods = this.groups[literalVersion];
822
+ return codemods ?? [];
737
823
  }
738
824
  findAll() {
739
825
  const entries = Object.entries(this.groups);
740
- return entries.map(([version2, codemods2]) => ({
826
+ return entries.map(([version2, codemods]) => ({
741
827
  version: semVerFactory(version2),
742
- codemods: codemods2
828
+ codemods
743
829
  }));
744
830
  }
745
831
  refreshAvailableVersions() {
@@ -771,18 +857,9 @@ const parseCodemodKindFromFilename = (filename) => {
771
857
  assert__default.default(CODEMOD_ALLOWED_SUFFIXES.includes(kind));
772
858
  return kind;
773
859
  };
774
- const codemodRepositoryFactory = (cwd) => new CodemodRepository(cwd);
775
- const INTERNAL_CODEMODS_DIRECTORY = path__default.default.join(
776
- __dirname,
777
- "..",
778
- "..",
779
- "resources",
780
- "codemods"
781
- );
782
- const constants$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
783
- __proto__: null,
784
- INTERNAL_CODEMODS_DIRECTORY
785
- }, Symbol.toStringTag, { value: "Module" }));
860
+ const codemodRepositoryFactory = (cwd = INTERNAL_CODEMODS_DIRECTORY) => {
861
+ return new CodemodRepository(cwd);
862
+ };
786
863
  const index$6 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
787
864
  __proto__: null,
788
865
  codemodRepositoryFactory,
@@ -817,40 +894,59 @@ class CodemodRunner {
817
894
  this.isDry = enabled;
818
895
  return this;
819
896
  }
820
- async run(codemodsDirectory) {
897
+ createRepository(codemodsDirectory) {
821
898
  const repository = codemodRepositoryFactory(
822
899
  codemodsDirectory ?? INTERNAL_CODEMODS_DIRECTORY
823
900
  );
824
901
  repository.refresh();
825
- const allVersionedCodemods = this.range ? repository.findByRange(this.range) : repository.findAll();
826
- const versionedCodemods = this.selectCodemodsCallback ? await this.selectCodemodsCallback(allVersionedCodemods) : allVersionedCodemods;
827
- const hasCodemodsToRun = versionedCodemods.length > 0;
828
- if (!hasCodemodsToRun) {
829
- if (this.range) {
830
- this.logger?.debug(`Found no codemods to run for ${versionRange(this.range)}`);
831
- } else {
832
- this.logger?.debug(`Found no codemods to run`);
833
- }
834
- return successReport$1();
835
- }
836
- if (this.range) {
837
- this.logger?.debug(
838
- `Found codemods for ${highlight(versionedCodemods.length)} version(s) using ${this.range}`
902
+ return repository;
903
+ }
904
+ async safeRunAndReport(codemods) {
905
+ if (this.isDry) {
906
+ this.logger?.warn?.(
907
+ "Running the codemods in dry mode. No files will be modified during the process."
839
908
  );
840
- } else {
841
- this.logger?.debug(`Found codemods for ${highlight(versionedCodemods.length)} version(s)`);
842
909
  }
843
- versionedCodemods.forEach(
844
- ({ version: version$1, codemods: codemods22 }) => this.logger?.debug(`- ${version(version$1)} (${codemods22.length})`)
845
- );
846
- const codemods2 = versionedCodemods.map(({ codemods: codemods22 }) => codemods22).flat();
847
910
  try {
848
- const reports$1 = await this.project.runCodemods(codemods2, { dry: this.isDry });
849
- this.logger?.raw(reports(reports$1));
911
+ const reports$1 = await this.project.runCodemods(codemods, { dry: this.isDry });
912
+ this.logger?.raw?.(reports(reports$1));
913
+ if (!this.isDry) {
914
+ const nbAffectedTotal = reports$1.flatMap((report) => report.report.ok).reduce((acc, nb) => acc + nb, 0);
915
+ this.logger?.debug?.(
916
+ `Successfully ran ${highlight(codemods.length)} codemod(s), ${highlight(nbAffectedTotal)} change(s) have been detected`
917
+ );
918
+ }
919
+ return successReport$1();
850
920
  } catch (e) {
851
921
  return erroredReport$1(unknownToError(e));
852
922
  }
853
- return successReport$1();
923
+ }
924
+ async runByUID(uid, codemodsDirectory) {
925
+ const repository = this.createRepository(codemodsDirectory);
926
+ if (!repository.has(uid)) {
927
+ throw new Error(`Unknown codemod UID provided: ${uid}`);
928
+ }
929
+ const codemods = repository.find({ uids: [uid] }).flatMap(({ codemods: codemods2 }) => codemods2);
930
+ return this.safeRunAndReport(codemods);
931
+ }
932
+ async run(codemodsDirectory) {
933
+ const repository = this.createRepository(codemodsDirectory);
934
+ const codemodsInRange = repository.find({ range: this.range });
935
+ const selectedCodemods = this.selectCodemodsCallback ? await this.selectCodemodsCallback(codemodsInRange) : codemodsInRange;
936
+ if (selectedCodemods.length === 0) {
937
+ this.logger?.debug?.(`Found no codemods to run for ${versionRange(this.range)}`);
938
+ return successReport$1();
939
+ }
940
+ const codemods = selectedCodemods.flatMap(({ codemods: codemods2 }) => codemods2);
941
+ const codemodsByVersion = fp.groupBy("version", codemods);
942
+ const fRange = versionRange(this.range);
943
+ this.logger?.debug?.(
944
+ `Found ${highlight(codemods.length)} codemods for ${highlight(fp.size(codemodsByVersion))} version(s) using ${fRange}`
945
+ );
946
+ for (const [version$1, codemods2] of Object.entries(codemodsByVersion)) {
947
+ this.logger?.debug?.(`- ${version(semVerFactory(version$1))} (${codemods2.length})`);
948
+ }
949
+ return this.safeRunAndReport(codemods);
854
950
  }
855
951
  }
856
952
  const codemodRunnerFactory = (project, range) => {
@@ -889,7 +985,7 @@ class Upgrader {
889
985
  this.codemodsTarget = semVerFactory(
890
986
  `${this.target.major}.${this.target.minor}.${this.target.patch}`
891
987
  );
892
- this.logger?.debug(
988
+ this.logger?.debug?.(
893
989
  `The codemods target has been synced with the upgrade target. The codemod runner will now look for ${version(
894
990
  this.codemodsTarget
895
991
  )}`
@@ -898,7 +994,7 @@ class Upgrader {
898
994
  }
899
995
  overrideCodemodsTarget(target) {
900
996
  this.codemodsTarget = target;
901
- this.logger?.debug(
997
+ this.logger?.debug?.(
902
998
  `Overriding the codemods target. The codemod runner will now look for ${version(target)}`
903
999
  );
904
1000
  return this;
@@ -918,40 +1014,40 @@ class Upgrader {
918
1014
  addRequirement(requirement) {
919
1015
  this.requirements.push(requirement);
920
1016
  const fRequired = requirement.isRequired ? "(required)" : "(optional)";
921
- this.logger?.debug(
1017
+ this.logger?.debug?.(
922
1018
  `Added a new requirement to the upgrade: ${highlight(requirement.name)} ${fRequired}`
923
1019
  );
924
1020
  return this;
925
1021
  }
926
1022
  async upgrade() {
927
- this.logger?.info(
1023
+ this.logger?.info?.(
928
1024
  `Upgrading from ${version(this.project.strapiVersion)} to ${version(this.target)}`
929
1025
  );
930
1026
  if (this.isDry) {
931
- this.logger?.warn(
1027
+ this.logger?.warn?.(
932
1028
  "Running the upgrade in dry mode. No files will be modified during the process."
933
1029
  );
934
1030
  }
935
1031
  const range = rangeFromVersions(this.project.strapiVersion, this.target);
936
1032
  const codemodsRange = rangeFromVersions(this.project.strapiVersion, this.codemodsTarget);
937
1033
  const npmVersionsMatches = this.npmPackage?.findVersionsInRange(range) ?? [];
938
- this.logger?.debug(
1034
+ this.logger?.debug?.(
939
1035
  `Found ${highlight(npmVersionsMatches.length)} versions satisfying ${versionRange(range)}`
940
1036
  );
941
1037
  try {
942
- this.logger?.info(upgradeStep("Checking requirement", [1, 4]));
1038
+ this.logger?.info?.(upgradeStep("Checking requirement", [1, 4]));
943
1039
  await this.checkRequirements(this.requirements, {
944
1040
  npmVersionsMatches,
945
1041
  project: this.project,
946
1042
  target: this.target
947
1043
  });
948
- this.logger?.info(upgradeStep("Applying the latest code modifications", [2, 4]));
1044
+ this.logger?.info?.(upgradeStep("Applying the latest code modifications", [2, 4]));
949
1045
  await this.runCodemods(codemodsRange);
950
- this.logger?.debug("Refreshing project information...");
1046
+ this.logger?.debug?.("Refreshing project information...");
951
1047
  this.project.refresh();
952
- this.logger?.info(upgradeStep("Upgrading Strapi dependencies", [3, 4]));
1048
+ this.logger?.info?.(upgradeStep("Upgrading Strapi dependencies", [3, 4]));
953
1049
  await this.updateDependencies();
954
- this.logger?.info(upgradeStep("Installing dependencies", [4, 4]));
1050
+ this.logger?.info?.(upgradeStep("Installing dependencies", [4, 4]));
955
1051
  await this.installDependencies();
956
1052
  } catch (e) {
957
1053
  return erroredReport(unknownToError(e));
@@ -984,7 +1080,7 @@ class Upgrader {
984
1080
  if (requirement.isRequired) {
985
1081
  throw error;
986
1082
  }
987
- this.logger?.warn(warningMessage);
1083
+ this.logger?.warn?.(warningMessage);
988
1084
  const response = await this.confirmationCallback?.(confirmationMessage);
989
1085
  if (!response) {
990
1086
  throw error;
@@ -995,9 +1091,11 @@ class Upgrader {
995
1091
  const json = createJSONTransformAPI(packageJSON);
996
1092
  const dependencies = json.get("dependencies", {});
997
1093
  const strapiDependencies = this.getScopedStrapiDependencies(dependencies);
998
- this.logger?.debug(`Found ${highlight(strapiDependencies.length)} dependency(ies) to update`);
1094
+ this.logger?.debug?.(
1095
+ `Found ${highlight(strapiDependencies.length)} dependency(ies) to update`
1096
+ );
999
1097
  strapiDependencies.forEach(
1000
- (dependency) => this.logger?.debug(`- ${dependency[0]} (${dependency[1]} -> ${this.target})`)
1098
+ (dependency) => this.logger?.debug?.(`- ${dependency[0]} (${dependency[1]} -> ${this.target})`)
1001
1099
  );
1002
1100
  if (strapiDependencies.length === 0) {
1003
1101
  return;
@@ -1005,7 +1103,7 @@ class Upgrader {
1005
1103
  strapiDependencies.forEach(([name]) => json.set(`dependencies.${name}`, this.target.raw));
1006
1104
  const updatedPackageJSON = json.root();
1007
1105
  if (this.isDry) {
1008
- this.logger?.debug(`Skipping dependencies update (${chalk__default.default.italic("dry mode")})`);
1106
+ this.logger?.debug?.(`Skipping dependencies update (${chalk__default.default.italic("dry mode")})`);
1009
1107
  return;
1010
1108
  }
1011
1109
  await saveJSON(packageJSONPath, updatedPackageJSON);
@@ -1025,9 +1123,9 @@ class Upgrader {
1025
1123
  async installDependencies() {
1026
1124
  const projectPath = this.project.cwd;
1027
1125
  const packageManagerName = await utils.packageManager.getPreferred(projectPath);
1028
- this.logger?.debug(`Using ${highlight(packageManagerName)} as package manager`);
1126
+ this.logger?.debug?.(`Using ${highlight(packageManagerName)} as package manager`);
1029
1127
  if (this.isDry) {
1030
- this.logger?.debug(`Skipping dependencies installation (${chalk__default.default.italic("dry mode")}`);
1128
+ this.logger?.debug?.(`Skipping dependencies installation (${chalk__default.default.italic("dry mode")}`);
1031
1129
  return;
1032
1130
  }
1033
1131
  await utils.packageManager.installDependencies(projectPath, packageManagerName, {
@@ -1126,7 +1224,7 @@ const upgrade = async (options) => {
1126
1224
  const { logger, codemodsTarget } = options;
1127
1225
  const cwd = path__default.default.resolve(options.cwd ?? process.cwd());
1128
1226
  const project = projectFactory(cwd);
1129
- if (!isAppProject(project)) {
1227
+ if (!isApplicationProject(project)) {
1130
1228
  throw new Error(
1131
1229
  `The "${options.target}" upgrade can only be run on a Strapi project; for plugins, please use "codemods".`
1132
1230
  );
@@ -1148,20 +1246,7 @@ const upgrade = async (options) => {
1148
1246
  timer.stop();
1149
1247
  logger.info(`Completed in ${durationMs(timer.elapsedMs)}`);
1150
1248
  };
1151
- const codemods = async (options) => {
1152
- const timer = timerFactory();
1153
- const { logger } = options;
1154
- const cwd = path__default.default.resolve(options.cwd ?? process.cwd());
1155
- const project = projectFactory(cwd);
1156
- const range = isAppProject(project) ? getRangeFromTarget(project.strapiVersion, options.target) : void 0;
1157
- const codemodRunner = codemodRunnerFactory(project, range).dry(options.dry ?? false).onSelectCodemods(options.selectCodemods ?? null).setLogger(logger);
1158
- const executionReport = await codemodRunner.run();
1159
- if (!executionReport.success) {
1160
- throw executionReport.error;
1161
- }
1162
- timer.stop();
1163
- logger.info(`Completed in ${timer.elapsedMs}`);
1164
- };
1249
+ const resolvePath = (cwd) => path__default.default.resolve(cwd ?? process.cwd());
1165
1250
  const getRangeFromTarget = (currentVersion, target) => {
1166
1251
  if (isSemverInstance(target)) {
1167
1252
  return rangeFactory(target);
@@ -1178,9 +1263,60 @@ const getRangeFromTarget = (currentVersion, target) => {
1178
1263
  throw new Error(`Invalid target set: ${target}`);
1179
1264
  }
1180
1265
  };
1266
+ const findRangeFromTarget = (project, target) => {
1267
+ if (isRangeInstance(target)) {
1268
+ return target;
1269
+ }
1270
+ if (isApplicationProject(project)) {
1271
+ return getRangeFromTarget(project.strapiVersion, target);
1272
+ }
1273
+ return rangeFactory("*");
1274
+ };
1275
+ const runCodemods = async (options) => {
1276
+ const timer = timerFactory();
1277
+ const { logger, uid } = options;
1278
+ const cwd = resolvePath(options.cwd);
1279
+ const project = projectFactory(cwd);
1280
+ const range = findRangeFromTarget(project, options.target);
1281
+ logger.debug(`Project: ${projectType(project.type)} found in ${path(cwd)}`);
1282
+ logger.debug(`Range: set to ${versionRange(range)}`);
1283
+ const codemodRunner = codemodRunnerFactory(project, range).dry(options.dry ?? false).onSelectCodemods(options.selectCodemods ?? null).setLogger(logger);
1284
+ let report;
1285
+ if (uid !== void 0) {
1286
+ logger.debug(`Running a single codemod: ${codemodUID(uid)}`);
1287
+ report = await codemodRunner.runByUID(uid);
1288
+ } else {
1289
+ report = await codemodRunner.run();
1290
+ }
1291
+ if (!report.success) {
1292
+ throw report.error;
1293
+ }
1294
+ timer.stop();
1295
+ logger.info(`Completed in ${timer.elapsedMs}`);
1296
+ };
1297
+ const listCodemods = async (options) => {
1298
+ const { logger, target } = options;
1299
+ const cwd = resolvePath(options.cwd);
1300
+ const project = projectFactory(cwd);
1301
+ const range = findRangeFromTarget(project, target);
1302
+ logger.debug(`Project: ${projectType(project.type)} found in ${path(cwd)}`);
1303
+ logger.debug(`Range: set to ${versionRange(range)}`);
1304
+ const repo = codemodRepositoryFactory();
1305
+ repo.refresh();
1306
+ const groups = repo.find({ range });
1307
+ const codemods = groups.flatMap((collection) => collection.codemods);
1308
+ logger.debug(`Found ${highlight(codemods.length)} codemods`);
1309
+ if (codemods.length === 0) {
1310
+ logger.info(`Found no codemods matching ${versionRange(range)}`);
1311
+ return;
1312
+ }
1313
+ const fCodemods = codemodList(codemods);
1314
+ logger.raw(fCodemods);
1315
+ };
1181
1316
  const index$4 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
1182
1317
  __proto__: null,
1183
- codemods,
1318
+ listCodemods,
1319
+ runCodemods,
1184
1320
  upgrade
1185
1321
  }, Symbol.toStringTag, { value: "Module" }));
1186
1322
  class Logger {