@pagopa/dx-cli 0.4.1 → 0.4.3
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 +124 -35
- package/package.json +5 -2
package/bin/index.js
CHANGED
|
@@ -167,6 +167,40 @@ var checkTurboConfig = async (dependencies, config2) => {
|
|
|
167
167
|
});
|
|
168
168
|
};
|
|
169
169
|
|
|
170
|
+
// src/domain/workspace.ts
|
|
171
|
+
import { ok as ok3 } from "neverthrow";
|
|
172
|
+
import { z as z2 } from "zod/v4";
|
|
173
|
+
var WorkspaceName = z2.string().min(1).brand();
|
|
174
|
+
var workspaceSchema = z2.object({
|
|
175
|
+
name: WorkspaceName,
|
|
176
|
+
path: z2.string()
|
|
177
|
+
});
|
|
178
|
+
var checkWorkspaces = async (dependencies, monorepoDir) => {
|
|
179
|
+
const { repositoryReader: repositoryReader2 } = dependencies;
|
|
180
|
+
const checkName = "Workspaces";
|
|
181
|
+
const workspacesResult = await repositoryReader2.getWorkspaces(monorepoDir);
|
|
182
|
+
if (workspacesResult.isErr()) {
|
|
183
|
+
return ok3({
|
|
184
|
+
checkName,
|
|
185
|
+
errorMessage: "Something is wrong with the workspaces configuration. If you need help, please contact the DevEx team.",
|
|
186
|
+
isValid: false
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
const { length: workspaceNumber } = workspacesResult.value;
|
|
190
|
+
if (workspaceNumber === 0) {
|
|
191
|
+
return ok3({
|
|
192
|
+
checkName,
|
|
193
|
+
errorMessage: "No workspace configuration found. Make sure to configure workspaces in pnpm-workspace.yaml.",
|
|
194
|
+
isValid: false
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
return ok3({
|
|
198
|
+
checkName,
|
|
199
|
+
isValid: true,
|
|
200
|
+
successMessage: `Found ${workspaceNumber} workspace${workspaceNumber === 1 ? "" : "s"}`
|
|
201
|
+
});
|
|
202
|
+
};
|
|
203
|
+
|
|
170
204
|
// src/domain/doctor.ts
|
|
171
205
|
var runDoctor = (dependencies, config2) => {
|
|
172
206
|
const doctorChecks = [
|
|
@@ -181,6 +215,10 @@ var runDoctor = (dependencies, config2) => {
|
|
|
181
215
|
ResultAsync3.fromPromise(
|
|
182
216
|
checkMonorepoScripts(dependencies, config2),
|
|
183
217
|
() => new Error("Error checking monorepo scripts")
|
|
218
|
+
),
|
|
219
|
+
ResultAsync3.fromPromise(
|
|
220
|
+
checkWorkspaces(dependencies, config2.repository.root),
|
|
221
|
+
() => new Error("Error checking monorepo scripts")
|
|
184
222
|
)
|
|
185
223
|
];
|
|
186
224
|
return ResultAsync3.combine(doctorChecks).match(
|
|
@@ -247,8 +285,9 @@ var detectPackageManager = async (dependencies, config2) => {
|
|
|
247
285
|
const packageManager = dependencies.packageJson.packageManager ?? await detectFromLockFile(dependencies, config2);
|
|
248
286
|
return packageManager ?? "npm";
|
|
249
287
|
};
|
|
250
|
-
var detectNodeVersion = async ({ repositoryReader: repositoryReader2 }, nodeVersionFilePath) => await repositoryReader2.readFile(nodeVersionFilePath).unwrapOr(void 0);
|
|
288
|
+
var detectNodeVersion = async ({ repositoryReader: repositoryReader2 }, nodeVersionFilePath) => await repositoryReader2.readFile(nodeVersionFilePath).map((nodeVersion) => nodeVersion.trim()).unwrapOr(void 0);
|
|
251
289
|
var detectTerraformVersion = async ({ repositoryReader: repositoryReader2 }, terraformVersionFilePath) => await repositoryReader2.readFile(terraformVersionFilePath).map((tfVersion) => tfVersion.trim()).unwrapOr(void 0);
|
|
290
|
+
var detectTurboVersion = ({ devDependencies }) => devDependencies.get("turbo")?.trim();
|
|
252
291
|
var getInfo = async (dependencies, config2) => ({
|
|
253
292
|
node: await detectNodeVersion(
|
|
254
293
|
{ repositoryReader: dependencies.repositoryReader },
|
|
@@ -256,9 +295,10 @@ var getInfo = async (dependencies, config2) => ({
|
|
|
256
295
|
),
|
|
257
296
|
packageManager: await detectPackageManager(dependencies, config2),
|
|
258
297
|
terraform: await detectTerraformVersion(
|
|
259
|
-
dependencies,
|
|
298
|
+
{ repositoryReader: dependencies.repositoryReader },
|
|
260
299
|
`${config2.repository.root}/.terraform-version`
|
|
261
|
-
)
|
|
300
|
+
),
|
|
301
|
+
turbo: detectTurboVersion(dependencies.packageJson)
|
|
262
302
|
});
|
|
263
303
|
var printInfo = (result) => {
|
|
264
304
|
const logger2 = getLogger("json");
|
|
@@ -278,7 +318,7 @@ import { Command as Command3 } from "commander";
|
|
|
278
318
|
import { getLogger as getLogger2 } from "@logtape/logtape";
|
|
279
319
|
function printVersion() {
|
|
280
320
|
const logger2 = getLogger2(["dx-cli", "version"]);
|
|
281
|
-
logger2.info(`dx CLI version: ${"0.4.
|
|
321
|
+
logger2.info(`dx CLI version: ${"0.4.3"}`);
|
|
282
322
|
}
|
|
283
323
|
|
|
284
324
|
// src/adapters/commander/commands/version.ts
|
|
@@ -287,7 +327,7 @@ var makeVersionCommand = () => new Command3().name("version").alias("v").action(
|
|
|
287
327
|
// src/adapters/commander/index.ts
|
|
288
328
|
var makeCli = (deps2, config2) => {
|
|
289
329
|
const program2 = new Command4();
|
|
290
|
-
program2.name("dx").description("The CLI for DX-Platform").version("0.4.
|
|
330
|
+
program2.name("dx").description("The CLI for DX-Platform").version("0.4.3");
|
|
291
331
|
program2.addCommand(makeDoctorCommand(deps2, config2));
|
|
292
332
|
program2.addCommand(makeVersionCommand());
|
|
293
333
|
program2.addCommand(makeInfoCommand(deps2, config2));
|
|
@@ -305,18 +345,6 @@ var makeValidationReporter = () => {
|
|
|
305
345
|
} else {
|
|
306
346
|
logger2.error(`\u274C ${result.errorMessage}`);
|
|
307
347
|
}
|
|
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
348
|
}
|
|
321
349
|
};
|
|
322
350
|
};
|
|
@@ -326,26 +354,32 @@ import { join as join2 } from "path";
|
|
|
326
354
|
import * as process3 from "process";
|
|
327
355
|
|
|
328
356
|
// src/adapters/node/fs/file-reader.ts
|
|
329
|
-
import {
|
|
357
|
+
import { ResultAsync as ResultAsync5 } from "neverthrow";
|
|
330
358
|
import fs2 from "fs/promises";
|
|
331
|
-
|
|
359
|
+
|
|
360
|
+
// src/adapters/zod/index.ts
|
|
361
|
+
import { ResultAsync as ResultAsync4 } from "neverthrow";
|
|
362
|
+
var decode = (schema) => ResultAsync4.fromThrowable(
|
|
363
|
+
schema.parseAsync,
|
|
364
|
+
(cause) => new Error("File content is not valid for the given schema", { cause })
|
|
365
|
+
);
|
|
366
|
+
|
|
367
|
+
// src/adapters/node/json/index.ts
|
|
368
|
+
import { Result } from "neverthrow";
|
|
369
|
+
var parseJson = Result.fromThrowable(
|
|
370
|
+
JSON.parse,
|
|
371
|
+
(cause) => new Error("Failed to parse JSON", { cause })
|
|
372
|
+
);
|
|
373
|
+
|
|
374
|
+
// src/adapters/node/fs/file-reader.ts
|
|
375
|
+
var readFile = (filePath) => ResultAsync5.fromPromise(
|
|
332
376
|
fs2.readFile(filePath, "utf-8"),
|
|
333
377
|
(cause) => new Error(`Failed to read file: ${filePath}`, { cause })
|
|
334
378
|
);
|
|
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.`)
|
|
379
|
+
var readFileAndDecode = (filePath, schema) => readFile(filePath).andThen(parseJson).andThen(decode(schema));
|
|
380
|
+
var fileExists = (path2) => ResultAsync5.fromPromise(
|
|
381
|
+
fs2.stat(path2),
|
|
382
|
+
() => new Error(`${path2} not found.`)
|
|
349
383
|
).map(() => true);
|
|
350
384
|
|
|
351
385
|
// src/adapters/node/package-json.ts
|
|
@@ -373,18 +407,73 @@ var makePackageJsonReader = () => ({
|
|
|
373
407
|
});
|
|
374
408
|
|
|
375
409
|
// src/adapters/node/repository.ts
|
|
376
|
-
import
|
|
410
|
+
import * as glob from "glob";
|
|
411
|
+
import { okAsync, ResultAsync as ResultAsync6 } from "neverthrow";
|
|
412
|
+
import * as path from "path";
|
|
413
|
+
import { z as z3 } from "zod/v4";
|
|
414
|
+
|
|
415
|
+
// src/adapters/yaml/index.ts
|
|
416
|
+
import { Result as Result2 } from "neverthrow";
|
|
417
|
+
import yaml from "yaml";
|
|
418
|
+
var parseYaml = Result2.fromThrowable(
|
|
419
|
+
(content) => yaml.parse(content),
|
|
420
|
+
() => new Error("Failed to parse YAML")
|
|
421
|
+
);
|
|
422
|
+
|
|
423
|
+
// src/adapters/node/repository.ts
|
|
377
424
|
var findRepositoryRoot = (dir = process.cwd()) => {
|
|
378
|
-
const gitPath =
|
|
425
|
+
const gitPath = path.join(dir, ".git");
|
|
379
426
|
return fileExists(gitPath).mapErr(
|
|
380
427
|
() => new Error(
|
|
381
428
|
"Could not find repository root. Make sure to have the repo initialized."
|
|
382
429
|
)
|
|
383
430
|
).map(() => dir);
|
|
384
431
|
};
|
|
432
|
+
var resolveWorkspacePattern = (repoRoot2, pattern) => ResultAsync6.fromPromise(
|
|
433
|
+
// For now it is not possible to use the fs.glob function (from node:fs/promises)
|
|
434
|
+
// because it is not possible to run it on Node 20.x
|
|
435
|
+
glob.glob(pattern, { cwd: repoRoot2 }),
|
|
436
|
+
(cause) => new Error(`Failed to resolve workspace glob: ${pattern}`, {
|
|
437
|
+
cause
|
|
438
|
+
})
|
|
439
|
+
).map(
|
|
440
|
+
(subDirectories) => (
|
|
441
|
+
// Create the absolute path to the subdirectory
|
|
442
|
+
subDirectories.map((directory) => path.join(repoRoot2, directory))
|
|
443
|
+
)
|
|
444
|
+
);
|
|
445
|
+
var getWorkspaces = (repoRoot2) => readFile(path.join(repoRoot2, "pnpm-workspace.yaml")).andThen(parseYaml).andThen(
|
|
446
|
+
(obj) => (
|
|
447
|
+
// If no packages are defined, go on with an empty array
|
|
448
|
+
decode(z3.object({ packages: z3.array(z3.string()) }))(obj).orElse(
|
|
449
|
+
() => okAsync({ packages: [] })
|
|
450
|
+
)
|
|
451
|
+
)
|
|
452
|
+
).andThen(
|
|
453
|
+
({ packages }) => (
|
|
454
|
+
// For every package pattern in the pnpm-workspace.yaml file, get the list of subdirectories
|
|
455
|
+
ResultAsync6.combine(
|
|
456
|
+
packages.map((pattern) => resolveWorkspacePattern(repoRoot2, pattern))
|
|
457
|
+
).map((workspacesList) => workspacesList.flat()).andThen((workspaceFolders) => {
|
|
458
|
+
const workspaceResults = workspaceFolders.map(
|
|
459
|
+
(nodeWorkspaceDirectory) => readFileAndDecode(
|
|
460
|
+
path.join(nodeWorkspaceDirectory, "package.json"),
|
|
461
|
+
packageJsonSchema
|
|
462
|
+
).map(
|
|
463
|
+
({ name }) => (
|
|
464
|
+
// Create the workspace object using the package.json name and the nodeWorkspaceDirectory
|
|
465
|
+
workspaceSchema.parse({ name, path: nodeWorkspaceDirectory })
|
|
466
|
+
)
|
|
467
|
+
)
|
|
468
|
+
);
|
|
469
|
+
return ResultAsync6.combine(workspaceResults);
|
|
470
|
+
})
|
|
471
|
+
)
|
|
472
|
+
);
|
|
385
473
|
var makeRepositoryReader = () => ({
|
|
386
474
|
fileExists,
|
|
387
475
|
findRepositoryRoot,
|
|
476
|
+
getWorkspaces,
|
|
388
477
|
readFile
|
|
389
478
|
});
|
|
390
479
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pagopa/dx-cli",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.3",
|
|
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": {
|
|
@@ -31,7 +33,8 @@
|
|
|
31
33
|
"@types/node": "^22.16.2",
|
|
32
34
|
"@types/semver": "^7.7.0",
|
|
33
35
|
"@vitest/coverage-v8": "^3.2.4",
|
|
34
|
-
"eslint": "^9.
|
|
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",
|