@pagopa/dx-cli 0.13.0 → 0.14.1

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 (3) hide show
  1. package/README.md +30 -6
  2. package/bin/index.js +195 -74
  3. package/package.json +6 -6
package/README.md CHANGED
@@ -112,19 +112,43 @@ This command helps you:
112
112
 
113
113
  #### `init`
114
114
 
115
- Initialize resources such as new projects with standardized structure.
115
+ Bootstrap a new monorepo project with standardized structure and remote repository provisioning.
116
116
 
117
117
  ```bash
118
- # Initialize a new monorepo project
119
118
  dx init project
120
119
  ```
121
120
 
122
121
  This command will:
123
122
 
124
- - Guide you through creating a new monorepo project
125
- - Set up the project structure according to PagoPA's DevEx guidelines
126
- - Configure necessary tools and dependencies
127
- - Bootstrap the project with best practices
123
+ - Check that required tools (e.g., Terraform CLI) are installed
124
+ - Interactively prompt for project metadata (cloud provider, region, environments, cost center, etc.)
125
+ - Generate a monorepo structure following PagoPA DevEx guidelines
126
+ - Create a remote GitHub repository using Terraform
127
+ - Push the initial codebase to the newly created repository
128
+
129
+ **Example usage:**
130
+
131
+ ```bash
132
+ $ dx init project
133
+ ? What is the repository name? my-monorepo
134
+ ? What is the GitHub repository owner? pagopa
135
+ ? What is the repository description? My new PagoPA monorepo
136
+ ...
137
+
138
+ ✔ Terraform CLI is installed!
139
+ ✔ Workspace files created successfully!
140
+ ✔ GitHub repository created successfully!
141
+ ✔ Code pushed to GitHub successfully!
142
+
143
+ Workspace created successfully!
144
+ - Name: my-monorepo
145
+ - Cloud Service Provider: azure
146
+ - CSP location: italynorth
147
+ - GitHub Repository: https://github.com/pagopa/my-monorepo
148
+ ```
149
+
150
+ > [!NOTE]
151
+ > The command will fail early if required tools are missing.
128
152
 
129
153
  #### `info`
130
154
 
package/bin/index.js CHANGED
@@ -3,6 +3,7 @@
3
3
  // src/index.ts
4
4
  import "core-js/actual/set/index.js";
5
5
  import { configure, getConsoleSink } from "@logtape/logtape";
6
+ import { Octokit as Octokit2 } from "octokit";
6
7
 
7
8
  // src/adapters/codemods/registry.ts
8
9
  import { okAsync } from "neverthrow";
@@ -31,8 +32,8 @@ import * as YAML2 from "yaml";
31
32
  import { getLogger } from "@logtape/logtape";
32
33
  import { Octokit } from "octokit";
33
34
  var getLatestCommitSha = async (owner, repo, ref = "main") => {
34
- const octokit = new Octokit();
35
- const response = await octokit.rest.repos.getCommit({
35
+ const octokit2 = new Octokit();
36
+ const response = await octokit2.rest.repos.getCommit({
36
37
  owner,
37
38
  ref,
38
39
  repo
@@ -52,8 +53,8 @@ var getLatestCommitShaOrRef = async (owner, repo, ref = "main") => {
52
53
 
53
54
  // src/adapters/codemods/yaml.ts
54
55
  import * as YAML from "yaml";
55
- var isChildOf = (path2, key) => {
56
- const ancestor = path2.at(-1);
56
+ var isChildOf = (path3, key) => {
57
+ const ancestor = path3.at(-1);
57
58
  return YAML.isPair(ancestor) && YAML.isScalar(ancestor.key) && typeof ancestor.key.value === "string" && ancestor.key.value === key;
58
59
  };
59
60
 
@@ -63,8 +64,8 @@ var updateJSCodeReviewJob = (sha) => (workflow, filename) => {
63
64
  const document = YAML2.parseDocument(workflow);
64
65
  let updated = false;
65
66
  YAML2.visit(document, {
66
- Map(_, map, path2) {
67
- if (map.has("jobs") || isChildOf(path2, "jobs")) {
67
+ Map(_, map, path3) {
68
+ if (map.has("jobs") || isChildOf(path3, "jobs")) {
68
69
  return void 0;
69
70
  }
70
71
  if (map.has("uses")) {
@@ -127,8 +128,8 @@ var migrateWorkflow = (sha) => (workflow, filename) => {
127
128
  const document = YAML3.parseDocument(workflow);
128
129
  let updated = false;
129
130
  YAML3.visit(document, {
130
- Map(_, map, path2) {
131
- if (isChildOf(path2, "jobs") || isChildOf(path2, "with")) {
131
+ Map(_, map, path3) {
132
+ if (isChildOf(path3, "jobs") || isChildOf(path3, "with")) {
132
133
  return void 0;
133
134
  }
134
135
  if (map.has("jobs")) {
@@ -746,20 +747,26 @@ import loadMonorepoScaffolder, {
746
747
  } from "@pagopa/monorepo-generator";
747
748
  import chalk from "chalk";
748
749
  import { Command as Command4 } from "commander";
749
- import { $ as $2 } from "execa";
750
- import { okAsync as okAsync2, Result, ResultAsync as ResultAsync5 } from "neverthrow";
751
- import nodePlop from "node-plop";
750
+ import { $ as $3 } from "execa";
751
+ import { okAsync as okAsync2, ResultAsync as ResultAsync6 } from "neverthrow";
752
+ import * as path from "path";
752
753
  import { oraPromise } from "ora";
753
754
 
754
- // src/adapters/zod/index.ts
755
- import { ResultAsync as ResultAsync4 } from "neverthrow";
756
- var decode = (schema) => (data) => ResultAsync4.fromPromise(
757
- schema.parseAsync(data),
758
- (cause) => new Error("Input is not valid for the given schema", { cause })
759
- );
755
+ // src/adapters/execa/terraform.ts
756
+ import { $ as $2 } from "execa";
757
+ var tf$ = $2({
758
+ environment: {
759
+ NO_COLOR: "1",
760
+ TF_IN_AUTOMATION: "1",
761
+ TF_INPUT: "0"
762
+ },
763
+ shell: true
764
+ });
760
765
 
761
- // src/adapters/commander/commands/init.ts
762
- var initPlop = () => ResultAsync5.fromPromise(
766
+ // src/adapters/plop/index.ts
767
+ import { Result, ResultAsync as ResultAsync4 } from "neverthrow";
768
+ import nodePlop from "node-plop";
769
+ var initPlop = () => ResultAsync4.fromPromise(
763
770
  nodePlop(),
764
771
  () => new Error("Failed to initialize plop")
765
772
  );
@@ -767,11 +774,32 @@ var getGenerator = (plopAPI) => Result.fromThrowable(
767
774
  plopAPI.getGenerator,
768
775
  () => new Error("Generator not found")
769
776
  );
770
- var getPrompts = (generator) => ResultAsync5.fromPromise(
777
+ var getPrompts = (generator) => ResultAsync4.fromPromise(
771
778
  generator.runPrompts(),
772
779
  (cause) => new Error("Failed to run the generator prompts", { cause })
773
780
  );
774
- var withSpinner = (text, successText, failText, promise) => ResultAsync5.fromPromise(
781
+
782
+ // src/adapters/zod/index.ts
783
+ import { ResultAsync as ResultAsync5 } from "neverthrow";
784
+ var decode = (schema) => (data) => ResultAsync5.fromPromise(
785
+ schema.parseAsync(data),
786
+ (cause) => new Error("Input is not valid for the given schema", { cause })
787
+ );
788
+
789
+ // src/adapters/commander/commands/init.ts
790
+ var Repository = class {
791
+ constructor(name, owner) {
792
+ this.name = name;
793
+ this.owner = owner;
794
+ }
795
+ get ssh() {
796
+ return `git@github.com:${this.owner}/${this.name}.git`;
797
+ }
798
+ get url() {
799
+ return `https://github.com/${this.owner}/${this.name}`;
800
+ }
801
+ };
802
+ var withSpinner = (text, successText, failText, promise) => ResultAsync6.fromPromise(
775
803
  oraPromise(promise, {
776
804
  failText,
777
805
  successText,
@@ -786,42 +814,127 @@ var runGeneratorActions = (generator) => (answers) => withSpinner(
786
814
  "Failed to create workspace files.",
787
815
  generator.runActions(answers)
788
816
  ).map(() => answers);
789
- var displaySummary = (answers) => {
790
- const { csp, repoName, repoOwner } = answers;
817
+ var displaySummary = (initResult) => {
818
+ const { csp, pr, repository } = initResult;
791
819
  console.log(chalk.green.bold("\nWorkspace created successfully!"));
792
- console.log(`- Name: ${chalk.cyan(repoName)}`);
793
- console.log(`- Cloud Service Provider: ${chalk.cyan(csp)}`);
794
- const cspLocation = csp === "azure" ? answers.azureLocation : answers.awsRegion;
795
- console.log(`- CSP location: ${chalk.cyan(cspLocation)}`);
796
- console.log(
797
- `- GitHub Repository: ${chalk.cyan(`https://github.com/${repoOwner}/${repoName}`)}
820
+ console.log(`- Cloud Service Provider: ${chalk.cyan(csp.name)}`);
821
+ console.log(`- CSP location: ${chalk.cyan(csp.location)}`);
822
+ if (repository) {
823
+ console.log(`- Name: ${chalk.cyan(repository.name)}`);
824
+ console.log(`- GitHub Repository: ${chalk.cyan(repository.url)}
825
+ `);
826
+ } else {
827
+ console.log(
828
+ chalk.yellow(
829
+ `
830
+ \u26A0\uFE0F GitHub repository may not have been created automatically.`
831
+ )
832
+ );
833
+ }
834
+ if (pr) {
835
+ console.log(chalk.green.bold("\nNext Steps:"));
836
+ console.log(
837
+ `1. Review the Pull Request in the GitHub repository: ${chalk.underline(pr.url)}`
838
+ );
839
+ console.log(
840
+ `2. Visit ${chalk.underline("https://dx.pagopa.it/getting-started")} to deploy your first project
798
841
  `
799
- );
800
- console.log(chalk.green.bold("\nNext Steps:"));
801
- console.log(`1. Review the Pull Request in the GitHub repository.`);
802
- console.log(
803
- `2. Wait for the approval on eng-azure-authorization and then merge both PRs.`
804
- );
805
- console.log(
806
- `3. Visit ${chalk.underline("https://dx.pagopa.it/getting-started")} to deploy your first project
842
+ );
843
+ } else {
844
+ console.log(
845
+ chalk.yellow(`
846
+ \u26A0\uFE0F There was an error during Pull Request creation.`)
847
+ );
848
+ console.log(
849
+ `Please, manually create a Pull Request in the GitHub repository to review the scaffolded code.
807
850
  `
808
- );
851
+ );
852
+ }
809
853
  };
810
- var checkGhCliIsInstalled = (text, successText, failText) => withSpinner(text, successText, failText, $2`gh --version`);
811
- var checkGhCliIsLoggedIn = (text, successText, failText) => withSpinner(text, successText, failText, $2`gh auth status`);
812
- var checkPreconditions = () => checkGhCliIsInstalled(
813
- "Checking GitHub CLI is installed...",
814
- "GitHub CLI is installed!",
815
- "GitHub CLI is not installed."
816
- ).andThen(
817
- () => checkGhCliIsLoggedIn(
818
- "Checking GitHub CLI login...",
819
- "GitHub CLI is logged in!",
820
- "GitHub CLI is not logged in."
821
- )
822
- ).map(() => void 0);
823
- var handleNewGitHubRepository = (answers) => okAsync2(answers);
824
- var makeInitCommand = () => new Command4().name("init").description(
854
+ var checkTerraformCliIsInstalled = (text, successText, failText) => withSpinner(text, successText, failText, tf$`terraform -version`);
855
+ var checkPreconditions = () => checkTerraformCliIsInstalled(
856
+ "Checking Terraform CLI is installed...",
857
+ "Terraform CLI is installed!",
858
+ "Terraform CLI is not installed."
859
+ );
860
+ var createRemoteRepository = ({
861
+ repoName,
862
+ repoOwner
863
+ }) => {
864
+ const cwd2 = path.resolve(repoName, "infra", "repository");
865
+ const applyTerraform = async () => {
866
+ await tf$({ cwd: cwd2 })`terraform init`;
867
+ await tf$({ cwd: cwd2 })`terraform apply -auto-approve`;
868
+ };
869
+ return withSpinner(
870
+ "Creating GitHub repository...",
871
+ "GitHub repository created successfully!",
872
+ "Failed to create GitHub repository.",
873
+ applyTerraform()
874
+ ).map(() => new Repository(repoName, repoOwner));
875
+ };
876
+ var initializeGitRepository = (repository) => {
877
+ const cwd2 = path.resolve(repository.name);
878
+ const branchName = "features/scaffold-workspace";
879
+ const git$ = $3({
880
+ cwd: cwd2,
881
+ shell: true
882
+ });
883
+ const pushToOrigin = async () => {
884
+ await git$`git init`;
885
+ await git$`git add README.md`;
886
+ await git$`git commit --no-gpg-sign -m "Create README.md"`;
887
+ await git$`git branch -M main`;
888
+ await git$`git remote add origin ${repository.ssh}`;
889
+ await git$`git push -u origin main`;
890
+ await git$`git switch -c ${branchName}`;
891
+ await git$`git add .`;
892
+ await git$`git commit --no-gpg-sign -m "Scaffold workspace"`;
893
+ await git$`git push -u origin ${branchName}`;
894
+ };
895
+ return withSpinner(
896
+ "Pushing code to GitHub...",
897
+ "Code pushed to GitHub successfully!",
898
+ "Failed to push code to GitHub.",
899
+ pushToOrigin()
900
+ ).map(() => ({ branchName, repository }));
901
+ };
902
+ var handleNewGitHubRepository = (octokit2) => (answers) => createRemoteRepository(answers).andThen(initializeGitRepository).andThen(
903
+ (localWorkspace) => createPullRequest(octokit2)(localWorkspace).map((pr) => ({
904
+ pr,
905
+ repository: localWorkspace.repository
906
+ }))
907
+ );
908
+ var makeInitResult = (answers, { pr, repository }) => {
909
+ const csp = {
910
+ location: answers.csp === "azure" ? answers.azureLocation : answers.awsRegion,
911
+ name: answers.csp
912
+ };
913
+ return {
914
+ csp,
915
+ pr,
916
+ repository
917
+ };
918
+ };
919
+ var createPullRequest = (octokit2) => ({
920
+ branchName,
921
+ repository
922
+ }) => withSpinner(
923
+ "Creating Pull Request...",
924
+ "Pull Request created successfully!",
925
+ "Failed to create Pull Request.",
926
+ octokit2.rest.pulls.create({
927
+ base: "main",
928
+ body: "This PR contains the scaffolded monorepo structure.",
929
+ head: branchName,
930
+ owner: repository.owner,
931
+ repo: repository.name,
932
+ title: "Scaffold repository"
933
+ })
934
+ ).map(({ data }) => ({ url: data.html_url })).orElse(() => okAsync2(void 0));
935
+ var makeInitCommand = ({
936
+ octokit: octokit2
937
+ }) => new Command4().name("init").description(
825
938
  "Command to initialize resources (like projects, subscriptions, ...)"
826
939
  ).addCommand(
827
940
  new Command4("project").description("Initialize a new monorepo project").action(async function() {
@@ -830,7 +943,11 @@ var makeInitCommand = () => new Command4().name("init").description(
830
943
  // Ask the user the questions defined in the plop generator
831
944
  getPrompts(generator).andThen(decode(answersSchema)).andThen(validateAnswers).andThen(runGeneratorActions(generator))
832
945
  )
833
- ).andThen(handleNewGitHubRepository).match(displaySummary, exitWithError(this));
946
+ ).andThen(
947
+ (answers) => handleNewGitHubRepository(octokit2)(answers).map(
948
+ (repoPr) => makeInitResult(answers, repoPr)
949
+ )
950
+ ).match(displaySummary, exitWithError(this));
834
951
  })
835
952
  );
836
953
 
@@ -867,10 +984,10 @@ var makeSavemoneyCommand = () => new Command5("savemoney").description(
867
984
  // src/adapters/commander/index.ts
868
985
  var makeCli = (deps2, config2, cliDeps) => {
869
986
  const program2 = new Command6();
870
- program2.name("dx").description("The CLI for DX-Platform").version("0.13.0");
987
+ program2.name("dx").description("The CLI for DX-Platform").version("0.14.1");
871
988
  program2.addCommand(makeDoctorCommand(deps2, config2));
872
989
  program2.addCommand(makeCodemodCommand(cliDeps));
873
- program2.addCommand(makeInitCommand());
990
+ program2.addCommand(makeInitCommand(deps2));
874
991
  program2.addCommand(makeSavemoneyCommand());
875
992
  program2.addCommand(makeInfoCommand(deps2));
876
993
  return program2;
@@ -899,7 +1016,7 @@ import { join as join2 } from "path";
899
1016
  import * as process3 from "process";
900
1017
 
901
1018
  // src/adapters/node/fs/file-reader.ts
902
- import { ResultAsync as ResultAsync6 } from "neverthrow";
1019
+ import { ResultAsync as ResultAsync7 } from "neverthrow";
903
1020
  import fs3 from "fs/promises";
904
1021
 
905
1022
  // src/adapters/node/json/index.ts
@@ -910,14 +1027,14 @@ var parseJson = Result2.fromThrowable(
910
1027
  );
911
1028
 
912
1029
  // src/adapters/node/fs/file-reader.ts
913
- var readFile2 = (filePath) => ResultAsync6.fromPromise(
1030
+ var readFile2 = (filePath) => ResultAsync7.fromPromise(
914
1031
  fs3.readFile(filePath, "utf-8"),
915
1032
  (cause) => new Error(`Failed to read file: ${filePath}`, { cause })
916
1033
  );
917
1034
  var readFileAndDecode = (filePath, schema) => readFile2(filePath).andThen(parseJson).andThen(decode(schema));
918
- var fileExists = (path2) => ResultAsync6.fromPromise(
919
- fs3.stat(path2),
920
- () => new Error(`${path2} not found.`)
1035
+ var fileExists = (path3) => ResultAsync7.fromPromise(
1036
+ fs3.stat(path3),
1037
+ () => new Error(`${path3} not found.`)
921
1038
  ).map(() => true);
922
1039
 
923
1040
  // src/adapters/node/package-json.ts
@@ -946,8 +1063,8 @@ var makePackageJsonReader = () => ({
946
1063
 
947
1064
  // src/adapters/node/repository.ts
948
1065
  import * as glob from "glob";
949
- import { okAsync as okAsync3, ResultAsync as ResultAsync7 } from "neverthrow";
950
- import * as path from "path";
1066
+ import { okAsync as okAsync3, ResultAsync as ResultAsync8 } from "neverthrow";
1067
+ import * as path2 from "path";
951
1068
  import { z as z3 } from "zod/v4";
952
1069
 
953
1070
  // src/adapters/yaml/index.ts
@@ -960,14 +1077,14 @@ var parseYaml = Result3.fromThrowable(
960
1077
 
961
1078
  // src/adapters/node/repository.ts
962
1079
  var findRepositoryRoot = (dir = process.cwd()) => {
963
- const gitPath = path.join(dir, ".git");
1080
+ const gitPath = path2.join(dir, ".git");
964
1081
  return fileExists(gitPath).mapErr(
965
1082
  () => new Error(
966
1083
  "Could not find repository root. Make sure to have the repo initialized."
967
1084
  )
968
1085
  ).map(() => dir);
969
1086
  };
970
- var resolveWorkspacePattern = (repoRoot, pattern) => ResultAsync7.fromPromise(
1087
+ var resolveWorkspacePattern = (repoRoot, pattern) => ResultAsync8.fromPromise(
971
1088
  // For now it is not possible to use the fs.glob function (from node:fs/promises)
972
1089
  // because it is not possible to run it on Node 20.x
973
1090
  glob.glob(pattern, { cwd: repoRoot }),
@@ -977,10 +1094,10 @@ var resolveWorkspacePattern = (repoRoot, pattern) => ResultAsync7.fromPromise(
977
1094
  ).map(
978
1095
  (subDirectories) => (
979
1096
  // Create the absolute path to the subdirectory
980
- subDirectories.map((directory) => path.join(repoRoot, directory))
1097
+ subDirectories.map((directory) => path2.join(repoRoot, directory))
981
1098
  )
982
1099
  );
983
- var getWorkspaces = (repoRoot) => readFile2(path.join(repoRoot, "pnpm-workspace.yaml")).andThen(parseYaml).andThen(
1100
+ var getWorkspaces = (repoRoot) => readFile2(path2.join(repoRoot, "pnpm-workspace.yaml")).andThen(parseYaml).andThen(
984
1101
  (obj) => (
985
1102
  // If no packages are defined, go on with an empty array
986
1103
  decode(z3.object({ packages: z3.array(z3.string()) }))(obj).orElse(
@@ -990,12 +1107,12 @@ var getWorkspaces = (repoRoot) => readFile2(path.join(repoRoot, "pnpm-workspace.
990
1107
  ).andThen(
991
1108
  ({ packages }) => (
992
1109
  // For every package pattern in the pnpm-workspace.yaml file, get the list of subdirectories
993
- ResultAsync7.combine(
1110
+ ResultAsync8.combine(
994
1111
  packages.map((pattern) => resolveWorkspacePattern(repoRoot, pattern))
995
1112
  ).map((workspacesList) => workspacesList.flat()).andThen((workspaceFolders) => {
996
1113
  const workspaceResults = workspaceFolders.map(
997
1114
  (nodeWorkspaceDirectory) => readFileAndDecode(
998
- path.join(nodeWorkspaceDirectory, "package.json"),
1115
+ path2.join(nodeWorkspaceDirectory, "package.json"),
999
1116
  packageJsonSchema
1000
1117
  ).map(
1001
1118
  ({ name }) => (
@@ -1004,7 +1121,7 @@ var getWorkspaces = (repoRoot) => readFile2(path.join(repoRoot, "pnpm-workspace.
1004
1121
  )
1005
1122
  )
1006
1123
  );
1007
- return ResultAsync7.combine(workspaceResults);
1124
+ return ResultAsync8.combine(workspaceResults);
1008
1125
  })
1009
1126
  )
1010
1127
  );
@@ -1023,19 +1140,19 @@ var getConfig = () => ({
1023
1140
  });
1024
1141
 
1025
1142
  // src/use-cases/apply-codemod.ts
1026
- import { errAsync, okAsync as okAsync4, ResultAsync as ResultAsync8 } from "neverthrow";
1143
+ import { errAsync, okAsync as okAsync4, ResultAsync as ResultAsync9 } from "neverthrow";
1027
1144
  var getCodemodById = (registry2, id) => registry2.getById(id).andThen(
1028
1145
  (codemod) => codemod ? okAsync4(codemod) : errAsync(new Error(`Codemod with id ${id} not found`))
1029
1146
  );
1030
- var safeGetInfo = (getInfo2) => ResultAsync8.fromPromise(
1147
+ var safeGetInfo = (getInfo2) => ResultAsync9.fromPromise(
1031
1148
  getInfo2(),
1032
1149
  (error) => new Error("Failed to get info", { cause: error })
1033
1150
  );
1034
- var applyCodemodById = (registry2, getInfo2) => (id) => ResultAsync8.combine([
1151
+ var applyCodemodById = (registry2, getInfo2) => (id) => ResultAsync9.combine([
1035
1152
  safeGetInfo(getInfo2),
1036
1153
  getCodemodById(registry2, id)
1037
1154
  ]).andThen(
1038
- ([info, codemod]) => ResultAsync8.fromPromise(codemod.apply(info), (error) => {
1155
+ ([info, codemod]) => ResultAsync9.fromPromise(codemod.apply(info), (error) => {
1039
1156
  const message = error instanceof Error ? `: ${error.message}` : "";
1040
1157
  return new Error("Failed to apply codemod" + message, { cause: error });
1041
1158
  })
@@ -1066,7 +1183,11 @@ await configure({
1066
1183
  var repositoryReader = makeRepositoryReader();
1067
1184
  var packageJsonReader = makePackageJsonReader();
1068
1185
  var validationReporter = makeValidationReporter();
1186
+ var octokit = new Octokit2({
1187
+ auth: process.env.GITHUB_TOKEN
1188
+ });
1069
1189
  var deps = {
1190
+ octokit,
1070
1191
  packageJsonReader,
1071
1192
  repositoryReader,
1072
1193
  validationReporter
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pagopa/dx-cli",
3
- "version": "0.13.0",
3
+ "version": "0.14.1",
4
4
  "type": "module",
5
5
  "description": "A CLI useful to manage DX tools.",
6
6
  "repository": {
@@ -19,7 +19,7 @@
19
19
  "dx": "./bin/index.js"
20
20
  },
21
21
  "dependencies": {
22
- "@logtape/logtape": "^1.2.2",
22
+ "@logtape/logtape": "^1.3.4",
23
23
  "chalk": "^5.6.2",
24
24
  "commander": "^14.0.2",
25
25
  "core-js": "^3.47.0",
@@ -29,19 +29,19 @@
29
29
  "node-plop": "^0.32.3",
30
30
  "octokit": "^5.0.5",
31
31
  "ora": "^9.0.0",
32
- "replace-in-file": "^8.3.0",
32
+ "replace-in-file": "^8.4.0",
33
33
  "semver": "^7.7.2",
34
34
  "yaml": "^2.8.2",
35
- "zod": "^4.1.13",
35
+ "zod": "^4.2.1",
36
36
  "@pagopa/dx-savemoney": "^0.1.4",
37
- "@pagopa/monorepo-generator": "^0.13.0"
37
+ "@pagopa/monorepo-generator": "^0.14.1"
38
38
  },
39
39
  "devDependencies": {
40
40
  "@tsconfig/node22": "22.0.2",
41
41
  "@types/node": "^22.19.1",
42
42
  "@types/semver": "^7.7.1",
43
43
  "@vitest/coverage-v8": "^3.2.4",
44
- "eslint": "^9.39.1",
44
+ "eslint": "^9.39.2",
45
45
  "memfs": "^4.51.1",
46
46
  "prettier": "3.6.2",
47
47
  "tsup": "^8.5.1",