@pagopa/dx-cli 0.10.3 → 0.11.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 +76 -6
  2. package/bin/index.js +104 -106
  3. package/package.json +15 -15
package/README.md CHANGED
@@ -18,14 +18,27 @@ The DX CLI is a command-line tool designed to help developers manage and validat
18
18
 
19
19
  ## ✨ Features
20
20
 
21
- - **Repository Validation**: Verify repository setup against DevEx guidelines
22
- - **Monorepo Script Checking**: Validate that required scripts are present in package.json
21
+ - **Repository Validation**: Verify repository setup against DevEx guidelines with the `doctor` command
22
+ - **Code Migrations**: Apply automated migration scripts (codemods) to update code and configurations
23
+ - **Project Initialization**: Bootstrap new monorepo projects with standardized structure
24
+ - **Cost Optimization**: Analyze Azure subscriptions to identify unused or underutilized resources
25
+ - **Project Information**: Display comprehensive information about your project setup and tools
23
26
  - **Developer Experience Optimization**: Ensure consistent development practices across projects
24
27
 
25
28
  ## 🚀 Installation
26
29
 
27
- > [!NOTE]
28
- > The CLI is currently only available locally and is not yet distributed through package managers.
30
+ Install the CLI globally using your preferred package manager:
31
+
32
+ ```bash
33
+ # Using npm
34
+ npm install -g @pagopa/dx-cli
35
+
36
+ # Using yarn
37
+ yarn global add @pagopa/dx-cli
38
+
39
+ # Using pnpm
40
+ pnpm add -g @pagopa/dx-cli
41
+ ```
29
42
 
30
43
  ### From Source (Development)
31
44
 
@@ -34,11 +47,19 @@ The DX CLI is a command-line tool designed to help developers manage and validat
34
47
  git clone https://github.com/pagopa/dx.git
35
48
  cd dx
36
49
 
37
- # Install dependencies
50
+ # Install dependencies (using npm)
51
+ npm install
52
+
53
+ # Or using yarn
38
54
  yarn install
39
55
 
56
+ # Or using pnpm
57
+ pnpm install
58
+
40
59
  # Build the CLI
41
- yarn build
60
+ npm run build
61
+ # Or: yarn build
62
+ # Or: pnpm build
42
63
 
43
64
  # Run the CLI
44
65
  node ./apps/cli/bin/index.js --help
@@ -71,6 +92,55 @@ Checking monorepo scripts...
71
92
  ✅ Monorepo scripts are correctly set up
72
93
  ```
73
94
 
95
+ #### `codemod`
96
+
97
+ Manage and apply migration scripts (codemods) to the repository.
98
+
99
+ ```bash
100
+ # List available codemods
101
+ dx codemod list
102
+
103
+ # Apply a specific codemod by ID
104
+ dx codemod apply <id>
105
+ ```
106
+
107
+ This command helps you:
108
+
109
+ - View all available migration scripts for your repository
110
+ - Apply automated code transformations to keep your codebase up to date
111
+ - Migrate configurations and code patterns to newer standards
112
+
113
+ #### `init`
114
+
115
+ Initialize resources such as new projects with standardized structure.
116
+
117
+ ```bash
118
+ # Initialize a new monorepo project
119
+ dx init project
120
+ ```
121
+
122
+ This command will:
123
+
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
128
+
129
+ #### `info`
130
+
131
+ Display comprehensive information about your project setup and tools.
132
+
133
+ ```bash
134
+ dx info
135
+ ```
136
+
137
+ This command provides:
138
+
139
+ - Current project configuration details
140
+ - Installed tool versions
141
+ - Repository metadata
142
+ - Development environment information
143
+
74
144
  #### `savemoney`
75
145
 
76
146
  Analyze Azure subscriptions to identify unused or underutilized resources that could be costing you money.
package/bin/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  // src/index.ts
4
4
  import "core-js/actual/set/index.js";
5
- import { configure, getConsoleSink, getLogger as getLogger8 } from "@logtape/logtape";
5
+ import { configure, getConsoleSink } from "@logtape/logtape";
6
6
 
7
7
  // src/adapters/codemods/registry.ts
8
8
  import { okAsync } from "neverthrow";
@@ -40,9 +40,9 @@ var getLatestCommitSha = async (owner, repo, ref = "main") => {
40
40
  return response.data.sha;
41
41
  };
42
42
  var getLatestCommitShaOrRef = async (owner, repo, ref = "main") => {
43
- const logger2 = getLogger(["dx-cli", "codemod"]);
43
+ const logger = getLogger(["dx-cli", "codemod"]);
44
44
  return getLatestCommitSha(owner, repo, ref).catch(() => {
45
- logger2.warn(
45
+ logger.warn(
46
46
  "Failed to fetch the latest commit from {owner}/{repo}, fallback to {fallback}",
47
47
  { fallback: ref, owner, repo }
48
48
  );
@@ -59,7 +59,7 @@ var isChildOf = (path2, key) => {
59
59
 
60
60
  // src/adapters/codemods/update-code-review.ts
61
61
  var updateJSCodeReviewJob = (sha) => (workflow, filename) => {
62
- const logger2 = getLogger2(["dx-cli", "codemod"]);
62
+ const logger = getLogger2(["dx-cli", "codemod"]);
63
63
  const document = YAML2.parseDocument(workflow);
64
64
  let updated = false;
65
65
  YAML2.visit(document, {
@@ -86,7 +86,7 @@ var updateJSCodeReviewJob = (sha) => (workflow, filename) => {
86
86
  }
87
87
  });
88
88
  if (updated) {
89
- logger2.info("Workflow {filename} updated", {
89
+ logger.info("Workflow {filename} updated", {
90
90
  filename
91
91
  });
92
92
  return YAML2.stringify(document);
@@ -95,7 +95,7 @@ var updateJSCodeReviewJob = (sha) => (workflow, filename) => {
95
95
  };
96
96
  var updateCodeReview = {
97
97
  apply: async () => {
98
- const logger2 = getLogger2(["dx-cli", "codemod"]);
98
+ const logger = getLogger2(["dx-cli", "codemod"]);
99
99
  const owner = "pagopa";
100
100
  const repo = "dx";
101
101
  return getLatestCommitSha(owner, repo).then(async (sha) => {
@@ -105,7 +105,7 @@ var updateCodeReview = {
105
105
  processor: updateJSCodeReviewJob(sha)
106
106
  });
107
107
  }).catch(() => {
108
- logger2.error(
108
+ logger.error(
109
109
  "Failed to fetch the latest commit sha from {repository}",
110
110
  {
111
111
  repository: `${owner}/${repo}`
@@ -122,8 +122,8 @@ import { getLogger as getLogger3 } from "@logtape/logtape";
122
122
  import { replaceInFile as replaceInFile2 } from "replace-in-file";
123
123
  import YAML3 from "yaml";
124
124
  var migrateWorkflow = (sha) => (workflow, filename) => {
125
- const logger2 = getLogger3(["dx-cli", "codemod"]);
126
- logger2.debug("Processing {filename} file", { filename });
125
+ const logger = getLogger3(["dx-cli", "codemod"]);
126
+ logger.debug("Processing {filename} file", { filename });
127
127
  const document = YAML3.parseDocument(workflow);
128
128
  let updated = false;
129
129
  YAML3.visit(document, {
@@ -139,7 +139,7 @@ var migrateWorkflow = (sha) => (workflow, filename) => {
139
139
  if (typeof uses === "string" && uses.match(
140
140
  /^pagopa\/dx\/.github\/workflows\/(web|function)_app_deploy/
141
141
  )) {
142
- logger2.debug("Adding disable_auto_staging_deploy");
142
+ logger.debug("Adding disable_auto_staging_deploy");
143
143
  map.addIn(["with", "disable_auto_staging_deploy"], true);
144
144
  map.set("permissions", {
145
145
  attestations: "write",
@@ -156,17 +156,17 @@ var migrateWorkflow = (sha) => (workflow, filename) => {
156
156
  if (YAML3.isScalar(pair.key)) {
157
157
  if (pair.key.value === "function_app_name") {
158
158
  updated = true;
159
- logger2.debug("Updating function_app_name to web_app_name");
159
+ logger.debug("Updating function_app_name to web_app_name");
160
160
  return new YAML3.Pair("web_app_name", pair.value);
161
161
  }
162
162
  if (pair.key.value === "use_staging_slot") {
163
163
  updated = true;
164
- logger2.debug("Removing use_staging_slot");
164
+ logger.debug("Removing use_staging_slot");
165
165
  return YAML3.visit.REMOVE;
166
166
  }
167
167
  if (pair.key.value === "uses") {
168
168
  updated = true;
169
- logger2.debug("Updating uses value");
169
+ logger.debug("Updating uses value");
170
170
  return new YAML3.Pair(
171
171
  "uses",
172
172
  `pagopa/dx/.github/workflows/release-azure-appsvc.yaml@${sha}`
@@ -176,12 +176,12 @@ var migrateWorkflow = (sha) => (workflow, filename) => {
176
176
  }
177
177
  });
178
178
  if (updated) {
179
- logger2.info("Workflow {filename} updated", {
179
+ logger.info("Workflow {filename} updated", {
180
180
  filename
181
181
  });
182
182
  return YAML3.stringify(document);
183
183
  }
184
- logger2.debug("No changes applied to {filename}", { filename });
184
+ logger.debug("No changes applied to {filename}", { filename });
185
185
  return workflow;
186
186
  };
187
187
  var useAzureAppsvc = {
@@ -245,8 +245,8 @@ async function extractPackageExtensions() {
245
245
  return void 0;
246
246
  }
247
247
  async function preparePackageJsonForPnpm() {
248
- const packageJson2 = await fs.readFile("package.json", "utf-8");
249
- const manifest = JSON.parse(packageJson2);
248
+ const packageJson = await fs.readFile("package.json", "utf-8");
249
+ const manifest = JSON.parse(packageJson);
250
250
  let workspaces = [];
251
251
  if (Object.hasOwn(manifest, "packageManager")) {
252
252
  delete manifest.packageManager;
@@ -271,8 +271,8 @@ async function removeFiles(...files) {
271
271
  );
272
272
  }
273
273
  async function replacePMOccurrences() {
274
- const logger2 = getLogger4(["dx-cli", "codemod"]);
275
- logger2.info("Replacing yarn and npm occurrences in files...");
274
+ const logger = getLogger4(["dx-cli", "codemod"]);
275
+ logger.info("Replacing yarn and npm occurrences in files...");
276
276
  const results = await replaceInFile3({
277
277
  allowEmptyPaths: true,
278
278
  files: ["**/*.json", "**/*.md", "**/Dockerfile", "**/docker-compose.yml"],
@@ -300,11 +300,11 @@ async function replacePMOccurrences() {
300
300
  (acc, file) => file.hasChanged ? acc + 1 : acc,
301
301
  0
302
302
  );
303
- logger2.info("Replaced yarn occurrences in {count} files", { count });
303
+ logger.info("Replaced yarn occurrences in {count} files", { count });
304
304
  }
305
305
  async function updateDXWorkflows() {
306
- const logger2 = getLogger4(["dx-cli", "codemod"]);
307
- logger2.info("Updating Github Workflows workflows...");
306
+ const logger = getLogger4(["dx-cli", "codemod"]);
307
+ logger.info("Updating Github Workflows workflows...");
308
308
  const sha = await getLatestCommitShaOrRef("pagopa", "dx");
309
309
  const results = await replaceInFile3({
310
310
  allowEmptyPaths: true,
@@ -332,9 +332,9 @@ var apply = async (info) => {
332
332
  throw new Error("Project is already using pnpm");
333
333
  }
334
334
  const pm = info.packageManager === "yarn" ? new Yarn() : new NPM();
335
- const logger2 = getLogger4(["dx-cli", "codemod"]);
335
+ const logger = getLogger4(["dx-cli", "codemod"]);
336
336
  const localWorkspaces = await pm.listWorkspaces();
337
- logger2.info("Using the {protocol} protocol for local dependencies", {
337
+ logger.info("Using the {protocol} protocol for local dependencies", {
338
338
  protocol: "workspace:"
339
339
  });
340
340
  if (localWorkspaces.length > 0) {
@@ -345,17 +345,17 @@ var apply = async (info) => {
345
345
  to: localWorkspaces.map((ws) => `"${ws}": "workspace:^"`)
346
346
  });
347
347
  }
348
- logger2.info("Remove unused fields from {file}", {
348
+ logger.info("Remove unused fields from {file}", {
349
349
  file: "package.json"
350
350
  });
351
351
  const workspaces = await preparePackageJsonForPnpm();
352
352
  const packageExtensions = info.packageManager === "yarn" ? await extractPackageExtensions() : void 0;
353
- logger2.info("Create {file}", {
353
+ logger.info("Create {file}", {
354
354
  file: "pnpm-workspace.yaml"
355
355
  });
356
356
  await writePnpmWorkspaceFile(workspaces, packageExtensions);
357
357
  await $`corepack pnpm@latest add --config pnpm-plugin-pagopa`;
358
- logger2.info("Remove node_modules and yarn files");
358
+ logger.info("Remove node_modules and yarn files");
359
359
  await removeFiles(
360
360
  ".yarnrc",
361
361
  ".yarnrc.yml",
@@ -367,22 +367,22 @@ var apply = async (info) => {
367
367
  );
368
368
  const stat2 = await fs.stat(pm.lockFileName);
369
369
  if (stat2.isFile()) {
370
- logger2.info("Importing {source} to {target}", {
370
+ logger.info("Importing {source} to {target}", {
371
371
  source: pm.lockFileName,
372
372
  target: "pnpm-lock.yaml"
373
373
  });
374
374
  await $`corepack pnpm@latest import ${pm.lockFileName}`;
375
375
  await removeFiles(pm.lockFileName);
376
376
  } else {
377
- logger2.info("No {source} file found, skipping import.", {
377
+ logger.info("No {source} file found, skipping import.", {
378
378
  source: pm.lockFileName
379
379
  });
380
380
  }
381
381
  await replacePMOccurrences();
382
382
  await updateDXWorkflows();
383
- logger2.info("Adding pnpm store to .gitignore...");
383
+ logger.info("Adding pnpm store to .gitignore...");
384
384
  await fs.appendFile(".gitignore", "\n\n# PNPM\n.pnpm-store");
385
- logger2.info("Setting pnpm as the package manager...");
385
+ logger.info("Setting pnpm as the package manager...");
386
386
  await $`corepack use pnpm@latest`;
387
387
  };
388
388
  var use_pnpm_default = {
@@ -415,9 +415,9 @@ var makeCodemodCommand = ({
415
415
  })
416
416
  ).addCommand(
417
417
  new Command("apply").argument("<id>", "The id of the codemod to apply").description("Apply migration scripts to the repository").action(async function(id) {
418
- const logger2 = getLogger5(["dx-cli", "codemod"]);
418
+ const logger = getLogger5(["dx-cli", "codemod"]);
419
419
  await applyCodemodById2(id).andTee(() => {
420
- logger2.info("Codemod applied \u2705");
420
+ logger.info("Codemod applied \u2705");
421
421
  }).orTee((error) => this.error(error.message));
422
422
  })
423
423
  );
@@ -468,12 +468,10 @@ var findMissingScripts = (availableScripts, requiredScripts) => {
468
468
  const requiredScriptNames = new Set(requiredScripts.keys());
469
469
  return requiredScriptNames.difference(availableScriptNames);
470
470
  };
471
- var checkMonorepoScripts = async (dependencies, config2) => {
471
+ var checkMonorepoScripts = async (dependencies, repositoryRoot) => {
472
472
  const { packageJsonReader: packageJsonReader2 } = dependencies;
473
473
  const checkName = "Monorepo Scripts";
474
- const scriptsResult = await packageJsonReader2.getScripts(
475
- config2.repository.root
476
- );
474
+ const scriptsResult = await packageJsonReader2.getScripts(repositoryRoot);
477
475
  if (scriptsResult.isErr()) {
478
476
  return err(scriptsResult.error);
479
477
  }
@@ -509,11 +507,11 @@ var isVersionValid = (version, minVersion) => {
509
507
  }
510
508
  return semverGte(dependencySemVer, minAcceptedSemVer);
511
509
  };
512
- var checkPreCommitConfig = async (dependencies, config2) => {
510
+ var checkPreCommitConfig = async (dependencies, repositoryRoot) => {
513
511
  const { repositoryReader: repositoryReader2 } = dependencies;
514
512
  const checkName = "Pre-commit Configuration";
515
513
  const preCommitResult = await repositoryReader2.fileExists(
516
- fs2.join(config2.repository.root, ".pre-commit-config.yaml")
514
+ fs2.join(repositoryRoot, ".pre-commit-config.yaml")
517
515
  );
518
516
  if (preCommitResult.isOk() && preCommitResult.value) {
519
517
  return ok2({
@@ -529,12 +527,11 @@ var checkPreCommitConfig = async (dependencies, config2) => {
529
527
  isValid: false
530
528
  });
531
529
  };
532
- var checkTurboConfig = async (dependencies, config2) => {
530
+ var checkTurboConfig = async (dependencies, repositoryRoot, config2) => {
533
531
  const { packageJsonReader: packageJsonReader2, repositoryReader: repositoryReader2 } = dependencies;
534
532
  const checkName = "Turbo Configuration";
535
- const repoRoot2 = config2.repository.root;
536
533
  const turboResult = await repositoryReader2.fileExists(
537
- fs2.join(repoRoot2, "turbo.json")
534
+ fs2.join(repositoryRoot, "turbo.json")
538
535
  );
539
536
  if (turboResult.isErr()) {
540
537
  return ok2({
@@ -544,7 +541,7 @@ var checkTurboConfig = async (dependencies, config2) => {
544
541
  });
545
542
  }
546
543
  const dependenciesResult = await packageJsonReader2.getDependencies(
547
- repoRoot2,
544
+ repositoryRoot,
548
545
  "dev"
549
546
  );
550
547
  if (dependenciesResult.isErr()) {
@@ -613,22 +610,36 @@ var checkWorkspaces = async (dependencies, monorepoDir) => {
613
610
  };
614
611
 
615
612
  // src/domain/doctor.ts
616
- var runDoctor = (dependencies, config2) => {
613
+ var runDoctor = async (dependencies, config2) => {
614
+ const repoRootResult = await dependencies.repositoryReader.findRepositoryRoot();
615
+ if (repoRootResult.isErr()) {
616
+ return {
617
+ checks: [
618
+ {
619
+ checkName: "Repository Detection",
620
+ errorMessage: "Could not find repository root. Make sure to run this command inside a Git repository.",
621
+ isValid: false
622
+ }
623
+ ],
624
+ hasErrors: true
625
+ };
626
+ }
627
+ const repositoryRoot = repoRootResult.value;
617
628
  const doctorChecks = [
618
629
  ResultAsync3.fromPromise(
619
- checkPreCommitConfig(dependencies, config2),
630
+ checkPreCommitConfig(dependencies, repositoryRoot),
620
631
  () => new Error("Error checking pre-commit configuration")
621
632
  ),
622
633
  ResultAsync3.fromPromise(
623
- checkTurboConfig(dependencies, config2),
634
+ checkTurboConfig(dependencies, repositoryRoot, config2),
624
635
  () => new Error("Error checking Turbo configuration")
625
636
  ),
626
637
  ResultAsync3.fromPromise(
627
- checkMonorepoScripts(dependencies, config2),
638
+ checkMonorepoScripts(dependencies, repositoryRoot),
628
639
  () => new Error("Error checking monorepo scripts")
629
640
  ),
630
641
  ResultAsync3.fromPromise(
631
- checkWorkspaces(dependencies, config2.repository.root),
642
+ checkWorkspaces(dependencies, repositoryRoot),
632
643
  () => new Error("Error checking monorepo scripts")
633
644
  )
634
645
  ];
@@ -675,50 +686,56 @@ import { Command as Command3 } from "commander";
675
686
  // src/domain/info.ts
676
687
  import { getLogger as getLogger6 } from "@logtape/logtape";
677
688
  import { join } from "path";
678
- var detectFromLockFile = async (dependencies, config2) => {
689
+ var detectFromLockFile = async (dependencies, repositoryRoot) => {
679
690
  const { repositoryReader: repositoryReader2 } = dependencies;
680
- const repoRoot2 = config2.repository.root;
681
691
  const pnpmResult = await repositoryReader2.fileExists(
682
- join(repoRoot2, "pnpm-lock.yaml")
692
+ join(repositoryRoot, "pnpm-lock.yaml")
683
693
  );
684
694
  if (pnpmResult.isOk() && pnpmResult.value) return "pnpm";
685
695
  const yarnResult = await repositoryReader2.fileExists(
686
- join(repoRoot2, "yarn.lock")
696
+ join(repositoryRoot, "yarn.lock")
687
697
  );
688
698
  if (yarnResult.isOk() && yarnResult.value) return "yarn";
689
699
  const npmResult = await repositoryReader2.fileExists(
690
- join(repoRoot2, "package-lock.json")
700
+ join(repositoryRoot, "package-lock.json")
691
701
  );
692
702
  if (npmResult.isOk() && npmResult.value) return "npm";
693
703
  return void 0;
694
704
  };
695
- var detectPackageManager = async (dependencies, config2) => {
696
- const packageManager = dependencies.packageJson.packageManager ?? await detectFromLockFile(dependencies, config2);
705
+ var detectPackageManager = async (dependencies, repositoryRoot) => {
706
+ const packageJsonResult = await dependencies.packageJsonReader.readPackageJson(repositoryRoot);
707
+ const packageManager = packageJsonResult.map((pkg) => pkg.packageManager).unwrapOr(void 0) ?? await detectFromLockFile(dependencies, repositoryRoot);
697
708
  return packageManager ?? "npm";
698
709
  };
699
710
  var detectNodeVersion = async ({ repositoryReader: repositoryReader2 }, nodeVersionFilePath) => await repositoryReader2.readFile(nodeVersionFilePath).map((nodeVersion) => nodeVersion.trim()).unwrapOr(void 0);
700
711
  var detectTerraformVersion = async ({ repositoryReader: repositoryReader2 }, terraformVersionFilePath) => await repositoryReader2.readFile(terraformVersionFilePath).map((tfVersion) => tfVersion.trim()).unwrapOr(void 0);
701
- var detectTurboVersion = ({ devDependencies }) => devDependencies.get("turbo")?.trim();
702
- var getInfo = (dependencies, config2) => async () => ({
703
- node: await detectNodeVersion(
704
- { repositoryReader: dependencies.repositoryReader },
705
- `${config2.repository.root}/.node-version`
706
- ),
707
- packageManager: await detectPackageManager(dependencies, config2),
708
- terraform: await detectTerraformVersion(
709
- { repositoryReader: dependencies.repositoryReader },
710
- `${config2.repository.root}/.terraform-version`
711
- ),
712
- turbo: detectTurboVersion(dependencies.packageJson)
713
- });
712
+ var detectTurboVersion = async (dependencies, repositoryRoot) => {
713
+ const packageJsonResult = await dependencies.packageJsonReader.readPackageJson(repositoryRoot);
714
+ return packageJsonResult.map((pkg) => pkg.devDependencies.get("turbo")?.trim()).unwrapOr(void 0);
715
+ };
716
+ var getInfo = (dependencies) => async () => {
717
+ const repositoryRoot = await dependencies.repositoryReader.findRepositoryRoot().unwrapOr(process.cwd());
718
+ return {
719
+ node: await detectNodeVersion(
720
+ { repositoryReader: dependencies.repositoryReader },
721
+ `${repositoryRoot}/.node-version`
722
+ ),
723
+ packageManager: await detectPackageManager(dependencies, repositoryRoot),
724
+ terraform: await detectTerraformVersion(
725
+ { repositoryReader: dependencies.repositoryReader },
726
+ `${repositoryRoot}/.terraform-version`
727
+ ),
728
+ turbo: await detectTurboVersion(dependencies, repositoryRoot)
729
+ };
730
+ };
714
731
  var printInfo = (result) => {
715
- const logger2 = getLogger6("json");
716
- logger2.info(JSON.stringify(result));
732
+ const logger = getLogger6("json");
733
+ logger.info(JSON.stringify(result));
717
734
  };
718
735
 
719
736
  // src/adapters/commander/commands/info.ts
720
- var makeInfoCommand = (dependencies, config2) => new Command3().name("info").description("Display information about the project").action(async () => {
721
- const result = await getInfo(dependencies, config2)();
737
+ var makeInfoCommand = (dependencies) => new Command3().name("info").description("Display information about the project").action(async () => {
738
+ const result = await getInfo(dependencies)();
722
739
  printInfo(result);
723
740
  });
724
741
 
@@ -789,25 +806,25 @@ var makeSavemoneyCommand = () => new Command5("savemoney").description(
789
806
  // src/adapters/commander/index.ts
790
807
  var makeCli = (deps2, config2, cliDeps) => {
791
808
  const program2 = new Command6();
792
- program2.name("dx").description("The CLI for DX-Platform").version("0.10.3");
809
+ program2.name("dx").description("The CLI for DX-Platform").version("0.11.1");
793
810
  program2.addCommand(makeDoctorCommand(deps2, config2));
794
811
  program2.addCommand(makeCodemodCommand(cliDeps));
795
812
  program2.addCommand(makeInitCommand());
796
813
  program2.addCommand(makeSavemoneyCommand());
797
- program2.addCommand(makeInfoCommand(deps2, config2));
814
+ program2.addCommand(makeInfoCommand(deps2));
798
815
  return program2;
799
816
  };
800
817
 
801
818
  // src/adapters/logtape/validation-reporter.ts
802
819
  import { getLogger as getLogger7 } from "@logtape/logtape";
803
820
  var makeValidationReporter = () => {
804
- const logger2 = getLogger7(["dx-cli", "validation"]);
821
+ const logger = getLogger7(["dx-cli", "validation"]);
805
822
  return {
806
823
  reportCheckResult(result) {
807
824
  if (result.isValid) {
808
- logger2.info(`\u2705 ${result.successMessage}`);
825
+ logger.info(`\u2705 ${result.successMessage}`);
809
826
  } else {
810
- logger2.error(`\u274C ${result.errorMessage}`);
827
+ logger.error(`\u274C ${result.errorMessage}`);
811
828
  }
812
829
  }
813
830
  };
@@ -851,9 +868,9 @@ var makePackageJsonReader = () => ({
851
868
  getDependencies: (cwd2 = process3.cwd(), type) => {
852
869
  const packageJsonPath = join2(cwd2, "package.json");
853
870
  return readFileAndDecode(packageJsonPath, packageJsonSchema).map(
854
- (packageJson2) => {
871
+ (packageJson) => {
855
872
  const key = type === "dev" ? "devDependencies" : "dependencies";
856
- return packageJson2[key];
873
+ return packageJson[key];
857
874
  }
858
875
  );
859
876
  },
@@ -893,20 +910,20 @@ var findRepositoryRoot = (dir = process.cwd()) => {
893
910
  )
894
911
  ).map(() => dir);
895
912
  };
896
- var resolveWorkspacePattern = (repoRoot2, pattern) => ResultAsync7.fromPromise(
913
+ var resolveWorkspacePattern = (repoRoot, pattern) => ResultAsync7.fromPromise(
897
914
  // For now it is not possible to use the fs.glob function (from node:fs/promises)
898
915
  // because it is not possible to run it on Node 20.x
899
- glob.glob(pattern, { cwd: repoRoot2 }),
916
+ glob.glob(pattern, { cwd: repoRoot }),
900
917
  (cause) => new Error(`Failed to resolve workspace glob: ${pattern}`, {
901
918
  cause
902
919
  })
903
920
  ).map(
904
921
  (subDirectories) => (
905
922
  // Create the absolute path to the subdirectory
906
- subDirectories.map((directory) => path.join(repoRoot2, directory))
923
+ subDirectories.map((directory) => path.join(repoRoot, directory))
907
924
  )
908
925
  );
909
- var getWorkspaces = (repoRoot2) => readFile2(path.join(repoRoot2, "pnpm-workspace.yaml")).andThen(parseYaml).andThen(
926
+ var getWorkspaces = (repoRoot) => readFile2(path.join(repoRoot, "pnpm-workspace.yaml")).andThen(parseYaml).andThen(
910
927
  (obj) => (
911
928
  // If no packages are defined, go on with an empty array
912
929
  decode(z3.object({ packages: z3.array(z3.string()) }))(obj).orElse(
@@ -917,7 +934,7 @@ var getWorkspaces = (repoRoot2) => readFile2(path.join(repoRoot2, "pnpm-workspac
917
934
  ({ packages }) => (
918
935
  // For every package pattern in the pnpm-workspace.yaml file, get the list of subdirectories
919
936
  ResultAsync7.combine(
920
- packages.map((pattern) => resolveWorkspacePattern(repoRoot2, pattern))
937
+ packages.map((pattern) => resolveWorkspacePattern(repoRoot, pattern))
921
938
  ).map((workspacesList) => workspacesList.flat()).andThen((workspaceFolders) => {
922
939
  const workspaceResults = workspaceFolders.map(
923
940
  (nodeWorkspaceDirectory) => readFileAndDecode(
@@ -942,12 +959,9 @@ var makeRepositoryReader = () => ({
942
959
  });
943
960
 
944
961
  // src/config.ts
945
- var getConfig = (repositoryRoot2) => ({
962
+ var getConfig = () => ({
946
963
  minVersions: {
947
964
  turbo: "2"
948
- },
949
- repository: {
950
- root: repositoryRoot2
951
965
  }
952
966
  });
953
967
 
@@ -992,33 +1006,17 @@ await configure({
992
1006
  }
993
1007
  }
994
1008
  });
995
- var logger = getLogger8(["dx-cli"]);
996
1009
  var repositoryReader = makeRepositoryReader();
997
1010
  var packageJsonReader = makePackageJsonReader();
998
1011
  var validationReporter = makeValidationReporter();
999
- var repoRoot = await repositoryReader.findRepositoryRoot(process.cwd());
1000
- if (repoRoot.isErr()) {
1001
- logger.error(
1002
- "Could not find repository root. Make sure to have the repo initialized."
1003
- );
1004
- process.exit(1);
1005
- }
1006
- var repositoryRoot = repoRoot.value;
1007
- var repoPackageJson = await packageJsonReader.readPackageJson(repositoryRoot);
1008
- if (repoPackageJson.isErr()) {
1009
- logger.error("Repository does not contain a package.json file");
1010
- process.exit(1);
1011
- }
1012
- var packageJson = repoPackageJson.value;
1013
1012
  var deps = {
1014
- packageJson,
1015
1013
  packageJsonReader,
1016
1014
  repositoryReader,
1017
1015
  validationReporter
1018
1016
  };
1019
- var config = getConfig(repositoryRoot);
1017
+ var config = getConfig();
1020
1018
  var useCases = {
1021
- applyCodemodById: applyCodemodById(codemods_default, getInfo(deps, config)),
1019
+ applyCodemodById: applyCodemodById(codemods_default, getInfo(deps)),
1022
1020
  listCodemods: listCodemods(codemods_default)
1023
1021
  };
1024
1022
  var program = makeCli(deps, config, useCases);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pagopa/dx-cli",
3
- "version": "0.10.3",
3
+ "version": "0.11.1",
4
4
  "type": "module",
5
5
  "description": "A CLI useful to manage DX tools.",
6
6
  "repository": {
@@ -19,32 +19,32 @@
19
19
  "dx": "./bin/index.js"
20
20
  },
21
21
  "dependencies": {
22
- "@logtape/logtape": "^1.0.0",
23
- "commander": "^14.0.0",
24
- "core-js": "^3.44.0",
25
- "execa": "^9.6.0",
26
- "glob": "^11.0.3",
22
+ "@logtape/logtape": "^1.2.2",
23
+ "commander": "^14.0.2",
24
+ "core-js": "^3.47.0",
25
+ "execa": "^9.6.1",
26
+ "glob": "^11.1.0",
27
27
  "neverthrow": "^8.2.0",
28
- "node-plop": "^0.32.1",
29
- "octokit": "^5.0.3",
28
+ "node-plop": "^0.32.3",
29
+ "octokit": "^5.0.5",
30
30
  "replace-in-file": "^8.3.0",
31
31
  "semver": "^7.7.2",
32
- "yaml": "^2.8.0",
33
- "zod": "^3.25.28",
34
- "@pagopa/dx-savemoney": "^0.1.3",
35
- "@pagopa/monorepo-generator": "^0.10.1"
32
+ "yaml": "^2.8.2",
33
+ "zod": "^3.25.76",
34
+ "@pagopa/dx-savemoney": "^0.1.4",
35
+ "@pagopa/monorepo-generator": "^0.11.1"
36
36
  },
37
37
  "devDependencies": {
38
38
  "@tsconfig/node22": "22.0.2",
39
39
  "@types/node": "^22.19.1",
40
40
  "@types/semver": "^7.7.1",
41
+ "@vitest/coverage-v8": "^3.2.4",
41
42
  "eslint": "^9.39.1",
42
- "memfs": "^4.23.0",
43
+ "memfs": "^4.51.1",
43
44
  "prettier": "3.6.2",
44
- "tsup": "^8.5.0",
45
+ "tsup": "^8.5.1",
45
46
  "typescript": "~5.8.3",
46
47
  "vitest": "^3.2.4",
47
- "@vitest/coverage-v8": "^3.2.4",
48
48
  "vitest-mock-extended": "^3.1.0",
49
49
  "@pagopa/eslint-config": "^5.1.1"
50
50
  },