@pagopa/dx-cli 0.6.0 → 0.7.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/bin/index.js +329 -54
- package/package.json +4 -1
package/bin/index.js
CHANGED
|
@@ -2,22 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
4
|
import "core-js/actual/set/index.js";
|
|
5
|
-
import { configure, getConsoleSink, getLogger as
|
|
6
|
-
|
|
7
|
-
// src/adapters/codemods/example.ts
|
|
8
|
-
import { okAsync } from "neverthrow";
|
|
9
|
-
var apply = () => {
|
|
10
|
-
console.log("Hello from example codemod!");
|
|
11
|
-
return okAsync(void 0);
|
|
12
|
-
};
|
|
13
|
-
var example_default = {
|
|
14
|
-
apply,
|
|
15
|
-
description: "An example codemod that does nothing",
|
|
16
|
-
id: "example"
|
|
17
|
-
};
|
|
5
|
+
import { configure, getConsoleSink, getLogger as getLogger9 } from "@logtape/logtape";
|
|
18
6
|
|
|
19
7
|
// src/adapters/codemods/registry.ts
|
|
20
|
-
import { okAsync
|
|
8
|
+
import { okAsync } from "neverthrow";
|
|
21
9
|
var LocalCodemodRegistry = class {
|
|
22
10
|
#m;
|
|
23
11
|
constructor() {
|
|
@@ -27,22 +15,296 @@ var LocalCodemodRegistry = class {
|
|
|
27
15
|
this.#m.set(codemod.id, codemod);
|
|
28
16
|
}
|
|
29
17
|
getAll() {
|
|
30
|
-
return
|
|
18
|
+
return okAsync(Array.from(this.#m.values()));
|
|
31
19
|
}
|
|
32
20
|
getById(id) {
|
|
33
|
-
return
|
|
21
|
+
return okAsync(this.#m.get(id));
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
// src/adapters/codemods/update-code-review.ts
|
|
26
|
+
import { getLogger as getLogger2 } from "@logtape/logtape";
|
|
27
|
+
import { replaceInFile } from "replace-in-file";
|
|
28
|
+
|
|
29
|
+
// src/adapters/codemods/git.ts
|
|
30
|
+
import { getLogger } from "@logtape/logtape";
|
|
31
|
+
import { Octokit } from "octokit";
|
|
32
|
+
var getLatestCommitSha = async (owner, repo, ref = "main") => {
|
|
33
|
+
const octokit = new Octokit();
|
|
34
|
+
const response = await octokit.rest.repos.getCommit({
|
|
35
|
+
owner,
|
|
36
|
+
ref,
|
|
37
|
+
repo
|
|
38
|
+
});
|
|
39
|
+
return response.data.sha;
|
|
40
|
+
};
|
|
41
|
+
var getLatestCommitShaOrRef = async (owner, repo, ref = "main") => {
|
|
42
|
+
const logger2 = getLogger(["dx-cli", "codemod"]);
|
|
43
|
+
return getLatestCommitSha(owner, repo, ref).catch(() => {
|
|
44
|
+
logger2.warn(
|
|
45
|
+
"Failed to fetch the latest commit from {owner}/{repo}, fallback to {fallback}",
|
|
46
|
+
{ fallback: ref, owner, repo }
|
|
47
|
+
);
|
|
48
|
+
return ref;
|
|
49
|
+
});
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
// src/adapters/codemods/update-code-review.ts
|
|
53
|
+
var updateJSCodeReview = async (sha) => {
|
|
54
|
+
const logger2 = getLogger2(["dx-cli", "codemod"]);
|
|
55
|
+
const results = await replaceInFile({
|
|
56
|
+
allowEmptyPaths: true,
|
|
57
|
+
files: [".github/workflows/*.yaml"],
|
|
58
|
+
from: [/pagopa\/dx\/.github\/workflows\/js_code_review.yaml@(\S+)/g],
|
|
59
|
+
to: [`pagopa/dx/.github/workflows/js_code_review.yaml@${sha}`]
|
|
60
|
+
});
|
|
61
|
+
const updated = results.filter((r) => r.hasChanged).map((r) => r.file);
|
|
62
|
+
updated.forEach((filename) => {
|
|
63
|
+
logger2.info("Workflow {filename} updated", { filename });
|
|
64
|
+
});
|
|
65
|
+
return updated;
|
|
66
|
+
};
|
|
67
|
+
var updateCodeReview = {
|
|
68
|
+
apply: async () => {
|
|
69
|
+
const logger2 = getLogger2(["dx-cli", "codemod"]);
|
|
70
|
+
const owner = "pagopa";
|
|
71
|
+
const repo = "dx";
|
|
72
|
+
return getLatestCommitSha(owner, repo).then(async (sha) => {
|
|
73
|
+
await updateJSCodeReview(sha);
|
|
74
|
+
}).catch(() => {
|
|
75
|
+
logger2.error(
|
|
76
|
+
"Failed to fetch the latest commit sha from {owner}/{repo}",
|
|
77
|
+
{
|
|
78
|
+
owner,
|
|
79
|
+
repo
|
|
80
|
+
}
|
|
81
|
+
);
|
|
82
|
+
});
|
|
83
|
+
},
|
|
84
|
+
description: "Update js_code_review workflow to its latest version",
|
|
85
|
+
id: "update-code-review"
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
// src/adapters/codemods/use-azure-appsvc.ts
|
|
89
|
+
import { getLogger as getLogger3 } from "@logtape/logtape";
|
|
90
|
+
import { replaceInFile as replaceInFile2 } from "replace-in-file";
|
|
91
|
+
import YAML from "yaml";
|
|
92
|
+
var isChildOf = (path2, key) => {
|
|
93
|
+
const ancestor = path2.at(-1);
|
|
94
|
+
return YAML.isPair(ancestor) && YAML.isScalar(ancestor.key) && typeof ancestor.key.value === "string" && ancestor.key.value === key;
|
|
95
|
+
};
|
|
96
|
+
var migrateWorkflow = (sha) => (workflow, filename) => {
|
|
97
|
+
const logger2 = getLogger3(["dx-cli", "codemod"]);
|
|
98
|
+
logger2.debug("Processing {filename} file", { filename });
|
|
99
|
+
const document = YAML.parseDocument(workflow);
|
|
100
|
+
let updated = false;
|
|
101
|
+
YAML.visit(document, {
|
|
102
|
+
Map(_, map, path2) {
|
|
103
|
+
if (isChildOf(path2, "jobs") || isChildOf(path2, "with")) {
|
|
104
|
+
return void 0;
|
|
105
|
+
}
|
|
106
|
+
if (map.has("jobs")) {
|
|
107
|
+
return void 0;
|
|
108
|
+
}
|
|
109
|
+
if (map.has("uses")) {
|
|
110
|
+
const uses = map.get("uses");
|
|
111
|
+
if (typeof uses === "string" && uses.match(
|
|
112
|
+
/^pagopa\/dx\/.github\/workflows\/(web|function)_app_deploy/
|
|
113
|
+
)) {
|
|
114
|
+
logger2.debug("Adding disable_auto_staging_deploy");
|
|
115
|
+
map.addIn(["with", "disable_auto_staging_deploy"], true);
|
|
116
|
+
updated = true;
|
|
117
|
+
return void 0;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return YAML.visit.SKIP;
|
|
121
|
+
},
|
|
122
|
+
Pair(_, pair) {
|
|
123
|
+
if (YAML.isScalar(pair.key)) {
|
|
124
|
+
if (pair.key.value === "function_app_name") {
|
|
125
|
+
updated = true;
|
|
126
|
+
logger2.debug("Updating function_app_name to web_app_name");
|
|
127
|
+
return new YAML.Pair("web_app_name", pair.value);
|
|
128
|
+
}
|
|
129
|
+
if (pair.key.value === "use_staging_slot") {
|
|
130
|
+
updated = true;
|
|
131
|
+
logger2.debug("Removing use_staging_slot");
|
|
132
|
+
return YAML.visit.REMOVE;
|
|
133
|
+
}
|
|
134
|
+
if (pair.key.value === "uses") {
|
|
135
|
+
updated = true;
|
|
136
|
+
logger2.debug("Updating uses value");
|
|
137
|
+
return new YAML.Pair(
|
|
138
|
+
"uses",
|
|
139
|
+
`pagopa/dx/.github/workflows/release-azure-appsvc.yaml@${sha}`
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
if (updated) {
|
|
146
|
+
logger2.info("Workflow {filename} updated", {
|
|
147
|
+
filename
|
|
148
|
+
});
|
|
149
|
+
return YAML.stringify(document);
|
|
150
|
+
}
|
|
151
|
+
logger2.debug("No changes applied to {filename}", { filename });
|
|
152
|
+
return workflow;
|
|
153
|
+
};
|
|
154
|
+
var useAzureAppsvc = {
|
|
155
|
+
apply: async () => {
|
|
156
|
+
const sha = await getLatestCommitShaOrRef("pagopa", "dx");
|
|
157
|
+
await replaceInFile2({
|
|
158
|
+
allowEmptyPaths: true,
|
|
159
|
+
files: [".github/workflows/*.yaml"],
|
|
160
|
+
processor: migrateWorkflow(sha)
|
|
161
|
+
});
|
|
162
|
+
},
|
|
163
|
+
description: "Refactor legacy deploy workflows to use release-azure-appsvc",
|
|
164
|
+
id: "use-azure-appsvc"
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
// src/adapters/codemods/use-pnpm.ts
|
|
168
|
+
import { getLogger as getLogger4 } from "@logtape/logtape";
|
|
169
|
+
import { $ } from "execa";
|
|
170
|
+
import * as fs from "fs/promises";
|
|
171
|
+
import { replaceInFile as replaceInFile3 } from "replace-in-file";
|
|
172
|
+
import YAML2 from "yaml";
|
|
173
|
+
async function preparePackageJsonForPnpm() {
|
|
174
|
+
const packageJson2 = await fs.readFile("package.json", "utf-8");
|
|
175
|
+
const manifest = JSON.parse(packageJson2);
|
|
176
|
+
let workspaces = [];
|
|
177
|
+
if (Object.hasOwn(manifest, "packageManager")) {
|
|
178
|
+
delete manifest.packageManager;
|
|
179
|
+
}
|
|
180
|
+
if (Object.hasOwn(manifest, "workspaces")) {
|
|
181
|
+
if (Array.isArray(manifest.workspaces)) {
|
|
182
|
+
workspaces = manifest.workspaces;
|
|
183
|
+
}
|
|
184
|
+
delete manifest.workspaces;
|
|
185
|
+
}
|
|
186
|
+
await fs.writeFile("package.json", JSON.stringify(manifest, null, 2));
|
|
187
|
+
return workspaces;
|
|
188
|
+
}
|
|
189
|
+
async function removeFiles(...files) {
|
|
190
|
+
await Promise.all(
|
|
191
|
+
files.map(
|
|
192
|
+
(file) => (
|
|
193
|
+
// Remove the file if it exists, fail silently if it doesn't.
|
|
194
|
+
fs.rm(file, { force: true, recursive: true }).catch(() => void 0)
|
|
195
|
+
)
|
|
196
|
+
)
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
async function replaceYarnOccurrences() {
|
|
200
|
+
const logger2 = getLogger4(["dx-cli", "codemod"]);
|
|
201
|
+
logger2.info("Replacing yarn occurrences in files...");
|
|
202
|
+
const results = await replaceInFile3({
|
|
203
|
+
allowEmptyPaths: true,
|
|
204
|
+
files: ["**/*.json", "**/*.md", "**/Dockerfile", "**/docker-compose.yml"],
|
|
205
|
+
from: [
|
|
206
|
+
"https://yarnpkg.com/",
|
|
207
|
+
"https://classic.yarnpkg.com/",
|
|
208
|
+
/yarn workspace (\S+)/g,
|
|
209
|
+
/yarn workspace/g,
|
|
210
|
+
/yarn install --immutable/g,
|
|
211
|
+
/yarn -q dlx/g,
|
|
212
|
+
/Yarn/gi
|
|
213
|
+
],
|
|
214
|
+
ignore: ["**/node_modules/**", "**/dist/**", "**/build/**"],
|
|
215
|
+
to: [
|
|
216
|
+
"https://pnpm.io/",
|
|
217
|
+
"https://pnpm.io/",
|
|
218
|
+
"pnpm --filter $1",
|
|
219
|
+
"pnpm --filter <package-selector>",
|
|
220
|
+
"pnpm install --frozen-lockfile",
|
|
221
|
+
"pnpm dlx",
|
|
222
|
+
"pnpm"
|
|
223
|
+
]
|
|
224
|
+
});
|
|
225
|
+
const count = results.reduce(
|
|
226
|
+
(acc, file) => file.hasChanged ? acc + 1 : acc,
|
|
227
|
+
0
|
|
228
|
+
);
|
|
229
|
+
logger2.info("Replaced yarn occurrences in {count} files", { count });
|
|
230
|
+
}
|
|
231
|
+
async function updateDXWorkflows() {
|
|
232
|
+
const logger2 = getLogger4(["dx-cli", "codemod"]);
|
|
233
|
+
logger2.info("Updating Github Workflows workflows...");
|
|
234
|
+
const sha = await getLatestCommitShaOrRef("pagopa", "dx");
|
|
235
|
+
const ignore = await updateJSCodeReview(sha);
|
|
236
|
+
await replaceInFile3({
|
|
237
|
+
allowEmptyPaths: true,
|
|
238
|
+
files: [".github/workflows/*.yaml"],
|
|
239
|
+
ignore,
|
|
240
|
+
processor: migrateWorkflow(sha)
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
async function writePnpmWorkspaceFile(workspaces) {
|
|
244
|
+
const pnpmWorkspace = {
|
|
245
|
+
packages: workspaces.length > 0 ? workspaces : ["apps/*", "packages/*"]
|
|
246
|
+
};
|
|
247
|
+
const yamlContent = YAML2.stringify(pnpmWorkspace);
|
|
248
|
+
await fs.writeFile("pnpm-workspace.yaml", yamlContent, "utf-8");
|
|
249
|
+
}
|
|
250
|
+
var apply = async (info) => {
|
|
251
|
+
if (info.packageManager === "pnpm") {
|
|
252
|
+
throw new Error("Project is already using pnpm");
|
|
34
253
|
}
|
|
254
|
+
const logger2 = getLogger4(["dx-cli", "codemod"]);
|
|
255
|
+
logger2.info("Remove unused fields from {file}", {
|
|
256
|
+
file: "package.json"
|
|
257
|
+
});
|
|
258
|
+
const workspaces = await preparePackageJsonForPnpm();
|
|
259
|
+
logger2.info("Create {file}", {
|
|
260
|
+
file: "pnpm-workspace.yaml"
|
|
261
|
+
});
|
|
262
|
+
await writePnpmWorkspaceFile(workspaces);
|
|
263
|
+
logger2.info("Remove node_modules and yarn files");
|
|
264
|
+
await removeFiles(
|
|
265
|
+
".yarnrc",
|
|
266
|
+
".yarnrc.yml",
|
|
267
|
+
"yarn.config.cjs",
|
|
268
|
+
".yarn",
|
|
269
|
+
".pnp.cjs",
|
|
270
|
+
".pnp.loader.cjs",
|
|
271
|
+
"node_modules"
|
|
272
|
+
);
|
|
273
|
+
logger2.info("Importing {source} to {target}", {
|
|
274
|
+
source: "yarn.lock",
|
|
275
|
+
target: "pnpm-lock.yaml"
|
|
276
|
+
});
|
|
277
|
+
try {
|
|
278
|
+
await fs.access("yarn.lock");
|
|
279
|
+
await $`corepack pnpm@latest import yarn.lock`;
|
|
280
|
+
await removeFiles("yarn.lock");
|
|
281
|
+
} catch {
|
|
282
|
+
logger2.info("No yarn.lock file found, skipping import.");
|
|
283
|
+
}
|
|
284
|
+
await $`corepack pnpm@latest add --config pnpm-plugin-pagopa`;
|
|
285
|
+
await replaceYarnOccurrences();
|
|
286
|
+
await updateDXWorkflows();
|
|
287
|
+
logger2.info("Setting pnpm as the package manager...");
|
|
288
|
+
await $`corepack use pnpm@latest`;
|
|
289
|
+
};
|
|
290
|
+
var use_pnpm_default = {
|
|
291
|
+
apply,
|
|
292
|
+
description: "A codemod that switches the project to use pnpm",
|
|
293
|
+
id: "use-pnpm"
|
|
35
294
|
};
|
|
36
295
|
|
|
37
296
|
// src/adapters/codemods/index.ts
|
|
38
297
|
var registry = new LocalCodemodRegistry();
|
|
39
|
-
registry.add(
|
|
298
|
+
registry.add(use_pnpm_default);
|
|
299
|
+
registry.add(useAzureAppsvc);
|
|
300
|
+
registry.add(updateCodeReview);
|
|
40
301
|
var codemods_default = registry;
|
|
41
302
|
|
|
42
303
|
// src/adapters/commander/index.ts
|
|
43
304
|
import { Command as Command6 } from "commander";
|
|
44
305
|
|
|
45
306
|
// src/adapters/commander/commands/codemod.ts
|
|
307
|
+
import { getLogger as getLogger5 } from "@logtape/logtape";
|
|
46
308
|
import { Command } from "commander";
|
|
47
309
|
var makeCodemodCommand = ({
|
|
48
310
|
applyCodemodById: applyCodemodById2,
|
|
@@ -50,16 +312,14 @@ var makeCodemodCommand = ({
|
|
|
50
312
|
}) => new Command("codemod").description("Manage and apply migration scripts to the repository").addCommand(
|
|
51
313
|
new Command("list").description("List available migration scripts").action(async function() {
|
|
52
314
|
await listCodemods2().andTee(
|
|
53
|
-
(codemods) => (
|
|
54
|
-
// eslint-disable-next-line no-console
|
|
55
|
-
console.table(codemods, ["id", "description"])
|
|
56
|
-
)
|
|
315
|
+
(codemods) => console.table(codemods, ["id", "description"])
|
|
57
316
|
).orTee((error) => this.error(error.message));
|
|
58
317
|
})
|
|
59
318
|
).addCommand(
|
|
60
319
|
new Command("apply").argument("<id>", "The id of the codemod to apply").description("Apply migration scripts to the repository").action(async function(id) {
|
|
320
|
+
const logger2 = getLogger5(["dx-cli", "codemod"]);
|
|
61
321
|
await applyCodemodById2(id).andTee(() => {
|
|
62
|
-
|
|
322
|
+
logger2.info("Codemod applied \u2705");
|
|
63
323
|
}).orTee((error) => this.error(error.message));
|
|
64
324
|
})
|
|
65
325
|
);
|
|
@@ -140,7 +400,7 @@ var checkMonorepoScripts = async (dependencies, config2) => {
|
|
|
140
400
|
|
|
141
401
|
// src/domain/repository.ts
|
|
142
402
|
import { ok as ok2 } from "neverthrow";
|
|
143
|
-
import
|
|
403
|
+
import fs2 from "path";
|
|
144
404
|
import coerce from "semver/functions/coerce.js";
|
|
145
405
|
import semverGte from "semver/functions/gte.js";
|
|
146
406
|
var isVersionValid = (version, minVersion) => {
|
|
@@ -155,7 +415,7 @@ var checkPreCommitConfig = async (dependencies, config2) => {
|
|
|
155
415
|
const { repositoryReader: repositoryReader2 } = dependencies;
|
|
156
416
|
const checkName = "Pre-commit Configuration";
|
|
157
417
|
const preCommitResult = await repositoryReader2.fileExists(
|
|
158
|
-
|
|
418
|
+
fs2.join(config2.repository.root, ".pre-commit-config.yaml")
|
|
159
419
|
);
|
|
160
420
|
if (preCommitResult.isOk() && preCommitResult.value) {
|
|
161
421
|
return ok2({
|
|
@@ -176,7 +436,7 @@ var checkTurboConfig = async (dependencies, config2) => {
|
|
|
176
436
|
const checkName = "Turbo Configuration";
|
|
177
437
|
const repoRoot2 = config2.repository.root;
|
|
178
438
|
const turboResult = await repositoryReader2.fileExists(
|
|
179
|
-
|
|
439
|
+
fs2.join(repoRoot2, "turbo.json")
|
|
180
440
|
);
|
|
181
441
|
if (turboResult.isErr()) {
|
|
182
442
|
return ok2({
|
|
@@ -315,7 +575,7 @@ var makeDoctorCommand = (dependencies, config2) => new Command2().name("doctor")
|
|
|
315
575
|
import { Command as Command3 } from "commander";
|
|
316
576
|
|
|
317
577
|
// src/domain/info.ts
|
|
318
|
-
import { getLogger } from "@logtape/logtape";
|
|
578
|
+
import { getLogger as getLogger6 } from "@logtape/logtape";
|
|
319
579
|
import { join } from "path";
|
|
320
580
|
var detectFromLockFile = async (dependencies, config2) => {
|
|
321
581
|
const { repositoryReader: repositoryReader2 } = dependencies;
|
|
@@ -341,7 +601,7 @@ var detectPackageManager = async (dependencies, config2) => {
|
|
|
341
601
|
var detectNodeVersion = async ({ repositoryReader: repositoryReader2 }, nodeVersionFilePath) => await repositoryReader2.readFile(nodeVersionFilePath).map((nodeVersion) => nodeVersion.trim()).unwrapOr(void 0);
|
|
342
602
|
var detectTerraformVersion = async ({ repositoryReader: repositoryReader2 }, terraformVersionFilePath) => await repositoryReader2.readFile(terraformVersionFilePath).map((tfVersion) => tfVersion.trim()).unwrapOr(void 0);
|
|
343
603
|
var detectTurboVersion = ({ devDependencies }) => devDependencies.get("turbo")?.trim();
|
|
344
|
-
var getInfo =
|
|
604
|
+
var getInfo = (dependencies, config2) => async () => ({
|
|
345
605
|
node: await detectNodeVersion(
|
|
346
606
|
{ repositoryReader: dependencies.repositoryReader },
|
|
347
607
|
`${config2.repository.root}/.node-version`
|
|
@@ -354,13 +614,13 @@ var getInfo = async (dependencies, config2) => ({
|
|
|
354
614
|
turbo: detectTurboVersion(dependencies.packageJson)
|
|
355
615
|
});
|
|
356
616
|
var printInfo = (result) => {
|
|
357
|
-
const logger2 =
|
|
617
|
+
const logger2 = getLogger6("json");
|
|
358
618
|
logger2.info(JSON.stringify(result));
|
|
359
619
|
};
|
|
360
620
|
|
|
361
621
|
// src/adapters/commander/commands/info.ts
|
|
362
622
|
var makeInfoCommand = (dependencies, config2) => new Command3().name("info").description("Display information about the project").action(async () => {
|
|
363
|
-
const result = await getInfo(dependencies, config2);
|
|
623
|
+
const result = await getInfo(dependencies, config2)();
|
|
364
624
|
printInfo(result);
|
|
365
625
|
});
|
|
366
626
|
|
|
@@ -402,22 +662,22 @@ var makeInitCommand = () => new Command4().name("init").description(
|
|
|
402
662
|
import { Command as Command5 } from "commander";
|
|
403
663
|
|
|
404
664
|
// src/domain/version.ts
|
|
405
|
-
import { getLogger as
|
|
665
|
+
import { getLogger as getLogger7 } from "@logtape/logtape";
|
|
406
666
|
function printVersion() {
|
|
407
|
-
const logger2 =
|
|
408
|
-
logger2.info(`dx CLI version: ${"0.
|
|
667
|
+
const logger2 = getLogger7(["dx-cli", "version"]);
|
|
668
|
+
logger2.info(`dx CLI version: ${"0.7.0"}`);
|
|
409
669
|
}
|
|
410
670
|
|
|
411
671
|
// src/adapters/commander/commands/version.ts
|
|
412
672
|
var makeVersionCommand = () => new Command5().name("version").alias("v").action(() => printVersion());
|
|
413
673
|
|
|
414
674
|
// src/adapters/commander/index.ts
|
|
415
|
-
var makeCli = (deps2, config2) => {
|
|
675
|
+
var makeCli = (deps2, config2, cliDeps) => {
|
|
416
676
|
const program2 = new Command6();
|
|
417
|
-
program2.name("dx").description("The CLI for DX-Platform").version("0.
|
|
677
|
+
program2.name("dx").description("The CLI for DX-Platform").version("0.7.0");
|
|
418
678
|
program2.addCommand(makeDoctorCommand(deps2, config2));
|
|
419
679
|
if (process.env.ENABLE_CODEMODS) {
|
|
420
|
-
program2.addCommand(makeCodemodCommand(
|
|
680
|
+
program2.addCommand(makeCodemodCommand(cliDeps));
|
|
421
681
|
}
|
|
422
682
|
if (process.env.ENABLE_INIT_COMMAND) {
|
|
423
683
|
program2.addCommand(makeInitCommand());
|
|
@@ -428,9 +688,9 @@ var makeCli = (deps2, config2) => {
|
|
|
428
688
|
};
|
|
429
689
|
|
|
430
690
|
// src/adapters/logtape/validation-reporter.ts
|
|
431
|
-
import { getLogger as
|
|
691
|
+
import { getLogger as getLogger8 } from "@logtape/logtape";
|
|
432
692
|
var makeValidationReporter = () => {
|
|
433
|
-
const logger2 =
|
|
693
|
+
const logger2 = getLogger8(["dx-cli", "validation"]);
|
|
434
694
|
return {
|
|
435
695
|
reportCheckResult(result) {
|
|
436
696
|
if (result.isValid) {
|
|
@@ -448,7 +708,7 @@ import * as process3 from "process";
|
|
|
448
708
|
|
|
449
709
|
// src/adapters/node/fs/file-reader.ts
|
|
450
710
|
import { ResultAsync as ResultAsync6 } from "neverthrow";
|
|
451
|
-
import
|
|
711
|
+
import fs3 from "fs/promises";
|
|
452
712
|
|
|
453
713
|
// src/adapters/zod/index.ts
|
|
454
714
|
import { ResultAsync as ResultAsync5 } from "neverthrow";
|
|
@@ -465,13 +725,13 @@ var parseJson = Result2.fromThrowable(
|
|
|
465
725
|
);
|
|
466
726
|
|
|
467
727
|
// src/adapters/node/fs/file-reader.ts
|
|
468
|
-
var
|
|
469
|
-
|
|
728
|
+
var readFile2 = (filePath) => ResultAsync6.fromPromise(
|
|
729
|
+
fs3.readFile(filePath, "utf-8"),
|
|
470
730
|
(cause) => new Error(`Failed to read file: ${filePath}`, { cause })
|
|
471
731
|
);
|
|
472
|
-
var readFileAndDecode = (filePath, schema) =>
|
|
732
|
+
var readFileAndDecode = (filePath, schema) => readFile2(filePath).andThen(parseJson).andThen(decode(schema));
|
|
473
733
|
var fileExists = (path2) => ResultAsync6.fromPromise(
|
|
474
|
-
|
|
734
|
+
fs3.stat(path2),
|
|
475
735
|
() => new Error(`${path2} not found.`)
|
|
476
736
|
).map(() => true);
|
|
477
737
|
|
|
@@ -501,7 +761,7 @@ var makePackageJsonReader = () => ({
|
|
|
501
761
|
|
|
502
762
|
// src/adapters/node/repository.ts
|
|
503
763
|
import * as glob from "glob";
|
|
504
|
-
import { okAsync as
|
|
764
|
+
import { okAsync as okAsync2, ResultAsync as ResultAsync7 } from "neverthrow";
|
|
505
765
|
import * as path from "path";
|
|
506
766
|
import { z as z3 } from "zod/v4";
|
|
507
767
|
|
|
@@ -535,11 +795,11 @@ var resolveWorkspacePattern = (repoRoot2, pattern) => ResultAsync7.fromPromise(
|
|
|
535
795
|
subDirectories.map((directory) => path.join(repoRoot2, directory))
|
|
536
796
|
)
|
|
537
797
|
);
|
|
538
|
-
var getWorkspaces = (repoRoot2) =>
|
|
798
|
+
var getWorkspaces = (repoRoot2) => readFile2(path.join(repoRoot2, "pnpm-workspace.yaml")).andThen(parseYaml).andThen(
|
|
539
799
|
(obj) => (
|
|
540
800
|
// If no packages are defined, go on with an empty array
|
|
541
801
|
decode(z3.object({ packages: z3.array(z3.string()) }))(obj).orElse(
|
|
542
|
-
() =>
|
|
802
|
+
() => okAsync2({ packages: [] })
|
|
543
803
|
)
|
|
544
804
|
)
|
|
545
805
|
).andThen(
|
|
@@ -567,7 +827,7 @@ var makeRepositoryReader = () => ({
|
|
|
567
827
|
fileExists,
|
|
568
828
|
findRepositoryRoot,
|
|
569
829
|
getWorkspaces,
|
|
570
|
-
readFile
|
|
830
|
+
readFile: readFile2
|
|
571
831
|
});
|
|
572
832
|
|
|
573
833
|
// src/config.ts
|
|
@@ -581,10 +841,23 @@ var getConfig = (repositoryRoot2) => ({
|
|
|
581
841
|
});
|
|
582
842
|
|
|
583
843
|
// src/use-cases/apply-codemod.ts
|
|
584
|
-
import { errAsync, okAsync as
|
|
585
|
-
var
|
|
586
|
-
(codemod) => codemod ?
|
|
587
|
-
)
|
|
844
|
+
import { errAsync, okAsync as okAsync3, ResultAsync as ResultAsync8 } from "neverthrow";
|
|
845
|
+
var getCodemodById = (registry2, id) => registry2.getById(id).andThen(
|
|
846
|
+
(codemod) => codemod ? okAsync3(codemod) : errAsync(new Error(`Codemod with id ${id} not found`))
|
|
847
|
+
);
|
|
848
|
+
var safeGetInfo = (getInfo2) => ResultAsync8.fromPromise(
|
|
849
|
+
getInfo2(),
|
|
850
|
+
(error) => new Error("Failed to get info", { cause: error })
|
|
851
|
+
);
|
|
852
|
+
var applyCodemodById = (registry2, getInfo2) => (id) => ResultAsync8.combine([
|
|
853
|
+
safeGetInfo(getInfo2),
|
|
854
|
+
getCodemodById(registry2, id)
|
|
855
|
+
]).andThen(
|
|
856
|
+
([info, codemod]) => ResultAsync8.fromPromise(codemod.apply(info), (error) => {
|
|
857
|
+
const message = error instanceof Error ? `: ${error.message}` : "";
|
|
858
|
+
return new Error("Failed to apply codemod" + message, { cause: error });
|
|
859
|
+
})
|
|
860
|
+
);
|
|
588
861
|
|
|
589
862
|
// src/use-cases/list-codemods.ts
|
|
590
863
|
var listCodemods = (registry2) => () => registry2.getAll();
|
|
@@ -607,7 +880,7 @@ await configure({
|
|
|
607
880
|
}
|
|
608
881
|
}
|
|
609
882
|
});
|
|
610
|
-
var logger =
|
|
883
|
+
var logger = getLogger9(["dx-cli"]);
|
|
611
884
|
var repositoryReader = makeRepositoryReader();
|
|
612
885
|
var packageJsonReader = makePackageJsonReader();
|
|
613
886
|
var validationReporter = makeValidationReporter();
|
|
@@ -626,13 +899,15 @@ if (repoPackageJson.isErr()) {
|
|
|
626
899
|
}
|
|
627
900
|
var packageJson = repoPackageJson.value;
|
|
628
901
|
var deps = {
|
|
629
|
-
applyCodemodById: applyCodemodById(codemods_default),
|
|
630
|
-
listCodemods: listCodemods(codemods_default),
|
|
631
902
|
packageJson,
|
|
632
903
|
packageJsonReader,
|
|
633
904
|
repositoryReader,
|
|
634
905
|
validationReporter
|
|
635
906
|
};
|
|
636
907
|
var config = getConfig(repositoryRoot);
|
|
637
|
-
var
|
|
908
|
+
var useCases = {
|
|
909
|
+
applyCodemodById: applyCodemodById(codemods_default, getInfo(deps, config)),
|
|
910
|
+
listCodemods: listCodemods(codemods_default)
|
|
911
|
+
};
|
|
912
|
+
var program = makeCli(deps, config, useCases);
|
|
638
913
|
program.parse();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pagopa/dx-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A CLI useful to manage DX tools.",
|
|
6
6
|
"repository": {
|
|
@@ -22,9 +22,12 @@
|
|
|
22
22
|
"@logtape/logtape": "^1.0.0",
|
|
23
23
|
"commander": "^14.0.0",
|
|
24
24
|
"core-js": "^3.44.0",
|
|
25
|
+
"execa": "^9.6.0",
|
|
25
26
|
"glob": "^11.0.3",
|
|
26
27
|
"neverthrow": "^8.2.0",
|
|
27
28
|
"node-plop": "^0.32.1",
|
|
29
|
+
"octokit": "^5.0.3",
|
|
30
|
+
"replace-in-file": "^8.3.0",
|
|
28
31
|
"semver": "^7.7.2",
|
|
29
32
|
"yaml": "^2.8.0",
|
|
30
33
|
"zod": "^3.25.28",
|