@pagopa/dx-cli 0.11.2 → 0.14.0
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.
- package/README.md +30 -6
- package/bin/index.js +229 -51
- package/package.json +5 -3
package/README.md
CHANGED
|
@@ -112,19 +112,43 @@ This command helps you:
|
|
|
112
112
|
|
|
113
113
|
#### `init`
|
|
114
114
|
|
|
115
|
-
|
|
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
|
-
-
|
|
125
|
-
-
|
|
126
|
-
-
|
|
127
|
-
-
|
|
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
|
|
35
|
-
const response = await
|
|
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 = (
|
|
56
|
-
const ancestor =
|
|
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,
|
|
67
|
-
if (map.has("jobs") || isChildOf(
|
|
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,
|
|
131
|
-
if (isChildOf(
|
|
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")) {
|
|
@@ -740,8 +741,29 @@ var makeInfoCommand = (dependencies) => new Command3().name("info").description(
|
|
|
740
741
|
});
|
|
741
742
|
|
|
742
743
|
// src/adapters/commander/commands/init.ts
|
|
743
|
-
import
|
|
744
|
+
import loadMonorepoScaffolder, {
|
|
745
|
+
answersSchema,
|
|
746
|
+
PLOP_MONOREPO_GENERATOR_NAME
|
|
747
|
+
} from "@pagopa/monorepo-generator";
|
|
748
|
+
import chalk from "chalk";
|
|
744
749
|
import { Command as Command4 } from "commander";
|
|
750
|
+
import { $ as $3 } from "execa";
|
|
751
|
+
import { okAsync as okAsync2, ResultAsync as ResultAsync6 } from "neverthrow";
|
|
752
|
+
import * as path from "path";
|
|
753
|
+
import { oraPromise } from "ora";
|
|
754
|
+
|
|
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
|
+
});
|
|
765
|
+
|
|
766
|
+
// src/adapters/plop/index.ts
|
|
745
767
|
import { Result, ResultAsync as ResultAsync4 } from "neverthrow";
|
|
746
768
|
import nodePlop from "node-plop";
|
|
747
769
|
var initPlop = () => ResultAsync4.fromPromise(
|
|
@@ -752,24 +774,180 @@ var getGenerator = (plopAPI) => Result.fromThrowable(
|
|
|
752
774
|
plopAPI.getGenerator,
|
|
753
775
|
() => new Error("Generator not found")
|
|
754
776
|
);
|
|
755
|
-
var
|
|
777
|
+
var getPrompts = (generator) => ResultAsync4.fromPromise(
|
|
756
778
|
generator.runPrompts(),
|
|
757
|
-
() => new Error("Failed to run the generator prompts")
|
|
758
|
-
)
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
779
|
+
(cause) => new Error("Failed to run the generator prompts", { cause })
|
|
780
|
+
);
|
|
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(
|
|
803
|
+
oraPromise(promise, {
|
|
804
|
+
failText,
|
|
805
|
+
successText,
|
|
806
|
+
text
|
|
807
|
+
}),
|
|
808
|
+
(cause) => new Error(failText, { cause })
|
|
763
809
|
);
|
|
764
|
-
var
|
|
810
|
+
var validateAnswers = (answers) => okAsync2(answers);
|
|
811
|
+
var runGeneratorActions = (generator) => (answers) => withSpinner(
|
|
812
|
+
"Creating workspace files...",
|
|
813
|
+
"Workspace files created successfully!",
|
|
814
|
+
"Failed to create workspace files.",
|
|
815
|
+
generator.runActions(answers)
|
|
816
|
+
).map(() => answers);
|
|
817
|
+
var displaySummary = (initResult) => {
|
|
818
|
+
const { csp, pr, repository } = initResult;
|
|
819
|
+
console.log(chalk.green.bold("\nWorkspace created successfully!"));
|
|
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
|
|
841
|
+
`
|
|
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.
|
|
850
|
+
`
|
|
851
|
+
);
|
|
852
|
+
}
|
|
853
|
+
};
|
|
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(
|
|
765
938
|
"Command to initialize resources (like projects, subscriptions, ...)"
|
|
766
939
|
).addCommand(
|
|
767
940
|
new Command4("project").description("Initialize a new monorepo project").action(async function() {
|
|
768
|
-
await
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
941
|
+
await checkPreconditions().andThen(initPlop).andTee(loadMonorepoScaffolder).andThen((plop) => getGenerator(plop)(PLOP_MONOREPO_GENERATOR_NAME)).andThen(
|
|
942
|
+
(generator) => (
|
|
943
|
+
// Ask the user the questions defined in the plop generator
|
|
944
|
+
getPrompts(generator).andThen(decode(answersSchema)).andThen(validateAnswers).andThen(runGeneratorActions(generator))
|
|
945
|
+
)
|
|
946
|
+
).andThen(
|
|
947
|
+
(answers) => handleNewGitHubRepository(octokit2)(answers).map(
|
|
948
|
+
(repoPr) => makeInitResult(answers, repoPr)
|
|
949
|
+
)
|
|
950
|
+
).match(displaySummary, exitWithError(this));
|
|
773
951
|
})
|
|
774
952
|
);
|
|
775
953
|
|
|
@@ -806,14 +984,17 @@ var makeSavemoneyCommand = () => new Command5("savemoney").description(
|
|
|
806
984
|
// src/adapters/commander/index.ts
|
|
807
985
|
var makeCli = (deps2, config2, cliDeps) => {
|
|
808
986
|
const program2 = new Command6();
|
|
809
|
-
program2.name("dx").description("The CLI for DX-Platform").version("0.
|
|
987
|
+
program2.name("dx").description("The CLI for DX-Platform").version("0.14.0");
|
|
810
988
|
program2.addCommand(makeDoctorCommand(deps2, config2));
|
|
811
989
|
program2.addCommand(makeCodemodCommand(cliDeps));
|
|
812
|
-
program2.addCommand(makeInitCommand());
|
|
990
|
+
program2.addCommand(makeInitCommand(deps2));
|
|
813
991
|
program2.addCommand(makeSavemoneyCommand());
|
|
814
992
|
program2.addCommand(makeInfoCommand(deps2));
|
|
815
993
|
return program2;
|
|
816
994
|
};
|
|
995
|
+
var exitWithError = (command) => (error) => {
|
|
996
|
+
command.error(error.message);
|
|
997
|
+
};
|
|
817
998
|
|
|
818
999
|
// src/adapters/logtape/validation-reporter.ts
|
|
819
1000
|
import { getLogger as getLogger7 } from "@logtape/logtape";
|
|
@@ -835,16 +1016,9 @@ import { join as join2 } from "path";
|
|
|
835
1016
|
import * as process3 from "process";
|
|
836
1017
|
|
|
837
1018
|
// src/adapters/node/fs/file-reader.ts
|
|
838
|
-
import { ResultAsync as
|
|
1019
|
+
import { ResultAsync as ResultAsync7 } from "neverthrow";
|
|
839
1020
|
import fs3 from "fs/promises";
|
|
840
1021
|
|
|
841
|
-
// src/adapters/zod/index.ts
|
|
842
|
-
import { ResultAsync as ResultAsync5 } from "neverthrow";
|
|
843
|
-
var decode = (schema) => ResultAsync5.fromThrowable(
|
|
844
|
-
schema.parseAsync,
|
|
845
|
-
(cause) => new Error("File content is not valid for the given schema", { cause })
|
|
846
|
-
);
|
|
847
|
-
|
|
848
1022
|
// src/adapters/node/json/index.ts
|
|
849
1023
|
import { Result as Result2 } from "neverthrow";
|
|
850
1024
|
var parseJson = Result2.fromThrowable(
|
|
@@ -853,14 +1027,14 @@ var parseJson = Result2.fromThrowable(
|
|
|
853
1027
|
);
|
|
854
1028
|
|
|
855
1029
|
// src/adapters/node/fs/file-reader.ts
|
|
856
|
-
var readFile2 = (filePath) =>
|
|
1030
|
+
var readFile2 = (filePath) => ResultAsync7.fromPromise(
|
|
857
1031
|
fs3.readFile(filePath, "utf-8"),
|
|
858
1032
|
(cause) => new Error(`Failed to read file: ${filePath}`, { cause })
|
|
859
1033
|
);
|
|
860
1034
|
var readFileAndDecode = (filePath, schema) => readFile2(filePath).andThen(parseJson).andThen(decode(schema));
|
|
861
|
-
var fileExists = (
|
|
862
|
-
fs3.stat(
|
|
863
|
-
() => new Error(`${
|
|
1035
|
+
var fileExists = (path3) => ResultAsync7.fromPromise(
|
|
1036
|
+
fs3.stat(path3),
|
|
1037
|
+
() => new Error(`${path3} not found.`)
|
|
864
1038
|
).map(() => true);
|
|
865
1039
|
|
|
866
1040
|
// src/adapters/node/package-json.ts
|
|
@@ -889,8 +1063,8 @@ var makePackageJsonReader = () => ({
|
|
|
889
1063
|
|
|
890
1064
|
// src/adapters/node/repository.ts
|
|
891
1065
|
import * as glob from "glob";
|
|
892
|
-
import { okAsync as
|
|
893
|
-
import * as
|
|
1066
|
+
import { okAsync as okAsync3, ResultAsync as ResultAsync8 } from "neverthrow";
|
|
1067
|
+
import * as path2 from "path";
|
|
894
1068
|
import { z as z3 } from "zod/v4";
|
|
895
1069
|
|
|
896
1070
|
// src/adapters/yaml/index.ts
|
|
@@ -903,14 +1077,14 @@ var parseYaml = Result3.fromThrowable(
|
|
|
903
1077
|
|
|
904
1078
|
// src/adapters/node/repository.ts
|
|
905
1079
|
var findRepositoryRoot = (dir = process.cwd()) => {
|
|
906
|
-
const gitPath =
|
|
1080
|
+
const gitPath = path2.join(dir, ".git");
|
|
907
1081
|
return fileExists(gitPath).mapErr(
|
|
908
1082
|
() => new Error(
|
|
909
1083
|
"Could not find repository root. Make sure to have the repo initialized."
|
|
910
1084
|
)
|
|
911
1085
|
).map(() => dir);
|
|
912
1086
|
};
|
|
913
|
-
var resolveWorkspacePattern = (repoRoot, pattern) =>
|
|
1087
|
+
var resolveWorkspacePattern = (repoRoot, pattern) => ResultAsync8.fromPromise(
|
|
914
1088
|
// For now it is not possible to use the fs.glob function (from node:fs/promises)
|
|
915
1089
|
// because it is not possible to run it on Node 20.x
|
|
916
1090
|
glob.glob(pattern, { cwd: repoRoot }),
|
|
@@ -920,25 +1094,25 @@ var resolveWorkspacePattern = (repoRoot, pattern) => ResultAsync7.fromPromise(
|
|
|
920
1094
|
).map(
|
|
921
1095
|
(subDirectories) => (
|
|
922
1096
|
// Create the absolute path to the subdirectory
|
|
923
|
-
subDirectories.map((directory) =>
|
|
1097
|
+
subDirectories.map((directory) => path2.join(repoRoot, directory))
|
|
924
1098
|
)
|
|
925
1099
|
);
|
|
926
|
-
var getWorkspaces = (repoRoot) => readFile2(
|
|
1100
|
+
var getWorkspaces = (repoRoot) => readFile2(path2.join(repoRoot, "pnpm-workspace.yaml")).andThen(parseYaml).andThen(
|
|
927
1101
|
(obj) => (
|
|
928
1102
|
// If no packages are defined, go on with an empty array
|
|
929
1103
|
decode(z3.object({ packages: z3.array(z3.string()) }))(obj).orElse(
|
|
930
|
-
() =>
|
|
1104
|
+
() => okAsync3({ packages: [] })
|
|
931
1105
|
)
|
|
932
1106
|
)
|
|
933
1107
|
).andThen(
|
|
934
1108
|
({ packages }) => (
|
|
935
1109
|
// For every package pattern in the pnpm-workspace.yaml file, get the list of subdirectories
|
|
936
|
-
|
|
1110
|
+
ResultAsync8.combine(
|
|
937
1111
|
packages.map((pattern) => resolveWorkspacePattern(repoRoot, pattern))
|
|
938
1112
|
).map((workspacesList) => workspacesList.flat()).andThen((workspaceFolders) => {
|
|
939
1113
|
const workspaceResults = workspaceFolders.map(
|
|
940
1114
|
(nodeWorkspaceDirectory) => readFileAndDecode(
|
|
941
|
-
|
|
1115
|
+
path2.join(nodeWorkspaceDirectory, "package.json"),
|
|
942
1116
|
packageJsonSchema
|
|
943
1117
|
).map(
|
|
944
1118
|
({ name }) => (
|
|
@@ -947,7 +1121,7 @@ var getWorkspaces = (repoRoot) => readFile2(path.join(repoRoot, "pnpm-workspace.
|
|
|
947
1121
|
)
|
|
948
1122
|
)
|
|
949
1123
|
);
|
|
950
|
-
return
|
|
1124
|
+
return ResultAsync8.combine(workspaceResults);
|
|
951
1125
|
})
|
|
952
1126
|
)
|
|
953
1127
|
);
|
|
@@ -966,19 +1140,19 @@ var getConfig = () => ({
|
|
|
966
1140
|
});
|
|
967
1141
|
|
|
968
1142
|
// src/use-cases/apply-codemod.ts
|
|
969
|
-
import { errAsync, okAsync as
|
|
1143
|
+
import { errAsync, okAsync as okAsync4, ResultAsync as ResultAsync9 } from "neverthrow";
|
|
970
1144
|
var getCodemodById = (registry2, id) => registry2.getById(id).andThen(
|
|
971
|
-
(codemod) => codemod ?
|
|
1145
|
+
(codemod) => codemod ? okAsync4(codemod) : errAsync(new Error(`Codemod with id ${id} not found`))
|
|
972
1146
|
);
|
|
973
|
-
var safeGetInfo = (getInfo2) =>
|
|
1147
|
+
var safeGetInfo = (getInfo2) => ResultAsync9.fromPromise(
|
|
974
1148
|
getInfo2(),
|
|
975
1149
|
(error) => new Error("Failed to get info", { cause: error })
|
|
976
1150
|
);
|
|
977
|
-
var applyCodemodById = (registry2, getInfo2) => (id) =>
|
|
1151
|
+
var applyCodemodById = (registry2, getInfo2) => (id) => ResultAsync9.combine([
|
|
978
1152
|
safeGetInfo(getInfo2),
|
|
979
1153
|
getCodemodById(registry2, id)
|
|
980
1154
|
]).andThen(
|
|
981
|
-
([info, codemod]) =>
|
|
1155
|
+
([info, codemod]) => ResultAsync9.fromPromise(codemod.apply(info), (error) => {
|
|
982
1156
|
const message = error instanceof Error ? `: ${error.message}` : "";
|
|
983
1157
|
return new Error("Failed to apply codemod" + message, { cause: error });
|
|
984
1158
|
})
|
|
@@ -1009,7 +1183,11 @@ await configure({
|
|
|
1009
1183
|
var repositoryReader = makeRepositoryReader();
|
|
1010
1184
|
var packageJsonReader = makePackageJsonReader();
|
|
1011
1185
|
var validationReporter = makeValidationReporter();
|
|
1186
|
+
var octokit = new Octokit2({
|
|
1187
|
+
auth: process.env.GITHUB_TOKEN
|
|
1188
|
+
});
|
|
1012
1189
|
var deps = {
|
|
1190
|
+
octokit,
|
|
1013
1191
|
packageJsonReader,
|
|
1014
1192
|
repositoryReader,
|
|
1015
1193
|
validationReporter
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pagopa/dx-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A CLI useful to manage DX tools.",
|
|
6
6
|
"repository": {
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"@logtape/logtape": "^1.2.2",
|
|
23
|
+
"chalk": "^5.6.2",
|
|
23
24
|
"commander": "^14.0.2",
|
|
24
25
|
"core-js": "^3.47.0",
|
|
25
26
|
"execa": "^9.6.1",
|
|
@@ -27,12 +28,13 @@
|
|
|
27
28
|
"neverthrow": "^8.2.0",
|
|
28
29
|
"node-plop": "^0.32.3",
|
|
29
30
|
"octokit": "^5.0.5",
|
|
31
|
+
"ora": "^9.0.0",
|
|
30
32
|
"replace-in-file": "^8.3.0",
|
|
31
33
|
"semver": "^7.7.2",
|
|
32
34
|
"yaml": "^2.8.2",
|
|
33
|
-
"zod": "^
|
|
35
|
+
"zod": "^4.1.13",
|
|
34
36
|
"@pagopa/dx-savemoney": "^0.1.4",
|
|
35
|
-
"@pagopa/monorepo-generator": "^0.
|
|
37
|
+
"@pagopa/monorepo-generator": "^0.13.0"
|
|
36
38
|
},
|
|
37
39
|
"devDependencies": {
|
|
38
40
|
"@tsconfig/node22": "22.0.2",
|