@theholocron/cli 5.0.0-alpha.50 → 5.0.0-alpha.52
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 +122 -107
- package/dist/cli.mjs.map +1 -1
- package/package.json +4 -4
package/dist/cli.mjs
CHANGED
|
@@ -532,7 +532,8 @@ var PluginLoader = class {
|
|
|
532
532
|
/** Default importer — resolves from cwd first so the global CLI finds project plugins. */
|
|
533
533
|
const defaultImporter$1 = async (pkg) => {
|
|
534
534
|
try {
|
|
535
|
-
|
|
535
|
+
const resolved = createRequire(process.cwd() + "/").resolve(pkg);
|
|
536
|
+
return import(pathToFileURL(resolved).href);
|
|
536
537
|
} catch {
|
|
537
538
|
return import(pkg);
|
|
538
539
|
}
|
|
@@ -664,7 +665,8 @@ const style = {
|
|
|
664
665
|
*/
|
|
665
666
|
const defaultImporter = async (pkg) => {
|
|
666
667
|
try {
|
|
667
|
-
|
|
668
|
+
const resolved = createRequire(process.cwd() + "/").resolve(pkg);
|
|
669
|
+
return await import(pathToFileURL(resolved).href);
|
|
668
670
|
} catch {
|
|
669
671
|
return await import(pkg);
|
|
670
672
|
}
|
|
@@ -1106,8 +1108,10 @@ async function runClone(input) {
|
|
|
1106
1108
|
}).status };
|
|
1107
1109
|
});
|
|
1108
1110
|
print(style.header(`Holocron clone — org=${input.org} → ${targetDir}${dryRun ? " (dry-run)" : ""}`));
|
|
1109
|
-
if (!existsSync(targetDir))
|
|
1110
|
-
|
|
1111
|
+
if (!existsSync(targetDir)) {
|
|
1112
|
+
if (dryRun) print(style.dim(` would create ${targetDir}`));
|
|
1113
|
+
else mkdirSync(targetDir, { recursive: true });
|
|
1114
|
+
}
|
|
1111
1115
|
let repos;
|
|
1112
1116
|
try {
|
|
1113
1117
|
repos = await listOrgRepos(input.org, input.token, fetchFn);
|
|
@@ -1129,7 +1133,8 @@ async function runClone(input) {
|
|
|
1129
1133
|
let skipped = 0;
|
|
1130
1134
|
let failed = 0;
|
|
1131
1135
|
for (const repo of repos) {
|
|
1132
|
-
const
|
|
1136
|
+
const dirName = repo.name.startsWith(".") ? repo.name.slice(1) : repo.name;
|
|
1137
|
+
const dest = join(targetDir, dirName);
|
|
1133
1138
|
if (existsSync(dest)) {
|
|
1134
1139
|
print(style.dim(` skip ${repo.full_name}`));
|
|
1135
1140
|
skipped++;
|
|
@@ -5413,34 +5418,36 @@ async function runSetup(input) {
|
|
|
5413
5418
|
print(formatStep(steps[steps.length - 1]));
|
|
5414
5419
|
}
|
|
5415
5420
|
const teams = repo?.teams ?? [];
|
|
5416
|
-
if (teams.length > 0)
|
|
5417
|
-
|
|
5418
|
-
|
|
5419
|
-
|
|
5420
|
-
|
|
5421
|
-
|
|
5422
|
-
|
|
5423
|
-
|
|
5424
|
-
|
|
5425
|
-
|
|
5426
|
-
|
|
5427
|
-
|
|
5428
|
-
|
|
5429
|
-
|
|
5430
|
-
|
|
5431
|
-
|
|
5432
|
-
|
|
5433
|
-
|
|
5421
|
+
if (teams.length > 0) {
|
|
5422
|
+
if (source.syncTeams) {
|
|
5423
|
+
steps.push(await runStep("source", "sync teams", dryRun, () => source.syncTeams(teams), { skipCodes: [422] }));
|
|
5424
|
+
print(formatStep(steps[steps.length - 1]));
|
|
5425
|
+
const repoCoord = input.context.repo ?? repo?.name ?? "";
|
|
5426
|
+
const org = repoCoord.includes("/") ? repoCoord.split("/")[0] : "";
|
|
5427
|
+
const writeableTeams = teams.map((t) => typeof t === "string" ? {
|
|
5428
|
+
slug: t,
|
|
5429
|
+
permission: "push"
|
|
5430
|
+
} : t).filter((t) => [
|
|
5431
|
+
"push",
|
|
5432
|
+
"maintain",
|
|
5433
|
+
"admin"
|
|
5434
|
+
].includes(t.permission));
|
|
5435
|
+
if (org && writeableTeams.length > 0) {
|
|
5436
|
+
steps.push(await runStep("source", "write .github/CODEOWNERS", dryRun, async () => {
|
|
5437
|
+
const content = writeableTeams.map((t) => `* @${org}/${t.slug}`).join("\n") + "\n";
|
|
5438
|
+
await source.writeRepoFile(".github/CODEOWNERS", content);
|
|
5439
|
+
}));
|
|
5440
|
+
print(formatStep(steps[steps.length - 1]));
|
|
5441
|
+
}
|
|
5442
|
+
} else {
|
|
5443
|
+
steps.push({
|
|
5444
|
+
capability: "source",
|
|
5445
|
+
step: "sync teams",
|
|
5446
|
+
status: "skip",
|
|
5447
|
+
message: "provider does not implement syncTeams"
|
|
5448
|
+
});
|
|
5434
5449
|
print(formatStep(steps[steps.length - 1]));
|
|
5435
5450
|
}
|
|
5436
|
-
} else {
|
|
5437
|
-
steps.push({
|
|
5438
|
-
capability: "source",
|
|
5439
|
-
step: "sync teams",
|
|
5440
|
-
status: "skip",
|
|
5441
|
-
message: "provider does not implement syncTeams"
|
|
5442
|
-
});
|
|
5443
|
-
print(formatStep(steps[steps.length - 1]));
|
|
5444
5451
|
}
|
|
5445
5452
|
}
|
|
5446
5453
|
if (loader.has("environments")) {
|
|
@@ -6002,11 +6009,13 @@ async function runSyncReadme(input) {
|
|
|
6002
6009
|
}
|
|
6003
6010
|
const description = loaded.resolved.description ?? "";
|
|
6004
6011
|
const homepage = loaded.resolved.homepage ?? pkg.homepage ?? "";
|
|
6012
|
+
const scripts = pkg.scripts ?? {};
|
|
6013
|
+
const packages = pkg.name ? REGISTRY_MAP[pkg.name]?.() : void 0;
|
|
6005
6014
|
const sections = generateReadme({
|
|
6006
6015
|
description,
|
|
6007
6016
|
homepage,
|
|
6008
|
-
scripts
|
|
6009
|
-
packages
|
|
6017
|
+
scripts,
|
|
6018
|
+
packages
|
|
6010
6019
|
});
|
|
6011
6020
|
const markerSections = {
|
|
6012
6021
|
...sections.packages !== void 0 && { packages: sections.packages },
|
|
@@ -6248,7 +6257,7 @@ async function runSyncWiki(input) {
|
|
|
6248
6257
|
capability: "local",
|
|
6249
6258
|
step: "sync wiki",
|
|
6250
6259
|
status: "fail",
|
|
6251
|
-
message: err instanceof Error ? err.message :
|
|
6260
|
+
message: err instanceof Error ? err.message : /* c8 ignore next */ String(err)
|
|
6252
6261
|
};
|
|
6253
6262
|
}
|
|
6254
6263
|
}
|
|
@@ -6310,55 +6319,59 @@ async function runSync(input) {
|
|
|
6310
6319
|
for (const stepName of SYNC_STEPS) {
|
|
6311
6320
|
if (requestedSteps !== void 0 && !requestedSteps.includes(stepName)) continue;
|
|
6312
6321
|
if (LOCAL_STEPS.has(stepName)) continue;
|
|
6313
|
-
if (stepName === "labels")
|
|
6314
|
-
|
|
6315
|
-
|
|
6316
|
-
|
|
6317
|
-
|
|
6318
|
-
|
|
6319
|
-
|
|
6320
|
-
|
|
6321
|
-
|
|
6322
|
-
|
|
6323
|
-
|
|
6322
|
+
if (stepName === "labels") {
|
|
6323
|
+
if (source.syncLabels) {
|
|
6324
|
+
steps.push(await runSyncStep("source", "sync labels", dryRun, () => source.syncLabels(CANONICAL_LABELS, STALE_LABELS)));
|
|
6325
|
+
print(formatSyncStep(steps[steps.length - 1]));
|
|
6326
|
+
} else {
|
|
6327
|
+
steps.push({
|
|
6328
|
+
capability: "source",
|
|
6329
|
+
step: "sync labels",
|
|
6330
|
+
status: "skip",
|
|
6331
|
+
message: "provider does not implement syncLabels"
|
|
6332
|
+
});
|
|
6333
|
+
print(formatSyncStep(steps[steps.length - 1]));
|
|
6334
|
+
}
|
|
6324
6335
|
}
|
|
6325
|
-
if (stepName === "properties")
|
|
6326
|
-
|
|
6327
|
-
|
|
6328
|
-
|
|
6329
|
-
|
|
6330
|
-
|
|
6331
|
-
|
|
6332
|
-
|
|
6333
|
-
|
|
6334
|
-
|
|
6335
|
-
|
|
6336
|
-
|
|
6337
|
-
|
|
6338
|
-
|
|
6339
|
-
|
|
6340
|
-
|
|
6341
|
-
|
|
6342
|
-
|
|
6343
|
-
|
|
6344
|
-
|
|
6345
|
-
|
|
6336
|
+
if (stepName === "properties") {
|
|
6337
|
+
if (source.syncProperties) {
|
|
6338
|
+
const repo = config.repo;
|
|
6339
|
+
const properties = {};
|
|
6340
|
+
const effectivePreset = repo?.protection;
|
|
6341
|
+
if (effectivePreset && effectivePreset !== "none") properties["holocron_branch_protection_level"] = effectivePreset;
|
|
6342
|
+
const isMonorepo = await access(join(input.context.repoRoot, "pnpm-workspace.yaml")).then(() => true).catch(() => false);
|
|
6343
|
+
properties["monorepo"] = String(isMonorepo);
|
|
6344
|
+
const manual = repo?.properties ?? {};
|
|
6345
|
+
if (manual.lifecycle) properties["lifecycle"] = manual.lifecycle;
|
|
6346
|
+
if (manual.open_source !== void 0) properties["open_source"] = String(manual.open_source);
|
|
6347
|
+
if (manual.runtime_environment) properties["runtime_environment"] = manual.runtime_environment;
|
|
6348
|
+
if (manual.uses_external_packages !== void 0) properties["uses_external_packages"] = String(manual.uses_external_packages);
|
|
6349
|
+
{
|
|
6350
|
+
const rootPackageJson = await readFile(join(input.context.repoRoot, "package.json"), "utf8").then((raw) => JSON.parse(raw)).catch(() => null);
|
|
6351
|
+
const workspacePackages = readWorkspacePackages(input.context.repoRoot);
|
|
6352
|
+
const workspacePackageJsons = await readWorkspacePackageJsons(input.context.repoRoot, workspacePackages);
|
|
6353
|
+
properties["holocron_profile"] = deriveProfile({
|
|
6354
|
+
rootPackageJson,
|
|
6355
|
+
repoName: basename(input.context.repoRoot),
|
|
6356
|
+
isMonorepo,
|
|
6357
|
+
workspacePackageJsons
|
|
6358
|
+
});
|
|
6359
|
+
properties["holocron_stack"] = deriveStack(rootPackageJson);
|
|
6360
|
+
const capabilities = deriveCapabilities(config.providers);
|
|
6361
|
+
properties["holocron_capabilities"] = capabilities;
|
|
6362
|
+
properties["holocron_compliance"] = deriveCompliance(capabilities);
|
|
6363
|
+
}
|
|
6364
|
+
steps.push(await runSyncStep("source", "sync properties", dryRun, () => source.syncProperties(properties)));
|
|
6365
|
+
print(formatSyncStep(steps[steps.length - 1]));
|
|
6366
|
+
} else {
|
|
6367
|
+
steps.push({
|
|
6368
|
+
capability: "source",
|
|
6369
|
+
step: "sync properties",
|
|
6370
|
+
status: "skip",
|
|
6371
|
+
message: "provider does not implement syncProperties"
|
|
6346
6372
|
});
|
|
6347
|
-
|
|
6348
|
-
const capabilities = deriveCapabilities(config.providers);
|
|
6349
|
-
properties["holocron_capabilities"] = capabilities;
|
|
6350
|
-
properties["holocron_compliance"] = deriveCompliance(capabilities);
|
|
6373
|
+
print(formatSyncStep(steps[steps.length - 1]));
|
|
6351
6374
|
}
|
|
6352
|
-
steps.push(await runSyncStep("source", "sync properties", dryRun, () => source.syncProperties(properties)));
|
|
6353
|
-
print(formatSyncStep(steps[steps.length - 1]));
|
|
6354
|
-
} else {
|
|
6355
|
-
steps.push({
|
|
6356
|
-
capability: "source",
|
|
6357
|
-
step: "sync properties",
|
|
6358
|
-
status: "skip",
|
|
6359
|
-
message: "provider does not implement syncProperties"
|
|
6360
|
-
});
|
|
6361
|
-
print(formatSyncStep(steps[steps.length - 1]));
|
|
6362
6375
|
}
|
|
6363
6376
|
if (stepName === "teams") {
|
|
6364
6377
|
const teams = config.repo?.teams ?? [];
|
|
@@ -6570,32 +6583,34 @@ async function runSync(input) {
|
|
|
6570
6583
|
}
|
|
6571
6584
|
}
|
|
6572
6585
|
}
|
|
6573
|
-
if (stepName === "scripts")
|
|
6574
|
-
|
|
6575
|
-
|
|
6576
|
-
|
|
6577
|
-
|
|
6578
|
-
|
|
6579
|
-
|
|
6580
|
-
|
|
6581
|
-
|
|
6582
|
-
|
|
6583
|
-
|
|
6584
|
-
|
|
6585
|
-
|
|
6586
|
-
|
|
6587
|
-
|
|
6588
|
-
|
|
6589
|
-
|
|
6590
|
-
|
|
6591
|
-
|
|
6592
|
-
|
|
6593
|
-
|
|
6594
|
-
|
|
6595
|
-
|
|
6596
|
-
|
|
6597
|
-
|
|
6598
|
-
|
|
6586
|
+
if (stepName === "scripts") {
|
|
6587
|
+
if (config.syncScripts === false) {
|
|
6588
|
+
steps.push({
|
|
6589
|
+
capability: "local",
|
|
6590
|
+
step: "sync scripts",
|
|
6591
|
+
status: "skip",
|
|
6592
|
+
message: "syncScripts: false"
|
|
6593
|
+
});
|
|
6594
|
+
print(formatSyncStep(steps[steps.length - 1]));
|
|
6595
|
+
} else {
|
|
6596
|
+
const tasksConfig = { tasks: config.tasks };
|
|
6597
|
+
if (config.holocronScript !== void 0) tasksConfig.holocronScript = config.holocronScript;
|
|
6598
|
+
const astromechScripts = createAstromech({
|
|
6599
|
+
cwd: input.context.repoRoot,
|
|
6600
|
+
config: tasksConfig,
|
|
6601
|
+
logger
|
|
6602
|
+
});
|
|
6603
|
+
const desired = astromechScripts.packageScripts();
|
|
6604
|
+
const turboContent = astromechScripts.turboConfig();
|
|
6605
|
+
const turboEligible = new Set(turboContent ? Object.keys(JSON.parse(turboContent).tasks) : []);
|
|
6606
|
+
steps.push(await runSyncStep("local", "sync scripts", dryRun, async () => {
|
|
6607
|
+
const changed = await mergePackageJsonScripts(input.context.repoRoot, desired, turboEligible);
|
|
6608
|
+
if (changed === null) return "no package.json";
|
|
6609
|
+
if (changed.length === 0) return `${Object.keys(desired).length} scripts already current`;
|
|
6610
|
+
return `${changed.join(", ")} set`;
|
|
6611
|
+
}));
|
|
6612
|
+
print(formatSyncStep(steps[steps.length - 1]));
|
|
6613
|
+
}
|
|
6599
6614
|
}
|
|
6600
6615
|
if (stepName === "turbo") {
|
|
6601
6616
|
const astromechTurbo = createAstromech({
|
|
@@ -8057,7 +8072,7 @@ async function launchMenu(entries, parentArgv, pickMessage, nonInteractiveMessag
|
|
|
8057
8072
|
//#endregion
|
|
8058
8073
|
//#region src/update-notifier.ts
|
|
8059
8074
|
const PACKAGE_NAME = "@theholocron/cli";
|
|
8060
|
-
const CACHE_TTL_MS =
|
|
8075
|
+
const CACHE_TTL_MS = 864e5;
|
|
8061
8076
|
const FETCH_TIMEOUT_MS = 3e3;
|
|
8062
8077
|
function getCacheDir() {
|
|
8063
8078
|
return env.get("HOLOCRON_CACHE_DIR") ?? join(homedir(), ".cache", "holocron");
|