@brainfish-ai/devdoc 0.1.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (268) hide show
  1. package/LICENSE +33 -0
  2. package/README.md +415 -0
  3. package/bin/devdoc.js +13 -0
  4. package/dist/cli/commands/build.d.ts +5 -0
  5. package/dist/cli/commands/build.js +87 -0
  6. package/dist/cli/commands/check.d.ts +1 -0
  7. package/dist/cli/commands/check.js +143 -0
  8. package/dist/cli/commands/create.d.ts +24 -0
  9. package/dist/cli/commands/create.js +387 -0
  10. package/dist/cli/commands/deploy.d.ts +9 -0
  11. package/dist/cli/commands/deploy.js +433 -0
  12. package/dist/cli/commands/dev.d.ts +6 -0
  13. package/dist/cli/commands/dev.js +139 -0
  14. package/dist/cli/commands/init.d.ts +11 -0
  15. package/dist/cli/commands/init.js +238 -0
  16. package/dist/cli/commands/keys.d.ts +12 -0
  17. package/dist/cli/commands/keys.js +165 -0
  18. package/dist/cli/commands/start.d.ts +5 -0
  19. package/dist/cli/commands/start.js +56 -0
  20. package/dist/cli/commands/upload.d.ts +13 -0
  21. package/dist/cli/commands/upload.js +238 -0
  22. package/dist/cli/commands/whoami.d.ts +8 -0
  23. package/dist/cli/commands/whoami.js +91 -0
  24. package/dist/cli/index.d.ts +1 -0
  25. package/dist/cli/index.js +106 -0
  26. package/dist/config/index.d.ts +80 -0
  27. package/dist/config/index.js +133 -0
  28. package/dist/constants.d.ts +9 -0
  29. package/dist/constants.js +13 -0
  30. package/dist/index.d.ts +7 -0
  31. package/dist/index.js +12 -0
  32. package/dist/utils/logger.d.ts +16 -0
  33. package/dist/utils/logger.js +61 -0
  34. package/dist/utils/paths.d.ts +16 -0
  35. package/dist/utils/paths.js +50 -0
  36. package/package.json +51 -0
  37. package/renderer/app/api/assets/[...path]/route.ts +123 -0
  38. package/renderer/app/api/assets/route.ts +124 -0
  39. package/renderer/app/api/assets/upload/route.ts +177 -0
  40. package/renderer/app/api/auth-schemes/route.ts +77 -0
  41. package/renderer/app/api/chat/route.ts +858 -0
  42. package/renderer/app/api/codegen/route.ts +72 -0
  43. package/renderer/app/api/collections/route.ts +1016 -0
  44. package/renderer/app/api/debug/route.ts +53 -0
  45. package/renderer/app/api/deploy/route.ts +234 -0
  46. package/renderer/app/api/device/route.ts +42 -0
  47. package/renderer/app/api/docs/route.ts +187 -0
  48. package/renderer/app/api/keys/regenerate/route.ts +80 -0
  49. package/renderer/app/api/openapi-spec/route.ts +151 -0
  50. package/renderer/app/api/projects/[slug]/route.ts +153 -0
  51. package/renderer/app/api/projects/[slug]/stats/route.ts +96 -0
  52. package/renderer/app/api/projects/register/route.ts +152 -0
  53. package/renderer/app/api/proxy/route.ts +149 -0
  54. package/renderer/app/api/proxy-stream/route.ts +168 -0
  55. package/renderer/app/api/redirects/route.ts +47 -0
  56. package/renderer/app/api/schema/route.ts +65 -0
  57. package/renderer/app/api/subdomains/check/route.ts +172 -0
  58. package/renderer/app/api/suggestions/route.ts +144 -0
  59. package/renderer/app/favicon.ico +0 -0
  60. package/renderer/app/globals.css +1103 -0
  61. package/renderer/app/layout.tsx +47 -0
  62. package/renderer/app/llms-full.txt/route.ts +346 -0
  63. package/renderer/app/llms.txt/route.ts +279 -0
  64. package/renderer/app/page.tsx +14 -0
  65. package/renderer/app/robots.txt/route.ts +84 -0
  66. package/renderer/app/sitemap.xml/route.ts +199 -0
  67. package/renderer/components/docs/index.ts +12 -0
  68. package/renderer/components/docs/mdx/accordion.tsx +169 -0
  69. package/renderer/components/docs/mdx/badge.tsx +132 -0
  70. package/renderer/components/docs/mdx/callouts.tsx +154 -0
  71. package/renderer/components/docs/mdx/cards.tsx +213 -0
  72. package/renderer/components/docs/mdx/changelog.tsx +120 -0
  73. package/renderer/components/docs/mdx/code-block.tsx +186 -0
  74. package/renderer/components/docs/mdx/code-group.tsx +421 -0
  75. package/renderer/components/docs/mdx/file-embeds.tsx +105 -0
  76. package/renderer/components/docs/mdx/frame.tsx +112 -0
  77. package/renderer/components/docs/mdx/highlight.tsx +151 -0
  78. package/renderer/components/docs/mdx/iframe.tsx +134 -0
  79. package/renderer/components/docs/mdx/image.tsx +235 -0
  80. package/renderer/components/docs/mdx/index.ts +204 -0
  81. package/renderer/components/docs/mdx/mermaid.tsx +240 -0
  82. package/renderer/components/docs/mdx/param-field.tsx +200 -0
  83. package/renderer/components/docs/mdx/steps.tsx +113 -0
  84. package/renderer/components/docs/mdx/tabs.tsx +86 -0
  85. package/renderer/components/docs/mdx-renderer.tsx +100 -0
  86. package/renderer/components/docs/navigation/breadcrumbs.tsx +76 -0
  87. package/renderer/components/docs/navigation/index.ts +8 -0
  88. package/renderer/components/docs/navigation/page-nav.tsx +64 -0
  89. package/renderer/components/docs/navigation/sidebar.tsx +515 -0
  90. package/renderer/components/docs/navigation/toc.tsx +113 -0
  91. package/renderer/components/docs/notice.tsx +105 -0
  92. package/renderer/components/docs-header.tsx +274 -0
  93. package/renderer/components/docs-viewer/agent/agent-chat.tsx +2076 -0
  94. package/renderer/components/docs-viewer/agent/cards/debug-context-card.tsx +90 -0
  95. package/renderer/components/docs-viewer/agent/cards/endpoint-context-card.tsx +49 -0
  96. package/renderer/components/docs-viewer/agent/cards/index.tsx +50 -0
  97. package/renderer/components/docs-viewer/agent/cards/response-options-card.tsx +212 -0
  98. package/renderer/components/docs-viewer/agent/cards/types.ts +84 -0
  99. package/renderer/components/docs-viewer/agent/chat-message.tsx +17 -0
  100. package/renderer/components/docs-viewer/agent/index.tsx +6 -0
  101. package/renderer/components/docs-viewer/agent/messages/assistant-message.tsx +119 -0
  102. package/renderer/components/docs-viewer/agent/messages/chat-message.tsx +46 -0
  103. package/renderer/components/docs-viewer/agent/messages/index.ts +17 -0
  104. package/renderer/components/docs-viewer/agent/messages/tool-call-display.tsx +721 -0
  105. package/renderer/components/docs-viewer/agent/messages/types.ts +61 -0
  106. package/renderer/components/docs-viewer/agent/messages/typing-indicator.tsx +24 -0
  107. package/renderer/components/docs-viewer/agent/messages/user-message.tsx +51 -0
  108. package/renderer/components/docs-viewer/code-editor/index.tsx +2 -0
  109. package/renderer/components/docs-viewer/code-editor/notes-mode.tsx +1283 -0
  110. package/renderer/components/docs-viewer/content/changelog-page.tsx +331 -0
  111. package/renderer/components/docs-viewer/content/doc-page.tsx +285 -0
  112. package/renderer/components/docs-viewer/content/documentation-viewer.tsx +17 -0
  113. package/renderer/components/docs-viewer/content/index.tsx +29 -0
  114. package/renderer/components/docs-viewer/content/introduction.tsx +21 -0
  115. package/renderer/components/docs-viewer/content/request-details.tsx +330 -0
  116. package/renderer/components/docs-viewer/content/sections/auth.tsx +69 -0
  117. package/renderer/components/docs-viewer/content/sections/body.tsx +66 -0
  118. package/renderer/components/docs-viewer/content/sections/headers.tsx +43 -0
  119. package/renderer/components/docs-viewer/content/sections/overview.tsx +40 -0
  120. package/renderer/components/docs-viewer/content/sections/parameters.tsx +43 -0
  121. package/renderer/components/docs-viewer/content/sections/responses.tsx +87 -0
  122. package/renderer/components/docs-viewer/global-auth-modal.tsx +352 -0
  123. package/renderer/components/docs-viewer/index.tsx +1466 -0
  124. package/renderer/components/docs-viewer/playground/auth-editor.tsx +280 -0
  125. package/renderer/components/docs-viewer/playground/body-editor.tsx +221 -0
  126. package/renderer/components/docs-viewer/playground/code-editor.tsx +224 -0
  127. package/renderer/components/docs-viewer/playground/code-snippet.tsx +387 -0
  128. package/renderer/components/docs-viewer/playground/graphql-playground.tsx +745 -0
  129. package/renderer/components/docs-viewer/playground/index.tsx +671 -0
  130. package/renderer/components/docs-viewer/playground/key-value-editor.tsx +261 -0
  131. package/renderer/components/docs-viewer/playground/method-selector.tsx +60 -0
  132. package/renderer/components/docs-viewer/playground/request-builder.tsx +179 -0
  133. package/renderer/components/docs-viewer/playground/request-tabs.tsx +237 -0
  134. package/renderer/components/docs-viewer/playground/response-cards/idle-card.tsx +21 -0
  135. package/renderer/components/docs-viewer/playground/response-cards/index.tsx +93 -0
  136. package/renderer/components/docs-viewer/playground/response-cards/loading-card.tsx +16 -0
  137. package/renderer/components/docs-viewer/playground/response-cards/network-error-card.tsx +23 -0
  138. package/renderer/components/docs-viewer/playground/response-cards/response-body-card.tsx +268 -0
  139. package/renderer/components/docs-viewer/playground/response-cards/types.ts +82 -0
  140. package/renderer/components/docs-viewer/playground/response-viewer.tsx +43 -0
  141. package/renderer/components/docs-viewer/search/index.ts +2 -0
  142. package/renderer/components/docs-viewer/search/search-dialog.tsx +331 -0
  143. package/renderer/components/docs-viewer/search/use-search.ts +117 -0
  144. package/renderer/components/docs-viewer/shared/markdown-renderer.tsx +431 -0
  145. package/renderer/components/docs-viewer/shared/method-badge.tsx +41 -0
  146. package/renderer/components/docs-viewer/shared/schema-viewer.tsx +349 -0
  147. package/renderer/components/docs-viewer/sidebar/collection-tree.tsx +239 -0
  148. package/renderer/components/docs-viewer/sidebar/endpoint-options.tsx +316 -0
  149. package/renderer/components/docs-viewer/sidebar/index.tsx +343 -0
  150. package/renderer/components/docs-viewer/sidebar/right-sidebar.tsx +202 -0
  151. package/renderer/components/docs-viewer/sidebar/sidebar-group.tsx +118 -0
  152. package/renderer/components/docs-viewer/sidebar/sidebar-item.tsx +226 -0
  153. package/renderer/components/docs-viewer/sidebar/sidebar-section.tsx +52 -0
  154. package/renderer/components/theme-provider.tsx +11 -0
  155. package/renderer/components/theme-toggle.tsx +76 -0
  156. package/renderer/components/ui/badge.tsx +46 -0
  157. package/renderer/components/ui/button.tsx +59 -0
  158. package/renderer/components/ui/dialog.tsx +118 -0
  159. package/renderer/components/ui/dropdown-menu.tsx +257 -0
  160. package/renderer/components/ui/input.tsx +21 -0
  161. package/renderer/components/ui/label.tsx +24 -0
  162. package/renderer/components/ui/navigation-menu.tsx +168 -0
  163. package/renderer/components/ui/select.tsx +190 -0
  164. package/renderer/components/ui/spinner.tsx +114 -0
  165. package/renderer/components/ui/tabs.tsx +66 -0
  166. package/renderer/components/ui/tooltip.tsx +61 -0
  167. package/renderer/hooks/use-code-copy.ts +88 -0
  168. package/renderer/hooks/use-openapi-title.ts +44 -0
  169. package/renderer/lib/api-docs/agent/index.ts +6 -0
  170. package/renderer/lib/api-docs/agent/indexer.ts +323 -0
  171. package/renderer/lib/api-docs/agent/spec-summary.ts +335 -0
  172. package/renderer/lib/api-docs/agent/types.ts +116 -0
  173. package/renderer/lib/api-docs/auth/auth-context.tsx +225 -0
  174. package/renderer/lib/api-docs/auth/auth-storage.ts +87 -0
  175. package/renderer/lib/api-docs/auth/crypto.ts +89 -0
  176. package/renderer/lib/api-docs/auth/index.ts +4 -0
  177. package/renderer/lib/api-docs/code-editor/db.ts +164 -0
  178. package/renderer/lib/api-docs/code-editor/hooks.ts +266 -0
  179. package/renderer/lib/api-docs/code-editor/index.ts +6 -0
  180. package/renderer/lib/api-docs/code-editor/mode-context.tsx +207 -0
  181. package/renderer/lib/api-docs/code-editor/types.ts +105 -0
  182. package/renderer/lib/api-docs/codegen/definitions.ts +297 -0
  183. package/renderer/lib/api-docs/codegen/har.ts +251 -0
  184. package/renderer/lib/api-docs/codegen/index.ts +159 -0
  185. package/renderer/lib/api-docs/factories.ts +151 -0
  186. package/renderer/lib/api-docs/index.ts +17 -0
  187. package/renderer/lib/api-docs/mobile-context.tsx +112 -0
  188. package/renderer/lib/api-docs/navigation-context.tsx +88 -0
  189. package/renderer/lib/api-docs/parsers/graphql/README.md +129 -0
  190. package/renderer/lib/api-docs/parsers/graphql/index.ts +91 -0
  191. package/renderer/lib/api-docs/parsers/graphql/parser.ts +491 -0
  192. package/renderer/lib/api-docs/parsers/graphql/transformer.ts +246 -0
  193. package/renderer/lib/api-docs/parsers/graphql/types.ts +283 -0
  194. package/renderer/lib/api-docs/parsers/openapi/README.md +32 -0
  195. package/renderer/lib/api-docs/parsers/openapi/dereferencer.ts +60 -0
  196. package/renderer/lib/api-docs/parsers/openapi/extractors/auth.ts +574 -0
  197. package/renderer/lib/api-docs/parsers/openapi/extractors/body.ts +403 -0
  198. package/renderer/lib/api-docs/parsers/openapi/extractors/index.ts +232 -0
  199. package/renderer/lib/api-docs/parsers/openapi/index.ts +171 -0
  200. package/renderer/lib/api-docs/parsers/openapi/transformer.ts +277 -0
  201. package/renderer/lib/api-docs/parsers/openapi/validator.ts +31 -0
  202. package/renderer/lib/api-docs/playground/context.tsx +107 -0
  203. package/renderer/lib/api-docs/playground/navigation-context.tsx +124 -0
  204. package/renderer/lib/api-docs/playground/request-builder.ts +223 -0
  205. package/renderer/lib/api-docs/playground/request-runner.ts +282 -0
  206. package/renderer/lib/api-docs/playground/types.ts +35 -0
  207. package/renderer/lib/api-docs/types.ts +269 -0
  208. package/renderer/lib/api-docs/utils.ts +311 -0
  209. package/renderer/lib/cache.ts +193 -0
  210. package/renderer/lib/docs/config/index.ts +29 -0
  211. package/renderer/lib/docs/config/loader.ts +142 -0
  212. package/renderer/lib/docs/config/schema.ts +298 -0
  213. package/renderer/lib/docs/index.ts +12 -0
  214. package/renderer/lib/docs/mdx/compiler.ts +176 -0
  215. package/renderer/lib/docs/mdx/frontmatter.ts +80 -0
  216. package/renderer/lib/docs/mdx/index.ts +26 -0
  217. package/renderer/lib/docs/navigation/generator.ts +348 -0
  218. package/renderer/lib/docs/navigation/index.ts +12 -0
  219. package/renderer/lib/docs/navigation/types.ts +123 -0
  220. package/renderer/lib/docs-navigation-context.tsx +80 -0
  221. package/renderer/lib/multi-tenant/context.ts +105 -0
  222. package/renderer/lib/storage/blob.ts +845 -0
  223. package/renderer/lib/utils.ts +6 -0
  224. package/renderer/next.config.ts +76 -0
  225. package/renderer/package.json +66 -0
  226. package/renderer/postcss.config.mjs +5 -0
  227. package/renderer/public/assets/images/screenshot.png +0 -0
  228. package/renderer/public/assets/logo/dark.svg +9 -0
  229. package/renderer/public/assets/logo/light.svg +9 -0
  230. package/renderer/public/assets/logo.svg +9 -0
  231. package/renderer/public/file.svg +1 -0
  232. package/renderer/public/globe.svg +1 -0
  233. package/renderer/public/icon.png +0 -0
  234. package/renderer/public/logo.svg +9 -0
  235. package/renderer/public/window.svg +1 -0
  236. package/renderer/tsconfig.json +28 -0
  237. package/templates/basic/README.md +139 -0
  238. package/templates/basic/assets/favicon.svg +4 -0
  239. package/templates/basic/assets/logo.svg +9 -0
  240. package/templates/basic/docs.json +47 -0
  241. package/templates/basic/guides/configuration.mdx +149 -0
  242. package/templates/basic/guides/overview.mdx +96 -0
  243. package/templates/basic/index.mdx +39 -0
  244. package/templates/basic/package.json +14 -0
  245. package/templates/basic/quickstart.mdx +92 -0
  246. package/templates/basic/vercel.json +6 -0
  247. package/templates/graphql/README.md +139 -0
  248. package/templates/graphql/api-reference/schema.graphql +305 -0
  249. package/templates/graphql/assets/favicon.svg +4 -0
  250. package/templates/graphql/assets/logo.svg +9 -0
  251. package/templates/graphql/docs.json +54 -0
  252. package/templates/graphql/guides/configuration.mdx +149 -0
  253. package/templates/graphql/guides/overview.mdx +96 -0
  254. package/templates/graphql/index.mdx +39 -0
  255. package/templates/graphql/package.json +14 -0
  256. package/templates/graphql/quickstart.mdx +92 -0
  257. package/templates/graphql/vercel.json +6 -0
  258. package/templates/openapi/README.md +139 -0
  259. package/templates/openapi/api-reference/openapi.json +419 -0
  260. package/templates/openapi/assets/favicon.svg +4 -0
  261. package/templates/openapi/assets/logo.svg +9 -0
  262. package/templates/openapi/docs.json +61 -0
  263. package/templates/openapi/guides/configuration.mdx +149 -0
  264. package/templates/openapi/guides/overview.mdx +96 -0
  265. package/templates/openapi/index.mdx +39 -0
  266. package/templates/openapi/package.json +14 -0
  267. package/templates/openapi/quickstart.mdx +92 -0
  268. package/templates/openapi/vercel.json +6 -0
@@ -0,0 +1,246 @@
1
+ /**
2
+ * GraphQL Transformer
3
+ *
4
+ * Converts parsed GraphQL schema to BrainfishCollection format
5
+ * for integration with the existing documentation system.
6
+ */
7
+
8
+ import type { BrainfishCollection, BrainfishRESTRequest } from '../../types'
9
+ import { makeBrainfishCollection } from '../../factories'
10
+ import {
11
+ formatTypeRef,
12
+ type GraphQLSchema,
13
+ type GraphQLOperation,
14
+ type BrainfishGraphQLCollection,
15
+ type BrainfishGraphQLRequest,
16
+ type GraphQLTypeDef,
17
+ } from './types'
18
+ import { generateExampleVariables, generateOperationQuery } from './parser'
19
+
20
+ // ============================================================================
21
+ // GraphQL to REST-like Request Conversion
22
+ // ============================================================================
23
+
24
+ /**
25
+ * Convert a GraphQL operation to a REST-like request for the playground
26
+ * This allows us to reuse the existing API client UI
27
+ */
28
+ function convertOperationToRESTRequest(
29
+ operation: GraphQLOperation,
30
+ endpoint: string
31
+ ): BrainfishRESTRequest {
32
+ // Generate the query string
33
+ const query = generateOperationQuery(operation)
34
+
35
+ // Generate example variables
36
+ const variables = generateExampleVariables(operation)
37
+
38
+ // GraphQL always uses POST with JSON body
39
+ const body = JSON.stringify(
40
+ {
41
+ query,
42
+ variables,
43
+ operationName: operation.name,
44
+ },
45
+ null,
46
+ 2
47
+ )
48
+
49
+ return {
50
+ id: operation.id,
51
+ name: operation.name,
52
+ description: operation.description || formatOperationDescription(operation),
53
+ method: 'POST',
54
+ endpoint,
55
+ params: [],
56
+ headers: [
57
+ {
58
+ key: 'Content-Type',
59
+ value: 'application/json',
60
+ active: true,
61
+ description: 'GraphQL requests use JSON',
62
+ },
63
+ ],
64
+ auth: {
65
+ authType: 'inherit',
66
+ authActive: true,
67
+ },
68
+ body: {
69
+ contentType: 'application/json',
70
+ body,
71
+ },
72
+ requestVariables: operation.args.map(arg => ({
73
+ key: arg.name,
74
+ value: JSON.stringify(generateExampleVariables({ ...operation, args: [arg] })[arg.name]),
75
+ active: true,
76
+ })),
77
+ responses: {},
78
+ tags: [operation.operationType],
79
+ }
80
+ }
81
+
82
+ /**
83
+ * Format a description for an operation based on its signature
84
+ */
85
+ function formatOperationDescription(operation: GraphQLOperation): string {
86
+ const args = operation.args
87
+ .map(arg => `${arg.name}: ${formatTypeRef(arg.type)}`)
88
+ .join(', ')
89
+
90
+ const returnType = formatTypeRef(operation.returnType)
91
+
92
+ return `${operation.operationType} ${operation.name}(${args}): ${returnType}`
93
+ }
94
+
95
+ // ============================================================================
96
+ // Main Transformer Functions
97
+ // ============================================================================
98
+
99
+ /**
100
+ * Convert GraphQL schema to a BrainfishGraphQLCollection
101
+ */
102
+ export function convertGraphQLToCollection(
103
+ schema: GraphQLSchema,
104
+ name: string,
105
+ endpoint: string,
106
+ description?: string
107
+ ): BrainfishGraphQLCollection {
108
+ // Convert operations to our request format
109
+ const queries: BrainfishGraphQLRequest[] = schema.queries.map(op => ({
110
+ id: op.id,
111
+ name: op.name,
112
+ description: op.description,
113
+ operationType: 'query',
114
+ query: generateOperationQuery(op),
115
+ variables: op.args,
116
+ returnType: op.returnType,
117
+ tags: ['Query'],
118
+ exampleVariables: generateExampleVariables(op),
119
+ }))
120
+
121
+ const mutations: BrainfishGraphQLRequest[] = schema.mutations.map(op => ({
122
+ id: op.id,
123
+ name: op.name,
124
+ description: op.description,
125
+ operationType: 'mutation',
126
+ query: generateOperationQuery(op),
127
+ variables: op.args,
128
+ returnType: op.returnType,
129
+ tags: ['Mutation'],
130
+ exampleVariables: generateExampleVariables(op),
131
+ }))
132
+
133
+ const subscriptions: BrainfishGraphQLRequest[] = schema.subscriptions.map(op => ({
134
+ id: op.id,
135
+ name: op.name,
136
+ description: op.description,
137
+ operationType: 'subscription',
138
+ query: generateOperationQuery(op),
139
+ variables: op.args,
140
+ returnType: op.returnType,
141
+ tags: ['Subscription'],
142
+ exampleVariables: generateExampleVariables(op),
143
+ }))
144
+
145
+ // Extract custom types (exclude built-in scalars)
146
+ const customTypes: GraphQLTypeDef[] = Object.values(schema.types).filter(
147
+ type => !['String', 'Int', 'Float', 'Boolean', 'ID'].includes(type.name)
148
+ )
149
+
150
+ return {
151
+ id: `graphql-${name.toLowerCase().replace(/\s+/g, '-')}`,
152
+ name,
153
+ description: description || schema.info.description,
154
+ endpoint,
155
+ schema,
156
+ queries,
157
+ mutations,
158
+ subscriptions,
159
+ types: customTypes,
160
+ }
161
+ }
162
+
163
+ /**
164
+ * Convert GraphQL schema to BrainfishCollection format
165
+ * This allows integration with the existing REST-based UI
166
+ */
167
+ export function convertGraphQLToBrainfishCollection(
168
+ schema: GraphQLSchema,
169
+ name: string,
170
+ endpoint: string,
171
+ description?: string
172
+ ): BrainfishCollection {
173
+ // Create folders for each operation type
174
+ const queryFolder = makeBrainfishCollection({
175
+ name: 'Queries',
176
+ description: 'GraphQL Query operations',
177
+ requests: schema.queries.map(op => convertOperationToRESTRequest(op, endpoint)),
178
+ folders: [],
179
+ variables: [],
180
+ auth: { authType: 'none', authActive: false },
181
+ headers: [],
182
+ })
183
+
184
+ const mutationFolder = makeBrainfishCollection({
185
+ name: 'Mutations',
186
+ description: 'GraphQL Mutation operations',
187
+ requests: schema.mutations.map(op => convertOperationToRESTRequest(op, endpoint)),
188
+ folders: [],
189
+ variables: [],
190
+ auth: { authType: 'none', authActive: false },
191
+ headers: [],
192
+ })
193
+
194
+ const subscriptionFolder = makeBrainfishCollection({
195
+ name: 'Subscriptions',
196
+ description: 'GraphQL Subscription operations',
197
+ requests: schema.subscriptions.map(op => convertOperationToRESTRequest(op, endpoint)),
198
+ folders: [],
199
+ variables: [],
200
+ auth: { authType: 'none', authActive: false },
201
+ headers: [],
202
+ })
203
+
204
+ // Only include folders that have operations
205
+ const folders: BrainfishCollection[] = []
206
+ if (schema.queries.length > 0) folders.push(queryFolder)
207
+ if (schema.mutations.length > 0) folders.push(mutationFolder)
208
+ if (schema.subscriptions.length > 0) folders.push(subscriptionFolder)
209
+
210
+ return makeBrainfishCollection({
211
+ name,
212
+ description: description || schema.info.description || 'GraphQL API',
213
+ folders,
214
+ requests: [],
215
+ variables: [],
216
+ auth: { authType: 'none', authActive: false },
217
+ headers: [
218
+ {
219
+ key: 'Content-Type',
220
+ value: 'application/json',
221
+ active: true,
222
+ description: 'GraphQL requests use JSON',
223
+ },
224
+ ],
225
+ })
226
+ }
227
+
228
+ /**
229
+ * Merge GraphQL collection with existing REST collection
230
+ */
231
+ export function mergeWithRESTCollection(
232
+ restCollection: BrainfishCollection,
233
+ graphqlSchema: GraphQLSchema,
234
+ graphqlEndpoint: string
235
+ ): BrainfishCollection {
236
+ const graphqlCollection = convertGraphQLToBrainfishCollection(
237
+ graphqlSchema,
238
+ 'GraphQL',
239
+ graphqlEndpoint
240
+ )
241
+
242
+ return {
243
+ ...restCollection,
244
+ folders: [...restCollection.folders, graphqlCollection],
245
+ }
246
+ }
@@ -0,0 +1,283 @@
1
+ /**
2
+ * GraphQL Types for Brainfish API Documentation
3
+ *
4
+ * Types for parsing and representing GraphQL schemas in the documentation system.
5
+ */
6
+
7
+ // ============================================================================
8
+ // GraphQL Scalar Types
9
+ // ============================================================================
10
+
11
+ export type GraphQLScalarType =
12
+ | 'String'
13
+ | 'Int'
14
+ | 'Float'
15
+ | 'Boolean'
16
+ | 'ID'
17
+ | string // Custom scalars
18
+
19
+ // ============================================================================
20
+ // GraphQL Type Kinds
21
+ // ============================================================================
22
+
23
+ export type GraphQLTypeKind =
24
+ | 'SCALAR'
25
+ | 'OBJECT'
26
+ | 'INPUT_OBJECT'
27
+ | 'ENUM'
28
+ | 'INTERFACE'
29
+ | 'UNION'
30
+ | 'LIST'
31
+ | 'NON_NULL'
32
+
33
+ // ============================================================================
34
+ // GraphQL Type Reference
35
+ // ============================================================================
36
+
37
+ export interface GraphQLTypeRef {
38
+ kind: GraphQLTypeKind
39
+ name: string | null
40
+ ofType?: GraphQLTypeRef | null
41
+ }
42
+
43
+ // ============================================================================
44
+ // GraphQL Argument
45
+ // ============================================================================
46
+
47
+ export interface GraphQLArgument {
48
+ name: string
49
+ description: string | null
50
+ type: GraphQLTypeRef
51
+ defaultValue: string | null
52
+ isRequired: boolean
53
+ }
54
+
55
+ // ============================================================================
56
+ // GraphQL Field
57
+ // ============================================================================
58
+
59
+ export interface GraphQLField {
60
+ name: string
61
+ description: string | null
62
+ args: GraphQLArgument[]
63
+ type: GraphQLTypeRef
64
+ isDeprecated: boolean
65
+ deprecationReason: string | null
66
+ }
67
+
68
+ // ============================================================================
69
+ // GraphQL Enum Value
70
+ // ============================================================================
71
+
72
+ export interface GraphQLEnumValue {
73
+ name: string
74
+ description: string | null
75
+ isDeprecated: boolean
76
+ deprecationReason: string | null
77
+ }
78
+
79
+ // ============================================================================
80
+ // GraphQL Input Field
81
+ // ============================================================================
82
+
83
+ export interface GraphQLInputField {
84
+ name: string
85
+ description: string | null
86
+ type: GraphQLTypeRef
87
+ defaultValue: string | null
88
+ isRequired: boolean
89
+ }
90
+
91
+ // ============================================================================
92
+ // GraphQL Type Definitions
93
+ // ============================================================================
94
+
95
+ export interface GraphQLScalarTypeDef {
96
+ kind: 'SCALAR'
97
+ name: string
98
+ description: string | null
99
+ }
100
+
101
+ export interface GraphQLObjectTypeDef {
102
+ kind: 'OBJECT'
103
+ name: string
104
+ description: string | null
105
+ fields: GraphQLField[]
106
+ interfaces: string[]
107
+ }
108
+
109
+ export interface GraphQLInputObjectTypeDef {
110
+ kind: 'INPUT_OBJECT'
111
+ name: string
112
+ description: string | null
113
+ inputFields: GraphQLInputField[]
114
+ }
115
+
116
+ export interface GraphQLEnumTypeDef {
117
+ kind: 'ENUM'
118
+ name: string
119
+ description: string | null
120
+ enumValues: GraphQLEnumValue[]
121
+ }
122
+
123
+ export interface GraphQLInterfaceTypeDef {
124
+ kind: 'INTERFACE'
125
+ name: string
126
+ description: string | null
127
+ fields: GraphQLField[]
128
+ possibleTypes: string[]
129
+ }
130
+
131
+ export interface GraphQLUnionTypeDef {
132
+ kind: 'UNION'
133
+ name: string
134
+ description: string | null
135
+ possibleTypes: string[]
136
+ }
137
+
138
+ export type GraphQLTypeDef =
139
+ | GraphQLScalarTypeDef
140
+ | GraphQLObjectTypeDef
141
+ | GraphQLInputObjectTypeDef
142
+ | GraphQLEnumTypeDef
143
+ | GraphQLInterfaceTypeDef
144
+ | GraphQLUnionTypeDef
145
+
146
+ // ============================================================================
147
+ // GraphQL Operation Types
148
+ // ============================================================================
149
+
150
+ export type GraphQLOperationType = 'query' | 'mutation' | 'subscription'
151
+
152
+ export interface GraphQLOperation {
153
+ id: string
154
+ name: string
155
+ description: string | null
156
+ operationType: GraphQLOperationType
157
+ args: GraphQLArgument[]
158
+ returnType: GraphQLTypeRef
159
+ isDeprecated: boolean
160
+ deprecationReason: string | null
161
+ }
162
+
163
+ // ============================================================================
164
+ // GraphQL Directive
165
+ // ============================================================================
166
+
167
+ export interface GraphQLDirective {
168
+ name: string
169
+ description: string | null
170
+ locations: string[]
171
+ args: GraphQLArgument[]
172
+ }
173
+
174
+ // ============================================================================
175
+ // GraphQL Schema
176
+ // ============================================================================
177
+
178
+ export interface GraphQLSchemaInfo {
179
+ /** Schema description */
180
+ description: string | null
181
+ /** Query type name (usually "Query") */
182
+ queryType: string | null
183
+ /** Mutation type name (usually "Mutation") */
184
+ mutationType: string | null
185
+ /** Subscription type name (usually "Subscription") */
186
+ subscriptionType: string | null
187
+ }
188
+
189
+ export interface GraphQLSchema {
190
+ /** Schema metadata */
191
+ info: GraphQLSchemaInfo
192
+ /** All type definitions */
193
+ types: Record<string, GraphQLTypeDef>
194
+ /** All directives */
195
+ directives: GraphQLDirective[]
196
+ /** Parsed queries */
197
+ queries: GraphQLOperation[]
198
+ /** Parsed mutations */
199
+ mutations: GraphQLOperation[]
200
+ /** Parsed subscriptions */
201
+ subscriptions: GraphQLOperation[]
202
+ }
203
+
204
+ // ============================================================================
205
+ // GraphQL Collection (for integration with existing system)
206
+ // ============================================================================
207
+
208
+ export interface BrainfishGraphQLRequest {
209
+ id: string
210
+ name: string
211
+ description: string | null
212
+ operationType: GraphQLOperationType
213
+ /** The GraphQL query/mutation/subscription string */
214
+ query: string
215
+ /** Variables schema */
216
+ variables: GraphQLArgument[]
217
+ /** Return type */
218
+ returnType: GraphQLTypeRef
219
+ /** Tags for grouping */
220
+ tags: string[]
221
+ /** Example variables */
222
+ exampleVariables?: Record<string, unknown>
223
+ /** Example response */
224
+ exampleResponse?: unknown
225
+ }
226
+
227
+ export interface BrainfishGraphQLCollection {
228
+ id: string
229
+ name: string
230
+ description: string | null
231
+ /** GraphQL endpoint URL */
232
+ endpoint: string
233
+ /** Schema information */
234
+ schema: GraphQLSchema
235
+ /** All operations organized */
236
+ queries: BrainfishGraphQLRequest[]
237
+ mutations: BrainfishGraphQLRequest[]
238
+ subscriptions: BrainfishGraphQLRequest[]
239
+ /** Custom types for reference */
240
+ types: GraphQLTypeDef[]
241
+ }
242
+
243
+ // ============================================================================
244
+ // Helper Functions
245
+ // ============================================================================
246
+
247
+ /**
248
+ * Format a GraphQL type reference as a string
249
+ * e.g., [String!]! -> "[String!]!"
250
+ */
251
+ export function formatTypeRef(typeRef: GraphQLTypeRef): string {
252
+ if (typeRef.kind === 'NON_NULL' && typeRef.ofType) {
253
+ return `${formatTypeRef(typeRef.ofType)}!`
254
+ }
255
+ if (typeRef.kind === 'LIST' && typeRef.ofType) {
256
+ return `[${formatTypeRef(typeRef.ofType)}]`
257
+ }
258
+ return typeRef.name || 'Unknown'
259
+ }
260
+
261
+ /**
262
+ * Check if a type is required (non-null at the top level)
263
+ */
264
+ export function isTypeRequired(typeRef: GraphQLTypeRef): boolean {
265
+ return typeRef.kind === 'NON_NULL'
266
+ }
267
+
268
+ /**
269
+ * Get the base type name from a type reference
270
+ */
271
+ export function getBaseTypeName(typeRef: GraphQLTypeRef): string {
272
+ if (typeRef.ofType) {
273
+ return getBaseTypeName(typeRef.ofType)
274
+ }
275
+ return typeRef.name || 'Unknown'
276
+ }
277
+
278
+ /**
279
+ * Check if a type is a scalar type
280
+ */
281
+ export function isScalarType(typeName: string): boolean {
282
+ return ['String', 'Int', 'Float', 'Boolean', 'ID'].includes(typeName)
283
+ }
@@ -0,0 +1,32 @@
1
+ # OpenAPI Parser
2
+
3
+ This directory contains the OpenAPI parsing logic ported from Hoppscotch.
4
+
5
+ ## Structure
6
+
7
+ - `index.ts` - Main importer function
8
+ - `validator.ts` - OpenAPI validation logic
9
+ - `dereferencer.ts` - Reference resolution
10
+ - `transformer.ts` - OpenAPI → BrainfishCollection conversion
11
+ - `parsers/` - Version-specific parsers (v2, v3, v31)
12
+ - `extractors/` - Extraction functions (auth, params, headers, body, responses)
13
+ - `example-generators/` - Example generation from schemas
14
+
15
+ ## Dependencies Required
16
+
17
+ Before implementing, install these dependencies:
18
+
19
+ ```bash
20
+ npm install @apidevtools/swagger-parser openapi-types js-yaml lodash-es
21
+ npm install -D @types/js-yaml @types/lodash-es
22
+ ```
23
+
24
+ ## Porting Strategy
25
+
26
+ 1. Copy functions from Hoppscotch's `openapi/index.ts`
27
+ 2. Replace `HoppCollection` → `BrainfishCollection`
28
+ 3. Replace `HoppRESTRequest` → `BrainfishRESTRequest`
29
+ 4. Replace `makeCollection` → `makeBrainfishCollection`
30
+ 5. Replace `makeRESTRequest` → `makeBrainfishRESTRequest`
31
+ 6. Convert fp-ts to native TypeScript (optional)
32
+ 7. Convert Web Worker to Next.js API route or direct function calls
@@ -0,0 +1,60 @@
1
+ /**
2
+ * OpenAPI Dereferencer
3
+ *
4
+ * Ported from Hoppscotch's openapi-import-worker.ts
5
+ * Converts Web Worker pattern to direct function calls for Next.js
6
+ */
7
+
8
+ import SwaggerParser from '@apidevtools/swagger-parser'
9
+ import type { OpenAPI } from 'openapi-types'
10
+
11
+ /**
12
+ * Dereferences all $ref references in an OpenAPI document
13
+ *
14
+ * @param docs - The OpenAPI document to dereference
15
+ * @returns Promise resolving to dereferenced OpenAPI document
16
+ * @throws Error if dereferencing fails
17
+ */
18
+ export async function dereferenceOpenAPISpec(
19
+ docs: OpenAPI.Document
20
+ ): Promise<OpenAPI.Document> {
21
+ try {
22
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
23
+ const dereferenced = await SwaggerParser.dereference(docs as any)
24
+ return dereferenced as OpenAPI.Document
25
+ } catch {
26
+ throw new Error('COULD_NOT_DEREFERENCE')
27
+ }
28
+ }
29
+
30
+ /**
31
+ * Checks if a document has unresolved $ref references
32
+ *
33
+ * @param obj - The object to check
34
+ * @param visited - Set of visited objects to detect circular references
35
+ * @returns true if unresolved references are found
36
+ */
37
+ export function hasUnresolvedRefs(
38
+ obj: unknown,
39
+ visited = new WeakSet()
40
+ ): boolean {
41
+ // Handle non-objects or null
42
+ if (!obj || typeof obj !== 'object') return false
43
+
44
+ // Check for circular references
45
+ if (visited.has(obj)) return false
46
+
47
+ // Add current object to visited set
48
+ visited.add(obj)
49
+
50
+ // Check if current object has $ref property
51
+ if ('$ref' in obj && typeof obj.$ref === 'string') return true
52
+
53
+ // Check arrays
54
+ if (Array.isArray(obj)) {
55
+ return obj.some((item) => hasUnresolvedRefs(item, visited))
56
+ }
57
+
58
+ // Check object properties
59
+ return Object.values(obj).some((value) => hasUnresolvedRefs(value, visited))
60
+ }