1
0
mirror of synced 2025-12-19 18:14:56 -05:00

docs(ai-agents): Move Sonar API docs from embedded-api to ai-agents instance (#70235)

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: ian.alton@airbyte.io <ian.alton@airbyte.io>
Co-authored-by: letiescanciano <leticia.escanciano@gmail.com>
This commit is contained in:
devin-ai-integration[bot]
2025-12-05 09:34:56 -08:00
committed by GitHub
parent 1088cedd76
commit cdd58ead27
8 changed files with 3452 additions and 1268 deletions

View File

@@ -0,0 +1,4 @@
# Ignore all generated OpenAPI documentation files
# These are generated by docusaurus-plugin-openapi-docs during build
*
!.gitignore

View File

@@ -2,8 +2,11 @@ import "dotenv/config.js";
import type { Config } from "@docusaurus/types";
import { themes as prismThemes } from "prism-react-renderer";
import type { Options as ClassicPresetOptions } from "@docusaurus/preset-classic";
import fs from "fs";
import { PluginOptions as LLmPluginOptions } from "@signalwire/docusaurus-plugin-llms-txt";
import {
loadSonarApiSidebar,
replaceApiReferenceCategory,
} from "./src/scripts/embedded-api/sidebar-generator";
// Import remark plugins - lazy load to prevent webpack from bundling Node.js code
const getRemarkPlugins = () => ({
@@ -19,7 +22,7 @@ const getRemarkPlugins = () => ({
const plugins = getRemarkPlugins();
// Import constants
// Import constants for embedded API sidebar generation
const {
SPEC_CACHE_PATH,
API_SIDEBAR_PATH,
@@ -164,8 +167,17 @@ const config: Config = {
id: "ai-agents",
path: "../docs/ai-agents",
routeBasePath: "/ai-agents",
sidebarPath: "./sidebar-ai-agents.js",
editUrl: "https://github.com/airbytehq/airbyte/blob/master/docs",
docItemComponent: "@theme/ApiItem", // Required for OpenAPI docs rendering
async sidebarItemsGenerator({ defaultSidebarItemsGenerator, ...args }) {
const sidebarItems = await defaultSidebarItemsGenerator(args);
// Load and filter the Sonar API sidebar based on allowed tags
const sonarApiItems = loadSonarApiSidebar();
// Replace the "api-reference" category with the filtered API items
return replaceApiReferenceCategory(sidebarItems, sonarApiItems);
},
remarkPlugins: [
plugins.docsHeaderDecoration,
plugins.enterpriseDocsHeaderInformation,
@@ -249,90 +261,15 @@ const config: Config = {
],
},
],
[
"@docusaurus/plugin-content-docs",
{
id: "embedded-api",
path: "api-docs/embedded-api",
routeBasePath: "/embedded-api/",
docItemComponent: "@theme/ApiItem",
async sidebarItemsGenerator() {
// We only want to include visible endpoints on the sidebar. We need to filter out endpoints with tags
// that are not included in the spec. Even if we didn't need to filter out elements the OpenAPI plugin generates a sidebar.ts
// file that exports a nested object, but Docusaurus expects just the array of sidebar items, so we need to extracts the actual sidebar
// items from the generated file structure.
try {
const specPath = SPEC_CACHE_PATH;
if (!fs.existsSync(specPath)) {
console.warn(
"Embedded API spec file not found, using empty sidebar",
);
return [];
}
const data = JSON.parse(fs.readFileSync(specPath, "utf8"));
console.log("Loaded embedded API spec from cache");
// Load the freshly generated sidebar (not the cached one from module load)
const sidebarPath = API_SIDEBAR_PATH;
let freshSidebar: any[] = [];
if (fs.existsSync(sidebarPath)) {
try {
const sidebarModule = require("./api-docs/embedded-api/sidebar.ts");
freshSidebar = sidebarModule.default || sidebarModule;
console.log("Loaded fresh sidebar from generated files");
} catch (sidebarError: any) {
console.warn(
"Could not load fresh sidebar, using empty array:",
sidebarError.message,
);
freshSidebar = [];
}
} else {
console.warn(
"Generated sidebar file not found, using empty array",
);
freshSidebar = [];
}
const allowedTags = data.tags?.map((tag: any) => tag["name"]) || [];
// Use freshly loaded sidebar items from the generated file
const sidebarItems = Array.isArray(freshSidebar)
? freshSidebar
: [];
const filteredItems = sidebarItems.filter((item: any) => {
if (item.type !== "category") {
return true;
}
return allowedTags.includes(item.label);
});
return filteredItems;
} catch (error: any) {
console.warn(
"Error loading embedded API spec from cache:",
error.message,
);
return [];
}
},
},
],
[
"docusaurus-plugin-openapi-docs",
{
id: "embedded-api",
docsPluginId: "embedded-api",
docsPluginId: "ai-agents",
config: {
embedded: {
specPath: "src/data/embedded_api_spec.json",
outputDir: "api-docs/embedded-api",
outputDir: "../docs/ai-agents/embedded/api-reference",
sidebarOptions: {
groupPathsBy: "tag",
categoryLinkSource: "tag",
@@ -476,10 +413,10 @@ const config: Config = {
label: "Release notes",
},
{
type: "docSidebar",
type: "doc",
position: "left",
docsPluginId: "ai-agents",
sidebarId: "ai-agents",
docId: "README",
label: "AI agents",
},
{

View File

@@ -16,7 +16,7 @@
"cleanup-cache": "node src/scripts/cleanup-cache.js",
"prebuild": "pnpm run prepare-registry-cache && pnpm run prepare-embedded-api",
"postbuild": "pnpm run cleanup-cache",
"prestart": "pnpm run prepare-registry-cache",
"prestart": "pnpm run prepare-registry-cache && pnpm run prepare-embedded-api",
"docusaurus": "docusaurus",
"start": "node src/scripts/fetchSchema.js && docusaurus start --port 3005",
"build": "node src/scripts/fetchSchema.js && docusaurus build",

View File

@@ -1,70 +0,0 @@
export default {
"ai-agents": [
{
type: "category",
collapsible: false,
label: "AI Agents",
link: {
type: "doc",
id: "README",
},
items: [
{
type: "category",
label: "Embedded",
items: [
{
type: "category",
label: "Widget",
items: [
"embedded/widget/quickstart",
{
type: "category",
label: "Tutorials",
items: [
"embedded/widget/tutorials/prerequisites-setup",
"embedded/widget/tutorials/develop-your-app",
"embedded/widget/tutorials/use-embedded",
],
},
"embedded/widget/managing-embedded",
"embedded/widget/template-tags",
],
},
{
type: "category",
label: "API",
items: [
"embedded/api/README",
{
type: "link",
label: "Sonar API reference",
href: "/embedded-api/sonar",
},
"embedded/api/connection-templates",
"embedded/api/source-templates",
"embedded/api/configuring-sources",
],
},
],
},
{
type: "category",
label: "MCP Servers",
items: [
{
type: "doc",
id: "pyairbyte-mcp",
label: "PyAirbyte MCP",
},
{
type: "doc",
id: "connector-builder-mcp",
label: "Connector Builder MCP",
},
]
}
]
}
],
};

File diff suppressed because it is too large Load Diff

View File

@@ -18,7 +18,7 @@ const SPEC_CACHE_PATH = path.join(PROJECT_ROOT, "src", "data", "embedded_api_spe
const EMBEDDED_API_SPEC_URL = "https://airbyte-sonar-prod.s3.us-east-2.amazonaws.com/openapi/latest/app.json";
// API documentation output directory (relative to project root)
const API_DOCS_OUTPUT_DIR = "api-docs/embedded-api";
const API_DOCS_OUTPUT_DIR = "../docs/ai-agents/embedded/api-reference";
// Sidebar file path for generated API docs
const API_SIDEBAR_PATH = path.join(PROJECT_ROOT, API_DOCS_OUTPUT_DIR, "sidebar.ts");

View File

@@ -0,0 +1,72 @@
import { API_SIDEBAR_PATH, SPEC_CACHE_PATH } from "./constants";
import * as fs from "fs";
const loadAllowedTags = (): string[] => {
if (fs.existsSync(SPEC_CACHE_PATH)) {
try {
const spec = JSON.parse(fs.readFileSync(SPEC_CACHE_PATH, "utf8"));
return spec.tags?.map((tag: any) => tag.name) || [];
} catch (e) {
console.warn("Could not load OpenAPI spec for tag filtering:", e);
}
}
return [];
};
export const loadSonarApiSidebar = (): any[] => {
const allowedTags = loadAllowedTags();
if (fs.existsSync(API_SIDEBAR_PATH)) {
try {
const sidebarModule = require(API_SIDEBAR_PATH);
// The sidebar.ts exports the array directly via: export default sidebar.apisidebar;
let apiSidebarItems = sidebarModule.default || sidebarModule || [];
// Filter to only show tags that are defined in the spec
apiSidebarItems = apiSidebarItems.filter((item: any) => {
if (item.type !== "category") {
return true;
}
return allowedTags.includes(item.label);
});
console.log(`Filtered API sidebar to ${apiSidebarItems.length} items`);
return apiSidebarItems;
} catch (e) {
console.warn("Could not load pre-generated API sidebar:", e);
return [];
}
}
return [];
};
// Helper function to find and replace the "api-reference" category
export const replaceApiReferenceCategory = (
items: any[],
sonarApiItems: any[],
): any[] => {
return items.map((item) => {
if (
item.type === "category" &&
item.label === "api-reference" &&
item.items !== undefined
) {
// Replace the api-reference category items with the filtered autogenerated API sidebar
return {
...item,
label: "Sonar API Reference",
items: sonarApiItems,
};
}
if (item.items) {
return {
...item,
items: replaceApiReferenceCategory(item.items, sonarApiItems),
};
}
return item;
});
};

View File

@@ -595,6 +595,16 @@
"source": "/platform/developer-guides/licenses/:path*",
"destination": "/community/licenses/:path*",
"statusCode": 301
},
{
"source": "/embedded-api/sonar",
"destination": "/ai-agents/embedded/api-reference/sonar",
"statusCode": 301
},
{
"source": "/embedded-api/:path*",
"destination": "/ai-agents/embedded/api-reference/:path*",
"statusCode": 301
}
]
}