@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.
Files changed (2) hide show
  1. package/dist/index.js +86 -4
  2. 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
- const projectSlug = await prompt("Project slug:");
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
- console.error("\n Error: Project slug is required\n");
708
- process.exit(1);
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
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@overscore/cli",
3
- "version": "0.9.0",
3
+ "version": "0.9.2",
4
4
  "description": "CLI for deploying Overscore dashboards and publishing analyses",
5
5
  "bin": {
6
6
  "overscore": "dist/index.js"