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,4 +1,5 @@
1
1
  import { Folder } from 'lucide-react';
2
+ import { ConnectCTA } from '@/components/ConnectCTA';
2
3
 
3
4
  interface BucketEmptyStateProps {
4
5
  searchTerm: string;
@@ -6,14 +7,16 @@ interface BucketEmptyStateProps {
6
7
 
7
8
  export function BucketEmptyState({ searchTerm }: BucketEmptyStateProps) {
8
9
  return (
9
- <div className="flex flex-col items-center justify-center py-8 px-4 text-center">
10
- <Folder className="h-10 w-10 text-gray-400 dark:text-zinc-300 mb-2.5" />
11
- <p className="text-sm text-gray-600 dark:text-zinc-300 font-medium">
10
+ <div className="flex flex-col items-center justify-center py-4 text-center">
11
+ <Folder 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 buckets found' : 'No buckets yet'}
13
14
  </p>
14
- <p className="text-xs text-gray-500 dark:text-zinc-300 mt-2.5">
15
- {searchTerm ? 'Try a different search term' : 'Create your first bucket to get started'}
16
- </p>
15
+ {!searchTerm && (
16
+ <p className="text-xs text-gray-500 dark:text-neutral-400 font-medium mt-1 mx-10">
17
+ <ConnectCTA fallback="Create your first bucket to get started" />
18
+ </p>
19
+ )}
17
20
  </div>
18
21
  );
19
22
  }
@@ -1,19 +1,17 @@
1
1
  import React, { useState, useEffect } from 'react';
2
- import { useMutation } from '@tanstack/react-query';
3
- import { storageService } from '@/features/storage/services/storage.service';
2
+ import { useStorage } from '@/features/storage/hooks/useStorage';
4
3
  import {
4
+ Button,
5
5
  Dialog,
6
6
  DialogContent,
7
7
  DialogDescription,
8
8
  DialogFooter,
9
9
  DialogHeader,
10
10
  DialogTitle,
11
- } from '@/components/radix/Dialog';
12
- import { Button } from '@/components/radix/Button';
13
- import { Input } from '@/components/radix/Input';
14
- import { Label } from '@/components/radix/Label';
15
- import { Switch } from '@/components/radix/Switch';
16
- import { useToast } from '@/lib/hooks/useToast';
11
+ Input,
12
+ Label,
13
+ Switch,
14
+ } from '@/components';
17
15
 
18
16
  interface BucketFormDialogProps {
19
17
  open: boolean;
@@ -35,7 +33,8 @@ export function BucketFormDialog({
35
33
  const [bucketName, setBucketName] = useState(initialBucketName);
36
34
  const [isPublic, setIsPublic] = useState(initialIsPublic);
37
35
  const [error, setError] = useState('');
38
- const { showToast } = useToast();
36
+
37
+ const { createBucket, editBucket, isCreatingBucket, isEditingBucket } = useStorage();
39
38
 
40
39
  useEffect(() => {
41
40
  if (open) {
@@ -50,33 +49,7 @@ export function BucketFormDialog({
50
49
  }
51
50
  }, [open, mode, initialBucketName, initialIsPublic]);
52
51
 
53
- const createBucketMutation = useMutation({
54
- mutationFn: ({ name, isPublic }: { name: string; isPublic: boolean }) =>
55
- storageService.createBucket(name, isPublic),
56
- onSuccess: () => {
57
- onSuccess(bucketName);
58
- showToast('Bucket created successfully', 'success');
59
- handleClose();
60
- },
61
- onError: (error: Error) => {
62
- setError(error.message || 'Failed to create bucket');
63
- },
64
- });
65
-
66
- const editBucketMutation = useMutation({
67
- mutationFn: ({ name, isPublic }: { name: string; isPublic: boolean }) =>
68
- storageService.editBucket(name, { isPublic: isPublic }),
69
- onSuccess: () => {
70
- onSuccess();
71
- showToast('Bucket updated successfully', 'success');
72
- handleClose();
73
- },
74
- onError: (error: Error) => {
75
- setError(error.message || 'Failed to update bucket');
76
- },
77
- });
78
-
79
- const handleSubmit = (e: React.FormEvent) => {
52
+ const handleSubmit = async (e: React.FormEvent): Promise<void> => {
80
53
  e.preventDefault();
81
54
 
82
55
  if (mode === 'create') {
@@ -84,9 +57,21 @@ export function BucketFormDialog({
84
57
  setError('Bucket name is required');
85
58
  return;
86
59
  }
87
- createBucketMutation.mutate({ name: bucketName.trim(), isPublic });
60
+ try {
61
+ await createBucket({ bucketName: bucketName.trim(), isPublic });
62
+ onSuccess(bucketName);
63
+ handleClose();
64
+ } catch (error) {
65
+ setError(error instanceof Error ? error.message : 'Failed to create bucket');
66
+ }
88
67
  } else {
89
- editBucketMutation.mutate({ name: bucketName, isPublic });
68
+ try {
69
+ await editBucket({ bucketName, config: { isPublic } });
70
+ onSuccess();
71
+ handleClose();
72
+ } catch (error) {
73
+ setError(error instanceof Error ? error.message : 'Failed to update bucket');
74
+ }
90
75
  }
91
76
  };
92
77
 
@@ -94,8 +79,7 @@ export function BucketFormDialog({
94
79
  onOpenChange(false);
95
80
  };
96
81
 
97
- const isLoading =
98
- mode === 'create' ? createBucketMutation.isPending : editBucketMutation.isPending;
82
+ const isLoading = mode === 'create' ? isCreatingBucket : isEditingBucket;
99
83
  const submitButtonText =
100
84
  mode === 'create'
101
85
  ? isLoading
@@ -108,7 +92,7 @@ export function BucketFormDialog({
108
92
  return (
109
93
  <Dialog open={open} onOpenChange={handleClose}>
110
94
  <DialogContent className="w-[480px] p-0 border-zinc-200 shadow-[0px_1px_3px_0px_rgba(0,0,0,0.1)]">
111
- <form onSubmit={handleSubmit} className="flex flex-col">
95
+ <form onSubmit={(e) => void handleSubmit(e)} className="flex flex-col">
112
96
  <DialogHeader className="px-6 py-3 flex flex-col gap-1 justify-start border-b border-zinc-200 dark:border-neutral-700">
113
97
  <DialogTitle className="text-lg font-semibold text-zinc-950 dark:text-white">
114
98
  {mode === 'create' ? 'Create New Bucket' : 'Edit Bucket'}
@@ -1,11 +1,8 @@
1
1
  import { useState, useEffect } from 'react';
2
2
  import { Download, ExternalLink } from 'lucide-react';
3
- import { Dialog, DialogContent } from '@/components/radix/Dialog';
4
- import { Button } from '@/components/radix/Button';
5
- import { LoadingState } from '@/components';
6
- import { storageService } from '@/features/storage/services/storage.service';
3
+ import { Button, Dialog, DialogContent, LoadingState, TypeBadge } from '@/components';
4
+ import { useStorage } from '@/features/storage/hooks/useStorage';
7
5
  import { StorageFileSchema } from '@insforge/shared-schemas';
8
- import { TypeBadge } from '@/components/TypeBadge';
9
6
 
10
7
  interface FilePreviewDialogProps {
11
8
  open: boolean;
@@ -19,6 +16,8 @@ export function FilePreviewDialog({ open, onOpenChange, file, bucket }: FilePrev
19
16
  const [previewUrl, setPreviewUrl] = useState<string | null>(null);
20
17
  const [error, setError] = useState<string | null>(null);
21
18
 
19
+ const { downloadObject } = useStorage();
20
+
22
21
  // Reset state when file changes
23
22
  useEffect(() => {
24
23
  if (!file || !open) {
@@ -27,7 +26,9 @@ export function FilePreviewDialog({ open, onOpenChange, file, bucket }: FilePrev
27
26
  return;
28
27
  }
29
28
 
30
- const loadPreview = () => {
29
+ let currentUrl: string | null = null;
30
+
31
+ const loadPreview = async () => {
31
32
  if (!file) {
32
33
  return;
33
34
  }
@@ -37,7 +38,10 @@ export function FilePreviewDialog({ open, onOpenChange, file, bucket }: FilePrev
37
38
 
38
39
  try {
39
40
  const fileBucket = file.bucket || bucket;
40
- const url = storageService.getDownloadUrl(fileBucket, file.key);
41
+ // Fetch file with authentication and create blob URL
42
+ const blob = await downloadObject(fileBucket, file.key);
43
+ const url = URL.createObjectURL(blob);
44
+ currentUrl = url;
41
45
  setPreviewUrl(url);
42
46
  } catch (err) {
43
47
  const errorMessage = err instanceof Error ? err.message : 'Failed to load preview';
@@ -48,7 +52,14 @@ export function FilePreviewDialog({ open, onOpenChange, file, bucket }: FilePrev
48
52
  };
49
53
 
50
54
  void loadPreview();
51
- }, [file, open, bucket]);
55
+
56
+ // Cleanup: Revoke blob URL when component unmounts or file changes
57
+ return () => {
58
+ if (currentUrl) {
59
+ URL.revokeObjectURL(currentUrl);
60
+ }
61
+ };
62
+ }, [file, open, bucket, downloadObject]);
52
63
 
53
64
  const handleDownload = () => {
54
65
  if (!file || !previewUrl) {
@@ -250,6 +261,7 @@ function TextPreview({ url }: { url: string }) {
250
261
  const loadTextContent = async () => {
251
262
  try {
252
263
  setLoading(true);
264
+ // Fetch the blob URL (which is already authenticated)
253
265
  const response = await fetch(url);
254
266
  if (!response.ok) {
255
267
  throw new Error('Failed to load text content');
@@ -6,8 +6,8 @@ import {
6
6
  type RenderCellProps,
7
7
  type DataGridColumn,
8
8
  type DataGridRowType,
9
- } from '@/components/datagrid';
10
- import { Button } from '@/components/radix/Button';
9
+ Button,
10
+ } from '@/components';
11
11
  import { Download, Eye, Trash2, Image, FileText, Music, Video, Archive, File } from 'lucide-react';
12
12
  import { StorageFileSchema } from '@insforge/shared-schemas';
13
13
 
@@ -135,6 +135,7 @@ export function createStorageColumns(
135
135
  columns.push({
136
136
  key: 'actions',
137
137
  name: '',
138
+ minWidth: 120,
138
139
  maxWidth: 120,
139
140
  resizable: false,
140
141
  sortable: false,
@@ -178,7 +179,7 @@ export function createStorageColumns(
178
179
  <Button
179
180
  variant="ghost"
180
181
  size="icon"
181
- className="h-8 w-8 hover:bg-red-50"
182
+ className="h-8 w-8"
182
183
  onClick={(e) => {
183
184
  e.stopPropagation();
184
185
  onDelete(row as StorageFileSchema);
@@ -1,12 +1,10 @@
1
1
  import { useState, useCallback, useMemo, useEffect } from 'react';
2
- import { useQuery, useQueryClient, useMutation } from '@tanstack/react-query';
3
2
  import { Folder } from 'lucide-react';
4
- import { storageService } from '@/features/storage/services/storage.service';
3
+ import { useStorage } from '@/features/storage/hooks/useStorage';
5
4
  import { StorageFileSchema } from '@insforge/shared-schemas';
6
- import { LoadingState, ErrorState, EmptyState } from '@/components';
5
+ import { LoadingState, ErrorState, EmptyState, ConfirmDialog, ConnectCTA } from '@/components';
7
6
  import { StorageDataGrid } from './StorageDataGrid';
8
7
  import { FilePreviewDialog } from './FilePreviewDialog';
9
- import { ConfirmDialog } from '@/components/ConfirmDialog';
10
8
  import { useConfirm } from '@/lib/hooks/useConfirm';
11
9
  import { useToast } from '@/lib/hooks/useToast';
12
10
  import { SortColumn } from 'react-data-grid';
@@ -28,7 +26,6 @@ export function StorageManager({
28
26
  onSelectedFilesChange,
29
27
  isRefreshing = false,
30
28
  }: StorageManagerProps) {
31
- const queryClient = useQueryClient();
32
29
  const [downloadingFiles, setDownloadingFiles] = useState<Set<string>>(new Set());
33
30
  const [previewFile, setPreviewFile] = useState<StorageFileSchema | null>(null);
34
31
  const [showPreviewDialog, setShowPreviewDialog] = useState(false);
@@ -45,25 +42,21 @@ export function StorageManager({
45
42
  setCurrentPage(1);
46
43
  }, [searchQuery, bucketName]);
47
44
 
45
+ const { useListObjects, deleteObjects, downloadObject } = useStorage();
46
+
48
47
  // Fetch objects in selected bucket
49
48
  const {
50
49
  data: objectsData,
51
50
  isLoading: objectsLoading,
52
51
  error: objectsError,
53
- } = useQuery({
54
- queryKey: ['storage', 'objects', bucketName, currentPage, pageSize, searchQuery],
55
- queryFn: () =>
56
- storageService.listObjects(
57
- bucketName,
58
- {
59
- limit: pageSize,
60
- offset: (currentPage - 1) * pageSize,
61
- },
62
- searchQuery
63
- ),
64
- enabled: !!bucketName,
65
- placeholderData: (previousData) => previousData, // Keep previous data while loading
66
- });
52
+ } = useListObjects(
53
+ bucketName,
54
+ {
55
+ limit: pageSize,
56
+ offset: (currentPage - 1) * pageSize,
57
+ },
58
+ searchQuery
59
+ );
67
60
 
68
61
  // Calculate pagination from backend response
69
62
  const totalPages = useMemo(() => {
@@ -71,22 +64,13 @@ export function StorageManager({
71
64
  return Math.ceil(total / pageSize);
72
65
  }, [objectsData?.pagination.total, fileCount, pageSize]);
73
66
 
74
- // Delete mutation
75
- const deleteMutation = useMutation({
76
- mutationFn: ({ bucket, key }: { bucket: string; key: string }) =>
77
- storageService.deleteObject(bucket, key),
78
- onSuccess: () => {
79
- void queryClient.invalidateQueries({ queryKey: ['storage'] });
80
- },
81
- });
82
-
83
67
  // No need for client-side filtering - backend handles search
84
68
  // Just apply sorting
85
69
  const processedFiles = useMemo(() => {
86
70
  let files = objectsData?.objects || [];
87
71
 
88
72
  // Apply sorting
89
- if (sortColumns.length > 0) {
73
+ if (sortColumns.length) {
90
74
  const sortColumn = sortColumns[0];
91
75
  files = [...files].sort((a, b) => {
92
76
  const aValue = a[sortColumn.columnKey as keyof StorageFileSchema];
@@ -115,7 +99,7 @@ export function StorageManager({
115
99
  async (file: StorageFileSchema) => {
116
100
  setDownloadingFiles((prev) => new Set(prev).add(file.key));
117
101
  try {
118
- const blob = await storageService.downloadObject(bucketName, file.key);
102
+ const blob = await downloadObject(bucketName, file.key);
119
103
 
120
104
  // Create download link
121
105
  const url = window.URL.createObjectURL(blob);
@@ -137,7 +121,7 @@ export function StorageManager({
137
121
  });
138
122
  }
139
123
  },
140
- [bucketName, showToast]
124
+ [bucketName, downloadObject, showToast]
141
125
  );
142
126
 
143
127
  const handlePreview = useCallback((file: StorageFileSchema) => {
@@ -157,10 +141,10 @@ export function StorageManager({
157
141
  const shouldDelete = await confirm(confirmOptions);
158
142
 
159
143
  if (shouldDelete) {
160
- deleteMutation.mutate({ bucket: bucketName, key: file.key });
144
+ deleteObjects({ bucket: bucketName, keys: [file.key] });
161
145
  }
162
146
  },
163
- [bucketName, confirm, deleteMutation]
147
+ [bucketName, confirm, deleteObjects]
164
148
  );
165
149
 
166
150
  const isDownloading = useCallback(
@@ -217,7 +201,12 @@ export function StorageManager({
217
201
  onDownload={(file) => void handleDownload(file)}
218
202
  onDelete={(file) => void handleDelete(file)}
219
203
  isDownloading={isDownloading}
220
- emptyStateTitle={searchQuery ? 'No files match your search criteria' : 'No files found'}
204
+ emptyState={
205
+ <div className="text-sm text-zinc-500 dark:text-zinc-400">
206
+ {searchQuery ? 'No files match your search criteria' : 'No files found'}.{' '}
207
+ <ConnectCTA />
208
+ </div>
209
+ }
221
210
  />
222
211
  </div>
223
212
 
@@ -0,0 +1,12 @@
1
+ export { BucketEmptyState } from './BucketEmptyState';
2
+ export { BucketFormDialog } from './BucketFormDialog';
3
+ export { BucketListSkeleton } from './BucketListSkeleton';
4
+ export { FilePreviewDialog } from './FilePreviewDialog';
5
+ export {
6
+ createStorageColumns,
7
+ StorageDataGrid,
8
+ type StorageDataGridProps,
9
+ } from './StorageDataGrid';
10
+ export { StorageManager } from './StorageManager';
11
+ export { StorageSidebar } from './StorageSidebar';
12
+ export { useUploadToast } from './UploadToast';
@@ -0,0 +1,208 @@
1
+ import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
2
+ import { storageService, type ListObjectsParams } from '../services/storage.service';
3
+ import { useToast } from '@/lib/hooks/useToast';
4
+
5
+ export function useStorage() {
6
+ const queryClient = useQueryClient();
7
+ const { showToast } = useToast();
8
+
9
+ // Query to fetch all buckets
10
+ const {
11
+ data: buckets,
12
+ isLoading: isLoadingBuckets,
13
+ error: bucketsError,
14
+ refetch: refetchBuckets,
15
+ } = useQuery({
16
+ queryKey: ['storage', 'buckets'],
17
+ queryFn: () => storageService.listBuckets(),
18
+ });
19
+
20
+ // Hook to fetch objects in a bucket
21
+ const useListObjects = (
22
+ bucketName: string,
23
+ params?: ListObjectsParams,
24
+ searchQuery?: string,
25
+ enabled = true
26
+ ) => {
27
+ return useQuery({
28
+ queryKey: ['storage', 'objects', bucketName, params?.limit, params?.offset, searchQuery],
29
+ queryFn: () => storageService.listObjects(bucketName, params, searchQuery),
30
+ enabled: enabled && !!bucketName,
31
+ placeholderData: (previousData) => previousData,
32
+ });
33
+ };
34
+
35
+ // Query to fetch bucket statistics
36
+ const useBucketStats = (enabled = true) => {
37
+ return useQuery({
38
+ queryKey: ['storage', 'bucket-stats', buckets],
39
+ queryFn: async () => {
40
+ const stats: Record<
41
+ string,
42
+ { fileCount: number; totalSize: number; public: boolean; createdAt?: string }
43
+ > = {};
44
+ const currentBuckets = buckets || [];
45
+ const promises = currentBuckets.map(async (bucket) => {
46
+ try {
47
+ const result = await storageService.listObjects(bucket.name, { limit: 1000 });
48
+ const objects = result.objects;
49
+ const totalSize = objects.reduce((sum, file) => sum + file.size, 0);
50
+ return {
51
+ bucketName: bucket.name,
52
+ stats: {
53
+ fileCount: result.pagination.total,
54
+ totalSize: totalSize,
55
+ public: bucket.public,
56
+ createdAt: bucket.createdAt,
57
+ },
58
+ };
59
+ } catch (error) {
60
+ if (error) {
61
+ console.error(error);
62
+ return null;
63
+ }
64
+ return {
65
+ bucketName: bucket.name,
66
+ stats: {
67
+ fileCount: 0,
68
+ totalSize: 0,
69
+ public: bucket.public,
70
+ createdAt: bucket.createdAt,
71
+ },
72
+ };
73
+ }
74
+ });
75
+ const results = await Promise.all(promises);
76
+ results.forEach((result) => {
77
+ if (result) {
78
+ stats[result.bucketName] = result.stats;
79
+ }
80
+ });
81
+ return stats;
82
+ },
83
+ enabled: enabled && (buckets?.length || 0) > 0,
84
+ staleTime: 30000,
85
+ });
86
+ };
87
+
88
+ // Mutation to upload an object
89
+ const uploadObjectMutation = useMutation({
90
+ mutationFn: async ({
91
+ bucket,
92
+ objectKey,
93
+ file,
94
+ }: {
95
+ bucket: string;
96
+ objectKey: string;
97
+ file: File;
98
+ }) => storageService.uploadObject(bucket, objectKey, file),
99
+ onSuccess: () => {
100
+ void queryClient.invalidateQueries({ queryKey: ['storage'] });
101
+ },
102
+ });
103
+
104
+ // Mutation to delete an object
105
+ const deleteObjectsMutation = useMutation({
106
+ mutationFn: ({ bucket, keys }: { bucket: string; keys: string[] }) =>
107
+ storageService.deleteObjects(bucket, keys),
108
+ onSuccess: (result) => {
109
+ const { success, failures } = result;
110
+ const successCount = success.length;
111
+ const failureCount = failures.length;
112
+ if (failureCount > 0 && successCount > 0) {
113
+ showToast(
114
+ `${successCount} ${successCount > 1 ? 'files' : 'file'} deleted, ${failureCount} ${failureCount > 1 ? 'files' : 'file'} failed to delete.`,
115
+ 'warn'
116
+ );
117
+ } else if (failureCount > 0) {
118
+ showToast(
119
+ `Failed to delete ${failureCount} ${failureCount > 1 ? 'files' : 'file'}`,
120
+ 'error'
121
+ );
122
+ } else if (successCount > 0) {
123
+ showToast(
124
+ `${successCount} ${successCount > 1 ? 'files' : 'file'} deleted successfully.`,
125
+ 'success'
126
+ );
127
+ }
128
+
129
+ void queryClient.invalidateQueries({ queryKey: ['storage'] });
130
+ },
131
+ onError: (error: Error) => {
132
+ const errorMessage = error instanceof Error ? error.message : 'Failed to delete file';
133
+ showToast(errorMessage, 'error');
134
+ },
135
+ });
136
+
137
+ // Mutation to create a bucket
138
+ const createBucketMutation = useMutation({
139
+ mutationFn: ({ bucketName, isPublic }: { bucketName: string; isPublic: boolean }) =>
140
+ storageService.createBucket(bucketName, isPublic),
141
+ onSuccess: () => {
142
+ void queryClient.invalidateQueries({ queryKey: ['storage', 'buckets'] });
143
+ showToast('Bucket created successfully', 'success');
144
+ },
145
+ onError: (error: Error) => {
146
+ const errorMessage = error instanceof Error ? error.message : 'Failed to create bucket';
147
+ showToast(errorMessage, 'error');
148
+ },
149
+ });
150
+
151
+ // Mutation to delete a bucket
152
+ const deleteBucketMutation = useMutation({
153
+ mutationFn: (bucketName: string) => storageService.deleteBucket(bucketName),
154
+ onSuccess: () => {
155
+ void queryClient.invalidateQueries({ queryKey: ['storage', 'buckets'] });
156
+ showToast('Bucket deleted successfully', 'success');
157
+ },
158
+ onError: (error: Error) => {
159
+ const errorMessage = error instanceof Error ? error.message : 'Failed to delete bucket';
160
+ showToast(errorMessage, 'error');
161
+ },
162
+ });
163
+
164
+ // Mutation to edit a bucket
165
+ const editBucketMutation = useMutation({
166
+ mutationFn: ({ bucketName, config }: { bucketName: string; config: { isPublic: boolean } }) =>
167
+ storageService.editBucket(bucketName, config),
168
+ onSuccess: () => {
169
+ void queryClient.invalidateQueries({ queryKey: ['storage'] });
170
+ showToast('Bucket updated successfully', 'success');
171
+ },
172
+ onError: (error: Error) => {
173
+ const errorMessage = error instanceof Error ? error.message : 'Failed to update bucket';
174
+ showToast(errorMessage, 'error');
175
+ },
176
+ });
177
+
178
+ return {
179
+ // Data
180
+ buckets: buckets || [],
181
+ bucketsCount: buckets?.length || 0,
182
+
183
+ // Loading states
184
+ isLoadingBuckets,
185
+ isUploadingObject: uploadObjectMutation.isPending,
186
+ isDeletingObject: deleteObjectsMutation.isPending,
187
+ isCreatingBucket: createBucketMutation.isPending,
188
+ isDeletingBucket: deleteBucketMutation.isPending,
189
+ isEditingBucket: editBucketMutation.isPending,
190
+
191
+ // Errors
192
+ bucketsError,
193
+
194
+ // Actions
195
+ uploadObject: uploadObjectMutation.mutateAsync,
196
+ deleteObjects: deleteObjectsMutation.mutate,
197
+ createBucket: createBucketMutation.mutateAsync,
198
+ deleteBucket: deleteBucketMutation.mutateAsync,
199
+ editBucket: editBucketMutation.mutateAsync,
200
+ refetchBuckets,
201
+
202
+ // Helpers
203
+ useListObjects,
204
+ useBucketStats,
205
+ getDownloadUrl: storageService.getDownloadUrl,
206
+ downloadObject: storageService.downloadObject,
207
+ };
208
+ }