insforge 1.2.10 → 1.4.8

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 (506) hide show
  1. package/.claude-plugin/marketplace.json +20 -20
  2. package/.dockerignore +60 -60
  3. package/.env.example +83 -77
  4. package/.github/ISSUE_TEMPLATE/bug_report.yml +36 -36
  5. package/.github/ISSUE_TEMPLATE/config.yml +11 -11
  6. package/.github/ISSUE_TEMPLATE/feature_request.yml +26 -26
  7. package/.github/PULL_REQUEST_TEMPLATE.md +7 -7
  8. package/.github/copilot-instructions.md +146 -146
  9. package/.github/workflows/build-image.yml +65 -65
  10. package/.github/workflows/ci-premerge-check.yml +23 -23
  11. package/.github/workflows/e2e.yml +63 -63
  12. package/.github/workflows/lint-and-format.yml +32 -32
  13. package/.prettierignore +64 -64
  14. package/CHANGELOG.md +46 -44
  15. package/CLAUDE_PLUGIN.md +104 -104
  16. package/CODE_OF_CONDUCT.md +128 -128
  17. package/CONTRIBUTING.md +125 -125
  18. package/Dockerfile +30 -30
  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 -182
  23. package/assets/Dark.svg +23 -23
  24. package/auth/package.json +30 -28
  25. package/auth/src/lib/broadcastService.ts +4 -4
  26. package/auth/src/lib/insforge.ts +8 -0
  27. package/auth/src/main.tsx +2 -4
  28. package/auth/src/pages/SignInPage.tsx +5 -2
  29. package/auth/src/pages/SignUpPage.tsx +5 -2
  30. package/auth/src/pages/VerifyEmailPage.tsx +18 -0
  31. package/auth/tsconfig.json +33 -32
  32. package/auth/tsconfig.node.json +11 -11
  33. package/backend/package.json +82 -75
  34. package/backend/src/api/middlewares/rate-limiters.ts +127 -127
  35. package/backend/src/api/routes/ai/index.routes.ts +475 -468
  36. package/backend/src/api/routes/auth/index.routes.ts +720 -570
  37. package/backend/src/api/routes/auth/oauth.routes.ts +478 -448
  38. package/backend/src/api/routes/database/advance.routes.ts +37 -16
  39. package/backend/src/api/routes/database/index.routes.ts +80 -1
  40. package/backend/src/api/routes/database/records.routes.ts +48 -184
  41. package/backend/src/api/routes/database/rpc.routes.ts +69 -0
  42. package/backend/src/api/routes/database/tables.routes.ts +0 -14
  43. package/backend/src/api/routes/deployments/index.routes.ts +192 -0
  44. package/backend/src/api/routes/docs/index.routes.ts +76 -76
  45. package/backend/src/api/routes/email/index.routes.ts +35 -0
  46. package/backend/src/api/routes/functions/index.routes.ts +21 -15
  47. package/backend/src/api/routes/metadata/index.routes.ts +38 -0
  48. package/backend/src/api/routes/realtime/channels.routes.ts +81 -0
  49. package/backend/src/api/routes/realtime/index.routes.ts +12 -0
  50. package/backend/src/api/routes/realtime/messages.routes.ts +48 -0
  51. package/backend/src/api/routes/realtime/permissions.routes.ts +19 -0
  52. package/backend/src/api/routes/storage/index.routes.ts +18 -12
  53. package/backend/src/api/routes/usage/index.routes.ts +6 -4
  54. package/backend/src/api/routes/webhooks/index.routes.ts +109 -0
  55. package/backend/src/infra/database/database.manager.ts +14 -11
  56. package/backend/src/infra/database/migrations/000_create-base-tables.sql +141 -141
  57. package/backend/src/infra/database/migrations/001_create-helper-functions.sql +40 -40
  58. package/backend/src/infra/database/migrations/002_rename-auth-tables.sql +29 -29
  59. package/backend/src/infra/database/migrations/003_create-users-table.sql +55 -55
  60. package/backend/src/infra/database/migrations/004_add-reload-postgrest-func.sql +23 -23
  61. package/backend/src/infra/database/migrations/005_enable-project-admin-modify-users.sql +29 -29
  62. package/backend/src/infra/database/migrations/006_modify-ai-usage-table.sql +24 -24
  63. package/backend/src/infra/database/migrations/007_drop-metadata-table.sql +1 -1
  64. package/backend/src/infra/database/migrations/008_add-system-tables.sql +76 -76
  65. package/backend/src/infra/database/migrations/009_add-function-secrets.sql +23 -23
  66. package/backend/src/infra/database/migrations/010_modify-ai-config-modalities.sql +93 -93
  67. package/backend/src/infra/database/migrations/011_refactor-secrets-table.sql +15 -15
  68. package/backend/src/infra/database/migrations/012_add-storage-uploaded-by.sql +7 -7
  69. package/backend/src/infra/database/migrations/013_create-auth-schema-functions.sql +44 -44
  70. package/backend/src/infra/database/migrations/014_add-updated-at-trigger-user-table.sql +7 -7
  71. package/backend/src/infra/database/migrations/015_create-auth-config-and-email-otp-tables.sql +59 -59
  72. package/backend/src/infra/database/migrations/016_update-auth-config-and-email-otp.sql +24 -24
  73. package/backend/src/infra/database/migrations/017_create-realtime-schema.sql +233 -0
  74. package/backend/src/infra/database/migrations/018_schema-rework.sql +441 -0
  75. package/backend/src/infra/database/migrations/019_create-deployments-table.sql +36 -0
  76. package/backend/src/infra/database/migrations/020_add-audio-modality.sql +11 -0
  77. package/backend/src/infra/database/migrations/bootstrap/bootstrap-migrations.js +103 -0
  78. package/backend/src/infra/realtime/realtime.manager.ts +246 -0
  79. package/backend/src/infra/realtime/webhook-sender.ts +82 -0
  80. package/backend/src/infra/security/token.manager.ts +216 -125
  81. package/backend/src/infra/socket/socket.manager.ts +198 -64
  82. package/backend/src/providers/ai/openrouter.provider.ts +24 -12
  83. package/backend/src/providers/database/base.provider.ts +39 -0
  84. package/backend/src/providers/database/cloud.provider.ts +159 -0
  85. package/backend/src/providers/deployments/vercel.provider.ts +516 -0
  86. package/backend/src/providers/email/base.provider.ts +4 -7
  87. package/backend/src/providers/email/cloud.provider.ts +84 -0
  88. package/backend/src/providers/oauth/apple.provider.ts +266 -0
  89. package/backend/src/providers/oauth/index.ts +1 -0
  90. package/backend/src/server.ts +329 -284
  91. package/backend/src/services/ai/ai-config.service.ts +6 -6
  92. package/backend/src/services/ai/ai-model.service.ts +60 -60
  93. package/backend/src/services/ai/ai-usage.service.ts +7 -7
  94. package/backend/src/services/ai/chat-completion.service.ts +415 -220
  95. package/backend/src/services/ai/helpers.ts +64 -64
  96. package/backend/src/services/ai/image-generation.service.ts +3 -3
  97. package/backend/src/services/ai/index.ts +13 -13
  98. package/backend/src/services/auth/auth-config.service.ts +4 -4
  99. package/backend/src/services/auth/auth-otp.service.ts +6 -6
  100. package/backend/src/services/auth/auth.service.ts +148 -74
  101. package/backend/src/services/auth/index.ts +4 -4
  102. package/backend/src/services/auth/oauth-config.service.ts +12 -12
  103. package/backend/src/services/database/database-advance.service.ts +19 -55
  104. package/backend/src/services/database/database-table.service.ts +38 -94
  105. package/backend/src/services/database/database.service.ts +127 -0
  106. package/backend/src/services/database/postgrest-proxy.service.ts +165 -0
  107. package/backend/src/services/deployments/deployment.service.ts +693 -0
  108. package/backend/src/services/email/email.service.ts +5 -7
  109. package/backend/src/services/functions/function.service.ts +61 -41
  110. package/backend/src/services/logs/audit.service.ts +10 -10
  111. package/backend/src/services/realtime/index.ts +3 -0
  112. package/backend/src/services/realtime/realtime-auth.service.ts +104 -0
  113. package/backend/src/services/realtime/realtime-channel.service.ts +237 -0
  114. package/backend/src/services/realtime/realtime-message.service.ts +260 -0
  115. package/backend/src/services/secrets/secret.service.ts +101 -27
  116. package/backend/src/services/storage/storage.service.ts +30 -30
  117. package/backend/src/services/usage/usage.service.ts +6 -6
  118. package/backend/src/types/ai.ts +8 -0
  119. package/backend/src/types/auth.ts +16 -1
  120. package/backend/src/types/database.ts +2 -0
  121. package/backend/src/types/deployments.ts +33 -0
  122. package/backend/src/types/realtime.ts +18 -0
  123. package/backend/src/types/socket.ts +7 -31
  124. package/backend/src/types/storage.ts +1 -1
  125. package/backend/src/types/webhooks.ts +45 -0
  126. package/backend/src/utils/cookies.ts +34 -0
  127. package/backend/src/utils/environment.ts +0 -14
  128. package/backend/src/utils/s3-config-loader.ts +64 -0
  129. package/backend/src/utils/seed.ts +79 -43
  130. package/backend/src/utils/sql-parser.ts +216 -0
  131. package/backend/src/utils/utils.ts +114 -114
  132. package/backend/src/utils/validations.ts +10 -10
  133. package/backend/tests/README.md +133 -133
  134. package/backend/tests/cleanup-all-test-data.sh +230 -230
  135. package/backend/tests/cloud/test-s3-multitenant.sh +131 -131
  136. package/backend/tests/local/comprehensive-curl-tests.sh +155 -155
  137. package/backend/tests/local/test-ai-config.sh +129 -129
  138. package/backend/tests/local/test-ai-usage.sh +80 -80
  139. package/backend/tests/local/test-auth-router.sh +143 -143
  140. package/backend/tests/local/test-database-router.sh +222 -222
  141. package/backend/tests/local/test-e2e.sh +240 -240
  142. package/backend/tests/local/test-fk-errors.sh +96 -96
  143. package/backend/tests/local/test-functions.sh +123 -123
  144. package/backend/tests/local/test-id-field.sh +200 -200
  145. package/backend/tests/local/test-logs.sh +132 -132
  146. package/backend/tests/local/test-public-bucket.sh +264 -264
  147. package/backend/tests/local/test-rpc.sh +141 -0
  148. package/backend/tests/local/test-secrets.sh +249 -249
  149. package/backend/tests/local/test-serverless-functions.sh.disabled +325 -325
  150. package/backend/tests/local/test-traditional-rest.sh +208 -208
  151. package/backend/tests/manual/README.md +50 -50
  152. package/backend/tests/manual/create-large-table-simple.sql +10 -10
  153. package/backend/tests/manual/seed-large-table.sql +100 -100
  154. package/backend/tests/manual/setup-large-table-extras.sql +33 -33
  155. package/backend/tests/manual/test-ai-model-plugins.sh +258 -0
  156. package/backend/tests/manual/test-bulk-upsert.sh +409 -409
  157. package/backend/tests/manual/test-database-advance.sh +296 -296
  158. package/backend/tests/manual/test-postgrest-stability.sh +191 -191
  159. package/backend/tests/manual/test-rawsql-export-import.sh +411 -411
  160. package/backend/tests/manual/test-rawsql-modes.sh +244 -244
  161. package/backend/tests/manual/test-universal-storage.sh +263 -263
  162. package/backend/tests/manual/test-users.sql +17 -17
  163. package/backend/tests/run-all-tests.sh +139 -139
  164. package/backend/tests/setup.ts +0 -0
  165. package/backend/tests/test-config.sh +338 -338
  166. package/backend/tests/unit/analyze-query.test.ts +697 -0
  167. package/backend/tests/unit/database-advance.test.ts +326 -0
  168. package/backend/tests/unit/helpers.test.ts +2 -2
  169. package/backend/tsconfig.json +22 -22
  170. package/claude-plugin/.claude-plugin/plugin.json +24 -24
  171. package/claude-plugin/README.md +133 -133
  172. package/claude-plugin/skills/insforge-schema-patterns/SKILL.md +273 -270
  173. package/docker-compose.prod.yml +204 -200
  174. package/docker-compose.yml +232 -228
  175. package/docker-init/db/db-init.sql +97 -97
  176. package/docker-init/db/jwt.sql +5 -5
  177. package/docker-init/db/postgresql.conf +16 -16
  178. package/docker-init/logs/vector.yml +236 -236
  179. package/docs/README.md +44 -44
  180. package/docs/agent-docs/deployment.md +79 -0
  181. package/docs/agent-docs/real-time.md +269 -0
  182. package/docs/changelog.mdx +212 -67
  183. package/docs/core-concepts/ai/architecture.mdx +350 -372
  184. package/docs/core-concepts/ai/sdk.mdx +238 -213
  185. package/docs/core-concepts/authentication/architecture.mdx +276 -278
  186. package/docs/core-concepts/authentication/sdk.mdx +710 -414
  187. package/docs/core-concepts/authentication/ui-components/customization.mdx +733 -529
  188. package/docs/core-concepts/authentication/ui-components/nextjs.mdx +247 -221
  189. package/docs/core-concepts/authentication/ui-components/react-router.mdx +183 -184
  190. package/docs/core-concepts/authentication/ui-components/react.mdx +136 -129
  191. package/docs/core-concepts/database/architecture.mdx +292 -255
  192. package/docs/core-concepts/database/pgvector.mdx +138 -0
  193. package/docs/core-concepts/database/sdk.mdx +382 -382
  194. package/docs/core-concepts/deployments/architecture.mdx +152 -0
  195. package/docs/core-concepts/email/architecture.mdx +103 -0
  196. package/docs/core-concepts/email/sdk.mdx +53 -0
  197. package/docs/core-concepts/functions/architecture.mdx +105 -105
  198. package/docs/core-concepts/functions/sdk.mdx +183 -184
  199. package/docs/core-concepts/realtime/architecture.mdx +446 -0
  200. package/docs/core-concepts/realtime/sdk.mdx +409 -0
  201. package/docs/core-concepts/storage/architecture.mdx +243 -243
  202. package/docs/core-concepts/storage/sdk.mdx +253 -253
  203. package/docs/deployment/README.md +94 -94
  204. package/docs/deployment/deploy-to-aws-ec2.md +564 -564
  205. package/docs/deployment/deploy-to-azure-virtual-machines.md +312 -312
  206. package/docs/deployment/deploy-to-google-cloud-compute-engine.md +613 -613
  207. package/docs/deployment/deploy-to-render.md +441 -441
  208. package/docs/deprecated/insforge-auth-api.md +214 -214
  209. package/docs/deprecated/insforge-auth-sdk.md +99 -99
  210. package/docs/deprecated/insforge-db-api.md +358 -358
  211. package/docs/deprecated/insforge-db-sdk.md +139 -139
  212. package/docs/deprecated/insforge-debug-sdk.md +156 -156
  213. package/docs/deprecated/insforge-debug.md +64 -64
  214. package/docs/deprecated/insforge-instructions.md +123 -123
  215. package/docs/deprecated/insforge-project.md +117 -117
  216. package/docs/deprecated/insforge-storage-api.md +278 -278
  217. package/docs/deprecated/insforge-storage-sdk.md +158 -158
  218. package/docs/docs.json +240 -210
  219. package/docs/examples/framework-guides/nextjs.mdx +131 -131
  220. package/docs/examples/framework-guides/nuxt.mdx +165 -165
  221. package/docs/examples/framework-guides/react.mdx +165 -165
  222. package/docs/examples/framework-guides/svelte.mdx +153 -153
  223. package/docs/examples/framework-guides/vue.mdx +159 -159
  224. package/docs/examples/overview.mdx +67 -67
  225. package/docs/favicon.png +0 -0
  226. package/docs/favicon.svg +4 -19
  227. package/docs/images/changelog/dec-2025/ai-integration.png +0 -0
  228. package/docs/images/changelog/dec-2025/ai-models.webp +0 -0
  229. package/docs/images/changelog/dec-2025/alipay-payment.webp +0 -0
  230. package/docs/images/changelog/dec-2025/apple-login.jpg +0 -0
  231. package/docs/images/changelog/dec-2025/apple-oauth.mp4 +0 -0
  232. package/docs/images/changelog/dec-2025/mcp-installer.png +0 -0
  233. package/docs/images/changelog/dec-2025/moreModels.png +0 -0
  234. package/docs/images/changelog/dec-2025/multi-region.webp +0 -0
  235. package/docs/images/changelog/dec-2025/postgres-connection.webp +0 -0
  236. package/docs/images/changelog/dec-2025/realtime-module.jpg +0 -0
  237. package/docs/images/changelog/dec-2025/realtime2.png +0 -0
  238. package/docs/images/icons/ai.svg +4 -4
  239. package/docs/images/logos/nextjs.svg +4 -4
  240. package/docs/images/logos/nuxt.svg +4 -4
  241. package/docs/images/logos/react.svg +5 -5
  242. package/docs/images/logos/svelte.svg +4 -4
  243. package/docs/images/logos/vue.svg +5 -5
  244. package/docs/images/mcp-setup/CC-MCP-1.mp4 +0 -0
  245. package/docs/images/mcp-setup/CC-MCP-2.mp4 +0 -0
  246. package/docs/images/mcp-setup/Cursor-MCP-1.mp4 +0 -0
  247. package/docs/images/mcp-setup/Cursor-MCP-2.mp4 +0 -0
  248. package/docs/images/mcp-setup/Cursor-MCP-3.mp4 +0 -0
  249. package/docs/images/mcp-setup/claude-code-connect.png +0 -0
  250. package/docs/images/mcp-setup/cline-1.png +0 -0
  251. package/docs/images/mcp-setup/cline-2.png +0 -0
  252. package/docs/images/mcp-setup/cline-3.png +0 -0
  253. package/docs/images/mcp-setup/connect-project.png +0 -0
  254. package/docs/images/mcp-setup/copilot-1.png +0 -0
  255. package/docs/images/mcp-setup/copilot-2.png +0 -0
  256. package/docs/images/mcp-setup/copilot-3.png +0 -0
  257. package/docs/images/mcp-setup/mcp-json-1.png +0 -0
  258. package/docs/images/mcp-setup/mcp-json-2.png +0 -0
  259. package/docs/images/mcp-setup/qoder-1.png +0 -0
  260. package/docs/images/mcp-setup/qoder-2.png +0 -0
  261. package/docs/images/mcp-setup/roocode-1.png +0 -0
  262. package/docs/images/mcp-setup/roocode-2.png +0 -0
  263. package/docs/images/mcp-setup/trae-1.png +0 -0
  264. package/docs/images/mcp-setup/trae-2.png +0 -0
  265. package/docs/images/mcp-setup/trae-3.png +0 -0
  266. package/docs/images/mcp-setup/trae-4.png +0 -0
  267. package/docs/images/mcp-setup/trae-5.png +0 -0
  268. package/docs/images/mcp-setup/windsurf-1.png +0 -0
  269. package/docs/images/mcp-setup/windsurf-2.png +0 -0
  270. package/docs/insforge-instructions-sdk.md +93 -88
  271. package/docs/introduction.mdx +46 -45
  272. package/docs/logo/dark.svg +22 -22
  273. package/docs/logo/light.svg +20 -20
  274. package/docs/mcp-setup.mdx +332 -0
  275. package/docs/oauth-server.mdx +563 -0
  276. package/docs/partnership.mdx +720 -646
  277. package/docs/quickstart.mdx +82 -82
  278. package/docs/showcase.mdx +52 -52
  279. package/docs/snippets/sdk-installation.mdx +21 -21
  280. package/docs/snippets/service-icons.mdx +27 -27
  281. package/docs/vscode-extension.mdx +74 -0
  282. package/eslint.config.js +1 -0
  283. package/examples/oauth/frontend-oauth-example.html +250 -250
  284. package/examples/response-examples.md +443 -443
  285. package/frontend/components.json +17 -17
  286. package/frontend/package.json +69 -69
  287. package/frontend/src/App.tsx +8 -3
  288. package/frontend/src/assets/icons/checkbox_checked.svg +6 -6
  289. package/frontend/src/assets/icons/checkbox_undetermined.svg +6 -6
  290. package/frontend/src/assets/icons/checked.svg +3 -3
  291. package/frontend/src/assets/icons/connected.svg +3 -3
  292. package/frontend/src/assets/icons/error.svg +3 -3
  293. package/frontend/src/assets/icons/loader.svg +9 -9
  294. package/frontend/src/assets/icons/pencil.svg +4 -4
  295. package/frontend/src/assets/icons/refresh.svg +4 -4
  296. package/frontend/src/assets/icons/step_active.svg +3 -3
  297. package/frontend/src/assets/icons/step_inactive.svg +11 -11
  298. package/frontend/src/assets/icons/warning.svg +3 -3
  299. package/frontend/src/assets/logos/antigravity.svg +1 -0
  300. package/frontend/src/assets/logos/apple.svg +3 -3
  301. package/frontend/src/assets/logos/claude_code.svg +3 -3
  302. package/frontend/src/assets/logos/cline.svg +6 -6
  303. package/frontend/src/assets/logos/copilot.svg +10 -0
  304. package/frontend/src/assets/logos/cursor.svg +20 -20
  305. package/frontend/src/assets/logos/deepseek.svg +139 -0
  306. package/frontend/src/assets/logos/discord.svg +8 -8
  307. package/frontend/src/assets/logos/facebook.svg +3 -3
  308. package/frontend/src/assets/logos/gemini.svg +19 -19
  309. package/frontend/src/assets/logos/github.svg +5 -5
  310. package/frontend/src/assets/logos/google.svg +13 -13
  311. package/frontend/src/assets/logos/grok.svg +10 -10
  312. package/frontend/src/assets/logos/insforge_dark.svg +15 -15
  313. package/frontend/src/assets/logos/insforge_light.svg +15 -15
  314. package/frontend/src/assets/logos/instagram.svg +1 -1
  315. package/frontend/src/assets/logos/kiro.svg +9 -0
  316. package/frontend/src/assets/logos/linkedin.svg +3 -3
  317. package/frontend/src/assets/logos/openai.svg +10 -10
  318. package/frontend/src/assets/logos/qoder.svg +4 -0
  319. package/frontend/src/assets/logos/qwen.svg +15 -0
  320. package/frontend/src/assets/logos/roo_code.svg +9 -9
  321. package/frontend/src/assets/logos/spotify.svg +16 -16
  322. package/frontend/src/assets/logos/tiktok.svg +5 -5
  323. package/frontend/src/assets/logos/trae.svg +3 -3
  324. package/frontend/src/assets/logos/windsurf.svg +10 -10
  325. package/frontend/src/assets/logos/x.svg +3 -3
  326. package/frontend/src/components/CodeBlock.tsx +2 -2
  327. package/frontend/src/components/ConnectCTA.tsx +3 -2
  328. package/frontend/src/components/datagrid/DataGrid.tsx +90 -62
  329. package/frontend/src/components/datagrid/datagridTypes.tsx +2 -1
  330. package/frontend/src/components/datagrid/index.ts +1 -1
  331. package/frontend/src/components/index.ts +0 -1
  332. package/frontend/src/components/layout/AppHeader.tsx +13 -37
  333. package/frontend/src/components/layout/AppSidebar.tsx +85 -100
  334. package/frontend/src/components/layout/Layout.tsx +34 -32
  335. package/frontend/src/components/layout/PrimaryMenu.tsx +12 -4
  336. package/frontend/src/components/radix/Select.tsx +151 -151
  337. package/frontend/src/features/ai/components/AIConfigCard.tsx +200 -200
  338. package/frontend/src/features/ai/components/AIEmptyState.tsx +23 -23
  339. package/frontend/src/features/ai/components/ModalityFilterSidebar.tsx +102 -101
  340. package/frontend/src/features/ai/components/ModelSelectionDialog.tsx +135 -135
  341. package/frontend/src/features/ai/components/ModelSelectionGrid.tsx +51 -51
  342. package/frontend/src/features/ai/components/SystemPromptDialog.tsx +118 -118
  343. package/frontend/src/features/ai/components/index.ts +6 -6
  344. package/frontend/src/features/ai/helpers.ts +147 -141
  345. package/frontend/src/features/ai/{page → pages}/AIPage.tsx +166 -166
  346. package/frontend/src/features/auth/components/AuthPreview.tsx +96 -96
  347. package/frontend/src/features/auth/components/OAuthConfigDialog.tsx +1 -0
  348. package/frontend/src/features/auth/components/UsersDataGrid.tsx +61 -31
  349. package/frontend/src/features/auth/components/index.ts +5 -5
  350. package/frontend/src/features/auth/helpers.tsx +8 -0
  351. package/frontend/src/features/auth/{page → pages}/AuthMethodsPage.tsx +275 -275
  352. package/frontend/src/features/auth/{page → pages}/UsersPage.tsx +0 -28
  353. package/frontend/src/features/dashboard/{page → pages}/DashboardPage.tsx +1 -1
  354. package/frontend/src/features/database/components/DatabaseDataGrid.tsx +0 -2
  355. package/frontend/src/features/database/components/ForeignKeyCell.tsx +38 -11
  356. package/frontend/src/features/database/components/ForeignKeyPopover.tsx +18 -8
  357. package/frontend/src/features/database/components/LinkRecordModal.tsx +61 -13
  358. package/frontend/src/features/database/components/RecordFormField.tsx +1 -1
  359. package/frontend/src/features/database/components/SQLModal.tsx +75 -0
  360. package/frontend/src/features/database/components/TableForm.tsx +0 -4
  361. package/frontend/src/features/database/components/TableSidebar.tsx +0 -3
  362. package/frontend/src/features/database/components/TablesEmptyState.tsx +1 -1
  363. package/frontend/src/features/database/components/TemplatePreview.tsx +1 -2
  364. package/frontend/src/features/database/constants.ts +16 -28
  365. package/frontend/src/features/database/hooks/useCSVImport.ts +3 -2
  366. package/frontend/src/features/database/hooks/useDatabase.ts +66 -0
  367. package/frontend/src/features/database/hooks/useRawSQL.ts +3 -2
  368. package/frontend/src/features/database/hooks/useTables.ts +30 -28
  369. package/frontend/src/features/database/index.ts +1 -0
  370. package/frontend/src/features/database/{page → pages}/FunctionsPage.tsx +29 -42
  371. package/frontend/src/features/database/{page → pages}/IndexesPage.tsx +34 -51
  372. package/frontend/src/features/database/{page → pages}/PoliciesPage.tsx +42 -58
  373. package/frontend/src/features/database/{page → pages}/SQLEditorPage.tsx +2 -2
  374. package/frontend/src/features/database/{page → pages}/TablesPage.tsx +0 -42
  375. package/frontend/src/features/database/{page → pages}/TriggersPage.tsx +34 -51
  376. package/frontend/src/features/database/services/advance.service.ts +1 -41
  377. package/frontend/src/features/database/services/database.service.ts +55 -0
  378. package/frontend/src/features/database/services/record.service.ts +4 -20
  379. package/frontend/src/features/database/services/table.service.ts +1 -10
  380. package/frontend/src/features/database/templates/ai-chatbot.ts +6 -6
  381. package/frontend/src/features/database/templates/ecommerce-platform.ts +2 -2
  382. package/frontend/src/features/database/templates/instagram-clone.ts +10 -10
  383. package/frontend/src/features/database/templates/notion-clone.ts +8 -8
  384. package/frontend/src/features/database/templates/reddit-clone.ts +10 -10
  385. package/frontend/src/features/deployments/components/DeploymentRow.tsx +93 -0
  386. package/frontend/src/features/deployments/components/DeploymentsEmptyState.tsx +15 -0
  387. package/frontend/src/features/deployments/hooks/useDeployments.ts +157 -0
  388. package/frontend/src/features/deployments/pages/DeploymentsPage.tsx +318 -0
  389. package/frontend/src/features/deployments/services/deployments.service.ts +63 -0
  390. package/frontend/src/features/functions/components/FunctionRow.tsx +72 -72
  391. package/frontend/src/features/functions/components/FunctionsSidebar.tsx +56 -56
  392. package/frontend/src/features/functions/components/SecretRow.tsx +3 -3
  393. package/frontend/src/features/functions/components/index.ts +5 -5
  394. package/frontend/src/features/functions/hooks/useFunctions.ts +5 -4
  395. package/frontend/src/features/functions/hooks/useSecrets.ts +6 -9
  396. package/frontend/src/features/functions/{page → pages}/FunctionsPage.tsx +21 -44
  397. package/frontend/src/features/functions/{page → pages}/SecretsPage.tsx +118 -116
  398. package/frontend/src/features/functions/services/function.service.ts +8 -25
  399. package/frontend/src/features/functions/services/secret.service.ts +23 -41
  400. package/frontend/src/features/login/{page → pages}/CloudLoginPage.tsx +125 -118
  401. package/frontend/src/features/logs/components/LogDetailPanel.tsx +41 -0
  402. package/frontend/src/features/logs/components/LogsDataGrid.tsx +32 -1
  403. package/frontend/src/features/logs/components/index.ts +1 -0
  404. package/frontend/src/features/logs/hooks/useMcpUsage.ts +13 -66
  405. package/frontend/src/features/logs/{page → pages}/LogsPage.tsx +36 -6
  406. package/frontend/src/features/onboard/components/ApiCredentialsSection.tsx +59 -0
  407. package/frontend/src/features/onboard/components/ConnectionStringSection.tsx +180 -0
  408. package/frontend/src/features/onboard/components/McpConnectionSection.tsx +159 -0
  409. package/frontend/src/features/onboard/components/OnboardingController.tsx +68 -0
  410. package/frontend/src/features/onboard/components/OnboardingModal.tsx +121 -267
  411. package/frontend/src/features/onboard/components/ShowPasswordButton.tsx +21 -0
  412. package/frontend/src/features/onboard/components/index.ts +9 -4
  413. package/frontend/src/features/onboard/components/mcp/CursorDeeplinkGenerator.tsx +1 -1
  414. package/frontend/src/features/onboard/components/mcp/QoderDeeplinkGenerator.tsx +36 -0
  415. package/frontend/src/features/onboard/components/mcp/helpers.tsx +123 -98
  416. package/frontend/src/features/onboard/components/mcp/index.ts +4 -3
  417. package/frontend/src/features/onboard/index.ts +17 -13
  418. package/frontend/src/features/realtime/components/ChannelRow.tsx +83 -0
  419. package/frontend/src/features/realtime/components/EditChannelModal.tsx +246 -0
  420. package/frontend/src/features/realtime/components/MessageRow.tsx +85 -0
  421. package/frontend/src/features/realtime/components/RealtimeEmptyState.tsx +30 -0
  422. package/frontend/src/features/realtime/hooks/useRealtime.ts +218 -0
  423. package/frontend/src/features/realtime/index.ts +11 -0
  424. package/frontend/src/features/realtime/pages/RealtimeChannelsPage.tsx +172 -0
  425. package/frontend/src/features/realtime/pages/RealtimeMessagesPage.tsx +211 -0
  426. package/frontend/src/features/realtime/pages/RealtimePermissionsPage.tsx +191 -0
  427. package/frontend/src/features/realtime/services/realtime.service.ts +107 -0
  428. package/frontend/src/features/settings/pages/SettingsPage.tsx +349 -0
  429. package/frontend/src/features/storage/{page → pages}/StoragePage.tsx +1 -29
  430. package/frontend/src/features/visualizer/components/AuthNode.tsx +4 -4
  431. package/frontend/src/features/visualizer/components/SchemaVisualizer.tsx +24 -11
  432. package/frontend/src/features/visualizer/{page → pages}/VisualizerPage.tsx +11 -36
  433. package/frontend/src/index.css +249 -249
  434. package/frontend/src/lib/contexts/ModalContext.tsx +35 -0
  435. package/frontend/src/lib/contexts/SocketContext.tsx +119 -75
  436. package/frontend/src/lib/hooks/useMetadata.ts +45 -1
  437. package/frontend/src/lib/hooks/useModal.tsx +2 -0
  438. package/frontend/src/lib/routing/AppRoutes.tsx +103 -84
  439. package/frontend/src/lib/services/metadata.service.ts +20 -3
  440. package/frontend/src/lib/utils/cloudMessaging.ts +1 -1
  441. package/frontend/src/lib/utils/menuItems.ts +223 -183
  442. package/frontend/src/lib/utils/utils.ts +196 -183
  443. package/frontend/tsconfig.json +25 -25
  444. package/frontend/tsconfig.node.json +9 -9
  445. package/functions/deno.json +24 -24
  446. package/functions/server.ts +6 -6
  447. package/functions/worker-template.js +1 -1
  448. package/i18n/README.ar.md +130 -130
  449. package/i18n/README.de.md +130 -130
  450. package/i18n/README.es.md +154 -154
  451. package/i18n/README.fr.md +134 -134
  452. package/i18n/README.hi.md +129 -129
  453. package/i18n/README.ja.md +174 -174
  454. package/i18n/README.ko.md +136 -136
  455. package/i18n/README.pt-BR.md +131 -131
  456. package/i18n/README.ru.md +129 -129
  457. package/i18n/README.zh-CN.md +133 -133
  458. package/openapi/ai.yaml +825 -715
  459. package/openapi/auth.yaml +1324 -1244
  460. package/openapi/email.yaml +158 -0
  461. package/openapi/functions.yaml +475 -475
  462. package/openapi/health.yaml +29 -29
  463. package/openapi/logs.yaml +221 -223
  464. package/openapi/metadata.yaml +175 -177
  465. package/openapi/realtime.yaml +699 -0
  466. package/openapi/records.yaml +381 -381
  467. package/openapi/secrets.yaml +370 -370
  468. package/openapi/storage.yaml +875 -875
  469. package/openapi/tables.yaml +462 -463
  470. package/package.json +97 -97
  471. package/shared-schemas/package.json +31 -31
  472. package/shared-schemas/src/ai-api.schema.ts +251 -143
  473. package/shared-schemas/src/ai.schema.ts +8 -4
  474. package/shared-schemas/src/auth-api.schema.ts +380 -339
  475. package/shared-schemas/src/auth.schema.ts +18 -11
  476. package/shared-schemas/src/cloud-events.schema.ts +26 -0
  477. package/shared-schemas/src/database-api.schema.ts +32 -1
  478. package/shared-schemas/src/database.schema.ts +39 -0
  479. package/shared-schemas/src/deployments-api.schema.ts +55 -0
  480. package/shared-schemas/src/deployments.schema.ts +30 -0
  481. package/shared-schemas/src/docs.schema.ts +32 -0
  482. package/shared-schemas/src/email-api.schema.ts +30 -0
  483. package/shared-schemas/src/functions-api.schema.ts +13 -4
  484. package/shared-schemas/src/functions.schema.ts +1 -1
  485. package/shared-schemas/src/index.ts +22 -14
  486. package/shared-schemas/src/metadata.schema.ts +39 -4
  487. package/shared-schemas/src/realtime-api.schema.ts +111 -0
  488. package/shared-schemas/src/realtime.schema.ts +143 -0
  489. package/shared-schemas/src/secrets-api.schema.ts +44 -0
  490. package/shared-schemas/src/secrets.schema.ts +15 -0
  491. package/shared-schemas/tsconfig.json +21 -21
  492. package/tsconfig.json +7 -7
  493. package/zeabur/README.md +26 -13
  494. package/zeabur/template.yml +1001 -1032
  495. package/.cursor/rules/cursor-rules.mdc +0 -94
  496. package/backend/src/types/profile.ts +0 -55
  497. package/frontend/src/components/ProjectInfoModal.tsx +0 -128
  498. package/frontend/src/features/database/hooks/useFullMetadata.ts +0 -18
  499. package/test-gemini.sh +0 -35
  500. package/test-usage-admin.sh +0 -57
  501. package/test-usage.sh +0 -50
  502. /package/frontend/src/features/auth/{page → pages}/ConfigurationPage.tsx +0 -0
  503. /package/frontend/src/features/database/{page → pages}/TemplatesPage.tsx +0 -0
  504. /package/frontend/src/features/login/{page → pages}/LoginPage.tsx +0 -0
  505. /package/frontend/src/features/logs/{page → pages}/AuditsPage.tsx +0 -0
  506. /package/frontend/src/features/logs/{page → pages}/MCPLogsPage.tsx +0 -0
@@ -1,4 +1,4 @@
1
- import { useMemo } from 'react';
1
+ import { useMemo, useCallback } from 'react';
2
2
  import {
3
3
  DataGrid,
4
4
  type DataGridProps,
@@ -6,6 +6,7 @@ import {
6
6
  type DataGridColumn,
7
7
  type DataGridRowType,
8
8
  } from '@/components/datagrid';
9
+ import type { CellClickArgs, CellMouseEvent } from 'react-data-grid';
9
10
 
10
11
  // Column definition type for LogsDataGrid
11
12
  export interface LogsColumnDef {
@@ -52,6 +53,9 @@ export interface LogsDataGridProps<T = Record<string, unknown>>
52
53
  columnDefs: LogsColumnDef[];
53
54
  data: T[];
54
55
  noPadding?: boolean;
56
+ selectedRowId?: string | null;
57
+ onRowClick?: (row: T) => void;
58
+ rightPanel?: React.ReactNode;
55
59
  }
56
60
 
57
61
  // Specialized DataGrid for logs
@@ -59,6 +63,9 @@ export function LogsDataGrid<T = Record<string, unknown>>({
59
63
  columnDefs,
60
64
  data,
61
65
  noPadding,
66
+ selectedRowId,
67
+ onRowClick,
68
+ rightPanel,
62
69
  ...restProps
63
70
  }: LogsDataGridProps<T>) {
64
71
  const columns = useMemo(() => {
@@ -76,6 +83,27 @@ export function LogsDataGrid<T = Record<string, unknown>>({
76
83
  }) as DataGridRowType[];
77
84
  }, [data]);
78
85
 
86
+ // Handle cell click to trigger row click
87
+ const handleCellClick = useCallback(
88
+ (args: CellClickArgs<DataGridRowType>, _event: CellMouseEvent) => {
89
+ if (onRowClick) {
90
+ onRowClick(args.row as T);
91
+ }
92
+ },
93
+ [onRowClick]
94
+ );
95
+
96
+ // Row class for highlighting selected row
97
+ const rowClass = useCallback(
98
+ (row: DataGridRowType) => {
99
+ if (selectedRowId && row.id === selectedRowId) {
100
+ return 'bg-gray-200 dark:bg-neutral-700';
101
+ }
102
+ return '';
103
+ },
104
+ [selectedRowId]
105
+ );
106
+
79
107
  return (
80
108
  <DataGrid<DataGridRowType>
81
109
  {...restProps}
@@ -84,6 +112,9 @@ export function LogsDataGrid<T = Record<string, unknown>>({
84
112
  showSelection={false}
85
113
  showPagination={true}
86
114
  noPadding={noPadding}
115
+ onCellClick={handleCellClick}
116
+ rowClass={rowClass}
117
+ rightPanel={rightPanel}
87
118
  />
88
119
  );
89
120
  }
@@ -1,2 +1,3 @@
1
1
  export { createLogsColumns, type LogsColumnDef } from './LogsDataGrid';
2
2
  export { SeverityBadge } from './SeverityBadge';
3
+ export { LogDetailPanel } from './LogDetailPanel';
@@ -1,40 +1,27 @@
1
- import { useCallback, useMemo, useEffect, useRef, useState } from 'react';
2
- import { useQuery, useQueryClient } from '@tanstack/react-query';
3
- import { useSocket, ServerEvents } from '@/lib/contexts/SocketContext';
1
+ import { useMemo, useEffect, useRef, useState } from 'react';
2
+ import { useQuery } from '@tanstack/react-query';
4
3
  import { useAuth } from '@/lib/contexts/AuthContext';
5
4
  import { usageService, McpUsageRecord } from '@/features/logs/services/usage.service';
6
5
  import { isInsForgeCloudProject } from '@/lib/utils/utils';
7
- import { LOGS_PAGE_SIZE } from '../helpers';
8
6
  import { postMessageToParent } from '@/lib/utils/cloudMessaging';
9
-
10
- // ============================================================================
11
- // Types
12
- // ============================================================================
13
-
14
- export interface McpConnectedPayload {
15
- tool_name: string;
16
- created_at: string;
17
- }
7
+ import { LOGS_PAGE_SIZE } from '../helpers';
18
8
 
19
9
  // ============================================================================
20
10
  // Main Hook
21
11
  // ============================================================================
22
12
 
23
13
  /**
24
- * Hook to manage MCP usage data and real-time updates
14
+ * Hook to manage MCP usage data
25
15
  *
26
16
  * Features:
27
- * - Fetches initial MCP logs from backend
28
- * - Listens to real-time socket updates for new MCP calls
29
- * - Invalidates queries on WebSocket events to refetch latest data
17
+ * - Fetches MCP logs from backend
30
18
  * - Provides helper functions for data access
31
- * - Handles parent window communication for onboarding (if in iframe)
19
+ * - Handles initial parent window notification for onboarding (if in iframe)
32
20
  * - Supports search and pagination
21
+ *
33
22
  */
34
23
  export function useMcpUsage() {
35
24
  // Hooks
36
- const queryClient = useQueryClient();
37
- const { socket, isConnected } = useSocket();
38
25
  const { isAuthenticated } = useAuth();
39
26
 
40
27
  // State
@@ -100,54 +87,14 @@ export function useMcpUsage() {
100
87
  hasNotifiedInitialStatus.current = true;
101
88
 
102
89
  const latestRecord = records[0];
103
- window.parent.postMessage(
104
- {
105
- type: 'MCP_CONNECTION_STATUS',
106
- connected: true,
107
- tool_name: latestRecord.tool_name,
108
- timestamp: latestRecord.created_at,
109
- },
110
- '*'
111
- );
90
+ postMessageToParent({
91
+ type: 'MCP_CONNECTION_STATUS',
92
+ connected: true,
93
+ tool_name: latestRecord.tool_name,
94
+ timestamp: latestRecord.created_at,
95
+ });
112
96
  }, [isLoading, records]);
113
97
 
114
- // Handle real-time MCP connection events from socket
115
- const handleMcpConnected = useCallback(
116
- (data: { id: string; payload: McpConnectedPayload; timestamp: number; type: string }) => {
117
- // Notify parent window with latest MCP call info
118
- if (window.parent !== window) {
119
- window.parent.postMessage(
120
- {
121
- type: 'MCP_CONNECTION_STATUS',
122
- connected: true,
123
- tool_name: data.payload.tool_name,
124
- timestamp: data.payload.created_at,
125
- },
126
- '*'
127
- );
128
- if (!records.length) {
129
- postMessageToParent({ type: 'ONBOARDING_SUCCESS' });
130
- }
131
- }
132
- // Invalidate query to refetch latest data (follows codebase pattern)
133
- void queryClient.invalidateQueries({ queryKey: ['mcp-usage'] });
134
- },
135
- [queryClient, records.length]
136
- );
137
-
138
- // Subscribe to socket MCP connection events
139
- useEffect(() => {
140
- if (!socket || !isConnected) {
141
- return;
142
- }
143
-
144
- socket.on(ServerEvents.MCP_CONNECTED, handleMcpConnected);
145
-
146
- return () => {
147
- socket.off(ServerEvents.MCP_CONNECTED, handleMcpConnected);
148
- };
149
- }, [socket, isConnected, handleMcpConnected]);
150
-
151
98
  // Computed values
152
99
  const hasCompletedOnboarding = useMemo(() => !!records.length, [records]);
153
100
  const recordsCount = useMemo(() => records.length, [records]);
@@ -1,4 +1,4 @@
1
- import { useMemo } from 'react';
1
+ import { useMemo, useState, useCallback, useEffect } from 'react';
2
2
  import { useParams } from 'react-router-dom';
3
3
  import { ChevronDown } from 'lucide-react';
4
4
  import { useLogs } from '../hooks/useLogs';
@@ -13,6 +13,7 @@ import {
13
13
  } from '@/components';
14
14
  import { LogsDataGrid, type LogsColumnDef } from '../components/LogsDataGrid';
15
15
  import { SeverityBadge } from '../components/SeverityBadge';
16
+ import { LogDetailPanel } from '../components/LogDetailPanel';
16
17
  import { SEVERITY_OPTIONS, LOGS_PAGE_SIZE } from '../helpers';
17
18
  import { formatTime } from '@/lib/utils/utils';
18
19
  import { LogSchema } from '@insforge/shared-schemas';
@@ -21,6 +22,9 @@ export default function LogsPage() {
21
22
  // Get the source from the URL params
22
23
  const { source = 'insforge.logs' } = useParams<{ source?: string }>();
23
24
 
25
+ // Selected log state for detail panel
26
+ const [selectedLog, setSelectedLog] = useState<LogSchema | null>(null);
27
+
24
28
  const {
25
29
  logs: paginatedLogs,
26
30
  filteredLogs,
@@ -36,12 +40,29 @@ export default function LogsPage() {
36
40
  getSeverity,
37
41
  } = useLogs(source);
38
42
 
43
+ // Close detail panel when switching log sources or changing filters
44
+ useEffect(() => {
45
+ setSelectedLog(null);
46
+ }, [source, severityFilter]);
47
+
48
+ // Handle row click to show log details
49
+ const handleRowClick = useCallback((log: LogSchema) => {
50
+ setSelectedLog(log);
51
+ }, []);
52
+
53
+ // Handle closing the detail panel
54
+ const handleClosePanel = useCallback(() => {
55
+ setSelectedLog(null);
56
+ }, []);
57
+
58
+ // Adjust column widths based on panel state
39
59
  const logsColumns: LogsColumnDef[] = useMemo(
40
60
  () => [
41
61
  {
42
62
  key: 'event_message',
43
63
  name: 'Logs',
44
- width: '10fr',
64
+ width: selectedLog ? '1fr' : '5fr',
65
+ minWidth: 200,
45
66
  renderCell: ({ row }) => (
46
67
  <p className="text-sm text-gray-900 dark:text-white font-normal leading-6 truncate">
47
68
  {String(row.eventMessage ?? '')}
@@ -51,7 +72,7 @@ export default function LogsPage() {
51
72
  {
52
73
  key: 'severity',
53
74
  name: 'Severity',
54
- width: '120px',
75
+ width: '100px',
55
76
  renderCell: ({ row }) => (
56
77
  <SeverityBadge severity={getSeverity(row as unknown as LogSchema)} />
57
78
  ),
@@ -59,7 +80,7 @@ export default function LogsPage() {
59
80
  {
60
81
  key: 'timestamp',
61
82
  name: 'Time',
62
- width: 'minmax(200px, 1fr)',
83
+ width: '200px',
63
84
  renderCell: ({ row }) => (
64
85
  <p className="text-sm text-gray-900 dark:text-white font-normal leading-6 flex-1">
65
86
  {formatTime(String(row.timestamp ?? ''))}
@@ -67,7 +88,7 @@ export default function LogsPage() {
67
88
  ),
68
89
  },
69
90
  ],
70
- [getSeverity]
91
+ [getSeverity, selectedLog]
71
92
  );
72
93
 
73
94
  return (
@@ -121,7 +142,7 @@ export default function LogsPage() {
121
142
  </div>
122
143
  </div>
123
144
 
124
- {/* Table with Pagination */}
145
+ {/* Table with Detail Panel */}
125
146
  <div className="flex-1 overflow-hidden">
126
147
  {logsError ? (
127
148
  <div className="flex items-center justify-center h-full">
@@ -137,6 +158,15 @@ export default function LogsPage() {
137
158
  pageSize={LOGS_PAGE_SIZE}
138
159
  totalRecords={filteredLogs.length}
139
160
  onPageChange={setCurrentPage}
161
+ selectedRowId={selectedLog?.id ?? null}
162
+ onRowClick={handleRowClick}
163
+ rightPanel={
164
+ selectedLog && (
165
+ <div className="w-[480px] h-full shrink-0">
166
+ <LogDetailPanel log={selectedLog} onClose={handleClosePanel} />
167
+ </div>
168
+ )
169
+ }
140
170
  emptyState={
141
171
  <div className="text-sm text-zinc-500 dark:text-zinc-400">
142
172
  {logsSearchQuery || severityFilter.length < 3
@@ -0,0 +1,59 @@
1
+ import { CopyButton } from '@/components';
2
+ import { cn } from '@/lib/utils/utils';
3
+
4
+ interface CredentialRowProps {
5
+ label: string;
6
+ value: string;
7
+ isLoading?: boolean;
8
+ }
9
+
10
+ function CredentialRow({ label, value, isLoading = false }: CredentialRowProps) {
11
+ return (
12
+ <div className="flex items-center gap-4 min-w-0">
13
+ <span className="text-gray-900 dark:text-white text-sm leading-6 w-25 shrink-0">{label}</span>
14
+ <div
15
+ className={cn(
16
+ 'flex-1 h-9 min-w-0 flex items-center justify-between gap-2 bg-white dark:bg-neutral-900 border border-gray-200 dark:border-neutral-700 rounded-lg px-3 py-2',
17
+ isLoading && 'animate-pulse'
18
+ )}
19
+ >
20
+ <span className="text-gray-900 dark:text-white text-sm truncate min-w-0 flex-1">
21
+ {value}
22
+ </span>
23
+ <CopyButton
24
+ text={value}
25
+ disabled={isLoading}
26
+ showText={false}
27
+ className="h-6 w-6 p-1 min-w-0 shrink-0 text-black dark:text-white bg-white dark:bg-neutral-700 hover:bg-neutral-100 dark:hover:bg-neutral-600 border-none"
28
+ />
29
+ </div>
30
+ </div>
31
+ );
32
+ }
33
+
34
+ interface ApiCredentialsSectionProps {
35
+ apiKey: string;
36
+ appUrl: string;
37
+ isLoading?: boolean;
38
+ className?: string;
39
+ }
40
+
41
+ export function ApiCredentialsSection({
42
+ apiKey,
43
+ appUrl,
44
+ isLoading = false,
45
+ className,
46
+ }: ApiCredentialsSectionProps) {
47
+ return (
48
+ <div className={cn('flex flex-col gap-6', className)}>
49
+ <p className="text-gray-500 dark:text-neutral-400 text-base leading-7">
50
+ Use the project URL and API key to connect directly via REST API or any HTTP client.
51
+ </p>
52
+
53
+ <div className="flex flex-col gap-4">
54
+ <CredentialRow label="Project URL" value={appUrl} isLoading={isLoading} />
55
+ <CredentialRow label="API Key" value={apiKey} isLoading={isLoading} />
56
+ </div>
57
+ </div>
58
+ );
59
+ }
@@ -0,0 +1,180 @@
1
+ import { useState, useCallback, useRef, useEffect, useMemo } from 'react';
2
+ import { CopyButton, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components';
3
+ import { ShowPasswordButton } from './ShowPasswordButton';
4
+ import { useDatabaseConnectionString, useDatabasePassword } from '@/lib/hooks/useMetadata';
5
+ import { cn } from '@/lib/utils/utils';
6
+
7
+ interface ParameterRowProps {
8
+ label: string;
9
+ value: string | number | undefined;
10
+ copyValue?: string;
11
+ }
12
+
13
+ const RESET_TIMEOUT_MS = 2000;
14
+
15
+ function ParameterRow({ label, value, copyValue }: ParameterRowProps) {
16
+ const [copied, setCopied] = useState(false);
17
+ const timeoutRef = useRef<NodeJS.Timeout | null>(null);
18
+
19
+ const textToCopy = copyValue ?? String(value ?? '');
20
+ const displayValue = value ?? '-';
21
+ const hasCopyableValue = value !== undefined && value !== null && value !== '';
22
+
23
+ useEffect(() => {
24
+ return () => {
25
+ if (timeoutRef.current) {
26
+ clearTimeout(timeoutRef.current);
27
+ }
28
+ };
29
+ }, []);
30
+
31
+ const handleCopy = useCallback(() => {
32
+ if (!hasCopyableValue) {
33
+ return;
34
+ }
35
+
36
+ if (timeoutRef.current) {
37
+ clearTimeout(timeoutRef.current);
38
+ }
39
+
40
+ navigator.clipboard
41
+ .writeText(textToCopy)
42
+ .then(() => {
43
+ setCopied(true);
44
+ timeoutRef.current = setTimeout(() => {
45
+ setCopied(false);
46
+ timeoutRef.current = null;
47
+ }, RESET_TIMEOUT_MS);
48
+ })
49
+ .catch((error) => {
50
+ console.error('Failed to copy to clipboard:', error);
51
+ });
52
+ }, [hasCopyableValue, textToCopy]);
53
+
54
+ return (
55
+ <div className="group flex items-center gap-2">
56
+ <span className="text-gray-400 dark:text-neutral-500 text-sm">{label}:</span>
57
+ <TooltipProvider>
58
+ <Tooltip open={copied}>
59
+ <TooltipTrigger asChild>
60
+ <button
61
+ type="button"
62
+ className={cn(
63
+ 'text-gray-700 dark:text-neutral-300 text-sm',
64
+ hasCopyableValue &&
65
+ 'cursor-pointer hover:text-gray-900 dark:hover:text-neutral-100 transition-colors'
66
+ )}
67
+ disabled={!hasCopyableValue}
68
+ aria-label={`Copy ${label}`}
69
+ onClick={handleCopy}
70
+ >
71
+ {displayValue}
72
+ </button>
73
+ </TooltipTrigger>
74
+ <TooltipContent side="top" sideOffset={4}>
75
+ <p className="font-medium text-xs leading-5">Copied</p>
76
+ </TooltipContent>
77
+ </Tooltip>
78
+ </TooltipProvider>
79
+ {hasCopyableValue && (
80
+ <CopyButton
81
+ text={textToCopy}
82
+ showText={false}
83
+ className="h-6 w-6 p-1 min-w-0 shrink-0 text-black dark:text-white bg-white dark:bg-neutral-700 hover:bg-neutral-100 dark:hover:bg-neutral-600 border-none opacity-0 group-hover:opacity-100 transition-opacity"
84
+ />
85
+ )}
86
+ </div>
87
+ );
88
+ }
89
+
90
+ interface ConnectionStringSectionProps {
91
+ className?: string;
92
+ }
93
+
94
+ export function ConnectionStringSection({ className }: ConnectionStringSectionProps) {
95
+ const [showConnectionPassword, setShowConnectionPassword] = useState(false);
96
+ const [showParamsPassword, setShowParamsPassword] = useState(false);
97
+
98
+ const { connectionData, isLoading: isConnectionLoading } = useDatabaseConnectionString();
99
+ const { passwordData } = useDatabasePassword();
100
+
101
+ const dbParams = connectionData?.parameters;
102
+ const dbPassword = passwordData?.databasePassword || '';
103
+ const maskedPassword = dbParams?.password || '********';
104
+
105
+ const connectionStringDisplay = useMemo(() => {
106
+ if (!connectionData?.connectionURL) {
107
+ return '';
108
+ }
109
+ if (showConnectionPassword && dbPassword) {
110
+ return connectionData.connectionURL.replace('********', dbPassword);
111
+ }
112
+ return connectionData.connectionURL;
113
+ }, [connectionData?.connectionURL, showConnectionPassword, dbPassword]);
114
+
115
+ const connectionStringClipboard = useMemo(() => {
116
+ if (!connectionData?.connectionURL || !dbPassword) {
117
+ return connectionData?.connectionURL || '';
118
+ }
119
+ return connectionData.connectionURL.replace('********', dbPassword);
120
+ }, [connectionData?.connectionURL, dbPassword]);
121
+
122
+ return (
123
+ <div className={cn('flex flex-col gap-6', isConnectionLoading && 'animate-pulse', className)}>
124
+ <p className="text-gray-500 dark:text-neutral-400 text-base leading-7">
125
+ Ideal for applications with persistent and long-lived connections, such as those running on
126
+ virtual machines or long-standing containers.
127
+ </p>
128
+
129
+ {/* Connection String */}
130
+ <div className="bg-gray-100 dark:bg-neutral-900 rounded p-3">
131
+ <div className="flex items-center justify-between mb-2">
132
+ <div className="bg-gray-200 dark:bg-neutral-700 rounded px-2 h-5 flex items-center justify-center">
133
+ <span className="text-gray-700 dark:text-neutral-50 text-xs">connection string</span>
134
+ </div>
135
+ <div className="flex items-center gap-2">
136
+ <ShowPasswordButton
137
+ show={showConnectionPassword}
138
+ onToggle={() => setShowConnectionPassword(!showConnectionPassword)}
139
+ />
140
+ <CopyButton
141
+ text={connectionStringClipboard}
142
+ showText={false}
143
+ className="h-6 w-6 p-1 min-w-0 shrink-0 text-black dark:text-white bg-white dark:bg-neutral-700 hover:bg-neutral-100 dark:hover:bg-neutral-600 border-none"
144
+ />
145
+ </div>
146
+ </div>
147
+ <p className="text-gray-700 dark:text-neutral-300 text-sm leading-6 break-words">
148
+ {connectionStringDisplay || 'Loading...'}
149
+ </p>
150
+ </div>
151
+
152
+ <div className="h-px bg-gray-200 dark:bg-neutral-700" />
153
+
154
+ {/* Parameters */}
155
+ <div className="bg-gray-100 dark:bg-neutral-900 rounded p-3">
156
+ <div className="flex items-center justify-between mb-4">
157
+ <div className="bg-gray-200 dark:bg-neutral-700 rounded px-2 h-5 flex items-center justify-center">
158
+ <span className="text-gray-700 dark:text-neutral-50 text-xs">parameters</span>
159
+ </div>
160
+ <ShowPasswordButton
161
+ show={showParamsPassword}
162
+ onToggle={() => setShowParamsPassword(!showParamsPassword)}
163
+ />
164
+ </div>
165
+ <div className="flex flex-col gap-3">
166
+ <ParameterRow label="HOST" value={dbParams?.host} />
167
+ <ParameterRow label="DATABASE" value={dbParams?.database} />
168
+ <ParameterRow label="USER" value={dbParams?.user} />
169
+ <ParameterRow label="PORT" value={dbParams?.port} />
170
+ <ParameterRow
171
+ label="PASSWORD"
172
+ value={showParamsPassword ? dbPassword || maskedPassword : maskedPassword}
173
+ copyValue={dbPassword || maskedPassword}
174
+ />
175
+ <ParameterRow label="SSL" value={dbParams?.sslmode} />
176
+ </div>
177
+ </div>
178
+ </div>
179
+ );
180
+ }
@@ -0,0 +1,159 @@
1
+ import { useState, useMemo } from 'react';
2
+ import { ChevronDown } from 'lucide-react';
3
+ import {
4
+ CodeBlock,
5
+ CopyButton,
6
+ DropdownMenu,
7
+ DropdownMenuContent,
8
+ DropdownMenuItem,
9
+ DropdownMenuTrigger,
10
+ } from '@/components';
11
+ import { CursorDeeplinkGenerator } from './mcp/CursorDeeplinkGenerator';
12
+ import { QoderDeeplinkGenerator } from './mcp/QoderDeeplinkGenerator';
13
+ import { MCP_AGENTS, GenerateInstallCommand, createMCPConfig, type MCPAgent } from './mcp/helpers';
14
+ import { cn } from '@/lib/utils/utils';
15
+
16
+ interface McpConnectionSectionProps {
17
+ apiKey: string;
18
+ appUrl: string;
19
+ isLoading?: boolean;
20
+ className?: string;
21
+ }
22
+
23
+ export function McpConnectionSection({
24
+ apiKey,
25
+ appUrl,
26
+ isLoading = false,
27
+ className,
28
+ }: McpConnectionSectionProps) {
29
+ const [selectedAgent, setSelectedAgent] = useState<MCPAgent>(MCP_AGENTS[0]);
30
+
31
+ const installCommand = useMemo(() => {
32
+ return GenerateInstallCommand(selectedAgent, apiKey);
33
+ }, [selectedAgent, apiKey]);
34
+
35
+ const mcpJsonConfig = useMemo(() => {
36
+ const config = createMCPConfig(apiKey, 'macos-linux', appUrl);
37
+ return JSON.stringify(config, null, 2);
38
+ }, [apiKey, appUrl]);
39
+
40
+ const testPrompt =
41
+ "I'm using InsForge as my backend platform, call InsForge MCP's fetch-docs tool to learn about InsForge instructions.";
42
+
43
+ return (
44
+ <div className={cn('flex flex-col gap-6', className)}>
45
+ <p className="text-gray-500 dark:text-neutral-400 text-base leading-7">
46
+ Install the MCP server so your coding agent can access and build the backend.
47
+ </p>
48
+
49
+ {/* Agent Selector Dropdown */}
50
+ <DropdownMenu>
51
+ <DropdownMenuTrigger asChild>
52
+ <button className="w-40 bg-gray-100 dark:bg-[rgba(0,0,0,0.12)] border border-gray-300 dark:border-[rgba(255,255,255,0.24)] rounded flex items-center justify-between px-2 py-1 cursor-pointer">
53
+ <div className="flex items-center gap-2">
54
+ {selectedAgent.logo && (
55
+ <div className="w-6 h-6 flex items-center justify-center">{selectedAgent.logo}</div>
56
+ )}
57
+ <span className="text-gray-900 dark:text-white text-sm font-medium">
58
+ {selectedAgent.displayName}
59
+ </span>
60
+ </div>
61
+ <ChevronDown className="w-5 h-5 text-gray-400 dark:text-neutral-400" />
62
+ </button>
63
+ </DropdownMenuTrigger>
64
+ <DropdownMenuContent
65
+ align="start"
66
+ className="w-40 bg-white dark:bg-neutral-800 border border-gray-200 dark:border-neutral-700 rounded shadow-lg p-0"
67
+ >
68
+ {MCP_AGENTS.map((agent) => (
69
+ <DropdownMenuItem
70
+ key={agent.id}
71
+ onSelect={() => setSelectedAgent(agent)}
72
+ className="flex items-center gap-2 px-2 py-2 text-gray-900 dark:text-white text-sm hover:bg-gray-100 dark:hover:bg-neutral-700 cursor-pointer"
73
+ >
74
+ {agent.logo && (
75
+ <div className="w-6 h-6 flex items-center justify-center">{agent.logo}</div>
76
+ )}
77
+ <span className="font-medium">{agent.displayName}</span>
78
+ </DropdownMenuItem>
79
+ ))}
80
+ </DropdownMenuContent>
81
+ </DropdownMenu>
82
+
83
+ {/* Step 1 - Conditional based on agent */}
84
+ {selectedAgent.id === 'cursor' ? (
85
+ <div className="flex flex-col gap-3">
86
+ <p className="text-gray-900 dark:text-white text-sm">
87
+ <span className="font-semibold leading-5">1.</span>
88
+ <span className="leading-6"> Install in one click</span>
89
+ </p>
90
+ <div className="w-fit">
91
+ <CursorDeeplinkGenerator apiKey={apiKey} os="macos-linux" />
92
+ </div>
93
+ </div>
94
+ ) : selectedAgent.id === 'qoder' ? (
95
+ <div className="flex flex-col gap-3">
96
+ <p className="text-gray-900 dark:text-white text-sm">
97
+ <span className="font-semibold leading-5">1.</span>
98
+ <span className="leading-6"> Install in one click</span>
99
+ </p>
100
+ <div className="w-fit">
101
+ <QoderDeeplinkGenerator apiKey={apiKey} os="macos-linux" />
102
+ </div>
103
+ </div>
104
+ ) : selectedAgent.id === 'mcp' ? (
105
+ <div className="flex flex-col gap-3">
106
+ <p className="text-gray-900 dark:text-white text-sm">
107
+ <span className="font-semibold leading-5">1.</span>
108
+ <span className="leading-6">
109
+ {' '}
110
+ Copy the configuration below and add it to your AI assistant.
111
+ </span>
112
+ </p>
113
+ <div className="bg-gray-100 dark:bg-neutral-900 rounded overflow-hidden flex flex-col h-[320px] w-full">
114
+ {/* Header - fixed at top */}
115
+ <div className="bg-gray-100 dark:bg-neutral-900 flex items-center justify-between p-3">
116
+ <div className="bg-gray-200 dark:bg-neutral-700 rounded px-2">
117
+ <span className="text-gray-700 dark:text-neutral-50 text-xs">
118
+ MCP Configuration
119
+ </span>
120
+ </div>
121
+ <CopyButton
122
+ text={mcpJsonConfig}
123
+ showText={false}
124
+ className="h-6 w-6 p-1 bg-white dark:bg-neutral-700 hover:bg-neutral-100 dark:hover:bg-neutral-600 border-none rounded-md shadow-sm min-w-0 text-black dark:text-white"
125
+ />
126
+ </div>
127
+ {/* Scrollable content */}
128
+ <div className="flex-1 overflow-auto p-3">
129
+ <pre className="text-gray-700 dark:text-neutral-300 text-sm leading-6 m-0 whitespace-pre-wrap break-all">
130
+ <code>{mcpJsonConfig}</code>
131
+ </pre>
132
+ </div>
133
+ </div>
134
+ </div>
135
+ ) : (
136
+ <div className="flex flex-col gap-3">
137
+ <p className="text-gray-900 dark:text-white text-sm">
138
+ <span className="font-semibold leading-5">1.</span>
139
+ <span className="leading-6"> Install in one click</span>
140
+ </p>
141
+ <CodeBlock
142
+ code={installCommand}
143
+ label="Terminal Command"
144
+ className={cn(isLoading && 'animate-pulse')}
145
+ />
146
+ </div>
147
+ )}
148
+
149
+ {/* Step 2 */}
150
+ <div className="flex flex-col gap-3">
151
+ <p className="text-gray-900 dark:text-white text-sm">
152
+ <span className="font-semibold leading-5">2.</span>
153
+ <span className="leading-6"> Check for connection using this prompt</span>
154
+ </p>
155
+ <CodeBlock code={testPrompt} label="prompt" className="bg-gray-100 dark:bg-neutral-900" />
156
+ </div>
157
+ </div>
158
+ );
159
+ }