@brainfish-ai/devdoc 0.1.21
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/LICENSE +33 -0
- package/README.md +415 -0
- package/bin/devdoc.js +13 -0
- package/dist/cli/commands/build.d.ts +5 -0
- package/dist/cli/commands/build.js +87 -0
- package/dist/cli/commands/check.d.ts +1 -0
- package/dist/cli/commands/check.js +143 -0
- package/dist/cli/commands/create.d.ts +24 -0
- package/dist/cli/commands/create.js +387 -0
- package/dist/cli/commands/deploy.d.ts +9 -0
- package/dist/cli/commands/deploy.js +433 -0
- package/dist/cli/commands/dev.d.ts +6 -0
- package/dist/cli/commands/dev.js +139 -0
- package/dist/cli/commands/init.d.ts +11 -0
- package/dist/cli/commands/init.js +238 -0
- package/dist/cli/commands/keys.d.ts +12 -0
- package/dist/cli/commands/keys.js +165 -0
- package/dist/cli/commands/start.d.ts +5 -0
- package/dist/cli/commands/start.js +56 -0
- package/dist/cli/commands/upload.d.ts +13 -0
- package/dist/cli/commands/upload.js +238 -0
- package/dist/cli/commands/whoami.d.ts +8 -0
- package/dist/cli/commands/whoami.js +91 -0
- package/dist/cli/index.d.ts +1 -0
- package/dist/cli/index.js +106 -0
- package/dist/config/index.d.ts +80 -0
- package/dist/config/index.js +133 -0
- package/dist/constants.d.ts +9 -0
- package/dist/constants.js +13 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +12 -0
- package/dist/utils/logger.d.ts +16 -0
- package/dist/utils/logger.js +61 -0
- package/dist/utils/paths.d.ts +16 -0
- package/dist/utils/paths.js +50 -0
- package/package.json +51 -0
- package/renderer/app/api/assets/[...path]/route.ts +123 -0
- package/renderer/app/api/assets/route.ts +124 -0
- package/renderer/app/api/assets/upload/route.ts +177 -0
- package/renderer/app/api/auth-schemes/route.ts +77 -0
- package/renderer/app/api/chat/route.ts +858 -0
- package/renderer/app/api/codegen/route.ts +72 -0
- package/renderer/app/api/collections/route.ts +1016 -0
- package/renderer/app/api/debug/route.ts +53 -0
- package/renderer/app/api/deploy/route.ts +234 -0
- package/renderer/app/api/device/route.ts +42 -0
- package/renderer/app/api/docs/route.ts +187 -0
- package/renderer/app/api/keys/regenerate/route.ts +80 -0
- package/renderer/app/api/openapi-spec/route.ts +151 -0
- package/renderer/app/api/projects/[slug]/route.ts +153 -0
- package/renderer/app/api/projects/[slug]/stats/route.ts +96 -0
- package/renderer/app/api/projects/register/route.ts +152 -0
- package/renderer/app/api/proxy/route.ts +149 -0
- package/renderer/app/api/proxy-stream/route.ts +168 -0
- package/renderer/app/api/redirects/route.ts +47 -0
- package/renderer/app/api/schema/route.ts +65 -0
- package/renderer/app/api/subdomains/check/route.ts +172 -0
- package/renderer/app/api/suggestions/route.ts +144 -0
- package/renderer/app/favicon.ico +0 -0
- package/renderer/app/globals.css +1103 -0
- package/renderer/app/layout.tsx +47 -0
- package/renderer/app/llms-full.txt/route.ts +346 -0
- package/renderer/app/llms.txt/route.ts +279 -0
- package/renderer/app/page.tsx +14 -0
- package/renderer/app/robots.txt/route.ts +84 -0
- package/renderer/app/sitemap.xml/route.ts +199 -0
- package/renderer/components/docs/index.ts +12 -0
- package/renderer/components/docs/mdx/accordion.tsx +169 -0
- package/renderer/components/docs/mdx/badge.tsx +132 -0
- package/renderer/components/docs/mdx/callouts.tsx +154 -0
- package/renderer/components/docs/mdx/cards.tsx +213 -0
- package/renderer/components/docs/mdx/changelog.tsx +120 -0
- package/renderer/components/docs/mdx/code-block.tsx +186 -0
- package/renderer/components/docs/mdx/code-group.tsx +421 -0
- package/renderer/components/docs/mdx/file-embeds.tsx +105 -0
- package/renderer/components/docs/mdx/frame.tsx +112 -0
- package/renderer/components/docs/mdx/highlight.tsx +151 -0
- package/renderer/components/docs/mdx/iframe.tsx +134 -0
- package/renderer/components/docs/mdx/image.tsx +235 -0
- package/renderer/components/docs/mdx/index.ts +204 -0
- package/renderer/components/docs/mdx/mermaid.tsx +240 -0
- package/renderer/components/docs/mdx/param-field.tsx +200 -0
- package/renderer/components/docs/mdx/steps.tsx +113 -0
- package/renderer/components/docs/mdx/tabs.tsx +86 -0
- package/renderer/components/docs/mdx-renderer.tsx +100 -0
- package/renderer/components/docs/navigation/breadcrumbs.tsx +76 -0
- package/renderer/components/docs/navigation/index.ts +8 -0
- package/renderer/components/docs/navigation/page-nav.tsx +64 -0
- package/renderer/components/docs/navigation/sidebar.tsx +515 -0
- package/renderer/components/docs/navigation/toc.tsx +113 -0
- package/renderer/components/docs/notice.tsx +105 -0
- package/renderer/components/docs-header.tsx +274 -0
- package/renderer/components/docs-viewer/agent/agent-chat.tsx +2076 -0
- package/renderer/components/docs-viewer/agent/cards/debug-context-card.tsx +90 -0
- package/renderer/components/docs-viewer/agent/cards/endpoint-context-card.tsx +49 -0
- package/renderer/components/docs-viewer/agent/cards/index.tsx +50 -0
- package/renderer/components/docs-viewer/agent/cards/response-options-card.tsx +212 -0
- package/renderer/components/docs-viewer/agent/cards/types.ts +84 -0
- package/renderer/components/docs-viewer/agent/chat-message.tsx +17 -0
- package/renderer/components/docs-viewer/agent/index.tsx +6 -0
- package/renderer/components/docs-viewer/agent/messages/assistant-message.tsx +119 -0
- package/renderer/components/docs-viewer/agent/messages/chat-message.tsx +46 -0
- package/renderer/components/docs-viewer/agent/messages/index.ts +17 -0
- package/renderer/components/docs-viewer/agent/messages/tool-call-display.tsx +721 -0
- package/renderer/components/docs-viewer/agent/messages/types.ts +61 -0
- package/renderer/components/docs-viewer/agent/messages/typing-indicator.tsx +24 -0
- package/renderer/components/docs-viewer/agent/messages/user-message.tsx +51 -0
- package/renderer/components/docs-viewer/code-editor/index.tsx +2 -0
- package/renderer/components/docs-viewer/code-editor/notes-mode.tsx +1283 -0
- package/renderer/components/docs-viewer/content/changelog-page.tsx +331 -0
- package/renderer/components/docs-viewer/content/doc-page.tsx +285 -0
- package/renderer/components/docs-viewer/content/documentation-viewer.tsx +17 -0
- package/renderer/components/docs-viewer/content/index.tsx +29 -0
- package/renderer/components/docs-viewer/content/introduction.tsx +21 -0
- package/renderer/components/docs-viewer/content/request-details.tsx +330 -0
- package/renderer/components/docs-viewer/content/sections/auth.tsx +69 -0
- package/renderer/components/docs-viewer/content/sections/body.tsx +66 -0
- package/renderer/components/docs-viewer/content/sections/headers.tsx +43 -0
- package/renderer/components/docs-viewer/content/sections/overview.tsx +40 -0
- package/renderer/components/docs-viewer/content/sections/parameters.tsx +43 -0
- package/renderer/components/docs-viewer/content/sections/responses.tsx +87 -0
- package/renderer/components/docs-viewer/global-auth-modal.tsx +352 -0
- package/renderer/components/docs-viewer/index.tsx +1466 -0
- package/renderer/components/docs-viewer/playground/auth-editor.tsx +280 -0
- package/renderer/components/docs-viewer/playground/body-editor.tsx +221 -0
- package/renderer/components/docs-viewer/playground/code-editor.tsx +224 -0
- package/renderer/components/docs-viewer/playground/code-snippet.tsx +387 -0
- package/renderer/components/docs-viewer/playground/graphql-playground.tsx +745 -0
- package/renderer/components/docs-viewer/playground/index.tsx +671 -0
- package/renderer/components/docs-viewer/playground/key-value-editor.tsx +261 -0
- package/renderer/components/docs-viewer/playground/method-selector.tsx +60 -0
- package/renderer/components/docs-viewer/playground/request-builder.tsx +179 -0
- package/renderer/components/docs-viewer/playground/request-tabs.tsx +237 -0
- package/renderer/components/docs-viewer/playground/response-cards/idle-card.tsx +21 -0
- package/renderer/components/docs-viewer/playground/response-cards/index.tsx +93 -0
- package/renderer/components/docs-viewer/playground/response-cards/loading-card.tsx +16 -0
- package/renderer/components/docs-viewer/playground/response-cards/network-error-card.tsx +23 -0
- package/renderer/components/docs-viewer/playground/response-cards/response-body-card.tsx +268 -0
- package/renderer/components/docs-viewer/playground/response-cards/types.ts +82 -0
- package/renderer/components/docs-viewer/playground/response-viewer.tsx +43 -0
- package/renderer/components/docs-viewer/search/index.ts +2 -0
- package/renderer/components/docs-viewer/search/search-dialog.tsx +331 -0
- package/renderer/components/docs-viewer/search/use-search.ts +117 -0
- package/renderer/components/docs-viewer/shared/markdown-renderer.tsx +431 -0
- package/renderer/components/docs-viewer/shared/method-badge.tsx +41 -0
- package/renderer/components/docs-viewer/shared/schema-viewer.tsx +349 -0
- package/renderer/components/docs-viewer/sidebar/collection-tree.tsx +239 -0
- package/renderer/components/docs-viewer/sidebar/endpoint-options.tsx +316 -0
- package/renderer/components/docs-viewer/sidebar/index.tsx +343 -0
- package/renderer/components/docs-viewer/sidebar/right-sidebar.tsx +202 -0
- package/renderer/components/docs-viewer/sidebar/sidebar-group.tsx +118 -0
- package/renderer/components/docs-viewer/sidebar/sidebar-item.tsx +226 -0
- package/renderer/components/docs-viewer/sidebar/sidebar-section.tsx +52 -0
- package/renderer/components/theme-provider.tsx +11 -0
- package/renderer/components/theme-toggle.tsx +76 -0
- package/renderer/components/ui/badge.tsx +46 -0
- package/renderer/components/ui/button.tsx +59 -0
- package/renderer/components/ui/dialog.tsx +118 -0
- package/renderer/components/ui/dropdown-menu.tsx +257 -0
- package/renderer/components/ui/input.tsx +21 -0
- package/renderer/components/ui/label.tsx +24 -0
- package/renderer/components/ui/navigation-menu.tsx +168 -0
- package/renderer/components/ui/select.tsx +190 -0
- package/renderer/components/ui/spinner.tsx +114 -0
- package/renderer/components/ui/tabs.tsx +66 -0
- package/renderer/components/ui/tooltip.tsx +61 -0
- package/renderer/hooks/use-code-copy.ts +88 -0
- package/renderer/hooks/use-openapi-title.ts +44 -0
- package/renderer/lib/api-docs/agent/index.ts +6 -0
- package/renderer/lib/api-docs/agent/indexer.ts +323 -0
- package/renderer/lib/api-docs/agent/spec-summary.ts +335 -0
- package/renderer/lib/api-docs/agent/types.ts +116 -0
- package/renderer/lib/api-docs/auth/auth-context.tsx +225 -0
- package/renderer/lib/api-docs/auth/auth-storage.ts +87 -0
- package/renderer/lib/api-docs/auth/crypto.ts +89 -0
- package/renderer/lib/api-docs/auth/index.ts +4 -0
- package/renderer/lib/api-docs/code-editor/db.ts +164 -0
- package/renderer/lib/api-docs/code-editor/hooks.ts +266 -0
- package/renderer/lib/api-docs/code-editor/index.ts +6 -0
- package/renderer/lib/api-docs/code-editor/mode-context.tsx +207 -0
- package/renderer/lib/api-docs/code-editor/types.ts +105 -0
- package/renderer/lib/api-docs/codegen/definitions.ts +297 -0
- package/renderer/lib/api-docs/codegen/har.ts +251 -0
- package/renderer/lib/api-docs/codegen/index.ts +159 -0
- package/renderer/lib/api-docs/factories.ts +151 -0
- package/renderer/lib/api-docs/index.ts +17 -0
- package/renderer/lib/api-docs/mobile-context.tsx +112 -0
- package/renderer/lib/api-docs/navigation-context.tsx +88 -0
- package/renderer/lib/api-docs/parsers/graphql/README.md +129 -0
- package/renderer/lib/api-docs/parsers/graphql/index.ts +91 -0
- package/renderer/lib/api-docs/parsers/graphql/parser.ts +491 -0
- package/renderer/lib/api-docs/parsers/graphql/transformer.ts +246 -0
- package/renderer/lib/api-docs/parsers/graphql/types.ts +283 -0
- package/renderer/lib/api-docs/parsers/openapi/README.md +32 -0
- package/renderer/lib/api-docs/parsers/openapi/dereferencer.ts +60 -0
- package/renderer/lib/api-docs/parsers/openapi/extractors/auth.ts +574 -0
- package/renderer/lib/api-docs/parsers/openapi/extractors/body.ts +403 -0
- package/renderer/lib/api-docs/parsers/openapi/extractors/index.ts +232 -0
- package/renderer/lib/api-docs/parsers/openapi/index.ts +171 -0
- package/renderer/lib/api-docs/parsers/openapi/transformer.ts +277 -0
- package/renderer/lib/api-docs/parsers/openapi/validator.ts +31 -0
- package/renderer/lib/api-docs/playground/context.tsx +107 -0
- package/renderer/lib/api-docs/playground/navigation-context.tsx +124 -0
- package/renderer/lib/api-docs/playground/request-builder.ts +223 -0
- package/renderer/lib/api-docs/playground/request-runner.ts +282 -0
- package/renderer/lib/api-docs/playground/types.ts +35 -0
- package/renderer/lib/api-docs/types.ts +269 -0
- package/renderer/lib/api-docs/utils.ts +311 -0
- package/renderer/lib/cache.ts +193 -0
- package/renderer/lib/docs/config/index.ts +29 -0
- package/renderer/lib/docs/config/loader.ts +142 -0
- package/renderer/lib/docs/config/schema.ts +298 -0
- package/renderer/lib/docs/index.ts +12 -0
- package/renderer/lib/docs/mdx/compiler.ts +176 -0
- package/renderer/lib/docs/mdx/frontmatter.ts +80 -0
- package/renderer/lib/docs/mdx/index.ts +26 -0
- package/renderer/lib/docs/navigation/generator.ts +348 -0
- package/renderer/lib/docs/navigation/index.ts +12 -0
- package/renderer/lib/docs/navigation/types.ts +123 -0
- package/renderer/lib/docs-navigation-context.tsx +80 -0
- package/renderer/lib/multi-tenant/context.ts +105 -0
- package/renderer/lib/storage/blob.ts +845 -0
- package/renderer/lib/utils.ts +6 -0
- package/renderer/next.config.ts +76 -0
- package/renderer/package.json +66 -0
- package/renderer/postcss.config.mjs +5 -0
- package/renderer/public/assets/images/screenshot.png +0 -0
- package/renderer/public/assets/logo/dark.svg +9 -0
- package/renderer/public/assets/logo/light.svg +9 -0
- package/renderer/public/assets/logo.svg +9 -0
- package/renderer/public/file.svg +1 -0
- package/renderer/public/globe.svg +1 -0
- package/renderer/public/icon.png +0 -0
- package/renderer/public/logo.svg +9 -0
- package/renderer/public/window.svg +1 -0
- package/renderer/tsconfig.json +28 -0
- package/templates/basic/README.md +139 -0
- package/templates/basic/assets/favicon.svg +4 -0
- package/templates/basic/assets/logo.svg +9 -0
- package/templates/basic/docs.json +47 -0
- package/templates/basic/guides/configuration.mdx +149 -0
- package/templates/basic/guides/overview.mdx +96 -0
- package/templates/basic/index.mdx +39 -0
- package/templates/basic/package.json +14 -0
- package/templates/basic/quickstart.mdx +92 -0
- package/templates/basic/vercel.json +6 -0
- package/templates/graphql/README.md +139 -0
- package/templates/graphql/api-reference/schema.graphql +305 -0
- package/templates/graphql/assets/favicon.svg +4 -0
- package/templates/graphql/assets/logo.svg +9 -0
- package/templates/graphql/docs.json +54 -0
- package/templates/graphql/guides/configuration.mdx +149 -0
- package/templates/graphql/guides/overview.mdx +96 -0
- package/templates/graphql/index.mdx +39 -0
- package/templates/graphql/package.json +14 -0
- package/templates/graphql/quickstart.mdx +92 -0
- package/templates/graphql/vercel.json +6 -0
- package/templates/openapi/README.md +139 -0
- package/templates/openapi/api-reference/openapi.json +419 -0
- package/templates/openapi/assets/favicon.svg +4 -0
- package/templates/openapi/assets/logo.svg +9 -0
- package/templates/openapi/docs.json +61 -0
- package/templates/openapi/guides/configuration.mdx +149 -0
- package/templates/openapi/guides/overview.mdx +96 -0
- package/templates/openapi/index.mdx +39 -0
- package/templates/openapi/package.json +14 -0
- package/templates/openapi/quickstart.mdx +92 -0
- package/templates/openapi/vercel.json +6 -0
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import { useState } from 'react'
|
|
4
|
+
import { CaretDown, CaretRight, Play } from '@phosphor-icons/react'
|
|
5
|
+
import { MethodBadge } from '../shared/method-badge'
|
|
6
|
+
import { MarkdownRenderer } from '../shared/markdown-renderer'
|
|
7
|
+
import { Badge } from '@/components/ui/badge'
|
|
8
|
+
import { Button } from '@/components/ui/button'
|
|
9
|
+
import { CodeViewer } from '../playground/code-editor'
|
|
10
|
+
import { ResponseSchema } from '../shared/schema-viewer'
|
|
11
|
+
import { CodeSnippetCompact } from '../playground/code-snippet'
|
|
12
|
+
import { useModeContext } from '@/lib/api-docs/code-editor'
|
|
13
|
+
import type { BrainfishRESTRequest } from '@/lib/api-docs/types'
|
|
14
|
+
|
|
15
|
+
interface RequestDetailsProps {
|
|
16
|
+
request: BrainfishRESTRequest
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Collapsible section component
|
|
20
|
+
function CollapsibleSection({
|
|
21
|
+
title,
|
|
22
|
+
children,
|
|
23
|
+
defaultOpen = true
|
|
24
|
+
}: {
|
|
25
|
+
title: string
|
|
26
|
+
children: React.ReactNode
|
|
27
|
+
defaultOpen?: boolean
|
|
28
|
+
}) {
|
|
29
|
+
const [isOpen, setIsOpen] = useState(defaultOpen)
|
|
30
|
+
|
|
31
|
+
return (
|
|
32
|
+
<div className="docs-api-section border-b border-border">
|
|
33
|
+
<button
|
|
34
|
+
onClick={() => setIsOpen(!isOpen)}
|
|
35
|
+
className="docs-api-section-header w-full flex items-center justify-between p-4 hover:bg-muted/50 transition-colors"
|
|
36
|
+
>
|
|
37
|
+
<span className="font-semibold text-sm">{title}</span>
|
|
38
|
+
{isOpen ? (
|
|
39
|
+
<CaretDown className="h-4 w-4 text-muted-foreground" weight="bold" />
|
|
40
|
+
) : (
|
|
41
|
+
<CaretRight className="h-4 w-4 text-muted-foreground" weight="bold" />
|
|
42
|
+
)}
|
|
43
|
+
</button>
|
|
44
|
+
{isOpen && <div className="docs-api-section-content px-4 pb-4">{children}</div>}
|
|
45
|
+
</div>
|
|
46
|
+
)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function RequestDetails({ request }: RequestDetailsProps) {
|
|
50
|
+
const { switchToApiClient } = useModeContext()
|
|
51
|
+
|
|
52
|
+
return (
|
|
53
|
+
<div className="docs-api-endpoint h-full overflow-y-auto bg-background">
|
|
54
|
+
{/* Endpoint Header */}
|
|
55
|
+
<div className="docs-api-endpoint-header p-4 border-b border-border">
|
|
56
|
+
<div className="flex items-center justify-between gap-2 mb-2">
|
|
57
|
+
<div className="flex items-center gap-2 min-w-0">
|
|
58
|
+
<MethodBadge method={request.method} />
|
|
59
|
+
<h2 className="docs-api-endpoint-name font-semibold text-lg truncate">{request.name}</h2>
|
|
60
|
+
</div>
|
|
61
|
+
<Button
|
|
62
|
+
size="sm"
|
|
63
|
+
onClick={() => switchToApiClient()}
|
|
64
|
+
className="docs-button docs-button-try-it shrink-0"
|
|
65
|
+
>
|
|
66
|
+
<Play className="h-3.5 w-3.5 mr-1.5" weight="fill" />
|
|
67
|
+
Try it out
|
|
68
|
+
</Button>
|
|
69
|
+
</div>
|
|
70
|
+
<code className="docs-api-path text-xs text-muted-foreground font-mono break-all">
|
|
71
|
+
{request.endpoint}
|
|
72
|
+
</code>
|
|
73
|
+
</div>
|
|
74
|
+
|
|
75
|
+
{/* Code Snippet */}
|
|
76
|
+
<CodeSnippetCompact request={request} />
|
|
77
|
+
|
|
78
|
+
{/* Description - only show if there's actual content */}
|
|
79
|
+
{request.description?.trim() && (
|
|
80
|
+
<CollapsibleSection title="Description" defaultOpen={true}>
|
|
81
|
+
<div className="text-sm text-muted-foreground">
|
|
82
|
+
<MarkdownRenderer content={request.description} />
|
|
83
|
+
</div>
|
|
84
|
+
</CollapsibleSection>
|
|
85
|
+
)}
|
|
86
|
+
|
|
87
|
+
{/* Parameters */}
|
|
88
|
+
{request.params.length > 0 && (
|
|
89
|
+
<CollapsibleSection title="Parameters" defaultOpen={false}>
|
|
90
|
+
<div className="border rounded-sm overflow-x-auto">
|
|
91
|
+
<table className="w-full text-sm min-w-[400px]">
|
|
92
|
+
<thead className="bg-muted/50">
|
|
93
|
+
<tr>
|
|
94
|
+
<th className="px-3 py-2 text-left text-xs font-semibold whitespace-nowrap">Name</th>
|
|
95
|
+
<th className="px-3 py-2 text-left text-xs font-semibold whitespace-nowrap">Description</th>
|
|
96
|
+
<th className="px-3 py-2 text-left text-xs font-semibold whitespace-nowrap">Required</th>
|
|
97
|
+
</tr>
|
|
98
|
+
</thead>
|
|
99
|
+
<tbody>
|
|
100
|
+
{request.params.map((param) => (
|
|
101
|
+
<tr key={param.key} className="border-t">
|
|
102
|
+
<td className="px-3 py-2 font-mono text-xs whitespace-nowrap">{param.key}</td>
|
|
103
|
+
<td className="px-3 py-2 text-xs text-muted-foreground">
|
|
104
|
+
{param.description || '-'}
|
|
105
|
+
</td>
|
|
106
|
+
<td className="px-3 py-2 text-xs whitespace-nowrap">
|
|
107
|
+
{param.active ? (
|
|
108
|
+
<Badge variant="default" className="text-xs">Required</Badge>
|
|
109
|
+
) : (
|
|
110
|
+
<span className="text-muted-foreground">Optional</span>
|
|
111
|
+
)}
|
|
112
|
+
</td>
|
|
113
|
+
</tr>
|
|
114
|
+
))}
|
|
115
|
+
</tbody>
|
|
116
|
+
</table>
|
|
117
|
+
</div>
|
|
118
|
+
</CollapsibleSection>
|
|
119
|
+
)}
|
|
120
|
+
|
|
121
|
+
{/* Headers */}
|
|
122
|
+
{request.headers.length > 0 && (
|
|
123
|
+
<CollapsibleSection title="Headers" defaultOpen={false}>
|
|
124
|
+
<div className="border rounded-sm overflow-x-auto">
|
|
125
|
+
<table className="w-full text-sm min-w-[400px]">
|
|
126
|
+
<thead className="bg-muted/50">
|
|
127
|
+
<tr>
|
|
128
|
+
<th className="px-3 py-2 text-left text-xs font-semibold whitespace-nowrap">Name</th>
|
|
129
|
+
<th className="px-3 py-2 text-left text-xs font-semibold whitespace-nowrap">Description</th>
|
|
130
|
+
<th className="px-3 py-2 text-left text-xs font-semibold whitespace-nowrap">Required</th>
|
|
131
|
+
</tr>
|
|
132
|
+
</thead>
|
|
133
|
+
<tbody>
|
|
134
|
+
{request.headers.map((header) => (
|
|
135
|
+
<tr key={header.key} className="border-t">
|
|
136
|
+
<td className="px-3 py-2 font-mono text-xs whitespace-nowrap">{header.key}</td>
|
|
137
|
+
<td className="px-3 py-2 text-xs text-muted-foreground">
|
|
138
|
+
{header.description || '-'}
|
|
139
|
+
</td>
|
|
140
|
+
<td className="px-3 py-2 text-xs whitespace-nowrap">
|
|
141
|
+
{header.active ? (
|
|
142
|
+
<Badge variant="default" className="text-xs">Required</Badge>
|
|
143
|
+
) : (
|
|
144
|
+
<span className="text-muted-foreground">Optional</span>
|
|
145
|
+
)}
|
|
146
|
+
</td>
|
|
147
|
+
</tr>
|
|
148
|
+
))}
|
|
149
|
+
</tbody>
|
|
150
|
+
</table>
|
|
151
|
+
</div>
|
|
152
|
+
</CollapsibleSection>
|
|
153
|
+
)}
|
|
154
|
+
|
|
155
|
+
{/* Authentication */}
|
|
156
|
+
{request.auth.authType !== 'none' && (
|
|
157
|
+
<CollapsibleSection title="Authentication" defaultOpen={false}>
|
|
158
|
+
<div className="border rounded-sm overflow-hidden">
|
|
159
|
+
{request.auth.authType === 'basic' && (
|
|
160
|
+
<>
|
|
161
|
+
<div className="px-3 py-2 border-b bg-muted/30">
|
|
162
|
+
<div className="flex items-center gap-2">
|
|
163
|
+
<span className="font-semibold text-sm">Basic Auth</span>
|
|
164
|
+
<span className="text-xs text-orange-500 font-medium">required</span>
|
|
165
|
+
</div>
|
|
166
|
+
</div>
|
|
167
|
+
<div className="p-3 space-y-2">
|
|
168
|
+
<div className="flex items-center justify-between py-2 border-b border-border/50">
|
|
169
|
+
<span className="text-sm font-medium">username</span>
|
|
170
|
+
<span className="text-xs text-muted-foreground">string</span>
|
|
171
|
+
</div>
|
|
172
|
+
<div className="flex items-center justify-between py-2">
|
|
173
|
+
<span className="text-sm font-medium">password</span>
|
|
174
|
+
<span className="text-xs text-muted-foreground">string</span>
|
|
175
|
+
</div>
|
|
176
|
+
</div>
|
|
177
|
+
</>
|
|
178
|
+
)}
|
|
179
|
+
|
|
180
|
+
{request.auth.authType === 'bearer' && (
|
|
181
|
+
<>
|
|
182
|
+
<div className="px-3 py-2 border-b bg-muted/30">
|
|
183
|
+
<div className="flex items-center gap-2">
|
|
184
|
+
<span className="font-semibold text-sm">Bearer Token</span>
|
|
185
|
+
<span className="text-xs text-orange-500 font-medium">required</span>
|
|
186
|
+
</div>
|
|
187
|
+
</div>
|
|
188
|
+
<div className="p-3">
|
|
189
|
+
<div className="flex items-center justify-between py-2">
|
|
190
|
+
<span className="text-sm font-medium">Authorization</span>
|
|
191
|
+
<span className="text-xs text-muted-foreground font-mono">Bearer <token></span>
|
|
192
|
+
</div>
|
|
193
|
+
<p className="text-xs text-muted-foreground mt-1">
|
|
194
|
+
Pass the token in the Authorization header
|
|
195
|
+
</p>
|
|
196
|
+
</div>
|
|
197
|
+
</>
|
|
198
|
+
)}
|
|
199
|
+
|
|
200
|
+
{request.auth.authType === 'api-key' && (
|
|
201
|
+
<>
|
|
202
|
+
<div className="px-3 py-2 border-b bg-muted/30">
|
|
203
|
+
<div className="flex items-center gap-2">
|
|
204
|
+
<span className="font-semibold text-sm">API Key</span>
|
|
205
|
+
<span className="text-xs text-orange-500 font-medium">required</span>
|
|
206
|
+
</div>
|
|
207
|
+
</div>
|
|
208
|
+
<div className="p-3 space-y-3">
|
|
209
|
+
<div className="border-b border-border/50 pb-3">
|
|
210
|
+
<div className="flex items-start gap-2 flex-wrap">
|
|
211
|
+
<span className="font-semibold text-sm">{request.auth.key}</span>
|
|
212
|
+
<span className="text-xs text-muted-foreground">string</span>
|
|
213
|
+
<span className="text-xs text-orange-500 font-medium">required</span>
|
|
214
|
+
</div>
|
|
215
|
+
<p className="text-xs text-muted-foreground mt-1">
|
|
216
|
+
Your API key for authentication
|
|
217
|
+
</p>
|
|
218
|
+
</div>
|
|
219
|
+
<div className="flex items-center gap-2 text-xs">
|
|
220
|
+
<span className="text-muted-foreground">Location:</span>
|
|
221
|
+
<code className="bg-muted px-2 py-0.5 rounded font-mono">
|
|
222
|
+
{request.auth.addTo === 'HEADERS' ? 'Header' : 'Query'}
|
|
223
|
+
</code>
|
|
224
|
+
</div>
|
|
225
|
+
</div>
|
|
226
|
+
</>
|
|
227
|
+
)}
|
|
228
|
+
|
|
229
|
+
{request.auth.authType === 'oauth-2' && (
|
|
230
|
+
<>
|
|
231
|
+
<div className="px-3 py-2 border-b bg-muted/30">
|
|
232
|
+
<div className="flex items-center gap-2">
|
|
233
|
+
<span className="font-semibold text-sm">OAuth 2.0</span>
|
|
234
|
+
<span className="text-xs text-orange-500 font-medium">required</span>
|
|
235
|
+
</div>
|
|
236
|
+
</div>
|
|
237
|
+
<div className="p-3 space-y-3">
|
|
238
|
+
<div className="border-b border-border/50 pb-3">
|
|
239
|
+
<div className="flex items-start gap-2 flex-wrap">
|
|
240
|
+
<span className="font-semibold text-sm">Grant Type</span>
|
|
241
|
+
<span className="text-xs text-muted-foreground">
|
|
242
|
+
{request.auth.grantTypeInfo.grantType.replace('_', ' ')}
|
|
243
|
+
</span>
|
|
244
|
+
</div>
|
|
245
|
+
</div>
|
|
246
|
+
{request.auth.grantTypeInfo.authEndpoint && (
|
|
247
|
+
<div className="border-b border-border/50 pb-3">
|
|
248
|
+
<div className="flex items-start gap-2 flex-wrap">
|
|
249
|
+
<span className="font-semibold text-sm">authEndpoint</span>
|
|
250
|
+
<span className="text-xs text-muted-foreground">string</span>
|
|
251
|
+
</div>
|
|
252
|
+
<code className="text-xs text-muted-foreground mt-1 block break-all">
|
|
253
|
+
{request.auth.grantTypeInfo.authEndpoint}
|
|
254
|
+
</code>
|
|
255
|
+
</div>
|
|
256
|
+
)}
|
|
257
|
+
{request.auth.grantTypeInfo.tokenEndpoint && (
|
|
258
|
+
<div className="pb-1">
|
|
259
|
+
<div className="flex items-start gap-2 flex-wrap">
|
|
260
|
+
<span className="font-semibold text-sm">tokenEndpoint</span>
|
|
261
|
+
<span className="text-xs text-muted-foreground">string</span>
|
|
262
|
+
</div>
|
|
263
|
+
<code className="text-xs text-muted-foreground mt-1 block break-all">
|
|
264
|
+
{request.auth.grantTypeInfo.tokenEndpoint}
|
|
265
|
+
</code>
|
|
266
|
+
</div>
|
|
267
|
+
)}
|
|
268
|
+
</div>
|
|
269
|
+
</>
|
|
270
|
+
)}
|
|
271
|
+
</div>
|
|
272
|
+
</CollapsibleSection>
|
|
273
|
+
)}
|
|
274
|
+
|
|
275
|
+
{/* Body */}
|
|
276
|
+
{request.body.body !== null && (
|
|
277
|
+
<CollapsibleSection title="Request Body" defaultOpen={false}>
|
|
278
|
+
<div className="border rounded-sm overflow-hidden">
|
|
279
|
+
<div className="bg-muted/50 px-3 py-2 border-b">
|
|
280
|
+
<span className="text-xs font-medium">Content-Type: </span>
|
|
281
|
+
<code className="text-xs">{request.body.contentType}</code>
|
|
282
|
+
</div>
|
|
283
|
+
{Array.isArray(request.body.body) ? (
|
|
284
|
+
<div className="p-3 space-y-1">
|
|
285
|
+
{request.body.body.map((item, index) => (
|
|
286
|
+
<div key={index} className="flex items-center gap-2 text-xs">
|
|
287
|
+
<code className="bg-background px-2 py-1 rounded">{item.key}</code>
|
|
288
|
+
<span className="text-muted-foreground">
|
|
289
|
+
{item.isFile ? '(file)' : '(text)'}
|
|
290
|
+
</span>
|
|
291
|
+
</div>
|
|
292
|
+
))}
|
|
293
|
+
</div>
|
|
294
|
+
) : (
|
|
295
|
+
<div className="dark-editor">
|
|
296
|
+
<CodeViewer
|
|
297
|
+
value={typeof request.body.body === 'string' ? request.body.body : JSON.stringify(request.body.body)}
|
|
298
|
+
language={request.body.contentType?.includes('json') ? 'json' : request.body.contentType?.includes('xml') ? 'xml' : 'plaintext'}
|
|
299
|
+
theme="dark"
|
|
300
|
+
height="auto"
|
|
301
|
+
minHeight={80}
|
|
302
|
+
maxHeight={250}
|
|
303
|
+
showBorder={false}
|
|
304
|
+
rounded={false}
|
|
305
|
+
/>
|
|
306
|
+
</div>
|
|
307
|
+
)}
|
|
308
|
+
</div>
|
|
309
|
+
</CollapsibleSection>
|
|
310
|
+
)}
|
|
311
|
+
|
|
312
|
+
{/* Responses */}
|
|
313
|
+
{Object.keys(request.responses).length > 0 && (
|
|
314
|
+
<CollapsibleSection title="Responses" defaultOpen={true}>
|
|
315
|
+
<div>
|
|
316
|
+
{Object.entries(request.responses).map(([name, response]) => (
|
|
317
|
+
<ResponseSchema
|
|
318
|
+
key={name}
|
|
319
|
+
code={response.code}
|
|
320
|
+
status={response.status}
|
|
321
|
+
description={name !== response.status ? name : undefined}
|
|
322
|
+
schema={response.body}
|
|
323
|
+
/>
|
|
324
|
+
))}
|
|
325
|
+
</div>
|
|
326
|
+
</CollapsibleSection>
|
|
327
|
+
)}
|
|
328
|
+
</div>
|
|
329
|
+
)
|
|
330
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import type { BrainfishRESTAuth } from '@/lib/api-docs/types'
|
|
4
|
+
|
|
5
|
+
interface AuthSectionProps {
|
|
6
|
+
auth: BrainfishRESTAuth
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function AuthSection({ auth }: AuthSectionProps) {
|
|
10
|
+
if (auth.authType === 'none' || auth.authType === 'inherit') {
|
|
11
|
+
return null
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return (
|
|
15
|
+
<section>
|
|
16
|
+
<h2 className="text-2xl font-semibold mb-4">Authentication</h2>
|
|
17
|
+
<div className="bg-muted/50 rounded-sm p-6">
|
|
18
|
+
{auth.authType === 'basic' && (
|
|
19
|
+
<div className="space-y-2">
|
|
20
|
+
<p className="text-sm font-medium">Type: Basic Authentication</p>
|
|
21
|
+
<p className="text-sm text-muted-foreground">
|
|
22
|
+
Username and password required
|
|
23
|
+
</p>
|
|
24
|
+
</div>
|
|
25
|
+
)}
|
|
26
|
+
|
|
27
|
+
{auth.authType === 'bearer' && (
|
|
28
|
+
<div className="space-y-2">
|
|
29
|
+
<p className="text-sm font-medium">Type: Bearer Token</p>
|
|
30
|
+
<p className="text-sm text-muted-foreground">
|
|
31
|
+
Token required in Authorization header
|
|
32
|
+
</p>
|
|
33
|
+
</div>
|
|
34
|
+
)}
|
|
35
|
+
|
|
36
|
+
{auth.authType === 'api-key' && (
|
|
37
|
+
<div className="space-y-2">
|
|
38
|
+
<p className="text-sm font-medium">Type: API Key</p>
|
|
39
|
+
<p className="text-sm text-muted-foreground">
|
|
40
|
+
Key: <code className="bg-background px-2 py-1 rounded">{auth.key}</code>
|
|
41
|
+
</p>
|
|
42
|
+
<p className="text-sm text-muted-foreground">
|
|
43
|
+
Location: {auth.addTo === 'HEADERS' ? 'Header' : 'Query Parameter'}
|
|
44
|
+
</p>
|
|
45
|
+
</div>
|
|
46
|
+
)}
|
|
47
|
+
|
|
48
|
+
{auth.authType === 'oauth-2' && (
|
|
49
|
+
<div className="space-y-2">
|
|
50
|
+
<p className="text-sm font-medium">Type: OAuth 2.0</p>
|
|
51
|
+
<p className="text-sm text-muted-foreground">
|
|
52
|
+
Grant Type: {auth.grantTypeInfo.grantType.replace('_', ' ')}
|
|
53
|
+
</p>
|
|
54
|
+
{auth.grantTypeInfo.authEndpoint && (
|
|
55
|
+
<p className="text-sm text-muted-foreground">
|
|
56
|
+
Auth Endpoint: <code className="bg-background px-2 py-1 rounded">{auth.grantTypeInfo.authEndpoint}</code>
|
|
57
|
+
</p>
|
|
58
|
+
)}
|
|
59
|
+
{auth.grantTypeInfo.tokenEndpoint && (
|
|
60
|
+
<p className="text-sm text-muted-foreground">
|
|
61
|
+
Token Endpoint: <code className="bg-background px-2 py-1 rounded">{auth.grantTypeInfo.tokenEndpoint}</code>
|
|
62
|
+
</p>
|
|
63
|
+
)}
|
|
64
|
+
</div>
|
|
65
|
+
)}
|
|
66
|
+
</div>
|
|
67
|
+
</section>
|
|
68
|
+
)
|
|
69
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import type { BrainfishRESTReqBody, FormDataKeyValue } from '@/lib/api-docs/types'
|
|
4
|
+
|
|
5
|
+
interface BodySectionProps {
|
|
6
|
+
body: BrainfishRESTReqBody
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function BodySection({ body }: BodySectionProps) {
|
|
10
|
+
if (!body.body || body.contentType === null) {
|
|
11
|
+
return null
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const isFormData = Array.isArray(body.body)
|
|
15
|
+
const isFormUrlEncoded = body.contentType === 'application/x-www-form-urlencoded'
|
|
16
|
+
|
|
17
|
+
let bodyContent: string
|
|
18
|
+
let formItems: FormDataKeyValue[] = []
|
|
19
|
+
|
|
20
|
+
if (isFormData) {
|
|
21
|
+
formItems = body.body as FormDataKeyValue[]
|
|
22
|
+
bodyContent = JSON.stringify(
|
|
23
|
+
formItems.map((item) => ({ key: item.key, value: item.value, isFile: item.isFile })),
|
|
24
|
+
null,
|
|
25
|
+
2
|
|
26
|
+
)
|
|
27
|
+
} else if (typeof body.body === 'string') {
|
|
28
|
+
bodyContent = body.body
|
|
29
|
+
} else {
|
|
30
|
+
bodyContent = JSON.stringify(body.body, null, 2)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<section>
|
|
35
|
+
<h2 className="text-2xl font-semibold mb-4">Request Body</h2>
|
|
36
|
+
<div className="border rounded-sm overflow-hidden">
|
|
37
|
+
<div className="bg-muted/50 px-4 py-2 border-b">
|
|
38
|
+
<span className="text-sm font-medium">Content-Type: </span>
|
|
39
|
+
<code className="text-sm">{body.contentType}</code>
|
|
40
|
+
</div>
|
|
41
|
+
<div className="p-4">
|
|
42
|
+
{isFormData && formItems.length > 0 ? (
|
|
43
|
+
<div className="space-y-2">
|
|
44
|
+
{formItems.map((item, index) => (
|
|
45
|
+
<div key={index} className="flex items-center gap-2">
|
|
46
|
+
<code className="bg-background px-2 py-1 rounded text-sm">{item.key}</code>
|
|
47
|
+
<span className="text-sm text-muted-foreground">
|
|
48
|
+
{item.isFile ? '(file)' : '(text)'}
|
|
49
|
+
</span>
|
|
50
|
+
</div>
|
|
51
|
+
))}
|
|
52
|
+
</div>
|
|
53
|
+
) : isFormUrlEncoded ? (
|
|
54
|
+
<pre className="bg-muted p-4 rounded overflow-x-auto">
|
|
55
|
+
<code className="text-sm">{bodyContent}</code>
|
|
56
|
+
</pre>
|
|
57
|
+
) : (
|
|
58
|
+
<pre className="bg-muted p-4 rounded overflow-x-auto">
|
|
59
|
+
<code className="text-sm">{bodyContent}</code>
|
|
60
|
+
</pre>
|
|
61
|
+
)}
|
|
62
|
+
</div>
|
|
63
|
+
</div>
|
|
64
|
+
</section>
|
|
65
|
+
)
|
|
66
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import type { BrainfishRESTHeader } from '@/lib/api-docs/types'
|
|
4
|
+
|
|
5
|
+
interface HeadersSectionProps {
|
|
6
|
+
headers: BrainfishRESTHeader[]
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function HeadersSection({ headers }: HeadersSectionProps) {
|
|
10
|
+
return (
|
|
11
|
+
<section>
|
|
12
|
+
<h2 className="text-2xl font-semibold mb-4">Headers</h2>
|
|
13
|
+
<div className="border rounded-sm overflow-hidden">
|
|
14
|
+
<table className="w-full">
|
|
15
|
+
<thead className="bg-muted/50">
|
|
16
|
+
<tr>
|
|
17
|
+
<th className="px-4 py-3 text-left text-sm font-semibold">Name</th>
|
|
18
|
+
<th className="px-4 py-3 text-left text-sm font-semibold">Description</th>
|
|
19
|
+
<th className="px-4 py-3 text-left text-sm font-semibold">Required</th>
|
|
20
|
+
</tr>
|
|
21
|
+
</thead>
|
|
22
|
+
<tbody>
|
|
23
|
+
{headers.map((header) => (
|
|
24
|
+
<tr key={header.key} className="border-t">
|
|
25
|
+
<td className="px-4 py-3 font-mono text-sm">{header.key}</td>
|
|
26
|
+
<td className="px-4 py-3 text-sm text-muted-foreground">
|
|
27
|
+
{header.description || '-'}
|
|
28
|
+
</td>
|
|
29
|
+
<td className="px-4 py-3 text-sm">
|
|
30
|
+
{header.active ? (
|
|
31
|
+
<span className="text-green-600">Required</span>
|
|
32
|
+
) : (
|
|
33
|
+
<span className="text-muted-foreground">Optional</span>
|
|
34
|
+
)}
|
|
35
|
+
</td>
|
|
36
|
+
</tr>
|
|
37
|
+
))}
|
|
38
|
+
</tbody>
|
|
39
|
+
</table>
|
|
40
|
+
</div>
|
|
41
|
+
</section>
|
|
42
|
+
)
|
|
43
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import type { BrainfishRESTRequest } from '@/lib/api-docs/types'
|
|
4
|
+
|
|
5
|
+
interface RequestOverviewProps {
|
|
6
|
+
request: BrainfishRESTRequest
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function RequestOverview({ request }: RequestOverviewProps) {
|
|
10
|
+
return (
|
|
11
|
+
<section>
|
|
12
|
+
<h2 className="text-2xl font-semibold mb-4">Overview</h2>
|
|
13
|
+
<div className="bg-muted/50 rounded-sm p-6 space-y-4">
|
|
14
|
+
<div>
|
|
15
|
+
<span className="text-sm font-medium text-muted-foreground">Method</span>
|
|
16
|
+
<p className="mt-1 font-mono">{request.method}</p>
|
|
17
|
+
</div>
|
|
18
|
+
<div>
|
|
19
|
+
<span className="text-sm font-medium text-muted-foreground">Endpoint</span>
|
|
20
|
+
<p className="mt-1 font-mono break-all">{request.endpoint}</p>
|
|
21
|
+
</div>
|
|
22
|
+
{request.tags && request.tags.length > 0 && (
|
|
23
|
+
<div>
|
|
24
|
+
<span className="text-sm font-medium text-muted-foreground">Tags</span>
|
|
25
|
+
<div className="mt-1 flex flex-wrap gap-2">
|
|
26
|
+
{request.tags.map((tag) => (
|
|
27
|
+
<span
|
|
28
|
+
key={tag}
|
|
29
|
+
className="px-2 py-1 bg-primary/10 text-primary rounded text-sm"
|
|
30
|
+
>
|
|
31
|
+
{tag}
|
|
32
|
+
</span>
|
|
33
|
+
))}
|
|
34
|
+
</div>
|
|
35
|
+
</div>
|
|
36
|
+
)}
|
|
37
|
+
</div>
|
|
38
|
+
</section>
|
|
39
|
+
)
|
|
40
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import type { BrainfishRESTParam } from '@/lib/api-docs/types'
|
|
4
|
+
|
|
5
|
+
interface ParametersSectionProps {
|
|
6
|
+
params: BrainfishRESTParam[]
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function ParametersSection({ params }: ParametersSectionProps) {
|
|
10
|
+
return (
|
|
11
|
+
<section>
|
|
12
|
+
<h2 className="text-2xl font-semibold mb-4">Query Parameters</h2>
|
|
13
|
+
<div className="border rounded-sm overflow-hidden">
|
|
14
|
+
<table className="w-full">
|
|
15
|
+
<thead className="bg-muted/50">
|
|
16
|
+
<tr>
|
|
17
|
+
<th className="px-4 py-3 text-left text-sm font-semibold">Name</th>
|
|
18
|
+
<th className="px-4 py-3 text-left text-sm font-semibold">Description</th>
|
|
19
|
+
<th className="px-4 py-3 text-left text-sm font-semibold">Required</th>
|
|
20
|
+
</tr>
|
|
21
|
+
</thead>
|
|
22
|
+
<tbody>
|
|
23
|
+
{params.map((param) => (
|
|
24
|
+
<tr key={param.key} className="border-t">
|
|
25
|
+
<td className="px-4 py-3 font-mono text-sm">{param.key}</td>
|
|
26
|
+
<td className="px-4 py-3 text-sm text-muted-foreground">
|
|
27
|
+
{param.description || '-'}
|
|
28
|
+
</td>
|
|
29
|
+
<td className="px-4 py-3 text-sm">
|
|
30
|
+
{param.active ? (
|
|
31
|
+
<span className="text-green-600">Required</span>
|
|
32
|
+
) : (
|
|
33
|
+
<span className="text-muted-foreground">Optional</span>
|
|
34
|
+
)}
|
|
35
|
+
</td>
|
|
36
|
+
</tr>
|
|
37
|
+
))}
|
|
38
|
+
</tbody>
|
|
39
|
+
</table>
|
|
40
|
+
</div>
|
|
41
|
+
</section>
|
|
42
|
+
)
|
|
43
|
+
}
|