@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.
Files changed (268) hide show
  1. package/LICENSE +33 -0
  2. package/README.md +415 -0
  3. package/bin/devdoc.js +13 -0
  4. package/dist/cli/commands/build.d.ts +5 -0
  5. package/dist/cli/commands/build.js +87 -0
  6. package/dist/cli/commands/check.d.ts +1 -0
  7. package/dist/cli/commands/check.js +143 -0
  8. package/dist/cli/commands/create.d.ts +24 -0
  9. package/dist/cli/commands/create.js +387 -0
  10. package/dist/cli/commands/deploy.d.ts +9 -0
  11. package/dist/cli/commands/deploy.js +433 -0
  12. package/dist/cli/commands/dev.d.ts +6 -0
  13. package/dist/cli/commands/dev.js +139 -0
  14. package/dist/cli/commands/init.d.ts +11 -0
  15. package/dist/cli/commands/init.js +238 -0
  16. package/dist/cli/commands/keys.d.ts +12 -0
  17. package/dist/cli/commands/keys.js +165 -0
  18. package/dist/cli/commands/start.d.ts +5 -0
  19. package/dist/cli/commands/start.js +56 -0
  20. package/dist/cli/commands/upload.d.ts +13 -0
  21. package/dist/cli/commands/upload.js +238 -0
  22. package/dist/cli/commands/whoami.d.ts +8 -0
  23. package/dist/cli/commands/whoami.js +91 -0
  24. package/dist/cli/index.d.ts +1 -0
  25. package/dist/cli/index.js +106 -0
  26. package/dist/config/index.d.ts +80 -0
  27. package/dist/config/index.js +133 -0
  28. package/dist/constants.d.ts +9 -0
  29. package/dist/constants.js +13 -0
  30. package/dist/index.d.ts +7 -0
  31. package/dist/index.js +12 -0
  32. package/dist/utils/logger.d.ts +16 -0
  33. package/dist/utils/logger.js +61 -0
  34. package/dist/utils/paths.d.ts +16 -0
  35. package/dist/utils/paths.js +50 -0
  36. package/package.json +51 -0
  37. package/renderer/app/api/assets/[...path]/route.ts +123 -0
  38. package/renderer/app/api/assets/route.ts +124 -0
  39. package/renderer/app/api/assets/upload/route.ts +177 -0
  40. package/renderer/app/api/auth-schemes/route.ts +77 -0
  41. package/renderer/app/api/chat/route.ts +858 -0
  42. package/renderer/app/api/codegen/route.ts +72 -0
  43. package/renderer/app/api/collections/route.ts +1016 -0
  44. package/renderer/app/api/debug/route.ts +53 -0
  45. package/renderer/app/api/deploy/route.ts +234 -0
  46. package/renderer/app/api/device/route.ts +42 -0
  47. package/renderer/app/api/docs/route.ts +187 -0
  48. package/renderer/app/api/keys/regenerate/route.ts +80 -0
  49. package/renderer/app/api/openapi-spec/route.ts +151 -0
  50. package/renderer/app/api/projects/[slug]/route.ts +153 -0
  51. package/renderer/app/api/projects/[slug]/stats/route.ts +96 -0
  52. package/renderer/app/api/projects/register/route.ts +152 -0
  53. package/renderer/app/api/proxy/route.ts +149 -0
  54. package/renderer/app/api/proxy-stream/route.ts +168 -0
  55. package/renderer/app/api/redirects/route.ts +47 -0
  56. package/renderer/app/api/schema/route.ts +65 -0
  57. package/renderer/app/api/subdomains/check/route.ts +172 -0
  58. package/renderer/app/api/suggestions/route.ts +144 -0
  59. package/renderer/app/favicon.ico +0 -0
  60. package/renderer/app/globals.css +1103 -0
  61. package/renderer/app/layout.tsx +47 -0
  62. package/renderer/app/llms-full.txt/route.ts +346 -0
  63. package/renderer/app/llms.txt/route.ts +279 -0
  64. package/renderer/app/page.tsx +14 -0
  65. package/renderer/app/robots.txt/route.ts +84 -0
  66. package/renderer/app/sitemap.xml/route.ts +199 -0
  67. package/renderer/components/docs/index.ts +12 -0
  68. package/renderer/components/docs/mdx/accordion.tsx +169 -0
  69. package/renderer/components/docs/mdx/badge.tsx +132 -0
  70. package/renderer/components/docs/mdx/callouts.tsx +154 -0
  71. package/renderer/components/docs/mdx/cards.tsx +213 -0
  72. package/renderer/components/docs/mdx/changelog.tsx +120 -0
  73. package/renderer/components/docs/mdx/code-block.tsx +186 -0
  74. package/renderer/components/docs/mdx/code-group.tsx +421 -0
  75. package/renderer/components/docs/mdx/file-embeds.tsx +105 -0
  76. package/renderer/components/docs/mdx/frame.tsx +112 -0
  77. package/renderer/components/docs/mdx/highlight.tsx +151 -0
  78. package/renderer/components/docs/mdx/iframe.tsx +134 -0
  79. package/renderer/components/docs/mdx/image.tsx +235 -0
  80. package/renderer/components/docs/mdx/index.ts +204 -0
  81. package/renderer/components/docs/mdx/mermaid.tsx +240 -0
  82. package/renderer/components/docs/mdx/param-field.tsx +200 -0
  83. package/renderer/components/docs/mdx/steps.tsx +113 -0
  84. package/renderer/components/docs/mdx/tabs.tsx +86 -0
  85. package/renderer/components/docs/mdx-renderer.tsx +100 -0
  86. package/renderer/components/docs/navigation/breadcrumbs.tsx +76 -0
  87. package/renderer/components/docs/navigation/index.ts +8 -0
  88. package/renderer/components/docs/navigation/page-nav.tsx +64 -0
  89. package/renderer/components/docs/navigation/sidebar.tsx +515 -0
  90. package/renderer/components/docs/navigation/toc.tsx +113 -0
  91. package/renderer/components/docs/notice.tsx +105 -0
  92. package/renderer/components/docs-header.tsx +274 -0
  93. package/renderer/components/docs-viewer/agent/agent-chat.tsx +2076 -0
  94. package/renderer/components/docs-viewer/agent/cards/debug-context-card.tsx +90 -0
  95. package/renderer/components/docs-viewer/agent/cards/endpoint-context-card.tsx +49 -0
  96. package/renderer/components/docs-viewer/agent/cards/index.tsx +50 -0
  97. package/renderer/components/docs-viewer/agent/cards/response-options-card.tsx +212 -0
  98. package/renderer/components/docs-viewer/agent/cards/types.ts +84 -0
  99. package/renderer/components/docs-viewer/agent/chat-message.tsx +17 -0
  100. package/renderer/components/docs-viewer/agent/index.tsx +6 -0
  101. package/renderer/components/docs-viewer/agent/messages/assistant-message.tsx +119 -0
  102. package/renderer/components/docs-viewer/agent/messages/chat-message.tsx +46 -0
  103. package/renderer/components/docs-viewer/agent/messages/index.ts +17 -0
  104. package/renderer/components/docs-viewer/agent/messages/tool-call-display.tsx +721 -0
  105. package/renderer/components/docs-viewer/agent/messages/types.ts +61 -0
  106. package/renderer/components/docs-viewer/agent/messages/typing-indicator.tsx +24 -0
  107. package/renderer/components/docs-viewer/agent/messages/user-message.tsx +51 -0
  108. package/renderer/components/docs-viewer/code-editor/index.tsx +2 -0
  109. package/renderer/components/docs-viewer/code-editor/notes-mode.tsx +1283 -0
  110. package/renderer/components/docs-viewer/content/changelog-page.tsx +331 -0
  111. package/renderer/components/docs-viewer/content/doc-page.tsx +285 -0
  112. package/renderer/components/docs-viewer/content/documentation-viewer.tsx +17 -0
  113. package/renderer/components/docs-viewer/content/index.tsx +29 -0
  114. package/renderer/components/docs-viewer/content/introduction.tsx +21 -0
  115. package/renderer/components/docs-viewer/content/request-details.tsx +330 -0
  116. package/renderer/components/docs-viewer/content/sections/auth.tsx +69 -0
  117. package/renderer/components/docs-viewer/content/sections/body.tsx +66 -0
  118. package/renderer/components/docs-viewer/content/sections/headers.tsx +43 -0
  119. package/renderer/components/docs-viewer/content/sections/overview.tsx +40 -0
  120. package/renderer/components/docs-viewer/content/sections/parameters.tsx +43 -0
  121. package/renderer/components/docs-viewer/content/sections/responses.tsx +87 -0
  122. package/renderer/components/docs-viewer/global-auth-modal.tsx +352 -0
  123. package/renderer/components/docs-viewer/index.tsx +1466 -0
  124. package/renderer/components/docs-viewer/playground/auth-editor.tsx +280 -0
  125. package/renderer/components/docs-viewer/playground/body-editor.tsx +221 -0
  126. package/renderer/components/docs-viewer/playground/code-editor.tsx +224 -0
  127. package/renderer/components/docs-viewer/playground/code-snippet.tsx +387 -0
  128. package/renderer/components/docs-viewer/playground/graphql-playground.tsx +745 -0
  129. package/renderer/components/docs-viewer/playground/index.tsx +671 -0
  130. package/renderer/components/docs-viewer/playground/key-value-editor.tsx +261 -0
  131. package/renderer/components/docs-viewer/playground/method-selector.tsx +60 -0
  132. package/renderer/components/docs-viewer/playground/request-builder.tsx +179 -0
  133. package/renderer/components/docs-viewer/playground/request-tabs.tsx +237 -0
  134. package/renderer/components/docs-viewer/playground/response-cards/idle-card.tsx +21 -0
  135. package/renderer/components/docs-viewer/playground/response-cards/index.tsx +93 -0
  136. package/renderer/components/docs-viewer/playground/response-cards/loading-card.tsx +16 -0
  137. package/renderer/components/docs-viewer/playground/response-cards/network-error-card.tsx +23 -0
  138. package/renderer/components/docs-viewer/playground/response-cards/response-body-card.tsx +268 -0
  139. package/renderer/components/docs-viewer/playground/response-cards/types.ts +82 -0
  140. package/renderer/components/docs-viewer/playground/response-viewer.tsx +43 -0
  141. package/renderer/components/docs-viewer/search/index.ts +2 -0
  142. package/renderer/components/docs-viewer/search/search-dialog.tsx +331 -0
  143. package/renderer/components/docs-viewer/search/use-search.ts +117 -0
  144. package/renderer/components/docs-viewer/shared/markdown-renderer.tsx +431 -0
  145. package/renderer/components/docs-viewer/shared/method-badge.tsx +41 -0
  146. package/renderer/components/docs-viewer/shared/schema-viewer.tsx +349 -0
  147. package/renderer/components/docs-viewer/sidebar/collection-tree.tsx +239 -0
  148. package/renderer/components/docs-viewer/sidebar/endpoint-options.tsx +316 -0
  149. package/renderer/components/docs-viewer/sidebar/index.tsx +343 -0
  150. package/renderer/components/docs-viewer/sidebar/right-sidebar.tsx +202 -0
  151. package/renderer/components/docs-viewer/sidebar/sidebar-group.tsx +118 -0
  152. package/renderer/components/docs-viewer/sidebar/sidebar-item.tsx +226 -0
  153. package/renderer/components/docs-viewer/sidebar/sidebar-section.tsx +52 -0
  154. package/renderer/components/theme-provider.tsx +11 -0
  155. package/renderer/components/theme-toggle.tsx +76 -0
  156. package/renderer/components/ui/badge.tsx +46 -0
  157. package/renderer/components/ui/button.tsx +59 -0
  158. package/renderer/components/ui/dialog.tsx +118 -0
  159. package/renderer/components/ui/dropdown-menu.tsx +257 -0
  160. package/renderer/components/ui/input.tsx +21 -0
  161. package/renderer/components/ui/label.tsx +24 -0
  162. package/renderer/components/ui/navigation-menu.tsx +168 -0
  163. package/renderer/components/ui/select.tsx +190 -0
  164. package/renderer/components/ui/spinner.tsx +114 -0
  165. package/renderer/components/ui/tabs.tsx +66 -0
  166. package/renderer/components/ui/tooltip.tsx +61 -0
  167. package/renderer/hooks/use-code-copy.ts +88 -0
  168. package/renderer/hooks/use-openapi-title.ts +44 -0
  169. package/renderer/lib/api-docs/agent/index.ts +6 -0
  170. package/renderer/lib/api-docs/agent/indexer.ts +323 -0
  171. package/renderer/lib/api-docs/agent/spec-summary.ts +335 -0
  172. package/renderer/lib/api-docs/agent/types.ts +116 -0
  173. package/renderer/lib/api-docs/auth/auth-context.tsx +225 -0
  174. package/renderer/lib/api-docs/auth/auth-storage.ts +87 -0
  175. package/renderer/lib/api-docs/auth/crypto.ts +89 -0
  176. package/renderer/lib/api-docs/auth/index.ts +4 -0
  177. package/renderer/lib/api-docs/code-editor/db.ts +164 -0
  178. package/renderer/lib/api-docs/code-editor/hooks.ts +266 -0
  179. package/renderer/lib/api-docs/code-editor/index.ts +6 -0
  180. package/renderer/lib/api-docs/code-editor/mode-context.tsx +207 -0
  181. package/renderer/lib/api-docs/code-editor/types.ts +105 -0
  182. package/renderer/lib/api-docs/codegen/definitions.ts +297 -0
  183. package/renderer/lib/api-docs/codegen/har.ts +251 -0
  184. package/renderer/lib/api-docs/codegen/index.ts +159 -0
  185. package/renderer/lib/api-docs/factories.ts +151 -0
  186. package/renderer/lib/api-docs/index.ts +17 -0
  187. package/renderer/lib/api-docs/mobile-context.tsx +112 -0
  188. package/renderer/lib/api-docs/navigation-context.tsx +88 -0
  189. package/renderer/lib/api-docs/parsers/graphql/README.md +129 -0
  190. package/renderer/lib/api-docs/parsers/graphql/index.ts +91 -0
  191. package/renderer/lib/api-docs/parsers/graphql/parser.ts +491 -0
  192. package/renderer/lib/api-docs/parsers/graphql/transformer.ts +246 -0
  193. package/renderer/lib/api-docs/parsers/graphql/types.ts +283 -0
  194. package/renderer/lib/api-docs/parsers/openapi/README.md +32 -0
  195. package/renderer/lib/api-docs/parsers/openapi/dereferencer.ts +60 -0
  196. package/renderer/lib/api-docs/parsers/openapi/extractors/auth.ts +574 -0
  197. package/renderer/lib/api-docs/parsers/openapi/extractors/body.ts +403 -0
  198. package/renderer/lib/api-docs/parsers/openapi/extractors/index.ts +232 -0
  199. package/renderer/lib/api-docs/parsers/openapi/index.ts +171 -0
  200. package/renderer/lib/api-docs/parsers/openapi/transformer.ts +277 -0
  201. package/renderer/lib/api-docs/parsers/openapi/validator.ts +31 -0
  202. package/renderer/lib/api-docs/playground/context.tsx +107 -0
  203. package/renderer/lib/api-docs/playground/navigation-context.tsx +124 -0
  204. package/renderer/lib/api-docs/playground/request-builder.ts +223 -0
  205. package/renderer/lib/api-docs/playground/request-runner.ts +282 -0
  206. package/renderer/lib/api-docs/playground/types.ts +35 -0
  207. package/renderer/lib/api-docs/types.ts +269 -0
  208. package/renderer/lib/api-docs/utils.ts +311 -0
  209. package/renderer/lib/cache.ts +193 -0
  210. package/renderer/lib/docs/config/index.ts +29 -0
  211. package/renderer/lib/docs/config/loader.ts +142 -0
  212. package/renderer/lib/docs/config/schema.ts +298 -0
  213. package/renderer/lib/docs/index.ts +12 -0
  214. package/renderer/lib/docs/mdx/compiler.ts +176 -0
  215. package/renderer/lib/docs/mdx/frontmatter.ts +80 -0
  216. package/renderer/lib/docs/mdx/index.ts +26 -0
  217. package/renderer/lib/docs/navigation/generator.ts +348 -0
  218. package/renderer/lib/docs/navigation/index.ts +12 -0
  219. package/renderer/lib/docs/navigation/types.ts +123 -0
  220. package/renderer/lib/docs-navigation-context.tsx +80 -0
  221. package/renderer/lib/multi-tenant/context.ts +105 -0
  222. package/renderer/lib/storage/blob.ts +845 -0
  223. package/renderer/lib/utils.ts +6 -0
  224. package/renderer/next.config.ts +76 -0
  225. package/renderer/package.json +66 -0
  226. package/renderer/postcss.config.mjs +5 -0
  227. package/renderer/public/assets/images/screenshot.png +0 -0
  228. package/renderer/public/assets/logo/dark.svg +9 -0
  229. package/renderer/public/assets/logo/light.svg +9 -0
  230. package/renderer/public/assets/logo.svg +9 -0
  231. package/renderer/public/file.svg +1 -0
  232. package/renderer/public/globe.svg +1 -0
  233. package/renderer/public/icon.png +0 -0
  234. package/renderer/public/logo.svg +9 -0
  235. package/renderer/public/window.svg +1 -0
  236. package/renderer/tsconfig.json +28 -0
  237. package/templates/basic/README.md +139 -0
  238. package/templates/basic/assets/favicon.svg +4 -0
  239. package/templates/basic/assets/logo.svg +9 -0
  240. package/templates/basic/docs.json +47 -0
  241. package/templates/basic/guides/configuration.mdx +149 -0
  242. package/templates/basic/guides/overview.mdx +96 -0
  243. package/templates/basic/index.mdx +39 -0
  244. package/templates/basic/package.json +14 -0
  245. package/templates/basic/quickstart.mdx +92 -0
  246. package/templates/basic/vercel.json +6 -0
  247. package/templates/graphql/README.md +139 -0
  248. package/templates/graphql/api-reference/schema.graphql +305 -0
  249. package/templates/graphql/assets/favicon.svg +4 -0
  250. package/templates/graphql/assets/logo.svg +9 -0
  251. package/templates/graphql/docs.json +54 -0
  252. package/templates/graphql/guides/configuration.mdx +149 -0
  253. package/templates/graphql/guides/overview.mdx +96 -0
  254. package/templates/graphql/index.mdx +39 -0
  255. package/templates/graphql/package.json +14 -0
  256. package/templates/graphql/quickstart.mdx +92 -0
  257. package/templates/graphql/vercel.json +6 -0
  258. package/templates/openapi/README.md +139 -0
  259. package/templates/openapi/api-reference/openapi.json +419 -0
  260. package/templates/openapi/assets/favicon.svg +4 -0
  261. package/templates/openapi/assets/logo.svg +9 -0
  262. package/templates/openapi/docs.json +61 -0
  263. package/templates/openapi/guides/configuration.mdx +149 -0
  264. package/templates/openapi/guides/overview.mdx +96 -0
  265. package/templates/openapi/index.mdx +39 -0
  266. package/templates/openapi/package.json +14 -0
  267. package/templates/openapi/quickstart.mdx +92 -0
  268. 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 &lt;token&gt;</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
+ }