@brainfish-ai/devdoc 0.1.42 → 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 (388) hide show
  1. package/dist/cli/commands/dev.js +19 -10
  2. package/package.json +3 -2
  3. package/renderer/app/api/assets/[...path]/route.js +108 -0
  4. package/renderer/app/api/assets/route.js +114 -0
  5. package/renderer/app/api/assets/upload/route.js +163 -0
  6. package/renderer/app/api/auth-schemes/route.js +58 -0
  7. package/renderer/app/api/chat/route.js +759 -0
  8. package/renderer/app/api/codegen/route.js +52 -0
  9. package/renderer/app/api/collections/route.js +675 -0
  10. package/renderer/app/api/debug/route.js +47 -0
  11. package/renderer/app/api/deploy/route.js +199 -0
  12. package/renderer/app/api/device/route.js +36 -0
  13. package/renderer/app/api/docs/route.js +205 -0
  14. package/renderer/app/api/domains/add/route.js +121 -0
  15. package/renderer/app/api/domains/lookup/route.js +43 -0
  16. package/renderer/app/api/domains/remove/route.js +89 -0
  17. package/renderer/app/api/domains/status/route.js +140 -0
  18. package/renderer/app/api/domains/verify/route.js +168 -0
  19. package/renderer/app/api/keys/regenerate/route.js +71 -0
  20. package/renderer/app/api/local-assets/[...path]/route.js +108 -0
  21. package/renderer/app/api/openapi-spec/route.js +73 -0
  22. package/renderer/app/api/projects/[slug]/route.js +129 -0
  23. package/renderer/app/api/projects/[slug]/stats/route.js +80 -0
  24. package/renderer/app/api/projects/register/route.js +176 -0
  25. package/renderer/app/api/proxy/route.js +139 -0
  26. package/renderer/app/api/proxy-stream/route.js +156 -0
  27. package/renderer/app/api/redirects/route.js +35 -0
  28. package/renderer/app/api/schema/route.js +85 -0
  29. package/renderer/app/api/subdomains/check/route.js +158 -0
  30. package/renderer/app/api/suggestions/route.js +175 -0
  31. package/renderer/app/layout.js +47 -0
  32. package/renderer/app/llms-full.txt/route.js +257 -0
  33. package/renderer/app/llms.txt/route.js +219 -0
  34. package/renderer/app/page.js +12 -0
  35. package/renderer/app/robots.txt/route.js +66 -0
  36. package/renderer/app/sitemap.xml/route.js +145 -0
  37. package/renderer/components/docs/index.js +8 -0
  38. package/renderer/components/docs/mdx/accordion.js +113 -0
  39. package/renderer/components/docs/mdx/badge.js +72 -0
  40. package/renderer/components/docs/mdx/callouts.js +137 -0
  41. package/renderer/components/docs/mdx/cards.js +175 -0
  42. package/renderer/components/docs/mdx/changelog.js +100 -0
  43. package/renderer/components/docs/mdx/code-block.js +147 -0
  44. package/renderer/components/docs/mdx/code-group.js +287 -0
  45. package/renderer/components/docs/mdx/file-embeds.js +82 -0
  46. package/renderer/components/docs/mdx/frame.js +59 -0
  47. package/renderer/components/docs/mdx/highlight.js +90 -0
  48. package/renderer/components/docs/mdx/iframe.js +69 -0
  49. package/renderer/components/docs/mdx/image.js +135 -0
  50. package/renderer/components/docs/mdx/index.js +134 -0
  51. package/renderer/components/docs/mdx/landing.js +315 -0
  52. package/renderer/components/docs/mdx/mermaid.js +212 -0
  53. package/renderer/components/docs/mdx/param-field.js +112 -0
  54. package/renderer/components/docs/mdx/steps.js +74 -0
  55. package/renderer/components/docs/mdx/tabs.js +50 -0
  56. package/renderer/components/docs/mdx-renderer.js +77 -0
  57. package/renderer/components/docs/navigation/breadcrumbs.js +64 -0
  58. package/renderer/components/docs/navigation/index.js +6 -0
  59. package/renderer/components/docs/navigation/page-nav.js +57 -0
  60. package/renderer/components/docs/navigation/sidebar.js +375 -0
  61. package/renderer/components/docs/navigation/toc.js +89 -0
  62. package/renderer/components/docs/notice.js +77 -0
  63. package/renderer/components/docs-header.js +202 -0
  64. package/renderer/components/docs-viewer/agent/agent-chat.js +1930 -0
  65. package/renderer/components/docs-viewer/agent/cards/debug-context-card.js +107 -0
  66. package/renderer/components/docs-viewer/agent/cards/endpoint-context-card.js +57 -0
  67. package/renderer/components/docs-viewer/agent/cards/index.js +45 -0
  68. package/renderer/components/docs-viewer/agent/cards/response-options-card.js +154 -0
  69. package/renderer/components/docs-viewer/agent/cards/types.js +22 -0
  70. package/renderer/components/docs-viewer/agent/chat-message.js +2 -0
  71. package/renderer/components/docs-viewer/agent/index.js +4 -0
  72. package/renderer/components/docs-viewer/agent/messages/assistant-message.js +108 -0
  73. package/renderer/components/docs-viewer/agent/messages/chat-message.js +34 -0
  74. package/renderer/components/docs-viewer/agent/messages/index.js +6 -0
  75. package/renderer/components/docs-viewer/agent/messages/tool-call-display.js +1065 -0
  76. package/renderer/components/docs-viewer/agent/messages/types.js +2 -0
  77. package/renderer/components/docs-viewer/agent/messages/typing-indicator.js +26 -0
  78. package/renderer/components/docs-viewer/agent/messages/user-message.js +37 -0
  79. package/renderer/components/docs-viewer/code-editor/{index.tsx → index.js} +1 -1
  80. package/renderer/components/docs-viewer/code-editor/notes-mode.js +1338 -0
  81. package/renderer/components/docs-viewer/content/changelog-page.js +297 -0
  82. package/renderer/components/docs-viewer/content/doc-page.js +264 -0
  83. package/renderer/components/docs-viewer/content/documentation-viewer.js +14 -0
  84. package/renderer/components/docs-viewer/content/index.js +29 -0
  85. package/renderer/components/docs-viewer/content/not-found-page.js +300 -0
  86. package/renderer/components/docs-viewer/content/request-details.js +528 -0
  87. package/renderer/components/docs-viewer/content/sections/auth.js +108 -0
  88. package/renderer/components/docs-viewer/content/sections/body.js +80 -0
  89. package/renderer/components/docs-viewer/content/sections/headers.js +64 -0
  90. package/renderer/components/docs-viewer/content/sections/overview.js +56 -0
  91. package/renderer/components/docs-viewer/content/sections/parameters.js +64 -0
  92. package/renderer/components/docs-viewer/content/sections/responses.js +91 -0
  93. package/renderer/components/docs-viewer/global-auth-modal.js +427 -0
  94. package/renderer/components/docs-viewer/index.js +1552 -0
  95. package/renderer/components/docs-viewer/playground/auth-editor.js +418 -0
  96. package/renderer/components/docs-viewer/playground/body-editor.js +240 -0
  97. package/renderer/components/docs-viewer/playground/code-editor.js +135 -0
  98. package/renderer/components/docs-viewer/playground/code-snippet.js +393 -0
  99. package/renderer/components/docs-viewer/playground/graphql-playground.js +734 -0
  100. package/renderer/components/docs-viewer/playground/index.js +682 -0
  101. package/renderer/components/docs-viewer/playground/key-value-editor.js +317 -0
  102. package/renderer/components/docs-viewer/playground/method-selector.js +65 -0
  103. package/renderer/components/docs-viewer/playground/request-builder.js +181 -0
  104. package/renderer/components/docs-viewer/playground/request-tabs.js +240 -0
  105. package/renderer/components/docs-viewer/playground/response-cards/idle-card.js +42 -0
  106. package/renderer/components/docs-viewer/playground/response-cards/index.js +72 -0
  107. package/renderer/components/docs-viewer/playground/response-cards/loading-card.js +24 -0
  108. package/renderer/components/docs-viewer/playground/response-cards/network-error-card.js +28 -0
  109. package/renderer/components/docs-viewer/playground/response-cards/response-body-card.js +308 -0
  110. package/renderer/components/docs-viewer/playground/response-cards/types.js +9 -0
  111. package/renderer/components/docs-viewer/playground/response-viewer.js +18 -0
  112. package/renderer/components/docs-viewer/search/index.js +2 -0
  113. package/renderer/components/docs-viewer/search/search-dialog.js +367 -0
  114. package/renderer/components/docs-viewer/search/use-search.js +89 -0
  115. package/renderer/components/docs-viewer/shared/markdown-renderer.js +423 -0
  116. package/renderer/components/docs-viewer/shared/method-badge.js +23 -0
  117. package/renderer/components/docs-viewer/shared/schema-viewer.js +321 -0
  118. package/renderer/components/docs-viewer/sidebar/collection-tree.js +222 -0
  119. package/renderer/components/docs-viewer/sidebar/endpoint-options.js +512 -0
  120. package/renderer/components/docs-viewer/sidebar/index.js +196 -0
  121. package/renderer/components/docs-viewer/sidebar/right-sidebar.js +163 -0
  122. package/renderer/components/docs-viewer/sidebar/sidebar-group.js +87 -0
  123. package/renderer/components/docs-viewer/sidebar/sidebar-item.js +172 -0
  124. package/renderer/components/docs-viewer/sidebar/sidebar-section.js +31 -0
  125. package/renderer/components/theme-provider.js +10 -0
  126. package/renderer/components/theme-toggle.js +106 -0
  127. package/renderer/components/ui/badge.js +29 -0
  128. package/renderer/components/ui/button.js +40 -0
  129. package/renderer/components/ui/dialog.js +50 -0
  130. package/renderer/components/ui/dropdown-menu.js +143 -0
  131. package/renderer/components/ui/input.js +12 -0
  132. package/renderer/components/ui/label.js +13 -0
  133. package/renderer/components/ui/navigation-menu.js +83 -0
  134. package/renderer/components/ui/select.js +116 -0
  135. package/renderer/components/ui/spinner.js +92 -0
  136. package/renderer/components/ui/tabs.js +34 -0
  137. package/renderer/components/ui/tooltip.js +43 -0
  138. package/renderer/hooks/use-code-copy.js +76 -0
  139. package/renderer/hooks/use-openapi-title.js +33 -0
  140. package/renderer/lib/api-docs/agent/index.js +4 -0
  141. package/renderer/lib/api-docs/agent/indexer.js +254 -0
  142. package/renderer/lib/api-docs/agent/spec-summary.js +227 -0
  143. package/renderer/lib/api-docs/agent/types.js +5 -0
  144. package/renderer/lib/api-docs/auth/auth-context.js +157 -0
  145. package/renderer/lib/api-docs/auth/auth-storage.js +66 -0
  146. package/renderer/lib/api-docs/auth/crypto.js +64 -0
  147. package/renderer/lib/api-docs/auth/index.js +3 -0
  148. package/renderer/lib/api-docs/code-editor/db.js +145 -0
  149. package/renderer/lib/api-docs/code-editor/hooks.js +254 -0
  150. package/renderer/lib/api-docs/code-editor/{index.ts → index.js} +3 -4
  151. package/renderer/lib/api-docs/code-editor/mode-context.js +154 -0
  152. package/renderer/lib/api-docs/code-editor/types.js +53 -0
  153. package/renderer/lib/api-docs/codegen/definitions.js +258 -0
  154. package/renderer/lib/api-docs/codegen/har.js +171 -0
  155. package/renderer/lib/api-docs/codegen/index.js +118 -0
  156. package/renderer/lib/api-docs/factories.js +136 -0
  157. package/renderer/lib/api-docs/{index.ts → index.js} +5 -10
  158. package/renderer/lib/api-docs/mobile-context.js +79 -0
  159. package/renderer/lib/api-docs/navigation-context.js +62 -0
  160. package/renderer/lib/api-docs/parsers/graphql/index.js +50 -0
  161. package/renderer/lib/api-docs/parsers/graphql/parser.js +350 -0
  162. package/renderer/lib/api-docs/parsers/graphql/transformer.js +215 -0
  163. package/renderer/lib/api-docs/parsers/graphql/types.js +46 -0
  164. package/renderer/lib/api-docs/parsers/openapi/dereferencer.js +43 -0
  165. package/renderer/lib/api-docs/parsers/openapi/extractors/auth.js +486 -0
  166. package/renderer/lib/api-docs/parsers/openapi/extractors/body.js +295 -0
  167. package/renderer/lib/api-docs/parsers/openapi/extractors/index.js +132 -0
  168. package/renderer/lib/api-docs/parsers/openapi/index.js +127 -0
  169. package/renderer/lib/api-docs/parsers/openapi/transformer.js +192 -0
  170. package/renderer/lib/api-docs/parsers/openapi/validator.js +24 -0
  171. package/renderer/lib/api-docs/playground/context.js +65 -0
  172. package/renderer/lib/api-docs/playground/navigation-context.js +74 -0
  173. package/renderer/lib/api-docs/playground/request-builder.js +163 -0
  174. package/renderer/lib/api-docs/playground/request-runner.js +224 -0
  175. package/renderer/lib/api-docs/playground/types.js +5 -0
  176. package/renderer/lib/api-docs/types.js +23 -0
  177. package/renderer/lib/api-docs/utils.js +212 -0
  178. package/renderer/lib/cache.js +157 -0
  179. package/renderer/lib/docs/config/domain-schema.js +161 -0
  180. package/renderer/lib/docs/config/index.js +5 -0
  181. package/renderer/lib/docs/config/loader.js +113 -0
  182. package/renderer/lib/docs/config/schema.js +269 -0
  183. package/renderer/lib/docs/index.js +8 -0
  184. package/renderer/lib/docs/mdx/compiler.js +128 -0
  185. package/renderer/lib/docs/mdx/frontmatter.js +73 -0
  186. package/renderer/lib/docs/mdx/index.js +8 -0
  187. package/renderer/lib/docs/navigation/generator.js +269 -0
  188. package/renderer/lib/docs/navigation/index.js +4 -0
  189. package/renderer/lib/docs/navigation/types.js +9 -0
  190. package/renderer/lib/docs-navigation-context.js +40 -0
  191. package/renderer/lib/multi-tenant/context.js +80 -0
  192. package/renderer/lib/storage/blob.js +767 -0
  193. package/renderer/lib/utils/icons.js +30 -0
  194. package/renderer/lib/utils.js +5 -0
  195. package/renderer/next.config.js +62 -0
  196. package/renderer/tsconfig.json +23 -5
  197. package/renderer/app/api/assets/[...path]/route.ts +0 -123
  198. package/renderer/app/api/assets/route.ts +0 -124
  199. package/renderer/app/api/assets/upload/route.ts +0 -177
  200. package/renderer/app/api/auth-schemes/route.ts +0 -77
  201. package/renderer/app/api/chat/route.ts +0 -858
  202. package/renderer/app/api/codegen/route.ts +0 -72
  203. package/renderer/app/api/collections/route.ts +0 -1002
  204. package/renderer/app/api/debug/route.ts +0 -53
  205. package/renderer/app/api/deploy/route.ts +0 -234
  206. package/renderer/app/api/device/route.ts +0 -42
  207. package/renderer/app/api/docs/route.ts +0 -201
  208. package/renderer/app/api/domains/add/route.ts +0 -132
  209. package/renderer/app/api/domains/lookup/route.ts +0 -43
  210. package/renderer/app/api/domains/remove/route.ts +0 -100
  211. package/renderer/app/api/domains/status/route.ts +0 -158
  212. package/renderer/app/api/domains/verify/route.ts +0 -181
  213. package/renderer/app/api/keys/regenerate/route.ts +0 -80
  214. package/renderer/app/api/local-assets/[...path]/route.ts +0 -122
  215. package/renderer/app/api/openapi-spec/route.ts +0 -151
  216. package/renderer/app/api/projects/[slug]/route.ts +0 -153
  217. package/renderer/app/api/projects/[slug]/stats/route.ts +0 -96
  218. package/renderer/app/api/projects/register/route.ts +0 -152
  219. package/renderer/app/api/proxy/route.ts +0 -149
  220. package/renderer/app/api/proxy-stream/route.ts +0 -168
  221. package/renderer/app/api/redirects/route.ts +0 -47
  222. package/renderer/app/api/schema/route.ts +0 -73
  223. package/renderer/app/api/subdomains/check/route.ts +0 -172
  224. package/renderer/app/api/suggestions/route.ts +0 -144
  225. package/renderer/app/layout.tsx +0 -54
  226. package/renderer/app/llms-full.txt/route.ts +0 -346
  227. package/renderer/app/llms.txt/route.ts +0 -279
  228. package/renderer/app/page.tsx +0 -14
  229. package/renderer/app/robots.txt/route.ts +0 -84
  230. package/renderer/app/sitemap.xml/route.ts +0 -199
  231. package/renderer/components/docs/index.ts +0 -12
  232. package/renderer/components/docs/mdx/accordion.tsx +0 -169
  233. package/renderer/components/docs/mdx/badge.tsx +0 -132
  234. package/renderer/components/docs/mdx/callouts.tsx +0 -154
  235. package/renderer/components/docs/mdx/cards.tsx +0 -241
  236. package/renderer/components/docs/mdx/changelog.tsx +0 -120
  237. package/renderer/components/docs/mdx/code-block.tsx +0 -186
  238. package/renderer/components/docs/mdx/code-group.tsx +0 -421
  239. package/renderer/components/docs/mdx/file-embeds.tsx +0 -105
  240. package/renderer/components/docs/mdx/frame.tsx +0 -112
  241. package/renderer/components/docs/mdx/highlight.tsx +0 -151
  242. package/renderer/components/docs/mdx/iframe.tsx +0 -134
  243. package/renderer/components/docs/mdx/image.tsx +0 -235
  244. package/renderer/components/docs/mdx/index.ts +0 -237
  245. package/renderer/components/docs/mdx/landing.tsx +0 -684
  246. package/renderer/components/docs/mdx/mermaid.tsx +0 -240
  247. package/renderer/components/docs/mdx/param-field.tsx +0 -200
  248. package/renderer/components/docs/mdx/steps.tsx +0 -113
  249. package/renderer/components/docs/mdx/tabs.tsx +0 -86
  250. package/renderer/components/docs/mdx-renderer.tsx +0 -100
  251. package/renderer/components/docs/navigation/breadcrumbs.tsx +0 -76
  252. package/renderer/components/docs/navigation/index.ts +0 -8
  253. package/renderer/components/docs/navigation/page-nav.tsx +0 -64
  254. package/renderer/components/docs/navigation/sidebar.tsx +0 -515
  255. package/renderer/components/docs/navigation/toc.tsx +0 -113
  256. package/renderer/components/docs/notice.tsx +0 -105
  257. package/renderer/components/docs-header.tsx +0 -278
  258. package/renderer/components/docs-viewer/agent/agent-chat.tsx +0 -2076
  259. package/renderer/components/docs-viewer/agent/cards/debug-context-card.tsx +0 -90
  260. package/renderer/components/docs-viewer/agent/cards/endpoint-context-card.tsx +0 -49
  261. package/renderer/components/docs-viewer/agent/cards/index.tsx +0 -50
  262. package/renderer/components/docs-viewer/agent/cards/response-options-card.tsx +0 -212
  263. package/renderer/components/docs-viewer/agent/cards/types.ts +0 -84
  264. package/renderer/components/docs-viewer/agent/chat-message.tsx +0 -17
  265. package/renderer/components/docs-viewer/agent/index.tsx +0 -6
  266. package/renderer/components/docs-viewer/agent/messages/assistant-message.tsx +0 -119
  267. package/renderer/components/docs-viewer/agent/messages/chat-message.tsx +0 -46
  268. package/renderer/components/docs-viewer/agent/messages/index.ts +0 -17
  269. package/renderer/components/docs-viewer/agent/messages/tool-call-display.tsx +0 -721
  270. package/renderer/components/docs-viewer/agent/messages/types.ts +0 -61
  271. package/renderer/components/docs-viewer/agent/messages/typing-indicator.tsx +0 -24
  272. package/renderer/components/docs-viewer/agent/messages/user-message.tsx +0 -51
  273. package/renderer/components/docs-viewer/code-editor/notes-mode.tsx +0 -1283
  274. package/renderer/components/docs-viewer/content/changelog-page.tsx +0 -331
  275. package/renderer/components/docs-viewer/content/doc-page.tsx +0 -367
  276. package/renderer/components/docs-viewer/content/documentation-viewer.tsx +0 -17
  277. package/renderer/components/docs-viewer/content/index.tsx +0 -29
  278. package/renderer/components/docs-viewer/content/not-found-page.tsx +0 -330
  279. package/renderer/components/docs-viewer/content/request-details.tsx +0 -330
  280. package/renderer/components/docs-viewer/content/sections/auth.tsx +0 -69
  281. package/renderer/components/docs-viewer/content/sections/body.tsx +0 -66
  282. package/renderer/components/docs-viewer/content/sections/headers.tsx +0 -43
  283. package/renderer/components/docs-viewer/content/sections/overview.tsx +0 -40
  284. package/renderer/components/docs-viewer/content/sections/parameters.tsx +0 -43
  285. package/renderer/components/docs-viewer/content/sections/responses.tsx +0 -87
  286. package/renderer/components/docs-viewer/global-auth-modal.tsx +0 -352
  287. package/renderer/components/docs-viewer/index.tsx +0 -1670
  288. package/renderer/components/docs-viewer/playground/auth-editor.tsx +0 -280
  289. package/renderer/components/docs-viewer/playground/body-editor.tsx +0 -221
  290. package/renderer/components/docs-viewer/playground/code-editor.tsx +0 -224
  291. package/renderer/components/docs-viewer/playground/code-snippet.tsx +0 -387
  292. package/renderer/components/docs-viewer/playground/graphql-playground.tsx +0 -745
  293. package/renderer/components/docs-viewer/playground/index.tsx +0 -671
  294. package/renderer/components/docs-viewer/playground/key-value-editor.tsx +0 -261
  295. package/renderer/components/docs-viewer/playground/method-selector.tsx +0 -60
  296. package/renderer/components/docs-viewer/playground/request-builder.tsx +0 -179
  297. package/renderer/components/docs-viewer/playground/request-tabs.tsx +0 -237
  298. package/renderer/components/docs-viewer/playground/response-cards/idle-card.tsx +0 -21
  299. package/renderer/components/docs-viewer/playground/response-cards/index.tsx +0 -93
  300. package/renderer/components/docs-viewer/playground/response-cards/loading-card.tsx +0 -16
  301. package/renderer/components/docs-viewer/playground/response-cards/network-error-card.tsx +0 -23
  302. package/renderer/components/docs-viewer/playground/response-cards/response-body-card.tsx +0 -268
  303. package/renderer/components/docs-viewer/playground/response-cards/types.ts +0 -82
  304. package/renderer/components/docs-viewer/playground/response-viewer.tsx +0 -43
  305. package/renderer/components/docs-viewer/search/index.ts +0 -2
  306. package/renderer/components/docs-viewer/search/search-dialog.tsx +0 -331
  307. package/renderer/components/docs-viewer/search/use-search.ts +0 -117
  308. package/renderer/components/docs-viewer/shared/markdown-renderer.tsx +0 -431
  309. package/renderer/components/docs-viewer/shared/method-badge.tsx +0 -41
  310. package/renderer/components/docs-viewer/shared/schema-viewer.tsx +0 -349
  311. package/renderer/components/docs-viewer/sidebar/collection-tree.tsx +0 -259
  312. package/renderer/components/docs-viewer/sidebar/endpoint-options.tsx +0 -316
  313. package/renderer/components/docs-viewer/sidebar/index.tsx +0 -282
  314. package/renderer/components/docs-viewer/sidebar/right-sidebar.tsx +0 -202
  315. package/renderer/components/docs-viewer/sidebar/sidebar-group.tsx +0 -118
  316. package/renderer/components/docs-viewer/sidebar/sidebar-item.tsx +0 -212
  317. package/renderer/components/docs-viewer/sidebar/sidebar-section.tsx +0 -38
  318. package/renderer/components/theme-provider.tsx +0 -11
  319. package/renderer/components/theme-toggle.tsx +0 -76
  320. package/renderer/components/ui/badge.tsx +0 -46
  321. package/renderer/components/ui/button.tsx +0 -59
  322. package/renderer/components/ui/dialog.tsx +0 -118
  323. package/renderer/components/ui/dropdown-menu.tsx +0 -257
  324. package/renderer/components/ui/input.tsx +0 -21
  325. package/renderer/components/ui/label.tsx +0 -24
  326. package/renderer/components/ui/navigation-menu.tsx +0 -168
  327. package/renderer/components/ui/select.tsx +0 -190
  328. package/renderer/components/ui/spinner.tsx +0 -114
  329. package/renderer/components/ui/tabs.tsx +0 -66
  330. package/renderer/components/ui/tooltip.tsx +0 -61
  331. package/renderer/hooks/use-code-copy.ts +0 -88
  332. package/renderer/hooks/use-openapi-title.ts +0 -44
  333. package/renderer/lib/api-docs/agent/index.ts +0 -6
  334. package/renderer/lib/api-docs/agent/indexer.ts +0 -323
  335. package/renderer/lib/api-docs/agent/spec-summary.ts +0 -335
  336. package/renderer/lib/api-docs/agent/types.ts +0 -116
  337. package/renderer/lib/api-docs/auth/auth-context.tsx +0 -225
  338. package/renderer/lib/api-docs/auth/auth-storage.ts +0 -87
  339. package/renderer/lib/api-docs/auth/crypto.ts +0 -89
  340. package/renderer/lib/api-docs/auth/index.ts +0 -4
  341. package/renderer/lib/api-docs/code-editor/db.ts +0 -164
  342. package/renderer/lib/api-docs/code-editor/hooks.ts +0 -266
  343. package/renderer/lib/api-docs/code-editor/mode-context.tsx +0 -207
  344. package/renderer/lib/api-docs/code-editor/types.ts +0 -105
  345. package/renderer/lib/api-docs/codegen/definitions.ts +0 -297
  346. package/renderer/lib/api-docs/codegen/har.ts +0 -251
  347. package/renderer/lib/api-docs/codegen/index.ts +0 -159
  348. package/renderer/lib/api-docs/factories.ts +0 -170
  349. package/renderer/lib/api-docs/mobile-context.tsx +0 -112
  350. package/renderer/lib/api-docs/navigation-context.tsx +0 -88
  351. package/renderer/lib/api-docs/parsers/graphql/README.md +0 -129
  352. package/renderer/lib/api-docs/parsers/graphql/index.ts +0 -91
  353. package/renderer/lib/api-docs/parsers/graphql/parser.ts +0 -491
  354. package/renderer/lib/api-docs/parsers/graphql/transformer.ts +0 -246
  355. package/renderer/lib/api-docs/parsers/graphql/types.ts +0 -283
  356. package/renderer/lib/api-docs/parsers/openapi/README.md +0 -32
  357. package/renderer/lib/api-docs/parsers/openapi/dereferencer.ts +0 -60
  358. package/renderer/lib/api-docs/parsers/openapi/extractors/auth.ts +0 -574
  359. package/renderer/lib/api-docs/parsers/openapi/extractors/body.ts +0 -403
  360. package/renderer/lib/api-docs/parsers/openapi/extractors/index.ts +0 -232
  361. package/renderer/lib/api-docs/parsers/openapi/index.ts +0 -171
  362. package/renderer/lib/api-docs/parsers/openapi/transformer.ts +0 -278
  363. package/renderer/lib/api-docs/parsers/openapi/validator.ts +0 -31
  364. package/renderer/lib/api-docs/playground/context.tsx +0 -107
  365. package/renderer/lib/api-docs/playground/navigation-context.tsx +0 -124
  366. package/renderer/lib/api-docs/playground/request-builder.ts +0 -223
  367. package/renderer/lib/api-docs/playground/request-runner.ts +0 -282
  368. package/renderer/lib/api-docs/playground/types.ts +0 -35
  369. package/renderer/lib/api-docs/types.ts +0 -269
  370. package/renderer/lib/api-docs/utils.ts +0 -311
  371. package/renderer/lib/cache.ts +0 -193
  372. package/renderer/lib/docs/config/domain-schema.ts +0 -260
  373. package/renderer/lib/docs/config/index.ts +0 -43
  374. package/renderer/lib/docs/config/loader.ts +0 -142
  375. package/renderer/lib/docs/config/schema.ts +0 -308
  376. package/renderer/lib/docs/index.ts +0 -12
  377. package/renderer/lib/docs/mdx/compiler.ts +0 -176
  378. package/renderer/lib/docs/mdx/frontmatter.ts +0 -91
  379. package/renderer/lib/docs/mdx/index.ts +0 -26
  380. package/renderer/lib/docs/navigation/generator.ts +0 -348
  381. package/renderer/lib/docs/navigation/index.ts +0 -12
  382. package/renderer/lib/docs/navigation/types.ts +0 -123
  383. package/renderer/lib/docs-navigation-context.tsx +0 -80
  384. package/renderer/lib/multi-tenant/context.ts +0 -105
  385. package/renderer/lib/storage/blob.ts +0 -1083
  386. package/renderer/lib/utils/icons.ts +0 -48
  387. package/renderer/lib/utils.ts +0 -6
  388. package/renderer/next.config.ts +0 -76
@@ -0,0 +1,47 @@
1
+ import { NextResponse } from 'next/server';
2
+ import { headers } from 'next/headers';
3
+ import { getProjectContent, projectExists } from '@/lib/storage/blob';
4
+ /**
5
+ * Debug endpoint to check multi-tenant routing
6
+ *
7
+ * GET /api/debug?slug=acme-api-docs-i2rjwv
8
+ */ export async function GET(request) {
9
+ const headersList = await headers();
10
+ const { searchParams } = new URL(request.url);
11
+ const testSlug = searchParams.get('slug');
12
+ // Collect all headers
13
+ const allHeaders = {};
14
+ headersList.forEach((value, key)=>{
15
+ allHeaders[key] = value;
16
+ });
17
+ // Check for project header
18
+ const projectSlug = headersList.get('x-devdoc-project');
19
+ // Test Blob storage if slug provided
20
+ let blobTest = null;
21
+ if (testSlug) {
22
+ try {
23
+ const exists = await projectExists(testSlug);
24
+ const content = exists ? await getProjectContent(testSlug) : null;
25
+ blobTest = {
26
+ slug: testSlug,
27
+ exists,
28
+ hasContent: !!content,
29
+ filesCount: content?.files?.length || 0,
30
+ projectName: content?.name || null
31
+ };
32
+ } catch (error) {
33
+ blobTest = {
34
+ slug: testSlug,
35
+ error: String(error)
36
+ };
37
+ }
38
+ }
39
+ return NextResponse.json({
40
+ timestamp: new Date().toISOString(),
41
+ host: headersList.get('host'),
42
+ projectSlug,
43
+ hasBlobToken: !!process.env.BLOB_READ_WRITE_TOKEN,
44
+ blobTest,
45
+ headers: allHeaders
46
+ });
47
+ }
@@ -0,0 +1,199 @@
1
+ import { NextResponse } from 'next/server';
2
+ import { storeProjectContent, updateProjectContent, projectExists, generateProjectSlug, generateApiKey, storeProjectApiKey, validateApiKey } from '@/lib/storage/blob';
3
+ import { getProjectUrl, isValidSlug } from '@/lib/multi-tenant/context';
4
+ /**
5
+ * Deploy API - receives content from CLI and stores in Vercel Blob
6
+ *
7
+ * POST /api/deploy
8
+ * Headers:
9
+ * Authorization: Bearer <api_key> // Required for updates
10
+ * Body: {
11
+ * name: string, // Project name from docs.json
12
+ * slug?: string, // Optional: existing slug for updates
13
+ * docsJson: object, // The docs.json configuration
14
+ * files: Array<{ // MDX and other content files
15
+ * path: string,
16
+ * content: string
17
+ * }>
18
+ * }
19
+ */ export async function POST(request) {
20
+ try {
21
+ const body = await request.json();
22
+ // Validate request body
23
+ const { name, slug: existingSlug, docsJson, files } = body;
24
+ if (!name || typeof name !== 'string') {
25
+ return NextResponse.json({
26
+ error: 'Missing or invalid project name'
27
+ }, {
28
+ status: 400
29
+ });
30
+ }
31
+ if (!docsJson || typeof docsJson !== 'object') {
32
+ return NextResponse.json({
33
+ error: 'Missing or invalid docs.json configuration'
34
+ }, {
35
+ status: 400
36
+ });
37
+ }
38
+ if (!files || !Array.isArray(files)) {
39
+ return NextResponse.json({
40
+ error: 'Missing or invalid files array'
41
+ }, {
42
+ status: 400
43
+ });
44
+ }
45
+ // Validate files structure
46
+ const validFiles = [];
47
+ for (const file of files){
48
+ if (!file.path || typeof file.path !== 'string') {
49
+ return NextResponse.json({
50
+ error: `Invalid file entry: missing path`
51
+ }, {
52
+ status: 400
53
+ });
54
+ }
55
+ if (typeof file.content !== 'string') {
56
+ return NextResponse.json({
57
+ error: `Invalid file entry for ${file.path}: content must be a string`
58
+ }, {
59
+ status: 400
60
+ });
61
+ }
62
+ validFiles.push({
63
+ path: file.path,
64
+ content: file.content
65
+ });
66
+ }
67
+ let slug;
68
+ let isUpdate = false;
69
+ let apiKey = null;
70
+ // Check if this is an update to an existing project
71
+ if (existingSlug) {
72
+ if (!isValidSlug(existingSlug)) {
73
+ return NextResponse.json({
74
+ error: 'Invalid project slug format'
75
+ }, {
76
+ status: 400
77
+ });
78
+ }
79
+ const exists = await projectExists(existingSlug);
80
+ if (!exists) {
81
+ return NextResponse.json({
82
+ error: `Project with slug "${existingSlug}" not found`
83
+ }, {
84
+ status: 404
85
+ });
86
+ }
87
+ // For updates, validate API key
88
+ const authHeader = request.headers.get('Authorization');
89
+ const providedKey = authHeader?.replace('Bearer ', '') || body.apiKey;
90
+ if (!providedKey) {
91
+ return NextResponse.json({
92
+ error: 'API key required for project updates. Provide via Authorization header or apiKey field.'
93
+ }, {
94
+ status: 401
95
+ });
96
+ }
97
+ const validatedSlug = await validateApiKey(providedKey);
98
+ if (validatedSlug !== existingSlug) {
99
+ return NextResponse.json({
100
+ error: 'Invalid API key for this project'
101
+ }, {
102
+ status: 403
103
+ });
104
+ }
105
+ slug = existingSlug;
106
+ isUpdate = true;
107
+ } else {
108
+ // Generate a new unique slug
109
+ slug = generateProjectSlug(name);
110
+ // Ensure it doesn't already exist (very unlikely but possible)
111
+ let attempts = 0;
112
+ while(await projectExists(slug) && attempts < 5){
113
+ slug = generateProjectSlug(name);
114
+ attempts++;
115
+ }
116
+ if (attempts >= 5) {
117
+ return NextResponse.json({
118
+ error: 'Failed to generate unique project slug'
119
+ }, {
120
+ status: 500
121
+ });
122
+ }
123
+ // Generate API key for new project
124
+ apiKey = generateApiKey();
125
+ }
126
+ // Store or update content
127
+ let result;
128
+ if (isUpdate) {
129
+ result = await updateProjectContent(slug, docsJson, validFiles);
130
+ } else {
131
+ result = await storeProjectContent(slug, name, docsJson, validFiles);
132
+ // Store the API key for new projects
133
+ if (apiKey) {
134
+ await storeProjectApiKey(slug, apiKey);
135
+ }
136
+ }
137
+ // Build response
138
+ const projectUrl = getProjectUrl(slug);
139
+ // For new projects, include the API key in response
140
+ const response = {
141
+ success: true,
142
+ slug,
143
+ url: projectUrl,
144
+ blobUrl: result.url,
145
+ isUpdate,
146
+ filesCount: validFiles.length
147
+ };
148
+ if (apiKey) {
149
+ response.apiKey = apiKey;
150
+ }
151
+ return NextResponse.json(response);
152
+ } catch (error) {
153
+ console.error('[Deploy API] Error:', error);
154
+ const message = error instanceof Error ? error.message : String(error);
155
+ // Provide clearer error messages for common issues
156
+ let userMessage = 'Deployment failed';
157
+ if (message.includes('blob already exists')) {
158
+ userMessage = 'Storage conflict - please try again';
159
+ } else if (message.includes('network') || message.includes('fetch')) {
160
+ userMessage = 'Network error connecting to storage';
161
+ } else if (message.includes('unauthorized') || message.includes('401')) {
162
+ userMessage = 'Authentication failed';
163
+ }
164
+ return NextResponse.json({
165
+ error: userMessage,
166
+ details: message
167
+ }, {
168
+ status: 500
169
+ });
170
+ }
171
+ }
172
+ /**
173
+ * GET /api/deploy - Check deployment status or get project info
174
+ */ export async function GET(request) {
175
+ const { searchParams } = new URL(request.url);
176
+ const slug = searchParams.get('slug');
177
+ if (!slug) {
178
+ return NextResponse.json({
179
+ error: 'Missing slug parameter'
180
+ }, {
181
+ status: 400
182
+ });
183
+ }
184
+ const exists = await projectExists(slug);
185
+ if (!exists) {
186
+ return NextResponse.json({
187
+ exists: false,
188
+ slug
189
+ }, {
190
+ status: 404
191
+ });
192
+ }
193
+ const projectUrl = getProjectUrl(slug);
194
+ return NextResponse.json({
195
+ exists: true,
196
+ slug,
197
+ url: projectUrl
198
+ });
199
+ }
@@ -0,0 +1,36 @@
1
+ import { NextResponse } from 'next/server';
2
+ import { cookies } from 'next/headers';
3
+ const DEVICE_COOKIE_NAME = 'bf_device_id';
4
+ const COOKIE_MAX_AGE = 60 * 60 * 24 * 365 // 1 year
5
+ ;
6
+ /**
7
+ * Generate a unique device ID
8
+ * Uses crypto.randomUUID for secure random generation
9
+ */ function generateDeviceId() {
10
+ return crypto.randomUUID();
11
+ }
12
+ /**
13
+ * GET /api/device
14
+ * Returns or creates a unique device ID for the client
15
+ * The device ID is stored in an httpOnly cookie for security
16
+ */ export async function GET() {
17
+ const cookieStore = await cookies();
18
+ let deviceId = cookieStore.get(DEVICE_COOKIE_NAME)?.value;
19
+ // Generate new device ID if not exists
20
+ if (!deviceId) {
21
+ deviceId = generateDeviceId();
22
+ }
23
+ // Create response with device ID
24
+ const response = NextResponse.json({
25
+ deviceId
26
+ });
27
+ // Set/refresh the httpOnly cookie
28
+ response.cookies.set(DEVICE_COOKIE_NAME, deviceId, {
29
+ httpOnly: true,
30
+ secure: process.env.NODE_ENV === 'production',
31
+ sameSite: 'strict',
32
+ maxAge: COOKIE_MAX_AGE,
33
+ path: '/'
34
+ });
35
+ return response;
36
+ }
@@ -0,0 +1,205 @@
1
+ import { NextResponse } from 'next/server';
2
+ import { readFileSync, existsSync } from 'fs';
3
+ import { join, isAbsolute } from 'path';
4
+ import matter from 'gray-matter';
5
+ import { serialize } from 'next-mdx-remote/serialize';
6
+ import remarkGfm from 'remark-gfm';
7
+ import rehypeSlug from 'rehype-slug';
8
+ // Note: rehype-pretty-code is dynamically imported to handle serverless environments
9
+ // where shiki may not be fully available
10
+ import { getProjectFile } from '@/lib/storage/blob';
11
+ const STARTER_PATH = process.env.STARTER_PATH || 'devdoc-docs';
12
+ // Helper to get content root - supports both relative and absolute paths
13
+ function getContentRoot() {
14
+ if (isAbsolute(STARTER_PATH)) {
15
+ return STARTER_PATH;
16
+ }
17
+ return join(process.cwd(), STARTER_PATH);
18
+ }
19
+ // Shiki theme options for syntax highlighting
20
+ const prettyCodeOptions = {
21
+ theme: 'github-dark',
22
+ keepBackground: true,
23
+ defaultLang: 'plaintext'
24
+ };
25
+ export async function GET(request) {
26
+ const searchParams = request.nextUrl.searchParams;
27
+ const slug = searchParams.get('slug');
28
+ const is404Request = searchParams.get('is404') === 'true';
29
+ if (!slug) {
30
+ return NextResponse.json({
31
+ error: 'Missing slug parameter'
32
+ }, {
33
+ status: 400
34
+ });
35
+ }
36
+ // Check for multi-tenant mode (project slug from middleware)
37
+ const projectSlug = request.headers.get('x-devdoc-project');
38
+ // If multi-tenant, fetch from Blob Storage
39
+ if (projectSlug && !projectSlug.startsWith('custom:')) {
40
+ return handleMultiTenantDocs(projectSlug, slug, is404Request);
41
+ }
42
+ try {
43
+ const starterDir = getContentRoot();
44
+ // Try .mdx then .md
45
+ let fullPath = join(starterDir, `${slug}.mdx`);
46
+ if (!existsSync(fullPath)) {
47
+ fullPath = join(starterDir, `${slug}.md`);
48
+ }
49
+ if (!existsSync(fullPath)) {
50
+ // For 404 page requests, return 404 status (not a server error)
51
+ // The client will handle showing the default 404 if custom doesn't exist
52
+ return NextResponse.json({
53
+ error: 'Page not found'
54
+ }, {
55
+ status: 404
56
+ });
57
+ }
58
+ const fileContent = readFileSync(fullPath, 'utf-8');
59
+ const { data: frontmatter, content } = matter(fileContent);
60
+ // Serialize MDX for client-side rendering
61
+ // Note: rehype-pretty-code is dynamically imported to handle cases where shiki
62
+ // may not be available in serverless environments
63
+ let mdxSource;
64
+ try {
65
+ // Try with syntax highlighting first
66
+ const rehypePrettyCodeModule = await import('rehype-pretty-code');
67
+ const rehypePrettyCode = rehypePrettyCodeModule.default;
68
+ mdxSource = await serialize(content, {
69
+ mdxOptions: {
70
+ remarkPlugins: [
71
+ remarkGfm
72
+ ],
73
+ rehypePlugins: [
74
+ rehypeSlug,
75
+ [
76
+ rehypePrettyCode,
77
+ prettyCodeOptions
78
+ ]
79
+ ]
80
+ },
81
+ parseFrontmatter: false
82
+ });
83
+ } catch (syntaxError) {
84
+ // Fallback: serialize without syntax highlighting if shiki is unavailable
85
+ console.warn('[Docs API] Syntax highlighting unavailable, using fallback:', syntaxError);
86
+ mdxSource = await serialize(content, {
87
+ mdxOptions: {
88
+ remarkPlugins: [
89
+ remarkGfm
90
+ ],
91
+ rehypePlugins: [
92
+ rehypeSlug
93
+ ]
94
+ },
95
+ parseFrontmatter: false
96
+ });
97
+ }
98
+ return NextResponse.json({
99
+ slug,
100
+ frontmatter: {
101
+ title: frontmatter.title || slug,
102
+ description: frontmatter.description,
103
+ icon: frontmatter.icon,
104
+ // Page mode and layout options
105
+ mode: frontmatter.mode || 'default',
106
+ hideHeader: frontmatter.hideHeader || false,
107
+ fullWidth: frontmatter.fullWidth || false,
108
+ background: frontmatter.background
109
+ },
110
+ mdxSource,
111
+ rawContent: content
112
+ });
113
+ } catch (error) {
114
+ console.error('[Docs API] Error loading page:', error);
115
+ return NextResponse.json({
116
+ error: 'Failed to load page',
117
+ details: error instanceof Error ? error.message : String(error)
118
+ }, {
119
+ status: 500
120
+ });
121
+ }
122
+ }
123
+ /**
124
+ * Handle multi-tenant docs request - fetch from Blob Storage
125
+ */ async function handleMultiTenantDocs(projectSlug, slug, is404Request = false) {
126
+ try {
127
+ // Try .mdx then .md
128
+ let fileContent = await getProjectFile(projectSlug, `${slug}.mdx`);
129
+ if (!fileContent) {
130
+ fileContent = await getProjectFile(projectSlug, `${slug}.md`);
131
+ }
132
+ if (!fileContent) {
133
+ // For 404 page requests, return 404 status
134
+ return NextResponse.json({
135
+ error: 'Page not found'
136
+ }, {
137
+ status: 404
138
+ });
139
+ }
140
+ const { data: frontmatter, content } = matter(fileContent);
141
+ // Serialize MDX for client-side rendering
142
+ // Note: rehype-pretty-code is dynamically imported to handle cases where shiki
143
+ // may not be available in serverless environments
144
+ let mdxSource;
145
+ try {
146
+ // Try with syntax highlighting first
147
+ const rehypePrettyCodeModule = await import('rehype-pretty-code');
148
+ const rehypePrettyCode = rehypePrettyCodeModule.default;
149
+ mdxSource = await serialize(content, {
150
+ mdxOptions: {
151
+ remarkPlugins: [
152
+ remarkGfm
153
+ ],
154
+ rehypePlugins: [
155
+ rehypeSlug,
156
+ [
157
+ rehypePrettyCode,
158
+ prettyCodeOptions
159
+ ]
160
+ ]
161
+ },
162
+ parseFrontmatter: false
163
+ });
164
+ } catch (syntaxError) {
165
+ // Fallback: serialize without syntax highlighting if shiki is unavailable
166
+ console.warn('[Docs API] Multi-tenant syntax highlighting unavailable:', syntaxError);
167
+ mdxSource = await serialize(content, {
168
+ mdxOptions: {
169
+ remarkPlugins: [
170
+ remarkGfm
171
+ ],
172
+ rehypePlugins: [
173
+ rehypeSlug
174
+ ]
175
+ },
176
+ parseFrontmatter: false
177
+ });
178
+ }
179
+ return NextResponse.json({
180
+ slug,
181
+ frontmatter: {
182
+ title: frontmatter.title || slug,
183
+ description: frontmatter.description,
184
+ icon: frontmatter.icon,
185
+ // Page mode and layout options
186
+ mode: frontmatter.mode || 'default',
187
+ hideHeader: frontmatter.hideHeader || false,
188
+ fullWidth: frontmatter.fullWidth || false,
189
+ background: frontmatter.background
190
+ },
191
+ mdxSource,
192
+ rawContent: content,
193
+ isMultiTenant: true,
194
+ projectSlug
195
+ });
196
+ } catch (error) {
197
+ console.error('[Docs API] Multi-tenant error:', error);
198
+ return NextResponse.json({
199
+ error: 'Failed to load page',
200
+ details: error instanceof Error ? error.message : String(error)
201
+ }, {
202
+ status: 500
203
+ });
204
+ }
205
+ }
@@ -0,0 +1,121 @@
1
+ import { NextResponse } from 'next/server';
2
+ import { validateApiKey, addCustomDomain, isCustomDomainRegistered } from '@/lib/storage/blob';
3
+ import { isValidDomain, normalizeDomain, getDnsInstructions } from '@/lib/docs/config';
4
+ /**
5
+ * POST /api/domains/add
6
+ *
7
+ * Add a custom domain to a project.
8
+ * Each project can have ONE custom domain (free).
9
+ *
10
+ * Headers:
11
+ * Authorization: Bearer <api_key>
12
+ *
13
+ * Body:
14
+ * { customDomain: "docs.example.com" }
15
+ *
16
+ * Response:
17
+ * {
18
+ * success: true,
19
+ * domain: "docs.example.com",
20
+ * status: "pending",
21
+ * verification: {
22
+ * cname: { name: "docs", value: "cname.devdoc-dns.com" },
23
+ * txt: { name: "_devdoc-verify.docs.example.com", value: "devdoc-verify=xxx" }
24
+ * }
25
+ * }
26
+ */ export async function POST(request) {
27
+ try {
28
+ // Validate API key
29
+ const authHeader = request.headers.get('Authorization');
30
+ const apiKey = authHeader?.replace('Bearer ', '');
31
+ if (!apiKey) {
32
+ return NextResponse.json({
33
+ error: 'API key required. Provide via Authorization header.'
34
+ }, {
35
+ status: 401
36
+ });
37
+ }
38
+ const projectSlug = await validateApiKey(apiKey);
39
+ if (!projectSlug) {
40
+ return NextResponse.json({
41
+ error: 'Invalid API key'
42
+ }, {
43
+ status: 403
44
+ });
45
+ }
46
+ // Parse request body
47
+ const body = await request.json();
48
+ const { customDomain: rawDomain } = body;
49
+ if (!rawDomain || typeof rawDomain !== 'string') {
50
+ return NextResponse.json({
51
+ error: 'Missing customDomain in request body'
52
+ }, {
53
+ status: 400
54
+ });
55
+ }
56
+ // Normalize and validate domain
57
+ const customDomain = normalizeDomain(rawDomain);
58
+ const validation = isValidDomain(customDomain);
59
+ if (!validation.valid) {
60
+ return NextResponse.json({
61
+ error: validation.error
62
+ }, {
63
+ status: 400
64
+ });
65
+ }
66
+ // Check if domain is already registered
67
+ const isRegistered = await isCustomDomainRegistered(customDomain);
68
+ if (isRegistered) {
69
+ return NextResponse.json({
70
+ error: `Domain ${customDomain} is already registered to another project.`
71
+ }, {
72
+ status: 409
73
+ });
74
+ }
75
+ // Add the custom domain
76
+ const result = await addCustomDomain(projectSlug, customDomain);
77
+ if (!result.success) {
78
+ return NextResponse.json({
79
+ error: result.error
80
+ }, {
81
+ status: 400
82
+ });
83
+ }
84
+ // Get DNS instructions
85
+ const dnsInstructions = getDnsInstructions(customDomain);
86
+ // Add verification token to TXT record
87
+ dnsInstructions.txt.value = result.entry.verificationToken || '';
88
+ return NextResponse.json({
89
+ success: true,
90
+ domain: customDomain,
91
+ projectSlug,
92
+ status: result.entry.status,
93
+ verification: {
94
+ cname: dnsInstructions.cname,
95
+ txt: dnsInstructions.txt
96
+ },
97
+ instructions: [
98
+ 'Add the following DNS records to your domain:',
99
+ '',
100
+ `1. CNAME Record:`,
101
+ ` Name: ${dnsInstructions.cname.name}`,
102
+ ` Value: ${dnsInstructions.cname.value}`,
103
+ '',
104
+ `2. TXT Record (for verification):`,
105
+ ` Name: ${dnsInstructions.txt.name}`,
106
+ ` Value: ${dnsInstructions.txt.value}`,
107
+ '',
108
+ 'After adding DNS records, run "devdoc domain verify" to verify.'
109
+ ]
110
+ });
111
+ } catch (error) {
112
+ console.error('[Domains API] Error adding domain:', error);
113
+ const message = error instanceof Error ? error.message : String(error);
114
+ return NextResponse.json({
115
+ error: 'Failed to add domain',
116
+ details: message
117
+ }, {
118
+ status: 500
119
+ });
120
+ }
121
+ }
@@ -0,0 +1,43 @@
1
+ import { NextResponse } from 'next/server';
2
+ import { lookupCustomDomain } from '@/lib/storage/blob';
3
+ /**
4
+ * GET /api/domains/lookup
5
+ *
6
+ * Internal API for middleware to look up custom domains.
7
+ * Returns the project slug for an active custom domain.
8
+ *
9
+ * Query:
10
+ * ?domain=docs.example.com
11
+ *
12
+ * Response:
13
+ * { found: true, projectSlug: "my-project" }
14
+ * or
15
+ * { found: false }
16
+ */ export async function GET(request) {
17
+ try {
18
+ const { searchParams } = new URL(request.url);
19
+ const domain = searchParams.get('domain');
20
+ if (!domain) {
21
+ return NextResponse.json({
22
+ found: false,
23
+ error: 'Missing domain parameter'
24
+ });
25
+ }
26
+ const entry = await lookupCustomDomain(domain);
27
+ if (entry) {
28
+ return NextResponse.json({
29
+ found: true,
30
+ projectSlug: entry.projectSlug,
31
+ status: entry.status
32
+ });
33
+ }
34
+ return NextResponse.json({
35
+ found: false
36
+ });
37
+ } catch (error) {
38
+ console.error('[Domains Lookup] Error:', error);
39
+ return NextResponse.json({
40
+ found: false
41
+ });
42
+ }
43
+ }