@pagopa/dx-cli 0.4.4 → 0.6.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 +132 -24
- package/package.json +7 -5
package/bin/index.js
CHANGED
|
@@ -4,11 +4,68 @@
|
|
|
4
4
|
import "core-js/actual/set/index.js";
|
|
5
5
|
import { configure, getConsoleSink, getLogger as getLogger4 } from "@logtape/logtape";
|
|
6
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
|
+
};
|
|
18
|
+
|
|
19
|
+
// src/adapters/codemods/registry.ts
|
|
20
|
+
import { okAsync as okAsync2 } from "neverthrow";
|
|
21
|
+
var LocalCodemodRegistry = class {
|
|
22
|
+
#m;
|
|
23
|
+
constructor() {
|
|
24
|
+
this.#m = /* @__PURE__ */ new Map();
|
|
25
|
+
}
|
|
26
|
+
add(codemod) {
|
|
27
|
+
this.#m.set(codemod.id, codemod);
|
|
28
|
+
}
|
|
29
|
+
getAll() {
|
|
30
|
+
return okAsync2(Array.from(this.#m.values()));
|
|
31
|
+
}
|
|
32
|
+
getById(id) {
|
|
33
|
+
return okAsync2(this.#m.get(id));
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
// src/adapters/codemods/index.ts
|
|
38
|
+
var registry = new LocalCodemodRegistry();
|
|
39
|
+
registry.add(example_default);
|
|
40
|
+
var codemods_default = registry;
|
|
41
|
+
|
|
7
42
|
// src/adapters/commander/index.ts
|
|
8
|
-
import { Command as
|
|
43
|
+
import { Command as Command6 } from "commander";
|
|
9
44
|
|
|
10
|
-
// src/adapters/commander/commands/
|
|
45
|
+
// src/adapters/commander/commands/codemod.ts
|
|
11
46
|
import { Command } from "commander";
|
|
47
|
+
var makeCodemodCommand = ({
|
|
48
|
+
applyCodemodById: applyCodemodById2,
|
|
49
|
+
listCodemods: listCodemods2
|
|
50
|
+
}) => new Command("codemod").description("Manage and apply migration scripts to the repository").addCommand(
|
|
51
|
+
new Command("list").description("List available migration scripts").action(async function() {
|
|
52
|
+
await listCodemods2().andTee(
|
|
53
|
+
(codemods) => (
|
|
54
|
+
// eslint-disable-next-line no-console
|
|
55
|
+
console.table(codemods, ["id", "description"])
|
|
56
|
+
)
|
|
57
|
+
).orTee((error) => this.error(error.message));
|
|
58
|
+
})
|
|
59
|
+
).addCommand(
|
|
60
|
+
new Command("apply").argument("<id>", "The id of the codemod to apply").description("Apply migration scripts to the repository").action(async function(id) {
|
|
61
|
+
await applyCodemodById2(id).andTee(() => {
|
|
62
|
+
console.log("Codemod applied successfully \u2705");
|
|
63
|
+
}).orTee((error) => this.error(error.message));
|
|
64
|
+
})
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
// src/adapters/commander/commands/doctor.ts
|
|
68
|
+
import { Command as Command2 } from "commander";
|
|
12
69
|
import * as process2 from "process";
|
|
13
70
|
|
|
14
71
|
// src/domain/doctor.ts
|
|
@@ -245,7 +302,7 @@ var toDoctorResult = (validationCheckResults) => {
|
|
|
245
302
|
var printDoctorResult = ({ validationReporter: validationReporter2 }, result) => result.checks.map(validationReporter2.reportCheckResult);
|
|
246
303
|
|
|
247
304
|
// src/adapters/commander/commands/doctor.ts
|
|
248
|
-
var makeDoctorCommand = (dependencies, config2) => new
|
|
305
|
+
var makeDoctorCommand = (dependencies, config2) => new Command2().name("doctor").description(
|
|
249
306
|
"Verify the repository setup according to the DevEx guidelines"
|
|
250
307
|
).action(async () => {
|
|
251
308
|
const result = await runDoctor(dependencies, config2);
|
|
@@ -255,7 +312,7 @@ var makeDoctorCommand = (dependencies, config2) => new Command().name("doctor").
|
|
|
255
312
|
});
|
|
256
313
|
|
|
257
314
|
// src/adapters/commander/commands/info.ts
|
|
258
|
-
import { Command as
|
|
315
|
+
import { Command as Command3 } from "commander";
|
|
259
316
|
|
|
260
317
|
// src/domain/info.ts
|
|
261
318
|
import { getLogger } from "@logtape/logtape";
|
|
@@ -302,29 +359,69 @@ var printInfo = (result) => {
|
|
|
302
359
|
};
|
|
303
360
|
|
|
304
361
|
// src/adapters/commander/commands/info.ts
|
|
305
|
-
var makeInfoCommand = (dependencies, config2) => new
|
|
362
|
+
var makeInfoCommand = (dependencies, config2) => new Command3().name("info").description("Display information about the project").action(async () => {
|
|
306
363
|
const result = await getInfo(dependencies, config2);
|
|
307
364
|
printInfo(result);
|
|
308
365
|
});
|
|
309
366
|
|
|
367
|
+
// src/adapters/commander/commands/init.ts
|
|
368
|
+
import scaffoldMonorepo from "@pagopa/monorepo-generator";
|
|
369
|
+
import { Command as Command4 } from "commander";
|
|
370
|
+
import { Result, ResultAsync as ResultAsync4 } from "neverthrow";
|
|
371
|
+
import nodePlop from "node-plop";
|
|
372
|
+
var initPlop = () => ResultAsync4.fromPromise(
|
|
373
|
+
nodePlop(),
|
|
374
|
+
() => new Error("Failed to initialize plop")
|
|
375
|
+
);
|
|
376
|
+
var getGenerator = (plopAPI) => Result.fromThrowable(
|
|
377
|
+
plopAPI.getGenerator,
|
|
378
|
+
() => new Error("Generator not found")
|
|
379
|
+
);
|
|
380
|
+
var runGenerator = (generator) => ResultAsync4.fromPromise(
|
|
381
|
+
generator.runPrompts(),
|
|
382
|
+
() => new Error("Failed to run the generator prompts")
|
|
383
|
+
).andThen(
|
|
384
|
+
(answers) => ResultAsync4.fromPromise(
|
|
385
|
+
generator.runActions(answers),
|
|
386
|
+
() => new Error("Failed to run the generator actions")
|
|
387
|
+
)
|
|
388
|
+
);
|
|
389
|
+
var makeInitCommand = () => new Command4().name("init").description(
|
|
390
|
+
"Command to initialize resources (like projects, subscriptions, ...)"
|
|
391
|
+
).addCommand(
|
|
392
|
+
new Command4("project").description("Initialize a new monorepo project").action(async function() {
|
|
393
|
+
await initPlop().andTee(scaffoldMonorepo).andThen((plop) => getGenerator(plop)("monorepo")).andThen(runGenerator).andTee(() => {
|
|
394
|
+
console.log("Monorepo initialized successfully \u2705");
|
|
395
|
+
}).orTee((err2) => {
|
|
396
|
+
this.error(err2.message);
|
|
397
|
+
});
|
|
398
|
+
})
|
|
399
|
+
);
|
|
400
|
+
|
|
310
401
|
// src/adapters/commander/commands/version.ts
|
|
311
|
-
import { Command as
|
|
402
|
+
import { Command as Command5 } from "commander";
|
|
312
403
|
|
|
313
404
|
// src/domain/version.ts
|
|
314
405
|
import { getLogger as getLogger2 } from "@logtape/logtape";
|
|
315
406
|
function printVersion() {
|
|
316
407
|
const logger2 = getLogger2(["dx-cli", "version"]);
|
|
317
|
-
logger2.info(`dx CLI version: ${"0.
|
|
408
|
+
logger2.info(`dx CLI version: ${"0.6.0"}`);
|
|
318
409
|
}
|
|
319
410
|
|
|
320
411
|
// src/adapters/commander/commands/version.ts
|
|
321
|
-
var makeVersionCommand = () => new
|
|
412
|
+
var makeVersionCommand = () => new Command5().name("version").alias("v").action(() => printVersion());
|
|
322
413
|
|
|
323
414
|
// src/adapters/commander/index.ts
|
|
324
415
|
var makeCli = (deps2, config2) => {
|
|
325
|
-
const program2 = new
|
|
326
|
-
program2.name("dx").description("The CLI for DX-Platform").version("0.
|
|
416
|
+
const program2 = new Command6();
|
|
417
|
+
program2.name("dx").description("The CLI for DX-Platform").version("0.6.0");
|
|
327
418
|
program2.addCommand(makeDoctorCommand(deps2, config2));
|
|
419
|
+
if (process.env.ENABLE_CODEMODS) {
|
|
420
|
+
program2.addCommand(makeCodemodCommand(deps2));
|
|
421
|
+
}
|
|
422
|
+
if (process.env.ENABLE_INIT_COMMAND) {
|
|
423
|
+
program2.addCommand(makeInitCommand());
|
|
424
|
+
}
|
|
328
425
|
program2.addCommand(makeVersionCommand());
|
|
329
426
|
program2.addCommand(makeInfoCommand(deps2, config2));
|
|
330
427
|
return program2;
|
|
@@ -350,30 +447,30 @@ import { join as join2 } from "path";
|
|
|
350
447
|
import * as process3 from "process";
|
|
351
448
|
|
|
352
449
|
// src/adapters/node/fs/file-reader.ts
|
|
353
|
-
import { ResultAsync as
|
|
450
|
+
import { ResultAsync as ResultAsync6 } from "neverthrow";
|
|
354
451
|
import fs2 from "fs/promises";
|
|
355
452
|
|
|
356
453
|
// src/adapters/zod/index.ts
|
|
357
|
-
import { ResultAsync as
|
|
358
|
-
var decode = (schema) =>
|
|
454
|
+
import { ResultAsync as ResultAsync5 } from "neverthrow";
|
|
455
|
+
var decode = (schema) => ResultAsync5.fromThrowable(
|
|
359
456
|
schema.parseAsync,
|
|
360
457
|
(cause) => new Error("File content is not valid for the given schema", { cause })
|
|
361
458
|
);
|
|
362
459
|
|
|
363
460
|
// src/adapters/node/json/index.ts
|
|
364
|
-
import { Result } from "neverthrow";
|
|
365
|
-
var parseJson =
|
|
461
|
+
import { Result as Result2 } from "neverthrow";
|
|
462
|
+
var parseJson = Result2.fromThrowable(
|
|
366
463
|
JSON.parse,
|
|
367
464
|
(cause) => new Error("Failed to parse JSON", { cause })
|
|
368
465
|
);
|
|
369
466
|
|
|
370
467
|
// src/adapters/node/fs/file-reader.ts
|
|
371
|
-
var readFile = (filePath) =>
|
|
468
|
+
var readFile = (filePath) => ResultAsync6.fromPromise(
|
|
372
469
|
fs2.readFile(filePath, "utf-8"),
|
|
373
470
|
(cause) => new Error(`Failed to read file: ${filePath}`, { cause })
|
|
374
471
|
);
|
|
375
472
|
var readFileAndDecode = (filePath, schema) => readFile(filePath).andThen(parseJson).andThen(decode(schema));
|
|
376
|
-
var fileExists = (path2) =>
|
|
473
|
+
var fileExists = (path2) => ResultAsync6.fromPromise(
|
|
377
474
|
fs2.stat(path2),
|
|
378
475
|
() => new Error(`${path2} not found.`)
|
|
379
476
|
).map(() => true);
|
|
@@ -404,14 +501,14 @@ var makePackageJsonReader = () => ({
|
|
|
404
501
|
|
|
405
502
|
// src/adapters/node/repository.ts
|
|
406
503
|
import * as glob from "glob";
|
|
407
|
-
import { okAsync, ResultAsync as
|
|
504
|
+
import { okAsync as okAsync3, ResultAsync as ResultAsync7 } from "neverthrow";
|
|
408
505
|
import * as path from "path";
|
|
409
506
|
import { z as z3 } from "zod/v4";
|
|
410
507
|
|
|
411
508
|
// src/adapters/yaml/index.ts
|
|
412
|
-
import { Result as
|
|
509
|
+
import { Result as Result3 } from "neverthrow";
|
|
413
510
|
import yaml from "yaml";
|
|
414
|
-
var parseYaml =
|
|
511
|
+
var parseYaml = Result3.fromThrowable(
|
|
415
512
|
(content) => yaml.parse(content),
|
|
416
513
|
() => new Error("Failed to parse YAML")
|
|
417
514
|
);
|
|
@@ -425,7 +522,7 @@ var findRepositoryRoot = (dir = process.cwd()) => {
|
|
|
425
522
|
)
|
|
426
523
|
).map(() => dir);
|
|
427
524
|
};
|
|
428
|
-
var resolveWorkspacePattern = (repoRoot2, pattern) =>
|
|
525
|
+
var resolveWorkspacePattern = (repoRoot2, pattern) => ResultAsync7.fromPromise(
|
|
429
526
|
// For now it is not possible to use the fs.glob function (from node:fs/promises)
|
|
430
527
|
// because it is not possible to run it on Node 20.x
|
|
431
528
|
glob.glob(pattern, { cwd: repoRoot2 }),
|
|
@@ -442,13 +539,13 @@ var getWorkspaces = (repoRoot2) => readFile(path.join(repoRoot2, "pnpm-workspace
|
|
|
442
539
|
(obj) => (
|
|
443
540
|
// If no packages are defined, go on with an empty array
|
|
444
541
|
decode(z3.object({ packages: z3.array(z3.string()) }))(obj).orElse(
|
|
445
|
-
() =>
|
|
542
|
+
() => okAsync3({ packages: [] })
|
|
446
543
|
)
|
|
447
544
|
)
|
|
448
545
|
).andThen(
|
|
449
546
|
({ packages }) => (
|
|
450
547
|
// For every package pattern in the pnpm-workspace.yaml file, get the list of subdirectories
|
|
451
|
-
|
|
548
|
+
ResultAsync7.combine(
|
|
452
549
|
packages.map((pattern) => resolveWorkspacePattern(repoRoot2, pattern))
|
|
453
550
|
).map((workspacesList) => workspacesList.flat()).andThen((workspaceFolders) => {
|
|
454
551
|
const workspaceResults = workspaceFolders.map(
|
|
@@ -462,7 +559,7 @@ var getWorkspaces = (repoRoot2) => readFile(path.join(repoRoot2, "pnpm-workspace
|
|
|
462
559
|
)
|
|
463
560
|
)
|
|
464
561
|
);
|
|
465
|
-
return
|
|
562
|
+
return ResultAsync7.combine(workspaceResults);
|
|
466
563
|
})
|
|
467
564
|
)
|
|
468
565
|
);
|
|
@@ -483,6 +580,15 @@ var getConfig = (repositoryRoot2) => ({
|
|
|
483
580
|
}
|
|
484
581
|
});
|
|
485
582
|
|
|
583
|
+
// src/use-cases/apply-codemod.ts
|
|
584
|
+
import { errAsync, okAsync as okAsync4 } from "neverthrow";
|
|
585
|
+
var applyCodemodById = (registry2) => (id) => registry2.getById(id).andThen(
|
|
586
|
+
(codemod) => codemod ? okAsync4(codemod) : errAsync(new Error(`Codemod with id ${id} not found`))
|
|
587
|
+
).andThen((codemod) => codemod.apply());
|
|
588
|
+
|
|
589
|
+
// src/use-cases/list-codemods.ts
|
|
590
|
+
var listCodemods = (registry2) => () => registry2.getAll();
|
|
591
|
+
|
|
486
592
|
// src/index.ts
|
|
487
593
|
await configure({
|
|
488
594
|
loggers: [
|
|
@@ -520,6 +626,8 @@ if (repoPackageJson.isErr()) {
|
|
|
520
626
|
}
|
|
521
627
|
var packageJson = repoPackageJson.value;
|
|
522
628
|
var deps = {
|
|
629
|
+
applyCodemodById: applyCodemodById(codemods_default),
|
|
630
|
+
listCodemods: listCodemods(codemods_default),
|
|
523
631
|
packageJson,
|
|
524
632
|
packageJsonReader,
|
|
525
633
|
repositoryReader,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pagopa/dx-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A CLI useful to manage DX tools.",
|
|
6
6
|
"repository": {
|
|
@@ -24,14 +24,16 @@
|
|
|
24
24
|
"core-js": "^3.44.0",
|
|
25
25
|
"glob": "^11.0.3",
|
|
26
26
|
"neverthrow": "^8.2.0",
|
|
27
|
+
"node-plop": "^0.32.1",
|
|
27
28
|
"semver": "^7.7.2",
|
|
28
29
|
"yaml": "^2.8.0",
|
|
29
|
-
"zod": "^3.25.28"
|
|
30
|
+
"zod": "^3.25.28",
|
|
31
|
+
"@pagopa/monorepo-generator": "^0.6.0"
|
|
30
32
|
},
|
|
31
33
|
"devDependencies": {
|
|
32
34
|
"@tsconfig/node22": "22.0.2",
|
|
33
35
|
"@types/node": "^22.16.2",
|
|
34
|
-
"@types/semver": "^7.7.
|
|
36
|
+
"@types/semver": "^7.7.1",
|
|
35
37
|
"@vitest/coverage-v8": "^3.2.4",
|
|
36
38
|
"eslint": "^9.30.0",
|
|
37
39
|
"memfs": "^4.23.0",
|
|
@@ -40,7 +42,7 @@
|
|
|
40
42
|
"typescript": "~5.8.3",
|
|
41
43
|
"vitest": "^3.2.4",
|
|
42
44
|
"vitest-mock-extended": "^3.1.0",
|
|
43
|
-
"@pagopa/eslint-config": "^5.
|
|
45
|
+
"@pagopa/eslint-config": "^5.1.0"
|
|
44
46
|
},
|
|
45
47
|
"engines": {
|
|
46
48
|
"node": ">=22.0.0"
|
|
@@ -53,6 +55,6 @@
|
|
|
53
55
|
"format:check": "prettier --check .",
|
|
54
56
|
"typecheck": "tsc --noEmit",
|
|
55
57
|
"test": "vitest run",
|
|
56
|
-
"test:coverage": "vitest --coverage"
|
|
58
|
+
"test:coverage": "vitest run --coverage"
|
|
57
59
|
}
|
|
58
60
|
}
|