insforge 0.3.1

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 (395) hide show
  1. package/.dockerignore +58 -0
  2. package/.env.example +49 -0
  3. package/.github/ISSUE_TEMPLATE/bug_report.yml +83 -0
  4. package/.github/ISSUE_TEMPLATE/config.yml +11 -0
  5. package/.github/ISSUE_TEMPLATE/feature_request.yml +79 -0
  6. package/.github/copilot-instructions.md +147 -0
  7. package/.github/workflows/build-image.yml +65 -0
  8. package/.github/workflows/ci-premerge-check.yml +24 -0
  9. package/.github/workflows/deploy-aws.yml +130 -0
  10. package/.github/workflows/lint-and-format.yml +33 -0
  11. package/.prettierignore +65 -0
  12. package/.prettierrc +9 -0
  13. package/CHANGELOG.md +3 -0
  14. package/CONTRIBUTING.md +126 -0
  15. package/Dockerfile +27 -0
  16. package/GITHUB_OAUTH_SETUP.md +49 -0
  17. package/GOOGLE_OAUTH_SETUP.md +148 -0
  18. package/LICENSE +201 -0
  19. package/README.md +134 -0
  20. package/assets/Dark.svg +23 -0
  21. package/assets/archDiagram.png +0 -0
  22. package/assets/banner.png +0 -0
  23. package/assets/mcpInstallv2.png +0 -0
  24. package/assets/sampleResponse.png +0 -0
  25. package/assets/signin.png +0 -0
  26. package/assets/userflow.png +0 -0
  27. package/backend/migrations/000_create-base-tables.sql +142 -0
  28. package/backend/migrations/001_create-helper-functions.sql +41 -0
  29. package/backend/migrations/002_rename-auth-tables.sql +30 -0
  30. package/backend/migrations/003_create-users-table.sql +56 -0
  31. package/backend/migrations/004_add-reload-postgrest-func.sql +24 -0
  32. package/backend/migrations/005_enable-project-admin-modify-users.sql +30 -0
  33. package/backend/migrations/006_modify-ai-usage-table.sql +25 -0
  34. package/backend/migrations/007_drop-metadata-table.sql +2 -0
  35. package/backend/migrations/008_add-system-tables.sql +77 -0
  36. package/backend/migrations/009_add-function-secrets.sql +24 -0
  37. package/backend/migrations/010_modify-ai-config-modalities.sql +93 -0
  38. package/backend/migrations/011_refactor-secrets-table.sql +15 -0
  39. package/backend/migrations/012_add-storage-uploaded-by.sql +8 -0
  40. package/backend/package.json +75 -0
  41. package/backend/src/api/middleware/auth.ts +240 -0
  42. package/backend/src/api/middleware/error.ts +231 -0
  43. package/backend/src/api/middleware/upload.ts +59 -0
  44. package/backend/src/api/routes/agent.ts +29 -0
  45. package/backend/src/api/routes/ai.ts +472 -0
  46. package/backend/src/api/routes/auth.oauth.ts +482 -0
  47. package/backend/src/api/routes/auth.ts +386 -0
  48. package/backend/src/api/routes/database.advance.ts +275 -0
  49. package/backend/src/api/routes/database.records.ts +246 -0
  50. package/backend/src/api/routes/database.tables.ts +161 -0
  51. package/backend/src/api/routes/docs.ts +66 -0
  52. package/backend/src/api/routes/functions.ts +183 -0
  53. package/backend/src/api/routes/logs.ts +150 -0
  54. package/backend/src/api/routes/metadata.ts +160 -0
  55. package/backend/src/api/routes/openapi.ts +82 -0
  56. package/backend/src/api/routes/secrets.ts +199 -0
  57. package/backend/src/api/routes/storage.ts +547 -0
  58. package/backend/src/api/routes/usage.ts +96 -0
  59. package/backend/src/core/ai/chat.ts +207 -0
  60. package/backend/src/core/ai/client.ts +242 -0
  61. package/backend/src/core/ai/config.ts +187 -0
  62. package/backend/src/core/ai/image.ts +156 -0
  63. package/backend/src/core/ai/model.ts +117 -0
  64. package/backend/src/core/ai/usage.ts +290 -0
  65. package/backend/src/core/auth/auth.ts +781 -0
  66. package/backend/src/core/auth/oauth.ts +398 -0
  67. package/backend/src/core/database/advance.ts +1074 -0
  68. package/backend/src/core/database/manager.ts +178 -0
  69. package/backend/src/core/database/table.ts +772 -0
  70. package/backend/src/core/documentation/agent.ts +689 -0
  71. package/backend/src/core/documentation/openapi.ts +856 -0
  72. package/backend/src/core/functions/functions.ts +310 -0
  73. package/backend/src/core/logs/analytics.ts +76 -0
  74. package/backend/src/core/logs/audit.ts +255 -0
  75. package/backend/src/core/logs/providers/base.provider.ts +83 -0
  76. package/backend/src/core/logs/providers/cloudwatch.provider.ts +510 -0
  77. package/backend/src/core/logs/providers/localdb.provider.ts +246 -0
  78. package/backend/src/core/secrets/encryption.ts +58 -0
  79. package/backend/src/core/secrets/secrets.ts +410 -0
  80. package/backend/src/core/socket/socket.ts +388 -0
  81. package/backend/src/core/socket/types.ts +79 -0
  82. package/backend/src/core/storage/storage.ts +923 -0
  83. package/backend/src/server.ts +288 -0
  84. package/backend/src/types/ai.ts +46 -0
  85. package/backend/src/types/auth.ts +90 -0
  86. package/backend/src/types/database.ts +136 -0
  87. package/backend/src/types/error-constants.ts +86 -0
  88. package/backend/src/types/logs.ts +47 -0
  89. package/backend/src/types/profile.ts +55 -0
  90. package/backend/src/types/storage.ts +23 -0
  91. package/backend/src/utils/cloud-token.ts +39 -0
  92. package/backend/src/utils/constants.ts +1 -0
  93. package/backend/src/utils/environment.ts +35 -0
  94. package/backend/src/utils/helpers.ts +49 -0
  95. package/backend/src/utils/logger.ts +13 -0
  96. package/backend/src/utils/response.ts +62 -0
  97. package/backend/src/utils/seed.ts +205 -0
  98. package/backend/src/utils/sql-parser.ts +63 -0
  99. package/backend/src/utils/uuid.ts +9 -0
  100. package/backend/src/utils/validations.ts +129 -0
  101. package/backend/tests/README.md +134 -0
  102. package/backend/tests/cleanup-all-test-data.sh +231 -0
  103. package/backend/tests/cloud/test-s3-multitenant.sh +132 -0
  104. package/backend/tests/local/comprehensive-curl-tests.sh +156 -0
  105. package/backend/tests/local/test-auth-router.sh +144 -0
  106. package/backend/tests/local/test-database-router.sh +222 -0
  107. package/backend/tests/local/test-e2e.sh +241 -0
  108. package/backend/tests/local/test-fk-errors.sh +97 -0
  109. package/backend/tests/local/test-id-field.sh +201 -0
  110. package/backend/tests/local/test-public-bucket.sh +265 -0
  111. package/backend/tests/local/test-secrets.sh +248 -0
  112. package/backend/tests/local/test-serverless-functions.sh.disabled +325 -0
  113. package/backend/tests/local/test-traditional-rest.sh +209 -0
  114. package/backend/tests/manual/README.md +51 -0
  115. package/backend/tests/manual/create-large-table-simple.sql +11 -0
  116. package/backend/tests/manual/seed-large-table.sql +101 -0
  117. package/backend/tests/manual/setup-large-table-extras.sql +34 -0
  118. package/backend/tests/manual/test-better-auth.sh +303 -0
  119. package/backend/tests/manual/test-bulk-upsert.sh +410 -0
  120. package/backend/tests/manual/test-database-advance.sh +297 -0
  121. package/backend/tests/manual/test-postgrest-stability.sh +192 -0
  122. package/backend/tests/manual/test-rawsql-export-import.sh +412 -0
  123. package/backend/tests/manual/test-universal-storage.sh +264 -0
  124. package/backend/tests/manual/test-users.sql +18 -0
  125. package/backend/tests/run-all-tests.sh +140 -0
  126. package/backend/tests/setup.ts +22 -0
  127. package/backend/tests/test-config.sh +303 -0
  128. package/backend/tsconfig.json +23 -0
  129. package/backend/tsup.config.ts +18 -0
  130. package/backend/vitest.config.ts +22 -0
  131. package/docker-compose.prod.yml +145 -0
  132. package/docker-compose.yml +167 -0
  133. package/docker-init/db/db-init.sql +125 -0
  134. package/docker-init/db/jwt.sql +5 -0
  135. package/docker-init/db/logs.sql +9 -0
  136. package/docker-init/db/postgresql.conf +17 -0
  137. package/docs/deprecated/insforge-auth-api.md +215 -0
  138. package/docs/deprecated/insforge-auth-sdk.md +100 -0
  139. package/docs/deprecated/insforge-db-api.md +359 -0
  140. package/docs/deprecated/insforge-db-sdk.md +140 -0
  141. package/docs/deprecated/insforge-debug-sdk.md +157 -0
  142. package/docs/deprecated/insforge-debug.md +65 -0
  143. package/docs/deprecated/insforge-instructions.md +124 -0
  144. package/docs/deprecated/insforge-project.md +118 -0
  145. package/docs/deprecated/insforge-storage-api.md +279 -0
  146. package/docs/deprecated/insforge-storage-sdk.md +159 -0
  147. package/docs/insforge-instructions-sdk.md +407 -0
  148. package/eslint.config.js +317 -0
  149. package/examples/oauth/frontend-oauth-example.html +251 -0
  150. package/examples/response-examples.md +444 -0
  151. package/frontend/README.md +112 -0
  152. package/frontend/components.json +17 -0
  153. package/frontend/index.html +13 -0
  154. package/frontend/package.json +63 -0
  155. package/frontend/public/favicon.ico +0 -0
  156. package/frontend/src/App.tsx +106 -0
  157. package/frontend/src/assets/icons/checkbox_checked.svg +6 -0
  158. package/frontend/src/assets/icons/checkbox_undetermined.svg +6 -0
  159. package/frontend/src/assets/icons/checked.svg +3 -0
  160. package/frontend/src/assets/icons/error.svg +3 -0
  161. package/frontend/src/assets/icons/pencil.svg +4 -0
  162. package/frontend/src/assets/icons/refresh.svg +4 -0
  163. package/frontend/src/assets/icons/step_active.svg +3 -0
  164. package/frontend/src/assets/icons/step_inactive.svg +11 -0
  165. package/frontend/src/assets/icons/warning.svg +3 -0
  166. package/frontend/src/assets/logos/amazon.svg +1 -0
  167. package/frontend/src/assets/logos/claude_code.svg +3 -0
  168. package/frontend/src/assets/logos/cline.svg +6 -0
  169. package/frontend/src/assets/logos/cursor.svg +20 -0
  170. package/frontend/src/assets/logos/discord.svg +9 -0
  171. package/frontend/src/assets/logos/gemini.svg +19 -0
  172. package/frontend/src/assets/logos/github.svg +5 -0
  173. package/frontend/src/assets/logos/google.svg +13 -0
  174. package/frontend/src/assets/logos/grok.svg +10 -0
  175. package/frontend/src/assets/logos/insforge_dark.svg +15 -0
  176. package/frontend/src/assets/logos/insforge_light.svg +15 -0
  177. package/frontend/src/assets/logos/openai.svg +10 -0
  178. package/frontend/src/assets/logos/roo_code.svg +9 -0
  179. package/frontend/src/assets/logos/trae.svg +3 -0
  180. package/frontend/src/assets/logos/windsurf.svg +10 -0
  181. package/frontend/src/components/ButtonWithLoading.tsx +27 -0
  182. package/frontend/src/components/Checkbox.tsx +61 -0
  183. package/frontend/src/components/CodeBlock.tsx +32 -0
  184. package/frontend/src/components/ConfirmDialog.tsx +96 -0
  185. package/frontend/src/components/CopyButton.tsx +69 -0
  186. package/frontend/src/components/DeleteActionButton.tsx +42 -0
  187. package/frontend/src/components/EmptyState.tsx +41 -0
  188. package/frontend/src/components/ErrorState.tsx +35 -0
  189. package/frontend/src/components/FeatureSidebar.tsx +126 -0
  190. package/frontend/src/components/FeatureSidebarItem.tsx +101 -0
  191. package/frontend/src/components/JsonHighlight.tsx +61 -0
  192. package/frontend/src/components/LoadingState.tsx +16 -0
  193. package/frontend/src/components/PaginationControls.tsx +54 -0
  194. package/frontend/src/components/PromptDialog.tsx +68 -0
  195. package/frontend/src/components/SearchInput.tsx +90 -0
  196. package/frontend/src/components/SelectionClearButton.tsx +26 -0
  197. package/frontend/src/components/Stepper.tsx +139 -0
  198. package/frontend/src/components/ThemeToggle.tsx +58 -0
  199. package/frontend/src/components/TypeBadge.tsx +20 -0
  200. package/frontend/src/components/datagrid/DataGrid.tsx +264 -0
  201. package/frontend/src/components/datagrid/DefaultCellRenderer.tsx +114 -0
  202. package/frontend/src/components/datagrid/IdCell.tsx +44 -0
  203. package/frontend/src/components/datagrid/SortableHeader.tsx +74 -0
  204. package/frontend/src/components/datagrid/cell-editors/BooleanCellEditor.tsx +54 -0
  205. package/frontend/src/components/datagrid/cell-editors/DateCellEditor.tsx +483 -0
  206. package/frontend/src/components/datagrid/cell-editors/JsonCellEditor.tsx +362 -0
  207. package/frontend/src/components/datagrid/cell-editors/TextCellEditor.tsx +38 -0
  208. package/frontend/src/components/datagrid/cell-editors/index.ts +14 -0
  209. package/frontend/src/components/datagrid/cell-editors/types.ts +43 -0
  210. package/frontend/src/components/datagrid/datagridTypes.tsx +72 -0
  211. package/frontend/src/components/datagrid/index.tsx +20 -0
  212. package/frontend/src/components/index.ts +39 -0
  213. package/frontend/src/components/layout/AppHeader.tsx +146 -0
  214. package/frontend/src/components/layout/AppSidebar.tsx +190 -0
  215. package/frontend/src/components/layout/CloudLayout.tsx +95 -0
  216. package/frontend/src/components/layout/Layout.tsx +43 -0
  217. package/frontend/src/components/radix/Alert.tsx +45 -0
  218. package/frontend/src/components/radix/AlertDialog.tsx +115 -0
  219. package/frontend/src/components/radix/Avatar.tsx +45 -0
  220. package/frontend/src/components/radix/Badge.tsx +33 -0
  221. package/frontend/src/components/radix/Button.tsx +50 -0
  222. package/frontend/src/components/radix/Card.tsx +58 -0
  223. package/frontend/src/components/radix/Dialog.tsx +98 -0
  224. package/frontend/src/components/radix/DropdownMenu.tsx +185 -0
  225. package/frontend/src/components/radix/Form.tsx +167 -0
  226. package/frontend/src/components/radix/Input.tsx +22 -0
  227. package/frontend/src/components/radix/Label.tsx +19 -0
  228. package/frontend/src/components/radix/Popover.tsx +29 -0
  229. package/frontend/src/components/radix/ScrollArea.tsx +44 -0
  230. package/frontend/src/components/radix/Select.tsx +151 -0
  231. package/frontend/src/components/radix/Separator.tsx +26 -0
  232. package/frontend/src/components/radix/Sheet.tsx +119 -0
  233. package/frontend/src/components/radix/Skeleton.tsx +7 -0
  234. package/frontend/src/components/radix/Switch.tsx +29 -0
  235. package/frontend/src/components/radix/Tabs.tsx +50 -0
  236. package/frontend/src/components/radix/Textarea.tsx +21 -0
  237. package/frontend/src/components/radix/Tooltip.tsx +28 -0
  238. package/frontend/src/features/ai/components/AIConfigCard.tsx +154 -0
  239. package/frontend/src/features/ai/components/AIConfigDialog.tsx +76 -0
  240. package/frontend/src/features/ai/components/AIConfigForm.tsx +222 -0
  241. package/frontend/src/features/ai/components/AIEmptyState.tsx +18 -0
  242. package/frontend/src/features/ai/components/fields/ModalityField.tsx +87 -0
  243. package/frontend/src/features/ai/components/fields/ModelSelectionField.tsx +134 -0
  244. package/frontend/src/features/ai/components/fields/SystemPromptField.tsx +33 -0
  245. package/frontend/src/features/ai/helpers.ts +155 -0
  246. package/frontend/src/features/ai/hooks/useAIConfigs.ts +221 -0
  247. package/frontend/src/features/ai/hooks/useAIUsage.ts +77 -0
  248. package/frontend/src/features/ai/page/AIPage.tsx +178 -0
  249. package/frontend/src/features/ai/services/ai.service.ts +148 -0
  250. package/frontend/src/features/auth/components/AddOAuthDialog.tsx +106 -0
  251. package/frontend/src/features/auth/components/AuthMethodTab.tsx +238 -0
  252. package/frontend/src/features/auth/components/OAuthConfigDialog.tsx +303 -0
  253. package/frontend/src/features/auth/components/OAuthEmptyState.tsx +15 -0
  254. package/frontend/src/features/auth/components/UserFormDialog.tsx +248 -0
  255. package/frontend/src/features/auth/components/UsersDataGrid.tsx +183 -0
  256. package/frontend/src/features/auth/components/UsersTab.tsx +114 -0
  257. package/frontend/src/features/auth/hooks/useOAuthConfig.ts +129 -0
  258. package/frontend/src/features/auth/hooks/useUsers.ts +57 -0
  259. package/frontend/src/features/auth/index.ts +9 -0
  260. package/frontend/src/features/auth/page/AuthenticationPage.tsx +169 -0
  261. package/frontend/src/features/auth/services/auth.service.ts +112 -0
  262. package/frontend/src/features/auth/services/oauth.service.ts +49 -0
  263. package/frontend/src/features/dashboard/page/DashboardPage.tsx +194 -0
  264. package/frontend/src/features/database/components/ColumnTypeSelect.tsx +64 -0
  265. package/frontend/src/features/database/components/DatabaseDataGrid.tsx +282 -0
  266. package/frontend/src/features/database/components/ForeignKeyCell.tsx +187 -0
  267. package/frontend/src/features/database/components/ForeignKeyPopover.tsx +378 -0
  268. package/frontend/src/features/database/components/LinkRecordModal.tsx +288 -0
  269. package/frontend/src/features/database/components/RecordFormDialog.tsx +164 -0
  270. package/frontend/src/features/database/components/RecordFormField.tsx +568 -0
  271. package/frontend/src/features/database/components/TableEmptyState.tsx +21 -0
  272. package/frontend/src/features/database/components/TableForm.tsx +656 -0
  273. package/frontend/src/features/database/components/TableFormColumn.tsx +137 -0
  274. package/frontend/src/features/database/components/TableListSkeleton.tsx +9 -0
  275. package/frontend/src/features/database/components/TableSidebar.tsx +47 -0
  276. package/frontend/src/features/database/constants.ts +26 -0
  277. package/frontend/src/features/database/helpers.ts +125 -0
  278. package/frontend/src/features/database/hooks/UseLinkModal.tsx +78 -0
  279. package/frontend/src/features/database/index.ts +12 -0
  280. package/frontend/src/features/database/page/DatabasePage.tsx +626 -0
  281. package/frontend/src/features/database/schema.ts +25 -0
  282. package/frontend/src/features/database/services/database.service.ts +216 -0
  283. package/frontend/src/features/functions/components/FunctionEmptyState.tsx +15 -0
  284. package/frontend/src/features/functions/components/FunctionRow.tsx +71 -0
  285. package/frontend/src/features/functions/components/FunctionViewer.tsx +46 -0
  286. package/frontend/src/features/functions/components/FunctionsContent.tsx +88 -0
  287. package/frontend/src/features/functions/components/FunctionsSidebar.tsx +56 -0
  288. package/frontend/src/features/functions/components/SecretEmptyState.tsx +23 -0
  289. package/frontend/src/features/functions/components/SecretRow.tsx +68 -0
  290. package/frontend/src/features/functions/components/SecretsContent.tsx +120 -0
  291. package/frontend/src/features/functions/hooks/useFunctions.ts +106 -0
  292. package/frontend/src/features/functions/page/FunctionsPage.tsx +28 -0
  293. package/frontend/src/features/functions/services/functions.service.ts +48 -0
  294. package/frontend/src/features/login/components/AuthErrorBoundary.tsx +87 -0
  295. package/frontend/src/features/login/components/PrivateRoute.tsx +24 -0
  296. package/frontend/src/features/login/page/CloudLoginPage.tsx +93 -0
  297. package/frontend/src/features/login/page/LoginPage.tsx +174 -0
  298. package/frontend/src/features/logs/components/AnalyticsLogsTable.tsx +313 -0
  299. package/frontend/src/features/logs/components/LogsTable.tsx +199 -0
  300. package/frontend/src/features/logs/hooks/useAuditLogs.ts +39 -0
  301. package/frontend/src/features/logs/index.ts +5 -0
  302. package/frontend/src/features/logs/page/AnalyticsLogsPage.tsx +530 -0
  303. package/frontend/src/features/logs/page/AuditsPage.tsx +192 -0
  304. package/frontend/src/features/logs/services/log.service.ts +171 -0
  305. package/frontend/src/features/metadata/hooks/useMetadata.ts +53 -0
  306. package/frontend/src/features/metadata/index.ts +0 -0
  307. package/frontend/src/features/metadata/page/MetadataPage.tsx +136 -0
  308. package/frontend/src/features/metadata/services/metadata.service.ts +17 -0
  309. package/frontend/src/features/onboard/components/CompletionCard.tsx +41 -0
  310. package/frontend/src/features/onboard/components/OnboardButton.tsx +84 -0
  311. package/frontend/src/features/onboard/components/StepContent.tsx +91 -0
  312. package/frontend/src/features/onboard/components/TestConnectionStep.tsx +53 -0
  313. package/frontend/src/features/onboard/components/mcp/CursorDeeplinkGenerator.tsx +35 -0
  314. package/frontend/src/features/onboard/components/mcp/McpInstallation.tsx +144 -0
  315. package/frontend/src/features/onboard/components/mcp/index.ts +4 -0
  316. package/frontend/src/features/onboard/components/mcp/mcp-helper.tsx +98 -0
  317. package/frontend/src/features/onboard/index.ts +3 -0
  318. package/frontend/src/features/onboard/page/OnBoardPage.tsx +104 -0
  319. package/frontend/src/features/onboard/types.ts +8 -0
  320. package/frontend/src/features/secrets/hooks/useSecrets.ts +139 -0
  321. package/frontend/src/features/secrets/services/secrets.service.ts +57 -0
  322. package/frontend/src/features/storage/components/BucketEmptyState.tsx +19 -0
  323. package/frontend/src/features/storage/components/BucketFormDialog.tsx +194 -0
  324. package/frontend/src/features/storage/components/BucketListSkeleton.tsx +17 -0
  325. package/frontend/src/features/storage/components/FilePreviewDialog.tsx +287 -0
  326. package/frontend/src/features/storage/components/StorageDataGrid.tsx +239 -0
  327. package/frontend/src/features/storage/components/StorageManager.tsx +236 -0
  328. package/frontend/src/features/storage/components/StorageSidebar.tsx +44 -0
  329. package/frontend/src/features/storage/components/UploadToast.tsx +46 -0
  330. package/frontend/src/features/storage/index.ts +3 -0
  331. package/frontend/src/features/storage/page/StoragePage.tsx +553 -0
  332. package/frontend/src/features/storage/services/storage.service.ts +144 -0
  333. package/frontend/src/features/visualizer/components/AuthNode.tsx +107 -0
  334. package/frontend/src/features/visualizer/components/BucketNode.tsx +34 -0
  335. package/frontend/src/features/visualizer/components/SchemaVisualizer.tsx +359 -0
  336. package/frontend/src/features/visualizer/components/TableNode.tsx +152 -0
  337. package/frontend/src/features/visualizer/components/VisualizerSkeleton.tsx +24 -0
  338. package/frontend/src/features/visualizer/components/index.ts +5 -0
  339. package/frontend/src/features/visualizer/page/VisualizerPage.tsx +127 -0
  340. package/frontend/src/index.css +248 -0
  341. package/frontend/src/lib/api/client.ts +163 -0
  342. package/frontend/src/lib/contexts/AuthContext.tsx +157 -0
  343. package/frontend/src/lib/contexts/OnboardStepContext.tsx +68 -0
  344. package/frontend/src/lib/contexts/SocketContext.tsx +303 -0
  345. package/frontend/src/lib/contexts/ThemeContext.tsx +125 -0
  346. package/frontend/src/lib/hooks/useAuth.ts +4 -0
  347. package/frontend/src/lib/hooks/useConfirm.ts +55 -0
  348. package/frontend/src/lib/hooks/useInterval.ts +27 -0
  349. package/frontend/src/lib/hooks/useMediaQuery.ts +59 -0
  350. package/frontend/src/lib/hooks/useOnboardingCompletion.ts +29 -0
  351. package/frontend/src/lib/hooks/usePagination.ts +27 -0
  352. package/frontend/src/lib/hooks/useTimeout.ts +27 -0
  353. package/frontend/src/lib/hooks/useToast.tsx +229 -0
  354. package/frontend/src/lib/utils/constants.ts +38 -0
  355. package/frontend/src/lib/utils/utils.ts +165 -0
  356. package/frontend/src/lib/utils/validation-schemas.ts +126 -0
  357. package/frontend/src/main.tsx +16 -0
  358. package/frontend/src/rdg.css +194 -0
  359. package/frontend/src/vite-env.d.ts +12 -0
  360. package/frontend/tailwind.config.js +97 -0
  361. package/frontend/tsconfig.json +26 -0
  362. package/frontend/tsconfig.node.json +10 -0
  363. package/frontend/vite.config.ts +37 -0
  364. package/frontend/vitest.config.ts +36 -0
  365. package/functions/deno.json +25 -0
  366. package/functions/server.ts +290 -0
  367. package/functions/worker-template.js +126 -0
  368. package/openapi/ai.yaml +689 -0
  369. package/openapi/auth.yaml +563 -0
  370. package/openapi/functions.yaml +476 -0
  371. package/openapi/health.yaml +30 -0
  372. package/openapi/logs.yaml +224 -0
  373. package/openapi/metadata.yaml +178 -0
  374. package/openapi/records.yaml +382 -0
  375. package/openapi/secrets.yaml +371 -0
  376. package/openapi/storage.yaml +876 -0
  377. package/openapi/tables.yaml +464 -0
  378. package/package.json +88 -0
  379. package/shared-schemas/package.json +31 -0
  380. package/shared-schemas/src/ai-api.schema.ts +167 -0
  381. package/shared-schemas/src/ai.schema.ts +54 -0
  382. package/shared-schemas/src/auth-api.schema.ts +193 -0
  383. package/shared-schemas/src/auth.schema.ts +94 -0
  384. package/shared-schemas/src/database-api.schema.ts +259 -0
  385. package/shared-schemas/src/database.schema.ts +69 -0
  386. package/shared-schemas/src/functions-api.schema.ts +25 -0
  387. package/shared-schemas/src/functions.schema.ts +16 -0
  388. package/shared-schemas/src/index.ts +13 -0
  389. package/shared-schemas/src/logs-api.schema.ts +49 -0
  390. package/shared-schemas/src/logs.schema.ts +14 -0
  391. package/shared-schemas/src/metadata.schema.ts +56 -0
  392. package/shared-schemas/src/storage-api.schema.ts +65 -0
  393. package/shared-schemas/src/storage.schema.ts +19 -0
  394. package/shared-schemas/tsconfig.json +21 -0
  395. package/tsconfig.json +8 -0
@@ -0,0 +1,127 @@
1
+ import { useQuery, useQueryClient } from '@tanstack/react-query';
2
+ import { RefreshCw } from 'lucide-react';
3
+ import { useCallback, useEffect } from 'react';
4
+ import { useMetadata } from '@/features/metadata/hooks/useMetadata';
5
+ import { authService } from '@/features/auth/services/auth.service';
6
+ import { SchemaVisualizer, VisualizerSkeleton } from '../components';
7
+ import { Button } from '@/components/radix/Button';
8
+ import { Alert, AlertDescription } from '@/components/radix/Alert';
9
+ import {
10
+ useSocket,
11
+ ServerEvents,
12
+ DataUpdatePayload,
13
+ DataUpdateResourceType,
14
+ SocketMessage,
15
+ } from '@/lib/contexts/SocketContext';
16
+
17
+ const VisualizerPage = () => {
18
+ const { socket, isConnected } = useSocket();
19
+ const queryClient = useQueryClient();
20
+
21
+ const {
22
+ metadata,
23
+ isLoading: metadataLoading,
24
+ error: metadataError,
25
+ refetch: refetchMetadata,
26
+ } = useMetadata();
27
+
28
+ const {
29
+ data: userStats,
30
+ isLoading: userStatsLoading,
31
+ refetch: refetchUserStats,
32
+ } = useQuery({
33
+ queryKey: ['user-stats-visualizer'],
34
+ queryFn: async () => {
35
+ const response = await authService.getUsers();
36
+ return { userCount: response.pagination.total };
37
+ },
38
+ staleTime: 5 * 60 * 1000,
39
+ gcTime: 10 * 60 * 1000,
40
+ });
41
+
42
+ const isLoading = metadataLoading || userStatsLoading;
43
+ const error = metadataError;
44
+
45
+ const handleRefresh = useCallback(() => {
46
+ void refetchMetadata();
47
+ void refetchUserStats();
48
+ }, [refetchMetadata, refetchUserStats]);
49
+
50
+ // Listen for schema change events
51
+ useEffect(() => {
52
+ if (!socket || !isConnected) {
53
+ return;
54
+ }
55
+
56
+ const handleDataUpdate = (message: SocketMessage<DataUpdatePayload>) => {
57
+ if (
58
+ message.payload?.resource === DataUpdateResourceType.METADATA ||
59
+ message.payload?.resource === DataUpdateResourceType.DATABASE_SCHEMA ||
60
+ message.payload?.resource === DataUpdateResourceType.TABLE_SCHEMA ||
61
+ message.payload?.resource === DataUpdateResourceType.OAUTH_SCHEMA ||
62
+ message.payload?.resource === DataUpdateResourceType.STORAGE_SCHEMA
63
+ ) {
64
+ // Invalidate all metadata-related queries
65
+ void queryClient.invalidateQueries({ queryKey: ['metadata'] });
66
+ }
67
+ };
68
+
69
+ socket.on(ServerEvents.DATA_UPDATE, handleDataUpdate);
70
+
71
+ return () => {
72
+ socket.off(ServerEvents.DATA_UPDATE, handleDataUpdate);
73
+ };
74
+ }, [socket, isConnected, queryClient]);
75
+
76
+ if (isLoading) {
77
+ return <VisualizerSkeleton />;
78
+ }
79
+
80
+ if (!metadata || error) {
81
+ return (
82
+ <div className="relative min-h-screen bg-neutral-800 overflow-hidden">
83
+ {/* Dot Matrix Background */}
84
+ <div
85
+ className="absolute inset-0 opacity-50"
86
+ style={{
87
+ backgroundImage: `radial-gradient(circle, #3B3B3B 1px, transparent 1px)`,
88
+ backgroundSize: '12px 12px',
89
+ }}
90
+ />
91
+
92
+ <div className="relative z-10 flex items-center justify-center min-h-screen p-8">
93
+ <Alert variant="destructive" className="max-w-md">
94
+ <AlertDescription>
95
+ Failed to load database schema. Please ensure the backend is running and try
96
+ refreshing.
97
+ </AlertDescription>
98
+ <Button onClick={handleRefresh} className="mt-4 w-full" variant="outline">
99
+ <RefreshCw className="w-4 h-4 mr-2" />
100
+ Retry
101
+ </Button>
102
+ </Alert>
103
+ </div>
104
+ </div>
105
+ );
106
+ }
107
+
108
+ return (
109
+ <div className="relative min-h-screen bg-neutral-800 overflow-hidden">
110
+ {/* Dot Matrix Background */}
111
+ <div
112
+ className="absolute inset-0 opacity-50"
113
+ style={{
114
+ backgroundImage: `radial-gradient(circle, #3B3B3B 1px, transparent 1px)`,
115
+ backgroundSize: '12px 12px',
116
+ }}
117
+ />
118
+
119
+ {/* Schema Visualizer */}
120
+ <div className="relative z-10 w-full h-screen">
121
+ <SchemaVisualizer metadata={metadata} userCount={userStats?.userCount} />
122
+ </div>
123
+ </div>
124
+ );
125
+ };
126
+
127
+ export default VisualizerPage;
@@ -0,0 +1,248 @@
1
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');
2
+ @import 'tailwindcss';
3
+ @config "../tailwind.config.js";
4
+
5
+ @layer utilities {
6
+ /* PocketBase-inspired Design Tokens */
7
+ :root {
8
+ /* Colors */
9
+ --pb-primary: #1a1a24;
10
+ --pb-text-primary: #1a1a24;
11
+ --pb-text-hint: #617079;
12
+ --pb-text-disabled: #a0a6ac;
13
+
14
+ --pb-body: #f8f9fa;
15
+ --pb-base: #ffffff;
16
+ --pb-base-alt1: #e3e8ed;
17
+ --pb-base-alt2: #d7dde3;
18
+ --pb-base-alt3: #c9d0da;
19
+ --pb-base-alt4: #a5b0c0;
20
+
21
+ --pb-info: #5499e8;
22
+ --pb-success: #32ad84;
23
+ --pb-danger: #e34562;
24
+ --pb-warning: #ff944d;
25
+
26
+ /* Spacing */
27
+ --pb-spacing-xs: 15px;
28
+ --pb-spacing-sm: 20px;
29
+ --pb-spacing-base: 30px;
30
+ --pb-spacing-lg: 50px;
31
+ --pb-spacing-xl: 60px;
32
+
33
+ /* Animation */
34
+ --pb-animation-base: 150ms;
35
+ --pb-animation-active: 70ms;
36
+ --pb-animation-entrance: 250ms;
37
+ }
38
+ }
39
+
40
+ @layer base {
41
+ :root {
42
+ /* Spacing system */
43
+ --baseSpacing: 2rem; /* 32px = 8 * 0.25rem */
44
+ --smSpacing: 1.25rem; /* 20px */
45
+ --xsSpacing: 1rem; /* 16px */
46
+
47
+ /* Font system */
48
+ --baseFontSize: 0.875rem; /* 14px */
49
+ --smFontSize: 0.8125rem; /* 13px */
50
+ --xsFontSize: 0.75rem; /* 12px */
51
+ --lgFontSize: 1.25rem; /* 20px */
52
+ --xlFontSize: 1.375rem; /* 22px */
53
+
54
+ /* Font weights */
55
+ --fontWeightNormal: 400;
56
+ --fontWeightMedium: 500;
57
+ --fontWeightSemibold: 600;
58
+
59
+ /* Font families */
60
+ --fontFamilyBase:
61
+ 'Inter', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
62
+ --fontFamilyMono: 'Ubuntu Mono', ui-monospace, monospace;
63
+ }
64
+
65
+ /* Prevent document-level scrolling */
66
+ html,
67
+ body {
68
+ overflow: hidden;
69
+ height: 100%;
70
+ }
71
+
72
+ /* Apply base font settings */
73
+ body {
74
+ font-family: var(--fontFamilyBase);
75
+ font-size: var(--baseFontSize);
76
+ font-weight: var(--fontWeightNormal);
77
+ }
78
+
79
+ /* Typography scale */
80
+ h1 {
81
+ font-size: var(--xlFontSize);
82
+ font-weight: var(--fontWeightSemibold);
83
+ line-height: 1.3;
84
+ }
85
+
86
+ h2 {
87
+ font-size: var(--lgFontSize);
88
+ font-weight: var(--fontWeightSemibold);
89
+ line-height: 1.3;
90
+ }
91
+
92
+ .text-xs {
93
+ font-size: var(--xsFontSize);
94
+ }
95
+
96
+ .text-sm {
97
+ font-size: var(--smFontSize);
98
+ }
99
+
100
+ .font-mono {
101
+ font-family: var(--fontFamilyMono);
102
+ }
103
+ }
104
+
105
+ @layer components {
106
+ /* Checkbox styling */
107
+ input[type='checkbox'] {
108
+ @apply cursor-pointer;
109
+ accent-color: #000000;
110
+ }
111
+
112
+ input[type='checkbox']:checked {
113
+ background-color: #000000 !important;
114
+ border-color: #000000 !important;
115
+ accent-color: #000000;
116
+ }
117
+
118
+ input[type='checkbox']:checked:hover {
119
+ background-color: #1a1a1a !important;
120
+ border-color: #1a1a1a !important;
121
+ }
122
+
123
+ input[type='checkbox']:focus {
124
+ outline: none !important;
125
+ box-shadow: none !important;
126
+ }
127
+
128
+ input[type='checkbox']:focus-visible {
129
+ outline: none !important;
130
+ box-shadow: none !important;
131
+ }
132
+
133
+ button {
134
+ cursor: pointer;
135
+ }
136
+
137
+ input:focus {
138
+ outline: none !important;
139
+ }
140
+
141
+ button:focus {
142
+ outline: none !important;
143
+ }
144
+ }
145
+
146
+ @layer base {
147
+ /* CSS Variables for Radix UI components - using RGB values for clarity */
148
+ :root {
149
+ /* Light mode colors */
150
+ --background: 255 255 255; /* white */
151
+ --foreground: 10 10 10; /* near-black */
152
+ --card: 255 255 255; /* white */
153
+ --card-foreground: 10 10 10; /* near-black */
154
+ --popover: 255 255 255; /* white */
155
+ --popover-foreground: 10 10 10; /* near-black */
156
+ --primary: 23 23 23; /* zinc-900 */
157
+ --primary-foreground: 250 250 250; /* zinc-50 */
158
+ --secondary: 245 245 245; /* neutral-100 */
159
+ --secondary-foreground: 23 23 23; /* zinc-900 */
160
+ --muted: 245 245 245; /* neutral-100 */
161
+ --muted-foreground: 115 115 115; /* neutral-500 */
162
+ --accent: 245 245 245; /* neutral-100 */
163
+ --accent-foreground: 23 23 23; /* zinc-900 */
164
+ --destructive: 239 68 68; /* red-500 */
165
+ --destructive-foreground: 250 250 250; /* zinc-50 */
166
+ --border: 228 228 231; /* zinc-200 */
167
+ --input: 228 228 231; /* zinc-200 */
168
+ --ring: 10 10 10; /* near-black */
169
+ --radius: 0.5rem;
170
+ --background-color: #ffffff;
171
+ --border-color: #737373;
172
+ --border-hover-color: #d4d4d4;
173
+ }
174
+
175
+ .dark {
176
+ /* Dark mode colors - matching your neutral theme */
177
+ --background: 38 38 38; /* neutral-800 */
178
+ --foreground: 250 250 250; /* zinc-50 */
179
+ --card: 64 64 64; /* neutral-700 */
180
+ --card-foreground: 250 250 250; /* zinc-50 */
181
+ --popover: 64 64 64; /* neutral-700 */
182
+ --popover-foreground: 250 250 250; /* zinc-50 */
183
+ --primary: 250 250 250; /* zinc-50 */
184
+ --primary-foreground: 23 23 23; /* zinc-900 */
185
+ --secondary: 82 82 82; /* neutral-600 */
186
+ --secondary-foreground: 250 250 250; /* zinc-50 */
187
+ --muted: 82 82 82; /* neutral-600 */
188
+ --muted-foreground: 163 163 163; /* neutral-400 */
189
+ --accent: 82 82 82; /* neutral-600 */
190
+ --accent-foreground: 250 250 250; /* zinc-50 */
191
+ --destructive: 127 29 29; /* red-900 */
192
+ --destructive-foreground: 250 250 250; /* zinc-50 */
193
+ --border: 64 64 64; /* neutral-700 */
194
+ --input: 64 64 64; /* neutral-700 */
195
+ --ring: 212 212 212; /* zinc-300 */
196
+ --background-color: #262626;
197
+ --border-color: #737373;
198
+ --border-hover-color: #d4d4d4;
199
+ }
200
+ }
201
+
202
+ @layer base {
203
+ body {
204
+ font-family:
205
+ 'Inter',
206
+ -apple-system,
207
+ BlinkMacSystemFont,
208
+ 'Segoe UI',
209
+ Roboto,
210
+ 'Helvetica Neue',
211
+ Arial,
212
+ sans-serif;
213
+ }
214
+ }
215
+
216
+ @theme {
217
+ --color-border-gray: #e4e4e7;
218
+ --color-chart-blue-dark: #2c7fff;
219
+ --color-text-gray: #a1a1a1;
220
+ --color-bg-gray: #f8f9fa;
221
+ --color-link-blue: #2c7fff;
222
+ --color-bg-gray-hover: #ebebeb;
223
+ }
224
+
225
+ /* Fix for Radix UI dropdowns to prevent scroll lock */
226
+ [data-radix-popper-content-wrapper] {
227
+ position: fixed !important;
228
+ }
229
+
230
+ /* Custom scrollbar styles */
231
+ ::-webkit-scrollbar {
232
+ width: 10px;
233
+ height: 10px;
234
+ }
235
+
236
+ ::-webkit-scrollbar-track {
237
+ background: var(--background-color);
238
+ border-radius: 5px;
239
+ }
240
+
241
+ ::-webkit-scrollbar-thumb {
242
+ background: var(--border-color);
243
+ border-radius: 5px;
244
+ }
245
+
246
+ ::-webkit-scrollbar-thumb:hover {
247
+ background: var(--border-hover-color);
248
+ }
@@ -0,0 +1,163 @@
1
+ const API_BASE = '/api';
2
+
3
+ interface ApiError extends Error {
4
+ response?: {
5
+ data: unknown;
6
+ status: number;
7
+ };
8
+ }
9
+
10
+ export class ApiClient {
11
+ private token: string | null = null;
12
+ private onAuthError?: () => void;
13
+
14
+ constructor() {
15
+ this.token = localStorage.getItem('insforge_token');
16
+ }
17
+
18
+ setToken(token: string) {
19
+ this.token = token;
20
+ localStorage.setItem('insforge_token', token);
21
+ }
22
+
23
+ clearToken() {
24
+ this.token = null;
25
+ localStorage.removeItem('insforge_token');
26
+ }
27
+
28
+ getToken() {
29
+ return this.token;
30
+ }
31
+
32
+ setAuthErrorHandler(handler?: () => void) {
33
+ this.onAuthError = handler;
34
+ }
35
+
36
+ request(
37
+ endpoint: string,
38
+ options: RequestInit & {
39
+ returnFullResponse?: boolean;
40
+ skipAuth?: boolean;
41
+ } = {}
42
+ ) {
43
+ const url = `${API_BASE}${endpoint}`;
44
+ const { returnFullResponse, skipAuth, ...fetchOptions } = options;
45
+
46
+ // Initial request attempt
47
+ const makeRequest = async () => {
48
+ // Merge headers properly to preserve Content-Type when body is present
49
+ const headers: Record<string, string> = {
50
+ ...(!skipAuth && this.token && { Authorization: `Bearer ${this.token}` }),
51
+ ...((fetchOptions.headers as Record<string, string>) || {}),
52
+ };
53
+
54
+ // Ensure Content-Type is set for JSON bodies
55
+ if (fetchOptions.body && typeof fetchOptions.body === 'string') {
56
+ headers['Content-Type'] = headers['Content-Type'] || 'application/json';
57
+ }
58
+
59
+ const config: RequestInit = {
60
+ ...fetchOptions,
61
+ headers,
62
+ };
63
+
64
+ const response = await fetch(url, config);
65
+
66
+ if (!response.ok) {
67
+ let errorData;
68
+ try {
69
+ errorData = await response.json();
70
+ } catch {
71
+ // If parsing JSON fails, throw a generic error
72
+ const error: ApiError = new Error(`HTTP ${response.status}: ${response.statusText}`);
73
+ error.response = { data: null, status: response.status };
74
+ throw error;
75
+ }
76
+
77
+ // Handle authentication errors
78
+ if (response.status === 401 && !skipAuth) {
79
+ // Clear token and notify auth context
80
+ this.clearToken();
81
+ if (this.onAuthError) {
82
+ this.onAuthError();
83
+ }
84
+ }
85
+
86
+ // Handle traditional REST error format
87
+ if (errorData.error && errorData.message) {
88
+ const error: ApiError = new Error(errorData.message);
89
+ error.response = {
90
+ data: errorData,
91
+ status: response.status,
92
+ };
93
+ throw error;
94
+ }
95
+
96
+ // Fallback for other error formats
97
+ const error: ApiError = new Error(`HTTP ${response.status}: ${JSON.stringify(errorData)}`);
98
+ error.response = {
99
+ data: errorData,
100
+ status: response.status,
101
+ };
102
+ throw error;
103
+ }
104
+ const text = await response.text();
105
+ // compatible with empty response
106
+ let responseData = null;
107
+ try {
108
+ responseData = text ? JSON.parse(text) : null;
109
+ } catch {
110
+ responseData = text;
111
+ }
112
+
113
+ // Check for Content-Range header and extract pagination if present
114
+ const contentRange = response.headers.get('content-range');
115
+ if (contentRange && Array.isArray(responseData)) {
116
+ const match = contentRange.match(/(\d+)-(\d+)\/(\d+|\*)/);
117
+ if (match) {
118
+ const start = parseInt(match[1]);
119
+ const end = parseInt(match[2]);
120
+ const total = match[3] === '*' ? responseData.length : parseInt(match[3]);
121
+
122
+ const pagination = {
123
+ offset: start,
124
+ limit: end - start + 1,
125
+ total,
126
+ };
127
+
128
+ return {
129
+ data: responseData,
130
+ pagination,
131
+ };
132
+ } else {
133
+ return {
134
+ data: responseData,
135
+ pagination: {
136
+ offset: 0,
137
+ limit: 0,
138
+ total: 0,
139
+ },
140
+ };
141
+ }
142
+ }
143
+
144
+ // If full response is requested, return it as-is
145
+ if (returnFullResponse) {
146
+ return responseData;
147
+ }
148
+
149
+ // Traditional REST format - return response directly
150
+ return responseData;
151
+ };
152
+
153
+ return makeRequest();
154
+ }
155
+
156
+ // Helper method to add authorization header with token
157
+ withAccessToken(headers: Record<string, string> = {}) {
158
+ return this.token ? { ...headers, Authorization: `Bearer ${this.token}` } : headers;
159
+ }
160
+ }
161
+
162
+ // Singleton instance
163
+ export const apiClient = new ApiClient();
@@ -0,0 +1,157 @@
1
+ import React, { createContext, useContext, useState, useEffect, useCallback } from 'react';
2
+ import { useQueryClient } from '@tanstack/react-query';
3
+ import { authService } from '@/features/auth/services/auth.service';
4
+ import { apiClient } from '@/lib/api/client';
5
+
6
+ export interface User {
7
+ id: string;
8
+ email: string;
9
+ name?: string;
10
+ createdAt: string;
11
+ updatedAt: string;
12
+ }
13
+
14
+ interface AuthContextType {
15
+ user: User | null;
16
+ isAuthenticated: boolean;
17
+ isLoading: boolean;
18
+ loginWithPassword: (email: string, password: string) => Promise<boolean>;
19
+ loginWithAuthorizationCode: (token: string) => Promise<boolean>;
20
+ logout: () => void;
21
+ refreshAuth: () => Promise<void>;
22
+ error: Error | null;
23
+ }
24
+
25
+ const AuthContext = createContext<AuthContextType | undefined>(undefined);
26
+
27
+ export const useAuth = () => {
28
+ const context = useContext(AuthContext);
29
+ if (!context) {
30
+ throw new Error('useAuth must be used within an AuthProvider');
31
+ }
32
+ return context;
33
+ };
34
+
35
+ interface AuthProviderProps {
36
+ children: React.ReactNode;
37
+ }
38
+
39
+ export const AuthProvider: React.FC<AuthProviderProps> = ({ children }) => {
40
+ const [user, setUser] = useState<User | null>(null);
41
+ const [isAuthenticated, setIsAuthenticated] = useState<boolean>(false);
42
+ const [isLoading, setIsLoading] = useState<boolean>(true);
43
+ const [error, setError] = useState<Error | null>(null);
44
+ const queryClient = useQueryClient();
45
+
46
+ const handleAuthError = useCallback(() => {
47
+ setUser(null);
48
+ setIsAuthenticated(false);
49
+ }, []);
50
+
51
+ // Set up auth error handler
52
+ useEffect(() => {
53
+ apiClient.setAuthErrorHandler(handleAuthError);
54
+ return () => {
55
+ apiClient.setAuthErrorHandler(undefined);
56
+ };
57
+ }, [handleAuthError]);
58
+
59
+ const checkAuthStatus = useCallback(async () => {
60
+ try {
61
+ setIsLoading(true);
62
+ setError(null);
63
+ const currentUser = await authService.getCurrentUser();
64
+ setUser(currentUser);
65
+ setIsAuthenticated(true);
66
+ return currentUser;
67
+ } catch (err) {
68
+ setUser(null);
69
+ setIsAuthenticated(false);
70
+ if (err instanceof Error && !err.message.includes('401')) {
71
+ setError(err);
72
+ }
73
+ apiClient.clearToken();
74
+ return null;
75
+ } finally {
76
+ setIsLoading(false);
77
+ }
78
+ }, []);
79
+
80
+ const loginWithPassword = useCallback(
81
+ async (email: string, password: string): Promise<boolean> => {
82
+ try {
83
+ setError(null);
84
+ await authService.loginWithPassword(email, password);
85
+ const currentUser = await checkAuthStatus();
86
+ if (currentUser) {
87
+ // Invalidate queries that depend on authentication
88
+ void queryClient.invalidateQueries({ queryKey: ['apiKey'] });
89
+ void queryClient.invalidateQueries({ queryKey: ['metadata'] });
90
+ void queryClient.invalidateQueries({ queryKey: ['users'] });
91
+ void queryClient.invalidateQueries({ queryKey: ['tables'] });
92
+ return true;
93
+ }
94
+ return false;
95
+ } catch (err) {
96
+ setError(err instanceof Error ? err : new Error('Login failed'));
97
+ return false;
98
+ }
99
+ },
100
+ [checkAuthStatus, queryClient]
101
+ );
102
+
103
+ const loginWithAuthorizationCode = useCallback(
104
+ async (token: string): Promise<boolean> => {
105
+ try {
106
+ setError(null);
107
+ await authService.loginWithAuthorizationCode(token);
108
+ const currentUser = await checkAuthStatus();
109
+ if (currentUser) {
110
+ // Invalidate queries that depend on authentication
111
+ void queryClient.invalidateQueries({ queryKey: ['apiKey'] });
112
+ void queryClient.invalidateQueries({ queryKey: ['metadata'] });
113
+ void queryClient.invalidateQueries({ queryKey: ['users'] });
114
+ void queryClient.invalidateQueries({ queryKey: ['tables'] });
115
+ return true;
116
+ }
117
+ return false;
118
+ } catch (err) {
119
+ setError(err instanceof Error ? err : new Error('Authorization code exchange failed'));
120
+ return false;
121
+ }
122
+ },
123
+ [checkAuthStatus, queryClient]
124
+ );
125
+
126
+ const logout = useCallback(() => {
127
+ void authService.logout();
128
+ setUser(null);
129
+ setIsAuthenticated(false);
130
+ setError(null);
131
+ }, []);
132
+
133
+ const refreshAuth = useCallback(async () => {
134
+ await checkAuthStatus();
135
+ }, [checkAuthStatus]);
136
+
137
+ // Check auth status on mount
138
+ useEffect(() => {
139
+ void checkAuthStatus();
140
+ }, [checkAuthStatus]);
141
+
142
+ // Removed periodic auth refresh - it was causing unnecessary unmounts
143
+ // Auth status is checked naturally when API calls are made
144
+
145
+ const value: AuthContextType = {
146
+ user,
147
+ isAuthenticated,
148
+ isLoading,
149
+ loginWithPassword,
150
+ loginWithAuthorizationCode,
151
+ logout,
152
+ refreshAuth,
153
+ error,
154
+ };
155
+
156
+ return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
157
+ };