@brainfish-ai/devdoc 0.1.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +33 -0
- package/README.md +415 -0
- package/bin/devdoc.js +13 -0
- package/dist/cli/commands/build.d.ts +5 -0
- package/dist/cli/commands/build.js +87 -0
- package/dist/cli/commands/check.d.ts +1 -0
- package/dist/cli/commands/check.js +143 -0
- package/dist/cli/commands/create.d.ts +24 -0
- package/dist/cli/commands/create.js +387 -0
- package/dist/cli/commands/deploy.d.ts +9 -0
- package/dist/cli/commands/deploy.js +433 -0
- package/dist/cli/commands/dev.d.ts +6 -0
- package/dist/cli/commands/dev.js +139 -0
- package/dist/cli/commands/init.d.ts +11 -0
- package/dist/cli/commands/init.js +238 -0
- package/dist/cli/commands/keys.d.ts +12 -0
- package/dist/cli/commands/keys.js +165 -0
- package/dist/cli/commands/start.d.ts +5 -0
- package/dist/cli/commands/start.js +56 -0
- package/dist/cli/commands/upload.d.ts +13 -0
- package/dist/cli/commands/upload.js +238 -0
- package/dist/cli/commands/whoami.d.ts +8 -0
- package/dist/cli/commands/whoami.js +91 -0
- package/dist/cli/index.d.ts +1 -0
- package/dist/cli/index.js +106 -0
- package/dist/config/index.d.ts +80 -0
- package/dist/config/index.js +133 -0
- package/dist/constants.d.ts +9 -0
- package/dist/constants.js +13 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +12 -0
- package/dist/utils/logger.d.ts +16 -0
- package/dist/utils/logger.js +61 -0
- package/dist/utils/paths.d.ts +16 -0
- package/dist/utils/paths.js +50 -0
- package/package.json +51 -0
- package/renderer/app/api/assets/[...path]/route.ts +123 -0
- package/renderer/app/api/assets/route.ts +124 -0
- package/renderer/app/api/assets/upload/route.ts +177 -0
- package/renderer/app/api/auth-schemes/route.ts +77 -0
- package/renderer/app/api/chat/route.ts +858 -0
- package/renderer/app/api/codegen/route.ts +72 -0
- package/renderer/app/api/collections/route.ts +1016 -0
- package/renderer/app/api/debug/route.ts +53 -0
- package/renderer/app/api/deploy/route.ts +234 -0
- package/renderer/app/api/device/route.ts +42 -0
- package/renderer/app/api/docs/route.ts +187 -0
- package/renderer/app/api/keys/regenerate/route.ts +80 -0
- package/renderer/app/api/openapi-spec/route.ts +151 -0
- package/renderer/app/api/projects/[slug]/route.ts +153 -0
- package/renderer/app/api/projects/[slug]/stats/route.ts +96 -0
- package/renderer/app/api/projects/register/route.ts +152 -0
- package/renderer/app/api/proxy/route.ts +149 -0
- package/renderer/app/api/proxy-stream/route.ts +168 -0
- package/renderer/app/api/redirects/route.ts +47 -0
- package/renderer/app/api/schema/route.ts +65 -0
- package/renderer/app/api/subdomains/check/route.ts +172 -0
- package/renderer/app/api/suggestions/route.ts +144 -0
- package/renderer/app/favicon.ico +0 -0
- package/renderer/app/globals.css +1103 -0
- package/renderer/app/layout.tsx +47 -0
- package/renderer/app/llms-full.txt/route.ts +346 -0
- package/renderer/app/llms.txt/route.ts +279 -0
- package/renderer/app/page.tsx +14 -0
- package/renderer/app/robots.txt/route.ts +84 -0
- package/renderer/app/sitemap.xml/route.ts +199 -0
- package/renderer/components/docs/index.ts +12 -0
- package/renderer/components/docs/mdx/accordion.tsx +169 -0
- package/renderer/components/docs/mdx/badge.tsx +132 -0
- package/renderer/components/docs/mdx/callouts.tsx +154 -0
- package/renderer/components/docs/mdx/cards.tsx +213 -0
- package/renderer/components/docs/mdx/changelog.tsx +120 -0
- package/renderer/components/docs/mdx/code-block.tsx +186 -0
- package/renderer/components/docs/mdx/code-group.tsx +421 -0
- package/renderer/components/docs/mdx/file-embeds.tsx +105 -0
- package/renderer/components/docs/mdx/frame.tsx +112 -0
- package/renderer/components/docs/mdx/highlight.tsx +151 -0
- package/renderer/components/docs/mdx/iframe.tsx +134 -0
- package/renderer/components/docs/mdx/image.tsx +235 -0
- package/renderer/components/docs/mdx/index.ts +204 -0
- package/renderer/components/docs/mdx/mermaid.tsx +240 -0
- package/renderer/components/docs/mdx/param-field.tsx +200 -0
- package/renderer/components/docs/mdx/steps.tsx +113 -0
- package/renderer/components/docs/mdx/tabs.tsx +86 -0
- package/renderer/components/docs/mdx-renderer.tsx +100 -0
- package/renderer/components/docs/navigation/breadcrumbs.tsx +76 -0
- package/renderer/components/docs/navigation/index.ts +8 -0
- package/renderer/components/docs/navigation/page-nav.tsx +64 -0
- package/renderer/components/docs/navigation/sidebar.tsx +515 -0
- package/renderer/components/docs/navigation/toc.tsx +113 -0
- package/renderer/components/docs/notice.tsx +105 -0
- package/renderer/components/docs-header.tsx +274 -0
- package/renderer/components/docs-viewer/agent/agent-chat.tsx +2076 -0
- package/renderer/components/docs-viewer/agent/cards/debug-context-card.tsx +90 -0
- package/renderer/components/docs-viewer/agent/cards/endpoint-context-card.tsx +49 -0
- package/renderer/components/docs-viewer/agent/cards/index.tsx +50 -0
- package/renderer/components/docs-viewer/agent/cards/response-options-card.tsx +212 -0
- package/renderer/components/docs-viewer/agent/cards/types.ts +84 -0
- package/renderer/components/docs-viewer/agent/chat-message.tsx +17 -0
- package/renderer/components/docs-viewer/agent/index.tsx +6 -0
- package/renderer/components/docs-viewer/agent/messages/assistant-message.tsx +119 -0
- package/renderer/components/docs-viewer/agent/messages/chat-message.tsx +46 -0
- package/renderer/components/docs-viewer/agent/messages/index.ts +17 -0
- package/renderer/components/docs-viewer/agent/messages/tool-call-display.tsx +721 -0
- package/renderer/components/docs-viewer/agent/messages/types.ts +61 -0
- package/renderer/components/docs-viewer/agent/messages/typing-indicator.tsx +24 -0
- package/renderer/components/docs-viewer/agent/messages/user-message.tsx +51 -0
- package/renderer/components/docs-viewer/code-editor/index.tsx +2 -0
- package/renderer/components/docs-viewer/code-editor/notes-mode.tsx +1283 -0
- package/renderer/components/docs-viewer/content/changelog-page.tsx +331 -0
- package/renderer/components/docs-viewer/content/doc-page.tsx +285 -0
- package/renderer/components/docs-viewer/content/documentation-viewer.tsx +17 -0
- package/renderer/components/docs-viewer/content/index.tsx +29 -0
- package/renderer/components/docs-viewer/content/introduction.tsx +21 -0
- package/renderer/components/docs-viewer/content/request-details.tsx +330 -0
- package/renderer/components/docs-viewer/content/sections/auth.tsx +69 -0
- package/renderer/components/docs-viewer/content/sections/body.tsx +66 -0
- package/renderer/components/docs-viewer/content/sections/headers.tsx +43 -0
- package/renderer/components/docs-viewer/content/sections/overview.tsx +40 -0
- package/renderer/components/docs-viewer/content/sections/parameters.tsx +43 -0
- package/renderer/components/docs-viewer/content/sections/responses.tsx +87 -0
- package/renderer/components/docs-viewer/global-auth-modal.tsx +352 -0
- package/renderer/components/docs-viewer/index.tsx +1466 -0
- package/renderer/components/docs-viewer/playground/auth-editor.tsx +280 -0
- package/renderer/components/docs-viewer/playground/body-editor.tsx +221 -0
- package/renderer/components/docs-viewer/playground/code-editor.tsx +224 -0
- package/renderer/components/docs-viewer/playground/code-snippet.tsx +387 -0
- package/renderer/components/docs-viewer/playground/graphql-playground.tsx +745 -0
- package/renderer/components/docs-viewer/playground/index.tsx +671 -0
- package/renderer/components/docs-viewer/playground/key-value-editor.tsx +261 -0
- package/renderer/components/docs-viewer/playground/method-selector.tsx +60 -0
- package/renderer/components/docs-viewer/playground/request-builder.tsx +179 -0
- package/renderer/components/docs-viewer/playground/request-tabs.tsx +237 -0
- package/renderer/components/docs-viewer/playground/response-cards/idle-card.tsx +21 -0
- package/renderer/components/docs-viewer/playground/response-cards/index.tsx +93 -0
- package/renderer/components/docs-viewer/playground/response-cards/loading-card.tsx +16 -0
- package/renderer/components/docs-viewer/playground/response-cards/network-error-card.tsx +23 -0
- package/renderer/components/docs-viewer/playground/response-cards/response-body-card.tsx +268 -0
- package/renderer/components/docs-viewer/playground/response-cards/types.ts +82 -0
- package/renderer/components/docs-viewer/playground/response-viewer.tsx +43 -0
- package/renderer/components/docs-viewer/search/index.ts +2 -0
- package/renderer/components/docs-viewer/search/search-dialog.tsx +331 -0
- package/renderer/components/docs-viewer/search/use-search.ts +117 -0
- package/renderer/components/docs-viewer/shared/markdown-renderer.tsx +431 -0
- package/renderer/components/docs-viewer/shared/method-badge.tsx +41 -0
- package/renderer/components/docs-viewer/shared/schema-viewer.tsx +349 -0
- package/renderer/components/docs-viewer/sidebar/collection-tree.tsx +239 -0
- package/renderer/components/docs-viewer/sidebar/endpoint-options.tsx +316 -0
- package/renderer/components/docs-viewer/sidebar/index.tsx +343 -0
- package/renderer/components/docs-viewer/sidebar/right-sidebar.tsx +202 -0
- package/renderer/components/docs-viewer/sidebar/sidebar-group.tsx +118 -0
- package/renderer/components/docs-viewer/sidebar/sidebar-item.tsx +226 -0
- package/renderer/components/docs-viewer/sidebar/sidebar-section.tsx +52 -0
- package/renderer/components/theme-provider.tsx +11 -0
- package/renderer/components/theme-toggle.tsx +76 -0
- package/renderer/components/ui/badge.tsx +46 -0
- package/renderer/components/ui/button.tsx +59 -0
- package/renderer/components/ui/dialog.tsx +118 -0
- package/renderer/components/ui/dropdown-menu.tsx +257 -0
- package/renderer/components/ui/input.tsx +21 -0
- package/renderer/components/ui/label.tsx +24 -0
- package/renderer/components/ui/navigation-menu.tsx +168 -0
- package/renderer/components/ui/select.tsx +190 -0
- package/renderer/components/ui/spinner.tsx +114 -0
- package/renderer/components/ui/tabs.tsx +66 -0
- package/renderer/components/ui/tooltip.tsx +61 -0
- package/renderer/hooks/use-code-copy.ts +88 -0
- package/renderer/hooks/use-openapi-title.ts +44 -0
- package/renderer/lib/api-docs/agent/index.ts +6 -0
- package/renderer/lib/api-docs/agent/indexer.ts +323 -0
- package/renderer/lib/api-docs/agent/spec-summary.ts +335 -0
- package/renderer/lib/api-docs/agent/types.ts +116 -0
- package/renderer/lib/api-docs/auth/auth-context.tsx +225 -0
- package/renderer/lib/api-docs/auth/auth-storage.ts +87 -0
- package/renderer/lib/api-docs/auth/crypto.ts +89 -0
- package/renderer/lib/api-docs/auth/index.ts +4 -0
- package/renderer/lib/api-docs/code-editor/db.ts +164 -0
- package/renderer/lib/api-docs/code-editor/hooks.ts +266 -0
- package/renderer/lib/api-docs/code-editor/index.ts +6 -0
- package/renderer/lib/api-docs/code-editor/mode-context.tsx +207 -0
- package/renderer/lib/api-docs/code-editor/types.ts +105 -0
- package/renderer/lib/api-docs/codegen/definitions.ts +297 -0
- package/renderer/lib/api-docs/codegen/har.ts +251 -0
- package/renderer/lib/api-docs/codegen/index.ts +159 -0
- package/renderer/lib/api-docs/factories.ts +151 -0
- package/renderer/lib/api-docs/index.ts +17 -0
- package/renderer/lib/api-docs/mobile-context.tsx +112 -0
- package/renderer/lib/api-docs/navigation-context.tsx +88 -0
- package/renderer/lib/api-docs/parsers/graphql/README.md +129 -0
- package/renderer/lib/api-docs/parsers/graphql/index.ts +91 -0
- package/renderer/lib/api-docs/parsers/graphql/parser.ts +491 -0
- package/renderer/lib/api-docs/parsers/graphql/transformer.ts +246 -0
- package/renderer/lib/api-docs/parsers/graphql/types.ts +283 -0
- package/renderer/lib/api-docs/parsers/openapi/README.md +32 -0
- package/renderer/lib/api-docs/parsers/openapi/dereferencer.ts +60 -0
- package/renderer/lib/api-docs/parsers/openapi/extractors/auth.ts +574 -0
- package/renderer/lib/api-docs/parsers/openapi/extractors/body.ts +403 -0
- package/renderer/lib/api-docs/parsers/openapi/extractors/index.ts +232 -0
- package/renderer/lib/api-docs/parsers/openapi/index.ts +171 -0
- package/renderer/lib/api-docs/parsers/openapi/transformer.ts +277 -0
- package/renderer/lib/api-docs/parsers/openapi/validator.ts +31 -0
- package/renderer/lib/api-docs/playground/context.tsx +107 -0
- package/renderer/lib/api-docs/playground/navigation-context.tsx +124 -0
- package/renderer/lib/api-docs/playground/request-builder.ts +223 -0
- package/renderer/lib/api-docs/playground/request-runner.ts +282 -0
- package/renderer/lib/api-docs/playground/types.ts +35 -0
- package/renderer/lib/api-docs/types.ts +269 -0
- package/renderer/lib/api-docs/utils.ts +311 -0
- package/renderer/lib/cache.ts +193 -0
- package/renderer/lib/docs/config/index.ts +29 -0
- package/renderer/lib/docs/config/loader.ts +142 -0
- package/renderer/lib/docs/config/schema.ts +298 -0
- package/renderer/lib/docs/index.ts +12 -0
- package/renderer/lib/docs/mdx/compiler.ts +176 -0
- package/renderer/lib/docs/mdx/frontmatter.ts +80 -0
- package/renderer/lib/docs/mdx/index.ts +26 -0
- package/renderer/lib/docs/navigation/generator.ts +348 -0
- package/renderer/lib/docs/navigation/index.ts +12 -0
- package/renderer/lib/docs/navigation/types.ts +123 -0
- package/renderer/lib/docs-navigation-context.tsx +80 -0
- package/renderer/lib/multi-tenant/context.ts +105 -0
- package/renderer/lib/storage/blob.ts +845 -0
- package/renderer/lib/utils.ts +6 -0
- package/renderer/next.config.ts +76 -0
- package/renderer/package.json +66 -0
- package/renderer/postcss.config.mjs +5 -0
- package/renderer/public/assets/images/screenshot.png +0 -0
- package/renderer/public/assets/logo/dark.svg +9 -0
- package/renderer/public/assets/logo/light.svg +9 -0
- package/renderer/public/assets/logo.svg +9 -0
- package/renderer/public/file.svg +1 -0
- package/renderer/public/globe.svg +1 -0
- package/renderer/public/icon.png +0 -0
- package/renderer/public/logo.svg +9 -0
- package/renderer/public/window.svg +1 -0
- package/renderer/tsconfig.json +28 -0
- package/templates/basic/README.md +139 -0
- package/templates/basic/assets/favicon.svg +4 -0
- package/templates/basic/assets/logo.svg +9 -0
- package/templates/basic/docs.json +47 -0
- package/templates/basic/guides/configuration.mdx +149 -0
- package/templates/basic/guides/overview.mdx +96 -0
- package/templates/basic/index.mdx +39 -0
- package/templates/basic/package.json +14 -0
- package/templates/basic/quickstart.mdx +92 -0
- package/templates/basic/vercel.json +6 -0
- package/templates/graphql/README.md +139 -0
- package/templates/graphql/api-reference/schema.graphql +305 -0
- package/templates/graphql/assets/favicon.svg +4 -0
- package/templates/graphql/assets/logo.svg +9 -0
- package/templates/graphql/docs.json +54 -0
- package/templates/graphql/guides/configuration.mdx +149 -0
- package/templates/graphql/guides/overview.mdx +96 -0
- package/templates/graphql/index.mdx +39 -0
- package/templates/graphql/package.json +14 -0
- package/templates/graphql/quickstart.mdx +92 -0
- package/templates/graphql/vercel.json +6 -0
- package/templates/openapi/README.md +139 -0
- package/templates/openapi/api-reference/openapi.json +419 -0
- package/templates/openapi/assets/favicon.svg +4 -0
- package/templates/openapi/assets/logo.svg +9 -0
- package/templates/openapi/docs.json +61 -0
- package/templates/openapi/guides/configuration.mdx +149 -0
- package/templates/openapi/guides/overview.mdx +96 -0
- package/templates/openapi/index.mdx +39 -0
- package/templates/openapi/package.json +14 -0
- package/templates/openapi/quickstart.mdx +92 -0
- package/templates/openapi/vercel.json +6 -0
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Factory Functions for Brainfish API Documentation
|
|
3
|
+
*
|
|
4
|
+
* Creates instances of BrainfishCollection and BrainfishRESTRequest
|
|
5
|
+
* with proper defaults and unique IDs.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type {
|
|
9
|
+
BrainfishCollection,
|
|
10
|
+
BrainfishRESTRequest,
|
|
11
|
+
} from './types'
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Generates a unique ID for collections and requests
|
|
15
|
+
* If a seed is provided, generates a deterministic hash-based ID
|
|
16
|
+
*/
|
|
17
|
+
function generateUniqueId(prefix: string, seed?: string): string {
|
|
18
|
+
if (seed) {
|
|
19
|
+
// Generate deterministic ID from seed using simple hash
|
|
20
|
+
let hash = 0
|
|
21
|
+
for (let i = 0; i < seed.length; i++) {
|
|
22
|
+
const char = seed.charCodeAt(i)
|
|
23
|
+
hash = ((hash << 5) - hash) + char
|
|
24
|
+
hash = hash & hash // Convert to 32bit integer
|
|
25
|
+
}
|
|
26
|
+
// Convert to positive number and base36
|
|
27
|
+
const hashStr = Math.abs(hash).toString(36)
|
|
28
|
+
return `${prefix}_${hashStr}`
|
|
29
|
+
}
|
|
30
|
+
return `${prefix}_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Creates a BrainfishRESTRequest with defaults
|
|
35
|
+
* If method and endpoint are provided, generates a deterministic ID
|
|
36
|
+
*/
|
|
37
|
+
export function makeBrainfishRESTRequest(
|
|
38
|
+
request: Omit<BrainfishRESTRequest, 'id'>
|
|
39
|
+
): BrainfishRESTRequest {
|
|
40
|
+
// Generate deterministic ID from method + endpoint
|
|
41
|
+
const idSeed = request.method && request.endpoint
|
|
42
|
+
? `${request.method}:${request.endpoint}`
|
|
43
|
+
: undefined
|
|
44
|
+
|
|
45
|
+
return {
|
|
46
|
+
id: generateUniqueId('req', idSeed),
|
|
47
|
+
name: request.name || 'Untitled Request',
|
|
48
|
+
description: request.description ?? null,
|
|
49
|
+
method: request.method || 'GET',
|
|
50
|
+
endpoint: request.endpoint || '',
|
|
51
|
+
params: request.params || [],
|
|
52
|
+
headers: request.headers || [],
|
|
53
|
+
auth: request.auth || { authType: 'none', authActive: true },
|
|
54
|
+
body: request.body || { contentType: null, body: null },
|
|
55
|
+
requestVariables: request.requestVariables || [],
|
|
56
|
+
responses: request.responses || {},
|
|
57
|
+
tags: request.tags || [],
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Creates a BrainfishCollection with defaults
|
|
63
|
+
* If name is provided, generates a deterministic ID
|
|
64
|
+
*/
|
|
65
|
+
export function makeBrainfishCollection(
|
|
66
|
+
collection: Omit<BrainfishCollection, 'id'>
|
|
67
|
+
): BrainfishCollection {
|
|
68
|
+
// Generate deterministic ID from collection name
|
|
69
|
+
const idSeed = collection.name ? `collection:${collection.name}` : undefined
|
|
70
|
+
|
|
71
|
+
return {
|
|
72
|
+
id: generateUniqueId('coll', idSeed),
|
|
73
|
+
name: collection.name || 'Untitled Collection',
|
|
74
|
+
description: collection.description ?? null,
|
|
75
|
+
folders: collection.folders || [],
|
|
76
|
+
requests: collection.requests || [],
|
|
77
|
+
variables: collection.variables || [],
|
|
78
|
+
auth: collection.auth || { authType: 'inherit', authActive: true },
|
|
79
|
+
headers: collection.headers || [],
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Creates a default BrainfishRESTRequest
|
|
85
|
+
*/
|
|
86
|
+
export function getDefaultBrainfishRESTRequest(): BrainfishRESTRequest {
|
|
87
|
+
return makeBrainfishRESTRequest({
|
|
88
|
+
name: 'Untitled Request',
|
|
89
|
+
description: null,
|
|
90
|
+
method: 'GET',
|
|
91
|
+
endpoint: '',
|
|
92
|
+
params: [],
|
|
93
|
+
headers: [],
|
|
94
|
+
auth: {
|
|
95
|
+
authType: 'none',
|
|
96
|
+
authActive: true,
|
|
97
|
+
},
|
|
98
|
+
body: {
|
|
99
|
+
contentType: null,
|
|
100
|
+
body: null,
|
|
101
|
+
},
|
|
102
|
+
requestVariables: [],
|
|
103
|
+
responses: {},
|
|
104
|
+
tags: [],
|
|
105
|
+
})
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Creates a default BrainfishCollection
|
|
110
|
+
*/
|
|
111
|
+
export function getDefaultBrainfishCollection(): BrainfishCollection {
|
|
112
|
+
return makeBrainfishCollection({
|
|
113
|
+
name: 'Untitled Collection',
|
|
114
|
+
description: null,
|
|
115
|
+
folders: [],
|
|
116
|
+
requests: [],
|
|
117
|
+
variables: [],
|
|
118
|
+
auth: {
|
|
119
|
+
authType: 'inherit',
|
|
120
|
+
authActive: true,
|
|
121
|
+
},
|
|
122
|
+
headers: [],
|
|
123
|
+
})
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Creates a BrainfishRESTResponseOriginalRequest
|
|
128
|
+
*/
|
|
129
|
+
export function makeBrainfishRESTResponseOriginalRequest(
|
|
130
|
+
request: {
|
|
131
|
+
name: string
|
|
132
|
+
method: BrainfishRESTRequest['method']
|
|
133
|
+
endpoint: string
|
|
134
|
+
params: BrainfishRESTRequest['params']
|
|
135
|
+
headers: BrainfishRESTRequest['headers']
|
|
136
|
+
body: BrainfishRESTRequest['body']
|
|
137
|
+
auth: BrainfishRESTRequest['auth']
|
|
138
|
+
requestVariables: BrainfishRESTRequest['requestVariables']
|
|
139
|
+
}
|
|
140
|
+
) {
|
|
141
|
+
return {
|
|
142
|
+
name: request.name,
|
|
143
|
+
method: request.method,
|
|
144
|
+
endpoint: request.endpoint,
|
|
145
|
+
params: request.params,
|
|
146
|
+
headers: request.headers,
|
|
147
|
+
body: request.body,
|
|
148
|
+
auth: request.auth,
|
|
149
|
+
requestVariables: request.requestVariables,
|
|
150
|
+
}
|
|
151
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Brainfish API Documentation - Main Export
|
|
3
|
+
*
|
|
4
|
+
* This module exports all types, factories, and utilities for the API documentation system.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// Types
|
|
8
|
+
export * from './types'
|
|
9
|
+
|
|
10
|
+
// Factories
|
|
11
|
+
export * from './factories'
|
|
12
|
+
|
|
13
|
+
// Utils
|
|
14
|
+
export * from './utils'
|
|
15
|
+
|
|
16
|
+
// Parsers
|
|
17
|
+
export * from './parsers/openapi'
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import { createContext, useContext, useState, useCallback, useEffect, type ReactNode } from 'react'
|
|
4
|
+
|
|
5
|
+
interface MobileContextValue {
|
|
6
|
+
// Sidebar visibility
|
|
7
|
+
isLeftSidebarOpen: boolean
|
|
8
|
+
isRightSidebarOpen: boolean
|
|
9
|
+
// Toggle functions
|
|
10
|
+
toggleLeftSidebar: () => void
|
|
11
|
+
toggleRightSidebar: () => void
|
|
12
|
+
openLeftSidebar: () => void
|
|
13
|
+
closeLeftSidebar: () => void
|
|
14
|
+
openRightSidebar: () => void
|
|
15
|
+
closeRightSidebar: () => void
|
|
16
|
+
// Close all sidebars (useful when navigating)
|
|
17
|
+
closeAllSidebars: () => void
|
|
18
|
+
// Mobile detection
|
|
19
|
+
isMobile: boolean
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const MobileContext = createContext<MobileContextValue | null>(null)
|
|
23
|
+
|
|
24
|
+
export function MobileProvider({ children }: { children: ReactNode }) {
|
|
25
|
+
const [isLeftSidebarOpen, setIsLeftSidebarOpen] = useState(false)
|
|
26
|
+
const [isRightSidebarOpen, setIsRightSidebarOpen] = useState(false)
|
|
27
|
+
const [isMobile, setIsMobile] = useState(false)
|
|
28
|
+
|
|
29
|
+
// Detect mobile on mount and window resize
|
|
30
|
+
useEffect(() => {
|
|
31
|
+
const checkMobile = () => {
|
|
32
|
+
setIsMobile(window.innerWidth < 1024) // lg breakpoint
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Initial check
|
|
36
|
+
checkMobile()
|
|
37
|
+
|
|
38
|
+
// Listen for resize
|
|
39
|
+
window.addEventListener('resize', checkMobile)
|
|
40
|
+
return () => window.removeEventListener('resize', checkMobile)
|
|
41
|
+
}, [])
|
|
42
|
+
|
|
43
|
+
// Close sidebars when switching to desktop
|
|
44
|
+
useEffect(() => {
|
|
45
|
+
if (!isMobile) {
|
|
46
|
+
setIsLeftSidebarOpen(false)
|
|
47
|
+
setIsRightSidebarOpen(false)
|
|
48
|
+
}
|
|
49
|
+
}, [isMobile])
|
|
50
|
+
|
|
51
|
+
const toggleLeftSidebar = useCallback(() => {
|
|
52
|
+
setIsLeftSidebarOpen(prev => !prev)
|
|
53
|
+
// Close right sidebar when opening left
|
|
54
|
+
setIsRightSidebarOpen(false)
|
|
55
|
+
}, [])
|
|
56
|
+
|
|
57
|
+
const toggleRightSidebar = useCallback(() => {
|
|
58
|
+
setIsRightSidebarOpen(prev => !prev)
|
|
59
|
+
// Close left sidebar when opening right
|
|
60
|
+
setIsLeftSidebarOpen(false)
|
|
61
|
+
}, [])
|
|
62
|
+
|
|
63
|
+
const openLeftSidebar = useCallback(() => {
|
|
64
|
+
setIsLeftSidebarOpen(true)
|
|
65
|
+
setIsRightSidebarOpen(false)
|
|
66
|
+
}, [])
|
|
67
|
+
|
|
68
|
+
const closeLeftSidebar = useCallback(() => {
|
|
69
|
+
setIsLeftSidebarOpen(false)
|
|
70
|
+
}, [])
|
|
71
|
+
|
|
72
|
+
const openRightSidebar = useCallback(() => {
|
|
73
|
+
setIsRightSidebarOpen(true)
|
|
74
|
+
setIsLeftSidebarOpen(false)
|
|
75
|
+
}, [])
|
|
76
|
+
|
|
77
|
+
const closeRightSidebar = useCallback(() => {
|
|
78
|
+
setIsRightSidebarOpen(false)
|
|
79
|
+
}, [])
|
|
80
|
+
|
|
81
|
+
const closeAllSidebars = useCallback(() => {
|
|
82
|
+
setIsLeftSidebarOpen(false)
|
|
83
|
+
setIsRightSidebarOpen(false)
|
|
84
|
+
}, [])
|
|
85
|
+
|
|
86
|
+
return (
|
|
87
|
+
<MobileContext.Provider
|
|
88
|
+
value={{
|
|
89
|
+
isLeftSidebarOpen,
|
|
90
|
+
isRightSidebarOpen,
|
|
91
|
+
toggleLeftSidebar,
|
|
92
|
+
toggleRightSidebar,
|
|
93
|
+
openLeftSidebar,
|
|
94
|
+
closeLeftSidebar,
|
|
95
|
+
openRightSidebar,
|
|
96
|
+
closeRightSidebar,
|
|
97
|
+
closeAllSidebars,
|
|
98
|
+
isMobile,
|
|
99
|
+
}}
|
|
100
|
+
>
|
|
101
|
+
{children}
|
|
102
|
+
</MobileContext.Provider>
|
|
103
|
+
)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export function useMobile() {
|
|
107
|
+
const context = useContext(MobileContext)
|
|
108
|
+
if (!context) {
|
|
109
|
+
throw new Error('useMobile must be used within a MobileProvider')
|
|
110
|
+
}
|
|
111
|
+
return context
|
|
112
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import { createContext, useContext, useCallback, type ReactNode } from 'react'
|
|
4
|
+
import type { BrainfishCollection, BrainfishRESTRequest } from './types'
|
|
5
|
+
|
|
6
|
+
interface NavigationContextValue {
|
|
7
|
+
/** Navigate to an endpoint by operationId or ID */
|
|
8
|
+
navigateToEndpoint: (operationIdOrId: string) => void
|
|
9
|
+
/** Current collection */
|
|
10
|
+
collection: BrainfishCollection | null
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const NavigationContext = createContext<NavigationContextValue | null>(null)
|
|
14
|
+
|
|
15
|
+
interface NavigationProviderProps {
|
|
16
|
+
children: ReactNode
|
|
17
|
+
collection: BrainfishCollection | null
|
|
18
|
+
onSelectRequest: (request: BrainfishRESTRequest) => void
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Helper to find request by operationId (name) or ID in collection
|
|
23
|
+
*/
|
|
24
|
+
function findRequestByOperationIdOrId(
|
|
25
|
+
collection: BrainfishCollection,
|
|
26
|
+
operationIdOrId: string
|
|
27
|
+
): BrainfishRESTRequest | null {
|
|
28
|
+
// Normalize the search term (handle both snake_case and the formatted name)
|
|
29
|
+
const normalizedSearch = operationIdOrId.toLowerCase().replace(/[\s-]/g, '_')
|
|
30
|
+
|
|
31
|
+
// Check direct requests
|
|
32
|
+
for (const request of collection.requests) {
|
|
33
|
+
// Check by ID
|
|
34
|
+
if (request.id === operationIdOrId) return request
|
|
35
|
+
// Check by name (operationId) - exact match
|
|
36
|
+
if (request.name.toLowerCase().replace(/[\s-]/g, '_') === normalizedSearch) return request
|
|
37
|
+
// Check by name - partial match (for formatted names like "Post Carts" -> "post_carts")
|
|
38
|
+
const requestNameNormalized = request.name.toLowerCase().replace(/[\s-]/g, '_')
|
|
39
|
+
if (requestNameNormalized === normalizedSearch) return request
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Check folders recursively
|
|
43
|
+
for (const folder of collection.folders) {
|
|
44
|
+
const request = findRequestByOperationIdOrId(folder, operationIdOrId)
|
|
45
|
+
if (request) return request
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return null
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function NavigationProvider({
|
|
52
|
+
children,
|
|
53
|
+
collection,
|
|
54
|
+
onSelectRequest
|
|
55
|
+
}: NavigationProviderProps) {
|
|
56
|
+
const navigateToEndpoint = useCallback((operationIdOrId: string) => {
|
|
57
|
+
if (!collection) {
|
|
58
|
+
console.warn('[Navigation] No collection available')
|
|
59
|
+
return
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const request = findRequestByOperationIdOrId(collection, operationIdOrId)
|
|
63
|
+
if (request) {
|
|
64
|
+
console.log('[Navigation] Navigating to endpoint:', request.name)
|
|
65
|
+
onSelectRequest(request)
|
|
66
|
+
} else {
|
|
67
|
+
console.warn('[Navigation] Endpoint not found:', operationIdOrId)
|
|
68
|
+
}
|
|
69
|
+
}, [collection, onSelectRequest])
|
|
70
|
+
|
|
71
|
+
return (
|
|
72
|
+
<NavigationContext.Provider value={{ navigateToEndpoint, collection }}>
|
|
73
|
+
{children}
|
|
74
|
+
</NavigationContext.Provider>
|
|
75
|
+
)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function useNavigation() {
|
|
79
|
+
const context = useContext(NavigationContext)
|
|
80
|
+
if (!context) {
|
|
81
|
+
// Return a no-op function if not in provider (for backwards compatibility)
|
|
82
|
+
return {
|
|
83
|
+
navigateToEndpoint: () => {},
|
|
84
|
+
collection: null
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return context
|
|
88
|
+
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# GraphQL Parser
|
|
2
|
+
|
|
3
|
+
This directory contains the GraphQL schema parsing logic for Brainfish API Docs.
|
|
4
|
+
|
|
5
|
+
## Structure
|
|
6
|
+
|
|
7
|
+
- `types.ts` - TypeScript types for GraphQL schema representation
|
|
8
|
+
- `parser.ts` - GraphQL SDL parsing using graphql-js
|
|
9
|
+
- `transformer.ts` - Convert GraphQL schema to BrainfishCollection
|
|
10
|
+
- `index.ts` - Main entry point and exports
|
|
11
|
+
|
|
12
|
+
## Dependencies Required
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm install graphql
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Usage
|
|
19
|
+
|
|
20
|
+
### Parse GraphQL Schema
|
|
21
|
+
|
|
22
|
+
```typescript
|
|
23
|
+
import { importGraphQLSchema } from '@/lib/api-docs/parsers/graphql'
|
|
24
|
+
|
|
25
|
+
// Parse SDL string
|
|
26
|
+
const collection = await importGraphQLSchema(sdlString, {
|
|
27
|
+
name: 'My GraphQL API',
|
|
28
|
+
endpoint: 'https://api.example.com/graphql',
|
|
29
|
+
})
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Get Full Schema Information
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
import { importGraphQLSchemaFull } from '@/lib/api-docs/parsers/graphql'
|
|
36
|
+
|
|
37
|
+
const graphqlCollection = await importGraphQLSchemaFull(sdlString, {
|
|
38
|
+
name: 'My GraphQL API',
|
|
39
|
+
endpoint: 'https://api.example.com/graphql',
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
// Access queries, mutations, subscriptions, and types
|
|
43
|
+
console.log(graphqlCollection.queries)
|
|
44
|
+
console.log(graphqlCollection.mutations)
|
|
45
|
+
console.log(graphqlCollection.types)
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Parse Schema Only
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
import { parseGraphQL } from '@/lib/api-docs/parsers/graphql'
|
|
52
|
+
|
|
53
|
+
const schema = await parseGraphQL(sdlString)
|
|
54
|
+
|
|
55
|
+
// Access schema information
|
|
56
|
+
console.log(schema.info)
|
|
57
|
+
console.log(schema.types)
|
|
58
|
+
console.log(schema.queries)
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Configuration in docs.json
|
|
62
|
+
|
|
63
|
+
Add a GraphQL tab to your navigation:
|
|
64
|
+
|
|
65
|
+
```json
|
|
66
|
+
{
|
|
67
|
+
"navigation": {
|
|
68
|
+
"tabs": [
|
|
69
|
+
{
|
|
70
|
+
"tab": "GraphQL API",
|
|
71
|
+
"type": "graphql",
|
|
72
|
+
"path": "/graphql",
|
|
73
|
+
"schema": "api-reference/schema.graphql",
|
|
74
|
+
"endpoint": "https://api.example.com/graphql"
|
|
75
|
+
}
|
|
76
|
+
]
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Multiple Schemas
|
|
82
|
+
|
|
83
|
+
```json
|
|
84
|
+
{
|
|
85
|
+
"navigation": {
|
|
86
|
+
"tabs": [
|
|
87
|
+
{
|
|
88
|
+
"tab": "GraphQL API",
|
|
89
|
+
"type": "graphql",
|
|
90
|
+
"path": "/graphql",
|
|
91
|
+
"schemas": [
|
|
92
|
+
{
|
|
93
|
+
"name": "Public API",
|
|
94
|
+
"schema": "api-reference/public.graphql",
|
|
95
|
+
"endpoint": "https://api.example.com/graphql",
|
|
96
|
+
"default": true
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
"name": "Admin API",
|
|
100
|
+
"schema": "api-reference/admin.graphql",
|
|
101
|
+
"endpoint": "https://admin.example.com/graphql"
|
|
102
|
+
}
|
|
103
|
+
]
|
|
104
|
+
}
|
|
105
|
+
]
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Features
|
|
111
|
+
|
|
112
|
+
- **SDL Parsing**: Parse GraphQL Schema Definition Language files
|
|
113
|
+
- **Introspection**: Support for introspection query results (planned)
|
|
114
|
+
- **Type Explorer**: View all types, inputs, enums, interfaces, unions
|
|
115
|
+
- **Operation Playground**: Test queries, mutations, and subscriptions
|
|
116
|
+
- **Variable Support**: Auto-generate example variables from schema
|
|
117
|
+
- **Documentation**: Extract descriptions from schema for docs
|
|
118
|
+
|
|
119
|
+
## Architecture
|
|
120
|
+
|
|
121
|
+
The GraphQL parser follows the same pattern as the OpenAPI parser:
|
|
122
|
+
|
|
123
|
+
1. **Parse**: Read SDL or introspection result
|
|
124
|
+
2. **Validate**: Ensure schema is valid GraphQL
|
|
125
|
+
3. **Transform**: Convert to internal types
|
|
126
|
+
4. **Export**: Generate BrainfishCollection for UI
|
|
127
|
+
|
|
128
|
+
This allows GraphQL APIs to use the same documentation UI as REST APIs,
|
|
129
|
+
with GraphQL-specific enhancements for the schema explorer and playground.
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GraphQL Parser Module
|
|
3
|
+
*
|
|
4
|
+
* Main entry point for GraphQL schema parsing and transformation.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export * from './types'
|
|
8
|
+
export * from './parser'
|
|
9
|
+
export * from './transformer'
|
|
10
|
+
|
|
11
|
+
import { parseGraphQLSchema, validateGraphQLSchema } from './parser'
|
|
12
|
+
import { convertGraphQLToBrainfishCollection, convertGraphQLToCollection } from './transformer'
|
|
13
|
+
import type { BrainfishCollection } from '../../types'
|
|
14
|
+
import type { BrainfishGraphQLCollection, GraphQLSchema } from './types'
|
|
15
|
+
|
|
16
|
+
export const GRAPHQL_INVALID_SCHEMA = 'graphql/invalid_schema' as const
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Import a GraphQL schema from SDL string or file content
|
|
20
|
+
* Returns a BrainfishCollection for integration with existing UI
|
|
21
|
+
*/
|
|
22
|
+
export async function importGraphQLSchema(
|
|
23
|
+
input: string,
|
|
24
|
+
options: {
|
|
25
|
+
name?: string
|
|
26
|
+
endpoint?: string
|
|
27
|
+
description?: string
|
|
28
|
+
} = {}
|
|
29
|
+
): Promise<BrainfishCollection> {
|
|
30
|
+
const {
|
|
31
|
+
name = 'GraphQL API',
|
|
32
|
+
endpoint = '/graphql',
|
|
33
|
+
description,
|
|
34
|
+
} = options
|
|
35
|
+
|
|
36
|
+
// Validate the schema
|
|
37
|
+
const validation = validateGraphQLSchema(input)
|
|
38
|
+
if (!validation.valid) {
|
|
39
|
+
throw new Error(`${GRAPHQL_INVALID_SCHEMA}: ${validation.error}`)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Parse the schema
|
|
43
|
+
const schema = parseGraphQLSchema(input)
|
|
44
|
+
|
|
45
|
+
// Convert to BrainfishCollection
|
|
46
|
+
return convertGraphQLToBrainfishCollection(schema, name, endpoint, description)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Import a GraphQL schema and return the full GraphQL collection
|
|
51
|
+
* with schema information preserved
|
|
52
|
+
*/
|
|
53
|
+
export async function importGraphQLSchemaFull(
|
|
54
|
+
input: string,
|
|
55
|
+
options: {
|
|
56
|
+
name?: string
|
|
57
|
+
endpoint?: string
|
|
58
|
+
description?: string
|
|
59
|
+
} = {}
|
|
60
|
+
): Promise<BrainfishGraphQLCollection> {
|
|
61
|
+
const {
|
|
62
|
+
name = 'GraphQL API',
|
|
63
|
+
endpoint = '/graphql',
|
|
64
|
+
description,
|
|
65
|
+
} = options
|
|
66
|
+
|
|
67
|
+
// Validate the schema
|
|
68
|
+
const validation = validateGraphQLSchema(input)
|
|
69
|
+
if (!validation.valid) {
|
|
70
|
+
throw new Error(`${GRAPHQL_INVALID_SCHEMA}: ${validation.error}`)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Parse the schema
|
|
74
|
+
const schema = parseGraphQLSchema(input)
|
|
75
|
+
|
|
76
|
+
// Convert to full GraphQL collection
|
|
77
|
+
return convertGraphQLToCollection(schema, name, endpoint, description)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Parse GraphQL schema without converting to collection
|
|
82
|
+
* Useful for schema exploration and type information
|
|
83
|
+
*/
|
|
84
|
+
export async function parseGraphQL(input: string): Promise<GraphQLSchema> {
|
|
85
|
+
const validation = validateGraphQLSchema(input)
|
|
86
|
+
if (!validation.valid) {
|
|
87
|
+
throw new Error(`${GRAPHQL_INVALID_SCHEMA}: ${validation.error}`)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return parseGraphQLSchema(input)
|
|
91
|
+
}
|