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
@@ -1,26 +1,25 @@
1
1
  import { useState, useEffect, useMemo } from 'react';
2
2
  import { useForm } from 'react-hook-form';
3
3
  import { zodResolver } from '@hookform/resolvers/zod';
4
- import { useMutation, useQueryClient } from '@tanstack/react-query';
4
+ import { useQueryClient } from '@tanstack/react-query';
5
5
  import { AlertCircle } from 'lucide-react';
6
6
  import {
7
+ Alert,
8
+ AlertDescription,
9
+ Button,
7
10
  Dialog,
8
11
  DialogContent,
9
12
  DialogHeader,
10
13
  DialogTitle,
11
14
  DialogFooter,
12
- } from '@/components/radix/Dialog';
13
- import { Button } from '@/components/radix/Button';
14
- import { Alert, AlertDescription } from '@/components/radix/Alert';
15
- import { ScrollArea } from '@/components/radix/ScrollArea';
16
- import { databaseService } from '@/features/database/services/database.service';
15
+ ScrollArea,
16
+ } from '@/components';
17
+ import { useRecords } from '@/features/database/hooks/useRecords';
17
18
  import { buildDynamicSchema, getInitialValues } from '@/features/database';
18
19
  import { RecordFormField } from '@/features/database/components/RecordFormField';
19
20
  import { cn } from '@/lib/utils/utils';
20
- import { useToast } from '@/lib/hooks/useToast';
21
21
  import { ColumnSchema } from '@insforge/shared-schemas';
22
22
  import { SYSTEM_FIELDS } from '../helpers';
23
- import { ConvertedValue } from '@/components/datagrid/datagridTypes';
24
23
 
25
24
  interface RecordFormDialogProps {
26
25
  open: boolean;
@@ -39,7 +38,7 @@ export function RecordFormDialog({
39
38
  }: RecordFormDialogProps) {
40
39
  const [error, setError] = useState<string | null>(null);
41
40
  const queryClient = useQueryClient();
42
- const { showToast } = useToast();
41
+ const { createRecord, isCreating } = useRecords(tableName);
43
42
 
44
43
  const displayFields = useMemo(() => {
45
44
  const filteredFields = schema.filter((field) => !SYSTEM_FIELDS.includes(field.columnName));
@@ -72,31 +71,21 @@ export function RecordFormDialog({
72
71
  }
73
72
  }, [open]);
74
73
 
75
- const createRecordMutation = useMutation({
76
- mutationFn: (data: { [key: string]: ConvertedValue }) => {
77
- return databaseService.createRecord(tableName, data);
78
- },
79
- onSuccess: () => {
80
- void queryClient.invalidateQueries({ queryKey: ['records', tableName] });
81
- void queryClient.invalidateQueries({ queryKey: ['table', tableName] });
82
- onOpenChange(false);
83
- form.reset();
84
- setError(null);
85
- if (onSuccess) {
86
- onSuccess();
87
- }
88
- showToast('Record created successfully', 'success');
89
- },
90
- onError: (err: Error) => {
91
- setError(err.message || 'Failed to create record');
92
- },
93
- });
94
-
95
74
  const handleSubmit = form.handleSubmit(
96
75
  async (data) => {
97
76
  try {
98
- await createRecordMutation.mutateAsync(data);
77
+ await createRecord(data);
78
+ void queryClient.invalidateQueries({ queryKey: ['records', tableName] });
79
+ void queryClient.invalidateQueries({ queryKey: ['table', tableName] });
80
+ onOpenChange(false);
81
+ form.reset();
82
+ setError(null);
83
+ if (onSuccess) {
84
+ onSuccess();
85
+ }
99
86
  } catch (err) {
87
+ const errorMessage = err instanceof Error ? err.message : 'Failed to create record';
88
+ setError(errorMessage);
100
89
  console.error('Form submission error:', err);
101
90
  }
102
91
  },
@@ -148,13 +137,13 @@ export function RecordFormDialog({
148
137
  </Button>
149
138
  <Button
150
139
  type="submit"
151
- disabled={createRecordMutation.isPending}
140
+ disabled={isCreating}
152
141
  className={cn(
153
142
  'h-10 px-4 bg-zinc-950 text-white hover:bg-zinc-800 dark:bg-emerald-300 dark:text-zinc-950 dark:hover:bg-emerald-400',
154
- createRecordMutation.isPending && 'opacity-40'
143
+ isCreating && 'opacity-40'
155
144
  )}
156
145
  >
157
- {createRecordMutation.isPending ? 'Saving...' : 'Add Record'}
146
+ {isCreating ? 'Saving...' : 'Add Record'}
158
147
  </Button>
159
148
  </DialogFooter>
160
149
  </form>
@@ -1,21 +1,21 @@
1
1
  import React, { useState } from 'react';
2
2
  import { Control, Controller, FieldError, UseFormReturn } from 'react-hook-form';
3
- import { Input } from '@/components/radix/Input';
4
- import { Label } from '@/components/radix/Label';
5
- import { Button } from '@/components/radix/Button';
6
3
  import { Calendar, Clock, Link2, X } from 'lucide-react';
7
4
  import {
5
+ Button,
6
+ Label,
7
+ Input,
8
8
  BooleanCellEditor,
9
9
  DateCellEditor,
10
10
  JsonCellEditor,
11
11
  type DatabaseRecord,
12
12
  type ConvertedValue,
13
13
  type UserInputValue,
14
- } from '@/components/datagrid';
14
+ TypeBadge,
15
+ } from '@/components';
15
16
  import { ColumnSchema, ColumnType } from '@insforge/shared-schemas';
16
- import { useLinkModal } from '@/features/database/hooks/UseLinkModal';
17
17
  import { convertValueForColumn, cn, formatValueForDisplay } from '@/lib/utils/utils';
18
- import { TypeBadge } from '@/components/TypeBadge';
18
+ import { LinkRecordModal } from '@/features/database/components/LinkRecordModal';
19
19
  import { isValid, parseISO } from 'date-fns';
20
20
 
21
21
  // Helper function to get appropriate placeholder text
@@ -184,7 +184,7 @@ function FormNumberEditor({ value, type, onChange, tableName, field }: FormNumbe
184
184
  }
185
185
  }}
186
186
  placeholder={getPlaceholderText(field)}
187
- className={`dark:text-white dark:placeholder:text-neutral-400 dark:bg-neutral-900 dark:border-neutral-700 ${field.foreignKey ? 'pr-16' : ''}`}
187
+ className={`dark:text-white dark:placeholder:text-neutral-400 dark:bg-neutral-900 dark:border-neutral-700 ${field.foreignKey ? 'pr-18' : ''}`}
188
188
  />
189
189
  );
190
190
  }
@@ -278,13 +278,14 @@ interface FieldWithLinkProps {
278
278
  }
279
279
 
280
280
  function FieldWithLink({ field, control, children }: FieldWithLinkProps) {
281
- const { openModal } = useLinkModal();
282
-
283
281
  if (!field.foreignKey) {
284
282
  // Regular field without foreign key
285
283
  return <>{children}</>;
286
284
  }
287
285
 
286
+ // Store foreignKey in a const to help TypeScript narrow the type
287
+ const foreignKey = field.foreignKey;
288
+
288
289
  // Field with foreign key linking capability - integrated design
289
290
  return (
290
291
  <>
@@ -309,56 +310,53 @@ function FieldWithLink({ field, control, children }: FieldWithLinkProps) {
309
310
  <div className="space-y-1">
310
311
  <div className="relative">
311
312
  {modifiedChildren}
312
- <div className="absolute right-0 top-1/2 -translate-y-1/2 flex items-center">
313
- {hasLinkedValue && (
313
+ <div className="absolute right-0 top-1/2 -translate-y-1/2 flex items-center gap-1">
314
+ {(hasLinkedValue || hasLinkedValue === 0) && (
314
315
  <Button
315
316
  type="button"
316
317
  variant="ghost"
317
318
  size="icon"
318
319
  onClick={() => formField.onChange('')}
319
- className="h-7 w-7 p-1 flex-shrink-0 text-zinc-500 hover:text-red-600 hover:bg-red-50 dark:text-neutral-400 dark:hover:text-red-400 dark:hover:bg-red-950/20"
320
+ className="h-7 w-7 p-1 flex-shrink-0 text-zinc-500 hover:text-zinc-700 hover:bg-zinc-100 dark:text-neutral-400 dark:hover:text-neutral-200 dark:hover:bg-neutral-700"
320
321
  title="Clear linked record"
321
322
  >
322
323
  <X className="h-4 w-4" />
323
324
  </Button>
324
325
  )}
325
- <Button
326
- type="button"
327
- variant="ghost"
328
- size="icon"
329
- onClick={() => {
330
- if (field.foreignKey) {
331
- openModal({
332
- referenceTable: field.foreignKey.referenceTable,
333
- referenceColumn: field.foreignKey.referenceColumn,
334
- currentValue: formField.value ? String(formField.value) : null,
335
- onSelectRecord: (record: DatabaseRecord) => {
336
- if (field.foreignKey) {
337
- const referenceValue = record[field.foreignKey.referenceColumn];
338
- const result = convertValueForColumn(
339
- field.type,
340
- String(referenceValue || '')
341
- );
342
- if (result.success) {
343
- formField.onChange(result.value);
344
- } else {
345
- // Fallback to string if conversion fails
346
- formField.onChange(String(referenceValue || ''));
347
- }
348
- }
349
- },
350
- });
326
+ <LinkRecordModal
327
+ referenceTable={foreignKey.referenceTable}
328
+ referenceColumn={foreignKey.referenceColumn}
329
+ onSelectRecord={(record: DatabaseRecord) => {
330
+ const referenceValue = record[foreignKey.referenceColumn];
331
+ const result = convertValueForColumn(
332
+ field.type,
333
+ String(referenceValue || '')
334
+ );
335
+ if (result.success) {
336
+ formField.onChange(result.value);
337
+ } else {
338
+ // Fallback to string if conversion fails
339
+ formField.onChange(String(referenceValue || ''));
351
340
  }
352
341
  }}
353
- className="rounded-l-none h-9 w-9 p-2 flex-shrink-0 text-zinc-500 hover:text-zinc-700 hover:bg-zinc-100 dark:text-neutral-400 dark:hover:text-neutral-200 dark:hover:bg-neutral-700 border-l border-zinc-200 dark:border-neutral-700"
354
- title={
355
- hasLinkedValue
356
- ? `Change linked ${field.foreignKey?.referenceTable} record`
357
- : `Link to ${field.foreignKey?.referenceTable} record`
358
- }
359
342
  >
360
- <Link2 className="h-5 w-5" />
361
- </Button>
343
+ {(openModal) => (
344
+ <Button
345
+ type="button"
346
+ variant="ghost"
347
+ size="icon"
348
+ onClick={openModal}
349
+ className="rounded-l-none h-9 w-9 p-2 flex-shrink-0 text-zinc-500 hover:text-zinc-700 hover:bg-zinc-100 dark:text-neutral-400 dark:hover:text-neutral-200 dark:hover:bg-neutral-700 border-l border-zinc-200 dark:border-neutral-700"
350
+ title={
351
+ hasLinkedValue
352
+ ? `Change linked ${foreignKey.referenceTable} record`
353
+ : `Link to ${foreignKey.referenceTable} record`
354
+ }
355
+ >
356
+ <Link2 className="h-5 w-5" />
357
+ </Button>
358
+ )}
359
+ </LinkRecordModal>
362
360
  </div>
363
361
  </div>
364
362
 
@@ -366,7 +364,7 @@ function FieldWithLink({ field, control, children }: FieldWithLinkProps) {
366
364
  <div className="text-xs text-medium text-black dark:text-neutral-400 flex items-center gap-1.5">
367
365
  <span>Has a Foreign Key relation to</span>
368
366
  <TypeBadge
369
- type={`${field.foreignKey?.referenceTable}.${field.foreignKey?.referenceColumn}`}
367
+ type={`${foreignKey.referenceTable}.${foreignKey.referenceColumn}`}
370
368
  className="dark:bg-neutral-700"
371
369
  />
372
370
  </div>
@@ -0,0 +1,75 @@
1
+ import { ExternalLink } from 'lucide-react';
2
+ import CodeMirror from '@uiw/react-codemirror';
3
+ import { sql } from '@codemirror/lang-sql';
4
+ import { EditorView } from '@codemirror/view';
5
+ import { vscodeDark, vscodeLight } from '@uiw/codemirror-theme-vscode';
6
+ import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components';
7
+ import { useTheme } from '@/lib/contexts/ThemeContext';
8
+
9
+ const customTheme = EditorView.theme({
10
+ '&': { backgroundColor: 'transparent', maxHeight: '400px' },
11
+ '.cm-scroller': { overflow: 'auto' },
12
+ '.cm-gutters': { display: 'none' },
13
+ '.cm-content': { padding: '16px' },
14
+ '.cm-line': { padding: '0' },
15
+ '&.cm-focused': { outline: 'none' },
16
+ '.cm-selectionBackground': { backgroundColor: 'transparent !important' },
17
+ '&.cm-focused .cm-selectionBackground': { backgroundColor: 'transparent !important' },
18
+ '.cm-cursor': { display: 'none' },
19
+ });
20
+
21
+ interface SQLModalProps {
22
+ open: boolean;
23
+ onOpenChange: (open: boolean) => void;
24
+ title: string;
25
+ value: string;
26
+ }
27
+
28
+ export function SQLModal({ open, onOpenChange, title, value }: SQLModalProps) {
29
+ const { resolvedTheme } = useTheme();
30
+
31
+ return (
32
+ <Dialog open={open} onOpenChange={onOpenChange}>
33
+ <DialogContent className="max-w-2xl">
34
+ <DialogHeader>
35
+ <DialogTitle className="text-zinc-950 dark:text-white">{title}</DialogTitle>
36
+ </DialogHeader>
37
+ <div className="mt-2 rounded-lg overflow-hidden bg-neutral-100 dark:bg-neutral-900">
38
+ <CodeMirror
39
+ value={value}
40
+ theme={[resolvedTheme === 'dark' ? vscodeDark : vscodeLight, customTheme]}
41
+ extensions={[sql(), EditorView.lineWrapping, EditorView.editable.of(false)]}
42
+ editable={false}
43
+ basicSetup={false}
44
+ />
45
+ </div>
46
+ </DialogContent>
47
+ </Dialog>
48
+ );
49
+ }
50
+
51
+ interface SQLCellButtonProps {
52
+ value: string | null;
53
+ onClick: () => void;
54
+ }
55
+
56
+ export function SQLCellButton({ value, onClick }: SQLCellButtonProps) {
57
+ if (!value) {
58
+ return <span className="text-sm">-</span>;
59
+ }
60
+
61
+ return (
62
+ <div className="flex items-center justify-between gap-1 min-w-0">
63
+ <span className="text-sm truncate">{value}</span>
64
+ <button
65
+ onClick={(e) => {
66
+ e.stopPropagation();
67
+ onClick();
68
+ }}
69
+ className="shrink-0 p-1 hover:bg-neutral-200 dark:hover:bg-neutral-700 rounded transition-colors"
70
+ >
71
+ <ExternalLink className="size-4 text-zinc-400 dark:text-neutral-400" />
72
+ </button>
73
+ </div>
74
+ );
75
+ }
@@ -1,4 +1,5 @@
1
1
  import { Database } from 'lucide-react';
2
+ import { ConnectCTA } from '@/components/ConnectCTA';
2
3
 
3
4
  interface TableEmptyStateProps {
4
5
  searchTerm: string;
@@ -6,14 +7,14 @@ interface TableEmptyStateProps {
6
7
 
7
8
  export function TableEmptyState({ searchTerm }: TableEmptyStateProps) {
8
9
  return (
9
- <div className="text-center py-8">
10
- <Database className="mx-auto h-8 w-8 text-muted-foreground mb-2.5" />
11
- <p className="text-sm text-muted-foreground">
10
+ <div className="flex flex-col items-center justify-center py-4 text-center">
11
+ <Database className="h-10 w-10 text-gray-400 dark:text-neutral-600 mb-3" />
12
+ <p className="text-sm text-gray-600 dark:text-neutral-400 font-medium">
12
13
  {searchTerm ? 'No tables found' : 'No tables yet'}
13
14
  </p>
14
15
  {!searchTerm && (
15
- <p className="text-xs text-muted-foreground mt-2.5">
16
- Create your first table to get started
16
+ <p className="text-xs text-gray-500 dark:text-neutral-400 font-medium mt-1 mx-10">
17
+ <ConnectCTA fallback="Create your first table to get started" />
17
18
  </p>
18
19
  )}
19
20
  </div>
@@ -3,10 +3,8 @@ import { useForm, useFieldArray } from 'react-hook-form';
3
3
  import { zodResolver } from '@hookform/resolvers/zod';
4
4
  import { useMutation, useQueryClient } from '@tanstack/react-query';
5
5
  import { AlertCircle, Plus, X, Link, MoveRight } from 'lucide-react';
6
- import { Button } from '@/components/radix/Button';
7
- import { Input } from '@/components/radix/Input';
8
- import { Alert, AlertDescription } from '@/components/radix/Alert';
9
- import { databaseService } from '@/features/database/services/database.service';
6
+ import { Alert, AlertDescription, Button, Input } from '@/components';
7
+ import { tableService } from '@/features/database/services/table.service';
10
8
  import {
11
9
  TableFormColumnSchema,
12
10
  TableFormForeignKeySchema,
@@ -50,6 +48,7 @@ export function TableForm({
50
48
  const [showForeignKeyDialog, setShowForeignKeyDialog] = useState(false);
51
49
  const [editingForeignKey, setEditingForeignKey] = useState<string>();
52
50
  const [foreignKeys, setForeignKeys] = useState<TableFormForeignKeySchema[]>([]);
51
+ const [foreignKeysDirty, setForeignKeysDirty] = useState(false);
53
52
  const queryClient = useQueryClient();
54
53
  const { showToast } = useToast();
55
54
 
@@ -220,7 +219,7 @@ export function TableForm({
220
219
  };
221
220
  });
222
221
 
223
- return databaseService.createTable(data.tableName, columns);
222
+ return tableService.createTable(data.tableName, columns);
224
223
  },
225
224
  onSuccess: (data) => {
226
225
  void queryClient.invalidateQueries({ queryKey: ['database-metadata'] });
@@ -232,12 +231,13 @@ export function TableForm({
232
231
  form.reset();
233
232
  setError(null);
234
233
  setForeignKeys([]);
234
+ setForeignKeysDirty(false);
235
235
  onSuccess?.(data.tableName);
236
236
  },
237
237
  onError: (err) => {
238
238
  const errorMessage = err.message || 'Failed to create table';
239
239
  setError(errorMessage);
240
- showToast('Failed to create table', 'error');
240
+ showToast(errorMessage, 'error');
241
241
  },
242
242
  });
243
243
 
@@ -350,7 +350,7 @@ export function TableForm({
350
350
  operations.renameTable = { newTableName: data.tableName };
351
351
  }
352
352
 
353
- return databaseService.updateTableSchema(editTable.tableName, operations);
353
+ return tableService.updateTableSchema(editTable.tableName, operations);
354
354
  },
355
355
  onSuccess: (_, data) => {
356
356
  void queryClient.invalidateQueries({ queryKey: ['database-metadata'] });
@@ -360,9 +360,6 @@ export function TableForm({
360
360
  // Invalidate all table data queries for this table (with all parameter combinations)
361
361
  void queryClient.invalidateQueries({ queryKey: ['table', editTable?.tableName] });
362
362
 
363
- // Invalidate the separate table schema query used by AddRecordSheet
364
- void queryClient.invalidateQueries({ queryKey: ['table-schema', editTable?.tableName] });
365
-
366
363
  showToast(`Table "${data.tableName}" updated successfully!`, 'success');
367
364
 
368
365
  form.reset();
@@ -373,15 +370,24 @@ export function TableForm({
373
370
  onError: (err) => {
374
371
  // Invalidate queries to ensure we have fresh data after failed request
375
372
  void queryClient.invalidateQueries({ queryKey: ['table', editTable?.tableName] });
376
- void queryClient.invalidateQueries({ queryKey: ['table-schema', editTable?.tableName] });
377
373
 
378
374
  const errorMessage = err.message || 'Failed to update table';
379
375
  setError(errorMessage);
380
- showToast('Failed to update table', 'error');
376
+ showToast(errorMessage, 'error');
381
377
  },
382
378
  });
383
379
 
384
380
  const handleSubmit = form.handleSubmit((data) => {
381
+ const userColumns = data.columns.filter((col) => !col.isSystemColumn);
382
+ if (!userColumns.length) {
383
+ const msg =
384
+ mode === 'create'
385
+ ? 'Please add at least one user-defined column to create a table.'
386
+ : 'Please ensure the table has at least one user-defined column.';
387
+ setError(msg);
388
+ showToast(msg, 'error');
389
+ return;
390
+ }
385
391
  if (mode === 'edit') {
386
392
  updateTableMutation.mutate(data);
387
393
  } else {
@@ -402,6 +408,7 @@ export function TableForm({
402
408
  )
403
409
  );
404
410
  setEditingForeignKey(undefined);
411
+ setForeignKeysDirty(true);
405
412
  } else {
406
413
  // Add new foreign key
407
414
  setForeignKeys([
@@ -411,10 +418,12 @@ export function TableForm({
411
418
  },
412
419
  ]);
413
420
  }
421
+ setForeignKeysDirty(true);
414
422
  };
415
423
 
416
424
  const handleRemoveForeignKey = (columnName?: string) => {
417
425
  setForeignKeys(foreignKeys.filter((fk) => fk.columnName !== columnName));
426
+ setForeignKeysDirty(true);
418
427
  };
419
428
 
420
429
  if (!open) {
@@ -470,7 +479,7 @@ export function TableForm({
470
479
  {/* Columns Table */}
471
480
  <div className="px-3 overflow-x-auto">
472
481
  {/* Table Headers */}
473
- <div className="flex items-center gap-6 px-4 py-2 bg-slate-50 rounded-t text-sm font-medium text-zinc-950 dark:bg-neutral-700 dark:text-white">
482
+ <div className="flex items-center gap-6 px-4 py-2 w-min xl:w-full bg-slate-50 rounded-t text-sm font-medium text-zinc-950 dark:bg-neutral-700 dark:text-white">
474
483
  <div className="flex-1 min-w-[175px]">Name</div>
475
484
  <div className="flex-1 min-w-[175px]">Type</div>
476
485
  <div className="flex-1 min-w-[175px]">Default Value</div>
@@ -511,7 +520,7 @@ export function TableForm({
511
520
  </div>
512
521
 
513
522
  {/* Foreign Keys Section */}
514
- <div className="bg-white pb-3 rounded-xl border border-zinc-200 dark:bg-neutral-800 dark:border-transparent">
523
+ <div className="bg-white pb-3 rounded-xl border border-zinc-200 overflow-hidden dark:bg-neutral-800 dark:border-transparent">
515
524
  <div className="p-6">
516
525
  <h2 className="text-base font-semibold text-black dark:text-white">Foreign Keys</h2>
517
526
  <p className="text-sm text-zinc-500 dark:text-neutral-400">
@@ -521,11 +530,11 @@ export function TableForm({
521
530
 
522
531
  {/* Existing foreign keys */}
523
532
  {foreignKeys.length > 0 && (
524
- <div className="px-6 pb-6 space-y-3">
533
+ <div className="px-6 pb-6 space-y-3 overflow-x-auto">
525
534
  {foreignKeys.map((fk) => (
526
535
  <div
527
536
  key={fk.columnName}
528
- className="group flex items-center gap-6 2xl:gap-8 pl-4 pr-2 py-2 rounded-lg border border-zinc-200 bg-white hover:bg-zinc-100 transition-colors duration-150 dark:bg-neutral-700 dark:border-transparent dark:hover:bg-neutral-600"
537
+ className="group flex items-center gap-6 2xl:gap-8 pl-4 pr-2 py-2 w-min xl:w-full rounded-lg border border-zinc-200 bg-white hover:bg-zinc-100 transition-colors duration-150 dark:bg-neutral-700 dark:border-transparent dark:hover:bg-neutral-600"
529
538
  >
530
539
  <div className="flex items-center gap-2 flex-1 min-w-[188px] overflow-hidden">
531
540
  <Link className="flex-shrink-0 w-5 h-5 text-zinc-500 dark:text-neutral-400" />
@@ -632,9 +641,8 @@ export function TableForm({
632
641
  <div className="flex justify-end gap-3 max-w-[1080px] mx-auto px-6">
633
642
  <Button
634
643
  type="button"
635
- variant="outline"
636
644
  onClick={() => onOpenChange(false)}
637
- className="h-10 px-4 text-sm font-medium border-zinc-200 shadow-sm dark:bg-neutral-800 dark:text-zinc-300 dark:border-neutral-700 dark:hover:bg-neutral-700"
645
+ className="h-10 px-4 text-sm font-medium bg-white border border-zinc-200 shadow-[0px_1px_2px_0px_rgba(0,0,0,0.1)] text-zinc-950 hover:bg-zinc-50 dark:bg-neutral-600 dark:border-neutral-600 dark:text-white dark:hover:bg-neutral-700"
638
646
  >
639
647
  Cancel
640
648
  </Button>
@@ -643,7 +651,8 @@ export function TableForm({
643
651
  disabled={
644
652
  !form.formState.isValid ||
645
653
  createTableMutation.isPending ||
646
- updateTableMutation.isPending
654
+ updateTableMutation.isPending ||
655
+ (!form.formState.isDirty && !foreignKeysDirty)
647
656
  }
648
657
  className="h-10 px-4 text-sm font-medium bg-zinc-950 text-neutral-50 shadow-sm disabled:opacity-40 dark:bg-emerald-300 dark:text-zinc-950 dark:hover:bg-emerald-400"
649
658
  >
@@ -1,8 +1,7 @@
1
1
  import { memo } from 'react';
2
2
  import { Controller, Control } from 'react-hook-form';
3
3
  import { X, Key } from 'lucide-react';
4
- import { Input } from '@/components/radix/Input';
5
- import { Checkbox } from '@/components';
4
+ import { Input, Checkbox } from '@/components';
6
5
  import { TableFormColumnSchema, TableFormSchema } from '../schema';
7
6
  import { ColumnTypeSelect } from './ColumnTypeSelect';
8
7
 
@@ -25,7 +24,7 @@ export const TableFormColumn = memo(function TableFormColumn({
25
24
  }: TableFormColumnProps) {
26
25
  return (
27
26
  <div
28
- className={`flex items-center gap-6 px-4 py-2 ${
27
+ className={`flex items-center gap-6 px-4 py-2 w-min xl:w-full ${
29
28
  isNewColumn ? 'bg-slate-50 dark:bg-neutral-800' : 'bg-white dark:bg-[#2D2D2D]'
30
29
  }`}
31
30
  >
@@ -24,7 +24,7 @@ export function TableSidebar({
24
24
  }: TableSidebarProps) {
25
25
  return (
26
26
  <FeatureSidebar
27
- title="Database"
27
+ title="Tables"
28
28
  items={tables}
29
29
  selectedItem={selectedTable}
30
30
  onItemSelect={onTableSelect}
@@ -0,0 +1,48 @@
1
+ import { Plus } from 'lucide-react';
2
+ import { Button } from '@/components/radix/Button';
3
+ import { DatabaseTemplate } from '@/features/database/templates';
4
+ import { TemplateCard } from './TemplateCard';
5
+
6
+ interface TablesEmptyStateProps {
7
+ templates: DatabaseTemplate[];
8
+ onCreateTable: () => void;
9
+ onTemplateClick: (template: DatabaseTemplate) => void;
10
+ }
11
+
12
+ export function TablesEmptyState({
13
+ templates,
14
+ onCreateTable,
15
+ onTemplateClick,
16
+ }: TablesEmptyStateProps) {
17
+ return (
18
+ <div className="flex justify-center w-full h-full bg-bg-gray dark:bg-neutral-800 px-6">
19
+ <div className="flex flex-col gap-6 max-w-[1024px] w-full pb-9 pt-6">
20
+ <h2 className="text-xl font-semibold text-zinc-950 dark:text-white leading-7 tracking-[-0.1px]">
21
+ Create Your First Table
22
+ </h2>
23
+ <Button
24
+ className="h-9 w-50 gap-2 font-medium dark:bg-emerald-300 dark:hover:bg-emerald-400 dark:text-black"
25
+ onClick={onCreateTable}
26
+ >
27
+ <Plus className="w-5 h-5" />
28
+ Create Table
29
+ </Button>
30
+ <div className="flex flex-col gap-3">
31
+ <p className="text-sm font-normal text-zinc-500 dark:text-neutral-400 leading-6">
32
+ or choose a template to start
33
+ </p>
34
+ <div className="grid grid-cols-2 xl:grid-cols-3 gap-6">
35
+ {templates.map((template) => (
36
+ <TemplateCard
37
+ key={template.id}
38
+ template={template}
39
+ onClick={() => onTemplateClick(template)}
40
+ showTableCount
41
+ />
42
+ ))}
43
+ </div>
44
+ </div>
45
+ </div>
46
+ </div>
47
+ );
48
+ }
@@ -0,0 +1,37 @@
1
+ import { Table } from 'lucide-react';
2
+ import { DatabaseTemplate } from '@/features/database/templates';
3
+
4
+ interface TemplateCardProps {
5
+ template: DatabaseTemplate;
6
+ onClick: () => void;
7
+ showTableCount?: boolean;
8
+ }
9
+
10
+ export function TemplateCard({ template, onClick, showTableCount = false }: TemplateCardProps) {
11
+ return (
12
+ <button
13
+ onClick={onClick}
14
+ className="bg-white dark:bg-[#363636] border border-gray-200 dark:border-[#414141] rounded-[4px] pl-6 pr-4 pt-4 pb-6 text-left transition-colors hover:bg-gray-50 hover:border-gray-300 dark:hover:bg-neutral-700 dark:hover:border-[#525252] hover:shadow-sm flex flex-col gap-3"
15
+ >
16
+ <div className="flex flex-col gap-2">
17
+ <h3 className="text-base font-normal text-zinc-950 dark:text-white leading-6">
18
+ {template.title}
19
+ </h3>
20
+ {/* Fixed height container for description with line clamp */}
21
+ <div className="h-[72px]">
22
+ <p className="text-sm font-normal text-zinc-500 dark:text-neutral-400 leading-6 line-clamp-3">
23
+ {template.description}
24
+ </p>
25
+ </div>
26
+ </div>
27
+ {showTableCount && (
28
+ <div className="flex items-center gap-2">
29
+ <Table className="w-5 h-5 text-zinc-500 dark:text-neutral-400" />
30
+ <p className="text-sm font-normal text-zinc-500 dark:text-neutral-400 leading-6">
31
+ {template.tableCount} {template.tableCount === 1 ? 'Table' : 'Tables'}
32
+ </p>
33
+ </div>
34
+ )}
35
+ </button>
36
+ );
37
+ }