@brainfish-ai/devdoc 0.1.42 → 0.1.44
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/dist/cli/commands/create.js +2 -2
- package/dist/cli/commands/dev.js +19 -10
- package/package.json +3 -2
- package/renderer/app/api/assets/[...path]/route.js +108 -0
- package/renderer/app/api/assets/route.js +114 -0
- package/renderer/app/api/assets/upload/route.js +163 -0
- package/renderer/app/api/auth-schemes/route.js +58 -0
- package/renderer/app/api/chat/route.js +759 -0
- package/renderer/app/api/codegen/route.js +52 -0
- package/renderer/app/api/collections/route.js +706 -0
- package/renderer/app/api/debug/route.js +47 -0
- package/renderer/app/api/deploy/route.js +199 -0
- package/renderer/app/api/device/route.js +36 -0
- package/renderer/app/api/docs/route.js +205 -0
- package/renderer/app/api/domains/add/route.js +121 -0
- package/renderer/app/api/domains/lookup/route.js +43 -0
- package/renderer/app/api/domains/remove/route.js +89 -0
- package/renderer/app/api/domains/status/route.js +140 -0
- package/renderer/app/api/domains/verify/route.js +168 -0
- package/renderer/app/api/keys/regenerate/route.js +71 -0
- package/renderer/app/api/local-assets/[...path]/route.js +108 -0
- package/renderer/app/api/openapi-spec/route.js +73 -0
- package/renderer/app/api/projects/[slug]/route.js +129 -0
- package/renderer/app/api/projects/[slug]/stats/route.js +80 -0
- package/renderer/app/api/projects/register/route.js +176 -0
- package/renderer/app/api/proxy/route.js +139 -0
- package/renderer/app/api/proxy-stream/route.js +156 -0
- package/renderer/app/api/redirects/route.js +35 -0
- package/renderer/app/api/schema/route.js +85 -0
- package/renderer/app/api/subdomains/check/route.js +158 -0
- package/renderer/app/api/suggestions/route.js +195 -0
- package/renderer/app/globals.css +69 -0
- package/renderer/app/layout.js +47 -0
- package/renderer/app/llms-full.txt/route.js +266 -0
- package/renderer/app/llms.txt/route.js +228 -0
- package/renderer/app/page.js +12 -0
- package/renderer/app/robots.txt/route.js +66 -0
- package/renderer/app/sitemap.xml/route.js +155 -0
- package/renderer/components/docs/index.js +8 -0
- package/renderer/components/docs/mdx/accordion.js +113 -0
- package/renderer/components/docs/mdx/badge.js +72 -0
- package/renderer/components/docs/mdx/callouts.js +137 -0
- package/renderer/components/docs/mdx/cards.js +175 -0
- package/renderer/components/docs/mdx/changelog.js +100 -0
- package/renderer/components/docs/mdx/code-block.js +147 -0
- package/renderer/components/docs/mdx/code-group.js +287 -0
- package/renderer/components/docs/mdx/file-embeds.js +82 -0
- package/renderer/components/docs/mdx/frame.js +59 -0
- package/renderer/components/docs/mdx/highlight.js +90 -0
- package/renderer/components/docs/mdx/iframe.js +69 -0
- package/renderer/components/docs/mdx/image.js +135 -0
- package/renderer/components/docs/mdx/index.js +134 -0
- package/renderer/components/docs/mdx/landing.js +317 -0
- package/renderer/components/docs/mdx/mermaid.js +212 -0
- package/renderer/components/docs/mdx/param-field.js +112 -0
- package/renderer/components/docs/mdx/steps.js +74 -0
- package/renderer/components/docs/mdx/tabs.js +50 -0
- package/renderer/components/docs/mdx-renderer.js +77 -0
- package/renderer/components/docs/navigation/breadcrumbs.js +64 -0
- package/renderer/components/docs/navigation/index.js +6 -0
- package/renderer/components/docs/navigation/page-nav.js +57 -0
- package/renderer/components/docs/navigation/sidebar.js +375 -0
- package/renderer/components/docs/navigation/toc.js +89 -0
- package/renderer/components/docs/notice.js +77 -0
- package/renderer/components/docs-header.js +202 -0
- package/renderer/components/docs-viewer/agent/agent-chat.js +1831 -0
- package/renderer/components/docs-viewer/agent/agent-popup-button.js +99 -0
- package/renderer/components/docs-viewer/agent/cards/debug-context-card.js +107 -0
- package/renderer/components/docs-viewer/agent/cards/endpoint-context-card.js +57 -0
- package/renderer/components/docs-viewer/agent/cards/index.js +45 -0
- package/renderer/components/docs-viewer/agent/cards/response-options-card.js +154 -0
- package/renderer/components/docs-viewer/agent/cards/types.js +22 -0
- package/renderer/components/docs-viewer/agent/chat-message.js +2 -0
- package/renderer/components/docs-viewer/agent/index.js +7 -0
- package/renderer/components/docs-viewer/agent/messages/assistant-message.js +108 -0
- package/renderer/components/docs-viewer/agent/messages/chat-message.js +34 -0
- package/renderer/components/docs-viewer/agent/messages/index.js +6 -0
- package/renderer/components/docs-viewer/agent/messages/tool-call-display.js +1065 -0
- package/renderer/components/docs-viewer/agent/messages/types.js +2 -0
- package/renderer/components/docs-viewer/agent/messages/typing-indicator.js +26 -0
- package/renderer/components/docs-viewer/agent/messages/user-message.js +37 -0
- package/renderer/components/docs-viewer/code-editor/{index.tsx → index.js} +1 -1
- package/renderer/components/docs-viewer/code-editor/notes-mode.js +1338 -0
- package/renderer/components/docs-viewer/content/changelog-page.js +297 -0
- package/renderer/components/docs-viewer/content/content-router.js +182 -0
- package/renderer/components/docs-viewer/content/doc-page.js +290 -0
- package/renderer/components/docs-viewer/content/documentation-viewer.js +14 -0
- package/renderer/components/docs-viewer/content/index.js +31 -0
- package/renderer/components/docs-viewer/content/not-found-page.js +300 -0
- package/renderer/components/docs-viewer/content/request-details.js +528 -0
- package/renderer/components/docs-viewer/content/sections/auth.js +108 -0
- package/renderer/components/docs-viewer/content/sections/body.js +80 -0
- package/renderer/components/docs-viewer/content/sections/headers.js +64 -0
- package/renderer/components/docs-viewer/content/sections/overview.js +56 -0
- package/renderer/components/docs-viewer/content/sections/parameters.js +64 -0
- package/renderer/components/docs-viewer/content/sections/responses.js +91 -0
- package/renderer/components/docs-viewer/global-auth-modal.js +427 -0
- package/renderer/components/docs-viewer/index.js +1448 -0
- package/renderer/components/docs-viewer/playground/auth-editor.js +418 -0
- package/renderer/components/docs-viewer/playground/body-editor.js +240 -0
- package/renderer/components/docs-viewer/playground/code-editor.js +135 -0
- package/renderer/components/docs-viewer/playground/code-snippet.js +393 -0
- package/renderer/components/docs-viewer/playground/graphql-playground.js +936 -0
- package/renderer/components/docs-viewer/playground/index.js +682 -0
- package/renderer/components/docs-viewer/playground/key-value-editor.js +317 -0
- package/renderer/components/docs-viewer/playground/method-selector.js +65 -0
- package/renderer/components/docs-viewer/playground/request-builder.js +181 -0
- package/renderer/components/docs-viewer/playground/request-tabs.js +240 -0
- package/renderer/components/docs-viewer/playground/response-cards/idle-card.js +42 -0
- package/renderer/components/docs-viewer/playground/response-cards/index.js +72 -0
- package/renderer/components/docs-viewer/playground/response-cards/loading-card.js +24 -0
- package/renderer/components/docs-viewer/playground/response-cards/network-error-card.js +28 -0
- package/renderer/components/docs-viewer/playground/response-cards/response-body-card.js +308 -0
- package/renderer/components/docs-viewer/playground/response-cards/types.js +9 -0
- package/renderer/components/docs-viewer/playground/response-viewer.js +18 -0
- package/renderer/components/docs-viewer/search/index.js +2 -0
- package/renderer/components/docs-viewer/search/search-dialog.js +367 -0
- package/renderer/components/docs-viewer/search/use-search.js +89 -0
- package/renderer/components/docs-viewer/shared/markdown-renderer.js +423 -0
- package/renderer/components/docs-viewer/shared/method-badge.js +23 -0
- package/renderer/components/docs-viewer/shared/schema-viewer.js +321 -0
- package/renderer/components/docs-viewer/sidebar/collection-tree.js +222 -0
- package/renderer/components/docs-viewer/sidebar/endpoint-options.js +512 -0
- package/renderer/components/docs-viewer/sidebar/index.js +196 -0
- package/renderer/components/docs-viewer/sidebar/right-sidebar.js +159 -0
- package/renderer/components/docs-viewer/sidebar/sidebar-group.js +87 -0
- package/renderer/components/docs-viewer/sidebar/sidebar-item.js +172 -0
- package/renderer/components/docs-viewer/sidebar/sidebar-section.js +31 -0
- package/renderer/components/theme-provider.js +10 -0
- package/renderer/components/theme-toggle.js +86 -0
- package/renderer/components/ui/badge.js +29 -0
- package/renderer/components/ui/button.js +40 -0
- package/renderer/components/ui/dialog.js +50 -0
- package/renderer/components/ui/dropdown-menu.js +143 -0
- package/renderer/components/ui/input.js +12 -0
- package/renderer/components/ui/label.js +13 -0
- package/renderer/components/ui/navigation-menu.js +83 -0
- package/renderer/components/ui/select.js +116 -0
- package/renderer/components/ui/spinner.js +92 -0
- package/renderer/components/ui/tabs.js +34 -0
- package/renderer/components/ui/tooltip.js +43 -0
- package/renderer/hooks/use-code-copy.js +76 -0
- package/renderer/hooks/use-openapi-title.js +33 -0
- package/renderer/hooks/use-route-state.js +159 -0
- package/renderer/lib/api-docs/agent/index.js +4 -0
- package/renderer/lib/api-docs/agent/indexer.js +254 -0
- package/renderer/lib/api-docs/agent/spec-summary.js +227 -0
- package/renderer/lib/api-docs/agent/types.js +5 -0
- package/renderer/lib/api-docs/agent/use-suggestions.js +97 -0
- package/renderer/lib/api-docs/auth/auth-context.js +157 -0
- package/renderer/lib/api-docs/auth/auth-storage.js +66 -0
- package/renderer/lib/api-docs/auth/crypto.js +64 -0
- package/renderer/lib/api-docs/auth/index.js +3 -0
- package/renderer/lib/api-docs/code-editor/db.js +145 -0
- package/renderer/lib/api-docs/code-editor/hooks.js +254 -0
- package/renderer/lib/api-docs/code-editor/{index.ts → index.js} +3 -4
- package/renderer/lib/api-docs/code-editor/mode-context.js +126 -0
- package/renderer/lib/api-docs/code-editor/types.js +53 -0
- package/renderer/lib/api-docs/codegen/definitions.js +258 -0
- package/renderer/lib/api-docs/codegen/har.js +171 -0
- package/renderer/lib/api-docs/codegen/index.js +118 -0
- package/renderer/lib/api-docs/factories.js +136 -0
- package/renderer/lib/api-docs/{index.ts → index.js} +5 -10
- package/renderer/lib/api-docs/mobile-context.js +116 -0
- package/renderer/lib/api-docs/navigation-context.js +62 -0
- package/renderer/lib/api-docs/parsers/graphql/index.js +50 -0
- package/renderer/lib/api-docs/parsers/graphql/parser.js +350 -0
- package/renderer/lib/api-docs/parsers/graphql/transformer.js +215 -0
- package/renderer/lib/api-docs/parsers/graphql/types.js +46 -0
- package/renderer/lib/api-docs/parsers/openapi/dereferencer.js +43 -0
- package/renderer/lib/api-docs/parsers/openapi/extractors/auth.js +486 -0
- package/renderer/lib/api-docs/parsers/openapi/extractors/body.js +295 -0
- package/renderer/lib/api-docs/parsers/openapi/extractors/index.js +132 -0
- package/renderer/lib/api-docs/parsers/openapi/index.js +127 -0
- package/renderer/lib/api-docs/parsers/openapi/transformer.js +192 -0
- package/renderer/lib/api-docs/parsers/openapi/validator.js +24 -0
- package/renderer/lib/api-docs/playground/context.js +65 -0
- package/renderer/lib/api-docs/playground/navigation-context.js +74 -0
- package/renderer/lib/api-docs/playground/request-builder.js +163 -0
- package/renderer/lib/api-docs/playground/request-runner.js +224 -0
- package/renderer/lib/api-docs/playground/types.js +5 -0
- package/renderer/lib/api-docs/types.js +23 -0
- package/renderer/lib/api-docs/utils.js +212 -0
- package/renderer/lib/cache.js +157 -0
- package/renderer/lib/docs/config/domain-schema.js +161 -0
- package/renderer/lib/docs/config/environment.js +38 -0
- package/renderer/lib/docs/config/index.js +6 -0
- package/renderer/lib/docs/config/loader.js +113 -0
- package/renderer/lib/docs/config/schema.js +281 -0
- package/renderer/lib/docs/index.js +8 -0
- package/renderer/lib/docs/mdx/compiler.js +131 -0
- package/renderer/lib/docs/mdx/frontmatter.js +73 -0
- package/renderer/lib/docs/mdx/index.js +10 -0
- package/renderer/lib/docs/mdx/remark-mermaid.js +63 -0
- package/renderer/lib/docs/navigation/generator.js +269 -0
- package/renderer/lib/docs/navigation/index.js +3 -0
- package/renderer/lib/docs/navigation/types.js +11 -0
- package/renderer/lib/docs-navigation-context.js +40 -0
- package/renderer/lib/docs-navigation.js +140 -0
- package/renderer/lib/multi-tenant/context.js +80 -0
- package/renderer/lib/storage/blob.js +767 -0
- package/renderer/lib/utils/icons.js +30 -0
- package/renderer/lib/utils.js +5 -0
- package/renderer/next.config.js +62 -0
- package/renderer/package.json +1 -0
- package/renderer/tsconfig.json +23 -5
- package/renderer/app/api/assets/[...path]/route.ts +0 -123
- package/renderer/app/api/assets/route.ts +0 -124
- package/renderer/app/api/assets/upload/route.ts +0 -177
- package/renderer/app/api/auth-schemes/route.ts +0 -77
- package/renderer/app/api/chat/route.ts +0 -858
- package/renderer/app/api/codegen/route.ts +0 -72
- package/renderer/app/api/collections/route.ts +0 -1002
- package/renderer/app/api/debug/route.ts +0 -53
- package/renderer/app/api/deploy/route.ts +0 -234
- package/renderer/app/api/device/route.ts +0 -42
- package/renderer/app/api/docs/route.ts +0 -201
- package/renderer/app/api/domains/add/route.ts +0 -132
- package/renderer/app/api/domains/lookup/route.ts +0 -43
- package/renderer/app/api/domains/remove/route.ts +0 -100
- package/renderer/app/api/domains/status/route.ts +0 -158
- package/renderer/app/api/domains/verify/route.ts +0 -181
- package/renderer/app/api/keys/regenerate/route.ts +0 -80
- package/renderer/app/api/local-assets/[...path]/route.ts +0 -122
- package/renderer/app/api/openapi-spec/route.ts +0 -151
- package/renderer/app/api/projects/[slug]/route.ts +0 -153
- package/renderer/app/api/projects/[slug]/stats/route.ts +0 -96
- package/renderer/app/api/projects/register/route.ts +0 -152
- package/renderer/app/api/proxy/route.ts +0 -149
- package/renderer/app/api/proxy-stream/route.ts +0 -168
- package/renderer/app/api/redirects/route.ts +0 -47
- package/renderer/app/api/schema/route.ts +0 -73
- package/renderer/app/api/subdomains/check/route.ts +0 -172
- package/renderer/app/api/suggestions/route.ts +0 -144
- package/renderer/app/layout.tsx +0 -54
- package/renderer/app/llms-full.txt/route.ts +0 -346
- package/renderer/app/llms.txt/route.ts +0 -279
- package/renderer/app/page.tsx +0 -14
- package/renderer/app/robots.txt/route.ts +0 -84
- package/renderer/app/sitemap.xml/route.ts +0 -199
- package/renderer/components/docs/index.ts +0 -12
- package/renderer/components/docs/mdx/accordion.tsx +0 -169
- package/renderer/components/docs/mdx/badge.tsx +0 -132
- package/renderer/components/docs/mdx/callouts.tsx +0 -154
- package/renderer/components/docs/mdx/cards.tsx +0 -241
- package/renderer/components/docs/mdx/changelog.tsx +0 -120
- package/renderer/components/docs/mdx/code-block.tsx +0 -186
- package/renderer/components/docs/mdx/code-group.tsx +0 -421
- package/renderer/components/docs/mdx/file-embeds.tsx +0 -105
- package/renderer/components/docs/mdx/frame.tsx +0 -112
- package/renderer/components/docs/mdx/highlight.tsx +0 -151
- package/renderer/components/docs/mdx/iframe.tsx +0 -134
- package/renderer/components/docs/mdx/image.tsx +0 -235
- package/renderer/components/docs/mdx/index.ts +0 -237
- package/renderer/components/docs/mdx/landing.tsx +0 -684
- package/renderer/components/docs/mdx/mermaid.tsx +0 -240
- package/renderer/components/docs/mdx/param-field.tsx +0 -200
- package/renderer/components/docs/mdx/steps.tsx +0 -113
- package/renderer/components/docs/mdx/tabs.tsx +0 -86
- package/renderer/components/docs/mdx-renderer.tsx +0 -100
- package/renderer/components/docs/navigation/breadcrumbs.tsx +0 -76
- package/renderer/components/docs/navigation/index.ts +0 -8
- package/renderer/components/docs/navigation/page-nav.tsx +0 -64
- package/renderer/components/docs/navigation/sidebar.tsx +0 -515
- package/renderer/components/docs/navigation/toc.tsx +0 -113
- package/renderer/components/docs/notice.tsx +0 -105
- package/renderer/components/docs-header.tsx +0 -278
- package/renderer/components/docs-viewer/agent/agent-chat.tsx +0 -2076
- package/renderer/components/docs-viewer/agent/cards/debug-context-card.tsx +0 -90
- package/renderer/components/docs-viewer/agent/cards/endpoint-context-card.tsx +0 -49
- package/renderer/components/docs-viewer/agent/cards/index.tsx +0 -50
- package/renderer/components/docs-viewer/agent/cards/response-options-card.tsx +0 -212
- package/renderer/components/docs-viewer/agent/cards/types.ts +0 -84
- package/renderer/components/docs-viewer/agent/chat-message.tsx +0 -17
- package/renderer/components/docs-viewer/agent/index.tsx +0 -6
- package/renderer/components/docs-viewer/agent/messages/assistant-message.tsx +0 -119
- package/renderer/components/docs-viewer/agent/messages/chat-message.tsx +0 -46
- package/renderer/components/docs-viewer/agent/messages/index.ts +0 -17
- package/renderer/components/docs-viewer/agent/messages/tool-call-display.tsx +0 -721
- package/renderer/components/docs-viewer/agent/messages/types.ts +0 -61
- package/renderer/components/docs-viewer/agent/messages/typing-indicator.tsx +0 -24
- package/renderer/components/docs-viewer/agent/messages/user-message.tsx +0 -51
- package/renderer/components/docs-viewer/code-editor/notes-mode.tsx +0 -1283
- package/renderer/components/docs-viewer/content/changelog-page.tsx +0 -331
- package/renderer/components/docs-viewer/content/doc-page.tsx +0 -367
- package/renderer/components/docs-viewer/content/documentation-viewer.tsx +0 -17
- package/renderer/components/docs-viewer/content/index.tsx +0 -29
- package/renderer/components/docs-viewer/content/not-found-page.tsx +0 -330
- package/renderer/components/docs-viewer/content/request-details.tsx +0 -330
- package/renderer/components/docs-viewer/content/sections/auth.tsx +0 -69
- package/renderer/components/docs-viewer/content/sections/body.tsx +0 -66
- package/renderer/components/docs-viewer/content/sections/headers.tsx +0 -43
- package/renderer/components/docs-viewer/content/sections/overview.tsx +0 -40
- package/renderer/components/docs-viewer/content/sections/parameters.tsx +0 -43
- package/renderer/components/docs-viewer/content/sections/responses.tsx +0 -87
- package/renderer/components/docs-viewer/global-auth-modal.tsx +0 -352
- package/renderer/components/docs-viewer/index.tsx +0 -1670
- package/renderer/components/docs-viewer/playground/auth-editor.tsx +0 -280
- package/renderer/components/docs-viewer/playground/body-editor.tsx +0 -221
- package/renderer/components/docs-viewer/playground/code-editor.tsx +0 -224
- package/renderer/components/docs-viewer/playground/code-snippet.tsx +0 -387
- package/renderer/components/docs-viewer/playground/graphql-playground.tsx +0 -745
- package/renderer/components/docs-viewer/playground/index.tsx +0 -671
- package/renderer/components/docs-viewer/playground/key-value-editor.tsx +0 -261
- package/renderer/components/docs-viewer/playground/method-selector.tsx +0 -60
- package/renderer/components/docs-viewer/playground/request-builder.tsx +0 -179
- package/renderer/components/docs-viewer/playground/request-tabs.tsx +0 -237
- package/renderer/components/docs-viewer/playground/response-cards/idle-card.tsx +0 -21
- package/renderer/components/docs-viewer/playground/response-cards/index.tsx +0 -93
- package/renderer/components/docs-viewer/playground/response-cards/loading-card.tsx +0 -16
- package/renderer/components/docs-viewer/playground/response-cards/network-error-card.tsx +0 -23
- package/renderer/components/docs-viewer/playground/response-cards/response-body-card.tsx +0 -268
- package/renderer/components/docs-viewer/playground/response-cards/types.ts +0 -82
- package/renderer/components/docs-viewer/playground/response-viewer.tsx +0 -43
- package/renderer/components/docs-viewer/search/index.ts +0 -2
- package/renderer/components/docs-viewer/search/search-dialog.tsx +0 -331
- package/renderer/components/docs-viewer/search/use-search.ts +0 -117
- package/renderer/components/docs-viewer/shared/markdown-renderer.tsx +0 -431
- package/renderer/components/docs-viewer/shared/method-badge.tsx +0 -41
- package/renderer/components/docs-viewer/shared/schema-viewer.tsx +0 -349
- package/renderer/components/docs-viewer/sidebar/collection-tree.tsx +0 -259
- package/renderer/components/docs-viewer/sidebar/endpoint-options.tsx +0 -316
- package/renderer/components/docs-viewer/sidebar/index.tsx +0 -282
- package/renderer/components/docs-viewer/sidebar/right-sidebar.tsx +0 -202
- package/renderer/components/docs-viewer/sidebar/sidebar-group.tsx +0 -118
- package/renderer/components/docs-viewer/sidebar/sidebar-item.tsx +0 -212
- package/renderer/components/docs-viewer/sidebar/sidebar-section.tsx +0 -38
- package/renderer/components/theme-provider.tsx +0 -11
- package/renderer/components/theme-toggle.tsx +0 -76
- package/renderer/components/ui/badge.tsx +0 -46
- package/renderer/components/ui/button.tsx +0 -59
- package/renderer/components/ui/dialog.tsx +0 -118
- package/renderer/components/ui/dropdown-menu.tsx +0 -257
- package/renderer/components/ui/input.tsx +0 -21
- package/renderer/components/ui/label.tsx +0 -24
- package/renderer/components/ui/navigation-menu.tsx +0 -168
- package/renderer/components/ui/select.tsx +0 -190
- package/renderer/components/ui/spinner.tsx +0 -114
- package/renderer/components/ui/tabs.tsx +0 -66
- package/renderer/components/ui/tooltip.tsx +0 -61
- package/renderer/hooks/use-code-copy.ts +0 -88
- package/renderer/hooks/use-openapi-title.ts +0 -44
- package/renderer/lib/api-docs/agent/index.ts +0 -6
- package/renderer/lib/api-docs/agent/indexer.ts +0 -323
- package/renderer/lib/api-docs/agent/spec-summary.ts +0 -335
- package/renderer/lib/api-docs/agent/types.ts +0 -116
- package/renderer/lib/api-docs/auth/auth-context.tsx +0 -225
- package/renderer/lib/api-docs/auth/auth-storage.ts +0 -87
- package/renderer/lib/api-docs/auth/crypto.ts +0 -89
- package/renderer/lib/api-docs/auth/index.ts +0 -4
- package/renderer/lib/api-docs/code-editor/db.ts +0 -164
- package/renderer/lib/api-docs/code-editor/hooks.ts +0 -266
- package/renderer/lib/api-docs/code-editor/mode-context.tsx +0 -207
- package/renderer/lib/api-docs/code-editor/types.ts +0 -105
- package/renderer/lib/api-docs/codegen/definitions.ts +0 -297
- package/renderer/lib/api-docs/codegen/har.ts +0 -251
- package/renderer/lib/api-docs/codegen/index.ts +0 -159
- package/renderer/lib/api-docs/factories.ts +0 -170
- package/renderer/lib/api-docs/mobile-context.tsx +0 -112
- package/renderer/lib/api-docs/navigation-context.tsx +0 -88
- package/renderer/lib/api-docs/parsers/graphql/README.md +0 -129
- package/renderer/lib/api-docs/parsers/graphql/index.ts +0 -91
- package/renderer/lib/api-docs/parsers/graphql/parser.ts +0 -491
- package/renderer/lib/api-docs/parsers/graphql/transformer.ts +0 -246
- package/renderer/lib/api-docs/parsers/graphql/types.ts +0 -283
- package/renderer/lib/api-docs/parsers/openapi/README.md +0 -32
- package/renderer/lib/api-docs/parsers/openapi/dereferencer.ts +0 -60
- package/renderer/lib/api-docs/parsers/openapi/extractors/auth.ts +0 -574
- package/renderer/lib/api-docs/parsers/openapi/extractors/body.ts +0 -403
- package/renderer/lib/api-docs/parsers/openapi/extractors/index.ts +0 -232
- package/renderer/lib/api-docs/parsers/openapi/index.ts +0 -171
- package/renderer/lib/api-docs/parsers/openapi/transformer.ts +0 -278
- package/renderer/lib/api-docs/parsers/openapi/validator.ts +0 -31
- package/renderer/lib/api-docs/playground/context.tsx +0 -107
- package/renderer/lib/api-docs/playground/navigation-context.tsx +0 -124
- package/renderer/lib/api-docs/playground/request-builder.ts +0 -223
- package/renderer/lib/api-docs/playground/request-runner.ts +0 -282
- package/renderer/lib/api-docs/playground/types.ts +0 -35
- package/renderer/lib/api-docs/types.ts +0 -269
- package/renderer/lib/api-docs/utils.ts +0 -311
- package/renderer/lib/cache.ts +0 -193
- package/renderer/lib/docs/config/domain-schema.ts +0 -260
- package/renderer/lib/docs/config/index.ts +0 -43
- package/renderer/lib/docs/config/loader.ts +0 -142
- package/renderer/lib/docs/config/schema.ts +0 -308
- package/renderer/lib/docs/index.ts +0 -12
- package/renderer/lib/docs/mdx/compiler.ts +0 -176
- package/renderer/lib/docs/mdx/frontmatter.ts +0 -91
- package/renderer/lib/docs/mdx/index.ts +0 -26
- package/renderer/lib/docs/navigation/generator.ts +0 -348
- package/renderer/lib/docs/navigation/index.ts +0 -12
- package/renderer/lib/docs/navigation/types.ts +0 -123
- package/renderer/lib/docs-navigation-context.tsx +0 -80
- package/renderer/lib/multi-tenant/context.ts +0 -105
- package/renderer/lib/storage/blob.ts +0 -1083
- package/renderer/lib/utils/icons.ts +0 -48
- package/renderer/lib/utils.ts +0 -6
- package/renderer/next.config.ts +0 -76
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { createContext, useContext, useState, useEffect, useCallback, useRef } from 'react';
|
|
4
|
+
import { authStorage, fetchDeviceId } from './auth-storage';
|
|
5
|
+
const AuthContext = /*#__PURE__*/ createContext(null);
|
|
6
|
+
const DEFAULT_AUTH = {
|
|
7
|
+
authType: 'none',
|
|
8
|
+
authActive: true
|
|
9
|
+
};
|
|
10
|
+
export function AuthProvider({ children }) {
|
|
11
|
+
const [globalAuth, setGlobalAuthState] = useState(null);
|
|
12
|
+
const [isInitialized, setIsInitialized] = useState(false);
|
|
13
|
+
const [specSchemes, setSpecSchemes] = useState([]);
|
|
14
|
+
const [specDefaultAuth, setSpecDefaultAuth] = useState(null);
|
|
15
|
+
const deviceIdRef = useRef(null);
|
|
16
|
+
// Load auth from localStorage on mount (async with encryption)
|
|
17
|
+
useEffect(()=>{
|
|
18
|
+
async function initializeAuth() {
|
|
19
|
+
try {
|
|
20
|
+
// Fetch device ID from backend (required for encryption)
|
|
21
|
+
const deviceId = await fetchDeviceId();
|
|
22
|
+
deviceIdRef.current = deviceId;
|
|
23
|
+
// Load encrypted auth from storage
|
|
24
|
+
const stored = await authStorage.load(deviceId);
|
|
25
|
+
if (stored) {
|
|
26
|
+
setGlobalAuthState(stored);
|
|
27
|
+
}
|
|
28
|
+
// Fetch security schemes from the spec
|
|
29
|
+
const schemesResponse = await fetch('/api/auth-schemes');
|
|
30
|
+
if (schemesResponse.ok) {
|
|
31
|
+
const data = await schemesResponse.json();
|
|
32
|
+
setSpecSchemes(data.schemes || []);
|
|
33
|
+
setSpecDefaultAuth(data.defaultAuth || null);
|
|
34
|
+
}
|
|
35
|
+
} catch (error) {
|
|
36
|
+
console.error('[AuthProvider] Failed to initialize auth:', error);
|
|
37
|
+
// Clear any potentially corrupted data
|
|
38
|
+
authStorage.clear();
|
|
39
|
+
} finally{
|
|
40
|
+
setIsInitialized(true);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
initializeAuth();
|
|
44
|
+
}, []);
|
|
45
|
+
const setGlobalAuth = useCallback(async (auth)=>{
|
|
46
|
+
if (!deviceIdRef.current) {
|
|
47
|
+
console.error('[AuthProvider] Cannot save auth: no device ID');
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
setGlobalAuthState(auth);
|
|
51
|
+
await authStorage.save(auth, deviceIdRef.current);
|
|
52
|
+
}, []);
|
|
53
|
+
const clearAuth = useCallback(()=>{
|
|
54
|
+
setGlobalAuthState(null);
|
|
55
|
+
authStorage.clear();
|
|
56
|
+
}, []);
|
|
57
|
+
/**
|
|
58
|
+
* Get effective auth for an endpoint
|
|
59
|
+
* - If endpoint has 'inherit' auth type, use global auth
|
|
60
|
+
* - If endpoint has 'none' auth type and global is set, use global
|
|
61
|
+
* - Otherwise use endpoint's own auth
|
|
62
|
+
*/ const getEffectiveAuth = useCallback((endpointAuth)=>{
|
|
63
|
+
// If endpoint explicitly wants to inherit, use global
|
|
64
|
+
if (endpointAuth.authType === 'inherit') {
|
|
65
|
+
return globalAuth || DEFAULT_AUTH;
|
|
66
|
+
}
|
|
67
|
+
// If endpoint has no auth but global is configured, suggest global
|
|
68
|
+
// but don't override - this allows explicit "no auth" endpoints
|
|
69
|
+
if (endpointAuth.authType === 'none' && globalAuth && globalAuth.authType !== 'none') {
|
|
70
|
+
// Return global auth but the UI should indicate it's using global
|
|
71
|
+
return globalAuth;
|
|
72
|
+
}
|
|
73
|
+
// Use endpoint's own auth
|
|
74
|
+
return endpointAuth;
|
|
75
|
+
}, [
|
|
76
|
+
globalAuth
|
|
77
|
+
]);
|
|
78
|
+
/**
|
|
79
|
+
* Check if an endpoint is using global auth
|
|
80
|
+
*/ const isUsingGlobalAuth = useCallback((endpointAuth)=>{
|
|
81
|
+
if (!globalAuth || globalAuth.authType === 'none') {
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
// Using global if inheriting or if endpoint has no auth
|
|
85
|
+
return endpointAuth.authType === 'inherit' || endpointAuth.authType === 'none';
|
|
86
|
+
}, [
|
|
87
|
+
globalAuth
|
|
88
|
+
]);
|
|
89
|
+
const isAuthenticated = globalAuth !== null && globalAuth.authType !== 'none';
|
|
90
|
+
const value = {
|
|
91
|
+
globalAuth,
|
|
92
|
+
isAuthenticated,
|
|
93
|
+
setGlobalAuth,
|
|
94
|
+
clearAuth,
|
|
95
|
+
getEffectiveAuth,
|
|
96
|
+
isUsingGlobalAuth,
|
|
97
|
+
specSchemes,
|
|
98
|
+
specDefaultAuth
|
|
99
|
+
};
|
|
100
|
+
// Don't render until we've checked sessionStorage
|
|
101
|
+
if (!isInitialized) {
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
return /*#__PURE__*/ _jsx(AuthContext.Provider, {
|
|
105
|
+
value: value,
|
|
106
|
+
children: children
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
export function useAuth() {
|
|
110
|
+
const context = useContext(AuthContext);
|
|
111
|
+
if (!context) {
|
|
112
|
+
throw new Error('useAuth must be used within an AuthProvider');
|
|
113
|
+
}
|
|
114
|
+
return context;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Get a human-readable label for auth type
|
|
118
|
+
*/ export function getAuthTypeLabel(auth) {
|
|
119
|
+
if (!auth || !auth.authType) {
|
|
120
|
+
return 'Not configured';
|
|
121
|
+
}
|
|
122
|
+
switch(auth.authType){
|
|
123
|
+
case 'none':
|
|
124
|
+
return 'No Auth';
|
|
125
|
+
case 'inherit':
|
|
126
|
+
return 'Inherited';
|
|
127
|
+
case 'basic':
|
|
128
|
+
return 'Basic Auth';
|
|
129
|
+
case 'bearer':
|
|
130
|
+
return 'Bearer Token';
|
|
131
|
+
case 'api-key':
|
|
132
|
+
return `API Key (${auth.key || 'key'})`;
|
|
133
|
+
case 'oauth-2':
|
|
134
|
+
return 'OAuth 2.0';
|
|
135
|
+
default:
|
|
136
|
+
return 'Not configured';
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Get a masked preview of auth value
|
|
141
|
+
*/ export function getAuthPreview(auth) {
|
|
142
|
+
switch(auth.authType){
|
|
143
|
+
case 'none':
|
|
144
|
+
case 'inherit':
|
|
145
|
+
return '';
|
|
146
|
+
case 'basic':
|
|
147
|
+
return auth.username ? `${auth.username}:****` : '';
|
|
148
|
+
case 'bearer':
|
|
149
|
+
return auth.token ? `${auth.token.slice(0, 8)}••••` : '';
|
|
150
|
+
case 'api-key':
|
|
151
|
+
return auth.value ? `${auth.value.slice(0, 4)}••••` : '';
|
|
152
|
+
case 'oauth-2':
|
|
153
|
+
return auth.grantTypeInfo.token ? `${auth.grantTypeInfo.token.slice(0, 8)}••••` : '';
|
|
154
|
+
default:
|
|
155
|
+
return '';
|
|
156
|
+
}
|
|
157
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { encrypt, decrypt } from './crypto';
|
|
3
|
+
const AUTH_STORAGE_KEY = 'brainfish-api-global-auth';
|
|
4
|
+
/**
|
|
5
|
+
* Fetch device ID from backend API
|
|
6
|
+
* The device ID is stored in an httpOnly cookie
|
|
7
|
+
* Throws error if device ID cannot be fetched (no fallback)
|
|
8
|
+
*/ export async function fetchDeviceId() {
|
|
9
|
+
const response = await fetch('/api/device', {
|
|
10
|
+
credentials: 'include'
|
|
11
|
+
});
|
|
12
|
+
if (!response.ok) {
|
|
13
|
+
throw new Error('Failed to fetch device ID');
|
|
14
|
+
}
|
|
15
|
+
const data = await response.json();
|
|
16
|
+
if (!data.deviceId) {
|
|
17
|
+
throw new Error('No device ID returned from server');
|
|
18
|
+
}
|
|
19
|
+
return data.deviceId;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Encrypted localStorage wrapper for global authentication
|
|
23
|
+
* Uses device ID from backend as encryption key
|
|
24
|
+
* No fallbacks - encryption is required
|
|
25
|
+
*/ export const authStorage = {
|
|
26
|
+
/**
|
|
27
|
+
* Save auth configuration to localStorage (encrypted)
|
|
28
|
+
* Requires valid device ID - throws if missing
|
|
29
|
+
*/ async save (auth, deviceId) {
|
|
30
|
+
if (!deviceId) {
|
|
31
|
+
throw new Error('Device ID required for secure storage');
|
|
32
|
+
}
|
|
33
|
+
const data = {
|
|
34
|
+
globalAuth: auth,
|
|
35
|
+
timestamp: Date.now()
|
|
36
|
+
};
|
|
37
|
+
const encrypted = await encrypt(JSON.stringify(data), deviceId);
|
|
38
|
+
localStorage.setItem(AUTH_STORAGE_KEY, encrypted);
|
|
39
|
+
},
|
|
40
|
+
/**
|
|
41
|
+
* Load auth configuration from localStorage (decrypted)
|
|
42
|
+
* Returns null if no data or decryption fails
|
|
43
|
+
*/ async load (deviceId) {
|
|
44
|
+
if (!deviceId) return null;
|
|
45
|
+
const stored = localStorage.getItem(AUTH_STORAGE_KEY);
|
|
46
|
+
if (!stored) return null;
|
|
47
|
+
try {
|
|
48
|
+
const jsonData = await decrypt(stored, deviceId);
|
|
49
|
+
const data = JSON.parse(jsonData);
|
|
50
|
+
if (!data.globalAuth?.authType) {
|
|
51
|
+
localStorage.removeItem(AUTH_STORAGE_KEY);
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
return data.globalAuth;
|
|
55
|
+
} catch {
|
|
56
|
+
// Decryption failed - clear corrupted/invalid data
|
|
57
|
+
localStorage.removeItem(AUTH_STORAGE_KEY);
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
/**
|
|
62
|
+
* Clear stored auth configuration
|
|
63
|
+
*/ clear () {
|
|
64
|
+
localStorage.removeItem(AUTH_STORAGE_KEY);
|
|
65
|
+
}
|
|
66
|
+
};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
/**
|
|
3
|
+
* Web Crypto API utilities for encrypting/decrypting auth credentials
|
|
4
|
+
* Uses AES-GCM with a key derived from device ID
|
|
5
|
+
*/ const ALGORITHM = 'AES-GCM';
|
|
6
|
+
const KEY_LENGTH = 256;
|
|
7
|
+
const IV_LENGTH = 12 // 96 bits for AES-GCM
|
|
8
|
+
;
|
|
9
|
+
/**
|
|
10
|
+
* Derive a crypto key from a device ID using PBKDF2
|
|
11
|
+
*/ async function deriveKey(deviceId) {
|
|
12
|
+
const encoder = new TextEncoder();
|
|
13
|
+
const keyMaterial = await crypto.subtle.importKey('raw', encoder.encode(deviceId), 'PBKDF2', false, [
|
|
14
|
+
'deriveKey'
|
|
15
|
+
]);
|
|
16
|
+
// Use a fixed salt (could be made dynamic per-user if needed)
|
|
17
|
+
const salt = encoder.encode('brainfish-api-docs-v1');
|
|
18
|
+
return crypto.subtle.deriveKey({
|
|
19
|
+
name: 'PBKDF2',
|
|
20
|
+
salt,
|
|
21
|
+
iterations: 100000,
|
|
22
|
+
hash: 'SHA-256'
|
|
23
|
+
}, keyMaterial, {
|
|
24
|
+
name: ALGORITHM,
|
|
25
|
+
length: KEY_LENGTH
|
|
26
|
+
}, false, [
|
|
27
|
+
'encrypt',
|
|
28
|
+
'decrypt'
|
|
29
|
+
]);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Encrypt a string using AES-GCM with device ID as key
|
|
33
|
+
*/ export async function encrypt(plaintext, deviceId) {
|
|
34
|
+
const key = await deriveKey(deviceId);
|
|
35
|
+
const encoder = new TextEncoder();
|
|
36
|
+
const data = encoder.encode(plaintext);
|
|
37
|
+
// Generate random IV
|
|
38
|
+
const iv = crypto.getRandomValues(new Uint8Array(IV_LENGTH));
|
|
39
|
+
const encrypted = await crypto.subtle.encrypt({
|
|
40
|
+
name: ALGORITHM,
|
|
41
|
+
iv
|
|
42
|
+
}, key, data);
|
|
43
|
+
// Combine IV + encrypted data and encode as base64
|
|
44
|
+
const combined = new Uint8Array(iv.length + encrypted.byteLength);
|
|
45
|
+
combined.set(iv);
|
|
46
|
+
combined.set(new Uint8Array(encrypted), iv.length);
|
|
47
|
+
return btoa(String.fromCharCode(...combined));
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Decrypt a string using AES-GCM with device ID as key
|
|
51
|
+
*/ export async function decrypt(ciphertext, deviceId) {
|
|
52
|
+
const key = await deriveKey(deviceId);
|
|
53
|
+
// Decode base64
|
|
54
|
+
const combined = Uint8Array.from(atob(ciphertext), (c)=>c.charCodeAt(0));
|
|
55
|
+
// Extract IV and encrypted data
|
|
56
|
+
const iv = combined.slice(0, IV_LENGTH);
|
|
57
|
+
const encrypted = combined.slice(IV_LENGTH);
|
|
58
|
+
const decrypted = await crypto.subtle.decrypt({
|
|
59
|
+
name: ALGORITHM,
|
|
60
|
+
iv
|
|
61
|
+
}, key, encrypted);
|
|
62
|
+
const decoder = new TextDecoder();
|
|
63
|
+
return decoder.decode(decrypted);
|
|
64
|
+
}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
function _define_property(obj, key, value) {
|
|
2
|
+
if (key in obj) {
|
|
3
|
+
Object.defineProperty(obj, key, {
|
|
4
|
+
value: value,
|
|
5
|
+
enumerable: true,
|
|
6
|
+
configurable: true,
|
|
7
|
+
writable: true
|
|
8
|
+
});
|
|
9
|
+
} else {
|
|
10
|
+
obj[key] = value;
|
|
11
|
+
}
|
|
12
|
+
return obj;
|
|
13
|
+
}
|
|
14
|
+
import Dexie from 'dexie';
|
|
15
|
+
/**
|
|
16
|
+
* Simplified database for Notes workspace
|
|
17
|
+
* - One workspace per API (not multiple projects)
|
|
18
|
+
* - Notes are files for brainstorming (code, diagrams, markdown)
|
|
19
|
+
*/ class NotesDatabase extends Dexie {
|
|
20
|
+
constructor(){
|
|
21
|
+
super('brainfish-notes'), _define_property(this, "workspaces", void 0), _define_property(this, "notes", void 0), _define_property(this, "editorStates", void 0);
|
|
22
|
+
this.version(1).stores({
|
|
23
|
+
// Single workspace per API
|
|
24
|
+
workspaces: 'id, apiSpecUrl, updatedAt',
|
|
25
|
+
// Notes/files in workspace
|
|
26
|
+
notes: 'id, workspaceId, [workspaceId+path], updatedAt',
|
|
27
|
+
// Editor state per workspace
|
|
28
|
+
editorStates: 'workspaceId'
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
// Singleton database instance
|
|
33
|
+
export const db = new NotesDatabase();
|
|
34
|
+
/**
|
|
35
|
+
* Generate a workspace ID from API spec URL
|
|
36
|
+
*/ export function getWorkspaceId(apiSpecUrl) {
|
|
37
|
+
// Simple hash for consistent ID
|
|
38
|
+
let hash = 0;
|
|
39
|
+
for(let i = 0; i < apiSpecUrl.length; i++){
|
|
40
|
+
const char = apiSpecUrl.charCodeAt(i);
|
|
41
|
+
hash = (hash << 5) - hash + char;
|
|
42
|
+
hash = hash & hash; // Convert to 32-bit integer
|
|
43
|
+
}
|
|
44
|
+
return `ws-${Math.abs(hash).toString(16)}`;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Database operations - simplified for notes workspace
|
|
48
|
+
*/ export const dbOperations = {
|
|
49
|
+
// Workspace operations (auto-created, one per API)
|
|
50
|
+
async getOrCreateWorkspace (apiSpecUrl, name) {
|
|
51
|
+
const id = getWorkspaceId(apiSpecUrl);
|
|
52
|
+
let workspace = await db.workspaces.get(id);
|
|
53
|
+
if (!workspace) {
|
|
54
|
+
workspace = {
|
|
55
|
+
id,
|
|
56
|
+
name,
|
|
57
|
+
apiSpecUrl,
|
|
58
|
+
createdAt: new Date(),
|
|
59
|
+
updatedAt: new Date()
|
|
60
|
+
};
|
|
61
|
+
await db.workspaces.add(workspace);
|
|
62
|
+
}
|
|
63
|
+
return workspace;
|
|
64
|
+
},
|
|
65
|
+
async getWorkspace (id) {
|
|
66
|
+
return db.workspaces.get(id);
|
|
67
|
+
},
|
|
68
|
+
async updateWorkspace (id, updates) {
|
|
69
|
+
await db.workspaces.update(id, {
|
|
70
|
+
...updates,
|
|
71
|
+
updatedAt: new Date()
|
|
72
|
+
});
|
|
73
|
+
},
|
|
74
|
+
// Note/file operations
|
|
75
|
+
async createNote (workspaceId, path, content = '') {
|
|
76
|
+
const note = {
|
|
77
|
+
id: crypto.randomUUID(),
|
|
78
|
+
workspaceId,
|
|
79
|
+
path,
|
|
80
|
+
content,
|
|
81
|
+
createdAt: new Date(),
|
|
82
|
+
updatedAt: new Date()
|
|
83
|
+
};
|
|
84
|
+
await db.notes.add(note);
|
|
85
|
+
// Update workspace timestamp
|
|
86
|
+
await db.workspaces.update(workspaceId, {
|
|
87
|
+
updatedAt: new Date()
|
|
88
|
+
});
|
|
89
|
+
return note;
|
|
90
|
+
},
|
|
91
|
+
async getNote (workspaceId, path) {
|
|
92
|
+
return db.notes.where('[workspaceId+path]').equals([
|
|
93
|
+
workspaceId,
|
|
94
|
+
path
|
|
95
|
+
]).first();
|
|
96
|
+
},
|
|
97
|
+
async listNotes (workspaceId) {
|
|
98
|
+
return db.notes.where('workspaceId').equals(workspaceId).toArray();
|
|
99
|
+
},
|
|
100
|
+
async updateNote (workspaceId, path, content) {
|
|
101
|
+
await db.notes.where('[workspaceId+path]').equals([
|
|
102
|
+
workspaceId,
|
|
103
|
+
path
|
|
104
|
+
]).modify({
|
|
105
|
+
content,
|
|
106
|
+
updatedAt: new Date()
|
|
107
|
+
});
|
|
108
|
+
await db.workspaces.update(workspaceId, {
|
|
109
|
+
updatedAt: new Date()
|
|
110
|
+
});
|
|
111
|
+
},
|
|
112
|
+
async deleteNote (workspaceId, path) {
|
|
113
|
+
await db.notes.where('[workspaceId+path]').equals([
|
|
114
|
+
workspaceId,
|
|
115
|
+
path
|
|
116
|
+
]).delete();
|
|
117
|
+
await db.workspaces.update(workspaceId, {
|
|
118
|
+
updatedAt: new Date()
|
|
119
|
+
});
|
|
120
|
+
},
|
|
121
|
+
async renameNote (workspaceId, oldPath, newPath) {
|
|
122
|
+
await db.notes.where('[workspaceId+path]').equals([
|
|
123
|
+
workspaceId,
|
|
124
|
+
oldPath
|
|
125
|
+
]).modify({
|
|
126
|
+
path: newPath,
|
|
127
|
+
updatedAt: new Date()
|
|
128
|
+
});
|
|
129
|
+
await db.workspaces.update(workspaceId, {
|
|
130
|
+
updatedAt: new Date()
|
|
131
|
+
});
|
|
132
|
+
},
|
|
133
|
+
// Editor state operations
|
|
134
|
+
async getEditorState (workspaceId) {
|
|
135
|
+
return db.editorStates.get(workspaceId);
|
|
136
|
+
},
|
|
137
|
+
async saveEditorState (state) {
|
|
138
|
+
await db.editorStates.put(state);
|
|
139
|
+
},
|
|
140
|
+
// Clear all notes in workspace (reset)
|
|
141
|
+
async clearWorkspace (workspaceId) {
|
|
142
|
+
await db.notes.where('workspaceId').equals(workspaceId).delete();
|
|
143
|
+
await db.editorStates.delete(workspaceId);
|
|
144
|
+
}
|
|
145
|
+
};
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { useState, useEffect, useCallback } from 'react';
|
|
3
|
+
import { dbOperations } from './db';
|
|
4
|
+
/**
|
|
5
|
+
* Hook for managing the workspace (auto-created per API)
|
|
6
|
+
*/ export function useWorkspace(apiSpecUrl, apiName = 'API Notes') {
|
|
7
|
+
const [workspace, setWorkspace] = useState(null);
|
|
8
|
+
const [loading, setLoading] = useState(true);
|
|
9
|
+
const [error, setError] = useState(null);
|
|
10
|
+
useEffect(()=>{
|
|
11
|
+
if (!apiSpecUrl) {
|
|
12
|
+
setWorkspace(null);
|
|
13
|
+
setLoading(false);
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
const loadWorkspace = async ()=>{
|
|
17
|
+
try {
|
|
18
|
+
setLoading(true);
|
|
19
|
+
const ws = await dbOperations.getOrCreateWorkspace(apiSpecUrl, `${apiName} Notes`);
|
|
20
|
+
setWorkspace(ws);
|
|
21
|
+
setError(null);
|
|
22
|
+
} catch (err) {
|
|
23
|
+
setError(err instanceof Error ? err : new Error('Failed to load workspace'));
|
|
24
|
+
} finally{
|
|
25
|
+
setLoading(false);
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
loadWorkspace();
|
|
29
|
+
}, [
|
|
30
|
+
apiSpecUrl,
|
|
31
|
+
apiName
|
|
32
|
+
]);
|
|
33
|
+
const clearWorkspace = useCallback(async ()=>{
|
|
34
|
+
if (!workspace) return;
|
|
35
|
+
await dbOperations.clearWorkspace(workspace.id);
|
|
36
|
+
}, [
|
|
37
|
+
workspace
|
|
38
|
+
]);
|
|
39
|
+
return {
|
|
40
|
+
workspace,
|
|
41
|
+
loading,
|
|
42
|
+
error,
|
|
43
|
+
clearWorkspace,
|
|
44
|
+
workspaceId: workspace?.id || null
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Hook for managing notes/files in the workspace
|
|
49
|
+
*/ export function useNotes(workspaceId) {
|
|
50
|
+
const [notes, setNotes] = useState([]);
|
|
51
|
+
const [loading, setLoading] = useState(true);
|
|
52
|
+
const [error, setError] = useState(null);
|
|
53
|
+
const loadNotes = useCallback(async ()=>{
|
|
54
|
+
if (!workspaceId) {
|
|
55
|
+
setNotes([]);
|
|
56
|
+
setLoading(false);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
try {
|
|
60
|
+
setLoading(true);
|
|
61
|
+
const list = await dbOperations.listNotes(workspaceId);
|
|
62
|
+
setNotes(list);
|
|
63
|
+
setError(null);
|
|
64
|
+
} catch (err) {
|
|
65
|
+
setError(err instanceof Error ? err : new Error('Failed to load notes'));
|
|
66
|
+
} finally{
|
|
67
|
+
setLoading(false);
|
|
68
|
+
}
|
|
69
|
+
}, [
|
|
70
|
+
workspaceId
|
|
71
|
+
]);
|
|
72
|
+
useEffect(()=>{
|
|
73
|
+
loadNotes();
|
|
74
|
+
}, [
|
|
75
|
+
loadNotes
|
|
76
|
+
]);
|
|
77
|
+
const createNote = useCallback(async (path, content = '')=>{
|
|
78
|
+
if (!workspaceId) return null;
|
|
79
|
+
const note = await dbOperations.createNote(workspaceId, path, content);
|
|
80
|
+
setNotes((prev)=>[
|
|
81
|
+
...prev,
|
|
82
|
+
note
|
|
83
|
+
]);
|
|
84
|
+
return note;
|
|
85
|
+
}, [
|
|
86
|
+
workspaceId
|
|
87
|
+
]);
|
|
88
|
+
const readNote = useCallback(async (path)=>{
|
|
89
|
+
if (!workspaceId) return '';
|
|
90
|
+
const note = await dbOperations.getNote(workspaceId, path);
|
|
91
|
+
return note?.content || '';
|
|
92
|
+
}, [
|
|
93
|
+
workspaceId
|
|
94
|
+
]);
|
|
95
|
+
const updateNote = useCallback(async (path, content)=>{
|
|
96
|
+
if (!workspaceId) return;
|
|
97
|
+
await dbOperations.updateNote(workspaceId, path, content);
|
|
98
|
+
setNotes((prev)=>prev.map((n)=>n.path === path ? {
|
|
99
|
+
...n,
|
|
100
|
+
content,
|
|
101
|
+
updatedAt: new Date()
|
|
102
|
+
} : n));
|
|
103
|
+
}, [
|
|
104
|
+
workspaceId
|
|
105
|
+
]);
|
|
106
|
+
const deleteNote = useCallback(async (path)=>{
|
|
107
|
+
if (!workspaceId) return;
|
|
108
|
+
await dbOperations.deleteNote(workspaceId, path);
|
|
109
|
+
setNotes((prev)=>prev.filter((n)=>n.path !== path));
|
|
110
|
+
}, [
|
|
111
|
+
workspaceId
|
|
112
|
+
]);
|
|
113
|
+
const renameNote = useCallback(async (oldPath, newPath)=>{
|
|
114
|
+
if (!workspaceId) return;
|
|
115
|
+
await dbOperations.renameNote(workspaceId, oldPath, newPath);
|
|
116
|
+
setNotes((prev)=>prev.map((n)=>n.path === oldPath ? {
|
|
117
|
+
...n,
|
|
118
|
+
path: newPath,
|
|
119
|
+
updatedAt: new Date()
|
|
120
|
+
} : n));
|
|
121
|
+
}, [
|
|
122
|
+
workspaceId
|
|
123
|
+
]);
|
|
124
|
+
const deleteAllNotes = useCallback(async ()=>{
|
|
125
|
+
if (!workspaceId) return;
|
|
126
|
+
await dbOperations.clearWorkspace(workspaceId);
|
|
127
|
+
setNotes([]);
|
|
128
|
+
}, [
|
|
129
|
+
workspaceId
|
|
130
|
+
]);
|
|
131
|
+
return {
|
|
132
|
+
notes,
|
|
133
|
+
loading,
|
|
134
|
+
error,
|
|
135
|
+
createNote,
|
|
136
|
+
readNote,
|
|
137
|
+
updateNote,
|
|
138
|
+
deleteNote,
|
|
139
|
+
deleteAllNotes,
|
|
140
|
+
renameNote,
|
|
141
|
+
refresh: loadNotes
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Hook for managing editor state (tabs, active file, etc.)
|
|
146
|
+
*/ export function useEditorState(workspaceId) {
|
|
147
|
+
const [state, setState] = useState(null);
|
|
148
|
+
// Load saved state
|
|
149
|
+
useEffect(()=>{
|
|
150
|
+
if (!workspaceId) {
|
|
151
|
+
setState(null);
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
const loadState = async ()=>{
|
|
155
|
+
const saved = await dbOperations.getEditorState(workspaceId);
|
|
156
|
+
if (saved) {
|
|
157
|
+
setState(saved);
|
|
158
|
+
} else {
|
|
159
|
+
// Initialize new state
|
|
160
|
+
setState({
|
|
161
|
+
workspaceId,
|
|
162
|
+
openTabs: [],
|
|
163
|
+
activeTab: null,
|
|
164
|
+
cursorPositions: {},
|
|
165
|
+
scrollPositions: {}
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
loadState();
|
|
170
|
+
}, [
|
|
171
|
+
workspaceId
|
|
172
|
+
]);
|
|
173
|
+
// Save state when it changes
|
|
174
|
+
useEffect(()=>{
|
|
175
|
+
if (state && workspaceId) {
|
|
176
|
+
dbOperations.saveEditorState(state);
|
|
177
|
+
}
|
|
178
|
+
}, [
|
|
179
|
+
state,
|
|
180
|
+
workspaceId
|
|
181
|
+
]);
|
|
182
|
+
const openTab = useCallback(async (path)=>{
|
|
183
|
+
setState((prev)=>{
|
|
184
|
+
if (!prev) return prev;
|
|
185
|
+
const newTabs = prev.openTabs.includes(path) ? prev.openTabs : [
|
|
186
|
+
...prev.openTabs,
|
|
187
|
+
path
|
|
188
|
+
];
|
|
189
|
+
return {
|
|
190
|
+
...prev,
|
|
191
|
+
openTabs: newTabs,
|
|
192
|
+
activeTab: path
|
|
193
|
+
};
|
|
194
|
+
});
|
|
195
|
+
}, []);
|
|
196
|
+
const closeTab = useCallback((path)=>{
|
|
197
|
+
setState((prev)=>{
|
|
198
|
+
if (!prev) return prev;
|
|
199
|
+
const newTabs = prev.openTabs.filter((t)=>t !== path);
|
|
200
|
+
const newActive = prev.activeTab === path ? newTabs[newTabs.length - 1] || null : prev.activeTab;
|
|
201
|
+
return {
|
|
202
|
+
...prev,
|
|
203
|
+
openTabs: newTabs,
|
|
204
|
+
activeTab: newActive
|
|
205
|
+
};
|
|
206
|
+
});
|
|
207
|
+
}, []);
|
|
208
|
+
const setActiveTab = useCallback((path)=>{
|
|
209
|
+
setState((prev)=>{
|
|
210
|
+
if (!prev) return prev;
|
|
211
|
+
return {
|
|
212
|
+
...prev,
|
|
213
|
+
activeTab: path
|
|
214
|
+
};
|
|
215
|
+
});
|
|
216
|
+
}, []);
|
|
217
|
+
const saveCursorPosition = useCallback((path, line, column)=>{
|
|
218
|
+
setState((prev)=>{
|
|
219
|
+
if (!prev) return prev;
|
|
220
|
+
return {
|
|
221
|
+
...prev,
|
|
222
|
+
cursorPositions: {
|
|
223
|
+
...prev.cursorPositions,
|
|
224
|
+
[path]: {
|
|
225
|
+
line,
|
|
226
|
+
column
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
});
|
|
231
|
+
}, []);
|
|
232
|
+
const clearAllTabs = useCallback(()=>{
|
|
233
|
+
setState((prev)=>{
|
|
234
|
+
if (!prev) return prev;
|
|
235
|
+
return {
|
|
236
|
+
...prev,
|
|
237
|
+
openTabs: [],
|
|
238
|
+
activeTab: null,
|
|
239
|
+
cursorPositions: {},
|
|
240
|
+
scrollPositions: {}
|
|
241
|
+
};
|
|
242
|
+
});
|
|
243
|
+
}, []);
|
|
244
|
+
return {
|
|
245
|
+
state,
|
|
246
|
+
openTab,
|
|
247
|
+
closeTab,
|
|
248
|
+
setActiveTab,
|
|
249
|
+
saveCursorPosition,
|
|
250
|
+
clearAllTabs
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
export { getFileType, getMonacoLanguage, supportsPreview } from './types';
|
|
254
|
+
export { getWorkspaceId } from './db';
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
// Notes workspace - simplified code editor for brainstorming
|
|
2
2
|
// Not for building apps, just for organizing ideas around APIs
|
|
3
|
-
|
|
4
|
-
export * from './
|
|
5
|
-
export
|
|
6
|
-
export { useModeContext, ModeProvider } from './mode-context'
|
|
3
|
+
export * from './types';
|
|
4
|
+
export * from './hooks';
|
|
5
|
+
export { useModeContext, ModeProvider } from './mode-context';
|