Major additions: - Community Next.js app (port 18187) for browsing claims with API docs - stemedb-chaos crate: Fault injection, chaos testing, CRDT properties - Latent ingestion system: Reddit/FDA ingesters with ADK-Go agents - Disputed claims handling: Manual review workflows and validation - Aphoria security scanner: New extractors (SQL injection, command injection, weak crypto, TLS version), policy-based ignores, UAT reports - Docker infrastructure: Dockerfile, docker-compose.yml for full stack - VulnBank demo: Intentionally vulnerable multi-language test corpus SDK & API enhancements: - Source registry handlers for tracking data provenance - Metrics endpoint - Skeptic filtering improvements Code quality: - Split 14 large files (>500 lines) into focused modules - All files now under 500-line limit per project guidelines Documentation: - Chaos testing guide, circuit breakers, observability docs - Phase 7 UAT documentation updates - Martin Kleppmann technical writer agent Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
61 lines
2.0 KiB
TypeScript
61 lines
2.0 KiB
TypeScript
/**
|
|
* Fetches the OpenAPI spec from the running stemedb-api server
|
|
* and saves it to public/openapi.json for use by Scalar.
|
|
*
|
|
* Usage:
|
|
* npx tsx scripts/fetch-openapi.ts
|
|
*
|
|
* Set STEMEDB_API_URL to override the default endpoint.
|
|
*/
|
|
|
|
import { writeFileSync, existsSync, readFileSync } from "fs";
|
|
import { join } from "path";
|
|
|
|
const API_URL = process.env.STEMEDB_API_URL || "http://127.0.0.1:18180";
|
|
const OPENAPI_ENDPOINT = `${API_URL}/api-docs/openapi.json`;
|
|
const OUTPUT_PATH = join(process.cwd(), "public", "openapi.json");
|
|
|
|
async function fetchOpenApiSpec(): Promise<void> {
|
|
console.log(`Fetching OpenAPI spec from ${OPENAPI_ENDPOINT}...`);
|
|
|
|
try {
|
|
const response = await fetch(OPENAPI_ENDPOINT);
|
|
|
|
if (!response.ok) {
|
|
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
}
|
|
|
|
const spec = await response.json();
|
|
|
|
// Validate it looks like an OpenAPI spec
|
|
if (!spec.openapi || !spec.info || !spec.paths) {
|
|
throw new Error("Invalid OpenAPI spec: missing required fields");
|
|
}
|
|
|
|
writeFileSync(OUTPUT_PATH, JSON.stringify(spec, null, 2));
|
|
console.log(`OpenAPI spec saved to ${OUTPUT_PATH}`);
|
|
console.log(` Version: ${spec.info.version}`);
|
|
console.log(` Title: ${spec.info.title}`);
|
|
console.log(` Endpoints: ${Object.keys(spec.paths).length}`);
|
|
} catch (error) {
|
|
if (error instanceof Error && error.message.includes("ECONNREFUSED")) {
|
|
console.warn("Could not connect to stemedb-api server.");
|
|
console.warn("Using existing spec if available, or provide a bundled fallback.");
|
|
|
|
if (existsSync(OUTPUT_PATH)) {
|
|
const existing = JSON.parse(readFileSync(OUTPUT_PATH, "utf-8"));
|
|
console.log(`Using cached spec (v${existing.info?.version || "unknown"})`);
|
|
return;
|
|
}
|
|
|
|
console.error("No cached spec available. Start stemedb-api and retry.");
|
|
process.exit(1);
|
|
}
|
|
|
|
console.error("Failed to fetch OpenAPI spec:", error);
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
fetchOpenApiSpec();
|