@dafish/gogo-meta 1.5.0 → 1.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/README.md +19 -0
- package/dist/cli.js +131 -6
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +131 -6
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { spawn, execSync } from 'child_process';
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
-
import { unlink, mkdir, appendFile, access, writeFile, readFile, symlink } from 'fs/promises';
|
|
3
|
+
import { unlink, mkdir, appendFile, access, writeFile, readFile, symlink, readdir } from 'fs/promises';
|
|
4
4
|
import { dirname, join, basename, resolve } from 'path';
|
|
5
|
-
import {
|
|
5
|
+
import { parse, stringify } from 'yaml';
|
|
6
6
|
import pc from 'picocolors';
|
|
7
7
|
import { homedir } from 'os';
|
|
8
8
|
import { Command } from 'commander';
|
|
@@ -539,7 +539,7 @@ function commandOutput(stdout, stderr) {
|
|
|
539
539
|
}
|
|
540
540
|
}
|
|
541
541
|
function summary(results) {
|
|
542
|
-
const { success: successCount, failed, total } = results;
|
|
542
|
+
const { success: successCount, failed, total, failedProjects } = results;
|
|
543
543
|
console.log("");
|
|
544
544
|
if (failed === 0) {
|
|
545
545
|
console.log(`${symbols.success} ${pc.green(`All ${total} projects completed successfully`)}`);
|
|
@@ -547,6 +547,13 @@ function summary(results) {
|
|
|
547
547
|
console.log(
|
|
548
548
|
`${symbols.warning} ${pc.yellow(`${successCount}/${total} projects succeeded, ${failed} failed`)}`
|
|
549
549
|
);
|
|
550
|
+
if (failedProjects && failedProjects.length > 0) {
|
|
551
|
+
console.log("");
|
|
552
|
+
console.log("Failed projects:");
|
|
553
|
+
for (const project of failedProjects) {
|
|
554
|
+
console.log(` ${symbols.error} ${pc.red(project)}`);
|
|
555
|
+
}
|
|
556
|
+
}
|
|
550
557
|
}
|
|
551
558
|
}
|
|
552
559
|
function formatDuration(ms) {
|
|
@@ -645,9 +652,14 @@ async function loop(command, context, options = {}) {
|
|
|
645
652
|
}
|
|
646
653
|
const results = options.parallel ? await runParallel(command, directories, context, options) : await runSequential(command, directories, context, options);
|
|
647
654
|
if (!options.suppressOutput) {
|
|
648
|
-
const
|
|
649
|
-
const
|
|
650
|
-
summary({
|
|
655
|
+
const failedResults = results.filter((r) => !r.success);
|
|
656
|
+
const successCount = results.length - failedResults.length;
|
|
657
|
+
summary({
|
|
658
|
+
success: successCount,
|
|
659
|
+
failed: failedResults.length,
|
|
660
|
+
total: results.length,
|
|
661
|
+
failedProjects: failedResults.map((r) => r.directory)
|
|
662
|
+
});
|
|
651
663
|
}
|
|
652
664
|
return results;
|
|
653
665
|
}
|
|
@@ -1476,6 +1488,118 @@ function registerNpmCommands(program) {
|
|
|
1476
1488
|
await runCommand2(script, options);
|
|
1477
1489
|
});
|
|
1478
1490
|
}
|
|
1491
|
+
var MISSING_DIRECTORY_HINT = "directory missing \u2014 run 'gogo migrate' if it moved, or 'gogo git update' to clone";
|
|
1492
|
+
function isGogoConfigFile(filename) {
|
|
1493
|
+
return filename === ".gogo" || filename.startsWith(".gogo.");
|
|
1494
|
+
}
|
|
1495
|
+
async function findConfigFiles(cwd) {
|
|
1496
|
+
const entries = await readdir(cwd);
|
|
1497
|
+
const configFiles = [];
|
|
1498
|
+
for (const entry of entries) {
|
|
1499
|
+
if (isGogoConfigFile(entry)) {
|
|
1500
|
+
configFiles.push(entry);
|
|
1501
|
+
}
|
|
1502
|
+
}
|
|
1503
|
+
if (entries.includes(LOOPRC_FILE)) {
|
|
1504
|
+
configFiles.push(LOOPRC_FILE);
|
|
1505
|
+
}
|
|
1506
|
+
return configFiles.sort();
|
|
1507
|
+
}
|
|
1508
|
+
async function validateCommand() {
|
|
1509
|
+
const cwd = process.cwd();
|
|
1510
|
+
const results = [];
|
|
1511
|
+
const configFiles = await findConfigFiles(cwd);
|
|
1512
|
+
for (const filename of configFiles) {
|
|
1513
|
+
const filePath = join(cwd, filename);
|
|
1514
|
+
if (filename === LOOPRC_FILE) {
|
|
1515
|
+
results.push(await validateLoopRcFile(filePath));
|
|
1516
|
+
} else {
|
|
1517
|
+
results.push(await validateConfigFile(filePath, filename));
|
|
1518
|
+
}
|
|
1519
|
+
}
|
|
1520
|
+
if (results.length === 0) {
|
|
1521
|
+
warning("No config files found in current directory");
|
|
1522
|
+
return;
|
|
1523
|
+
}
|
|
1524
|
+
const hasErrors = results.some((r) => !r.valid);
|
|
1525
|
+
for (const result of results) {
|
|
1526
|
+
if (result.valid) {
|
|
1527
|
+
projectStatus(result.file, "success");
|
|
1528
|
+
} else {
|
|
1529
|
+
projectStatus(result.file, "error", result.error);
|
|
1530
|
+
}
|
|
1531
|
+
}
|
|
1532
|
+
const workingCopyHasErrors = await validateWorkingCopy(cwd);
|
|
1533
|
+
if (hasErrors || workingCopyHasErrors) {
|
|
1534
|
+
throw new Error("Validation failed");
|
|
1535
|
+
}
|
|
1536
|
+
}
|
|
1537
|
+
async function validateWorkingCopy(cwd) {
|
|
1538
|
+
let config;
|
|
1539
|
+
let metaDir;
|
|
1540
|
+
try {
|
|
1541
|
+
({ config, metaDir } = await readMetaConfig(cwd));
|
|
1542
|
+
} catch {
|
|
1543
|
+
return false;
|
|
1544
|
+
}
|
|
1545
|
+
const projectPaths = Object.keys(config.projects);
|
|
1546
|
+
if (projectPaths.length === 0) {
|
|
1547
|
+
return false;
|
|
1548
|
+
}
|
|
1549
|
+
let hasErrors = false;
|
|
1550
|
+
for (const projectPath of projectPaths) {
|
|
1551
|
+
const projectDir = join(metaDir, projectPath);
|
|
1552
|
+
if (!await fileExists(projectDir)) {
|
|
1553
|
+
projectStatus(projectPath, "error", MISSING_DIRECTORY_HINT);
|
|
1554
|
+
hasErrors = true;
|
|
1555
|
+
}
|
|
1556
|
+
}
|
|
1557
|
+
if (!hasErrors) {
|
|
1558
|
+
success(`All ${projectPaths.length} project directories present`);
|
|
1559
|
+
}
|
|
1560
|
+
return hasErrors;
|
|
1561
|
+
}
|
|
1562
|
+
async function validateConfigFile(filePath, filename) {
|
|
1563
|
+
const format = detectFormat(filePath);
|
|
1564
|
+
try {
|
|
1565
|
+
const content = await readFile(filePath, "utf-8");
|
|
1566
|
+
const parsed = format === "yaml" ? parse(content) : JSON.parse(content);
|
|
1567
|
+
MetaConfigSchema.parse(parsed);
|
|
1568
|
+
return { file: filename, valid: true };
|
|
1569
|
+
} catch (error2) {
|
|
1570
|
+
if (error2 instanceof SyntaxError) {
|
|
1571
|
+
return { file: filename, valid: false, error: "Invalid JSON" };
|
|
1572
|
+
}
|
|
1573
|
+
if (error2 instanceof Error && error2.name === "YAMLParseError") {
|
|
1574
|
+
return { file: filename, valid: false, error: "Invalid YAML" };
|
|
1575
|
+
}
|
|
1576
|
+
if (error2 instanceof Error && error2.name === "ZodError") {
|
|
1577
|
+
return { file: filename, valid: false, error: `Invalid structure: ${error2.message}` };
|
|
1578
|
+
}
|
|
1579
|
+
return { file: filename, valid: false, error: String(error2) };
|
|
1580
|
+
}
|
|
1581
|
+
}
|
|
1582
|
+
async function validateLoopRcFile(filePath) {
|
|
1583
|
+
try {
|
|
1584
|
+
const content = await readFile(filePath, "utf-8");
|
|
1585
|
+
const parsed = JSON.parse(content);
|
|
1586
|
+
LoopRcSchema.parse(parsed);
|
|
1587
|
+
return { file: LOOPRC_FILE, valid: true };
|
|
1588
|
+
} catch (error2) {
|
|
1589
|
+
if (error2 instanceof SyntaxError) {
|
|
1590
|
+
return { file: LOOPRC_FILE, valid: false, error: "Invalid JSON" };
|
|
1591
|
+
}
|
|
1592
|
+
if (error2 instanceof Error && error2.name === "ZodError") {
|
|
1593
|
+
return { file: LOOPRC_FILE, valid: false, error: `Invalid structure: ${error2.message}` };
|
|
1594
|
+
}
|
|
1595
|
+
return { file: LOOPRC_FILE, valid: false, error: String(error2) };
|
|
1596
|
+
}
|
|
1597
|
+
}
|
|
1598
|
+
function registerValidateCommand(program) {
|
|
1599
|
+
program.command("validate").description("Validate config files and check that configured projects exist in the working copy").action(async () => {
|
|
1600
|
+
await validateCommand();
|
|
1601
|
+
});
|
|
1602
|
+
}
|
|
1479
1603
|
|
|
1480
1604
|
// src/cli.ts
|
|
1481
1605
|
function getVersion() {
|
|
@@ -1506,6 +1630,7 @@ function createProgram() {
|
|
|
1506
1630
|
registerGitCommands(program);
|
|
1507
1631
|
registerProjectCommands(program);
|
|
1508
1632
|
registerNpmCommands(program);
|
|
1633
|
+
registerValidateCommand(program);
|
|
1509
1634
|
return program;
|
|
1510
1635
|
}
|
|
1511
1636
|
async function main() {
|