insforge 1.2.10 → 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 (335) 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 +44 -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 +28 -28
  25. package/auth/src/lib/broadcastService.ts +117 -115
  26. package/auth/src/pages/SignInPage.tsx +60 -57
  27. package/auth/src/pages/SignUpPage.tsx +60 -57
  28. package/auth/tsconfig.json +32 -32
  29. package/auth/tsconfig.node.json +11 -11
  30. package/backend/package.json +78 -75
  31. package/backend/src/api/routes/ai/index.routes.ts +3 -3
  32. package/backend/src/api/routes/auth/index.routes.ts +667 -570
  33. package/backend/src/api/routes/auth/oauth.routes.ts +473 -448
  34. package/backend/src/api/routes/database/advance.routes.ts +37 -16
  35. package/backend/src/api/routes/database/index.routes.ts +78 -1
  36. package/backend/src/api/routes/database/records.routes.ts +10 -10
  37. package/backend/src/api/routes/database/tables.routes.ts +0 -14
  38. package/backend/src/api/routes/docs/index.routes.ts +75 -76
  39. package/backend/src/api/routes/email/index.routes.ts +35 -0
  40. package/backend/src/api/routes/functions/index.routes.ts +18 -12
  41. package/backend/src/api/routes/metadata/index.routes.ts +12 -0
  42. package/backend/src/api/routes/realtime/channels.routes.ts +81 -0
  43. package/backend/src/api/routes/realtime/index.routes.ts +12 -0
  44. package/backend/src/api/routes/realtime/messages.routes.ts +48 -0
  45. package/backend/src/api/routes/realtime/permissions.routes.ts +19 -0
  46. package/backend/src/api/routes/storage/index.routes.ts +18 -12
  47. package/backend/src/api/routes/usage/index.routes.ts +6 -4
  48. package/backend/src/infra/database/database.manager.ts +14 -1
  49. package/backend/src/infra/database/migrations/000_create-base-tables.sql +141 -141
  50. package/backend/src/infra/database/migrations/001_create-helper-functions.sql +40 -40
  51. package/backend/src/infra/database/migrations/002_rename-auth-tables.sql +29 -29
  52. package/backend/src/infra/database/migrations/003_create-users-table.sql +55 -55
  53. package/backend/src/infra/database/migrations/004_add-reload-postgrest-func.sql +23 -23
  54. package/backend/src/infra/database/migrations/005_enable-project-admin-modify-users.sql +29 -29
  55. package/backend/src/infra/database/migrations/006_modify-ai-usage-table.sql +24 -24
  56. package/backend/src/infra/database/migrations/007_drop-metadata-table.sql +1 -1
  57. package/backend/src/infra/database/migrations/008_add-system-tables.sql +76 -76
  58. package/backend/src/infra/database/migrations/009_add-function-secrets.sql +23 -23
  59. package/backend/src/infra/database/migrations/010_modify-ai-config-modalities.sql +93 -93
  60. package/backend/src/infra/database/migrations/011_refactor-secrets-table.sql +15 -15
  61. package/backend/src/infra/database/migrations/012_add-storage-uploaded-by.sql +7 -7
  62. package/backend/src/infra/database/migrations/013_create-auth-schema-functions.sql +44 -44
  63. package/backend/src/infra/database/migrations/014_add-updated-at-trigger-user-table.sql +7 -7
  64. package/backend/src/infra/database/migrations/015_create-auth-config-and-email-otp-tables.sql +59 -59
  65. package/backend/src/infra/database/migrations/016_update-auth-config-and-email-otp.sql +24 -24
  66. package/backend/src/infra/database/migrations/017_create-realtime-schema.sql +233 -0
  67. package/backend/src/infra/realtime/realtime.manager.ts +246 -0
  68. package/backend/src/infra/realtime/webhook-sender.ts +82 -0
  69. package/backend/src/infra/security/token.manager.ts +219 -125
  70. package/backend/src/infra/socket/socket.manager.ts +198 -64
  71. package/backend/src/providers/ai/openrouter.provider.ts +12 -9
  72. package/backend/src/providers/email/base.provider.ts +4 -7
  73. package/backend/src/providers/email/cloud.provider.ts +84 -0
  74. package/backend/src/providers/oauth/apple.provider.ts +266 -0
  75. package/backend/src/providers/oauth/index.ts +1 -0
  76. package/backend/src/server.ts +317 -284
  77. package/backend/src/services/ai/ai-model.service.ts +5 -5
  78. package/backend/src/services/ai/chat-completion.service.ts +4 -4
  79. package/backend/src/services/ai/image-generation.service.ts +3 -3
  80. package/backend/src/services/auth/auth.service.ts +14 -0
  81. package/backend/src/services/database/database-table.service.ts +0 -9
  82. package/backend/src/services/database/database.service.ts +127 -0
  83. package/backend/src/services/email/email.service.ts +5 -7
  84. package/backend/src/services/realtime/index.ts +3 -0
  85. package/backend/src/services/realtime/realtime-auth.service.ts +104 -0
  86. package/backend/src/services/realtime/realtime-channel.service.ts +237 -0
  87. package/backend/src/services/realtime/realtime-message.service.ts +260 -0
  88. package/backend/src/types/auth.ts +11 -0
  89. package/backend/src/types/realtime.ts +18 -0
  90. package/backend/src/types/socket.ts +7 -31
  91. package/backend/src/utils/cookies.ts +35 -0
  92. package/backend/src/utils/s3-config-loader.ts +64 -0
  93. package/backend/src/utils/seed.ts +301 -298
  94. package/backend/src/utils/sql-parser.ts +90 -0
  95. package/backend/tests/README.md +133 -133
  96. package/backend/tests/cleanup-all-test-data.sh +230 -230
  97. package/backend/tests/cloud/test-s3-multitenant.sh +131 -131
  98. package/backend/tests/local/comprehensive-curl-tests.sh +155 -155
  99. package/backend/tests/local/test-ai-config.sh +129 -129
  100. package/backend/tests/local/test-ai-usage.sh +80 -80
  101. package/backend/tests/local/test-auth-router.sh +143 -143
  102. package/backend/tests/local/test-database-router.sh +222 -222
  103. package/backend/tests/local/test-e2e.sh +240 -240
  104. package/backend/tests/local/test-fk-errors.sh +96 -96
  105. package/backend/tests/local/test-functions.sh +123 -123
  106. package/backend/tests/local/test-id-field.sh +200 -200
  107. package/backend/tests/local/test-logs.sh +132 -132
  108. package/backend/tests/local/test-public-bucket.sh +264 -264
  109. package/backend/tests/local/test-secrets.sh +249 -249
  110. package/backend/tests/local/test-serverless-functions.sh.disabled +325 -325
  111. package/backend/tests/local/test-traditional-rest.sh +208 -208
  112. package/backend/tests/manual/README.md +50 -50
  113. package/backend/tests/manual/create-large-table-simple.sql +10 -10
  114. package/backend/tests/manual/seed-large-table.sql +100 -100
  115. package/backend/tests/manual/setup-large-table-extras.sql +33 -33
  116. package/backend/tests/manual/test-bulk-upsert.sh +409 -409
  117. package/backend/tests/manual/test-database-advance.sh +296 -296
  118. package/backend/tests/manual/test-postgrest-stability.sh +191 -191
  119. package/backend/tests/manual/test-rawsql-export-import.sh +411 -411
  120. package/backend/tests/manual/test-rawsql-modes.sh +244 -244
  121. package/backend/tests/manual/test-universal-storage.sh +263 -263
  122. package/backend/tests/manual/test-users.sql +17 -17
  123. package/backend/tests/run-all-tests.sh +139 -139
  124. package/backend/tests/setup.ts +0 -0
  125. package/backend/tests/test-config.sh +338 -338
  126. package/backend/tests/unit/analyze-query.test.ts +697 -0
  127. package/backend/tsconfig.json +22 -22
  128. package/claude-plugin/.claude-plugin/plugin.json +24 -24
  129. package/claude-plugin/README.md +133 -133
  130. package/claude-plugin/skills/insforge-schema-patterns/SKILL.md +270 -270
  131. package/docker-compose.prod.yml +204 -200
  132. package/docker-compose.yml +232 -228
  133. package/docker-init/db/db-init.sql +97 -97
  134. package/docker-init/db/jwt.sql +5 -5
  135. package/docker-init/db/postgresql.conf +16 -16
  136. package/docker-init/logs/vector.yml +236 -236
  137. package/docs/README.md +44 -44
  138. package/docs/agent-docs/real-time.md +269 -0
  139. package/docs/changelog.mdx +119 -67
  140. package/docs/core-concepts/ai/architecture.mdx +372 -372
  141. package/docs/core-concepts/ai/sdk.mdx +213 -213
  142. package/docs/core-concepts/authentication/architecture.mdx +278 -278
  143. package/docs/core-concepts/authentication/sdk.mdx +414 -414
  144. package/docs/core-concepts/authentication/ui-components/customization.mdx +529 -529
  145. package/docs/core-concepts/authentication/ui-components/nextjs.mdx +221 -221
  146. package/docs/core-concepts/authentication/ui-components/react-router.mdx +184 -184
  147. package/docs/core-concepts/authentication/ui-components/react.mdx +129 -129
  148. package/docs/core-concepts/database/architecture.mdx +255 -255
  149. package/docs/core-concepts/database/sdk.mdx +382 -382
  150. package/docs/core-concepts/email/architecture.mdx +101 -0
  151. package/docs/core-concepts/email/sdk.mdx +53 -0
  152. package/docs/core-concepts/functions/architecture.mdx +105 -105
  153. package/docs/core-concepts/functions/sdk.mdx +184 -184
  154. package/docs/core-concepts/realtime/architecture.mdx +446 -0
  155. package/docs/core-concepts/realtime/sdk.mdx +409 -0
  156. package/docs/core-concepts/storage/architecture.mdx +243 -243
  157. package/docs/core-concepts/storage/sdk.mdx +253 -253
  158. package/docs/deployment/README.md +94 -94
  159. package/docs/deployment/deploy-to-aws-ec2.md +564 -564
  160. package/docs/deployment/deploy-to-azure-virtual-machines.md +312 -312
  161. package/docs/deployment/deploy-to-google-cloud-compute-engine.md +613 -613
  162. package/docs/deployment/deploy-to-render.md +441 -441
  163. package/docs/deprecated/insforge-auth-api.md +214 -214
  164. package/docs/deprecated/insforge-auth-sdk.md +99 -99
  165. package/docs/deprecated/insforge-db-api.md +358 -358
  166. package/docs/deprecated/insforge-db-sdk.md +139 -139
  167. package/docs/deprecated/insforge-debug-sdk.md +156 -156
  168. package/docs/deprecated/insforge-debug.md +64 -64
  169. package/docs/deprecated/insforge-instructions.md +123 -123
  170. package/docs/deprecated/insforge-project.md +117 -117
  171. package/docs/deprecated/insforge-storage-api.md +278 -278
  172. package/docs/deprecated/insforge-storage-sdk.md +158 -158
  173. package/docs/docs.json +232 -210
  174. package/docs/examples/framework-guides/nextjs.mdx +131 -131
  175. package/docs/examples/framework-guides/nuxt.mdx +165 -165
  176. package/docs/examples/framework-guides/react.mdx +165 -165
  177. package/docs/examples/framework-guides/svelte.mdx +153 -153
  178. package/docs/examples/framework-guides/vue.mdx +159 -159
  179. package/docs/examples/overview.mdx +67 -67
  180. package/docs/favicon.svg +19 -19
  181. package/docs/images/changelog/dec-2025/ai-integration.png +0 -0
  182. package/docs/images/changelog/dec-2025/ai-models.webp +0 -0
  183. package/docs/images/changelog/dec-2025/alipay-payment.webp +0 -0
  184. package/docs/images/changelog/dec-2025/apple-login.jpg +0 -0
  185. package/docs/images/changelog/dec-2025/mcp-installer.png +0 -0
  186. package/docs/images/changelog/dec-2025/realtime-module.jpg +0 -0
  187. package/docs/images/icons/ai.svg +4 -4
  188. package/docs/images/logos/nextjs.svg +4 -4
  189. package/docs/images/logos/nuxt.svg +4 -4
  190. package/docs/images/logos/react.svg +5 -5
  191. package/docs/images/logos/svelte.svg +4 -4
  192. package/docs/images/logos/vue.svg +5 -5
  193. package/docs/insforge-instructions-sdk.md +89 -88
  194. package/docs/introduction.mdx +45 -45
  195. package/docs/logo/dark.svg +22 -22
  196. package/docs/logo/light.svg +20 -20
  197. package/docs/partnership.mdx +651 -646
  198. package/docs/quickstart.mdx +82 -82
  199. package/docs/showcase.mdx +52 -52
  200. package/docs/snippets/sdk-installation.mdx +21 -21
  201. package/docs/snippets/service-icons.mdx +27 -27
  202. package/examples/oauth/frontend-oauth-example.html +250 -250
  203. package/examples/response-examples.md +443 -443
  204. package/frontend/components.json +17 -17
  205. package/frontend/package.json +69 -69
  206. package/frontend/src/assets/icons/checkbox_checked.svg +6 -6
  207. package/frontend/src/assets/icons/checkbox_undetermined.svg +6 -6
  208. package/frontend/src/assets/icons/checked.svg +3 -3
  209. package/frontend/src/assets/icons/connected.svg +3 -3
  210. package/frontend/src/assets/icons/error.svg +3 -3
  211. package/frontend/src/assets/icons/loader.svg +9 -9
  212. package/frontend/src/assets/icons/pencil.svg +4 -4
  213. package/frontend/src/assets/icons/refresh.svg +4 -4
  214. package/frontend/src/assets/icons/step_active.svg +3 -3
  215. package/frontend/src/assets/icons/step_inactive.svg +11 -11
  216. package/frontend/src/assets/icons/warning.svg +3 -3
  217. package/frontend/src/assets/logos/apple.svg +3 -3
  218. package/frontend/src/assets/logos/claude_code.svg +3 -3
  219. package/frontend/src/assets/logos/cline.svg +6 -6
  220. package/frontend/src/assets/logos/cursor.svg +20 -20
  221. package/frontend/src/assets/logos/discord.svg +8 -8
  222. package/frontend/src/assets/logos/facebook.svg +3 -3
  223. package/frontend/src/assets/logos/gemini.svg +19 -19
  224. package/frontend/src/assets/logos/github.svg +5 -5
  225. package/frontend/src/assets/logos/google.svg +13 -13
  226. package/frontend/src/assets/logos/grok.svg +10 -10
  227. package/frontend/src/assets/logos/insforge_dark.svg +15 -15
  228. package/frontend/src/assets/logos/insforge_light.svg +15 -15
  229. package/frontend/src/assets/logos/instagram.svg +1 -1
  230. package/frontend/src/assets/logos/linkedin.svg +3 -3
  231. package/frontend/src/assets/logos/openai.svg +10 -10
  232. package/frontend/src/assets/logos/roo_code.svg +9 -9
  233. package/frontend/src/assets/logos/spotify.svg +16 -16
  234. package/frontend/src/assets/logos/tiktok.svg +5 -5
  235. package/frontend/src/assets/logos/trae.svg +3 -3
  236. package/frontend/src/assets/logos/windsurf.svg +10 -10
  237. package/frontend/src/assets/logos/x.svg +3 -3
  238. package/frontend/src/components/layout/AppHeader.tsx +9 -10
  239. package/frontend/src/features/auth/components/OAuthConfigDialog.tsx +1 -0
  240. package/frontend/src/features/auth/components/UsersDataGrid.tsx +6 -0
  241. package/frontend/src/features/auth/helpers.tsx +8 -0
  242. package/frontend/src/features/auth/{page → pages}/UsersPage.tsx +0 -28
  243. package/frontend/src/features/database/components/SQLModal.tsx +75 -0
  244. package/frontend/src/features/database/components/TableForm.tsx +0 -4
  245. package/frontend/src/features/database/hooks/useDatabase.ts +66 -0
  246. package/frontend/src/features/database/hooks/useTables.ts +32 -28
  247. package/frontend/src/features/database/index.ts +1 -0
  248. package/frontend/src/features/database/{page → pages}/FunctionsPage.tsx +29 -37
  249. package/frontend/src/features/database/{page → pages}/IndexesPage.tsx +35 -47
  250. package/frontend/src/features/database/{page → pages}/PoliciesPage.tsx +43 -54
  251. package/frontend/src/features/database/{page → pages}/TablesPage.tsx +0 -42
  252. package/frontend/src/features/database/{page → pages}/TriggersPage.tsx +35 -47
  253. package/frontend/src/features/database/services/advance.service.ts +0 -26
  254. package/frontend/src/features/database/services/database.service.ts +55 -0
  255. package/frontend/src/features/database/services/table.service.ts +0 -6
  256. package/frontend/src/features/functions/{page → pages}/FunctionsPage.tsx +21 -44
  257. package/frontend/src/features/functions/{page → pages}/SecretsPage.tsx +11 -9
  258. package/frontend/src/features/logs/hooks/useMcpUsage.ts +13 -66
  259. package/frontend/src/features/realtime/components/ChannelRow.tsx +83 -0
  260. package/frontend/src/features/realtime/components/EditChannelModal.tsx +246 -0
  261. package/frontend/src/features/realtime/components/MessageRow.tsx +85 -0
  262. package/frontend/src/features/realtime/components/RealtimeEmptyState.tsx +30 -0
  263. package/frontend/src/features/realtime/hooks/useRealtime.ts +218 -0
  264. package/frontend/src/features/realtime/index.ts +11 -0
  265. package/frontend/src/features/realtime/pages/RealtimeChannelsPage.tsx +172 -0
  266. package/frontend/src/features/realtime/pages/RealtimeMessagesPage.tsx +211 -0
  267. package/frontend/src/features/realtime/pages/RealtimePermissionsPage.tsx +191 -0
  268. package/frontend/src/features/realtime/services/realtime.service.ts +107 -0
  269. package/frontend/src/features/storage/{page → pages}/StoragePage.tsx +1 -29
  270. package/frontend/src/features/visualizer/components/SchemaVisualizer.tsx +3 -3
  271. package/frontend/src/features/visualizer/{page → pages}/VisualizerPage.tsx +1 -35
  272. package/frontend/src/lib/contexts/SocketContext.tsx +119 -75
  273. package/frontend/src/lib/routing/AppRoutes.tsx +35 -20
  274. package/frontend/src/lib/utils/cloudMessaging.ts +1 -1
  275. package/frontend/src/lib/utils/menuItems.ts +24 -0
  276. package/frontend/src/lib/utils/utils.ts +14 -1
  277. package/frontend/tsconfig.json +25 -25
  278. package/frontend/tsconfig.node.json +9 -9
  279. package/functions/deno.json +24 -24
  280. package/functions/server.ts +315 -315
  281. package/i18n/README.ar.md +130 -130
  282. package/i18n/README.de.md +130 -130
  283. package/i18n/README.es.md +154 -154
  284. package/i18n/README.fr.md +134 -134
  285. package/i18n/README.hi.md +129 -129
  286. package/i18n/README.ja.md +174 -174
  287. package/i18n/README.ko.md +136 -136
  288. package/i18n/README.pt-BR.md +131 -131
  289. package/i18n/README.ru.md +129 -129
  290. package/i18n/README.zh-CN.md +133 -133
  291. package/openapi/ai.yaml +715 -715
  292. package/openapi/auth.yaml +1244 -1244
  293. package/openapi/email.yaml +158 -0
  294. package/openapi/functions.yaml +475 -475
  295. package/openapi/health.yaml +29 -29
  296. package/openapi/logs.yaml +223 -223
  297. package/openapi/metadata.yaml +177 -177
  298. package/openapi/realtime.yaml +699 -0
  299. package/openapi/records.yaml +381 -381
  300. package/openapi/secrets.yaml +370 -370
  301. package/openapi/storage.yaml +875 -875
  302. package/openapi/tables.yaml +463 -463
  303. package/package.json +97 -97
  304. package/shared-schemas/package.json +31 -31
  305. package/shared-schemas/src/ai.schema.ts +63 -59
  306. package/shared-schemas/src/auth-api.schema.ts +352 -339
  307. package/shared-schemas/src/auth.schema.ts +1 -1
  308. package/shared-schemas/src/database-api.schema.ts +32 -1
  309. package/shared-schemas/src/database.schema.ts +39 -0
  310. package/shared-schemas/src/docs.schema.ts +26 -0
  311. package/shared-schemas/src/email-api.schema.ts +30 -0
  312. package/shared-schemas/src/index.ts +4 -0
  313. package/shared-schemas/src/metadata.schema.ts +9 -0
  314. package/shared-schemas/src/realtime-api.schema.ts +111 -0
  315. package/shared-schemas/src/realtime.schema.ts +143 -0
  316. package/shared-schemas/tsconfig.json +21 -21
  317. package/tsconfig.json +7 -7
  318. package/zeabur/README.md +13 -13
  319. package/zeabur/template.yml +1032 -1032
  320. package/.cursor/rules/cursor-rules.mdc +0 -94
  321. package/frontend/src/features/database/hooks/useFullMetadata.ts +0 -18
  322. package/test-gemini.sh +0 -35
  323. package/test-usage-admin.sh +0 -57
  324. package/test-usage.sh +0 -50
  325. /package/frontend/src/features/ai/{page → pages}/AIPage.tsx +0 -0
  326. /package/frontend/src/features/auth/{page → pages}/AuthMethodsPage.tsx +0 -0
  327. /package/frontend/src/features/auth/{page → pages}/ConfigurationPage.tsx +0 -0
  328. /package/frontend/src/features/dashboard/{page → pages}/DashboardPage.tsx +0 -0
  329. /package/frontend/src/features/database/{page → pages}/SQLEditorPage.tsx +0 -0
  330. /package/frontend/src/features/database/{page → pages}/TemplatesPage.tsx +0 -0
  331. /package/frontend/src/features/login/{page → pages}/CloudLoginPage.tsx +0 -0
  332. /package/frontend/src/features/login/{page → pages}/LoginPage.tsx +0 -0
  333. /package/frontend/src/features/logs/{page → pages}/AuditsPage.tsx +0 -0
  334. /package/frontend/src/features/logs/{page → pages}/LogsPage.tsx +0 -0
  335. /package/frontend/src/features/logs/{page → pages}/MCPLogsPage.tsx +0 -0
@@ -1,4 +1,4 @@
1
- import { useMemo, useState, useEffect } from 'react';
1
+ import { useMemo, useState } from 'react';
2
2
  import RefreshIcon from '@/assets/icons/refresh.svg?react';
3
3
  import {
4
4
  Button,
@@ -13,16 +13,10 @@ import {
13
13
  TooltipProvider,
14
14
  TooltipTrigger,
15
15
  } from '@/components';
16
- import { useFullMetadata } from '../hooks/useFullMetadata';
17
- import type { ExportDatabaseResponse, ExportDatabaseJsonData } from '@insforge/shared-schemas';
16
+ import { useTriggers } from '../hooks/useDatabase';
17
+ import { SQLModal, SQLCellButton } from '../components/SQLModal';
18
+ import type { DatabaseTriggersResponse } from '@insforge/shared-schemas';
18
19
  import { isSystemTable } from '../constants';
19
- import {
20
- DataUpdatePayload,
21
- DataUpdateResourceType,
22
- ServerEvents,
23
- SocketMessage,
24
- useSocket,
25
- } from '@/lib/contexts/SocketContext';
26
20
 
27
21
  interface TriggerRow extends DataGridRowType {
28
22
  id: string;
@@ -34,28 +28,25 @@ interface TriggerRow extends DataGridRowType {
34
28
  [key: string]: ConvertedValue | { [key: string]: string }[];
35
29
  }
36
30
 
37
- function parseTriggersFromMetadata(metadata: ExportDatabaseResponse | undefined): TriggerRow[] {
38
- if (!metadata || metadata.format !== 'json' || typeof metadata.data === 'string') {
31
+ function parseTriggersFromResponse(response: DatabaseTriggersResponse | undefined): TriggerRow[] {
32
+ if (!response?.triggers) {
39
33
  return [];
40
34
  }
41
35
 
42
- const data = metadata.data as ExportDatabaseJsonData;
43
36
  const triggers: TriggerRow[] = [];
44
37
 
45
- Object.entries(data.tables).forEach(([tableName, tableData]) => {
46
- if (isSystemTable(tableName)) {
38
+ response.triggers.forEach((trigger) => {
39
+ if (isSystemTable(trigger.tableName)) {
47
40
  return;
48
41
  }
49
42
 
50
- tableData.triggers.forEach((trigger) => {
51
- triggers.push({
52
- id: `${tableName}_${trigger.triggerName}`,
53
- tableName,
54
- triggerName: trigger.triggerName,
55
- actionTiming: trigger.actionTiming,
56
- eventManipulation: trigger.eventManipulation,
57
- actionStatement: trigger.actionStatement,
58
- });
43
+ triggers.push({
44
+ id: `${trigger.tableName}_${trigger.triggerName}`,
45
+ tableName: trigger.tableName,
46
+ triggerName: trigger.triggerName,
47
+ actionTiming: trigger.actionTiming,
48
+ eventManipulation: trigger.eventManipulation,
49
+ actionStatement: trigger.actionStatement,
59
50
  });
60
51
  });
61
52
 
@@ -65,29 +56,10 @@ function parseTriggersFromMetadata(metadata: ExportDatabaseResponse | undefined)
65
56
  export default function TriggersPage() {
66
57
  const [searchQuery, setSearchQuery] = useState('');
67
58
  const [isRefreshing, setIsRefreshing] = useState(false);
68
- const { data: metadata, isLoading, error, refetch } = useFullMetadata(true);
69
-
70
- const { socket, isConnected } = useSocket();
71
-
72
- const allTriggers = useMemo(() => parseTriggersFromMetadata(metadata), [metadata]);
73
-
74
- useEffect(() => {
75
- if (!socket || !isConnected) {
76
- return;
77
- }
59
+ const { data, isLoading, error, refetch } = useTriggers(true);
60
+ const [sqlModal, setSqlModal] = useState({ open: false, title: '', value: '' });
78
61
 
79
- const handleDataUpdate = (message: SocketMessage<DataUpdatePayload>) => {
80
- if (message.payload?.resource === DataUpdateResourceType.DATABASE) {
81
- void refetch();
82
- }
83
- };
84
-
85
- socket.on(ServerEvents.DATA_UPDATE, handleDataUpdate);
86
-
87
- return () => {
88
- socket.off(ServerEvents.DATA_UPDATE, handleDataUpdate);
89
- };
90
- }, [socket, isConnected, refetch]);
62
+ const allTriggers = useMemo(() => parseTriggersFromResponse(data), [data]);
91
63
 
92
64
  const filteredTriggers = useMemo(() => {
93
65
  if (!searchQuery.trim()) {
@@ -163,9 +135,17 @@ export default function TriggersPage() {
163
135
  name: 'Statement',
164
136
  width: 'minmax(300px, 3fr)',
165
137
  resizable: true,
138
+ renderCell: ({ row }) => (
139
+ <SQLCellButton
140
+ value={row.actionStatement}
141
+ onClick={() =>
142
+ setSqlModal({ open: true, title: 'Trigger Statement', value: row.actionStatement })
143
+ }
144
+ />
145
+ ),
166
146
  },
167
147
  ],
168
- []
148
+ [setSqlModal]
169
149
  );
170
150
 
171
151
  if (error) {
@@ -237,6 +217,14 @@ export default function TriggersPage() {
237
217
  />
238
218
  </div>
239
219
  )}
220
+
221
+ {/* SQL Detail Modal */}
222
+ <SQLModal
223
+ open={sqlModal.open}
224
+ onOpenChange={(open) => setSqlModal((prev) => ({ ...prev, open }))}
225
+ title={sqlModal.title}
226
+ value={sqlModal.value}
227
+ />
240
228
  </div>
241
229
  );
242
230
  }
@@ -1,5 +1,4 @@
1
1
  import { apiClient } from '@/lib/api/client';
2
- import type { ExportDatabaseRequest, ExportDatabaseResponse } from '@insforge/shared-schemas';
3
2
 
4
3
  export interface RawSQLRequest {
5
4
  query: string;
@@ -36,31 +35,6 @@ export class AdvanceService {
36
35
  body: JSON.stringify(body),
37
36
  });
38
37
  }
39
-
40
- /**
41
- * Get full database metadata including schema, functions, triggers, etc.
42
- * Requires admin privileges.
43
- *
44
- * @returns Response with complete database metadata in JSON format
45
- */
46
- async getDatabaseFullMetadata(): Promise<ExportDatabaseResponse> {
47
- const body: ExportDatabaseRequest = {
48
- format: 'json',
49
- includeData: false,
50
- includeFunctions: true,
51
- includeSequences: false,
52
- includeViews: false,
53
- rowLimit: 1000,
54
- };
55
-
56
- return apiClient.request('/database/advance/export', {
57
- method: 'POST',
58
- headers: apiClient.withAccessToken({
59
- 'Content-Type': 'application/json',
60
- }),
61
- body: JSON.stringify(body),
62
- });
63
- }
64
38
  }
65
39
 
66
40
  export const advanceService = new AdvanceService();
@@ -0,0 +1,55 @@
1
+ import { apiClient } from '@/lib/api/client';
2
+ import type {
3
+ DatabaseFunctionsResponse,
4
+ DatabaseIndexesResponse,
5
+ DatabasePoliciesResponse,
6
+ DatabaseTriggersResponse,
7
+ } from '@insforge/shared-schemas';
8
+
9
+ export class DatabaseService {
10
+ /**
11
+ * Get all database functions.
12
+ * Requires admin privileges.
13
+ */
14
+ async getFunctions(): Promise<DatabaseFunctionsResponse> {
15
+ return apiClient.request('/database/functions', {
16
+ method: 'GET',
17
+ headers: apiClient.withAccessToken({}),
18
+ });
19
+ }
20
+
21
+ /**
22
+ * Get all database indexes.
23
+ * Requires admin privileges.
24
+ */
25
+ async getIndexes(): Promise<DatabaseIndexesResponse> {
26
+ return apiClient.request('/database/indexes', {
27
+ method: 'GET',
28
+ headers: apiClient.withAccessToken({}),
29
+ });
30
+ }
31
+
32
+ /**
33
+ * Get all RLS policies.
34
+ * Requires admin privileges.
35
+ */
36
+ async getPolicies(): Promise<DatabasePoliciesResponse> {
37
+ return apiClient.request('/database/policies', {
38
+ method: 'GET',
39
+ headers: apiClient.withAccessToken({}),
40
+ });
41
+ }
42
+
43
+ /**
44
+ * Get all database triggers.
45
+ * Requires admin privileges.
46
+ */
47
+ async getTriggers(): Promise<DatabaseTriggersResponse> {
48
+ return apiClient.request('/database/triggers', {
49
+ method: 'GET',
50
+ headers: apiClient.withAccessToken({}),
51
+ });
52
+ }
53
+ }
54
+
55
+ export const databaseService = new DatabaseService();
@@ -17,12 +17,6 @@ export class TableService {
17
17
  return Array.isArray(data) ? data.filter((table) => table !== 'users') : [];
18
18
  }
19
19
 
20
- getAllTableSchemas(): Promise<GetTableSchemaResponse[]> {
21
- return apiClient.request('/database/tables/schemas', {
22
- headers: apiClient.withAccessToken(),
23
- });
24
- }
25
-
26
20
  getTableSchema(tableName: string): Promise<GetTableSchemaResponse> {
27
21
  return apiClient.request(`/database/tables/${tableName}/schema`, {
28
22
  headers: apiClient.withAccessToken(),
@@ -14,13 +14,6 @@ import {
14
14
  TooltipProvider,
15
15
  TooltipTrigger,
16
16
  } from '@/components';
17
- import {
18
- DataUpdatePayload,
19
- DataUpdateResourceType,
20
- ServerEvents,
21
- SocketMessage,
22
- useSocket,
23
- } from '@/lib/contexts/SocketContext';
24
17
 
25
18
  export default function FunctionsPage() {
26
19
  const toastShownRef = useRef(false);
@@ -36,8 +29,6 @@ export default function FunctionsPage() {
36
29
  refetch,
37
30
  } = useFunctions();
38
31
 
39
- const { socket, isConnected } = useSocket();
40
-
41
32
  const handleRefresh = async () => {
42
33
  setIsRefreshing(true);
43
34
  try {
@@ -54,24 +45,6 @@ export default function FunctionsPage() {
54
45
  }
55
46
  }, [isRuntimeAvailable, showToast]);
56
47
 
57
- useEffect(() => {
58
- if (!socket || !isConnected) {
59
- return;
60
- }
61
-
62
- const handleDataUpdate = (message: SocketMessage<DataUpdatePayload>) => {
63
- if (message.payload?.resource === DataUpdateResourceType.FUNCTIONS) {
64
- void refetch();
65
- }
66
- };
67
-
68
- socket.on(ServerEvents.DATA_UPDATE, handleDataUpdate);
69
-
70
- return () => {
71
- socket.off(ServerEvents.DATA_UPDATE, handleDataUpdate);
72
- };
73
- }, [socket, isConnected, refetch]);
74
-
75
48
  // If a function is selected, show the detail view
76
49
  if (selectedFunction) {
77
50
  return (
@@ -124,14 +97,18 @@ export default function FunctionsPage() {
124
97
  </Tooltip>
125
98
  </TooltipProvider>
126
99
  </div>
127
- <div className="flex flex-col gap-2 relative">
128
- {/* Table Header */}
129
- <div className="grid grid-cols-12 px-3 text-sm text-muted-foreground dark:text-neutral-400">
130
- <div className="col-span-2 py-1 px-3">Name</div>
131
- <div className="col-span-6 py-1 px-3">URL</div>
132
- <div className="col-span-2 py-1 px-3">Created</div>
133
- <div className="col-span-2 py-1 px-3">Last Update</div>
134
- </div>
100
+ {/* Table Header */}
101
+ <div className="grid grid-cols-12 px-3 text-sm text-muted-foreground dark:text-neutral-400">
102
+ <div className="col-span-2 py-1 px-3">Name</div>
103
+ <div className="col-span-6 py-1 px-3">URL</div>
104
+ <div className="col-span-2 py-1 px-3">Created</div>
105
+ <div className="col-span-2 py-1 px-3">Last Update</div>
106
+ </div>
107
+ </div>
108
+
109
+ {/* Scrollable Table Body */}
110
+ <div className="flex-1 min-h-0 overflow-y-auto px-4 pb-4 relative">
111
+ <div className="flex flex-col gap-2">
135
112
  {loading ? (
136
113
  <>
137
114
  {[...Array(4)].map((_, i) => (
@@ -154,17 +131,17 @@ export default function FunctionsPage() {
154
131
  <FunctionEmptyState />
155
132
  </div>
156
133
  )}
134
+ </div>
157
135
 
158
- {/* Loading mask overlay */}
159
- {isRefreshing && (
160
- <div className="absolute inset-0 bg-white dark:bg-neutral-800 flex items-center justify-center z-50">
161
- <div className="flex items-center gap-1">
162
- <div className="w-5 h-5 border-2 border-zinc-500 dark:border-neutral-700 border-t-transparent rounded-full animate-spin" />
163
- <span className="text-sm text-zinc-500 dark:text-zinc-400">Loading</span>
164
- </div>
136
+ {/* Loading mask overlay */}
137
+ {isRefreshing && (
138
+ <div className="absolute inset-0 bg-white dark:bg-neutral-800 flex items-center justify-center z-50">
139
+ <div className="flex items-center gap-1">
140
+ <div className="w-5 h-5 border-2 border-zinc-500 dark:border-neutral-700 border-t-transparent rounded-full animate-spin" />
141
+ <span className="text-sm text-zinc-500 dark:text-zinc-400">Loading</span>
165
142
  </div>
166
- )}
167
- </div>
143
+ </div>
144
+ )}
168
145
  </div>
169
146
  </div>
170
147
  );
@@ -75,16 +75,18 @@ export default function SecretsPage() {
75
75
  className="max-w-70 dark:bg-neutral-900 dark:border-neutral-700"
76
76
  />
77
77
 
78
- {/* Secrets Table */}
79
- <div className="flex flex-col gap-2">
80
- {/* Table Header */}
81
- <div className="grid grid-cols-12 px-3 text-sm text-muted-foreground dark:text-neutral-400">
82
- <div className="col-span-8 py-1 px-3">Name</div>
83
- {/* <div className="col-span-5 py-1 px-3">Digest</div> */}
84
- <div className="col-span-3 py-1 px-3">Updated at</div>
85
- <div className="col-span-1 py-1 px-3" />
86
- </div>
78
+ {/* Secrets Table Header */}
79
+ <div className="grid grid-cols-12 px-3 text-sm text-muted-foreground dark:text-neutral-400">
80
+ <div className="col-span-8 py-1 px-3">Name</div>
81
+ {/* <div className="col-span-5 py-1 px-3">Digest</div> */}
82
+ <div className="col-span-3 py-1 px-3">Updated at</div>
83
+ <div className="col-span-1 py-1 px-3" />
84
+ </div>
85
+ </div>
87
86
 
87
+ {/* Scrollable Table Body */}
88
+ <div className="flex-1 min-h-0 overflow-y-auto px-4 pb-4">
89
+ <div className="flex flex-col gap-2">
88
90
  {loading ? (
89
91
  <>
90
92
  {[...Array(4)].map((_, i) => (
@@ -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]);
@@ -0,0 +1,83 @@
1
+ import { cn, formatDate } from '@/lib/utils/utils';
2
+ import { Trash2 } from 'lucide-react';
3
+ import { Switch } from '@/components';
4
+ import type { RealtimeChannel } from '../services/realtime.service';
5
+
6
+ interface ChannelRowProps {
7
+ channel: RealtimeChannel;
8
+ onClick: () => void;
9
+ onToggleEnabled: (enabled: boolean) => void;
10
+ onDelete: () => void;
11
+ isUpdating?: boolean;
12
+ isDeleting?: boolean;
13
+ className?: string;
14
+ }
15
+
16
+ export function ChannelRow({
17
+ channel,
18
+ onClick,
19
+ onToggleEnabled,
20
+ onDelete,
21
+ isUpdating,
22
+ isDeleting,
23
+ className,
24
+ }: ChannelRowProps) {
25
+ return (
26
+ <div
27
+ className={cn(
28
+ 'group flex items-center h-14 px-3 bg-white hover:bg-neutral-100 dark:bg-[#333333] dark:hover:bg-neutral-700 rounded-lg transition-all cursor-pointer',
29
+ className
30
+ )}
31
+ onClick={onClick}
32
+ >
33
+ {/* Toggle Switch - matches header w-[76px] */}
34
+ <div className="flex items-center w-[76px] shrink-0 px-3 py-1.5">
35
+ <Switch
36
+ checked={channel.enabled}
37
+ disabled={isUpdating}
38
+ onCheckedChange={(checked) => {
39
+ onToggleEnabled(checked);
40
+ }}
41
+ onClick={(e) => e.stopPropagation()}
42
+ />
43
+ </div>
44
+
45
+ {/* Pattern Column - flex-1 to match header */}
46
+ <div className="flex-1 min-w-0 px-3 py-1.5">
47
+ <p className="text-sm text-zinc-950 dark:text-white truncate" title={channel.pattern}>
48
+ {channel.pattern}
49
+ </p>
50
+ </div>
51
+
52
+ {/* Description Column - fixed w-[640px] to match header */}
53
+ <div className="w-[640px] min-w-0 px-3 py-1.5">
54
+ <span
55
+ className="text-sm text-zinc-700 dark:text-white truncate block"
56
+ title={channel.description || ''}
57
+ >
58
+ {channel.description || '-'}
59
+ </span>
60
+ </div>
61
+
62
+ {/* Created Column - flex-1 to match header */}
63
+ <div className="flex-1 min-w-0 px-3 py-1">
64
+ <span className="text-sm text-zinc-700 dark:text-white truncate" title={channel.createdAt}>
65
+ {formatDate(channel.createdAt)}
66
+ </span>
67
+ </div>
68
+
69
+ {/* Delete Button - hidden by default, visible on hover */}
70
+ <button
71
+ className="flex items-center justify-center size-8 rounded opacity-0 group-hover:opacity-100 hover:bg-neutral-200 dark:hover:bg-neutral-600 transition-all disabled:opacity-50"
72
+ onClick={(e) => {
73
+ e.stopPropagation();
74
+ onDelete();
75
+ }}
76
+ disabled={isDeleting}
77
+ aria-label="Delete channel"
78
+ >
79
+ <Trash2 className="size-5 text-neutral-400 group-hover:text-zinc-600 dark:group-hover:text-white transition-colors" />
80
+ </button>
81
+ </div>
82
+ );
83
+ }