insforge 0.3.3 → 1.3.0

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 (635) hide show
  1. package/.claude-plugin/marketplace.json +20 -0
  2. package/.dockerignore +60 -57
  3. package/.env.example +84 -49
  4. package/.github/ISSUE_TEMPLATE/bug_report.yml +36 -83
  5. package/.github/ISSUE_TEMPLATE/config.yml +11 -11
  6. package/.github/ISSUE_TEMPLATE/feature_request.yml +26 -79
  7. package/.github/PULL_REQUEST_TEMPLATE.md +7 -0
  8. package/.github/copilot-instructions.md +146 -146
  9. package/.github/workflows/build-image.yml +66 -65
  10. package/.github/workflows/ci-premerge-check.yml +23 -23
  11. package/.github/workflows/e2e.yml +63 -0
  12. package/.github/workflows/lint-and-format.yml +32 -32
  13. package/.prettierignore +64 -64
  14. package/CHANGELOG.md +44 -3
  15. package/CLAUDE_PLUGIN.md +104 -0
  16. package/CODE_OF_CONDUCT.md +128 -0
  17. package/CONTRIBUTING.md +125 -125
  18. package/Dockerfile +30 -27
  19. package/GITHUB_OAUTH_SETUP.md +49 -49
  20. package/GOOGLE_OAUTH_SETUP.md +148 -148
  21. package/LICENSE +201 -201
  22. package/README.md +182 -134
  23. package/assets/Dark.svg +23 -23
  24. package/assets/mcpInstallv2.png +0 -0
  25. package/assets/sampleResponse.png +0 -0
  26. package/auth/index.html +13 -0
  27. package/auth/package.json +28 -0
  28. package/auth/public/favicon.ico +0 -0
  29. package/auth/src/App.tsx +33 -0
  30. package/auth/src/components/ErrorCard.tsx +37 -0
  31. package/auth/src/components/Layout.tsx +13 -0
  32. package/auth/src/index.css +19 -0
  33. package/auth/src/lib/broadcastService.ts +117 -0
  34. package/auth/src/lib/utils.ts +11 -0
  35. package/auth/src/main.tsx +22 -0
  36. package/auth/src/pages/ForgotPasswordPage.tsx +11 -0
  37. package/auth/src/pages/ResetPasswordPage.tsx +11 -0
  38. package/auth/src/pages/SignInPage.tsx +60 -0
  39. package/auth/src/pages/SignUpPage.tsx +60 -0
  40. package/auth/src/pages/VerifyEmailPage.tsx +20 -0
  41. package/auth/src/vite-env.d.ts +10 -0
  42. package/auth/tsconfig.json +32 -0
  43. package/auth/tsconfig.node.json +11 -0
  44. package/auth/vite.config.ts +25 -0
  45. package/backend/package.json +78 -75
  46. package/backend/src/api/{middleware → middlewares}/auth.ts +8 -9
  47. package/backend/src/api/middlewares/rate-limiters.ts +127 -0
  48. package/backend/src/api/routes/{ai.ts → ai/index.routes.ts} +22 -26
  49. package/backend/src/api/routes/auth/index.routes.ts +667 -0
  50. package/backend/src/api/routes/auth/oauth.routes.ts +473 -0
  51. package/backend/src/api/routes/{database.advance.ts → database/advance.routes.ts} +128 -65
  52. package/backend/src/api/routes/database/index.routes.ts +90 -0
  53. package/backend/src/api/routes/{database.records.ts → database/records.routes.ts} +26 -12
  54. package/backend/src/api/routes/{database.tables.ts → database/tables.routes.ts} +6 -23
  55. package/backend/src/api/routes/docs/index.routes.ts +75 -0
  56. package/backend/src/api/routes/email/index.routes.ts +35 -0
  57. package/backend/src/api/routes/functions/index.routes.ts +194 -0
  58. package/backend/src/api/routes/{logs.ts → logs/index.routes.ts} +25 -30
  59. package/backend/src/api/routes/{metadata.ts → metadata/index.routes.ts} +33 -31
  60. package/backend/src/api/routes/realtime/channels.routes.ts +81 -0
  61. package/backend/src/api/routes/realtime/index.routes.ts +12 -0
  62. package/backend/src/api/routes/realtime/messages.routes.ts +48 -0
  63. package/backend/src/api/routes/realtime/permissions.routes.ts +19 -0
  64. package/backend/src/api/routes/{secrets.ts → secrets/index.routes.ts} +27 -22
  65. package/backend/src/api/routes/{storage.ts → storage/index.routes.ts} +48 -61
  66. package/backend/src/api/routes/usage/index.routes.ts +91 -0
  67. package/backend/src/infra/config/app.config.ts +51 -0
  68. package/backend/src/infra/database/database.manager.ts +182 -0
  69. package/backend/{migrations → src/infra/database/migrations}/000_create-base-tables.sql +141 -141
  70. package/backend/{migrations → src/infra/database/migrations}/001_create-helper-functions.sql +40 -40
  71. package/backend/{migrations → src/infra/database/migrations}/002_rename-auth-tables.sql +29 -29
  72. package/backend/{migrations → src/infra/database/migrations}/003_create-users-table.sql +55 -55
  73. package/backend/{migrations → src/infra/database/migrations}/004_add-reload-postgrest-func.sql +23 -23
  74. package/backend/{migrations → src/infra/database/migrations}/005_enable-project-admin-modify-users.sql +29 -29
  75. package/backend/{migrations → src/infra/database/migrations}/006_modify-ai-usage-table.sql +24 -24
  76. package/backend/{migrations → src/infra/database/migrations}/007_drop-metadata-table.sql +1 -1
  77. package/backend/{migrations → src/infra/database/migrations}/008_add-system-tables.sql +76 -76
  78. package/backend/{migrations → src/infra/database/migrations}/009_add-function-secrets.sql +23 -23
  79. package/backend/{migrations → src/infra/database/migrations}/010_modify-ai-config-modalities.sql +93 -93
  80. package/backend/{migrations → src/infra/database/migrations}/011_refactor-secrets-table.sql +15 -15
  81. package/backend/{migrations → src/infra/database/migrations}/012_add-storage-uploaded-by.sql +7 -7
  82. package/backend/src/infra/database/migrations/013_create-auth-schema-functions.sql +44 -0
  83. package/backend/src/infra/database/migrations/014_add-updated-at-trigger-user-table.sql +8 -0
  84. package/backend/src/infra/database/migrations/015_create-auth-config-and-email-otp-tables.sql +60 -0
  85. package/backend/src/infra/database/migrations/016_update-auth-config-and-email-otp.sql +24 -0
  86. package/backend/src/infra/database/migrations/017_create-realtime-schema.sql +233 -0
  87. package/backend/src/infra/realtime/realtime.manager.ts +246 -0
  88. package/backend/src/infra/realtime/webhook-sender.ts +82 -0
  89. package/backend/src/{core/secrets/encryption.ts → infra/security/encryption.manager.ts} +3 -2
  90. package/backend/src/infra/security/token.manager.ts +219 -0
  91. package/backend/src/infra/socket/socket.manager.ts +522 -0
  92. package/backend/src/providers/ai/openrouter.provider.ts +380 -0
  93. package/backend/src/providers/email/base.provider.ts +38 -0
  94. package/backend/src/providers/email/cloud.provider.ts +271 -0
  95. package/backend/src/{core/logs/providers → providers/logs}/base.provider.ts +11 -11
  96. package/backend/src/{core/logs/providers → providers/logs}/cloudwatch.provider.ts +61 -38
  97. package/backend/src/providers/logs/local.provider.ts +185 -0
  98. package/backend/src/providers/oauth/apple.provider.ts +266 -0
  99. package/backend/src/providers/oauth/base.provider.ts +29 -0
  100. package/backend/src/providers/oauth/discord.provider.ts +195 -0
  101. package/backend/src/providers/oauth/facebook.provider.ts +194 -0
  102. package/backend/src/providers/oauth/github.provider.ts +208 -0
  103. package/backend/src/providers/oauth/google.provider.ts +249 -0
  104. package/backend/src/providers/oauth/index.ts +8 -0
  105. package/backend/src/providers/oauth/linkedin.provider.ts +240 -0
  106. package/backend/src/providers/oauth/microsoft.provider.ts +169 -0
  107. package/backend/src/providers/oauth/x.provider.ts +202 -0
  108. package/backend/src/providers/storage/base.provider.ts +29 -0
  109. package/backend/src/providers/storage/local.provider.ts +103 -0
  110. package/backend/src/providers/storage/s3.provider.ts +313 -0
  111. package/backend/src/server.ts +317 -288
  112. package/backend/src/{core/ai/config.ts → services/ai/ai-config.service.ts} +19 -24
  113. package/backend/src/services/ai/ai-model.service.ts +60 -0
  114. package/backend/src/{core/ai/usage.ts → services/ai/ai-usage.service.ts} +28 -35
  115. package/backend/src/{core/ai/chat.ts → services/ai/chat-completion.service.ts} +37 -24
  116. package/backend/src/services/ai/helpers.ts +64 -0
  117. package/backend/src/{core/ai/image.ts → services/ai/image-generation.service.ts} +17 -19
  118. package/backend/src/services/ai/index.ts +13 -0
  119. package/backend/src/services/auth/auth-config.service.ts +250 -0
  120. package/backend/src/services/auth/auth-otp.service.ts +424 -0
  121. package/backend/src/services/auth/auth.service.ts +1150 -0
  122. package/backend/src/services/auth/index.ts +4 -0
  123. package/backend/src/{core/auth/oauth.ts → services/auth/oauth-config.service.ts} +106 -52
  124. package/backend/src/{core/database/advance.ts → services/database/database-advance.service.ts} +97 -131
  125. package/backend/src/services/database/database-table.service.ts +802 -0
  126. package/backend/src/services/database/database.service.ts +127 -0
  127. package/backend/src/services/email/email.service.ts +73 -0
  128. package/backend/src/{core/functions/functions.ts → services/functions/function.service.ts} +95 -88
  129. package/backend/src/{core/logs/audit.ts → services/logs/audit.service.ts} +92 -75
  130. package/backend/src/services/logs/log.service.ts +73 -0
  131. package/backend/src/services/realtime/index.ts +3 -0
  132. package/backend/src/services/realtime/realtime-auth.service.ts +104 -0
  133. package/backend/src/services/realtime/realtime-channel.service.ts +237 -0
  134. package/backend/src/services/realtime/realtime-message.service.ts +260 -0
  135. package/backend/src/{core/secrets/secrets.ts → services/secrets/secret.service.ts} +48 -66
  136. package/backend/src/services/storage/storage.service.ts +617 -0
  137. package/backend/src/services/usage/usage.service.ts +149 -0
  138. package/backend/src/types/auth.ts +77 -2
  139. package/backend/src/types/email.ts +8 -0
  140. package/backend/src/types/error-constants.ts +4 -0
  141. package/backend/src/types/logs.ts +0 -29
  142. package/backend/src/types/realtime.ts +18 -0
  143. package/backend/src/{core/socket/types.ts → types/socket.ts} +11 -36
  144. package/backend/src/utils/cookies.ts +35 -0
  145. package/backend/src/utils/environment.ts +9 -3
  146. package/backend/src/utils/logger.ts +20 -2
  147. package/backend/src/utils/s3-config-loader.ts +64 -0
  148. package/backend/src/utils/seed.ts +301 -205
  149. package/backend/src/utils/sql-parser.ts +91 -1
  150. package/backend/src/utils/utils.ts +114 -0
  151. package/backend/src/utils/validations.ts +40 -4
  152. package/backend/tests/README.md +133 -133
  153. package/backend/tests/cleanup-all-test-data.sh +230 -230
  154. package/backend/tests/cloud/test-s3-multitenant.sh +131 -131
  155. package/backend/tests/local/comprehensive-curl-tests.sh +155 -155
  156. package/backend/tests/local/test-ai-config.sh +129 -0
  157. package/backend/tests/local/test-ai-usage.sh +80 -0
  158. package/backend/tests/local/test-auth-router.sh +143 -143
  159. package/backend/tests/local/test-database-router.sh +222 -222
  160. package/backend/tests/local/test-e2e.sh +240 -240
  161. package/backend/tests/local/test-fk-errors.sh +96 -96
  162. package/backend/tests/local/test-functions.sh +123 -0
  163. package/backend/tests/local/test-id-field.sh +200 -200
  164. package/backend/tests/local/test-logs.sh +132 -0
  165. package/backend/tests/local/test-public-bucket.sh +264 -264
  166. package/backend/tests/local/test-secrets.sh +249 -247
  167. package/backend/tests/local/test-serverless-functions.sh.disabled +325 -325
  168. package/backend/tests/local/test-traditional-rest.sh +208 -208
  169. package/backend/tests/manual/README.md +50 -50
  170. package/backend/tests/manual/create-large-table-simple.sql +10 -10
  171. package/backend/tests/manual/seed-large-table.sql +100 -100
  172. package/backend/tests/manual/setup-large-table-extras.sql +33 -33
  173. package/backend/tests/manual/test-bulk-upsert.sh +409 -409
  174. package/backend/tests/manual/test-database-advance.sh +296 -296
  175. package/backend/tests/manual/test-postgrest-stability.sh +191 -191
  176. package/backend/tests/manual/test-rawsql-export-import.sh +411 -411
  177. package/backend/tests/manual/test-rawsql-modes.sh +244 -0
  178. package/backend/tests/manual/test-universal-storage.sh +263 -263
  179. package/backend/tests/manual/test-users.sql +17 -17
  180. package/backend/tests/run-all-tests.sh +139 -139
  181. package/backend/tests/setup.ts +0 -0
  182. package/backend/tests/test-config.sh +338 -302
  183. package/backend/tests/unit/analyze-query.test.ts +697 -0
  184. package/backend/tests/unit/cloud-token.test.ts +48 -0
  185. package/backend/tests/unit/constant.test.ts +8 -0
  186. package/backend/tests/unit/email.test.ts +372 -0
  187. package/backend/tests/unit/environment.test.ts +59 -0
  188. package/backend/tests/unit/helpers.test.ts +63 -0
  189. package/backend/tests/unit/logger.test.ts +22 -0
  190. package/backend/tests/unit/rate-limit.test.ts +154 -0
  191. package/backend/tests/unit/response.test.ts +58 -0
  192. package/backend/tests/unit/sql-parser.test.ts +74 -0
  193. package/backend/tests/unit/uuid.test.ts +21 -0
  194. package/backend/tests/unit/validations.test.ts +80 -0
  195. package/backend/tsconfig.json +22 -22
  196. package/backend/vitest.config.ts +11 -0
  197. package/claude-plugin/.claude-plugin/plugin.json +24 -0
  198. package/claude-plugin/README.md +133 -0
  199. package/claude-plugin/skills/insforge-schema-patterns/SKILL.md +270 -0
  200. package/docker-compose.prod.yml +204 -144
  201. package/docker-compose.yml +232 -167
  202. package/docker-init/db/db-init.sql +97 -125
  203. package/docker-init/db/jwt.sql +5 -5
  204. package/docker-init/db/postgresql.conf +16 -16
  205. package/docker-init/logs/vector.yml +236 -0
  206. package/docs/README.md +44 -0
  207. package/docs/agent-docs/real-time.md +269 -0
  208. package/docs/changelog.mdx +119 -0
  209. package/docs/core-concepts/ai/architecture.mdx +373 -0
  210. package/docs/core-concepts/ai/sdk.mdx +213 -0
  211. package/docs/core-concepts/authentication/architecture.mdx +278 -0
  212. package/docs/core-concepts/authentication/sdk.mdx +414 -0
  213. package/docs/core-concepts/authentication/ui-components/customization.mdx +529 -0
  214. package/docs/core-concepts/authentication/ui-components/nextjs.mdx +221 -0
  215. package/docs/core-concepts/authentication/ui-components/react-router.mdx +184 -0
  216. package/docs/core-concepts/authentication/ui-components/react.mdx +129 -0
  217. package/docs/core-concepts/database/architecture.mdx +256 -0
  218. package/docs/core-concepts/database/sdk.mdx +382 -0
  219. package/docs/core-concepts/email/architecture.mdx +101 -0
  220. package/docs/core-concepts/email/sdk.mdx +53 -0
  221. package/docs/core-concepts/functions/architecture.mdx +105 -0
  222. package/docs/core-concepts/functions/sdk.mdx +184 -0
  223. package/docs/core-concepts/realtime/architecture.mdx +446 -0
  224. package/docs/core-concepts/realtime/sdk.mdx +409 -0
  225. package/docs/core-concepts/storage/architecture.mdx +243 -0
  226. package/docs/core-concepts/storage/sdk.mdx +253 -0
  227. package/docs/deployment/README.md +94 -0
  228. package/docs/deployment/deploy-to-aws-ec2.md +565 -0
  229. package/docs/deployment/deploy-to-azure-virtual-machines.md +313 -0
  230. package/docs/deployment/deploy-to-google-cloud-compute-engine.md +613 -0
  231. package/docs/deployment/deploy-to-render.md +441 -0
  232. package/docs/deprecated/insforge-auth-api.md +214 -214
  233. package/docs/deprecated/insforge-auth-sdk.md +99 -99
  234. package/docs/deprecated/insforge-db-api.md +358 -358
  235. package/docs/deprecated/insforge-db-sdk.md +139 -139
  236. package/docs/deprecated/insforge-debug-sdk.md +156 -156
  237. package/docs/deprecated/insforge-debug.md +64 -64
  238. package/docs/deprecated/insforge-instructions.md +123 -123
  239. package/docs/deprecated/insforge-project.md +117 -117
  240. package/docs/deprecated/insforge-storage-api.md +278 -278
  241. package/docs/deprecated/insforge-storage-sdk.md +158 -158
  242. package/docs/docs.json +232 -0
  243. package/docs/examples/framework-guides/nextjs.mdx +131 -0
  244. package/docs/examples/framework-guides/nuxt.mdx +165 -0
  245. package/docs/examples/framework-guides/react.mdx +165 -0
  246. package/docs/examples/framework-guides/svelte.mdx +153 -0
  247. package/docs/examples/framework-guides/vue.mdx +159 -0
  248. package/docs/examples/overview.mdx +67 -0
  249. package/docs/favicon.svg +19 -0
  250. package/docs/images/changelog/dec-2025/ai-integration.png +0 -0
  251. package/docs/images/changelog/dec-2025/ai-models.webp +0 -0
  252. package/docs/images/changelog/dec-2025/alipay-payment.webp +0 -0
  253. package/docs/images/changelog/dec-2025/apple-login.jpg +0 -0
  254. package/docs/images/changelog/dec-2025/mcp-installer.png +0 -0
  255. package/docs/images/changelog/dec-2025/realtime-module.jpg +0 -0
  256. package/docs/images/changelog/nov-2025/auth-components.webp +0 -0
  257. package/docs/images/changelog/nov-2025/database-metadata.webp +0 -0
  258. package/docs/images/changelog/nov-2025/quickstart-prompts.webp +0 -0
  259. package/docs/images/changelog/nov-2025/sql-editor.webp +0 -0
  260. package/docs/images/changelog/nov-2025/usage-page.webp +0 -0
  261. package/docs/images/changelog/october-2025/csv-upload.webp +0 -0
  262. package/docs/images/changelog/october-2025/logs-feature.webp +0 -0
  263. package/docs/images/changelog/october-2025/oauth-providers.webp +0 -0
  264. package/docs/images/checks-passed.png +0 -0
  265. package/docs/images/dashboard-connect-expanded.png +0 -0
  266. package/docs/images/dashboard-connect.png +0 -0
  267. package/docs/images/hero-dark.png +0 -0
  268. package/docs/images/hero-light.png +0 -0
  269. package/docs/images/icons/ai.svg +4 -0
  270. package/docs/images/icons/auth.svg +1 -0
  271. package/docs/images/icons/database.svg +1 -0
  272. package/docs/images/icons/function.svg +1 -0
  273. package/docs/images/icons/storage.svg +1 -0
  274. package/docs/images/logos/nextjs.svg +4 -0
  275. package/docs/images/logos/nuxt.svg +4 -0
  276. package/docs/images/logos/react.svg +5 -0
  277. package/docs/images/logos/svelte.svg +4 -0
  278. package/docs/images/logos/vue.svg +5 -0
  279. package/docs/images/mcp-install.png +0 -0
  280. package/docs/images/onboarding-mcp.png +0 -0
  281. package/docs/insforge-instructions-sdk.md +89 -407
  282. package/docs/introduction.mdx +45 -0
  283. package/docs/logo/dark.svg +22 -0
  284. package/docs/logo/light.svg +20 -0
  285. package/docs/partnership.mdx +652 -0
  286. package/docs/quickstart.mdx +83 -0
  287. package/docs/showcase/2048-arena.png +0 -0
  288. package/docs/showcase/framegen-cloud.png +0 -0
  289. package/docs/showcase/line-connect-race.png +0 -0
  290. package/docs/showcase/moment-vibe.png +0 -0
  291. package/docs/showcase/national-flags.png +0 -0
  292. package/docs/showcase/pokemon-vibe.png +0 -0
  293. package/docs/showcase/pure-browse-buy.png +0 -0
  294. package/docs/showcase.mdx +52 -0
  295. package/docs/snippets/sdk-installation.mdx +22 -0
  296. package/docs/snippets/service-icons.mdx +27 -0
  297. package/eslint.config.js +10 -3
  298. package/examples/oauth/frontend-oauth-example.html +250 -250
  299. package/examples/response-examples.md +443 -443
  300. package/frontend/components.json +17 -17
  301. package/frontend/package.json +69 -63
  302. package/frontend/src/App.tsx +13 -82
  303. package/frontend/src/assets/icons/checkbox_checked.svg +6 -6
  304. package/frontend/src/assets/icons/checkbox_undetermined.svg +6 -6
  305. package/frontend/src/assets/icons/checked.svg +3 -3
  306. package/frontend/src/assets/icons/connected.svg +3 -0
  307. package/frontend/src/assets/icons/error.svg +3 -3
  308. package/frontend/src/assets/icons/loader.svg +9 -0
  309. package/frontend/src/assets/icons/pencil.svg +4 -4
  310. package/frontend/src/assets/icons/refresh.svg +4 -4
  311. package/frontend/src/assets/icons/step_active.svg +3 -3
  312. package/frontend/src/assets/icons/step_inactive.svg +11 -11
  313. package/frontend/src/assets/icons/warning.svg +3 -3
  314. package/frontend/src/assets/logos/apple.svg +4 -0
  315. package/frontend/src/assets/logos/claude_code.svg +3 -3
  316. package/frontend/src/assets/logos/cline.svg +6 -6
  317. package/frontend/src/assets/logos/cursor.svg +20 -20
  318. package/frontend/src/assets/logos/discord.svg +8 -8
  319. package/frontend/src/assets/logos/facebook.svg +3 -0
  320. package/frontend/src/assets/logos/gemini.svg +19 -19
  321. package/frontend/src/assets/logos/github.svg +5 -5
  322. package/frontend/src/assets/logos/google.svg +13 -13
  323. package/frontend/src/assets/logos/grok.svg +10 -10
  324. package/frontend/src/assets/logos/insforge_dark.svg +15 -15
  325. package/frontend/src/assets/logos/insforge_light.svg +15 -15
  326. package/frontend/src/assets/logos/instagram.svg +2 -0
  327. package/frontend/src/assets/logos/linkedin.svg +3 -0
  328. package/frontend/src/assets/logos/microsoft.svg +1 -0
  329. package/frontend/src/assets/logos/openai.svg +10 -10
  330. package/frontend/src/assets/logos/roo_code.svg +9 -9
  331. package/frontend/src/assets/logos/spotify.svg +17 -0
  332. package/frontend/src/assets/logos/tiktok.svg +6 -0
  333. package/frontend/src/assets/logos/trae.svg +3 -3
  334. package/frontend/src/assets/logos/windsurf.svg +10 -10
  335. package/frontend/src/assets/logos/x.svg +3 -0
  336. package/frontend/src/components/Checkbox.tsx +27 -29
  337. package/frontend/src/components/CodeBlock.tsx +55 -2
  338. package/frontend/src/components/CodeEditor.tsx +92 -0
  339. package/frontend/src/components/ConfirmDialog.tsx +1 -1
  340. package/frontend/src/components/ConnectCTA.tsx +38 -0
  341. package/frontend/src/components/CopyButton.tsx +52 -15
  342. package/frontend/src/components/ErrorState.tsx +1 -2
  343. package/frontend/src/components/FeatureSidebar.tsx +6 -6
  344. package/frontend/src/components/FeatureSidebarItem.tsx +2 -2
  345. package/frontend/src/components/JsonHighlight.tsx +21 -9
  346. package/frontend/src/components/ProjectInfoModal.tsx +128 -0
  347. package/frontend/src/components/PromptDialog.tsx +1 -4
  348. package/frontend/src/components/SearchInput.tsx +1 -2
  349. package/frontend/src/components/Stepper.tsx +53 -0
  350. package/frontend/src/components/ThemeToggle.tsx +3 -3
  351. package/frontend/src/components/datagrid/DataGrid.tsx +25 -32
  352. package/frontend/src/components/datagrid/cell-editors/DateCellEditor.tsx +1 -2
  353. package/frontend/src/components/datagrid/cell-editors/JsonCellEditor.tsx +2 -4
  354. package/frontend/src/components/datagrid/index.ts +23 -0
  355. package/frontend/src/components/index.ts +23 -30
  356. package/frontend/src/components/layout/AppHeader.tsx +131 -91
  357. package/frontend/src/components/layout/AppSidebar.tsx +80 -170
  358. package/frontend/src/components/layout/Layout.tsx +12 -23
  359. package/frontend/src/components/layout/PrimaryMenu.tsx +187 -0
  360. package/frontend/src/components/layout/SecondaryMenu.tsx +70 -0
  361. package/frontend/src/components/layout/index.ts +5 -0
  362. package/frontend/src/components/radix/Tooltip.tsx +24 -13
  363. package/frontend/src/components/radix/index.ts +22 -0
  364. package/frontend/src/features/ai/components/AIConfigCard.tsx +129 -83
  365. package/frontend/src/features/ai/components/AIEmptyState.tsx +12 -7
  366. package/frontend/src/features/ai/components/ModalityFilterSidebar.tsx +101 -0
  367. package/frontend/src/features/ai/components/ModelSelectionDialog.tsx +135 -0
  368. package/frontend/src/features/ai/components/ModelSelectionGrid.tsx +51 -0
  369. package/frontend/src/features/ai/components/SystemPromptDialog.tsx +118 -0
  370. package/frontend/src/features/ai/components/index.ts +6 -0
  371. package/frontend/src/features/ai/helpers.ts +57 -71
  372. package/frontend/src/features/ai/hooks/useAIConfigs.ts +39 -113
  373. package/frontend/src/features/ai/hooks/useAIUsage.ts +0 -2
  374. package/frontend/src/features/ai/pages/AIPage.tsx +166 -0
  375. package/frontend/src/features/ai/services/ai.service.ts +5 -5
  376. package/frontend/src/features/auth/components/AuthPreview.tsx +96 -0
  377. package/frontend/src/features/auth/components/OAuthConfigDialog.tsx +54 -30
  378. package/frontend/src/features/auth/components/UserFormDialog.tsx +13 -6
  379. package/frontend/src/features/auth/components/UsersDataGrid.tsx +50 -14
  380. package/frontend/src/features/auth/components/index.ts +5 -0
  381. package/frontend/src/features/auth/helpers.tsx +208 -0
  382. package/frontend/src/features/auth/hooks/useAnonToken.ts +30 -0
  383. package/frontend/src/features/auth/hooks/useAuthConfig.ts +48 -0
  384. package/frontend/src/features/auth/hooks/useOAuthConfig.ts +14 -10
  385. package/frontend/src/features/auth/hooks/useUsers.ts +43 -5
  386. package/frontend/src/features/auth/index.ts +3 -2
  387. package/frontend/src/features/auth/pages/AuthMethodsPage.tsx +275 -0
  388. package/frontend/src/features/auth/pages/ConfigurationPage.tsx +395 -0
  389. package/frontend/src/features/auth/pages/UsersPage.tsx +257 -0
  390. package/frontend/src/features/auth/services/anonToken.service.ts +11 -0
  391. package/frontend/src/features/auth/services/config.service.ts +19 -0
  392. package/frontend/src/features/auth/services/{oauth.service.ts → oauth-config.service.ts} +4 -4
  393. package/frontend/src/features/auth/services/{auth.service.ts → user.service.ts} +7 -53
  394. package/frontend/src/features/dashboard/components/ConnectionSuccessBanner.tsx +35 -0
  395. package/frontend/src/features/dashboard/components/PromptCard.tsx +21 -0
  396. package/frontend/src/features/dashboard/components/PromptDialog.tsx +103 -0
  397. package/frontend/src/features/dashboard/components/StatsCard.tsx +50 -0
  398. package/frontend/src/features/dashboard/components/index.ts +4 -0
  399. package/frontend/src/features/dashboard/pages/DashboardPage.tsx +212 -0
  400. package/frontend/src/features/dashboard/prompts/ai-chatbot.ts +13 -0
  401. package/frontend/src/features/dashboard/prompts/crm-system.ts +13 -0
  402. package/frontend/src/features/dashboard/prompts/ecommerce-platform.ts +12 -0
  403. package/frontend/src/features/dashboard/prompts/index.ts +31 -0
  404. package/frontend/src/features/dashboard/prompts/instagram-clone.ts +11 -0
  405. package/frontend/src/features/dashboard/prompts/notion-clone.ts +14 -0
  406. package/frontend/src/features/dashboard/prompts/reddit-clone.ts +12 -0
  407. package/frontend/src/features/database/components/DatabaseDataGrid.tsx +48 -17
  408. package/frontend/src/features/database/components/ForeignKeyCell.tsx +15 -34
  409. package/frontend/src/features/database/components/ForeignKeyPopover.tsx +19 -20
  410. package/frontend/src/features/database/components/LinkRecordModal.tsx +120 -125
  411. package/frontend/src/features/database/components/RecordFormDialog.tsx +22 -33
  412. package/frontend/src/features/database/components/RecordFormField.tsx +45 -47
  413. package/frontend/src/features/database/components/SQLModal.tsx +75 -0
  414. package/frontend/src/features/database/components/TableEmptyState.tsx +6 -5
  415. package/frontend/src/features/database/components/TableForm.tsx +28 -19
  416. package/frontend/src/features/database/components/TableFormColumn.tsx +2 -3
  417. package/frontend/src/features/database/components/TableSidebar.tsx +1 -1
  418. package/frontend/src/features/database/components/TablesEmptyState.tsx +48 -0
  419. package/frontend/src/features/database/components/TemplateCard.tsx +37 -0
  420. package/frontend/src/features/database/components/TemplatePreview.tsx +92 -0
  421. package/frontend/src/features/database/components/index.ts +19 -0
  422. package/frontend/src/features/database/constants.ts +28 -2
  423. package/frontend/src/features/database/contexts/SQLEditorContext.tsx +188 -0
  424. package/frontend/src/features/database/helpers.ts +2 -2
  425. package/frontend/src/features/database/hooks/useCSVImport.ts +29 -0
  426. package/frontend/src/features/database/hooks/useDatabase.ts +66 -0
  427. package/frontend/src/features/database/hooks/useRawSQL.ts +55 -0
  428. package/frontend/src/features/database/hooks/useRecords.ts +139 -0
  429. package/frontend/src/features/database/hooks/useTables.ts +135 -0
  430. package/frontend/src/features/database/index.ts +7 -1
  431. package/frontend/src/features/database/pages/FunctionsPage.tsx +203 -0
  432. package/frontend/src/features/database/pages/IndexesPage.tsx +228 -0
  433. package/frontend/src/features/database/pages/PoliciesPage.tsx +237 -0
  434. package/frontend/src/features/database/pages/SQLEditorPage.tsx +382 -0
  435. package/frontend/src/features/database/{page/DatabasePage.tsx → pages/TablesPage.tsx} +168 -209
  436. package/frontend/src/features/database/pages/TemplatesPage.tsx +39 -0
  437. package/frontend/src/features/database/pages/TriggersPage.tsx +230 -0
  438. package/frontend/src/features/database/services/advance.service.ts +40 -0
  439. package/frontend/src/features/database/services/database.service.ts +33 -194
  440. package/frontend/src/features/database/services/record.service.ts +219 -0
  441. package/frontend/src/features/database/services/table.service.ts +58 -0
  442. package/frontend/src/features/database/templates/ai-chatbot.ts +402 -0
  443. package/frontend/src/features/database/templates/crm-system.ts +528 -0
  444. package/frontend/src/features/database/templates/ecommerce-platform.ts +553 -0
  445. package/frontend/src/features/database/templates/index.ts +34 -0
  446. package/frontend/src/features/database/templates/instagram-clone.ts +222 -0
  447. package/frontend/src/features/database/templates/notion-clone.ts +483 -0
  448. package/frontend/src/features/database/templates/reddit-clone.ts +526 -0
  449. package/frontend/src/features/functions/components/FunctionRow.tsx +2 -1
  450. package/frontend/src/features/functions/components/FunctionsSidebar.tsx +1 -1
  451. package/frontend/src/features/functions/components/SecretRow.tsx +1 -1
  452. package/frontend/src/features/functions/components/index.ts +5 -0
  453. package/frontend/src/features/functions/hooks/useFunctions.ts +4 -4
  454. package/frontend/src/features/{secrets → functions}/hooks/useSecrets.ts +5 -5
  455. package/frontend/src/features/functions/pages/FunctionsPage.tsx +148 -0
  456. package/frontend/src/features/functions/{components/SecretsContent.tsx → pages/SecretsPage.tsx} +19 -21
  457. package/frontend/src/features/functions/services/{functions.service.ts → function.service.ts} +2 -2
  458. package/frontend/src/features/{secrets/services/secrets.service.ts → functions/services/secret.service.ts} +2 -2
  459. package/frontend/src/features/login/hooks/usePartnerOrigin.ts +27 -0
  460. package/frontend/src/features/login/pages/CloudLoginPage.tsx +118 -0
  461. package/frontend/src/features/login/{page → pages}/LoginPage.tsx +16 -23
  462. package/frontend/src/features/login/services/partnership.service.ts +65 -0
  463. package/frontend/src/features/logs/components/LogsDataGrid.tsx +89 -0
  464. package/frontend/src/features/logs/components/SeverityBadge.tsx +18 -0
  465. package/frontend/src/features/logs/components/index.ts +2 -0
  466. package/frontend/src/features/logs/helpers.ts +24 -0
  467. package/frontend/src/features/logs/hooks/useAuditLogs.ts +4 -4
  468. package/frontend/src/features/logs/hooks/useLogSources.ts +137 -0
  469. package/frontend/src/features/logs/hooks/useLogs.ts +163 -0
  470. package/frontend/src/features/logs/hooks/useMcpUsage.ts +128 -0
  471. package/frontend/src/features/logs/index.ts +8 -2
  472. package/frontend/src/features/logs/{page → pages}/AuditsPage.tsx +91 -38
  473. package/frontend/src/features/logs/pages/LogsPage.tsx +152 -0
  474. package/frontend/src/features/logs/pages/MCPLogsPage.tsx +84 -0
  475. package/frontend/src/features/logs/services/audit.service.ts +63 -0
  476. package/frontend/src/features/logs/services/log.service.ts +15 -110
  477. package/frontend/src/features/logs/services/usage.service.ts +31 -0
  478. package/frontend/src/features/onboard/components/McpConnectionStatus.tsx +68 -0
  479. package/frontend/src/features/onboard/components/OnboardingModal.tsx +267 -0
  480. package/frontend/src/features/onboard/components/VideoDemoModal.tsx +38 -0
  481. package/frontend/src/features/onboard/components/index.ts +4 -0
  482. package/frontend/src/features/onboard/components/mcp/CursorDeeplinkGenerator.tsx +2 -2
  483. package/frontend/src/features/onboard/components/mcp/{mcp-helper.tsx → helpers.tsx} +8 -8
  484. package/frontend/src/features/onboard/components/mcp/index.ts +2 -3
  485. package/frontend/src/features/onboard/index.ts +13 -3
  486. package/frontend/src/features/realtime/components/ChannelRow.tsx +83 -0
  487. package/frontend/src/features/realtime/components/EditChannelModal.tsx +246 -0
  488. package/frontend/src/features/realtime/components/MessageRow.tsx +85 -0
  489. package/frontend/src/features/realtime/components/RealtimeEmptyState.tsx +30 -0
  490. package/frontend/src/features/realtime/hooks/useRealtime.ts +218 -0
  491. package/frontend/src/features/realtime/index.ts +11 -0
  492. package/frontend/src/features/realtime/pages/RealtimeChannelsPage.tsx +172 -0
  493. package/frontend/src/features/realtime/pages/RealtimeMessagesPage.tsx +211 -0
  494. package/frontend/src/features/realtime/pages/RealtimePermissionsPage.tsx +191 -0
  495. package/frontend/src/features/realtime/services/realtime.service.ts +107 -0
  496. package/frontend/src/features/storage/components/BucketEmptyState.tsx +9 -6
  497. package/frontend/src/features/storage/components/BucketFormDialog.tsx +25 -41
  498. package/frontend/src/features/storage/components/FilePreviewDialog.tsx +20 -8
  499. package/frontend/src/features/storage/components/StorageDataGrid.tsx +4 -3
  500. package/frontend/src/features/storage/components/StorageManager.tsx +23 -34
  501. package/frontend/src/features/storage/components/index.ts +12 -0
  502. package/frontend/src/features/storage/hooks/useStorage.ts +208 -0
  503. package/frontend/src/features/storage/{page → pages}/StoragePage.tsx +41 -143
  504. package/frontend/src/features/storage/services/storage.service.ts +22 -1
  505. package/frontend/src/features/visualizer/components/AuthNode.tsx +72 -56
  506. package/frontend/src/features/visualizer/components/BucketNode.tsx +4 -4
  507. package/frontend/src/features/visualizer/components/SchemaVisualizer.tsx +108 -80
  508. package/frontend/src/features/visualizer/components/TableNode.tsx +34 -41
  509. package/frontend/src/features/visualizer/components/VisualizerSkeleton.tsx +12 -4
  510. package/frontend/src/features/visualizer/pages/VisualizerPage.tsx +97 -0
  511. package/frontend/src/index.css +1 -0
  512. package/frontend/src/lib/analytics/posthog.tsx +27 -0
  513. package/frontend/src/lib/contexts/AuthContext.tsx +38 -31
  514. package/frontend/src/lib/contexts/SocketContext.tsx +123 -80
  515. package/frontend/src/{features/metadata → lib}/hooks/useMetadata.ts +1 -1
  516. package/frontend/src/lib/hooks/useToast.tsx +6 -2
  517. package/frontend/src/lib/routing/AppRoutes.tsx +99 -0
  518. package/frontend/src/lib/routing/RequireAuth.tsx +27 -0
  519. package/frontend/src/lib/utils/cloudMessaging.ts +20 -0
  520. package/frontend/src/lib/utils/menuItems.ts +207 -0
  521. package/frontend/src/lib/utils/{validation-schemas.ts → schemaValidations.ts} +10 -5
  522. package/frontend/src/lib/utils/utils.ts +32 -1
  523. package/frontend/src/vite-env.d.ts +1 -0
  524. package/frontend/tsconfig.json +25 -25
  525. package/frontend/tsconfig.node.json +9 -9
  526. package/frontend/vite.config.ts +5 -3
  527. package/functions/deno.json +24 -24
  528. package/functions/server.ts +315 -290
  529. package/functions/worker-template.js +15 -4
  530. package/i18n/README.ar.md +130 -0
  531. package/i18n/README.de.md +130 -0
  532. package/i18n/README.es.md +154 -0
  533. package/i18n/README.fr.md +134 -0
  534. package/i18n/README.hi.md +129 -0
  535. package/i18n/README.ja.md +174 -0
  536. package/i18n/README.ko.md +137 -0
  537. package/i18n/README.pt-BR.md +131 -0
  538. package/i18n/README.ru.md +129 -0
  539. package/i18n/README.zh-CN.md +133 -0
  540. package/openapi/ai.yaml +715 -688
  541. package/openapi/auth.yaml +1244 -563
  542. package/openapi/email.yaml +158 -0
  543. package/openapi/functions.yaml +475 -475
  544. package/openapi/health.yaml +29 -29
  545. package/openapi/logs.yaml +223 -223
  546. package/openapi/metadata.yaml +177 -177
  547. package/openapi/realtime.yaml +699 -0
  548. package/openapi/records.yaml +381 -381
  549. package/openapi/secrets.yaml +370 -370
  550. package/openapi/storage.yaml +875 -875
  551. package/openapi/tables.yaml +463 -463
  552. package/package.json +97 -88
  553. package/shared-schemas/package.json +31 -31
  554. package/shared-schemas/src/ai-api.schema.ts +34 -58
  555. package/shared-schemas/src/ai.schema.ts +63 -54
  556. package/shared-schemas/src/auth-api.schema.ts +352 -193
  557. package/shared-schemas/src/auth.schema.ts +43 -7
  558. package/shared-schemas/src/cloud-events.schema.ts +57 -0
  559. package/shared-schemas/src/database-api.schema.ts +35 -4
  560. package/shared-schemas/src/database.schema.ts +40 -1
  561. package/shared-schemas/src/docs.schema.ts +26 -0
  562. package/shared-schemas/src/email-api.schema.ts +30 -0
  563. package/shared-schemas/src/index.ts +5 -0
  564. package/shared-schemas/src/logs-api.schema.ts +7 -1
  565. package/shared-schemas/src/logs.schema.ts +26 -0
  566. package/shared-schemas/src/metadata.schema.ts +18 -4
  567. package/shared-schemas/src/realtime-api.schema.ts +111 -0
  568. package/shared-schemas/src/realtime.schema.ts +143 -0
  569. package/shared-schemas/tsconfig.json +21 -21
  570. package/tsconfig.json +7 -7
  571. package/zeabur/README.md +13 -0
  572. package/zeabur/template.yml +1032 -0
  573. package/.github/workflows/deploy-aws.yml +0 -130
  574. package/backend/src/api/routes/agent.ts +0 -29
  575. package/backend/src/api/routes/auth.oauth.ts +0 -482
  576. package/backend/src/api/routes/auth.ts +0 -386
  577. package/backend/src/api/routes/docs.ts +0 -66
  578. package/backend/src/api/routes/functions.ts +0 -183
  579. package/backend/src/api/routes/openapi.ts +0 -82
  580. package/backend/src/api/routes/usage.ts +0 -96
  581. package/backend/src/core/ai/client.ts +0 -242
  582. package/backend/src/core/ai/model.ts +0 -117
  583. package/backend/src/core/auth/auth.ts +0 -780
  584. package/backend/src/core/database/manager.ts +0 -178
  585. package/backend/src/core/database/table.ts +0 -772
  586. package/backend/src/core/documentation/agent.ts +0 -689
  587. package/backend/src/core/documentation/openapi.ts +0 -856
  588. package/backend/src/core/logs/analytics.ts +0 -76
  589. package/backend/src/core/logs/providers/localdb.provider.ts +0 -246
  590. package/backend/src/core/socket/socket.ts +0 -388
  591. package/backend/src/core/storage/storage.ts +0 -923
  592. package/backend/src/utils/cloud-token.ts +0 -39
  593. package/backend/src/utils/helpers.ts +0 -49
  594. package/backend/src/utils/uuid.ts +0 -9
  595. package/backend/tests/manual/test-better-auth.sh +0 -303
  596. package/docker-init/db/logs.sql +0 -9
  597. package/frontend/README.md +0 -112
  598. package/frontend/src/components/datagrid/index.tsx +0 -20
  599. package/frontend/src/components/layout/CloudLayout.tsx +0 -95
  600. package/frontend/src/features/ai/components/AIConfigDialog.tsx +0 -76
  601. package/frontend/src/features/ai/components/AIConfigForm.tsx +0 -222
  602. package/frontend/src/features/ai/components/fields/ModalityField.tsx +0 -87
  603. package/frontend/src/features/ai/components/fields/ModelSelectionField.tsx +0 -134
  604. package/frontend/src/features/ai/components/fields/SystemPromptField.tsx +0 -33
  605. package/frontend/src/features/ai/page/AIPage.tsx +0 -178
  606. package/frontend/src/features/auth/components/AddOAuthDialog.tsx +0 -106
  607. package/frontend/src/features/auth/components/AuthMethodTab.tsx +0 -238
  608. package/frontend/src/features/auth/components/UsersTab.tsx +0 -114
  609. package/frontend/src/features/auth/page/AuthenticationPage.tsx +0 -169
  610. package/frontend/src/features/dashboard/page/DashboardPage.tsx +0 -194
  611. package/frontend/src/features/database/hooks/UseLinkModal.tsx +0 -78
  612. package/frontend/src/features/functions/components/FunctionViewer.tsx +0 -46
  613. package/frontend/src/features/functions/components/FunctionsContent.tsx +0 -88
  614. package/frontend/src/features/functions/page/FunctionsPage.tsx +0 -28
  615. package/frontend/src/features/login/components/AuthErrorBoundary.tsx +0 -87
  616. package/frontend/src/features/login/components/PrivateRoute.tsx +0 -24
  617. package/frontend/src/features/login/page/CloudLoginPage.tsx +0 -93
  618. package/frontend/src/features/logs/components/AnalyticsLogsTable.tsx +0 -313
  619. package/frontend/src/features/logs/components/LogsTable.tsx +0 -199
  620. package/frontend/src/features/logs/page/AnalyticsLogsPage.tsx +0 -530
  621. package/frontend/src/features/metadata/index.ts +0 -0
  622. package/frontend/src/features/metadata/page/MetadataPage.tsx +0 -136
  623. package/frontend/src/features/onboard/components/CompletionCard.tsx +0 -41
  624. package/frontend/src/features/onboard/components/OnboardButton.tsx +0 -84
  625. package/frontend/src/features/onboard/components/StepContent.tsx +0 -91
  626. package/frontend/src/features/onboard/components/TestConnectionStep.tsx +0 -53
  627. package/frontend/src/features/onboard/components/mcp/McpInstallation.tsx +0 -144
  628. package/frontend/src/features/onboard/page/OnBoardPage.tsx +0 -104
  629. package/frontend/src/features/onboard/types.ts +0 -8
  630. package/frontend/src/features/visualizer/page/VisualizerPage.tsx +0 -127
  631. package/frontend/src/lib/contexts/OnboardStepContext.tsx +0 -68
  632. package/frontend/src/lib/hooks/useOnboardingCompletion.ts +0 -29
  633. /package/backend/src/api/{middleware → middlewares}/error.ts +0 -0
  634. /package/backend/src/api/{middleware → middlewares}/upload.ts +0 -0
  635. /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
  }