Skip to content

Commit 0df1d23

Browse files
ataibarkaiclaude
andcommitted
feat(showcase/scripts): port loadDocsLinks() into generate-registry
Ports the loadDocsLinks() helper from 4084 into generate-registry.ts. After schema validation, each integration gets a docs_links field merged in from its sibling packages/<slug>/docs-links.json (best-effort: missing file or stale shell_docs_url shape is tolerated). The shell-internal DocsRow reads this via integration.docs_links.features[<id>] to prefer curated per-column overrides over the per-feature defaults. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent aa93004 commit 0df1d23

1 file changed

Lines changed: 66 additions & 0 deletions

File tree

showcase/scripts/generate-registry.ts

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,64 @@ function loadFeatureRegistry() {
3939
return JSON.parse(raw);
4040
}
4141

42+
type DocsLinkEntry = {
43+
og_docs_url: string | null;
44+
shell_docs_path: string | null;
45+
};
46+
47+
type DocsLinks = {
48+
features: Record<string, DocsLinkEntry>;
49+
};
50+
51+
/**
52+
* Load per-package docs-links.json. Returns best-effort normalized overrides
53+
* ({ features: { <feature_id>: { og_docs_url, shell_docs_path } } }).
54+
*
55+
* Missing file -> empty overrides. A file with the older shape (e.g. using
56+
* `shell_docs_url` instead of `shell_docs_path`) is treated as stale: we
57+
* still merge what we can without erroring. Completely malformed JSON is
58+
* logged and treated as empty.
59+
*/
60+
function loadDocsLinks(packageDir: string): DocsLinks {
61+
const docsLinksPath = path.join(packageDir, "docs-links.json");
62+
if (!fs.existsSync(docsLinksPath)) {
63+
return { features: {} };
64+
}
65+
66+
try {
67+
const raw = fs.readFileSync(docsLinksPath, "utf-8");
68+
const parsed = JSON.parse(raw) as {
69+
features?: Record<string, Record<string, unknown>>;
70+
};
71+
72+
const features: Record<string, DocsLinkEntry> = {};
73+
const rawFeatures = parsed?.features ?? {};
74+
for (const [featureId, entry] of Object.entries(rawFeatures)) {
75+
if (!entry || typeof entry !== "object") continue;
76+
const og =
77+
typeof entry.og_docs_url === "string" ? entry.og_docs_url : null;
78+
// Preferred key is `shell_docs_path`; fall back to legacy
79+
// `shell_docs_url` so older files still contribute something.
80+
const shellPath =
81+
typeof entry.shell_docs_path === "string"
82+
? entry.shell_docs_path
83+
: typeof entry.shell_docs_url === "string"
84+
? entry.shell_docs_url
85+
: null;
86+
features[featureId] = {
87+
og_docs_url: og,
88+
shell_docs_path: shellPath,
89+
};
90+
}
91+
return { features };
92+
} catch (e) {
93+
console.warn(
94+
` WARN: failed to parse ${docsLinksPath}, treating as empty: ${e}`,
95+
);
96+
return { features: {} };
97+
}
98+
}
99+
42100
function findManifests(): string[] {
43101
if (!fs.existsSync(PACKAGES_DIR)) {
44102
return [];
@@ -146,6 +204,14 @@ function main() {
146204
console.log(` OK: ${manifest.name} (${manifest.slug})`);
147205
}
148206

207+
// Merge per-package docs-links.json overrides onto each integration *after*
208+
// schema validation, since `docs_links` isn't part of the manifest schema.
209+
// Best-effort: missing file or stale shapes are tolerated and don't error.
210+
for (const manifest of integrations) {
211+
const pkgDir = path.join(PACKAGES_DIR, manifest.slug as string);
212+
manifest.docs_links = loadDocsLinks(pkgDir);
213+
}
214+
149215
// Constraint validation
150216
const constraintsRaw = fs.readFileSync(CONSTRAINTS_PATH, "utf-8");
151217
const constraints = yaml.parse(constraintsRaw);

0 commit comments

Comments
 (0)