@theholocron/cli 5.0.0-alpha.122 → 5.0.0-alpha.123
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/dist/cli.mjs +45 -15
- package/dist/cli.mjs.map +1 -1
- package/package.json +4 -4
package/dist/cli.mjs
CHANGED
|
@@ -309,6 +309,8 @@ const style = {
|
|
|
309
309
|
warn: (msg) => `${chalk.yellow("⚠")} ${msg}`,
|
|
310
310
|
fail: (msg) => `${chalk.red("✗")} ${msg}`,
|
|
311
311
|
step: (msg) => `${chalk.cyan("→")} ${msg}`,
|
|
312
|
+
/** A dim `·` marker for a row that's neither a pass nor a failure — loaded but inactive, or skipped. */
|
|
313
|
+
skip: (msg) => chalk.dim(`· ${msg}`),
|
|
312
314
|
hint: (msg) => chalk.dim(msg),
|
|
313
315
|
dim: (msg) => chalk.dim(msg),
|
|
314
316
|
header: (msg) => chalk.bold(msg)
|
|
@@ -1117,6 +1119,27 @@ async function runCleanupPreview(input) {
|
|
|
1117
1119
|
}
|
|
1118
1120
|
}
|
|
1119
1121
|
//#endregion
|
|
1122
|
+
//#region src/ui/status-row.ts
|
|
1123
|
+
/** Right-pads `s` to `width` with spaces — never truncates. */
|
|
1124
|
+
function pad(s, width) {
|
|
1125
|
+
return s.length >= width ? s : s + " ".repeat(width - s.length);
|
|
1126
|
+
}
|
|
1127
|
+
/**
|
|
1128
|
+
* One row of a status report: a 2-space indent, the status icon (✓ / ✗ / ·),
|
|
1129
|
+
* then `columns` joined with a two-space gap (blank columns dropped, so a
|
|
1130
|
+
* row that has nothing for its last column doesn't trail whitespace).
|
|
1131
|
+
* Column padding (`pad`) is the caller's job — `doctor` pads capability and
|
|
1132
|
+
* provider to a fixed width; `clone`'s repo names and paths don't, since
|
|
1133
|
+
* they vary too widely for fixed-width alignment to read cleanly.
|
|
1134
|
+
*
|
|
1135
|
+
* Shared by `doctor` (capability / provider / message) and `clone` (repo /
|
|
1136
|
+
* destination / reason) so every status table in the CLI reads the same way.
|
|
1137
|
+
*/
|
|
1138
|
+
function statusRow(status, columns) {
|
|
1139
|
+
const joined = columns.filter((c) => c.length > 0).join(" ");
|
|
1140
|
+
return ` ${status === "ok" ? style.success(joined) : status === "fail" ? style.fail(joined) : style.skip(joined)}`;
|
|
1141
|
+
}
|
|
1142
|
+
//#endregion
|
|
1120
1143
|
//#region src/commands/clone.ts
|
|
1121
1144
|
/**
|
|
1122
1145
|
* Accepts a bare org (`"theholocron"`) — clones every repo in it — or an
|
|
@@ -1190,6 +1213,7 @@ async function runClone(input) {
|
|
|
1190
1213
|
stdio: "inherit"
|
|
1191
1214
|
}).status };
|
|
1192
1215
|
});
|
|
1216
|
+
print("");
|
|
1193
1217
|
if (!existsSync(targetDir)) {
|
|
1194
1218
|
if (dryRun) print(style.dim(` would create ${targetDir}`));
|
|
1195
1219
|
else mkdirSync(targetDir, { recursive: true });
|
|
@@ -1240,7 +1264,11 @@ async function runClone(input) {
|
|
|
1240
1264
|
for (const repo of repos) {
|
|
1241
1265
|
const dest = join(targetDir, repoDirName(repo));
|
|
1242
1266
|
if (existsSync(dest)) {
|
|
1243
|
-
print(
|
|
1267
|
+
print(statusRow("skip", [
|
|
1268
|
+
repo.full_name,
|
|
1269
|
+
dest,
|
|
1270
|
+
"already exists"
|
|
1271
|
+
]));
|
|
1244
1272
|
skipped++;
|
|
1245
1273
|
continue;
|
|
1246
1274
|
}
|
|
@@ -1252,7 +1280,11 @@ async function runClone(input) {
|
|
|
1252
1280
|
print(style.step(` clone ${repo.full_name} → ${dest}`));
|
|
1253
1281
|
const { clone_url } = repo;
|
|
1254
1282
|
if (!clone_url.startsWith("https://github.com/")) {
|
|
1255
|
-
print(
|
|
1283
|
+
print(statusRow("fail", [
|
|
1284
|
+
repo.full_name,
|
|
1285
|
+
dest,
|
|
1286
|
+
`unexpected clone URL: ${clone_url}`
|
|
1287
|
+
]));
|
|
1256
1288
|
failed++;
|
|
1257
1289
|
continue;
|
|
1258
1290
|
}
|
|
@@ -1260,7 +1292,11 @@ async function runClone(input) {
|
|
|
1260
1292
|
try {
|
|
1261
1293
|
encodedToken = encodeTokenForGitHttpAuth(input.token);
|
|
1262
1294
|
} catch (err) {
|
|
1263
|
-
print(
|
|
1295
|
+
print(statusRow("fail", [
|
|
1296
|
+
repo.full_name,
|
|
1297
|
+
dest,
|
|
1298
|
+
`invalid token format: ${errorMessage(err)}`
|
|
1299
|
+
]));
|
|
1264
1300
|
failed++;
|
|
1265
1301
|
continue;
|
|
1266
1302
|
}
|
|
@@ -1270,14 +1306,14 @@ async function runClone(input) {
|
|
|
1270
1306
|
`https://x-access-token:${encodedToken}@github.com/${clone_url.slice(19)}`,
|
|
1271
1307
|
dest
|
|
1272
1308
|
], { cwd: targetDir }).status !== 0) {
|
|
1273
|
-
print(
|
|
1309
|
+
print(statusRow("fail", [repo.full_name, dest]));
|
|
1274
1310
|
failed++;
|
|
1275
1311
|
} else {
|
|
1276
|
-
print(
|
|
1312
|
+
print(statusRow("ok", [repo.full_name, dest]));
|
|
1277
1313
|
cloned++;
|
|
1278
1314
|
}
|
|
1279
1315
|
}
|
|
1280
|
-
const summary = `${cloned} cloned, ${
|
|
1316
|
+
const summary = `${cloned} cloned, ${failed} failed, ${skipped} skipped`;
|
|
1281
1317
|
print("");
|
|
1282
1318
|
print(dryRun ? style.dim(` dry-run: ${summary}`) : failed > 0 ? style.fail(` ${summary}`) : style.success(` ${summary}`));
|
|
1283
1319
|
const status = dryRun ? "dry-run" : failed > 0 ? "fail" : "ok";
|
|
@@ -1623,7 +1659,7 @@ async function runDoctor(input) {
|
|
|
1623
1659
|
assertPluginsResolvable(loader, "doctor");
|
|
1624
1660
|
const rows = [];
|
|
1625
1661
|
const config = input.loaded.resolved;
|
|
1626
|
-
print(
|
|
1662
|
+
print("");
|
|
1627
1663
|
print(style.dim(` config: ${input.loaded.filepath}`));
|
|
1628
1664
|
print("");
|
|
1629
1665
|
for (const failure of loader.loadFailures()) rows.push({
|
|
@@ -1658,10 +1694,7 @@ async function runDoctor(input) {
|
|
|
1658
1694
|
status: row.status,
|
|
1659
1695
|
detail: row.message
|
|
1660
1696
|
}, `doctor: ${row.capability}`);
|
|
1661
|
-
|
|
1662
|
-
if (row.status === "ok") print(` ${style.success(label)}`);
|
|
1663
|
-
else if (row.status === "fail") print(` ${style.fail(label)}`);
|
|
1664
|
-
else print(` ${style.dim(`· ${label}`)}`);
|
|
1697
|
+
print(statusRow(row.status, [`${pad(row.capability, 14)} via ${pad(row.provider, 14)}`, row.message]));
|
|
1665
1698
|
}
|
|
1666
1699
|
const summary = rows.reduce((acc, r) => {
|
|
1667
1700
|
acc[r.status] += 1;
|
|
@@ -1673,7 +1706,7 @@ async function runDoctor(input) {
|
|
|
1673
1706
|
});
|
|
1674
1707
|
const summaryLine = `${summary.ok} ok, ${summary.fail} fail, ${summary.skip} skipped`;
|
|
1675
1708
|
print("");
|
|
1676
|
-
print(
|
|
1709
|
+
print(style.header(summaryLine));
|
|
1677
1710
|
return {
|
|
1678
1711
|
rows,
|
|
1679
1712
|
summary
|
|
@@ -1727,9 +1760,6 @@ function mk(capability, provider, status, message) {
|
|
|
1727
1760
|
message
|
|
1728
1761
|
};
|
|
1729
1762
|
}
|
|
1730
|
-
function pad(s, width) {
|
|
1731
|
-
return s.length >= width ? s : s + " ".repeat(width - s.length);
|
|
1732
|
-
}
|
|
1733
1763
|
//#endregion
|
|
1734
1764
|
//#region src/commands/new.ts
|
|
1735
1765
|
/**
|