@brainfish-ai/devdoc 0.1.41 → 0.1.43

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 (400) hide show
  1. package/ai-agents/.claude/skills/bootstrap-docs/SKILL.md +710 -79
  2. package/ai-agents/.claude/skills/check-docs/SKILL.md +83 -8
  3. package/ai-agents/.claude/skills/create-doc/SKILL.md +267 -55
  4. package/ai-agents/.claude/skills/update-doc/SKILL.md +162 -63
  5. package/ai-agents/.cursor/rules/devdoc-bootstrap.mdc +145 -15
  6. package/ai-agents/.cursor/rules/devdoc-create.mdc +108 -57
  7. package/ai-agents/.cursor/rules/devdoc-update.mdc +93 -70
  8. package/ai-agents/.cursor/rules/devdoc.mdc +21 -0
  9. package/ai-agents/schemas/docs.schema.json +332 -0
  10. package/ai-agents/schemas/theme.schema.json +243 -0
  11. package/dist/cli/commands/create.js +4 -9
  12. package/dist/cli/commands/deploy.js +50 -25
  13. package/dist/cli/commands/dev.js +19 -10
  14. package/package.json +3 -2
  15. package/renderer/app/api/assets/[...path]/route.js +108 -0
  16. package/renderer/app/api/assets/route.js +114 -0
  17. package/renderer/app/api/assets/upload/route.js +163 -0
  18. package/renderer/app/api/auth-schemes/route.js +58 -0
  19. package/renderer/app/api/chat/route.js +759 -0
  20. package/renderer/app/api/codegen/route.js +52 -0
  21. package/renderer/app/api/collections/route.js +675 -0
  22. package/renderer/app/api/debug/route.js +47 -0
  23. package/renderer/app/api/deploy/route.js +199 -0
  24. package/renderer/app/api/device/route.js +36 -0
  25. package/renderer/app/api/docs/route.js +205 -0
  26. package/renderer/app/api/domains/add/route.js +121 -0
  27. package/renderer/app/api/domains/lookup/route.js +43 -0
  28. package/renderer/app/api/domains/remove/route.js +89 -0
  29. package/renderer/app/api/domains/status/route.js +140 -0
  30. package/renderer/app/api/domains/verify/route.js +168 -0
  31. package/renderer/app/api/keys/regenerate/route.js +71 -0
  32. package/renderer/app/api/local-assets/[...path]/route.js +108 -0
  33. package/renderer/app/api/openapi-spec/route.js +73 -0
  34. package/renderer/app/api/projects/[slug]/route.js +129 -0
  35. package/renderer/app/api/projects/[slug]/stats/route.js +80 -0
  36. package/renderer/app/api/projects/register/route.js +176 -0
  37. package/renderer/app/api/proxy/route.js +139 -0
  38. package/renderer/app/api/proxy-stream/route.js +156 -0
  39. package/renderer/app/api/redirects/route.js +35 -0
  40. package/renderer/app/api/schema/route.js +85 -0
  41. package/renderer/app/api/subdomains/check/route.js +158 -0
  42. package/renderer/app/api/suggestions/route.js +175 -0
  43. package/renderer/app/layout.js +47 -0
  44. package/renderer/app/llms-full.txt/route.js +257 -0
  45. package/renderer/app/llms.txt/route.js +219 -0
  46. package/renderer/app/page.js +12 -0
  47. package/renderer/app/robots.txt/route.js +66 -0
  48. package/renderer/app/sitemap.xml/route.js +145 -0
  49. package/renderer/components/docs/index.js +8 -0
  50. package/renderer/components/docs/mdx/accordion.js +113 -0
  51. package/renderer/components/docs/mdx/badge.js +72 -0
  52. package/renderer/components/docs/mdx/callouts.js +137 -0
  53. package/renderer/components/docs/mdx/cards.js +175 -0
  54. package/renderer/components/docs/mdx/changelog.js +100 -0
  55. package/renderer/components/docs/mdx/code-block.js +147 -0
  56. package/renderer/components/docs/mdx/code-group.js +287 -0
  57. package/renderer/components/docs/mdx/file-embeds.js +82 -0
  58. package/renderer/components/docs/mdx/frame.js +59 -0
  59. package/renderer/components/docs/mdx/highlight.js +90 -0
  60. package/renderer/components/docs/mdx/iframe.js +69 -0
  61. package/renderer/components/docs/mdx/image.js +135 -0
  62. package/renderer/components/docs/mdx/index.js +134 -0
  63. package/renderer/components/docs/mdx/landing.js +315 -0
  64. package/renderer/components/docs/mdx/mermaid.js +212 -0
  65. package/renderer/components/docs/mdx/param-field.js +112 -0
  66. package/renderer/components/docs/mdx/steps.js +74 -0
  67. package/renderer/components/docs/mdx/tabs.js +50 -0
  68. package/renderer/components/docs/mdx-renderer.js +77 -0
  69. package/renderer/components/docs/navigation/breadcrumbs.js +64 -0
  70. package/renderer/components/docs/navigation/index.js +6 -0
  71. package/renderer/components/docs/navigation/page-nav.js +57 -0
  72. package/renderer/components/docs/navigation/sidebar.js +375 -0
  73. package/renderer/components/docs/navigation/toc.js +89 -0
  74. package/renderer/components/docs/notice.js +77 -0
  75. package/renderer/components/docs-header.js +202 -0
  76. package/renderer/components/docs-viewer/agent/agent-chat.js +1930 -0
  77. package/renderer/components/docs-viewer/agent/cards/debug-context-card.js +107 -0
  78. package/renderer/components/docs-viewer/agent/cards/endpoint-context-card.js +57 -0
  79. package/renderer/components/docs-viewer/agent/cards/index.js +45 -0
  80. package/renderer/components/docs-viewer/agent/cards/response-options-card.js +154 -0
  81. package/renderer/components/docs-viewer/agent/cards/types.js +22 -0
  82. package/renderer/components/docs-viewer/agent/chat-message.js +2 -0
  83. package/renderer/components/docs-viewer/agent/index.js +4 -0
  84. package/renderer/components/docs-viewer/agent/messages/assistant-message.js +108 -0
  85. package/renderer/components/docs-viewer/agent/messages/chat-message.js +34 -0
  86. package/renderer/components/docs-viewer/agent/messages/index.js +6 -0
  87. package/renderer/components/docs-viewer/agent/messages/tool-call-display.js +1065 -0
  88. package/renderer/components/docs-viewer/agent/messages/types.js +2 -0
  89. package/renderer/components/docs-viewer/agent/messages/typing-indicator.js +26 -0
  90. package/renderer/components/docs-viewer/agent/messages/user-message.js +37 -0
  91. package/renderer/components/docs-viewer/code-editor/{index.tsx → index.js} +1 -1
  92. package/renderer/components/docs-viewer/code-editor/notes-mode.js +1338 -0
  93. package/renderer/components/docs-viewer/content/changelog-page.js +297 -0
  94. package/renderer/components/docs-viewer/content/doc-page.js +264 -0
  95. package/renderer/components/docs-viewer/content/documentation-viewer.js +14 -0
  96. package/renderer/components/docs-viewer/content/index.js +29 -0
  97. package/renderer/components/docs-viewer/content/not-found-page.js +300 -0
  98. package/renderer/components/docs-viewer/content/request-details.js +528 -0
  99. package/renderer/components/docs-viewer/content/sections/auth.js +108 -0
  100. package/renderer/components/docs-viewer/content/sections/body.js +80 -0
  101. package/renderer/components/docs-viewer/content/sections/headers.js +64 -0
  102. package/renderer/components/docs-viewer/content/sections/overview.js +56 -0
  103. package/renderer/components/docs-viewer/content/sections/parameters.js +64 -0
  104. package/renderer/components/docs-viewer/content/sections/responses.js +91 -0
  105. package/renderer/components/docs-viewer/global-auth-modal.js +427 -0
  106. package/renderer/components/docs-viewer/index.js +1552 -0
  107. package/renderer/components/docs-viewer/playground/auth-editor.js +418 -0
  108. package/renderer/components/docs-viewer/playground/body-editor.js +240 -0
  109. package/renderer/components/docs-viewer/playground/code-editor.js +135 -0
  110. package/renderer/components/docs-viewer/playground/code-snippet.js +393 -0
  111. package/renderer/components/docs-viewer/playground/graphql-playground.js +734 -0
  112. package/renderer/components/docs-viewer/playground/index.js +682 -0
  113. package/renderer/components/docs-viewer/playground/key-value-editor.js +317 -0
  114. package/renderer/components/docs-viewer/playground/method-selector.js +65 -0
  115. package/renderer/components/docs-viewer/playground/request-builder.js +181 -0
  116. package/renderer/components/docs-viewer/playground/request-tabs.js +240 -0
  117. package/renderer/components/docs-viewer/playground/response-cards/idle-card.js +42 -0
  118. package/renderer/components/docs-viewer/playground/response-cards/index.js +72 -0
  119. package/renderer/components/docs-viewer/playground/response-cards/loading-card.js +24 -0
  120. package/renderer/components/docs-viewer/playground/response-cards/network-error-card.js +28 -0
  121. package/renderer/components/docs-viewer/playground/response-cards/response-body-card.js +308 -0
  122. package/renderer/components/docs-viewer/playground/response-cards/types.js +9 -0
  123. package/renderer/components/docs-viewer/playground/response-viewer.js +18 -0
  124. package/renderer/components/docs-viewer/search/index.js +2 -0
  125. package/renderer/components/docs-viewer/search/search-dialog.js +367 -0
  126. package/renderer/components/docs-viewer/search/use-search.js +89 -0
  127. package/renderer/components/docs-viewer/shared/markdown-renderer.js +423 -0
  128. package/renderer/components/docs-viewer/shared/method-badge.js +23 -0
  129. package/renderer/components/docs-viewer/shared/schema-viewer.js +321 -0
  130. package/renderer/components/docs-viewer/sidebar/collection-tree.js +222 -0
  131. package/renderer/components/docs-viewer/sidebar/endpoint-options.js +512 -0
  132. package/renderer/components/docs-viewer/sidebar/index.js +196 -0
  133. package/renderer/components/docs-viewer/sidebar/right-sidebar.js +163 -0
  134. package/renderer/components/docs-viewer/sidebar/sidebar-group.js +87 -0
  135. package/renderer/components/docs-viewer/sidebar/sidebar-item.js +172 -0
  136. package/renderer/components/docs-viewer/sidebar/sidebar-section.js +31 -0
  137. package/renderer/components/theme-provider.js +10 -0
  138. package/renderer/components/theme-toggle.js +106 -0
  139. package/renderer/components/ui/badge.js +29 -0
  140. package/renderer/components/ui/button.js +40 -0
  141. package/renderer/components/ui/dialog.js +50 -0
  142. package/renderer/components/ui/dropdown-menu.js +143 -0
  143. package/renderer/components/ui/input.js +12 -0
  144. package/renderer/components/ui/label.js +13 -0
  145. package/renderer/components/ui/navigation-menu.js +83 -0
  146. package/renderer/components/ui/select.js +116 -0
  147. package/renderer/components/ui/spinner.js +92 -0
  148. package/renderer/components/ui/tabs.js +34 -0
  149. package/renderer/components/ui/tooltip.js +43 -0
  150. package/renderer/hooks/use-code-copy.js +76 -0
  151. package/renderer/hooks/use-openapi-title.js +33 -0
  152. package/renderer/lib/api-docs/agent/index.js +4 -0
  153. package/renderer/lib/api-docs/agent/indexer.js +254 -0
  154. package/renderer/lib/api-docs/agent/spec-summary.js +227 -0
  155. package/renderer/lib/api-docs/agent/types.js +5 -0
  156. package/renderer/lib/api-docs/auth/auth-context.js +157 -0
  157. package/renderer/lib/api-docs/auth/auth-storage.js +66 -0
  158. package/renderer/lib/api-docs/auth/crypto.js +64 -0
  159. package/renderer/lib/api-docs/auth/index.js +3 -0
  160. package/renderer/lib/api-docs/code-editor/db.js +145 -0
  161. package/renderer/lib/api-docs/code-editor/hooks.js +254 -0
  162. package/renderer/lib/api-docs/code-editor/{index.ts → index.js} +3 -4
  163. package/renderer/lib/api-docs/code-editor/mode-context.js +154 -0
  164. package/renderer/lib/api-docs/code-editor/types.js +53 -0
  165. package/renderer/lib/api-docs/codegen/definitions.js +258 -0
  166. package/renderer/lib/api-docs/codegen/har.js +171 -0
  167. package/renderer/lib/api-docs/codegen/index.js +118 -0
  168. package/renderer/lib/api-docs/factories.js +136 -0
  169. package/renderer/lib/api-docs/{index.ts → index.js} +5 -10
  170. package/renderer/lib/api-docs/mobile-context.js +79 -0
  171. package/renderer/lib/api-docs/navigation-context.js +62 -0
  172. package/renderer/lib/api-docs/parsers/graphql/index.js +50 -0
  173. package/renderer/lib/api-docs/parsers/graphql/parser.js +350 -0
  174. package/renderer/lib/api-docs/parsers/graphql/transformer.js +215 -0
  175. package/renderer/lib/api-docs/parsers/graphql/types.js +46 -0
  176. package/renderer/lib/api-docs/parsers/openapi/dereferencer.js +43 -0
  177. package/renderer/lib/api-docs/parsers/openapi/extractors/auth.js +486 -0
  178. package/renderer/lib/api-docs/parsers/openapi/extractors/body.js +295 -0
  179. package/renderer/lib/api-docs/parsers/openapi/extractors/index.js +132 -0
  180. package/renderer/lib/api-docs/parsers/openapi/index.js +127 -0
  181. package/renderer/lib/api-docs/parsers/openapi/transformer.js +192 -0
  182. package/renderer/lib/api-docs/parsers/openapi/validator.js +24 -0
  183. package/renderer/lib/api-docs/playground/context.js +65 -0
  184. package/renderer/lib/api-docs/playground/navigation-context.js +74 -0
  185. package/renderer/lib/api-docs/playground/request-builder.js +163 -0
  186. package/renderer/lib/api-docs/playground/request-runner.js +224 -0
  187. package/renderer/lib/api-docs/playground/types.js +5 -0
  188. package/renderer/lib/api-docs/types.js +23 -0
  189. package/renderer/lib/api-docs/utils.js +212 -0
  190. package/renderer/lib/cache.js +157 -0
  191. package/renderer/lib/docs/config/domain-schema.js +161 -0
  192. package/renderer/lib/docs/config/index.js +5 -0
  193. package/renderer/lib/docs/config/loader.js +113 -0
  194. package/renderer/lib/docs/config/schema.js +269 -0
  195. package/renderer/lib/docs/index.js +8 -0
  196. package/renderer/lib/docs/mdx/compiler.js +128 -0
  197. package/renderer/lib/docs/mdx/frontmatter.js +73 -0
  198. package/renderer/lib/docs/mdx/index.js +8 -0
  199. package/renderer/lib/docs/navigation/generator.js +269 -0
  200. package/renderer/lib/docs/navigation/index.js +4 -0
  201. package/renderer/lib/docs/navigation/types.js +9 -0
  202. package/renderer/lib/docs-navigation-context.js +40 -0
  203. package/renderer/lib/multi-tenant/context.js +80 -0
  204. package/renderer/lib/storage/blob.js +767 -0
  205. package/renderer/lib/utils/icons.js +30 -0
  206. package/renderer/lib/utils.js +5 -0
  207. package/renderer/next.config.js +62 -0
  208. package/renderer/tsconfig.json +23 -5
  209. package/renderer/app/api/assets/[...path]/route.ts +0 -123
  210. package/renderer/app/api/assets/route.ts +0 -124
  211. package/renderer/app/api/assets/upload/route.ts +0 -177
  212. package/renderer/app/api/auth-schemes/route.ts +0 -77
  213. package/renderer/app/api/chat/route.ts +0 -858
  214. package/renderer/app/api/codegen/route.ts +0 -72
  215. package/renderer/app/api/collections/route.ts +0 -1002
  216. package/renderer/app/api/debug/route.ts +0 -53
  217. package/renderer/app/api/deploy/route.ts +0 -234
  218. package/renderer/app/api/device/route.ts +0 -42
  219. package/renderer/app/api/docs/route.ts +0 -201
  220. package/renderer/app/api/domains/add/route.ts +0 -132
  221. package/renderer/app/api/domains/lookup/route.ts +0 -43
  222. package/renderer/app/api/domains/remove/route.ts +0 -100
  223. package/renderer/app/api/domains/status/route.ts +0 -158
  224. package/renderer/app/api/domains/verify/route.ts +0 -181
  225. package/renderer/app/api/keys/regenerate/route.ts +0 -80
  226. package/renderer/app/api/local-assets/[...path]/route.ts +0 -122
  227. package/renderer/app/api/openapi-spec/route.ts +0 -151
  228. package/renderer/app/api/projects/[slug]/route.ts +0 -153
  229. package/renderer/app/api/projects/[slug]/stats/route.ts +0 -96
  230. package/renderer/app/api/projects/register/route.ts +0 -152
  231. package/renderer/app/api/proxy/route.ts +0 -149
  232. package/renderer/app/api/proxy-stream/route.ts +0 -168
  233. package/renderer/app/api/redirects/route.ts +0 -47
  234. package/renderer/app/api/schema/route.ts +0 -73
  235. package/renderer/app/api/subdomains/check/route.ts +0 -172
  236. package/renderer/app/api/suggestions/route.ts +0 -144
  237. package/renderer/app/layout.tsx +0 -54
  238. package/renderer/app/llms-full.txt/route.ts +0 -346
  239. package/renderer/app/llms.txt/route.ts +0 -279
  240. package/renderer/app/page.tsx +0 -14
  241. package/renderer/app/robots.txt/route.ts +0 -84
  242. package/renderer/app/sitemap.xml/route.ts +0 -199
  243. package/renderer/components/docs/index.ts +0 -12
  244. package/renderer/components/docs/mdx/accordion.tsx +0 -169
  245. package/renderer/components/docs/mdx/badge.tsx +0 -132
  246. package/renderer/components/docs/mdx/callouts.tsx +0 -154
  247. package/renderer/components/docs/mdx/cards.tsx +0 -241
  248. package/renderer/components/docs/mdx/changelog.tsx +0 -120
  249. package/renderer/components/docs/mdx/code-block.tsx +0 -186
  250. package/renderer/components/docs/mdx/code-group.tsx +0 -421
  251. package/renderer/components/docs/mdx/file-embeds.tsx +0 -105
  252. package/renderer/components/docs/mdx/frame.tsx +0 -112
  253. package/renderer/components/docs/mdx/highlight.tsx +0 -151
  254. package/renderer/components/docs/mdx/iframe.tsx +0 -134
  255. package/renderer/components/docs/mdx/image.tsx +0 -235
  256. package/renderer/components/docs/mdx/index.ts +0 -237
  257. package/renderer/components/docs/mdx/landing.tsx +0 -684
  258. package/renderer/components/docs/mdx/mermaid.tsx +0 -240
  259. package/renderer/components/docs/mdx/param-field.tsx +0 -200
  260. package/renderer/components/docs/mdx/steps.tsx +0 -113
  261. package/renderer/components/docs/mdx/tabs.tsx +0 -86
  262. package/renderer/components/docs/mdx-renderer.tsx +0 -100
  263. package/renderer/components/docs/navigation/breadcrumbs.tsx +0 -76
  264. package/renderer/components/docs/navigation/index.ts +0 -8
  265. package/renderer/components/docs/navigation/page-nav.tsx +0 -64
  266. package/renderer/components/docs/navigation/sidebar.tsx +0 -515
  267. package/renderer/components/docs/navigation/toc.tsx +0 -113
  268. package/renderer/components/docs/notice.tsx +0 -105
  269. package/renderer/components/docs-header.tsx +0 -278
  270. package/renderer/components/docs-viewer/agent/agent-chat.tsx +0 -2076
  271. package/renderer/components/docs-viewer/agent/cards/debug-context-card.tsx +0 -90
  272. package/renderer/components/docs-viewer/agent/cards/endpoint-context-card.tsx +0 -49
  273. package/renderer/components/docs-viewer/agent/cards/index.tsx +0 -50
  274. package/renderer/components/docs-viewer/agent/cards/response-options-card.tsx +0 -212
  275. package/renderer/components/docs-viewer/agent/cards/types.ts +0 -84
  276. package/renderer/components/docs-viewer/agent/chat-message.tsx +0 -17
  277. package/renderer/components/docs-viewer/agent/index.tsx +0 -6
  278. package/renderer/components/docs-viewer/agent/messages/assistant-message.tsx +0 -119
  279. package/renderer/components/docs-viewer/agent/messages/chat-message.tsx +0 -46
  280. package/renderer/components/docs-viewer/agent/messages/index.ts +0 -17
  281. package/renderer/components/docs-viewer/agent/messages/tool-call-display.tsx +0 -721
  282. package/renderer/components/docs-viewer/agent/messages/types.ts +0 -61
  283. package/renderer/components/docs-viewer/agent/messages/typing-indicator.tsx +0 -24
  284. package/renderer/components/docs-viewer/agent/messages/user-message.tsx +0 -51
  285. package/renderer/components/docs-viewer/code-editor/notes-mode.tsx +0 -1283
  286. package/renderer/components/docs-viewer/content/changelog-page.tsx +0 -331
  287. package/renderer/components/docs-viewer/content/doc-page.tsx +0 -367
  288. package/renderer/components/docs-viewer/content/documentation-viewer.tsx +0 -17
  289. package/renderer/components/docs-viewer/content/index.tsx +0 -29
  290. package/renderer/components/docs-viewer/content/not-found-page.tsx +0 -330
  291. package/renderer/components/docs-viewer/content/request-details.tsx +0 -330
  292. package/renderer/components/docs-viewer/content/sections/auth.tsx +0 -69
  293. package/renderer/components/docs-viewer/content/sections/body.tsx +0 -66
  294. package/renderer/components/docs-viewer/content/sections/headers.tsx +0 -43
  295. package/renderer/components/docs-viewer/content/sections/overview.tsx +0 -40
  296. package/renderer/components/docs-viewer/content/sections/parameters.tsx +0 -43
  297. package/renderer/components/docs-viewer/content/sections/responses.tsx +0 -87
  298. package/renderer/components/docs-viewer/global-auth-modal.tsx +0 -352
  299. package/renderer/components/docs-viewer/index.tsx +0 -1662
  300. package/renderer/components/docs-viewer/playground/auth-editor.tsx +0 -280
  301. package/renderer/components/docs-viewer/playground/body-editor.tsx +0 -221
  302. package/renderer/components/docs-viewer/playground/code-editor.tsx +0 -224
  303. package/renderer/components/docs-viewer/playground/code-snippet.tsx +0 -387
  304. package/renderer/components/docs-viewer/playground/graphql-playground.tsx +0 -745
  305. package/renderer/components/docs-viewer/playground/index.tsx +0 -671
  306. package/renderer/components/docs-viewer/playground/key-value-editor.tsx +0 -261
  307. package/renderer/components/docs-viewer/playground/method-selector.tsx +0 -60
  308. package/renderer/components/docs-viewer/playground/request-builder.tsx +0 -179
  309. package/renderer/components/docs-viewer/playground/request-tabs.tsx +0 -237
  310. package/renderer/components/docs-viewer/playground/response-cards/idle-card.tsx +0 -21
  311. package/renderer/components/docs-viewer/playground/response-cards/index.tsx +0 -93
  312. package/renderer/components/docs-viewer/playground/response-cards/loading-card.tsx +0 -16
  313. package/renderer/components/docs-viewer/playground/response-cards/network-error-card.tsx +0 -23
  314. package/renderer/components/docs-viewer/playground/response-cards/response-body-card.tsx +0 -268
  315. package/renderer/components/docs-viewer/playground/response-cards/types.ts +0 -82
  316. package/renderer/components/docs-viewer/playground/response-viewer.tsx +0 -43
  317. package/renderer/components/docs-viewer/search/index.ts +0 -2
  318. package/renderer/components/docs-viewer/search/search-dialog.tsx +0 -331
  319. package/renderer/components/docs-viewer/search/use-search.ts +0 -117
  320. package/renderer/components/docs-viewer/shared/markdown-renderer.tsx +0 -431
  321. package/renderer/components/docs-viewer/shared/method-badge.tsx +0 -41
  322. package/renderer/components/docs-viewer/shared/schema-viewer.tsx +0 -349
  323. package/renderer/components/docs-viewer/sidebar/collection-tree.tsx +0 -259
  324. package/renderer/components/docs-viewer/sidebar/endpoint-options.tsx +0 -316
  325. package/renderer/components/docs-viewer/sidebar/index.tsx +0 -282
  326. package/renderer/components/docs-viewer/sidebar/right-sidebar.tsx +0 -202
  327. package/renderer/components/docs-viewer/sidebar/sidebar-group.tsx +0 -118
  328. package/renderer/components/docs-viewer/sidebar/sidebar-item.tsx +0 -212
  329. package/renderer/components/docs-viewer/sidebar/sidebar-section.tsx +0 -38
  330. package/renderer/components/theme-provider.tsx +0 -11
  331. package/renderer/components/theme-toggle.tsx +0 -76
  332. package/renderer/components/ui/badge.tsx +0 -46
  333. package/renderer/components/ui/button.tsx +0 -59
  334. package/renderer/components/ui/dialog.tsx +0 -118
  335. package/renderer/components/ui/dropdown-menu.tsx +0 -257
  336. package/renderer/components/ui/input.tsx +0 -21
  337. package/renderer/components/ui/label.tsx +0 -24
  338. package/renderer/components/ui/navigation-menu.tsx +0 -168
  339. package/renderer/components/ui/select.tsx +0 -190
  340. package/renderer/components/ui/spinner.tsx +0 -114
  341. package/renderer/components/ui/tabs.tsx +0 -66
  342. package/renderer/components/ui/tooltip.tsx +0 -61
  343. package/renderer/hooks/use-code-copy.ts +0 -88
  344. package/renderer/hooks/use-openapi-title.ts +0 -44
  345. package/renderer/lib/api-docs/agent/index.ts +0 -6
  346. package/renderer/lib/api-docs/agent/indexer.ts +0 -323
  347. package/renderer/lib/api-docs/agent/spec-summary.ts +0 -335
  348. package/renderer/lib/api-docs/agent/types.ts +0 -116
  349. package/renderer/lib/api-docs/auth/auth-context.tsx +0 -225
  350. package/renderer/lib/api-docs/auth/auth-storage.ts +0 -87
  351. package/renderer/lib/api-docs/auth/crypto.ts +0 -89
  352. package/renderer/lib/api-docs/auth/index.ts +0 -4
  353. package/renderer/lib/api-docs/code-editor/db.ts +0 -164
  354. package/renderer/lib/api-docs/code-editor/hooks.ts +0 -266
  355. package/renderer/lib/api-docs/code-editor/mode-context.tsx +0 -207
  356. package/renderer/lib/api-docs/code-editor/types.ts +0 -105
  357. package/renderer/lib/api-docs/codegen/definitions.ts +0 -297
  358. package/renderer/lib/api-docs/codegen/har.ts +0 -251
  359. package/renderer/lib/api-docs/codegen/index.ts +0 -159
  360. package/renderer/lib/api-docs/factories.ts +0 -170
  361. package/renderer/lib/api-docs/mobile-context.tsx +0 -112
  362. package/renderer/lib/api-docs/navigation-context.tsx +0 -88
  363. package/renderer/lib/api-docs/parsers/graphql/README.md +0 -129
  364. package/renderer/lib/api-docs/parsers/graphql/index.ts +0 -91
  365. package/renderer/lib/api-docs/parsers/graphql/parser.ts +0 -491
  366. package/renderer/lib/api-docs/parsers/graphql/transformer.ts +0 -246
  367. package/renderer/lib/api-docs/parsers/graphql/types.ts +0 -283
  368. package/renderer/lib/api-docs/parsers/openapi/README.md +0 -32
  369. package/renderer/lib/api-docs/parsers/openapi/dereferencer.ts +0 -60
  370. package/renderer/lib/api-docs/parsers/openapi/extractors/auth.ts +0 -574
  371. package/renderer/lib/api-docs/parsers/openapi/extractors/body.ts +0 -403
  372. package/renderer/lib/api-docs/parsers/openapi/extractors/index.ts +0 -232
  373. package/renderer/lib/api-docs/parsers/openapi/index.ts +0 -171
  374. package/renderer/lib/api-docs/parsers/openapi/transformer.ts +0 -278
  375. package/renderer/lib/api-docs/parsers/openapi/validator.ts +0 -31
  376. package/renderer/lib/api-docs/playground/context.tsx +0 -107
  377. package/renderer/lib/api-docs/playground/navigation-context.tsx +0 -124
  378. package/renderer/lib/api-docs/playground/request-builder.ts +0 -223
  379. package/renderer/lib/api-docs/playground/request-runner.ts +0 -282
  380. package/renderer/lib/api-docs/playground/types.ts +0 -35
  381. package/renderer/lib/api-docs/types.ts +0 -269
  382. package/renderer/lib/api-docs/utils.ts +0 -311
  383. package/renderer/lib/cache.ts +0 -193
  384. package/renderer/lib/docs/config/domain-schema.ts +0 -260
  385. package/renderer/lib/docs/config/index.ts +0 -43
  386. package/renderer/lib/docs/config/loader.ts +0 -142
  387. package/renderer/lib/docs/config/schema.ts +0 -308
  388. package/renderer/lib/docs/index.ts +0 -12
  389. package/renderer/lib/docs/mdx/compiler.ts +0 -176
  390. package/renderer/lib/docs/mdx/frontmatter.ts +0 -91
  391. package/renderer/lib/docs/mdx/index.ts +0 -26
  392. package/renderer/lib/docs/navigation/generator.ts +0 -348
  393. package/renderer/lib/docs/navigation/index.ts +0 -12
  394. package/renderer/lib/docs/navigation/types.ts +0 -123
  395. package/renderer/lib/docs-navigation-context.tsx +0 -80
  396. package/renderer/lib/multi-tenant/context.ts +0 -105
  397. package/renderer/lib/storage/blob.ts +0 -1083
  398. package/renderer/lib/utils/icons.ts +0 -48
  399. package/renderer/lib/utils.ts +0 -6
  400. package/renderer/next.config.ts +0 -76
@@ -1,745 +0,0 @@
1
- 'use client'
2
-
3
- import { useState, useCallback, useEffect, useRef } from 'react'
4
- import { cn } from '@/lib/utils'
5
- import {
6
- Play,
7
- ArrowClockwise,
8
- Copy,
9
- Check,
10
- Spinner,
11
- X,
12
- FileText,
13
- BracketsCurly,
14
- Key,
15
- CaretRight,
16
- CaretDown,
17
- MagnifyingGlass,
18
- Lightning,
19
- ArrowsClockwise
20
- } from '@phosphor-icons/react'
21
- import { Button } from '@/components/ui/button'
22
- import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'
23
- import Editor, { loader } from '@monaco-editor/react'
24
-
25
- // Configure Monaco to use CDN
26
- loader.config({
27
- paths: {
28
- vs: 'https://cdn.jsdelivr.net/npm/monaco-editor@0.45.0/min/vs',
29
- },
30
- })
31
-
32
- // ============================================================================
33
- // Types
34
- // ============================================================================
35
-
36
- export interface GraphQLOperationItem {
37
- id: string
38
- name: string
39
- description?: string | null
40
- operationType: 'query' | 'mutation' | 'subscription'
41
- query: string
42
- exampleVariables?: Record<string, unknown>
43
- }
44
-
45
- interface GraphQLPlaygroundProps {
46
- /** GraphQL endpoint URL */
47
- endpoint: string
48
- /** Initial query to display */
49
- defaultQuery?: string
50
- /** Headers to include with requests */
51
- headers?: Record<string, string>
52
- /** Operations from parsed schema */
53
- operations?: GraphQLOperationItem[]
54
- /** Selected operation ID (controlled from outside) */
55
- selectedOperationId?: string
56
- /** Hide internal schema explorer (when using main sidebar) */
57
- hideExplorer?: boolean
58
- /** Custom class name */
59
- className?: string
60
- /** Theme */
61
- theme?: 'light' | 'dark'
62
- }
63
-
64
- interface GraphQLResponse {
65
- data?: unknown
66
- errors?: Array<{
67
- message: string
68
- locations?: Array<{ line: number; column: number }>
69
- path?: Array<string | number>
70
- }>
71
- extensions?: Record<string, unknown>
72
- }
73
-
74
- type TabType = 'variables' | 'headers'
75
-
76
- const STORAGE_KEY = 'brainfish-graphql-playground'
77
-
78
- // ============================================================================
79
- // Helpers
80
- // ============================================================================
81
-
82
- function loadStoredState(): { query?: string; variables?: string; headers?: string } | null {
83
- if (typeof window === 'undefined') return null
84
- try {
85
- const stored = localStorage.getItem(STORAGE_KEY)
86
- if (stored) return JSON.parse(stored)
87
- } catch { /* ignore */ }
88
- return null
89
- }
90
-
91
- function saveStoredState(state: { query: string; variables: string; headers: string }): void {
92
- if (typeof window === 'undefined') return
93
- try {
94
- localStorage.setItem(STORAGE_KEY, JSON.stringify(state))
95
- } catch { /* ignore */ }
96
- }
97
-
98
- // ============================================================================
99
- // Schema Explorer Sidebar
100
- // ============================================================================
101
-
102
- interface SchemaExplorerProps {
103
- operations: GraphQLOperationItem[]
104
- onSelectOperation: (operation: GraphQLOperationItem) => void
105
- selectedOperationId?: string
106
- }
107
-
108
- function SchemaExplorer({ operations, onSelectOperation, selectedOperationId }: SchemaExplorerProps) {
109
- const [searchQuery, setSearchQuery] = useState('')
110
- const [expandedSections, setExpandedSections] = useState<Record<string, boolean>>({
111
- query: true,
112
- mutation: true,
113
- subscription: true,
114
- })
115
-
116
- // Group operations by type
117
- const queries = operations.filter(op => op.operationType === 'query')
118
- const mutations = operations.filter(op => op.operationType === 'mutation')
119
- const subscriptions = operations.filter(op => op.operationType === 'subscription')
120
-
121
- // Filter by search
122
- const filterOps = (ops: GraphQLOperationItem[]) => {
123
- if (!searchQuery.trim()) return ops
124
- const query = searchQuery.toLowerCase()
125
- return ops.filter(op =>
126
- op.name.toLowerCase().includes(query) ||
127
- op.description?.toLowerCase().includes(query)
128
- )
129
- }
130
-
131
- const filteredQueries = filterOps(queries)
132
- const filteredMutations = filterOps(mutations)
133
- const filteredSubscriptions = filterOps(subscriptions)
134
-
135
- const toggleSection = (section: string) => {
136
- setExpandedSections(prev => ({
137
- ...prev,
138
- [section]: !prev[section],
139
- }))
140
- }
141
-
142
- const renderSection = (
143
- title: string,
144
- icon: React.ReactNode,
145
- ops: GraphQLOperationItem[],
146
- sectionKey: string,
147
- iconColor: string
148
- ) => {
149
- if (ops.length === 0) return null
150
- const isExpanded = expandedSections[sectionKey]
151
-
152
- return (
153
- <div className="mb-2">
154
- <button
155
- onClick={() => toggleSection(sectionKey)}
156
- className="w-full flex items-center gap-2 px-3 py-2 text-xs font-semibold uppercase tracking-wider text-muted-foreground hover:bg-muted/50 transition-colors"
157
- >
158
- {isExpanded ? (
159
- <CaretDown className="w-3 h-3" />
160
- ) : (
161
- <CaretRight className="w-3 h-3" />
162
- )}
163
- <span className={iconColor}>{icon}</span>
164
- <span>{title}</span>
165
- <span className="ml-auto text-[10px] font-normal opacity-60">
166
- {ops.length}
167
- </span>
168
- </button>
169
-
170
- {isExpanded && (
171
- <div className="ml-2">
172
- {ops.map((op) => (
173
- <button
174
- key={op.id}
175
- onClick={() => onSelectOperation(op)}
176
- className={cn(
177
- 'w-full flex items-start gap-2 px-3 py-2 text-left',
178
- 'hover:bg-muted/50 transition-colors rounded-sm',
179
- 'border-l-2',
180
- selectedOperationId === op.id
181
- ? 'bg-muted/70 border-primary'
182
- : 'border-transparent'
183
- )}
184
- >
185
- <div className="flex-1 min-w-0">
186
- <div className="text-sm font-medium truncate">
187
- {op.name}
188
- </div>
189
- {op.description && (
190
- <div className="text-xs text-muted-foreground truncate mt-0.5">
191
- {op.description}
192
- </div>
193
- )}
194
- </div>
195
- </button>
196
- ))}
197
- </div>
198
- )}
199
- </div>
200
- )
201
- }
202
-
203
- const hasOperations = operations.length > 0
204
- const hasFilteredResults = filteredQueries.length > 0 || filteredMutations.length > 0 || filteredSubscriptions.length > 0
205
-
206
- return (
207
- <div className="flex flex-col h-full border-r border-border bg-muted/20">
208
- {/* Search */}
209
- <div className="p-2 border-b border-border">
210
- <div className="relative">
211
- <MagnifyingGlass className="absolute left-2.5 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground" />
212
- <input
213
- type="text"
214
- value={searchQuery}
215
- onChange={(e) => setSearchQuery(e.target.value)}
216
- placeholder="Search operations..."
217
- className={cn(
218
- 'w-full pl-8 pr-3 py-1.5 text-sm rounded-md',
219
- 'bg-background border border-border',
220
- 'focus:outline-none focus:ring-1 focus:ring-primary',
221
- 'placeholder:text-muted-foreground'
222
- )}
223
- />
224
- </div>
225
- </div>
226
-
227
- {/* Operations list */}
228
- <div className="flex-1 overflow-y-auto py-2">
229
- {!hasOperations ? (
230
- <div className="flex flex-col items-center justify-center h-full px-4 text-center">
231
- <FileText className="w-8 h-8 text-muted-foreground/50 mb-2" />
232
- <p className="text-sm text-muted-foreground">
233
- No schema loaded
234
- </p>
235
- <p className="text-xs text-muted-foreground/60 mt-1">
236
- Operations will appear here
237
- </p>
238
- </div>
239
- ) : !hasFilteredResults ? (
240
- <div className="flex flex-col items-center justify-center h-32 px-4 text-center">
241
- <p className="text-sm text-muted-foreground">
242
- No matching operations
243
- </p>
244
- </div>
245
- ) : (
246
- <>
247
- {renderSection(
248
- 'Queries',
249
- <MagnifyingGlass className="w-3.5 h-3.5" weight="bold" />,
250
- filteredQueries,
251
- 'query',
252
- 'text-blue-500'
253
- )}
254
- {renderSection(
255
- 'Mutations',
256
- <Lightning className="w-3.5 h-3.5" weight="bold" />,
257
- filteredMutations,
258
- 'mutation',
259
- 'text-orange-500'
260
- )}
261
- {renderSection(
262
- 'Subscriptions',
263
- <ArrowsClockwise className="w-3.5 h-3.5" weight="bold" />,
264
- filteredSubscriptions,
265
- 'subscription',
266
- 'text-purple-500'
267
- )}
268
- </>
269
- )}
270
- </div>
271
- </div>
272
- )
273
- }
274
-
275
- // ============================================================================
276
- // Main Component
277
- // ============================================================================
278
-
279
- export function GraphQLPlayground({
280
- endpoint,
281
- defaultQuery = `# Welcome to the GraphQL Playground!
282
- #
283
- # Select an operation from the sidebar, or
284
- # type your query below and press Ctrl+Enter
285
-
286
- query {
287
- __typename
288
- }
289
- `,
290
- headers: defaultHeaders = {},
291
- operations = [],
292
- selectedOperationId: externalSelectedId,
293
- hideExplorer = false,
294
- className,
295
- theme = 'dark',
296
- }: GraphQLPlaygroundProps) {
297
- const [query, setQuery] = useState(defaultQuery)
298
- const [variables, setVariables] = useState('{}')
299
- const [customHeaders, setCustomHeaders] = useState(
300
- Object.keys(defaultHeaders).length > 0
301
- ? JSON.stringify(defaultHeaders, null, 2)
302
- : '{}'
303
- )
304
- const [response, setResponse] = useState<GraphQLResponse | null>(null)
305
- const [isLoading, setIsLoading] = useState(false)
306
- const [error, setError] = useState<string | null>(null)
307
- const [copied, setCopied] = useState(false)
308
- const [activeTab, setActiveTab] = useState<TabType>('variables')
309
- const [responseTime, setResponseTime] = useState<number | null>(null)
310
- const [internalSelectedId, setInternalSelectedId] = useState<string | undefined>()
311
-
312
- // Use external selection if provided, otherwise use internal
313
- const selectedOperationId = externalSelectedId ?? internalSelectedId
314
-
315
- const abortControllerRef = useRef<AbortController | null>(null)
316
- const hasLoadedRef = useRef(false)
317
-
318
- // Load from localStorage on mount
319
- useEffect(() => {
320
- const stored = loadStoredState()
321
- if (stored) {
322
- if (stored.query) setQuery(stored.query)
323
- if (stored.variables) setVariables(stored.variables)
324
- if (stored.headers) setCustomHeaders(stored.headers)
325
- }
326
- hasLoadedRef.current = true
327
- }, [])
328
-
329
- // Save to localStorage when values change
330
- useEffect(() => {
331
- if (!hasLoadedRef.current) return
332
- const timeoutId = setTimeout(() => {
333
- saveStoredState({ query, variables, headers: customHeaders })
334
- }, 500)
335
- return () => clearTimeout(timeoutId)
336
- }, [query, variables, customHeaders])
337
-
338
- // Handle operation selection from sidebar (internal)
339
- const handleSelectOperation = useCallback((operation: GraphQLOperationItem) => {
340
- setQuery(operation.query)
341
- setInternalSelectedId(operation.id)
342
-
343
- // Set example variables if available
344
- if (operation.exampleVariables && Object.keys(operation.exampleVariables).length > 0) {
345
- setVariables(JSON.stringify(operation.exampleVariables, null, 2))
346
- } else {
347
- setVariables('{}')
348
- }
349
-
350
- // Clear previous response
351
- setResponse(null)
352
- setError(null)
353
- setResponseTime(null)
354
- }, [])
355
-
356
- // Sync with external selection (from main sidebar)
357
- useEffect(() => {
358
- if (externalSelectedId && operations.length > 0) {
359
- const op = operations.find(o => o.id === externalSelectedId)
360
- if (op) {
361
- setQuery(op.query)
362
- if (op.exampleVariables && Object.keys(op.exampleVariables).length > 0) {
363
- setVariables(JSON.stringify(op.exampleVariables, null, 2))
364
- } else {
365
- setVariables('{}')
366
- }
367
- setResponse(null)
368
- setError(null)
369
- setResponseTime(null)
370
- }
371
- }
372
- }, [externalSelectedId, operations])
373
-
374
- // Execute GraphQL query
375
- const executeQuery = useCallback(async () => {
376
- setIsLoading(true)
377
- setError(null)
378
- setResponse(null)
379
- setResponseTime(null)
380
-
381
- if (abortControllerRef.current) {
382
- abortControllerRef.current.abort()
383
- }
384
- abortControllerRef.current = new AbortController()
385
-
386
- const startTime = performance.now()
387
-
388
- try {
389
- let parsedVariables = {}
390
- try {
391
- parsedVariables = variables.trim() && variables.trim() !== '{}'
392
- ? JSON.parse(variables)
393
- : {}
394
- } catch {
395
- setError('Invalid JSON in variables')
396
- setIsLoading(false)
397
- return
398
- }
399
-
400
- let parsedHeaders: Record<string, string> = {}
401
- try {
402
- parsedHeaders = customHeaders.trim() && customHeaders.trim() !== '{}'
403
- ? JSON.parse(customHeaders)
404
- : {}
405
- } catch {
406
- setError('Invalid JSON in headers')
407
- setIsLoading(false)
408
- return
409
- }
410
-
411
- const res = await fetch(endpoint, {
412
- method: 'POST',
413
- headers: {
414
- 'Content-Type': 'application/json',
415
- Accept: 'application/json',
416
- ...defaultHeaders,
417
- ...parsedHeaders,
418
- },
419
- body: JSON.stringify({
420
- query,
421
- variables: parsedVariables,
422
- }),
423
- signal: abortControllerRef.current.signal,
424
- })
425
-
426
- const endTime = performance.now()
427
- setResponseTime(Math.round(endTime - startTime))
428
-
429
- const data = await res.json()
430
- setResponse(data)
431
- } catch (err) {
432
- if (err instanceof Error && err.name === 'AbortError') return
433
- setError(err instanceof Error ? err.message : 'Request failed')
434
- } finally {
435
- setIsLoading(false)
436
- }
437
- }, [query, variables, customHeaders, endpoint, defaultHeaders])
438
-
439
- const handleCancel = useCallback(() => {
440
- if (abortControllerRef.current) {
441
- abortControllerRef.current.abort()
442
- abortControllerRef.current = null
443
- }
444
- setIsLoading(false)
445
- }, [])
446
-
447
- useEffect(() => {
448
- const handleKeyDown = (e: KeyboardEvent) => {
449
- if ((e.ctrlKey || e.metaKey) && e.key === 'Enter') {
450
- e.preventDefault()
451
- if (!isLoading) executeQuery()
452
- }
453
- }
454
- window.addEventListener('keydown', handleKeyDown)
455
- return () => window.removeEventListener('keydown', handleKeyDown)
456
- }, [executeQuery, isLoading])
457
-
458
- const copyResponse = useCallback(() => {
459
- if (response) {
460
- navigator.clipboard.writeText(JSON.stringify(response, null, 2))
461
- setCopied(true)
462
- setTimeout(() => setCopied(false), 2000)
463
- }
464
- }, [response])
465
-
466
- const handleReset = useCallback(() => {
467
- setQuery(defaultQuery)
468
- setVariables('{}')
469
- setCustomHeaders(
470
- Object.keys(defaultHeaders).length > 0
471
- ? JSON.stringify(defaultHeaders, null, 2)
472
- : '{}'
473
- )
474
- setResponse(null)
475
- setError(null)
476
- setResponseTime(null)
477
- setInternalSelectedId(undefined)
478
- localStorage.removeItem(STORAGE_KEY)
479
- }, [defaultQuery, defaultHeaders])
480
-
481
- const monacoTheme = theme === 'dark' ? 'vs-dark' : 'vs'
482
- const hasErrors = response?.errors && response.errors.length > 0
483
- const statusColor = hasErrors ? 'text-red-400' : response ? 'text-emerald-400' : 'text-zinc-500'
484
-
485
- return (
486
- <TooltipProvider>
487
- <div className={cn('flex flex-col h-full bg-background', className)}>
488
- {/* Toolbar */}
489
- <div className="flex items-center justify-between gap-2 px-4 py-2 border-b border-border bg-muted/50">
490
- <div className="flex items-center gap-2">
491
- <div className="hidden sm:flex items-center gap-2 px-3 py-1.5 rounded-md bg-background border border-border">
492
- <span className="text-xs font-medium text-emerald-500">POST</span>
493
- <span className="text-xs text-muted-foreground font-mono truncate max-w-[200px] md:max-w-[400px]">
494
- {endpoint}
495
- </span>
496
- </div>
497
- </div>
498
-
499
- <div className="flex items-center gap-2">
500
- <Button
501
- onClick={isLoading ? handleCancel : executeQuery}
502
- variant={isLoading ? 'destructive' : 'default'}
503
- size="sm"
504
- className="px-4"
505
- >
506
- {isLoading ? (
507
- <>
508
- <X className="h-4 w-4 mr-2" weight="bold" />
509
- Cancel
510
- </>
511
- ) : (
512
- <>
513
- <Play className="h-4 w-4 mr-2" weight="fill" />
514
- Run
515
- </>
516
- )}
517
- </Button>
518
-
519
- <Tooltip>
520
- <TooltipTrigger asChild>
521
- <Button variant="outline" size="icon" onClick={handleReset}>
522
- <ArrowClockwise className="h-4 w-4" weight="bold" />
523
- </Button>
524
- </TooltipTrigger>
525
- <TooltipContent>Reset to defaults</TooltipContent>
526
- </Tooltip>
527
- </div>
528
- </div>
529
-
530
- {/* Main Content */}
531
- <div className="flex-1 flex overflow-hidden">
532
- {/* Left Sidebar - Schema Explorer (only shown when not using main sidebar) */}
533
- {!hideExplorer && operations.length > 0 && (
534
- <div className="w-64 flex-shrink-0 hidden md:block">
535
- <SchemaExplorer
536
- operations={operations}
537
- onSelectOperation={handleSelectOperation}
538
- selectedOperationId={selectedOperationId}
539
- />
540
- </div>
541
- )}
542
-
543
- {/* Center & Right - Query/Response */}
544
- <div className="flex-1 flex flex-col lg:flex-row overflow-hidden">
545
- {/* Query editor */}
546
- <div className="flex-1 flex flex-col border-b lg:border-b-0 lg:border-r border-border min-h-[200px] lg:min-h-0">
547
- <div className="flex-1 flex flex-col min-h-0">
548
- <div className="flex items-center px-3 py-2 border-b border-border bg-muted/30">
549
- <FileText className="h-4 w-4 mr-2 text-muted-foreground" />
550
- <span className="text-xs font-medium text-muted-foreground uppercase tracking-wider">
551
- Query
552
- </span>
553
- <span className="ml-auto text-xs text-muted-foreground">
554
- Ctrl+Enter to run
555
- </span>
556
- </div>
557
- <div className="flex-1 min-h-0">
558
- <Editor
559
- height="100%"
560
- language="graphql"
561
- value={query}
562
- onChange={(value) => {
563
- setQuery(value || '')
564
- setInternalSelectedId(undefined) // Clear internal selection when manually editing
565
- }}
566
- theme={monacoTheme}
567
- options={{
568
- minimap: { enabled: false },
569
- scrollBeyondLastLine: false,
570
- fontSize: 13,
571
- fontFamily: "'JetBrains Mono', 'Fira Code', 'SF Mono', Consolas, monospace",
572
- lineNumbers: 'on',
573
- renderLineHighlight: 'line',
574
- scrollbar: { vertical: 'auto', horizontal: 'auto' },
575
- padding: { top: 12, bottom: 12 },
576
- wordWrap: 'on',
577
- automaticLayout: true,
578
- tabSize: 2,
579
- }}
580
- loading={
581
- <div className="flex items-center justify-center h-full text-muted-foreground text-sm">
582
- <Spinner className="w-5 h-5 animate-spin mr-2" />
583
- Loading editor...
584
- </div>
585
- }
586
- />
587
- </div>
588
- </div>
589
-
590
- {/* Variables/Headers tabs */}
591
- <div className="border-t border-border h-[180px] flex flex-col">
592
- <div className="flex border-b border-border bg-muted/30">
593
- <button
594
- onClick={() => setActiveTab('variables')}
595
- className={cn(
596
- 'flex items-center gap-1.5 px-4 py-2 text-xs font-medium uppercase tracking-wider transition-colors',
597
- activeTab === 'variables'
598
- ? 'text-primary border-b-2 border-primary -mb-px bg-background'
599
- : 'text-muted-foreground hover:text-foreground'
600
- )}
601
- >
602
- <BracketsCurly className="h-3.5 w-3.5" />
603
- Variables
604
- </button>
605
- <button
606
- onClick={() => setActiveTab('headers')}
607
- className={cn(
608
- 'flex items-center gap-1.5 px-4 py-2 text-xs font-medium uppercase tracking-wider transition-colors',
609
- activeTab === 'headers'
610
- ? 'text-primary border-b-2 border-primary -mb-px bg-background'
611
- : 'text-muted-foreground hover:text-foreground'
612
- )}
613
- >
614
- <Key className="h-3.5 w-3.5" />
615
- Headers
616
- </button>
617
- </div>
618
- <div className="flex-1 min-h-0">
619
- <Editor
620
- height="100%"
621
- language="json"
622
- value={activeTab === 'variables' ? variables : customHeaders}
623
- onChange={(value) =>
624
- activeTab === 'variables'
625
- ? setVariables(value || '{}')
626
- : setCustomHeaders(value || '{}')
627
- }
628
- theme={monacoTheme}
629
- options={{
630
- minimap: { enabled: false },
631
- scrollBeyondLastLine: false,
632
- fontSize: 13,
633
- fontFamily: "'JetBrains Mono', 'Fira Code', 'SF Mono', Consolas, monospace",
634
- lineNumbers: 'off',
635
- renderLineHighlight: 'none',
636
- scrollbar: { vertical: 'auto', horizontal: 'auto' },
637
- padding: { top: 8, bottom: 8 },
638
- wordWrap: 'on',
639
- automaticLayout: true,
640
- tabSize: 2,
641
- folding: false,
642
- }}
643
- loading={
644
- <div className="flex items-center justify-center h-full text-muted-foreground text-sm">
645
- Loading...
646
- </div>
647
- }
648
- />
649
- </div>
650
- </div>
651
- </div>
652
-
653
- {/* Response */}
654
- <div className="flex-1 flex flex-col min-h-[200px] lg:min-h-0">
655
- <div className="flex items-center justify-between px-3 py-2 border-b border-border bg-muted/30">
656
- <div className="flex items-center gap-3">
657
- <span className="text-xs font-medium text-muted-foreground uppercase tracking-wider">
658
- Response
659
- </span>
660
- {responseTime !== null && (
661
- <span className="text-xs text-muted-foreground">
662
- {responseTime}ms
663
- </span>
664
- )}
665
- {response && (
666
- <span className={cn('text-xs font-medium', statusColor)}>
667
- {hasErrors ? 'Error' : 'Success'}
668
- </span>
669
- )}
670
- </div>
671
- {response && (
672
- <Tooltip>
673
- <TooltipTrigger asChild>
674
- <Button variant="ghost" size="sm" onClick={copyResponse} className="h-7 px-2">
675
- {copied ? (
676
- <>
677
- <Check className="h-3.5 w-3.5 mr-1 text-emerald-500" />
678
- <span className="text-xs">Copied</span>
679
- </>
680
- ) : (
681
- <>
682
- <Copy className="h-3.5 w-3.5 mr-1" />
683
- <span className="text-xs">Copy</span>
684
- </>
685
- )}
686
- </Button>
687
- </TooltipTrigger>
688
- <TooltipContent>Copy response</TooltipContent>
689
- </Tooltip>
690
- )}
691
- </div>
692
- <div className="flex-1 min-h-0 overflow-hidden">
693
- {isLoading ? (
694
- <div className="flex items-center justify-center h-full">
695
- <Spinner className="w-6 h-6 animate-spin text-primary" />
696
- <span className="ml-2 text-sm text-muted-foreground">Executing query...</span>
697
- </div>
698
- ) : error ? (
699
- <div className="p-4">
700
- <div className="p-4 bg-destructive/10 border border-destructive/20 rounded-lg">
701
- <p className="text-destructive text-sm font-mono">{error}</p>
702
- </div>
703
- </div>
704
- ) : response ? (
705
- <Editor
706
- height="100%"
707
- language="json"
708
- value={JSON.stringify(response, null, 2)}
709
- theme={monacoTheme}
710
- options={{
711
- readOnly: true,
712
- minimap: { enabled: false },
713
- scrollBeyondLastLine: false,
714
- fontSize: 13,
715
- fontFamily: "'JetBrains Mono', 'Fira Code', 'SF Mono', Consolas, monospace",
716
- lineNumbers: 'on',
717
- renderLineHighlight: 'none',
718
- scrollbar: { vertical: 'auto', horizontal: 'auto' },
719
- padding: { top: 12, bottom: 12 },
720
- wordWrap: 'on',
721
- automaticLayout: true,
722
- folding: true,
723
- }}
724
- />
725
- ) : (
726
- <div className="flex flex-col items-center justify-center h-full text-muted-foreground">
727
- <Play className="h-12 w-12 mb-3 opacity-20" />
728
- <p className="text-sm">Run a query to see results</p>
729
- <p className="text-xs mt-1 opacity-60">Press Ctrl+Enter or click Run</p>
730
- </div>
731
- )}
732
- </div>
733
- </div>
734
- </div>
735
- </div>
736
- </div>
737
- </TooltipProvider>
738
- )
739
- }
740
-
741
- export function GraphQLPlaygroundWithExplorer(props: GraphQLPlaygroundProps) {
742
- return <GraphQLPlayground {...props} />
743
- }
744
-
745
- export default GraphQLPlayground