@pagopa/dx-cli 0.4.2 → 0.4.4
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 +125 -40
- package/package.json +4 -1
package/bin/index.js
CHANGED
|
@@ -22,9 +22,8 @@ var scriptSchema = z.object({
|
|
|
22
22
|
name: ScriptName,
|
|
23
23
|
script: z.string()
|
|
24
24
|
});
|
|
25
|
-
var DependencyName = z.string().brand();
|
|
26
25
|
var dependencySchema = z.object({
|
|
27
|
-
name:
|
|
26
|
+
name: z.string(),
|
|
28
27
|
version: z.string()
|
|
29
28
|
});
|
|
30
29
|
var PackageName = z.string().min(1).brand();
|
|
@@ -36,12 +35,9 @@ var scriptsSchema = z.record(ScriptName, z.string()).optional().transform(
|
|
|
36
35
|
]) : []
|
|
37
36
|
)
|
|
38
37
|
);
|
|
39
|
-
var dependenciesSchema = z.record(
|
|
38
|
+
var dependenciesSchema = z.record(z.string(), z.string()).optional().transform(
|
|
40
39
|
(obj) => new Map(
|
|
41
|
-
obj ? Object.entries(obj).map(([name, version]) => [
|
|
42
|
-
DependencyName.parse(name),
|
|
43
|
-
version
|
|
44
|
-
]) : []
|
|
40
|
+
obj ? Object.entries(obj).map(([name, version]) => [name, version]) : []
|
|
45
41
|
)
|
|
46
42
|
);
|
|
47
43
|
var packageManagerSchema = z.enum(["npm", "pnpm", "yarn"]);
|
|
@@ -167,6 +163,40 @@ var checkTurboConfig = async (dependencies, config2) => {
|
|
|
167
163
|
});
|
|
168
164
|
};
|
|
169
165
|
|
|
166
|
+
// src/domain/workspace.ts
|
|
167
|
+
import { ok as ok3 } from "neverthrow";
|
|
168
|
+
import { z as z2 } from "zod/v4";
|
|
169
|
+
var WorkspaceName = z2.string().min(1).brand();
|
|
170
|
+
var workspaceSchema = z2.object({
|
|
171
|
+
name: WorkspaceName,
|
|
172
|
+
path: z2.string()
|
|
173
|
+
});
|
|
174
|
+
var checkWorkspaces = async (dependencies, monorepoDir) => {
|
|
175
|
+
const { repositoryReader: repositoryReader2 } = dependencies;
|
|
176
|
+
const checkName = "Workspaces";
|
|
177
|
+
const workspacesResult = await repositoryReader2.getWorkspaces(monorepoDir);
|
|
178
|
+
if (workspacesResult.isErr()) {
|
|
179
|
+
return ok3({
|
|
180
|
+
checkName,
|
|
181
|
+
errorMessage: "Something is wrong with the workspaces configuration. If you need help, please contact the DevEx team.",
|
|
182
|
+
isValid: false
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
const { length: workspaceNumber } = workspacesResult.value;
|
|
186
|
+
if (workspaceNumber === 0) {
|
|
187
|
+
return ok3({
|
|
188
|
+
checkName,
|
|
189
|
+
errorMessage: "No workspace configuration found. Make sure to configure workspaces in pnpm-workspace.yaml.",
|
|
190
|
+
isValid: false
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
return ok3({
|
|
194
|
+
checkName,
|
|
195
|
+
isValid: true,
|
|
196
|
+
successMessage: `Found ${workspaceNumber} workspace${workspaceNumber === 1 ? "" : "s"}`
|
|
197
|
+
});
|
|
198
|
+
};
|
|
199
|
+
|
|
170
200
|
// src/domain/doctor.ts
|
|
171
201
|
var runDoctor = (dependencies, config2) => {
|
|
172
202
|
const doctorChecks = [
|
|
@@ -181,6 +211,10 @@ var runDoctor = (dependencies, config2) => {
|
|
|
181
211
|
ResultAsync3.fromPromise(
|
|
182
212
|
checkMonorepoScripts(dependencies, config2),
|
|
183
213
|
() => new Error("Error checking monorepo scripts")
|
|
214
|
+
),
|
|
215
|
+
ResultAsync3.fromPromise(
|
|
216
|
+
checkWorkspaces(dependencies, config2.repository.root),
|
|
217
|
+
() => new Error("Error checking monorepo scripts")
|
|
184
218
|
)
|
|
185
219
|
];
|
|
186
220
|
return ResultAsync3.combine(doctorChecks).match(
|
|
@@ -249,6 +283,7 @@ var detectPackageManager = async (dependencies, config2) => {
|
|
|
249
283
|
};
|
|
250
284
|
var detectNodeVersion = async ({ repositoryReader: repositoryReader2 }, nodeVersionFilePath) => await repositoryReader2.readFile(nodeVersionFilePath).map((nodeVersion) => nodeVersion.trim()).unwrapOr(void 0);
|
|
251
285
|
var detectTerraformVersion = async ({ repositoryReader: repositoryReader2 }, terraformVersionFilePath) => await repositoryReader2.readFile(terraformVersionFilePath).map((tfVersion) => tfVersion.trim()).unwrapOr(void 0);
|
|
286
|
+
var detectTurboVersion = ({ devDependencies }) => devDependencies.get("turbo")?.trim();
|
|
252
287
|
var getInfo = async (dependencies, config2) => ({
|
|
253
288
|
node: await detectNodeVersion(
|
|
254
289
|
{ repositoryReader: dependencies.repositoryReader },
|
|
@@ -258,7 +293,8 @@ var getInfo = async (dependencies, config2) => ({
|
|
|
258
293
|
terraform: await detectTerraformVersion(
|
|
259
294
|
{ repositoryReader: dependencies.repositoryReader },
|
|
260
295
|
`${config2.repository.root}/.terraform-version`
|
|
261
|
-
)
|
|
296
|
+
),
|
|
297
|
+
turbo: detectTurboVersion(dependencies.packageJson)
|
|
262
298
|
});
|
|
263
299
|
var printInfo = (result) => {
|
|
264
300
|
const logger2 = getLogger("json");
|
|
@@ -278,7 +314,7 @@ import { Command as Command3 } from "commander";
|
|
|
278
314
|
import { getLogger as getLogger2 } from "@logtape/logtape";
|
|
279
315
|
function printVersion() {
|
|
280
316
|
const logger2 = getLogger2(["dx-cli", "version"]);
|
|
281
|
-
logger2.info(`dx CLI version: ${"0.4.
|
|
317
|
+
logger2.info(`dx CLI version: ${"0.4.4"}`);
|
|
282
318
|
}
|
|
283
319
|
|
|
284
320
|
// src/adapters/commander/commands/version.ts
|
|
@@ -287,7 +323,7 @@ var makeVersionCommand = () => new Command3().name("version").alias("v").action(
|
|
|
287
323
|
// src/adapters/commander/index.ts
|
|
288
324
|
var makeCli = (deps2, config2) => {
|
|
289
325
|
const program2 = new Command4();
|
|
290
|
-
program2.name("dx").description("The CLI for DX-Platform").version("0.4.
|
|
326
|
+
program2.name("dx").description("The CLI for DX-Platform").version("0.4.4");
|
|
291
327
|
program2.addCommand(makeDoctorCommand(deps2, config2));
|
|
292
328
|
program2.addCommand(makeVersionCommand());
|
|
293
329
|
program2.addCommand(makeInfoCommand(deps2, config2));
|
|
@@ -305,18 +341,6 @@ var makeValidationReporter = () => {
|
|
|
305
341
|
} else {
|
|
306
342
|
logger2.error(`\u274C ${result.errorMessage}`);
|
|
307
343
|
}
|
|
308
|
-
},
|
|
309
|
-
reportValidationResult(result) {
|
|
310
|
-
if (result.isOk()) {
|
|
311
|
-
const validation = result.value;
|
|
312
|
-
if (validation.isValid) {
|
|
313
|
-
logger2.info(`\u2705 ${validation.successMessage}`);
|
|
314
|
-
} else {
|
|
315
|
-
logger2.error(`\u274C ${validation.errorMessage}`);
|
|
316
|
-
}
|
|
317
|
-
} else {
|
|
318
|
-
logger2.error(`\u274C ${result.error.message}`);
|
|
319
|
-
}
|
|
320
344
|
}
|
|
321
345
|
};
|
|
322
346
|
};
|
|
@@ -326,26 +350,32 @@ import { join as join2 } from "path";
|
|
|
326
350
|
import * as process3 from "process";
|
|
327
351
|
|
|
328
352
|
// src/adapters/node/fs/file-reader.ts
|
|
329
|
-
import {
|
|
353
|
+
import { ResultAsync as ResultAsync5 } from "neverthrow";
|
|
330
354
|
import fs2 from "fs/promises";
|
|
331
|
-
|
|
355
|
+
|
|
356
|
+
// src/adapters/zod/index.ts
|
|
357
|
+
import { ResultAsync as ResultAsync4 } from "neverthrow";
|
|
358
|
+
var decode = (schema) => ResultAsync4.fromThrowable(
|
|
359
|
+
schema.parseAsync,
|
|
360
|
+
(cause) => new Error("File content is not valid for the given schema", { cause })
|
|
361
|
+
);
|
|
362
|
+
|
|
363
|
+
// src/adapters/node/json/index.ts
|
|
364
|
+
import { Result } from "neverthrow";
|
|
365
|
+
var parseJson = Result.fromThrowable(
|
|
366
|
+
JSON.parse,
|
|
367
|
+
(cause) => new Error("Failed to parse JSON", { cause })
|
|
368
|
+
);
|
|
369
|
+
|
|
370
|
+
// src/adapters/node/fs/file-reader.ts
|
|
371
|
+
var readFile = (filePath) => ResultAsync5.fromPromise(
|
|
332
372
|
fs2.readFile(filePath, "utf-8"),
|
|
333
373
|
(cause) => new Error(`Failed to read file: ${filePath}`, { cause })
|
|
334
374
|
);
|
|
335
|
-
var readFileAndDecode = (filePath, schema) =>
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
);
|
|
340
|
-
const toJSON = Result.fromThrowable(
|
|
341
|
-
JSON.parse,
|
|
342
|
-
() => new Error("Failed to parse JSON")
|
|
343
|
-
);
|
|
344
|
-
return readFile(filePath).andThen(toJSON).andThen(decode);
|
|
345
|
-
};
|
|
346
|
-
var fileExists = (path) => ResultAsync4.fromPromise(
|
|
347
|
-
fs2.stat(path),
|
|
348
|
-
() => new Error(`${path} not found.`)
|
|
375
|
+
var readFileAndDecode = (filePath, schema) => readFile(filePath).andThen(parseJson).andThen(decode(schema));
|
|
376
|
+
var fileExists = (path2) => ResultAsync5.fromPromise(
|
|
377
|
+
fs2.stat(path2),
|
|
378
|
+
() => new Error(`${path2} not found.`)
|
|
349
379
|
).map(() => true);
|
|
350
380
|
|
|
351
381
|
// src/adapters/node/package-json.ts
|
|
@@ -373,18 +403,73 @@ var makePackageJsonReader = () => ({
|
|
|
373
403
|
});
|
|
374
404
|
|
|
375
405
|
// src/adapters/node/repository.ts
|
|
376
|
-
import
|
|
406
|
+
import * as glob from "glob";
|
|
407
|
+
import { okAsync, ResultAsync as ResultAsync6 } from "neverthrow";
|
|
408
|
+
import * as path from "path";
|
|
409
|
+
import { z as z3 } from "zod/v4";
|
|
410
|
+
|
|
411
|
+
// src/adapters/yaml/index.ts
|
|
412
|
+
import { Result as Result2 } from "neverthrow";
|
|
413
|
+
import yaml from "yaml";
|
|
414
|
+
var parseYaml = Result2.fromThrowable(
|
|
415
|
+
(content) => yaml.parse(content),
|
|
416
|
+
() => new Error("Failed to parse YAML")
|
|
417
|
+
);
|
|
418
|
+
|
|
419
|
+
// src/adapters/node/repository.ts
|
|
377
420
|
var findRepositoryRoot = (dir = process.cwd()) => {
|
|
378
|
-
const gitPath =
|
|
421
|
+
const gitPath = path.join(dir, ".git");
|
|
379
422
|
return fileExists(gitPath).mapErr(
|
|
380
423
|
() => new Error(
|
|
381
424
|
"Could not find repository root. Make sure to have the repo initialized."
|
|
382
425
|
)
|
|
383
426
|
).map(() => dir);
|
|
384
427
|
};
|
|
428
|
+
var resolveWorkspacePattern = (repoRoot2, pattern) => ResultAsync6.fromPromise(
|
|
429
|
+
// For now it is not possible to use the fs.glob function (from node:fs/promises)
|
|
430
|
+
// because it is not possible to run it on Node 20.x
|
|
431
|
+
glob.glob(pattern, { cwd: repoRoot2 }),
|
|
432
|
+
(cause) => new Error(`Failed to resolve workspace glob: ${pattern}`, {
|
|
433
|
+
cause
|
|
434
|
+
})
|
|
435
|
+
).map(
|
|
436
|
+
(subDirectories) => (
|
|
437
|
+
// Create the absolute path to the subdirectory
|
|
438
|
+
subDirectories.map((directory) => path.join(repoRoot2, directory))
|
|
439
|
+
)
|
|
440
|
+
);
|
|
441
|
+
var getWorkspaces = (repoRoot2) => readFile(path.join(repoRoot2, "pnpm-workspace.yaml")).andThen(parseYaml).andThen(
|
|
442
|
+
(obj) => (
|
|
443
|
+
// If no packages are defined, go on with an empty array
|
|
444
|
+
decode(z3.object({ packages: z3.array(z3.string()) }))(obj).orElse(
|
|
445
|
+
() => okAsync({ packages: [] })
|
|
446
|
+
)
|
|
447
|
+
)
|
|
448
|
+
).andThen(
|
|
449
|
+
({ packages }) => (
|
|
450
|
+
// For every package pattern in the pnpm-workspace.yaml file, get the list of subdirectories
|
|
451
|
+
ResultAsync6.combine(
|
|
452
|
+
packages.map((pattern) => resolveWorkspacePattern(repoRoot2, pattern))
|
|
453
|
+
).map((workspacesList) => workspacesList.flat()).andThen((workspaceFolders) => {
|
|
454
|
+
const workspaceResults = workspaceFolders.map(
|
|
455
|
+
(nodeWorkspaceDirectory) => readFileAndDecode(
|
|
456
|
+
path.join(nodeWorkspaceDirectory, "package.json"),
|
|
457
|
+
packageJsonSchema
|
|
458
|
+
).map(
|
|
459
|
+
({ name }) => (
|
|
460
|
+
// Create the workspace object using the package.json name and the nodeWorkspaceDirectory
|
|
461
|
+
workspaceSchema.parse({ name, path: nodeWorkspaceDirectory })
|
|
462
|
+
)
|
|
463
|
+
)
|
|
464
|
+
);
|
|
465
|
+
return ResultAsync6.combine(workspaceResults);
|
|
466
|
+
})
|
|
467
|
+
)
|
|
468
|
+
);
|
|
385
469
|
var makeRepositoryReader = () => ({
|
|
386
470
|
fileExists,
|
|
387
471
|
findRepositoryRoot,
|
|
472
|
+
getWorkspaces,
|
|
388
473
|
readFile
|
|
389
474
|
});
|
|
390
475
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pagopa/dx-cli",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A CLI useful to manage DX tools.",
|
|
6
6
|
"repository": {
|
|
@@ -22,8 +22,10 @@
|
|
|
22
22
|
"@logtape/logtape": "^1.0.0",
|
|
23
23
|
"commander": "^14.0.0",
|
|
24
24
|
"core-js": "^3.44.0",
|
|
25
|
+
"glob": "^11.0.3",
|
|
25
26
|
"neverthrow": "^8.2.0",
|
|
26
27
|
"semver": "^7.7.2",
|
|
28
|
+
"yaml": "^2.8.0",
|
|
27
29
|
"zod": "^3.25.28"
|
|
28
30
|
},
|
|
29
31
|
"devDependencies": {
|
|
@@ -32,6 +34,7 @@
|
|
|
32
34
|
"@types/semver": "^7.7.0",
|
|
33
35
|
"@vitest/coverage-v8": "^3.2.4",
|
|
34
36
|
"eslint": "^9.30.0",
|
|
37
|
+
"memfs": "^4.23.0",
|
|
35
38
|
"prettier": "3.6.2",
|
|
36
39
|
"tsup": "^8.5.0",
|
|
37
40
|
"typescript": "~5.8.3",
|