@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.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,
@@ -418,10 +424,10 @@ class Project {
418
424
  this.refreshProjectFiles();
419
425
  return this;
420
426
  }
421
- async runCodemods(codemods2, options) {
427
+ async runCodemods(codemods, options) {
422
428
  const runners = this.createProjectCodemodsRunners(options.dry);
423
429
  const reports2 = [];
424
- for (const codemod of codemods2) {
430
+ for (const codemod of codemods) {
425
431
  for (const runner of runners) {
426
432
  if (runner.valid(codemod)) {
427
433
  const report = await runner.run(codemod);
@@ -480,7 +486,7 @@ class Project {
480
486
  }
481
487
  class AppProject extends Project {
482
488
  strapiVersion;
483
- type = "app";
489
+ type = "application";
484
490
  constructor(cwd) {
485
491
  super(cwd);
486
492
  this.refreshStrapiVersion();
@@ -564,12 +570,12 @@ function assertPluginProject(project) {
564
570
  throw new Error("Project is not a plugin");
565
571
  }
566
572
  }
567
- const isAppProject = (project) => {
573
+ const isApplicationProject = (project) => {
568
574
  return project instanceof AppProject;
569
575
  };
570
576
  function assertAppProject(project) {
571
- if (!isAppProject(project)) {
572
- throw new Error("Project is not an app");
577
+ if (!isApplicationProject(project)) {
578
+ throw new Error("Project is not an application");
573
579
  }
574
580
  }
575
581
  const index$a = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
@@ -577,7 +583,7 @@ const index$a = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePrope
577
583
  assertAppProject,
578
584
  assertPluginProject,
579
585
  constants: constants$3,
580
- isAppProject,
586
+ isApplicationProject,
581
587
  isPluginProject,
582
588
  projectFactory
583
589
  }, Symbol.toStringTag, { value: "Module" }));
@@ -604,7 +610,11 @@ const path = (path2) => chalk.blue(path2);
604
610
  const version = (version2) => {
605
611
  return chalk.italic.yellow(`v${version2}`);
606
612
  };
607
- const versionRange = (range) => chalk.italic.yellow(range);
613
+ const codemodUID = (uid) => {
614
+ return chalk.bold.cyan(uid);
615
+ };
616
+ const projectType = (type) => chalk.cyan(type);
617
+ const versionRange = (range) => chalk.italic.yellow(range.raw);
608
618
  const transform = (transformFilePath) => chalk.cyan(transformFilePath);
609
619
  const highlight = (arg) => chalk.bold.underline(arg);
610
620
  const upgradeStep = (text, step) => {
@@ -636,15 +646,40 @@ const reports = (reports2) => {
636
646
  table.push(...rows);
637
647
  return table.toString();
638
648
  };
649
+ const codemodList = (codemods) => {
650
+ const rows = codemods.map((codemod, index2) => {
651
+ const fIndex = chalk.grey(index2);
652
+ const fVersion = chalk.magenta(codemod.version);
653
+ const fKind = chalk.yellow(codemod.kind);
654
+ const fName = chalk.blue(codemod.format());
655
+ const fUID = codemodUID(codemod.uid);
656
+ return [fIndex, fVersion, fKind, fName, fUID];
657
+ });
658
+ const table = new CliTable3({
659
+ style: { compact: true },
660
+ head: [
661
+ chalk.bold.grey("N°"),
662
+ chalk.bold.magenta("Version"),
663
+ chalk.bold.yellow("Kind"),
664
+ chalk.bold.blue("Name"),
665
+ chalk.bold.cyan("UID")
666
+ ]
667
+ });
668
+ table.push(...rows);
669
+ return table.toString();
670
+ };
639
671
  const durationMs = (elapsedMs) => {
640
672
  const elapsedSeconds = (elapsedMs / ONE_SECOND_MS).toFixed(3);
641
673
  return `${elapsedSeconds}s`;
642
674
  };
643
675
  const index$8 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
644
676
  __proto__: null,
677
+ codemodList,
678
+ codemodUID,
645
679
  durationMs,
646
680
  highlight,
647
681
  path,
682
+ projectType,
648
683
  reports,
649
684
  transform,
650
685
  upgradeStep,
@@ -667,6 +702,7 @@ const constants$2 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineP
667
702
  CODEMOD_JSON_SUFFIX
668
703
  }, Symbol.toStringTag, { value: "Module" }));
669
704
  class Codemod {
705
+ uid;
670
706
  kind;
671
707
  version;
672
708
  baseDirectory;
@@ -678,9 +714,27 @@ class Codemod {
678
714
  this.baseDirectory = options.baseDirectory;
679
715
  this.filename = options.filename;
680
716
  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("-", " ");
717
+ this.uid = this.createUID();
718
+ }
719
+ createUID() {
720
+ const name = this.format({ stripExtension: true, stripKind: true, stripHyphens: false });
721
+ const kind = this.kind;
722
+ const version2 = this.version.raw;
723
+ return `${version2}-${name}-${kind}`;
724
+ }
725
+ format(options) {
726
+ const { stripExtension = true, stripKind = true, stripHyphens = true } = options ?? {};
727
+ let formatted = this.filename;
728
+ if (stripExtension) {
729
+ formatted = formatted.replace(new RegExp(`\\.${CODEMOD_EXTENSION}$`, "i"), "");
730
+ }
731
+ if (stripKind) {
732
+ formatted = formatted.replace(`.${CODEMOD_CODE_SUFFIX}`, "").replace(`.${CODEMOD_JSON_SUFFIX}`, "");
733
+ }
734
+ if (stripHyphens) {
735
+ formatted = formatted.replaceAll("-", " ");
736
+ }
737
+ return formatted;
684
738
  }
685
739
  }
686
740
  const codemodFactory = (options) => new Codemod(options);
@@ -689,6 +743,20 @@ const index$7 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePrope
689
743
  codemodFactory,
690
744
  constants: constants$2
691
745
  }, Symbol.toStringTag, { value: "Module" }));
746
+ const INTERNAL_CODEMODS_DIRECTORY = path$1.join(
747
+ __dirname,
748
+ // upgrade/dist
749
+ "..",
750
+ // upgrade
751
+ "resources",
752
+ // upgrade/resources
753
+ "codemods"
754
+ // upgrade/resources/codemods
755
+ );
756
+ const constants$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
757
+ __proto__: null,
758
+ INTERNAL_CODEMODS_DIRECTORY
759
+ }, Symbol.toStringTag, { value: "Module" }));
692
760
  class CodemodRepository {
693
761
  groups;
694
762
  versions;
@@ -707,29 +775,47 @@ class CodemodRepository {
707
775
  count(version2) {
708
776
  return this.findByVersion(version2).length;
709
777
  }
710
- countRange(range) {
711
- return this.findByRange(range).length;
712
- }
713
- exists(version2) {
778
+ versionExists(version2) {
714
779
  return version2.raw in this.groups;
715
780
  }
716
- findByRange(range) {
781
+ has(uid) {
782
+ const result = this.find({ uids: [uid] });
783
+ if (result.length !== 1) {
784
+ return false;
785
+ }
786
+ const { codemods } = result[0];
787
+ return codemods.length === 1 && codemods[0].uid === uid;
788
+ }
789
+ find(q) {
717
790
  const entries = Object.entries(this.groups);
718
- return entries.filter(([version2]) => range.test(version2)).map(([version2, codemods2]) => ({
791
+ return entries.filter(maybeFilterByRange).map(([version2, codemods]) => ({
719
792
  version: semVerFactory(version2),
720
- codemods: codemods2
721
- }));
793
+ // Filter by UID if provided in the query
794
+ codemods: codemods.filter(maybeFilterByUIDs)
795
+ })).filter(({ codemods }) => codemods.length > 0);
796
+ function maybeFilterByRange([version2]) {
797
+ if (!isRangeInstance(q.range)) {
798
+ return true;
799
+ }
800
+ return q.range.test(version2);
801
+ }
802
+ function maybeFilterByUIDs(codemod) {
803
+ if (q.uids === void 0) {
804
+ return true;
805
+ }
806
+ return q.uids.includes(codemod.uid);
807
+ }
722
808
  }
723
809
  findByVersion(version2) {
724
810
  const literalVersion = version2.raw;
725
- const codemods2 = this.groups[literalVersion];
726
- return codemods2 ?? [];
811
+ const codemods = this.groups[literalVersion];
812
+ return codemods ?? [];
727
813
  }
728
814
  findAll() {
729
815
  const entries = Object.entries(this.groups);
730
- return entries.map(([version2, codemods2]) => ({
816
+ return entries.map(([version2, codemods]) => ({
731
817
  version: semVerFactory(version2),
732
- codemods: codemods2
818
+ codemods
733
819
  }));
734
820
  }
735
821
  refreshAvailableVersions() {
@@ -761,18 +847,9 @@ const parseCodemodKindFromFilename = (filename) => {
761
847
  assert(CODEMOD_ALLOWED_SUFFIXES.includes(kind));
762
848
  return kind;
763
849
  };
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" }));
850
+ const codemodRepositoryFactory = (cwd = INTERNAL_CODEMODS_DIRECTORY) => {
851
+ return new CodemodRepository(cwd);
852
+ };
776
853
  const index$6 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
777
854
  __proto__: null,
778
855
  codemodRepositoryFactory,
@@ -807,40 +884,59 @@ class CodemodRunner {
807
884
  this.isDry = enabled;
808
885
  return this;
809
886
  }
810
- async run(codemodsDirectory) {
887
+ createRepository(codemodsDirectory) {
811
888
  const repository = codemodRepositoryFactory(
812
889
  codemodsDirectory ?? INTERNAL_CODEMODS_DIRECTORY
813
890
  );
814
891
  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}`
892
+ return repository;
893
+ }
894
+ async safeRunAndReport(codemods) {
895
+ if (this.isDry) {
896
+ this.logger?.warn?.(
897
+ "Running the codemods in dry mode. No files will be modified during the process."
829
898
  );
830
- } else {
831
- this.logger?.debug(`Found codemods for ${highlight(versionedCodemods.length)} version(s)`);
832
899
  }
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
900
  try {
838
- const reports$1 = await this.project.runCodemods(codemods2, { dry: this.isDry });
839
- this.logger?.raw(reports(reports$1));
901
+ const reports$1 = await this.project.runCodemods(codemods, { dry: this.isDry });
902
+ this.logger?.raw?.(reports(reports$1));
903
+ if (!this.isDry) {
904
+ const nbAffectedTotal = reports$1.flatMap((report) => report.report.ok).reduce((acc, nb) => acc + nb, 0);
905
+ this.logger?.debug?.(
906
+ `Successfully ran ${highlight(codemods.length)} codemod(s), ${highlight(nbAffectedTotal)} change(s) have been detected`
907
+ );
908
+ }
909
+ return successReport$1();
840
910
  } catch (e) {
841
911
  return erroredReport$1(unknownToError(e));
842
912
  }
843
- return successReport$1();
913
+ }
914
+ async runByUID(uid, codemodsDirectory) {
915
+ const repository = this.createRepository(codemodsDirectory);
916
+ if (!repository.has(uid)) {
917
+ throw new Error(`Unknown codemod UID provided: ${uid}`);
918
+ }
919
+ const codemods = repository.find({ uids: [uid] }).flatMap(({ codemods: codemods2 }) => codemods2);
920
+ return this.safeRunAndReport(codemods);
921
+ }
922
+ async run(codemodsDirectory) {
923
+ const repository = this.createRepository(codemodsDirectory);
924
+ const codemodsInRange = repository.find({ range: this.range });
925
+ const selectedCodemods = this.selectCodemodsCallback ? await this.selectCodemodsCallback(codemodsInRange) : codemodsInRange;
926
+ if (selectedCodemods.length === 0) {
927
+ this.logger?.debug?.(`Found no codemods to run for ${versionRange(this.range)}`);
928
+ return successReport$1();
929
+ }
930
+ const codemods = selectedCodemods.flatMap(({ codemods: codemods2 }) => codemods2);
931
+ const codemodsByVersion = groupBy("version", codemods);
932
+ const fRange = versionRange(this.range);
933
+ this.logger?.debug?.(
934
+ `Found ${highlight(codemods.length)} codemods for ${highlight(size(codemodsByVersion))} version(s) using ${fRange}`
935
+ );
936
+ for (const [version$1, codemods2] of Object.entries(codemodsByVersion)) {
937
+ this.logger?.debug?.(`- ${version(semVerFactory(version$1))} (${codemods2.length})`);
938
+ }
939
+ return this.safeRunAndReport(codemods);
844
940
  }
845
941
  }
846
942
  const codemodRunnerFactory = (project, range) => {
@@ -879,7 +975,7 @@ class Upgrader {
879
975
  this.codemodsTarget = semVerFactory(
880
976
  `${this.target.major}.${this.target.minor}.${this.target.patch}`
881
977
  );
882
- this.logger?.debug(
978
+ this.logger?.debug?.(
883
979
  `The codemods target has been synced with the upgrade target. The codemod runner will now look for ${version(
884
980
  this.codemodsTarget
885
981
  )}`
@@ -888,7 +984,7 @@ class Upgrader {
888
984
  }
889
985
  overrideCodemodsTarget(target) {
890
986
  this.codemodsTarget = target;
891
- this.logger?.debug(
987
+ this.logger?.debug?.(
892
988
  `Overriding the codemods target. The codemod runner will now look for ${version(target)}`
893
989
  );
894
990
  return this;
@@ -908,40 +1004,40 @@ class Upgrader {
908
1004
  addRequirement(requirement) {
909
1005
  this.requirements.push(requirement);
910
1006
  const fRequired = requirement.isRequired ? "(required)" : "(optional)";
911
- this.logger?.debug(
1007
+ this.logger?.debug?.(
912
1008
  `Added a new requirement to the upgrade: ${highlight(requirement.name)} ${fRequired}`
913
1009
  );
914
1010
  return this;
915
1011
  }
916
1012
  async upgrade() {
917
- this.logger?.info(
1013
+ this.logger?.info?.(
918
1014
  `Upgrading from ${version(this.project.strapiVersion)} to ${version(this.target)}`
919
1015
  );
920
1016
  if (this.isDry) {
921
- this.logger?.warn(
1017
+ this.logger?.warn?.(
922
1018
  "Running the upgrade in dry mode. No files will be modified during the process."
923
1019
  );
924
1020
  }
925
1021
  const range = rangeFromVersions(this.project.strapiVersion, this.target);
926
1022
  const codemodsRange = rangeFromVersions(this.project.strapiVersion, this.codemodsTarget);
927
1023
  const npmVersionsMatches = this.npmPackage?.findVersionsInRange(range) ?? [];
928
- this.logger?.debug(
1024
+ this.logger?.debug?.(
929
1025
  `Found ${highlight(npmVersionsMatches.length)} versions satisfying ${versionRange(range)}`
930
1026
  );
931
1027
  try {
932
- this.logger?.info(upgradeStep("Checking requirement", [1, 4]));
1028
+ this.logger?.info?.(upgradeStep("Checking requirement", [1, 4]));
933
1029
  await this.checkRequirements(this.requirements, {
934
1030
  npmVersionsMatches,
935
1031
  project: this.project,
936
1032
  target: this.target
937
1033
  });
938
- this.logger?.info(upgradeStep("Applying the latest code modifications", [2, 4]));
1034
+ this.logger?.info?.(upgradeStep("Applying the latest code modifications", [2, 4]));
939
1035
  await this.runCodemods(codemodsRange);
940
- this.logger?.debug("Refreshing project information...");
1036
+ this.logger?.debug?.("Refreshing project information...");
941
1037
  this.project.refresh();
942
- this.logger?.info(upgradeStep("Upgrading Strapi dependencies", [3, 4]));
1038
+ this.logger?.info?.(upgradeStep("Upgrading Strapi dependencies", [3, 4]));
943
1039
  await this.updateDependencies();
944
- this.logger?.info(upgradeStep("Installing dependencies", [4, 4]));
1040
+ this.logger?.info?.(upgradeStep("Installing dependencies", [4, 4]));
945
1041
  await this.installDependencies();
946
1042
  } catch (e) {
947
1043
  return erroredReport(unknownToError(e));
@@ -974,7 +1070,7 @@ class Upgrader {
974
1070
  if (requirement.isRequired) {
975
1071
  throw error;
976
1072
  }
977
- this.logger?.warn(warningMessage);
1073
+ this.logger?.warn?.(warningMessage);
978
1074
  const response = await this.confirmationCallback?.(confirmationMessage);
979
1075
  if (!response) {
980
1076
  throw error;
@@ -985,9 +1081,11 @@ class Upgrader {
985
1081
  const json = createJSONTransformAPI(packageJSON);
986
1082
  const dependencies = json.get("dependencies", {});
987
1083
  const strapiDependencies = this.getScopedStrapiDependencies(dependencies);
988
- this.logger?.debug(`Found ${highlight(strapiDependencies.length)} dependency(ies) to update`);
1084
+ this.logger?.debug?.(
1085
+ `Found ${highlight(strapiDependencies.length)} dependency(ies) to update`
1086
+ );
989
1087
  strapiDependencies.forEach(
990
- (dependency) => this.logger?.debug(`- ${dependency[0]} (${dependency[1]} -> ${this.target})`)
1088
+ (dependency) => this.logger?.debug?.(`- ${dependency[0]} (${dependency[1]} -> ${this.target})`)
991
1089
  );
992
1090
  if (strapiDependencies.length === 0) {
993
1091
  return;
@@ -995,7 +1093,7 @@ class Upgrader {
995
1093
  strapiDependencies.forEach(([name]) => json.set(`dependencies.${name}`, this.target.raw));
996
1094
  const updatedPackageJSON = json.root();
997
1095
  if (this.isDry) {
998
- this.logger?.debug(`Skipping dependencies update (${chalk.italic("dry mode")})`);
1096
+ this.logger?.debug?.(`Skipping dependencies update (${chalk.italic("dry mode")})`);
999
1097
  return;
1000
1098
  }
1001
1099
  await saveJSON(packageJSONPath, updatedPackageJSON);
@@ -1015,9 +1113,9 @@ class Upgrader {
1015
1113
  async installDependencies() {
1016
1114
  const projectPath = this.project.cwd;
1017
1115
  const packageManagerName = await packageManager.getPreferred(projectPath);
1018
- this.logger?.debug(`Using ${highlight(packageManagerName)} as package manager`);
1116
+ this.logger?.debug?.(`Using ${highlight(packageManagerName)} as package manager`);
1019
1117
  if (this.isDry) {
1020
- this.logger?.debug(`Skipping dependencies installation (${chalk.italic("dry mode")}`);
1118
+ this.logger?.debug?.(`Skipping dependencies installation (${chalk.italic("dry mode")}`);
1021
1119
  return;
1022
1120
  }
1023
1121
  await packageManager.installDependencies(projectPath, packageManagerName, {
@@ -1116,7 +1214,7 @@ const upgrade = async (options) => {
1116
1214
  const { logger, codemodsTarget } = options;
1117
1215
  const cwd = path$1.resolve(options.cwd ?? process.cwd());
1118
1216
  const project = projectFactory(cwd);
1119
- if (!isAppProject(project)) {
1217
+ if (!isApplicationProject(project)) {
1120
1218
  throw new Error(
1121
1219
  `The "${options.target}" upgrade can only be run on a Strapi project; for plugins, please use "codemods".`
1122
1220
  );
@@ -1138,20 +1236,7 @@ const upgrade = async (options) => {
1138
1236
  timer.stop();
1139
1237
  logger.info(`Completed in ${durationMs(timer.elapsedMs)}`);
1140
1238
  };
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
- };
1239
+ const resolvePath = (cwd) => path$1.resolve(cwd ?? process.cwd());
1155
1240
  const getRangeFromTarget = (currentVersion, target) => {
1156
1241
  if (isSemverInstance(target)) {
1157
1242
  return rangeFactory(target);
@@ -1168,9 +1253,60 @@ const getRangeFromTarget = (currentVersion, target) => {
1168
1253
  throw new Error(`Invalid target set: ${target}`);
1169
1254
  }
1170
1255
  };
1256
+ const findRangeFromTarget = (project, target) => {
1257
+ if (isRangeInstance(target)) {
1258
+ return target;
1259
+ }
1260
+ if (isApplicationProject(project)) {
1261
+ return getRangeFromTarget(project.strapiVersion, target);
1262
+ }
1263
+ return rangeFactory("*");
1264
+ };
1265
+ const runCodemods = async (options) => {
1266
+ const timer = timerFactory();
1267
+ const { logger, uid } = options;
1268
+ const cwd = resolvePath(options.cwd);
1269
+ const project = projectFactory(cwd);
1270
+ const range = findRangeFromTarget(project, options.target);
1271
+ logger.debug(`Project: ${projectType(project.type)} found in ${path(cwd)}`);
1272
+ logger.debug(`Range: set to ${versionRange(range)}`);
1273
+ const codemodRunner = codemodRunnerFactory(project, range).dry(options.dry ?? false).onSelectCodemods(options.selectCodemods ?? null).setLogger(logger);
1274
+ let report;
1275
+ if (uid !== void 0) {
1276
+ logger.debug(`Running a single codemod: ${codemodUID(uid)}`);
1277
+ report = await codemodRunner.runByUID(uid);
1278
+ } else {
1279
+ report = await codemodRunner.run();
1280
+ }
1281
+ if (!report.success) {
1282
+ throw report.error;
1283
+ }
1284
+ timer.stop();
1285
+ logger.info(`Completed in ${timer.elapsedMs}`);
1286
+ };
1287
+ const listCodemods = async (options) => {
1288
+ const { logger, target } = options;
1289
+ const cwd = resolvePath(options.cwd);
1290
+ const project = projectFactory(cwd);
1291
+ const range = findRangeFromTarget(project, target);
1292
+ logger.debug(`Project: ${projectType(project.type)} found in ${path(cwd)}`);
1293
+ logger.debug(`Range: set to ${versionRange(range)}`);
1294
+ const repo = codemodRepositoryFactory();
1295
+ repo.refresh();
1296
+ const groups = repo.find({ range });
1297
+ const codemods = groups.flatMap((collection) => collection.codemods);
1298
+ logger.debug(`Found ${highlight(codemods.length)} codemods`);
1299
+ if (codemods.length === 0) {
1300
+ logger.info(`Found no codemods matching ${versionRange(range)}`);
1301
+ return;
1302
+ }
1303
+ const fCodemods = codemodList(codemods);
1304
+ logger.raw(fCodemods);
1305
+ };
1171
1306
  const index$4 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
1172
1307
  __proto__: null,
1173
- codemods,
1308
+ listCodemods,
1309
+ runCodemods,
1174
1310
  upgrade
1175
1311
  }, Symbol.toStringTag, { value: "Module" }));
1176
1312
  class Logger {