@overscore/cli 0.9.0 → 0.9.2
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/index.js +86 -4
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -695,17 +695,38 @@ async function loadAnalysisConfig() {
|
|
|
695
695
|
};
|
|
696
696
|
}
|
|
697
697
|
}
|
|
698
|
-
// (3) Interactive
|
|
698
|
+
// (3) Interactive — only ask for the API key, resolve project automatically
|
|
699
699
|
console.log("\n No Overscore config found. Let's set one up.\n");
|
|
700
700
|
const apiKey = await prompt("API key (from the Hub):");
|
|
701
701
|
if (!apiKey || !apiKey.startsWith("os_")) {
|
|
702
702
|
console.error("\n Error: API key should start with os_\n");
|
|
703
703
|
process.exit(1);
|
|
704
704
|
}
|
|
705
|
-
|
|
705
|
+
// Look up the project slug from the key
|
|
706
|
+
let projectSlug = null;
|
|
707
|
+
try {
|
|
708
|
+
const res = await fetch(`${HUB_URL}/api/auth/key-info`, {
|
|
709
|
+
method: "POST",
|
|
710
|
+
headers: { "Content-Type": "application/json" },
|
|
711
|
+
body: JSON.stringify({ key: apiKey }),
|
|
712
|
+
});
|
|
713
|
+
if (res.ok) {
|
|
714
|
+
const data = (await res.json());
|
|
715
|
+
projectSlug = data.project_slug || null;
|
|
716
|
+
if (projectSlug) {
|
|
717
|
+
console.log(`\n Detected project: ${projectSlug}`);
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
catch {
|
|
722
|
+
// Fall back to manual entry
|
|
723
|
+
}
|
|
706
724
|
if (!projectSlug) {
|
|
707
|
-
|
|
708
|
-
|
|
725
|
+
projectSlug = await prompt("Project slug:");
|
|
726
|
+
if (!projectSlug) {
|
|
727
|
+
console.error("\n Error: Project slug is required\n");
|
|
728
|
+
process.exit(1);
|
|
729
|
+
}
|
|
709
730
|
}
|
|
710
731
|
// Save for next time
|
|
711
732
|
fs.mkdirSync(configDir, { recursive: true });
|
|
@@ -998,13 +1019,74 @@ async function analysisPull(slug) {
|
|
|
998
1019
|
});
|
|
999
1020
|
if (!res.ok) {
|
|
1000
1021
|
let errorMsg = `HTTP ${res.status}`;
|
|
1022
|
+
let isUnpublished = false;
|
|
1001
1023
|
try {
|
|
1002
1024
|
const body = await res.json();
|
|
1003
1025
|
errorMsg = body.error || errorMsg;
|
|
1026
|
+
if (res.status === 404 && errorMsg.includes("not been published")) {
|
|
1027
|
+
isUnpublished = true;
|
|
1028
|
+
}
|
|
1004
1029
|
}
|
|
1005
1030
|
catch {
|
|
1006
1031
|
// not JSON
|
|
1007
1032
|
}
|
|
1033
|
+
// If the analysis exists but hasn't been published yet, scaffold from
|
|
1034
|
+
// the template instead of trying to download a bundle that doesn't exist.
|
|
1035
|
+
if (isUnpublished) {
|
|
1036
|
+
console.log(" Not yet published — scaffolding from template...\n");
|
|
1037
|
+
const distDir = path.dirname(new URL(import.meta.url).pathname);
|
|
1038
|
+
const pkgRoot = path.resolve(distDir, "..");
|
|
1039
|
+
const templateDir = path.join(pkgRoot, "templates", "analysis");
|
|
1040
|
+
if (!fs.existsSync(templateDir)) {
|
|
1041
|
+
console.error(`\n Error: Bundled analysis template not found.\n`);
|
|
1042
|
+
process.exit(1);
|
|
1043
|
+
}
|
|
1044
|
+
// Fetch analysis metadata from the Hub
|
|
1045
|
+
const metaRes = await analysisApiRequest(cfg, "GET", `/api/analyses/${slug}/meta`).catch(() => null);
|
|
1046
|
+
const targetDir = path.resolve(process.cwd(), slug);
|
|
1047
|
+
if (fs.existsSync(targetDir)) {
|
|
1048
|
+
const yes = await confirm(`Directory "${slug}" already exists. Overwrite?`);
|
|
1049
|
+
if (!yes) {
|
|
1050
|
+
console.log(" Cancelled.\n");
|
|
1051
|
+
return;
|
|
1052
|
+
}
|
|
1053
|
+
fs.rmSync(targetDir, { recursive: true, force: true });
|
|
1054
|
+
}
|
|
1055
|
+
fs.mkdirSync(targetDir, { recursive: true });
|
|
1056
|
+
fs.mkdirSync(path.join(targetDir, ".overscore"), { recursive: true });
|
|
1057
|
+
const today = new Date().toISOString().slice(0, 10);
|
|
1058
|
+
const title = metaRes?.title || slug;
|
|
1059
|
+
scaffoldFromTemplate(templateDir, targetDir, {
|
|
1060
|
+
TITLE: title,
|
|
1061
|
+
SLUG: slug,
|
|
1062
|
+
PROJECT_SLUG: cfg.projectSlug,
|
|
1063
|
+
DATE: today,
|
|
1064
|
+
});
|
|
1065
|
+
// Write analysis.json so publish knows which analysis this is
|
|
1066
|
+
fs.writeFileSync(path.join(targetDir, ".overscore", "analysis.json"), JSON.stringify({
|
|
1067
|
+
id: metaRes?.id || "",
|
|
1068
|
+
slug,
|
|
1069
|
+
title,
|
|
1070
|
+
project_slug: cfg.projectSlug,
|
|
1071
|
+
created_at: new Date().toISOString(),
|
|
1072
|
+
}, null, 2));
|
|
1073
|
+
const baseUrl = cfg.apiUrl.replace(/\/api$/, "");
|
|
1074
|
+
await syncHubManagedRules(targetDir, baseUrl, cfg.projectSlug, cfg.apiKey);
|
|
1075
|
+
await syncPlatformRules(targetDir, baseUrl, cfg.apiKey);
|
|
1076
|
+
console.log(` Scaffolded "${title}"
|
|
1077
|
+
|
|
1078
|
+
Next steps:
|
|
1079
|
+
|
|
1080
|
+
cd ${slug}
|
|
1081
|
+
code .
|
|
1082
|
+
claude
|
|
1083
|
+
|
|
1084
|
+
Then ask Claude to do the analysis. When the report.html looks good:
|
|
1085
|
+
|
|
1086
|
+
npx @overscore/cli analysis publish
|
|
1087
|
+
`);
|
|
1088
|
+
return;
|
|
1089
|
+
}
|
|
1008
1090
|
console.error(`\n Error: ${errorMsg}\n`);
|
|
1009
1091
|
process.exit(1);
|
|
1010
1092
|
}
|