insforge 0.3.3 → 1.2.10

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 (507) hide show
  1. package/.claude-plugin/marketplace.json +20 -0
  2. package/.cursor/rules/cursor-rules.mdc +94 -0
  3. package/.dockerignore +3 -0
  4. package/.env.example +33 -4
  5. package/.github/ISSUE_TEMPLATE/bug_report.yml +13 -60
  6. package/.github/ISSUE_TEMPLATE/config.yml +2 -2
  7. package/.github/ISSUE_TEMPLATE/feature_request.yml +10 -63
  8. package/.github/PULL_REQUEST_TEMPLATE.md +7 -0
  9. package/.github/workflows/build-image.yml +2 -1
  10. package/.github/workflows/e2e.yml +63 -0
  11. package/CHANGELOG.md +41 -0
  12. package/CLAUDE_PLUGIN.md +104 -0
  13. package/CODE_OF_CONDUCT.md +128 -0
  14. package/CONTRIBUTING.md +1 -1
  15. package/Dockerfile +4 -1
  16. package/README.md +66 -18
  17. package/assets/mcpInstallv2.png +0 -0
  18. package/assets/sampleResponse.png +0 -0
  19. package/auth/index.html +13 -0
  20. package/auth/package.json +28 -0
  21. package/auth/public/favicon.ico +0 -0
  22. package/auth/src/App.tsx +33 -0
  23. package/auth/src/components/ErrorCard.tsx +37 -0
  24. package/auth/src/components/Layout.tsx +13 -0
  25. package/auth/src/index.css +19 -0
  26. package/auth/src/lib/broadcastService.ts +115 -0
  27. package/auth/src/lib/utils.ts +11 -0
  28. package/auth/src/main.tsx +22 -0
  29. package/auth/src/pages/ForgotPasswordPage.tsx +11 -0
  30. package/auth/src/pages/ResetPasswordPage.tsx +11 -0
  31. package/auth/src/pages/SignInPage.tsx +57 -0
  32. package/auth/src/pages/SignUpPage.tsx +57 -0
  33. package/auth/src/pages/VerifyEmailPage.tsx +20 -0
  34. package/auth/src/vite-env.d.ts +10 -0
  35. package/auth/tsconfig.json +32 -0
  36. package/auth/tsconfig.node.json +11 -0
  37. package/auth/vite.config.ts +25 -0
  38. package/backend/package.json +9 -9
  39. package/backend/src/api/{middleware → middlewares}/auth.ts +8 -9
  40. package/backend/src/api/middlewares/rate-limiters.ts +127 -0
  41. package/backend/src/api/routes/{ai.ts → ai/index.routes.ts} +20 -24
  42. package/backend/src/api/routes/auth/index.routes.ts +570 -0
  43. package/backend/src/api/routes/auth/oauth.routes.ts +448 -0
  44. package/backend/src/api/routes/{database.advance.ts → database/advance.routes.ts} +107 -65
  45. package/backend/src/api/routes/database/index.routes.ts +13 -0
  46. package/backend/src/api/routes/{database.records.ts → database/records.routes.ts} +22 -8
  47. package/backend/src/api/routes/{database.tables.ts → database/tables.routes.ts} +20 -23
  48. package/backend/src/api/routes/docs/index.routes.ts +76 -0
  49. package/backend/src/api/routes/functions/index.routes.ts +188 -0
  50. package/backend/src/api/routes/{logs.ts → logs/index.routes.ts} +25 -30
  51. package/backend/src/api/routes/{metadata.ts → metadata/index.routes.ts} +21 -31
  52. package/backend/src/api/routes/{secrets.ts → secrets/index.routes.ts} +27 -22
  53. package/backend/src/api/routes/{storage.ts → storage/index.routes.ts} +34 -53
  54. package/backend/src/api/routes/usage/index.routes.ts +89 -0
  55. package/backend/src/infra/config/app.config.ts +51 -0
  56. package/backend/src/{core/database/manager.ts → infra/database/database.manager.ts} +76 -85
  57. package/backend/src/infra/database/migrations/013_create-auth-schema-functions.sql +44 -0
  58. package/backend/src/infra/database/migrations/014_add-updated-at-trigger-user-table.sql +8 -0
  59. package/backend/src/infra/database/migrations/015_create-auth-config-and-email-otp-tables.sql +60 -0
  60. package/backend/src/infra/database/migrations/016_update-auth-config-and-email-otp.sql +24 -0
  61. package/backend/src/{core/secrets/encryption.ts → infra/security/encryption.manager.ts} +3 -2
  62. package/backend/src/infra/security/token.manager.ts +125 -0
  63. package/backend/src/{core/socket/socket.ts → infra/socket/socket.manager.ts} +15 -15
  64. package/backend/src/providers/ai/openrouter.provider.ts +377 -0
  65. package/backend/src/providers/email/base.provider.ts +41 -0
  66. package/backend/src/providers/email/cloud.provider.ts +187 -0
  67. package/backend/src/{core/logs/providers → providers/logs}/base.provider.ts +11 -11
  68. package/backend/src/{core/logs/providers → providers/logs}/cloudwatch.provider.ts +61 -38
  69. package/backend/src/providers/logs/local.provider.ts +185 -0
  70. package/backend/src/providers/oauth/base.provider.ts +29 -0
  71. package/backend/src/providers/oauth/discord.provider.ts +195 -0
  72. package/backend/src/providers/oauth/facebook.provider.ts +194 -0
  73. package/backend/src/providers/oauth/github.provider.ts +208 -0
  74. package/backend/src/providers/oauth/google.provider.ts +249 -0
  75. package/backend/src/providers/oauth/index.ts +7 -0
  76. package/backend/src/providers/oauth/linkedin.provider.ts +240 -0
  77. package/backend/src/providers/oauth/microsoft.provider.ts +169 -0
  78. package/backend/src/providers/oauth/x.provider.ts +202 -0
  79. package/backend/src/providers/storage/base.provider.ts +29 -0
  80. package/backend/src/providers/storage/local.provider.ts +103 -0
  81. package/backend/src/providers/storage/s3.provider.ts +313 -0
  82. package/backend/src/server.ts +70 -74
  83. package/backend/src/{core/ai/config.ts → services/ai/ai-config.service.ts} +19 -24
  84. package/backend/src/services/ai/ai-model.service.ts +60 -0
  85. package/backend/src/{core/ai/usage.ts → services/ai/ai-usage.service.ts} +28 -35
  86. package/backend/src/{core/ai/chat.ts → services/ai/chat-completion.service.ts} +37 -24
  87. package/backend/src/services/ai/helpers.ts +64 -0
  88. package/backend/src/{core/ai/image.ts → services/ai/image-generation.service.ts} +17 -19
  89. package/backend/src/services/ai/index.ts +13 -0
  90. package/backend/src/services/auth/auth-config.service.ts +250 -0
  91. package/backend/src/services/auth/auth-otp.service.ts +424 -0
  92. package/backend/src/services/auth/auth.service.ts +1136 -0
  93. package/backend/src/services/auth/index.ts +4 -0
  94. package/backend/src/{core/auth/oauth.ts → services/auth/oauth-config.service.ts} +106 -52
  95. package/backend/src/{core/database/advance.ts → services/database/database-advance.service.ts} +97 -131
  96. package/backend/src/services/database/database-table.service.ts +811 -0
  97. package/backend/src/services/email/email.service.ts +75 -0
  98. package/backend/src/{core/functions/functions.ts → services/functions/function.service.ts} +95 -88
  99. package/backend/src/{core/logs/audit.ts → services/logs/audit.service.ts} +92 -75
  100. package/backend/src/services/logs/log.service.ts +73 -0
  101. package/backend/src/{core/secrets/secrets.ts → services/secrets/secret.service.ts} +48 -66
  102. package/backend/src/services/storage/storage.service.ts +617 -0
  103. package/backend/src/services/usage/usage.service.ts +149 -0
  104. package/backend/src/types/auth.ts +66 -2
  105. package/backend/src/types/email.ts +8 -0
  106. package/backend/src/types/error-constants.ts +4 -0
  107. package/backend/src/types/logs.ts +0 -29
  108. package/backend/src/{core/socket/types.ts → types/socket.ts} +5 -6
  109. package/backend/src/utils/environment.ts +9 -3
  110. package/backend/src/utils/logger.ts +20 -2
  111. package/backend/src/utils/seed.ts +150 -57
  112. package/backend/src/utils/sql-parser.ts +1 -1
  113. package/backend/src/utils/utils.ts +114 -0
  114. package/backend/src/utils/validations.ts +40 -4
  115. package/backend/tests/local/test-ai-config.sh +129 -0
  116. package/backend/tests/local/test-ai-usage.sh +80 -0
  117. package/backend/tests/local/test-auth-router.sh +1 -1
  118. package/backend/tests/local/test-e2e.sh +1 -1
  119. package/backend/tests/local/test-functions.sh +123 -0
  120. package/backend/tests/local/test-logs.sh +132 -0
  121. package/backend/tests/local/test-public-bucket.sh +3 -3
  122. package/backend/tests/local/test-secrets.sh +14 -12
  123. package/backend/tests/local/test-traditional-rest.sh +2 -2
  124. package/backend/tests/manual/test-rawsql-modes.sh +244 -0
  125. package/backend/tests/test-config.sh +37 -1
  126. package/backend/tests/unit/cloud-token.test.ts +48 -0
  127. package/backend/tests/unit/constant.test.ts +8 -0
  128. package/backend/tests/unit/email.test.ts +372 -0
  129. package/backend/tests/unit/environment.test.ts +59 -0
  130. package/backend/tests/unit/helpers.test.ts +63 -0
  131. package/backend/tests/unit/logger.test.ts +22 -0
  132. package/backend/tests/unit/rate-limit.test.ts +154 -0
  133. package/backend/tests/unit/response.test.ts +58 -0
  134. package/backend/tests/unit/sql-parser.test.ts +74 -0
  135. package/backend/tests/unit/uuid.test.ts +21 -0
  136. package/backend/tests/unit/validations.test.ts +80 -0
  137. package/backend/tsconfig.json +1 -1
  138. package/backend/vitest.config.ts +11 -0
  139. package/claude-plugin/.claude-plugin/plugin.json +24 -0
  140. package/claude-plugin/README.md +133 -0
  141. package/claude-plugin/skills/insforge-schema-patterns/SKILL.md +270 -0
  142. package/docker-compose.prod.yml +60 -4
  143. package/docker-compose.yml +65 -4
  144. package/docker-init/db/db-init.sql +6 -34
  145. package/docker-init/logs/vector.yml +236 -0
  146. package/docs/README.md +44 -0
  147. package/docs/changelog.mdx +67 -0
  148. package/docs/core-concepts/ai/architecture.mdx +373 -0
  149. package/docs/core-concepts/ai/sdk.mdx +213 -0
  150. package/docs/core-concepts/authentication/architecture.mdx +278 -0
  151. package/docs/core-concepts/authentication/sdk.mdx +414 -0
  152. package/docs/core-concepts/authentication/ui-components/customization.mdx +529 -0
  153. package/docs/core-concepts/authentication/ui-components/nextjs.mdx +221 -0
  154. package/docs/core-concepts/authentication/ui-components/react-router.mdx +184 -0
  155. package/docs/core-concepts/authentication/ui-components/react.mdx +129 -0
  156. package/docs/core-concepts/database/architecture.mdx +256 -0
  157. package/docs/core-concepts/database/sdk.mdx +382 -0
  158. package/docs/core-concepts/functions/architecture.mdx +105 -0
  159. package/docs/core-concepts/functions/sdk.mdx +184 -0
  160. package/docs/core-concepts/storage/architecture.mdx +243 -0
  161. package/docs/core-concepts/storage/sdk.mdx +253 -0
  162. package/docs/deployment/README.md +94 -0
  163. package/docs/deployment/deploy-to-aws-ec2.md +565 -0
  164. package/docs/deployment/deploy-to-azure-virtual-machines.md +313 -0
  165. package/docs/deployment/deploy-to-google-cloud-compute-engine.md +613 -0
  166. package/docs/deployment/deploy-to-render.md +441 -0
  167. package/docs/docs.json +210 -0
  168. package/docs/examples/framework-guides/nextjs.mdx +131 -0
  169. package/docs/examples/framework-guides/nuxt.mdx +165 -0
  170. package/docs/examples/framework-guides/react.mdx +165 -0
  171. package/docs/examples/framework-guides/svelte.mdx +153 -0
  172. package/docs/examples/framework-guides/vue.mdx +159 -0
  173. package/docs/examples/overview.mdx +67 -0
  174. package/docs/favicon.svg +19 -0
  175. package/docs/images/changelog/nov-2025/auth-components.webp +0 -0
  176. package/docs/images/changelog/nov-2025/database-metadata.webp +0 -0
  177. package/docs/images/changelog/nov-2025/quickstart-prompts.webp +0 -0
  178. package/docs/images/changelog/nov-2025/sql-editor.webp +0 -0
  179. package/docs/images/changelog/nov-2025/usage-page.webp +0 -0
  180. package/docs/images/changelog/october-2025/csv-upload.webp +0 -0
  181. package/docs/images/changelog/october-2025/logs-feature.webp +0 -0
  182. package/docs/images/changelog/october-2025/oauth-providers.webp +0 -0
  183. package/docs/images/checks-passed.png +0 -0
  184. package/docs/images/dashboard-connect-expanded.png +0 -0
  185. package/docs/images/dashboard-connect.png +0 -0
  186. package/docs/images/hero-dark.png +0 -0
  187. package/docs/images/hero-light.png +0 -0
  188. package/docs/images/icons/ai.svg +4 -0
  189. package/docs/images/icons/auth.svg +1 -0
  190. package/docs/images/icons/database.svg +1 -0
  191. package/docs/images/icons/function.svg +1 -0
  192. package/docs/images/icons/storage.svg +1 -0
  193. package/docs/images/logos/nextjs.svg +4 -0
  194. package/docs/images/logos/nuxt.svg +4 -0
  195. package/docs/images/logos/react.svg +5 -0
  196. package/docs/images/logos/svelte.svg +4 -0
  197. package/docs/images/logos/vue.svg +5 -0
  198. package/docs/images/mcp-install.png +0 -0
  199. package/docs/images/onboarding-mcp.png +0 -0
  200. package/docs/insforge-instructions-sdk.md +55 -374
  201. package/docs/introduction.mdx +45 -0
  202. package/docs/logo/dark.svg +22 -0
  203. package/docs/logo/light.svg +20 -0
  204. package/docs/partnership.mdx +647 -0
  205. package/docs/quickstart.mdx +83 -0
  206. package/docs/showcase/2048-arena.png +0 -0
  207. package/docs/showcase/framegen-cloud.png +0 -0
  208. package/docs/showcase/line-connect-race.png +0 -0
  209. package/docs/showcase/moment-vibe.png +0 -0
  210. package/docs/showcase/national-flags.png +0 -0
  211. package/docs/showcase/pokemon-vibe.png +0 -0
  212. package/docs/showcase/pure-browse-buy.png +0 -0
  213. package/docs/showcase.mdx +52 -0
  214. package/docs/snippets/sdk-installation.mdx +22 -0
  215. package/docs/snippets/service-icons.mdx +27 -0
  216. package/eslint.config.js +10 -3
  217. package/frontend/package.json +10 -4
  218. package/frontend/src/App.tsx +13 -82
  219. package/frontend/src/assets/icons/connected.svg +3 -0
  220. package/frontend/src/assets/icons/loader.svg +9 -0
  221. package/frontend/src/assets/logos/apple.svg +4 -0
  222. package/frontend/src/assets/logos/discord.svg +1 -1
  223. package/frontend/src/assets/logos/facebook.svg +3 -0
  224. package/frontend/src/assets/logos/instagram.svg +2 -0
  225. package/frontend/src/assets/logos/linkedin.svg +3 -0
  226. package/frontend/src/assets/logos/microsoft.svg +1 -0
  227. package/frontend/src/assets/logos/spotify.svg +17 -0
  228. package/frontend/src/assets/logos/tiktok.svg +6 -0
  229. package/frontend/src/assets/logos/x.svg +3 -0
  230. package/frontend/src/components/Checkbox.tsx +27 -29
  231. package/frontend/src/components/CodeBlock.tsx +55 -2
  232. package/frontend/src/components/CodeEditor.tsx +92 -0
  233. package/frontend/src/components/ConfirmDialog.tsx +1 -1
  234. package/frontend/src/components/ConnectCTA.tsx +38 -0
  235. package/frontend/src/components/CopyButton.tsx +52 -15
  236. package/frontend/src/components/ErrorState.tsx +1 -2
  237. package/frontend/src/components/FeatureSidebar.tsx +6 -6
  238. package/frontend/src/components/FeatureSidebarItem.tsx +2 -2
  239. package/frontend/src/components/JsonHighlight.tsx +21 -9
  240. package/frontend/src/components/ProjectInfoModal.tsx +128 -0
  241. package/frontend/src/components/PromptDialog.tsx +1 -4
  242. package/frontend/src/components/SearchInput.tsx +1 -2
  243. package/frontend/src/components/Stepper.tsx +53 -0
  244. package/frontend/src/components/ThemeToggle.tsx +3 -3
  245. package/frontend/src/components/datagrid/DataGrid.tsx +25 -32
  246. package/frontend/src/components/datagrid/cell-editors/DateCellEditor.tsx +1 -2
  247. package/frontend/src/components/datagrid/cell-editors/JsonCellEditor.tsx +2 -4
  248. package/frontend/src/components/datagrid/index.ts +23 -0
  249. package/frontend/src/components/index.ts +23 -30
  250. package/frontend/src/components/layout/AppHeader.tsx +133 -92
  251. package/frontend/src/components/layout/AppSidebar.tsx +80 -170
  252. package/frontend/src/components/layout/Layout.tsx +12 -23
  253. package/frontend/src/components/layout/PrimaryMenu.tsx +187 -0
  254. package/frontend/src/components/layout/SecondaryMenu.tsx +70 -0
  255. package/frontend/src/components/layout/index.ts +5 -0
  256. package/frontend/src/components/radix/Tooltip.tsx +24 -13
  257. package/frontend/src/components/radix/index.ts +22 -0
  258. package/frontend/src/features/ai/components/AIConfigCard.tsx +129 -83
  259. package/frontend/src/features/ai/components/AIEmptyState.tsx +12 -7
  260. package/frontend/src/features/ai/components/ModalityFilterSidebar.tsx +101 -0
  261. package/frontend/src/features/ai/components/ModelSelectionDialog.tsx +135 -0
  262. package/frontend/src/features/ai/components/ModelSelectionGrid.tsx +51 -0
  263. package/frontend/src/features/ai/components/SystemPromptDialog.tsx +118 -0
  264. package/frontend/src/features/ai/components/index.ts +6 -0
  265. package/frontend/src/features/ai/helpers.ts +57 -71
  266. package/frontend/src/features/ai/hooks/useAIConfigs.ts +39 -113
  267. package/frontend/src/features/ai/hooks/useAIUsage.ts +0 -2
  268. package/frontend/src/features/ai/page/AIPage.tsx +67 -79
  269. package/frontend/src/features/ai/services/ai.service.ts +5 -5
  270. package/frontend/src/features/auth/components/AuthPreview.tsx +96 -0
  271. package/frontend/src/features/auth/components/OAuthConfigDialog.tsx +53 -30
  272. package/frontend/src/features/auth/components/UserFormDialog.tsx +13 -6
  273. package/frontend/src/features/auth/components/UsersDataGrid.tsx +44 -14
  274. package/frontend/src/features/auth/components/index.ts +5 -0
  275. package/frontend/src/features/auth/helpers.tsx +200 -0
  276. package/frontend/src/features/auth/hooks/useAnonToken.ts +30 -0
  277. package/frontend/src/features/auth/hooks/useAuthConfig.ts +48 -0
  278. package/frontend/src/features/auth/hooks/useOAuthConfig.ts +14 -10
  279. package/frontend/src/features/auth/hooks/useUsers.ts +43 -5
  280. package/frontend/src/features/auth/index.ts +3 -2
  281. package/frontend/src/features/auth/page/AuthMethodsPage.tsx +275 -0
  282. package/frontend/src/features/auth/page/ConfigurationPage.tsx +395 -0
  283. package/frontend/src/features/auth/page/UsersPage.tsx +285 -0
  284. package/frontend/src/features/auth/services/anonToken.service.ts +11 -0
  285. package/frontend/src/features/auth/services/config.service.ts +19 -0
  286. package/frontend/src/features/auth/services/{oauth.service.ts → oauth-config.service.ts} +4 -4
  287. package/frontend/src/features/auth/services/{auth.service.ts → user.service.ts} +7 -53
  288. package/frontend/src/features/dashboard/components/ConnectionSuccessBanner.tsx +35 -0
  289. package/frontend/src/features/dashboard/components/PromptCard.tsx +21 -0
  290. package/frontend/src/features/dashboard/components/PromptDialog.tsx +103 -0
  291. package/frontend/src/features/dashboard/components/StatsCard.tsx +50 -0
  292. package/frontend/src/features/dashboard/components/index.ts +4 -0
  293. package/frontend/src/features/dashboard/page/DashboardPage.tsx +187 -169
  294. package/frontend/src/features/dashboard/prompts/ai-chatbot.ts +13 -0
  295. package/frontend/src/features/dashboard/prompts/crm-system.ts +13 -0
  296. package/frontend/src/features/dashboard/prompts/ecommerce-platform.ts +12 -0
  297. package/frontend/src/features/dashboard/prompts/index.ts +31 -0
  298. package/frontend/src/features/dashboard/prompts/instagram-clone.ts +11 -0
  299. package/frontend/src/features/dashboard/prompts/notion-clone.ts +14 -0
  300. package/frontend/src/features/dashboard/prompts/reddit-clone.ts +12 -0
  301. package/frontend/src/features/database/components/DatabaseDataGrid.tsx +48 -17
  302. package/frontend/src/features/database/components/ForeignKeyCell.tsx +15 -34
  303. package/frontend/src/features/database/components/ForeignKeyPopover.tsx +19 -20
  304. package/frontend/src/features/database/components/LinkRecordModal.tsx +120 -125
  305. package/frontend/src/features/database/components/RecordFormDialog.tsx +22 -33
  306. package/frontend/src/features/database/components/RecordFormField.tsx +45 -47
  307. package/frontend/src/features/database/components/TableEmptyState.tsx +6 -5
  308. package/frontend/src/features/database/components/TableForm.tsx +28 -15
  309. package/frontend/src/features/database/components/TableFormColumn.tsx +2 -3
  310. package/frontend/src/features/database/components/TableSidebar.tsx +1 -1
  311. package/frontend/src/features/database/components/TablesEmptyState.tsx +48 -0
  312. package/frontend/src/features/database/components/TemplateCard.tsx +37 -0
  313. package/frontend/src/features/database/components/TemplatePreview.tsx +92 -0
  314. package/frontend/src/features/database/components/index.ts +19 -0
  315. package/frontend/src/features/database/constants.ts +28 -2
  316. package/frontend/src/features/database/contexts/SQLEditorContext.tsx +188 -0
  317. package/frontend/src/features/database/helpers.ts +2 -2
  318. package/frontend/src/features/database/hooks/useCSVImport.ts +29 -0
  319. package/frontend/src/features/database/hooks/useFullMetadata.ts +18 -0
  320. package/frontend/src/features/database/hooks/useRawSQL.ts +55 -0
  321. package/frontend/src/features/database/hooks/useRecords.ts +139 -0
  322. package/frontend/src/features/database/hooks/useTables.ts +131 -0
  323. package/frontend/src/features/database/index.ts +6 -1
  324. package/frontend/src/features/database/page/FunctionsPage.tsx +211 -0
  325. package/frontend/src/features/database/page/IndexesPage.tsx +240 -0
  326. package/frontend/src/features/database/page/PoliciesPage.tsx +248 -0
  327. package/frontend/src/features/database/page/SQLEditorPage.tsx +382 -0
  328. package/frontend/src/features/database/page/{DatabasePage.tsx → TablesPage.tsx} +186 -185
  329. package/frontend/src/features/database/page/TemplatesPage.tsx +39 -0
  330. package/frontend/src/features/database/page/TriggersPage.tsx +242 -0
  331. package/frontend/src/features/database/services/advance.service.ts +66 -0
  332. package/frontend/src/features/database/services/{database.service.ts → record.service.ts} +67 -64
  333. package/frontend/src/features/database/services/table.service.ts +64 -0
  334. package/frontend/src/features/database/templates/ai-chatbot.ts +402 -0
  335. package/frontend/src/features/database/templates/crm-system.ts +528 -0
  336. package/frontend/src/features/database/templates/ecommerce-platform.ts +553 -0
  337. package/frontend/src/features/database/templates/index.ts +34 -0
  338. package/frontend/src/features/database/templates/instagram-clone.ts +222 -0
  339. package/frontend/src/features/database/templates/notion-clone.ts +483 -0
  340. package/frontend/src/features/database/templates/reddit-clone.ts +526 -0
  341. package/frontend/src/features/functions/components/FunctionRow.tsx +2 -1
  342. package/frontend/src/features/functions/components/FunctionsSidebar.tsx +1 -1
  343. package/frontend/src/features/functions/components/SecretRow.tsx +1 -1
  344. package/frontend/src/features/functions/components/index.ts +5 -0
  345. package/frontend/src/features/functions/hooks/useFunctions.ts +4 -4
  346. package/frontend/src/features/{secrets → functions}/hooks/useSecrets.ts +5 -5
  347. package/frontend/src/features/functions/page/FunctionsPage.tsx +160 -17
  348. package/frontend/src/features/functions/{components/SecretsContent.tsx → page/SecretsPage.tsx} +8 -12
  349. package/frontend/src/features/functions/services/{functions.service.ts → function.service.ts} +2 -2
  350. package/frontend/src/features/{secrets/services/secrets.service.ts → functions/services/secret.service.ts} +2 -2
  351. package/frontend/src/features/login/hooks/usePartnerOrigin.ts +27 -0
  352. package/frontend/src/features/login/page/CloudLoginPage.tsx +79 -54
  353. package/frontend/src/features/login/page/LoginPage.tsx +16 -23
  354. package/frontend/src/features/login/services/partnership.service.ts +65 -0
  355. package/frontend/src/features/logs/components/LogsDataGrid.tsx +89 -0
  356. package/frontend/src/features/logs/components/SeverityBadge.tsx +18 -0
  357. package/frontend/src/features/logs/components/index.ts +2 -0
  358. package/frontend/src/features/logs/helpers.ts +24 -0
  359. package/frontend/src/features/logs/hooks/useAuditLogs.ts +4 -4
  360. package/frontend/src/features/logs/hooks/useLogSources.ts +137 -0
  361. package/frontend/src/features/logs/hooks/useLogs.ts +163 -0
  362. package/frontend/src/features/logs/hooks/useMcpUsage.ts +181 -0
  363. package/frontend/src/features/logs/index.ts +8 -2
  364. package/frontend/src/features/logs/page/AuditsPage.tsx +91 -38
  365. package/frontend/src/features/logs/page/LogsPage.tsx +152 -0
  366. package/frontend/src/features/logs/page/MCPLogsPage.tsx +84 -0
  367. package/frontend/src/features/logs/services/audit.service.ts +63 -0
  368. package/frontend/src/features/logs/services/log.service.ts +15 -110
  369. package/frontend/src/features/logs/services/usage.service.ts +31 -0
  370. package/frontend/src/features/onboard/components/McpConnectionStatus.tsx +68 -0
  371. package/frontend/src/features/onboard/components/OnboardingModal.tsx +267 -0
  372. package/frontend/src/features/onboard/components/VideoDemoModal.tsx +38 -0
  373. package/frontend/src/features/onboard/components/index.ts +4 -0
  374. package/frontend/src/features/onboard/components/mcp/CursorDeeplinkGenerator.tsx +2 -2
  375. package/frontend/src/features/onboard/components/mcp/{mcp-helper.tsx → helpers.tsx} +8 -8
  376. package/frontend/src/features/onboard/components/mcp/index.ts +2 -3
  377. package/frontend/src/features/onboard/index.ts +13 -3
  378. package/frontend/src/features/storage/components/BucketEmptyState.tsx +9 -6
  379. package/frontend/src/features/storage/components/BucketFormDialog.tsx +25 -41
  380. package/frontend/src/features/storage/components/FilePreviewDialog.tsx +20 -8
  381. package/frontend/src/features/storage/components/StorageDataGrid.tsx +4 -3
  382. package/frontend/src/features/storage/components/StorageManager.tsx +23 -34
  383. package/frontend/src/features/storage/components/index.ts +12 -0
  384. package/frontend/src/features/storage/hooks/useStorage.ts +208 -0
  385. package/frontend/src/features/storage/page/StoragePage.tsx +41 -115
  386. package/frontend/src/features/storage/services/storage.service.ts +22 -1
  387. package/frontend/src/features/visualizer/components/AuthNode.tsx +72 -56
  388. package/frontend/src/features/visualizer/components/BucketNode.tsx +4 -4
  389. package/frontend/src/features/visualizer/components/SchemaVisualizer.tsx +108 -80
  390. package/frontend/src/features/visualizer/components/TableNode.tsx +34 -41
  391. package/frontend/src/features/visualizer/components/VisualizerSkeleton.tsx +12 -4
  392. package/frontend/src/features/visualizer/page/VisualizerPage.tsx +33 -29
  393. package/frontend/src/index.css +1 -0
  394. package/frontend/src/lib/analytics/posthog.tsx +27 -0
  395. package/frontend/src/lib/contexts/AuthContext.tsx +38 -31
  396. package/frontend/src/lib/contexts/SocketContext.tsx +5 -6
  397. package/frontend/src/{features/metadata → lib}/hooks/useMetadata.ts +1 -1
  398. package/frontend/src/lib/hooks/useToast.tsx +6 -2
  399. package/frontend/src/lib/routing/AppRoutes.tsx +84 -0
  400. package/frontend/src/lib/routing/RequireAuth.tsx +27 -0
  401. package/frontend/src/lib/utils/cloudMessaging.ts +20 -0
  402. package/frontend/src/lib/utils/menuItems.ts +183 -0
  403. package/frontend/src/lib/utils/{validation-schemas.ts → schemaValidations.ts} +10 -5
  404. package/frontend/src/lib/utils/utils.ts +19 -1
  405. package/frontend/src/vite-env.d.ts +1 -0
  406. package/frontend/vite.config.ts +5 -3
  407. package/functions/server.ts +28 -3
  408. package/functions/worker-template.js +15 -4
  409. package/i18n/README.ar.md +130 -0
  410. package/i18n/README.de.md +130 -0
  411. package/i18n/README.es.md +154 -0
  412. package/i18n/README.fr.md +134 -0
  413. package/i18n/README.hi.md +129 -0
  414. package/i18n/README.ja.md +174 -0
  415. package/i18n/README.ko.md +137 -0
  416. package/i18n/README.pt-BR.md +131 -0
  417. package/i18n/README.ru.md +129 -0
  418. package/i18n/README.zh-CN.md +133 -0
  419. package/openapi/ai.yaml +31 -4
  420. package/openapi/auth.yaml +827 -146
  421. package/package.json +16 -7
  422. package/shared-schemas/package.json +1 -1
  423. package/shared-schemas/src/ai-api.schema.ts +34 -58
  424. package/shared-schemas/src/ai.schema.ts +5 -0
  425. package/shared-schemas/src/auth-api.schema.ts +154 -8
  426. package/shared-schemas/src/auth.schema.ts +42 -6
  427. package/shared-schemas/src/cloud-events.schema.ts +57 -0
  428. package/shared-schemas/src/database-api.schema.ts +3 -3
  429. package/shared-schemas/src/database.schema.ts +1 -1
  430. package/shared-schemas/src/index.ts +1 -0
  431. package/shared-schemas/src/logs-api.schema.ts +7 -1
  432. package/shared-schemas/src/logs.schema.ts +26 -0
  433. package/shared-schemas/src/metadata.schema.ts +9 -4
  434. package/test-gemini.sh +35 -0
  435. package/test-usage-admin.sh +57 -0
  436. package/test-usage.sh +50 -0
  437. package/zeabur/README.md +13 -0
  438. package/zeabur/template.yml +1032 -0
  439. package/.github/workflows/deploy-aws.yml +0 -130
  440. package/backend/src/api/routes/agent.ts +0 -29
  441. package/backend/src/api/routes/auth.oauth.ts +0 -482
  442. package/backend/src/api/routes/auth.ts +0 -386
  443. package/backend/src/api/routes/docs.ts +0 -66
  444. package/backend/src/api/routes/functions.ts +0 -183
  445. package/backend/src/api/routes/openapi.ts +0 -82
  446. package/backend/src/api/routes/usage.ts +0 -96
  447. package/backend/src/core/ai/client.ts +0 -242
  448. package/backend/src/core/ai/model.ts +0 -117
  449. package/backend/src/core/auth/auth.ts +0 -780
  450. package/backend/src/core/database/table.ts +0 -772
  451. package/backend/src/core/documentation/agent.ts +0 -689
  452. package/backend/src/core/documentation/openapi.ts +0 -856
  453. package/backend/src/core/logs/analytics.ts +0 -76
  454. package/backend/src/core/logs/providers/localdb.provider.ts +0 -246
  455. package/backend/src/core/storage/storage.ts +0 -923
  456. package/backend/src/utils/cloud-token.ts +0 -39
  457. package/backend/src/utils/helpers.ts +0 -49
  458. package/backend/src/utils/uuid.ts +0 -9
  459. package/backend/tests/manual/test-better-auth.sh +0 -303
  460. package/docker-init/db/logs.sql +0 -9
  461. package/frontend/README.md +0 -112
  462. package/frontend/src/components/datagrid/index.tsx +0 -20
  463. package/frontend/src/components/layout/CloudLayout.tsx +0 -95
  464. package/frontend/src/features/ai/components/AIConfigDialog.tsx +0 -76
  465. package/frontend/src/features/ai/components/AIConfigForm.tsx +0 -222
  466. package/frontend/src/features/ai/components/fields/ModalityField.tsx +0 -87
  467. package/frontend/src/features/ai/components/fields/ModelSelectionField.tsx +0 -134
  468. package/frontend/src/features/ai/components/fields/SystemPromptField.tsx +0 -33
  469. package/frontend/src/features/auth/components/AddOAuthDialog.tsx +0 -106
  470. package/frontend/src/features/auth/components/AuthMethodTab.tsx +0 -238
  471. package/frontend/src/features/auth/components/UsersTab.tsx +0 -114
  472. package/frontend/src/features/auth/page/AuthenticationPage.tsx +0 -169
  473. package/frontend/src/features/database/hooks/UseLinkModal.tsx +0 -78
  474. package/frontend/src/features/functions/components/FunctionViewer.tsx +0 -46
  475. package/frontend/src/features/functions/components/FunctionsContent.tsx +0 -88
  476. package/frontend/src/features/login/components/AuthErrorBoundary.tsx +0 -87
  477. package/frontend/src/features/login/components/PrivateRoute.tsx +0 -24
  478. package/frontend/src/features/logs/components/AnalyticsLogsTable.tsx +0 -313
  479. package/frontend/src/features/logs/components/LogsTable.tsx +0 -199
  480. package/frontend/src/features/logs/page/AnalyticsLogsPage.tsx +0 -530
  481. package/frontend/src/features/metadata/index.ts +0 -0
  482. package/frontend/src/features/metadata/page/MetadataPage.tsx +0 -136
  483. package/frontend/src/features/onboard/components/CompletionCard.tsx +0 -41
  484. package/frontend/src/features/onboard/components/OnboardButton.tsx +0 -84
  485. package/frontend/src/features/onboard/components/StepContent.tsx +0 -91
  486. package/frontend/src/features/onboard/components/TestConnectionStep.tsx +0 -53
  487. package/frontend/src/features/onboard/components/mcp/McpInstallation.tsx +0 -144
  488. package/frontend/src/features/onboard/page/OnBoardPage.tsx +0 -104
  489. package/frontend/src/features/onboard/types.ts +0 -8
  490. package/frontend/src/lib/contexts/OnboardStepContext.tsx +0 -68
  491. package/frontend/src/lib/hooks/useOnboardingCompletion.ts +0 -29
  492. /package/backend/src/api/{middleware → middlewares}/error.ts +0 -0
  493. /package/backend/src/api/{middleware → middlewares}/upload.ts +0 -0
  494. /package/backend/{migrations → src/infra/database/migrations}/000_create-base-tables.sql +0 -0
  495. /package/backend/{migrations → src/infra/database/migrations}/001_create-helper-functions.sql +0 -0
  496. /package/backend/{migrations → src/infra/database/migrations}/002_rename-auth-tables.sql +0 -0
  497. /package/backend/{migrations → src/infra/database/migrations}/003_create-users-table.sql +0 -0
  498. /package/backend/{migrations → src/infra/database/migrations}/004_add-reload-postgrest-func.sql +0 -0
  499. /package/backend/{migrations → src/infra/database/migrations}/005_enable-project-admin-modify-users.sql +0 -0
  500. /package/backend/{migrations → src/infra/database/migrations}/006_modify-ai-usage-table.sql +0 -0
  501. /package/backend/{migrations → src/infra/database/migrations}/007_drop-metadata-table.sql +0 -0
  502. /package/backend/{migrations → src/infra/database/migrations}/008_add-system-tables.sql +0 -0
  503. /package/backend/{migrations → src/infra/database/migrations}/009_add-function-secrets.sql +0 -0
  504. /package/backend/{migrations → src/infra/database/migrations}/010_modify-ai-config-modalities.sql +0 -0
  505. /package/backend/{migrations → src/infra/database/migrations}/011_refactor-secrets-table.sql +0 -0
  506. /package/backend/{migrations → src/infra/database/migrations}/012_add-storage-uploaded-by.sql +0 -0
  507. /package/frontend/src/{features/metadata → lib}/services/metadata.service.ts +0 -0
@@ -26,22 +26,24 @@ function DatabaseTextCellEditor({
26
26
  onRowChange,
27
27
  onClose,
28
28
  onCellEdit,
29
+ primaryKeyColumn,
29
30
  }: RenderEditCellProps<DatabaseDataGridRow> & {
30
31
  onCellEdit?: (rowId: string, columnKey: string, newValue: string) => Promise<void>;
32
+ primaryKeyColumn: string;
31
33
  }) {
32
34
  const handleValueChange = React.useCallback(
33
35
  (newValue: string) => {
34
36
  const oldValue = row[column.key];
35
37
 
36
38
  if (onCellEdit && String(oldValue) !== String(newValue)) {
37
- void onCellEdit(String(row.id || ''), column.key, newValue);
39
+ void onCellEdit(String(row[primaryKeyColumn] || ''), column.key, newValue);
38
40
  }
39
41
 
40
42
  const updatedRow = { ...row, [column.key]: newValue };
41
43
  onRowChange(updatedRow);
42
44
  onClose();
43
45
  },
44
- [row, column.key, onCellEdit, onRowChange, onClose]
46
+ [row, column.key, onCellEdit, onRowChange, onClose, primaryKeyColumn]
45
47
  );
46
48
 
47
49
  return (
@@ -61,23 +63,25 @@ function DatabaseBooleanCellEditor({
61
63
  onClose,
62
64
  onCellEdit,
63
65
  columnSchema,
66
+ primaryKeyColumn,
64
67
  }: RenderEditCellProps<DatabaseDataGridRow> & {
65
68
  onCellEdit?: (rowId: string, columnKey: string, newValue: string) => Promise<void>;
66
69
  columnSchema: ColumnSchema;
70
+ primaryKeyColumn: string;
67
71
  }) {
68
72
  const handleValueChange = React.useCallback(
69
73
  (newValue: string) => {
70
74
  const value: boolean | null = newValue === 'null' ? null : newValue === 'true';
71
75
 
72
76
  if (onCellEdit && row[column.key] !== value) {
73
- void onCellEdit(String(row.id || ''), column.key, newValue);
77
+ void onCellEdit(String(row[primaryKeyColumn] || ''), column.key, newValue);
74
78
  }
75
79
 
76
80
  const updatedRow = { ...row, [column.key]: value };
77
81
  onRowChange(updatedRow);
78
82
  onClose();
79
83
  },
80
- [row, column.key, onRowChange, onClose, onCellEdit]
84
+ [row, column.key, onRowChange, onClose, onCellEdit, primaryKeyColumn]
81
85
  );
82
86
 
83
87
  return (
@@ -97,9 +101,11 @@ function DatabaseDateCellEditor({
97
101
  onClose,
98
102
  onCellEdit,
99
103
  columnSchema,
104
+ primaryKeyColumn,
100
105
  }: RenderEditCellProps<DatabaseDataGridRow> & {
101
106
  onCellEdit?: (rowId: string, columnKey: string, newValue: string) => Promise<void>;
102
107
  columnSchema: ColumnSchema;
108
+ primaryKeyColumn: string;
103
109
  }) {
104
110
  const handleValueChange = React.useCallback(
105
111
  (newValue: string | null) => {
@@ -107,14 +113,14 @@ function DatabaseDateCellEditor({
107
113
  onCellEdit &&
108
114
  new Date(row[column.key] as string).getTime() !== new Date(newValue ?? '').getTime()
109
115
  ) {
110
- void onCellEdit(String(row.id || ''), column.key, newValue ?? '');
116
+ void onCellEdit(String(row[primaryKeyColumn] || ''), column.key, newValue ?? '');
111
117
  }
112
118
 
113
119
  const updatedRow = { ...row, [column.key]: newValue };
114
120
  onRowChange(updatedRow);
115
121
  onClose();
116
122
  },
117
- [onCellEdit, row, column.key, onRowChange, onClose]
123
+ [onCellEdit, row, column.key, onRowChange, onClose, primaryKeyColumn]
118
124
  );
119
125
 
120
126
  return (
@@ -135,21 +141,23 @@ function DatabaseJsonCellEditor({
135
141
  onClose,
136
142
  onCellEdit,
137
143
  columnSchema,
144
+ primaryKeyColumn,
138
145
  }: RenderEditCellProps<DatabaseDataGridRow> & {
139
146
  onCellEdit?: (rowId: string, columnKey: string, newValue: string) => Promise<void>;
140
147
  columnSchema: ColumnSchema;
148
+ primaryKeyColumn: string;
141
149
  }) {
142
150
  const handleValueChange = React.useCallback(
143
151
  (newValue: string) => {
144
152
  if (onCellEdit && row[column.key] !== newValue) {
145
- void onCellEdit(String(row.id || ''), column.key, newValue);
153
+ void onCellEdit(String(row[primaryKeyColumn] || ''), column.key, newValue);
146
154
  }
147
155
 
148
156
  const updatedRow = { ...row, [column.key]: newValue };
149
157
  onRowChange(updatedRow);
150
158
  onClose();
151
159
  },
152
- [column.key, onCellEdit, row, onRowChange, onClose]
160
+ [column.key, onCellEdit, row, onRowChange, onClose, primaryKeyColumn]
153
161
  );
154
162
 
155
163
  return (
@@ -172,6 +180,8 @@ export function convertSchemaToColumns(
172
180
  return [];
173
181
  }
174
182
 
183
+ const primaryKeyColumn = schema.columns.find((col) => col.isPrimaryKey)?.columnName || '';
184
+
175
185
  // Create typed cell renderers
176
186
  const cellRenderers = createDefaultCellRenderer<DatabaseDataGridRow>();
177
187
 
@@ -216,33 +226,57 @@ export function convertSchemaToColumns(
216
226
  />
217
227
  );
218
228
  // Note: editable is set in the column definition above
219
- } else if (col.columnName === 'id') {
229
+ } else if (col.columnName === primaryKeyColumn) {
220
230
  column.renderCell = cellRenderers.id;
221
231
  // Note: editable is set in the column definition above
222
232
  } else if (col.type === ColumnType.BOOLEAN) {
223
233
  column.renderCell = cellRenderers.boolean;
224
234
  column.renderEditCell = (props: RenderEditCellProps<DatabaseDataGridRow>) => (
225
- <DatabaseBooleanCellEditor {...props} columnSchema={col} onCellEdit={onCellEdit} />
235
+ <DatabaseBooleanCellEditor
236
+ {...props}
237
+ columnSchema={col}
238
+ onCellEdit={onCellEdit}
239
+ primaryKeyColumn={primaryKeyColumn}
240
+ />
226
241
  );
227
242
  } else if (col.type === ColumnType.DATE) {
228
243
  column.renderCell = cellRenderers.date;
229
244
  column.renderEditCell = (props: RenderEditCellProps<DatabaseDataGridRow>) => (
230
- <DatabaseDateCellEditor {...props} columnSchema={col} onCellEdit={onCellEdit} />
245
+ <DatabaseDateCellEditor
246
+ {...props}
247
+ columnSchema={col}
248
+ onCellEdit={onCellEdit}
249
+ primaryKeyColumn={primaryKeyColumn}
250
+ />
231
251
  );
232
252
  } else if (col.type === ColumnType.DATETIME) {
233
253
  column.renderCell = cellRenderers.datetime;
234
254
  column.renderEditCell = (props: RenderEditCellProps<DatabaseDataGridRow>) => (
235
- <DatabaseDateCellEditor {...props} columnSchema={col} onCellEdit={onCellEdit} />
255
+ <DatabaseDateCellEditor
256
+ {...props}
257
+ columnSchema={col}
258
+ onCellEdit={onCellEdit}
259
+ primaryKeyColumn={primaryKeyColumn}
260
+ />
236
261
  );
237
262
  } else if (col.type === ColumnType.JSON) {
238
263
  column.renderCell = cellRenderers.json;
239
264
  column.renderEditCell = (props: RenderEditCellProps<DatabaseDataGridRow>) => (
240
- <DatabaseJsonCellEditor {...props} columnSchema={col} onCellEdit={onCellEdit} />
265
+ <DatabaseJsonCellEditor
266
+ {...props}
267
+ columnSchema={col}
268
+ onCellEdit={onCellEdit}
269
+ primaryKeyColumn={primaryKeyColumn}
270
+ />
241
271
  );
242
272
  } else {
243
273
  column.renderCell = cellRenderers.text;
244
274
  column.renderEditCell = (props: RenderEditCellProps<DatabaseDataGridRow>) => (
245
- <DatabaseTextCellEditor {...props} onCellEdit={onCellEdit} />
275
+ <DatabaseTextCellEditor
276
+ {...props}
277
+ onCellEdit={onCellEdit}
278
+ primaryKeyColumn={primaryKeyColumn}
279
+ />
246
280
  );
247
281
  }
248
282
 
@@ -255,7 +289,6 @@ export interface DatabaseDataGridProps extends Omit<DataGridProps<DatabaseDataGr
255
289
  schema?: TableSchema;
256
290
  onCellEdit?: (rowId: string, columnKey: string, newValue: string) => Promise<void>;
257
291
  onJumpToTable?: (tableName: string) => void;
258
- searchQuery?: string;
259
292
  }
260
293
 
261
294
  // Specialized DataGrid for database tables
@@ -263,7 +296,6 @@ export function DatabaseDataGrid({
263
296
  schema,
264
297
  onCellEdit,
265
298
  onJumpToTable,
266
- searchQuery,
267
299
  ...props
268
300
  }: DatabaseDataGridProps) {
269
301
  const columns = useMemo(() => {
@@ -274,7 +306,6 @@ export function DatabaseDataGrid({
274
306
  <DataGrid<DatabaseDataGridRow>
275
307
  {...props}
276
308
  columns={columns}
277
- emptyStateTitle={searchQuery ? 'No records match your search criteria' : undefined}
278
309
  showSelection={true}
279
310
  showPagination={true}
280
311
  />
@@ -1,17 +1,20 @@
1
1
  import { useState, useMemo } from 'react';
2
- import { useQuery } from '@tanstack/react-query';
3
2
  import { Link2, AlertCircle, X } from 'lucide-react';
4
- import { Button } from '@/components/radix/Button';
5
- import { TypeBadge } from '@/components/TypeBadge';
6
- import { Popover, PopoverContent, PopoverTrigger } from '@/components/radix/Popover';
7
3
  import {
4
+ Button,
5
+ TypeBadge,
6
+ Popover,
7
+ PopoverContent,
8
+ PopoverTrigger,
8
9
  Tooltip,
9
10
  TooltipContent,
10
11
  TooltipProvider,
11
12
  TooltipTrigger,
12
- } from '@/components/radix/Tooltip';
13
- import { databaseService } from '@/features/database/services/database.service';
14
- import { ConvertedValue, DataGrid } from '@/components/datagrid';
13
+ ConvertedValue,
14
+ DataGrid,
15
+ } from '@/components';
16
+ import { useTables } from '@/features/database/hooks/useTables';
17
+ import { useRecords } from '@/features/database/hooks/useRecords';
15
18
  import { convertSchemaToColumns } from '@/features/database/components/DatabaseDataGrid';
16
19
  import { formatValueForDisplay } from '@/lib/utils/utils';
17
20
 
@@ -26,6 +29,8 @@ interface ForeignKeyCellProps {
26
29
 
27
30
  export function ForeignKeyCell({ value, foreignKey, onJumpToTable }: ForeignKeyCellProps) {
28
31
  const [open, setOpen] = useState(false);
32
+ const { useTableSchema } = useTables();
33
+ const recordsHook = useRecords(foreignKey.table);
29
34
 
30
35
  // Helper function to safely render any value type (including JSON objects)
31
36
  const renderValue = (val: ConvertedValue): string => {
@@ -33,41 +38,17 @@ export function ForeignKeyCell({ value, foreignKey, onJumpToTable }: ForeignKeyC
33
38
  };
34
39
 
35
40
  // Fetch the referenced record when popover opens
41
+ const searchValue = value ? renderValue(value) : '';
36
42
  const {
37
43
  data: recordData,
38
44
  isLoading: _isLoading,
39
45
  error,
40
- } = useQuery({
41
- queryKey: ['table', foreignKey.table, foreignKey.column, value],
42
- queryFn: async () => {
43
- if (!value) {
44
- return null;
45
- }
46
-
47
- try {
48
- const searchValue = renderValue(value);
49
- const record = await databaseService.getRecordByForeignKeyValue(
50
- foreignKey.table,
51
- foreignKey.column,
52
- searchValue
53
- );
54
- return record;
55
- } catch (error) {
56
- console.error('Failed to fetch foreign key record:', error);
57
- throw error;
58
- }
59
- },
60
- enabled: open && !!value,
61
- });
46
+ } = recordsHook.useRecordByForeignKey(foreignKey.column, searchValue, open && !!value);
62
47
 
63
48
  const record = recordData;
64
49
 
65
50
  // Fetch schema for the referenced table
66
- const { data: schema } = useQuery({
67
- queryKey: ['schema', foreignKey.table],
68
- queryFn: () => databaseService.getTableSchema(foreignKey.table),
69
- enabled: open && !!value,
70
- });
51
+ const { data: schema } = useTableSchema(foreignKey.table, open && !!value);
71
52
 
72
53
  // Convert schema to columns for the mini DataGrid
73
54
  const columns = useMemo(() => {
@@ -1,11 +1,17 @@
1
1
  import { useState, useEffect, useMemo } from 'react';
2
- import { useQuery } from '@tanstack/react-query';
3
- import { Button } from '@/components/radix/Button';
4
- import { Label } from '@/components/radix/Label';
5
- import { Dialog, DialogContent, DialogTitle, DialogDescription } from '@/components/radix/Dialog';
6
- import { Select, SelectContent, SelectItem, SelectTrigger } from '@/components/radix/Select';
7
- import { useMetadata } from '@/features/metadata/hooks/useMetadata';
8
- import { databaseService } from '@/features/database/services/database.service';
2
+ import {
3
+ Button,
4
+ Label,
5
+ Dialog,
6
+ DialogContent,
7
+ DialogTitle,
8
+ DialogDescription,
9
+ Select,
10
+ SelectContent,
11
+ SelectItem,
12
+ SelectTrigger,
13
+ } from '@/components';
14
+ import { useTables } from '@/features/database/hooks/useTables';
9
15
  import { UseFormReturn } from 'react-hook-form';
10
16
  import { TableFormSchema, TableFormForeignKeySchema } from '../schema';
11
17
  import { ColumnSchema, OnDeleteActionSchema, OnUpdateActionSchema } from '@insforge/shared-schemas';
@@ -39,6 +45,7 @@ export function ForeignKeyPopover({
39
45
  });
40
46
 
41
47
  const columns = form.watch('columns');
48
+ const { tables, useTableSchema } = useTables();
42
49
 
43
50
  // Set initial values when editing
44
51
  useEffect(() => {
@@ -63,23 +70,15 @@ export function ForeignKeyPopover({
63
70
  }, [open, initialValue]);
64
71
 
65
72
  // Get available tables
66
- const { tables } = useMetadata({ enabled: open });
67
-
68
73
  const availableTables = tables.filter(
69
74
  (tableName) => mode === 'create' || tableName !== editTableName
70
75
  );
71
76
 
72
77
  // Get columns for selected reference table
73
- const { data: referenceTableSchema } = useQuery({
74
- queryKey: ['table-schema', newForeignKey.referenceTable],
75
- queryFn: async () => {
76
- if (!newForeignKey.referenceTable) {
77
- return null;
78
- }
79
- return await databaseService.getTableSchema(newForeignKey.referenceTable);
80
- },
81
- enabled: !!newForeignKey.referenceTable && open,
82
- });
78
+ const { data: referenceTableSchema } = useTableSchema(
79
+ newForeignKey.referenceTable || '',
80
+ !!newForeignKey.referenceTable && open
81
+ );
83
82
 
84
83
  // Get the type of the selected source column
85
84
  const getSourceFieldType = useMemo(() => {
@@ -237,7 +236,7 @@ export function ForeignKeyPopover({
237
236
  <SelectContent className="max-w-[360px]">
238
237
  {(() => {
239
238
  const allColumns = referenceTableSchema?.columns || [];
240
- if (allColumns.length > 0) {
239
+ if (allColumns.length) {
241
240
  const sourceType = getSourceFieldType;
242
241
 
243
242
  return allColumns.map((col: ColumnSchema) => {
@@ -1,11 +1,13 @@
1
- import { useState, useEffect, useMemo, useCallback } from 'react';
2
- import { useQuery } from '@tanstack/react-query';
3
- import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/radix/Dialog';
4
- import { Button } from '@/components/radix/Button';
5
- import { databaseService } from '@/features/database/services/database.service';
6
- import { convertSchemaToColumns } from '@/features/database/components/DatabaseDataGrid';
7
- import { SearchInput, DataGrid, TypeBadge } from '@/components';
1
+ import { useState, useEffect, useMemo, useCallback, ReactNode } from 'react';
8
2
  import {
3
+ Button,
4
+ Dialog,
5
+ DialogContent,
6
+ DialogHeader,
7
+ DialogTitle,
8
+ SearchInput,
9
+ DataGrid,
10
+ TypeBadge,
9
11
  type CellMouseEvent,
10
12
  type CellClickArgs,
11
13
  type RenderCellProps,
@@ -15,71 +17,57 @@ import {
15
17
  type DatabaseRecord,
16
18
  type ConvertedValue,
17
19
  type DataGridRowType,
18
- } from '@/components/datagrid';
20
+ } from '@/components';
21
+ import { useTables } from '@/features/database/hooks/useTables';
22
+ import { useRecords } from '@/features/database/hooks/useRecords';
23
+ import { convertSchemaToColumns } from '@/features/database/components/DatabaseDataGrid';
19
24
  import { formatValueForDisplay } from '@/lib/utils/utils';
20
25
  import { ColumnType } from '@insforge/shared-schemas';
21
26
 
22
27
  const PAGE_SIZE = 50;
23
28
 
24
29
  interface LinkRecordModalProps {
25
- open: boolean;
26
- onOpenChange: (open: boolean) => void;
27
30
  referenceTable: string;
28
31
  referenceColumn: string;
29
32
  onSelectRecord: (record: DatabaseRecord) => void;
30
- currentValue?: string | null;
33
+ children: (openModal: () => void) => ReactNode;
31
34
  }
32
35
 
33
36
  export function LinkRecordModal({
34
- open,
35
- onOpenChange,
36
37
  referenceTable,
37
38
  referenceColumn,
38
39
  onSelectRecord,
40
+ children,
39
41
  }: LinkRecordModalProps) {
42
+ const [open, setOpen] = useState(false);
40
43
  const [searchQuery, setSearchQuery] = useState('');
41
44
  const [selectedRecord, setSelectedRecord] = useState<DatabaseRecord | null>(null);
42
45
  const [sortColumns, setSortColumns] = useState<SortColumn[]>([]);
43
46
  const [currentPage, setCurrentPage] = useState(1);
47
+ const { useTableSchema } = useTables();
48
+ const recordsHook = useRecords(referenceTable);
44
49
 
45
50
  // Fetch table schema
46
- const { data: schema } = useQuery({
47
- queryKey: ['table-schema', referenceTable],
48
- queryFn: () => databaseService.getTableSchema(referenceTable),
49
- enabled: open,
50
- });
51
+ const { data: schema } = useTableSchema(referenceTable, open);
51
52
 
52
53
  // Fetch records from the reference table
53
- const { data: recordsData, isLoading } = useQuery({
54
- queryKey: [
55
- 'table',
56
- referenceTable,
57
- currentPage,
58
- PAGE_SIZE,
59
- searchQuery,
60
- JSON.stringify(sortColumns),
61
- ],
62
- queryFn: async () => {
63
- const offset = (currentPage - 1) * PAGE_SIZE;
64
- const [schema, records] = await Promise.all([
65
- databaseService.getTableSchema(referenceTable),
66
- databaseService.getTableRecords(
67
- referenceTable,
68
- PAGE_SIZE,
69
- offset,
70
- searchQuery || undefined,
71
- sortColumns
72
- ),
73
- ]);
54
+ const offset = (currentPage - 1) * PAGE_SIZE;
55
+ const { data: recordsResponse, isLoading } = recordsHook.useTableRecords(
56
+ PAGE_SIZE,
57
+ offset,
58
+ searchQuery || undefined,
59
+ sortColumns,
60
+ open
61
+ );
74
62
 
75
- return {
76
- schema,
77
- records: records.records,
78
- totalRecords: records.pagination.total || schema.recordCount,
79
- };
80
- },
81
- enabled: open,
82
- });
63
+ const recordsData =
64
+ schema && recordsResponse
65
+ ? {
66
+ schema,
67
+ records: recordsResponse.records,
68
+ totalRecords: recordsResponse.pagination.total || schema.recordCount,
69
+ }
70
+ : undefined;
83
71
 
84
72
  // Reset page when search query changes
85
73
  useEffect(() => {
@@ -193,96 +181,103 @@ export function LinkRecordModal({
193
181
  const handleConfirmSelection = () => {
194
182
  if (selectedRecord) {
195
183
  onSelectRecord(selectedRecord);
196
- onOpenChange(false);
184
+ setOpen(false);
197
185
  }
198
186
  };
199
187
 
200
188
  const handleCancel = () => {
201
- onOpenChange(false);
189
+ setOpen(false);
202
190
  };
203
191
 
204
192
  return (
205
- <Dialog open={open} onOpenChange={onOpenChange}>
206
- <DialogContent className="max-w-4xl h-[calc(100vh-48px)] p-0 gap-0 flex flex-col">
207
- <DialogHeader className="px-6 py-3 border-b border-zinc-200 dark:border-neutral-700 flex-shrink-0 flex flex-col gap-1">
208
- <DialogTitle className="text-lg font-semibold text-zinc-950 dark:text-white">
209
- Link Record
210
- </DialogTitle>
211
- <div className="flex items-center gap-1.5">
212
- <span className="text-sm text-zinc-500 dark:text-neutral-400">
213
- Select a record to reference from
214
- </span>
215
- <TypeBadge
216
- type={`${referenceTable}.${referenceColumn}`}
217
- className="dark:bg-neutral-700"
193
+ <>
194
+ {children(() => setOpen(true))}
195
+ <Dialog open={open} onOpenChange={setOpen}>
196
+ <DialogContent className="max-w-4xl h-[calc(100vh-48px)] p-0 gap-0 flex flex-col">
197
+ <DialogHeader className="px-6 py-3 border-b border-zinc-200 dark:border-neutral-700 flex-shrink-0 flex flex-col gap-1">
198
+ <DialogTitle className="text-lg font-semibold text-zinc-950 dark:text-white">
199
+ Link Record
200
+ </DialogTitle>
201
+ <div className="flex items-center gap-1.5">
202
+ <span className="text-sm text-zinc-500 dark:text-neutral-400">
203
+ Select a record to reference from
204
+ </span>
205
+ <TypeBadge
206
+ type={`${referenceTable}.${referenceColumn}`}
207
+ className="dark:bg-neutral-700"
208
+ />
209
+ </div>
210
+ </DialogHeader>
211
+
212
+ {/* Search Bar */}
213
+ <div className="p-3">
214
+ <SearchInput
215
+ value={searchQuery}
216
+ onChange={setSearchQuery}
217
+ placeholder="Search records..."
218
+ className="w-60 dark:text-white dark:bg-neutral-900 dark:border-neutral-700"
219
+ debounceTime={300}
218
220
  />
219
221
  </div>
220
- </DialogHeader>
221
-
222
- {/* Search Bar */}
223
- <div className="p-3">
224
- <SearchInput
225
- value={searchQuery}
226
- onChange={setSearchQuery}
227
- placeholder="Search records..."
228
- className="w-60 dark:text-white dark:bg-neutral-900 dark:border-neutral-700"
229
- debounceTime={300}
230
- />
231
- </div>
232
222
 
233
- {/* Records DataGrid */}
234
- <div className="flex-1 overflow-hidden">
235
- <DataGrid
236
- data={records}
237
- columns={columns}
238
- loading={isLoading && !records.length}
239
- selectedRows={selectedRows}
240
- onSelectedRowsChange={(newSelectedRows) => {
241
- // Handle selection changes from cell clicks
242
- const selectedId = Array.from(newSelectedRows)[0];
243
- if (selectedId) {
244
- const record = records.find((r: DatabaseRecord) => String(r.id) === selectedId);
245
- if (record) {
246
- setSelectedRecord(record);
223
+ {/* Records DataGrid */}
224
+ <div className="flex-1 overflow-hidden">
225
+ <DataGrid
226
+ data={records}
227
+ columns={columns}
228
+ loading={isLoading && !records.length}
229
+ selectedRows={selectedRows}
230
+ onSelectedRowsChange={(newSelectedRows) => {
231
+ // Handle selection changes from cell clicks
232
+ const selectedId = Array.from(newSelectedRows)[0];
233
+ if (selectedId) {
234
+ const record = records.find((r: DatabaseRecord) => String(r.id) === selectedId);
235
+ if (record) {
236
+ setSelectedRecord(record);
237
+ }
238
+ } else {
239
+ setSelectedRecord(null);
247
240
  }
248
- } else {
249
- setSelectedRecord(null);
241
+ }}
242
+ sortColumns={sortColumns}
243
+ onSortColumnsChange={setSortColumns}
244
+ onCellClick={handleCellClick}
245
+ currentPage={currentPage}
246
+ totalPages={totalPages}
247
+ pageSize={PAGE_SIZE}
248
+ totalRecords={totalRecords}
249
+ onPageChange={setCurrentPage}
250
+ showSelection={false}
251
+ showPagination={true}
252
+ emptyState={
253
+ <div className="flex flex-col items-center justify-center h-full">
254
+ <p className="text-neutral-500 dark:text-neutral-400 select-none">
255
+ {searchQuery ? 'No records match your search criteria' : 'No records found'}
256
+ </p>
257
+ </div>
250
258
  }
251
- }}
252
- sortColumns={sortColumns}
253
- onSortColumnsChange={setSortColumns}
254
- onCellClick={handleCellClick}
255
- currentPage={currentPage}
256
- totalPages={totalPages}
257
- pageSize={PAGE_SIZE}
258
- totalRecords={totalRecords}
259
- onPageChange={setCurrentPage}
260
- showSelection={false}
261
- showPagination={true}
262
- emptyStateTitle={
263
- searchQuery ? 'No records match your search criteria' : 'No records found'
264
- }
265
- />
266
- </div>
259
+ />
260
+ </div>
267
261
 
268
- {/* Footer */}
269
- <div className="px-6 py-4 border-t border-zinc-200 dark:border-neutral-700 flex justify-end gap-3 flex-shrink-0">
270
- <Button
271
- variant="outline"
272
- onClick={handleCancel}
273
- className="dark:bg-neutral-600 dark:text-white dark:border-transparent dark:hover:bg-neutral-700"
274
- >
275
- Cancel
276
- </Button>
277
- <Button
278
- onClick={handleConfirmSelection}
279
- disabled={!selectedRecord}
280
- className="bg-zinc-950 hover:bg-zinc-800 text-white dark:bg-emerald-300 dark:text-zinc-950 dark:hover:bg-emerald-400"
281
- >
282
- Add Record
283
- </Button>
284
- </div>
285
- </DialogContent>
286
- </Dialog>
262
+ {/* Footer */}
263
+ <div className="px-6 py-4 border-t border-zinc-200 dark:border-neutral-700 flex justify-end gap-3 flex-shrink-0">
264
+ <Button
265
+ variant="outline"
266
+ onClick={handleCancel}
267
+ className="dark:bg-neutral-600 dark:text-white dark:border-transparent dark:hover:bg-neutral-700"
268
+ >
269
+ Cancel
270
+ </Button>
271
+ <Button
272
+ onClick={handleConfirmSelection}
273
+ disabled={!selectedRecord}
274
+ className="bg-zinc-950 hover:bg-zinc-800 text-white dark:bg-emerald-300 dark:text-zinc-950 dark:hover:bg-emerald-400"
275
+ >
276
+ Add Record
277
+ </Button>
278
+ </div>
279
+ </DialogContent>
280
+ </Dialog>
281
+ </>
287
282
  );
288
283
  }