fix circular deps (#840)
Some checks failed
all-good: Did all the other checks pass? / all-good (push) Has been cancelled
Ensure Prisma migrations are in sync with the schema / check_prisma_migrations (22.x) (push) Has been cancelled
Docker Emulator Test / docker (push) Has been cancelled
Docker Server Build and Push / Docker Build and Push Server (push) Has been cancelled
Docker Server Test / docker (push) Has been cancelled
Runs E2E API Tests / build (22.x) (push) Has been cancelled
Runs E2E API Tests with external source of truth / build (22.x) (push) Has been cancelled
Lint & build / lint_and_build (latest) (push) Has been cancelled
Mirror main branch to main-mirror-for-wdb / lint_and_build (push) Has been cancelled
Dev Environment Test / restart-dev-and-test (push) Has been cancelled
Run setup tests / setup-tests (push) Has been cancelled
TOC Generator / TOC Generator (push) Has been cancelled

<!--

Make sure you've read the CONTRIBUTING.md guidelines:
https://github.com/stack-auth/stack-auth/blob/dev/CONTRIBUTING.md

-->

<!-- ELLIPSIS_HIDDEN -->


----

> [!IMPORTANT]
> Fixes circular dependencies by restructuring OpenAPI type definitions
and updating API paths, with enhancements to the API Explorer.
> 
>   - **Breaking Changes**:
> - MCP API endpoints are now prefixed with `/api/internal` instead of
`/api`.
>   - **New Features**:
> - API Explorer now supports building JSON request bodies from
individual fields.
> - Generated curl/JavaScript/Python snippets reflect the new body
builder.
>   - **Bug Fixes**:
> - Improved URL handling in the API Explorer to prevent errors when
server URLs are missing.
>   - **Refactor**:
> - Centralized OpenAPI type definitions into `openapi-types.ts` for
consistency and reuse.
> - Updated imports in `enhanced-api-page.tsx` and `openapi-utils.ts` to
use the new `openapi-types.ts`.
> 
> <sup>This description was created by </sup>[<img alt="Ellipsis"
src="https://img.shields.io/badge/Ellipsis-blue?color=175173">](https://www.ellipsis.dev?ref=stack-auth%2Fstack-auth&utm_source=github&utm_medium=referral)<sup>
for bb27147b03. You can
[customize](https://app.ellipsis.dev/stack-auth/settings/summaries) this
summary. It will automatically update as commits are pushed.</sup>

----


<!-- ELLIPSIS_HIDDEN -->

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Refactor**
* Centralized OpenAPI type definitions into a shared module for
consistency.
* Updated internal tool API routing under an internal namespace; no
user-facing behavior changes.
  * Improved URL handling with safer fallbacks.
* Switched request builder to field-based JSON bodies for clearer, more
reliable payload construction.

* **Documentation**
* Regenerated code examples (cURL/JS/Python) to reflect safer URL
handling and structured JSON bodies.
* Aligned docs components with shared types for improved
maintainability.

* **Chores**
  * Adjusted internal imports and paths to match new module locations.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
Madison 2025-08-12 13:00:35 -05:00 committed by GitHub
parent 34a46584c6
commit 0580a563d8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 83 additions and 80 deletions

View File

@ -1,7 +1,7 @@
import { createMcpHandler } from "@vercel/mcp-adapter";
import { readFile } from "node:fs/promises";
import { z } from "zod";
import { apiSource, source } from "../../../../lib/source";
import { apiSource, source } from "../../../../../lib/source";
import { PostHog } from "posthog-node";
@ -246,7 +246,7 @@ const handler = createMcpHandler(
},
},
{
basePath: "/api",
basePath: "/api/internal",
verboseLogs: true,
maxDuration: 60,
}

View File

@ -35,7 +35,7 @@ export default function McpBrowserPage() {
// Function to call MCP tools
const callMcpTool = async (toolName: string, args: Record<string, string> = {}) => {
const response = await fetch('/api/mcp', {
const response = await fetch('/api/internal/mcp', {
method: 'POST',
headers: {
'Content-Type': 'application/json',

View File

@ -2,81 +2,11 @@
import { ArrowRight, Check, Code, Copy, Play, Send, Settings, Zap } from 'lucide-react';
import { useCallback, useEffect, useState } from 'react';
import type { OpenAPIOperation, OpenAPIParameter, OpenAPISchema, OpenAPISpec } from '../../lib/openapi-types';
import { resolveSchema } from '../../lib/openapi-utils';
import { useAPIPageContext } from './api-page-wrapper';
import { Button } from './button';
// Types for OpenAPI specification
export type OpenAPISchema = {
type?: 'string' | 'number' | 'integer' | 'boolean' | 'array' | 'object' | 'null',
properties?: Record<string, OpenAPISchema>,
items?: OpenAPISchema,
required?: string[],
example?: unknown,
description?: string,
$ref?: string,
allOf?: OpenAPISchema[],
oneOf?: OpenAPISchema[],
anyOf?: OpenAPISchema[],
enum?: unknown[],
format?: string,
minimum?: number,
maximum?: number,
minLength?: number,
maxLength?: number,
pattern?: string,
additionalProperties?: boolean | OpenAPISchema,
}
export type OpenAPISpec = {
openapi: string,
info: {
title: string,
version: string,
description?: string,
},
servers: Array<{
url: string,
description?: string,
}>,
paths: Record<string, Record<string, OpenAPIOperation>>,
webhooks?: Record<string, Record<string, OpenAPIOperation>>,
components?: {
schemas?: Record<string, OpenAPISchema>,
securitySchemes?: Record<string, unknown>,
},
}
type OpenAPIOperation = {
summary?: string,
description?: string,
operationId?: string,
tags?: string[],
parameters?: OpenAPIParameter[],
requestBody?: {
required?: boolean,
content: Record<string, {
schema: OpenAPISchema,
}>,
},
responses: Record<string, {
description: string,
content?: Record<string, {
schema: OpenAPISchema,
}>,
}>,
security?: Array<Record<string, string[]>>,
}
type OpenAPIParameter = {
name: string,
in: 'query' | 'path' | 'header' | 'cookie',
required?: boolean,
description?: string,
schema: OpenAPISchema,
example?: unknown,
}
type EnhancedAPIPageProps = {
document: string,
operations: Array<{
@ -275,7 +205,7 @@ export function EnhancedAPIPage({ document, operations, description }: EnhancedA
}));
try {
const baseUrl = spec?.servers[0]?.url || '';
const baseUrl = spec?.servers?.[0]?.url || '';
let url = baseUrl + path;
// Replace path parameters
@ -455,7 +385,7 @@ function ModernAPIPlayground({
};
const generateCurlCommand = useCallback(() => {
const baseUrl = spec.servers[0]?.url || '';
const baseUrl = spec.servers?.[0]?.url || '';
let url = baseUrl + path;
// Replace path parameters
@ -500,9 +430,8 @@ function ModernAPIPlayground({
return curlCommand;
}, [operation, path, method, spec, requestState]);
const generateJavaScriptCode = useCallback(() => {
const baseUrl = spec.servers[0]?.url || '';
const baseUrl = spec.servers?.[0]?.url || '';
let url = baseUrl + path;
// Replace path parameters
@ -552,7 +481,7 @@ function ModernAPIPlayground({
}, [operation, path, method, spec, requestState]);
const generatePythonCode = useCallback(() => {
const baseUrl = spec.servers[0]?.url || '';
const baseUrl = spec.servers?.[0]?.url || '';
let url = baseUrl + path;
// Replace path parameters

View File

@ -0,0 +1,74 @@
// Types for OpenAPI specification
export type OpenAPISchema = {
type?: 'string' | 'number' | 'integer' | 'boolean' | 'array' | 'object' | 'null',
properties?: Record<string, OpenAPISchema>,
items?: OpenAPISchema,
required?: string[],
enum?: (string | number)[],
example?: unknown,
description?: string,
format?: string,
pattern?: string,
minLength?: number,
maxLength?: number,
minimum?: number,
maximum?: number,
$ref?: string,
allOf?: OpenAPISchema[],
oneOf?: OpenAPISchema[],
anyOf?: OpenAPISchema[],
not?: OpenAPISchema,
additionalProperties?: boolean | OpenAPISchema,
}
export type OpenAPISpec = {
openapi: string,
info: {
title: string,
version: string,
description?: string,
},
servers?: Array<{
url: string,
description?: string,
}>,
paths: Record<string, Record<string, OpenAPIOperation>>,
components?: {
schemas?: Record<string, OpenAPISchema>,
securitySchemes?: Record<string, unknown>,
},
}
export type OpenAPIParameter = {
name: string,
in: 'query' | 'path' | 'header' | 'cookie',
required?: boolean,
description?: string,
schema: OpenAPISchema,
example?: unknown,
}
export type OpenAPIOperation = {
summary?: string,
description?: string,
operationId?: string,
tags?: string[],
parameters?: OpenAPIParameter[],
requestBody?: {
required?: boolean,
content: {
'application/json'?: {
schema: OpenAPISchema,
},
},
},
responses: Record<string, {
description: string,
content?: {
'application/json'?: {
schema: OpenAPISchema,
},
},
}>,
security?: Array<Record<string, string[]>>,
}

View File

@ -1,4 +1,4 @@
import type { OpenAPISchema, OpenAPISpec } from '../components/api/enhanced-api-page';
import type { OpenAPISchema, OpenAPISpec } from './openapi-types';
/**
* Resolves $ref references in OpenAPI schemas recursively