@overscore/cli 0.8.0 → 0.9.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/dist/index.js +108 -31
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -287,6 +287,8 @@ async function deploy() {
|
|
|
287
287
|
// Non-fatal
|
|
288
288
|
}
|
|
289
289
|
}
|
|
290
|
+
// Pull latest platform rules so the local project stays up to date
|
|
291
|
+
await syncPlatformRules(process.cwd(), baseUrl, apiKey);
|
|
290
292
|
}
|
|
291
293
|
async function queryList() {
|
|
292
294
|
const { dashboardSlug } = loadEnv();
|
|
@@ -543,6 +545,26 @@ VITE_OVERSCORE_API_URL=https://overscore.dev/api
|
|
|
543
545
|
catch {
|
|
544
546
|
// Non-fatal — the version from the source zip is fine
|
|
545
547
|
}
|
|
548
|
+
// Pull dashboard context from Hub (may be newer than the source zip)
|
|
549
|
+
try {
|
|
550
|
+
const dashCtxRes = await fetch(`${baseUrl}/api/dashboards/${dashboardSlug}/context`, {
|
|
551
|
+
headers: { Authorization: `Bearer ${apiKey}` },
|
|
552
|
+
});
|
|
553
|
+
if (dashCtxRes.ok) {
|
|
554
|
+
const dashCtxData = (await dashCtxRes.json());
|
|
555
|
+
if (dashCtxData.context_md) {
|
|
556
|
+
const rulesDir = path.join(targetDir, ".claude", "rules");
|
|
557
|
+
fs.mkdirSync(rulesDir, { recursive: true });
|
|
558
|
+
fs.writeFileSync(path.join(rulesDir, "dashboard-context.md"), dashCtxData.context_md);
|
|
559
|
+
console.log(" Updated dashboard context from Hub.");
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
catch {
|
|
564
|
+
// Non-fatal
|
|
565
|
+
}
|
|
566
|
+
// Pull latest platform rules
|
|
567
|
+
await syncPlatformRules(targetDir, baseUrl, apiKey);
|
|
546
568
|
console.log(`
|
|
547
569
|
Pulled v${version}${commitMsg ? ` — "${commitMsg}"` : ""}
|
|
548
570
|
|
|
@@ -711,6 +733,84 @@ async function analysisApiRequest(cfg, method, urlPath, body) {
|
|
|
711
733
|
}
|
|
712
734
|
return data;
|
|
713
735
|
}
|
|
736
|
+
/**
|
|
737
|
+
* Fetch hub-managed rule files (company-context, sql-style) for a project
|
|
738
|
+
* and write them into the target analysis folder, overwriting whatever's
|
|
739
|
+
* there. Best-effort and non-fatal — if the hub is unreachable, the existing
|
|
740
|
+
* files (template defaults or bundle contents) stay in place.
|
|
741
|
+
*
|
|
742
|
+
* Called from both `analysis new` (after the template walker) and `analysis
|
|
743
|
+
* pull` (after the bundle extraction) so hub overrides always reflect the
|
|
744
|
+
* latest state regardless of how the analysis was created.
|
|
745
|
+
*/
|
|
746
|
+
async function syncHubManagedRules(targetDir, baseUrl, projectSlug, apiKey) {
|
|
747
|
+
const authHeader = { Authorization: `Bearer ${apiKey}` };
|
|
748
|
+
const rulesDir = path.join(targetDir, ".claude", "rules");
|
|
749
|
+
fs.mkdirSync(rulesDir, { recursive: true });
|
|
750
|
+
// Company context — null means "no company context set yet"; leave any
|
|
751
|
+
// existing file alone in that case.
|
|
752
|
+
try {
|
|
753
|
+
const ctxRes = await fetch(`${baseUrl}/api/projects/${projectSlug}/context`, { headers: authHeader });
|
|
754
|
+
if (ctxRes.ok) {
|
|
755
|
+
const ctxData = (await ctxRes.json());
|
|
756
|
+
if (ctxData.context_md) {
|
|
757
|
+
fs.writeFileSync(path.join(rulesDir, "company-context.md"), ctxData.context_md);
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
catch {
|
|
762
|
+
// Non-fatal
|
|
763
|
+
}
|
|
764
|
+
// SQL style override — null means "use the CLI default"; leave the
|
|
765
|
+
// template/bundle file alone in that case.
|
|
766
|
+
try {
|
|
767
|
+
const sqlRes = await fetch(`${baseUrl}/api/projects/${projectSlug}/sql-style`, { headers: authHeader });
|
|
768
|
+
if (sqlRes.ok) {
|
|
769
|
+
const sqlData = (await sqlRes.json());
|
|
770
|
+
if (sqlData.sql_style_md) {
|
|
771
|
+
fs.writeFileSync(path.join(rulesDir, "sql-style.md"), sqlData.sql_style_md);
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
catch {
|
|
776
|
+
// Non-fatal
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
/**
|
|
780
|
+
* Fetch the latest platform-owned Claude Code rules from the Hub and write
|
|
781
|
+
* them into the project's .claude/ directory. This keeps rules like
|
|
782
|
+
* data-fetching.md, query-performance.md, and skills up to date even in
|
|
783
|
+
* projects that were scaffolded months ago.
|
|
784
|
+
*
|
|
785
|
+
* Called from `deploy` (before uploading) and `pull` (after extracting).
|
|
786
|
+
* User-owned files (company-context.md, dashboard-context.md) are NOT
|
|
787
|
+
* touched — those sync via separate mechanisms.
|
|
788
|
+
*/
|
|
789
|
+
async function syncPlatformRules(targetDir, baseUrl, apiKey) {
|
|
790
|
+
try {
|
|
791
|
+
const res = await fetch(`${baseUrl}/api/platform-rules`, {
|
|
792
|
+
headers: { Authorization: `Bearer ${apiKey}` },
|
|
793
|
+
});
|
|
794
|
+
if (!res.ok)
|
|
795
|
+
return;
|
|
796
|
+
const data = (await res.json());
|
|
797
|
+
if (!data.files)
|
|
798
|
+
return;
|
|
799
|
+
let count = 0;
|
|
800
|
+
for (const [relPath, content] of Object.entries(data.files)) {
|
|
801
|
+
const fullPath = path.join(targetDir, ".claude", relPath);
|
|
802
|
+
fs.mkdirSync(path.dirname(fullPath), { recursive: true });
|
|
803
|
+
fs.writeFileSync(fullPath, content);
|
|
804
|
+
count++;
|
|
805
|
+
}
|
|
806
|
+
if (count > 0) {
|
|
807
|
+
console.log(` Platform rules synced (${count} files).`);
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
catch {
|
|
811
|
+
// Non-fatal — existing rules stay in place
|
|
812
|
+
}
|
|
813
|
+
}
|
|
714
814
|
/**
|
|
715
815
|
* Recursively copies a template directory to a target directory, substituting
|
|
716
816
|
* `{{KEY}}` placeholders in text files. Mirrors directory structure.
|
|
@@ -793,38 +893,10 @@ async function analysisNew(title) {
|
|
|
793
893
|
PROJECT_SLUG: data.project_slug,
|
|
794
894
|
DATE: today,
|
|
795
895
|
});
|
|
796
|
-
// Pull
|
|
797
|
-
//
|
|
798
|
-
// the network is down or the hub is unreachable).
|
|
896
|
+
// Pull hub-managed rules (company context + sql style override). Best-effort
|
|
897
|
+
// and non-fatal — template defaults stay in place if the hub is unreachable.
|
|
799
898
|
const baseUrl = cfg.apiUrl.replace(/\/api$/, "");
|
|
800
|
-
|
|
801
|
-
// Company context
|
|
802
|
-
try {
|
|
803
|
-
const ctxRes = await fetch(`${baseUrl}/api/projects/${data.project_slug}/context`, { headers: authHeader });
|
|
804
|
-
if (ctxRes.ok) {
|
|
805
|
-
const ctxData = (await ctxRes.json());
|
|
806
|
-
if (ctxData.context_md) {
|
|
807
|
-
fs.writeFileSync(path.join(targetDir, ".claude", "rules", "company-context.md"), ctxData.context_md);
|
|
808
|
-
}
|
|
809
|
-
}
|
|
810
|
-
}
|
|
811
|
-
catch {
|
|
812
|
-
// Non-fatal
|
|
813
|
-
}
|
|
814
|
-
// SQL style override — if the project has a custom version, replace the
|
|
815
|
-
// template default. If null/missing, the template default stays in place.
|
|
816
|
-
try {
|
|
817
|
-
const sqlRes = await fetch(`${baseUrl}/api/projects/${data.project_slug}/sql-style`, { headers: authHeader });
|
|
818
|
-
if (sqlRes.ok) {
|
|
819
|
-
const sqlData = (await sqlRes.json());
|
|
820
|
-
if (sqlData.sql_style_md) {
|
|
821
|
-
fs.writeFileSync(path.join(targetDir, ".claude", "rules", "sql-style.md"), sqlData.sql_style_md);
|
|
822
|
-
}
|
|
823
|
-
}
|
|
824
|
-
}
|
|
825
|
-
catch {
|
|
826
|
-
// Non-fatal
|
|
827
|
-
}
|
|
899
|
+
await syncHubManagedRules(targetDir, baseUrl, data.project_slug, cfg.apiKey);
|
|
828
900
|
console.log(` Analysis created: ${data.title}
|
|
829
901
|
Slug: ${data.slug}
|
|
830
902
|
Project: ${data.project_slug}
|
|
@@ -965,6 +1037,11 @@ async function analysisPull(slug) {
|
|
|
965
1037
|
// Non-fatal
|
|
966
1038
|
}
|
|
967
1039
|
}
|
|
1040
|
+
// Refresh hub-managed rule files after restoring from the bundle. The
|
|
1041
|
+
// bundle contains whatever was set at publish time; this overwrites them
|
|
1042
|
+
// with the latest hub state so company context and SQL style stay in
|
|
1043
|
+
// sync across pulls. Best-effort and non-fatal.
|
|
1044
|
+
await syncHubManagedRules(targetDir, baseUrl, projectSlug, cfg.apiKey);
|
|
968
1045
|
console.log(`
|
|
969
1046
|
Pulled "${analysisTitle}"
|
|
970
1047
|
|