insforge 0.3.3 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (635) hide show
  1. package/.claude-plugin/marketplace.json +20 -0
  2. package/.dockerignore +60 -57
  3. package/.env.example +84 -49
  4. package/.github/ISSUE_TEMPLATE/bug_report.yml +36 -83
  5. package/.github/ISSUE_TEMPLATE/config.yml +11 -11
  6. package/.github/ISSUE_TEMPLATE/feature_request.yml +26 -79
  7. package/.github/PULL_REQUEST_TEMPLATE.md +7 -0
  8. package/.github/copilot-instructions.md +146 -146
  9. package/.github/workflows/build-image.yml +66 -65
  10. package/.github/workflows/ci-premerge-check.yml +23 -23
  11. package/.github/workflows/e2e.yml +63 -0
  12. package/.github/workflows/lint-and-format.yml +32 -32
  13. package/.prettierignore +64 -64
  14. package/CHANGELOG.md +44 -3
  15. package/CLAUDE_PLUGIN.md +104 -0
  16. package/CODE_OF_CONDUCT.md +128 -0
  17. package/CONTRIBUTING.md +125 -125
  18. package/Dockerfile +30 -27
  19. package/GITHUB_OAUTH_SETUP.md +49 -49
  20. package/GOOGLE_OAUTH_SETUP.md +148 -148
  21. package/LICENSE +201 -201
  22. package/README.md +182 -134
  23. package/assets/Dark.svg +23 -23
  24. package/assets/mcpInstallv2.png +0 -0
  25. package/assets/sampleResponse.png +0 -0
  26. package/auth/index.html +13 -0
  27. package/auth/package.json +28 -0
  28. package/auth/public/favicon.ico +0 -0
  29. package/auth/src/App.tsx +33 -0
  30. package/auth/src/components/ErrorCard.tsx +37 -0
  31. package/auth/src/components/Layout.tsx +13 -0
  32. package/auth/src/index.css +19 -0
  33. package/auth/src/lib/broadcastService.ts +117 -0
  34. package/auth/src/lib/utils.ts +11 -0
  35. package/auth/src/main.tsx +22 -0
  36. package/auth/src/pages/ForgotPasswordPage.tsx +11 -0
  37. package/auth/src/pages/ResetPasswordPage.tsx +11 -0
  38. package/auth/src/pages/SignInPage.tsx +60 -0
  39. package/auth/src/pages/SignUpPage.tsx +60 -0
  40. package/auth/src/pages/VerifyEmailPage.tsx +20 -0
  41. package/auth/src/vite-env.d.ts +10 -0
  42. package/auth/tsconfig.json +32 -0
  43. package/auth/tsconfig.node.json +11 -0
  44. package/auth/vite.config.ts +25 -0
  45. package/backend/package.json +78 -75
  46. package/backend/src/api/{middleware → middlewares}/auth.ts +8 -9
  47. package/backend/src/api/middlewares/rate-limiters.ts +127 -0
  48. package/backend/src/api/routes/{ai.ts → ai/index.routes.ts} +22 -26
  49. package/backend/src/api/routes/auth/index.routes.ts +667 -0
  50. package/backend/src/api/routes/auth/oauth.routes.ts +473 -0
  51. package/backend/src/api/routes/{database.advance.ts → database/advance.routes.ts} +128 -65
  52. package/backend/src/api/routes/database/index.routes.ts +90 -0
  53. package/backend/src/api/routes/{database.records.ts → database/records.routes.ts} +26 -12
  54. package/backend/src/api/routes/{database.tables.ts → database/tables.routes.ts} +6 -23
  55. package/backend/src/api/routes/docs/index.routes.ts +75 -0
  56. package/backend/src/api/routes/email/index.routes.ts +35 -0
  57. package/backend/src/api/routes/functions/index.routes.ts +194 -0
  58. package/backend/src/api/routes/{logs.ts → logs/index.routes.ts} +25 -30
  59. package/backend/src/api/routes/{metadata.ts → metadata/index.routes.ts} +33 -31
  60. package/backend/src/api/routes/realtime/channels.routes.ts +81 -0
  61. package/backend/src/api/routes/realtime/index.routes.ts +12 -0
  62. package/backend/src/api/routes/realtime/messages.routes.ts +48 -0
  63. package/backend/src/api/routes/realtime/permissions.routes.ts +19 -0
  64. package/backend/src/api/routes/{secrets.ts → secrets/index.routes.ts} +27 -22
  65. package/backend/src/api/routes/{storage.ts → storage/index.routes.ts} +48 -61
  66. package/backend/src/api/routes/usage/index.routes.ts +91 -0
  67. package/backend/src/infra/config/app.config.ts +51 -0
  68. package/backend/src/infra/database/database.manager.ts +182 -0
  69. package/backend/{migrations → src/infra/database/migrations}/000_create-base-tables.sql +141 -141
  70. package/backend/{migrations → src/infra/database/migrations}/001_create-helper-functions.sql +40 -40
  71. package/backend/{migrations → src/infra/database/migrations}/002_rename-auth-tables.sql +29 -29
  72. package/backend/{migrations → src/infra/database/migrations}/003_create-users-table.sql +55 -55
  73. package/backend/{migrations → src/infra/database/migrations}/004_add-reload-postgrest-func.sql +23 -23
  74. package/backend/{migrations → src/infra/database/migrations}/005_enable-project-admin-modify-users.sql +29 -29
  75. package/backend/{migrations → src/infra/database/migrations}/006_modify-ai-usage-table.sql +24 -24
  76. package/backend/{migrations → src/infra/database/migrations}/007_drop-metadata-table.sql +1 -1
  77. package/backend/{migrations → src/infra/database/migrations}/008_add-system-tables.sql +76 -76
  78. package/backend/{migrations → src/infra/database/migrations}/009_add-function-secrets.sql +23 -23
  79. package/backend/{migrations → src/infra/database/migrations}/010_modify-ai-config-modalities.sql +93 -93
  80. package/backend/{migrations → src/infra/database/migrations}/011_refactor-secrets-table.sql +15 -15
  81. package/backend/{migrations → src/infra/database/migrations}/012_add-storage-uploaded-by.sql +7 -7
  82. package/backend/src/infra/database/migrations/013_create-auth-schema-functions.sql +44 -0
  83. package/backend/src/infra/database/migrations/014_add-updated-at-trigger-user-table.sql +8 -0
  84. package/backend/src/infra/database/migrations/015_create-auth-config-and-email-otp-tables.sql +60 -0
  85. package/backend/src/infra/database/migrations/016_update-auth-config-and-email-otp.sql +24 -0
  86. package/backend/src/infra/database/migrations/017_create-realtime-schema.sql +233 -0
  87. package/backend/src/infra/realtime/realtime.manager.ts +246 -0
  88. package/backend/src/infra/realtime/webhook-sender.ts +82 -0
  89. package/backend/src/{core/secrets/encryption.ts → infra/security/encryption.manager.ts} +3 -2
  90. package/backend/src/infra/security/token.manager.ts +219 -0
  91. package/backend/src/infra/socket/socket.manager.ts +522 -0
  92. package/backend/src/providers/ai/openrouter.provider.ts +380 -0
  93. package/backend/src/providers/email/base.provider.ts +38 -0
  94. package/backend/src/providers/email/cloud.provider.ts +271 -0
  95. package/backend/src/{core/logs/providers → providers/logs}/base.provider.ts +11 -11
  96. package/backend/src/{core/logs/providers → providers/logs}/cloudwatch.provider.ts +61 -38
  97. package/backend/src/providers/logs/local.provider.ts +185 -0
  98. package/backend/src/providers/oauth/apple.provider.ts +266 -0
  99. package/backend/src/providers/oauth/base.provider.ts +29 -0
  100. package/backend/src/providers/oauth/discord.provider.ts +195 -0
  101. package/backend/src/providers/oauth/facebook.provider.ts +194 -0
  102. package/backend/src/providers/oauth/github.provider.ts +208 -0
  103. package/backend/src/providers/oauth/google.provider.ts +249 -0
  104. package/backend/src/providers/oauth/index.ts +8 -0
  105. package/backend/src/providers/oauth/linkedin.provider.ts +240 -0
  106. package/backend/src/providers/oauth/microsoft.provider.ts +169 -0
  107. package/backend/src/providers/oauth/x.provider.ts +202 -0
  108. package/backend/src/providers/storage/base.provider.ts +29 -0
  109. package/backend/src/providers/storage/local.provider.ts +103 -0
  110. package/backend/src/providers/storage/s3.provider.ts +313 -0
  111. package/backend/src/server.ts +317 -288
  112. package/backend/src/{core/ai/config.ts → services/ai/ai-config.service.ts} +19 -24
  113. package/backend/src/services/ai/ai-model.service.ts +60 -0
  114. package/backend/src/{core/ai/usage.ts → services/ai/ai-usage.service.ts} +28 -35
  115. package/backend/src/{core/ai/chat.ts → services/ai/chat-completion.service.ts} +37 -24
  116. package/backend/src/services/ai/helpers.ts +64 -0
  117. package/backend/src/{core/ai/image.ts → services/ai/image-generation.service.ts} +17 -19
  118. package/backend/src/services/ai/index.ts +13 -0
  119. package/backend/src/services/auth/auth-config.service.ts +250 -0
  120. package/backend/src/services/auth/auth-otp.service.ts +424 -0
  121. package/backend/src/services/auth/auth.service.ts +1150 -0
  122. package/backend/src/services/auth/index.ts +4 -0
  123. package/backend/src/{core/auth/oauth.ts → services/auth/oauth-config.service.ts} +106 -52
  124. package/backend/src/{core/database/advance.ts → services/database/database-advance.service.ts} +97 -131
  125. package/backend/src/services/database/database-table.service.ts +802 -0
  126. package/backend/src/services/database/database.service.ts +127 -0
  127. package/backend/src/services/email/email.service.ts +73 -0
  128. package/backend/src/{core/functions/functions.ts → services/functions/function.service.ts} +95 -88
  129. package/backend/src/{core/logs/audit.ts → services/logs/audit.service.ts} +92 -75
  130. package/backend/src/services/logs/log.service.ts +73 -0
  131. package/backend/src/services/realtime/index.ts +3 -0
  132. package/backend/src/services/realtime/realtime-auth.service.ts +104 -0
  133. package/backend/src/services/realtime/realtime-channel.service.ts +237 -0
  134. package/backend/src/services/realtime/realtime-message.service.ts +260 -0
  135. package/backend/src/{core/secrets/secrets.ts → services/secrets/secret.service.ts} +48 -66
  136. package/backend/src/services/storage/storage.service.ts +617 -0
  137. package/backend/src/services/usage/usage.service.ts +149 -0
  138. package/backend/src/types/auth.ts +77 -2
  139. package/backend/src/types/email.ts +8 -0
  140. package/backend/src/types/error-constants.ts +4 -0
  141. package/backend/src/types/logs.ts +0 -29
  142. package/backend/src/types/realtime.ts +18 -0
  143. package/backend/src/{core/socket/types.ts → types/socket.ts} +11 -36
  144. package/backend/src/utils/cookies.ts +35 -0
  145. package/backend/src/utils/environment.ts +9 -3
  146. package/backend/src/utils/logger.ts +20 -2
  147. package/backend/src/utils/s3-config-loader.ts +64 -0
  148. package/backend/src/utils/seed.ts +301 -205
  149. package/backend/src/utils/sql-parser.ts +91 -1
  150. package/backend/src/utils/utils.ts +114 -0
  151. package/backend/src/utils/validations.ts +40 -4
  152. package/backend/tests/README.md +133 -133
  153. package/backend/tests/cleanup-all-test-data.sh +230 -230
  154. package/backend/tests/cloud/test-s3-multitenant.sh +131 -131
  155. package/backend/tests/local/comprehensive-curl-tests.sh +155 -155
  156. package/backend/tests/local/test-ai-config.sh +129 -0
  157. package/backend/tests/local/test-ai-usage.sh +80 -0
  158. package/backend/tests/local/test-auth-router.sh +143 -143
  159. package/backend/tests/local/test-database-router.sh +222 -222
  160. package/backend/tests/local/test-e2e.sh +240 -240
  161. package/backend/tests/local/test-fk-errors.sh +96 -96
  162. package/backend/tests/local/test-functions.sh +123 -0
  163. package/backend/tests/local/test-id-field.sh +200 -200
  164. package/backend/tests/local/test-logs.sh +132 -0
  165. package/backend/tests/local/test-public-bucket.sh +264 -264
  166. package/backend/tests/local/test-secrets.sh +249 -247
  167. package/backend/tests/local/test-serverless-functions.sh.disabled +325 -325
  168. package/backend/tests/local/test-traditional-rest.sh +208 -208
  169. package/backend/tests/manual/README.md +50 -50
  170. package/backend/tests/manual/create-large-table-simple.sql +10 -10
  171. package/backend/tests/manual/seed-large-table.sql +100 -100
  172. package/backend/tests/manual/setup-large-table-extras.sql +33 -33
  173. package/backend/tests/manual/test-bulk-upsert.sh +409 -409
  174. package/backend/tests/manual/test-database-advance.sh +296 -296
  175. package/backend/tests/manual/test-postgrest-stability.sh +191 -191
  176. package/backend/tests/manual/test-rawsql-export-import.sh +411 -411
  177. package/backend/tests/manual/test-rawsql-modes.sh +244 -0
  178. package/backend/tests/manual/test-universal-storage.sh +263 -263
  179. package/backend/tests/manual/test-users.sql +17 -17
  180. package/backend/tests/run-all-tests.sh +139 -139
  181. package/backend/tests/setup.ts +0 -0
  182. package/backend/tests/test-config.sh +338 -302
  183. package/backend/tests/unit/analyze-query.test.ts +697 -0
  184. package/backend/tests/unit/cloud-token.test.ts +48 -0
  185. package/backend/tests/unit/constant.test.ts +8 -0
  186. package/backend/tests/unit/email.test.ts +372 -0
  187. package/backend/tests/unit/environment.test.ts +59 -0
  188. package/backend/tests/unit/helpers.test.ts +63 -0
  189. package/backend/tests/unit/logger.test.ts +22 -0
  190. package/backend/tests/unit/rate-limit.test.ts +154 -0
  191. package/backend/tests/unit/response.test.ts +58 -0
  192. package/backend/tests/unit/sql-parser.test.ts +74 -0
  193. package/backend/tests/unit/uuid.test.ts +21 -0
  194. package/backend/tests/unit/validations.test.ts +80 -0
  195. package/backend/tsconfig.json +22 -22
  196. package/backend/vitest.config.ts +11 -0
  197. package/claude-plugin/.claude-plugin/plugin.json +24 -0
  198. package/claude-plugin/README.md +133 -0
  199. package/claude-plugin/skills/insforge-schema-patterns/SKILL.md +270 -0
  200. package/docker-compose.prod.yml +204 -144
  201. package/docker-compose.yml +232 -167
  202. package/docker-init/db/db-init.sql +97 -125
  203. package/docker-init/db/jwt.sql +5 -5
  204. package/docker-init/db/postgresql.conf +16 -16
  205. package/docker-init/logs/vector.yml +236 -0
  206. package/docs/README.md +44 -0
  207. package/docs/agent-docs/real-time.md +269 -0
  208. package/docs/changelog.mdx +119 -0
  209. package/docs/core-concepts/ai/architecture.mdx +373 -0
  210. package/docs/core-concepts/ai/sdk.mdx +213 -0
  211. package/docs/core-concepts/authentication/architecture.mdx +278 -0
  212. package/docs/core-concepts/authentication/sdk.mdx +414 -0
  213. package/docs/core-concepts/authentication/ui-components/customization.mdx +529 -0
  214. package/docs/core-concepts/authentication/ui-components/nextjs.mdx +221 -0
  215. package/docs/core-concepts/authentication/ui-components/react-router.mdx +184 -0
  216. package/docs/core-concepts/authentication/ui-components/react.mdx +129 -0
  217. package/docs/core-concepts/database/architecture.mdx +256 -0
  218. package/docs/core-concepts/database/sdk.mdx +382 -0
  219. package/docs/core-concepts/email/architecture.mdx +101 -0
  220. package/docs/core-concepts/email/sdk.mdx +53 -0
  221. package/docs/core-concepts/functions/architecture.mdx +105 -0
  222. package/docs/core-concepts/functions/sdk.mdx +184 -0
  223. package/docs/core-concepts/realtime/architecture.mdx +446 -0
  224. package/docs/core-concepts/realtime/sdk.mdx +409 -0
  225. package/docs/core-concepts/storage/architecture.mdx +243 -0
  226. package/docs/core-concepts/storage/sdk.mdx +253 -0
  227. package/docs/deployment/README.md +94 -0
  228. package/docs/deployment/deploy-to-aws-ec2.md +565 -0
  229. package/docs/deployment/deploy-to-azure-virtual-machines.md +313 -0
  230. package/docs/deployment/deploy-to-google-cloud-compute-engine.md +613 -0
  231. package/docs/deployment/deploy-to-render.md +441 -0
  232. package/docs/deprecated/insforge-auth-api.md +214 -214
  233. package/docs/deprecated/insforge-auth-sdk.md +99 -99
  234. package/docs/deprecated/insforge-db-api.md +358 -358
  235. package/docs/deprecated/insforge-db-sdk.md +139 -139
  236. package/docs/deprecated/insforge-debug-sdk.md +156 -156
  237. package/docs/deprecated/insforge-debug.md +64 -64
  238. package/docs/deprecated/insforge-instructions.md +123 -123
  239. package/docs/deprecated/insforge-project.md +117 -117
  240. package/docs/deprecated/insforge-storage-api.md +278 -278
  241. package/docs/deprecated/insforge-storage-sdk.md +158 -158
  242. package/docs/docs.json +232 -0
  243. package/docs/examples/framework-guides/nextjs.mdx +131 -0
  244. package/docs/examples/framework-guides/nuxt.mdx +165 -0
  245. package/docs/examples/framework-guides/react.mdx +165 -0
  246. package/docs/examples/framework-guides/svelte.mdx +153 -0
  247. package/docs/examples/framework-guides/vue.mdx +159 -0
  248. package/docs/examples/overview.mdx +67 -0
  249. package/docs/favicon.svg +19 -0
  250. package/docs/images/changelog/dec-2025/ai-integration.png +0 -0
  251. package/docs/images/changelog/dec-2025/ai-models.webp +0 -0
  252. package/docs/images/changelog/dec-2025/alipay-payment.webp +0 -0
  253. package/docs/images/changelog/dec-2025/apple-login.jpg +0 -0
  254. package/docs/images/changelog/dec-2025/mcp-installer.png +0 -0
  255. package/docs/images/changelog/dec-2025/realtime-module.jpg +0 -0
  256. package/docs/images/changelog/nov-2025/auth-components.webp +0 -0
  257. package/docs/images/changelog/nov-2025/database-metadata.webp +0 -0
  258. package/docs/images/changelog/nov-2025/quickstart-prompts.webp +0 -0
  259. package/docs/images/changelog/nov-2025/sql-editor.webp +0 -0
  260. package/docs/images/changelog/nov-2025/usage-page.webp +0 -0
  261. package/docs/images/changelog/october-2025/csv-upload.webp +0 -0
  262. package/docs/images/changelog/october-2025/logs-feature.webp +0 -0
  263. package/docs/images/changelog/october-2025/oauth-providers.webp +0 -0
  264. package/docs/images/checks-passed.png +0 -0
  265. package/docs/images/dashboard-connect-expanded.png +0 -0
  266. package/docs/images/dashboard-connect.png +0 -0
  267. package/docs/images/hero-dark.png +0 -0
  268. package/docs/images/hero-light.png +0 -0
  269. package/docs/images/icons/ai.svg +4 -0
  270. package/docs/images/icons/auth.svg +1 -0
  271. package/docs/images/icons/database.svg +1 -0
  272. package/docs/images/icons/function.svg +1 -0
  273. package/docs/images/icons/storage.svg +1 -0
  274. package/docs/images/logos/nextjs.svg +4 -0
  275. package/docs/images/logos/nuxt.svg +4 -0
  276. package/docs/images/logos/react.svg +5 -0
  277. package/docs/images/logos/svelte.svg +4 -0
  278. package/docs/images/logos/vue.svg +5 -0
  279. package/docs/images/mcp-install.png +0 -0
  280. package/docs/images/onboarding-mcp.png +0 -0
  281. package/docs/insforge-instructions-sdk.md +89 -407
  282. package/docs/introduction.mdx +45 -0
  283. package/docs/logo/dark.svg +22 -0
  284. package/docs/logo/light.svg +20 -0
  285. package/docs/partnership.mdx +652 -0
  286. package/docs/quickstart.mdx +83 -0
  287. package/docs/showcase/2048-arena.png +0 -0
  288. package/docs/showcase/framegen-cloud.png +0 -0
  289. package/docs/showcase/line-connect-race.png +0 -0
  290. package/docs/showcase/moment-vibe.png +0 -0
  291. package/docs/showcase/national-flags.png +0 -0
  292. package/docs/showcase/pokemon-vibe.png +0 -0
  293. package/docs/showcase/pure-browse-buy.png +0 -0
  294. package/docs/showcase.mdx +52 -0
  295. package/docs/snippets/sdk-installation.mdx +22 -0
  296. package/docs/snippets/service-icons.mdx +27 -0
  297. package/eslint.config.js +10 -3
  298. package/examples/oauth/frontend-oauth-example.html +250 -250
  299. package/examples/response-examples.md +443 -443
  300. package/frontend/components.json +17 -17
  301. package/frontend/package.json +69 -63
  302. package/frontend/src/App.tsx +13 -82
  303. package/frontend/src/assets/icons/checkbox_checked.svg +6 -6
  304. package/frontend/src/assets/icons/checkbox_undetermined.svg +6 -6
  305. package/frontend/src/assets/icons/checked.svg +3 -3
  306. package/frontend/src/assets/icons/connected.svg +3 -0
  307. package/frontend/src/assets/icons/error.svg +3 -3
  308. package/frontend/src/assets/icons/loader.svg +9 -0
  309. package/frontend/src/assets/icons/pencil.svg +4 -4
  310. package/frontend/src/assets/icons/refresh.svg +4 -4
  311. package/frontend/src/assets/icons/step_active.svg +3 -3
  312. package/frontend/src/assets/icons/step_inactive.svg +11 -11
  313. package/frontend/src/assets/icons/warning.svg +3 -3
  314. package/frontend/src/assets/logos/apple.svg +4 -0
  315. package/frontend/src/assets/logos/claude_code.svg +3 -3
  316. package/frontend/src/assets/logos/cline.svg +6 -6
  317. package/frontend/src/assets/logos/cursor.svg +20 -20
  318. package/frontend/src/assets/logos/discord.svg +8 -8
  319. package/frontend/src/assets/logos/facebook.svg +3 -0
  320. package/frontend/src/assets/logos/gemini.svg +19 -19
  321. package/frontend/src/assets/logos/github.svg +5 -5
  322. package/frontend/src/assets/logos/google.svg +13 -13
  323. package/frontend/src/assets/logos/grok.svg +10 -10
  324. package/frontend/src/assets/logos/insforge_dark.svg +15 -15
  325. package/frontend/src/assets/logos/insforge_light.svg +15 -15
  326. package/frontend/src/assets/logos/instagram.svg +2 -0
  327. package/frontend/src/assets/logos/linkedin.svg +3 -0
  328. package/frontend/src/assets/logos/microsoft.svg +1 -0
  329. package/frontend/src/assets/logos/openai.svg +10 -10
  330. package/frontend/src/assets/logos/roo_code.svg +9 -9
  331. package/frontend/src/assets/logos/spotify.svg +17 -0
  332. package/frontend/src/assets/logos/tiktok.svg +6 -0
  333. package/frontend/src/assets/logos/trae.svg +3 -3
  334. package/frontend/src/assets/logos/windsurf.svg +10 -10
  335. package/frontend/src/assets/logos/x.svg +3 -0
  336. package/frontend/src/components/Checkbox.tsx +27 -29
  337. package/frontend/src/components/CodeBlock.tsx +55 -2
  338. package/frontend/src/components/CodeEditor.tsx +92 -0
  339. package/frontend/src/components/ConfirmDialog.tsx +1 -1
  340. package/frontend/src/components/ConnectCTA.tsx +38 -0
  341. package/frontend/src/components/CopyButton.tsx +52 -15
  342. package/frontend/src/components/ErrorState.tsx +1 -2
  343. package/frontend/src/components/FeatureSidebar.tsx +6 -6
  344. package/frontend/src/components/FeatureSidebarItem.tsx +2 -2
  345. package/frontend/src/components/JsonHighlight.tsx +21 -9
  346. package/frontend/src/components/ProjectInfoModal.tsx +128 -0
  347. package/frontend/src/components/PromptDialog.tsx +1 -4
  348. package/frontend/src/components/SearchInput.tsx +1 -2
  349. package/frontend/src/components/Stepper.tsx +53 -0
  350. package/frontend/src/components/ThemeToggle.tsx +3 -3
  351. package/frontend/src/components/datagrid/DataGrid.tsx +25 -32
  352. package/frontend/src/components/datagrid/cell-editors/DateCellEditor.tsx +1 -2
  353. package/frontend/src/components/datagrid/cell-editors/JsonCellEditor.tsx +2 -4
  354. package/frontend/src/components/datagrid/index.ts +23 -0
  355. package/frontend/src/components/index.ts +23 -30
  356. package/frontend/src/components/layout/AppHeader.tsx +131 -91
  357. package/frontend/src/components/layout/AppSidebar.tsx +80 -170
  358. package/frontend/src/components/layout/Layout.tsx +12 -23
  359. package/frontend/src/components/layout/PrimaryMenu.tsx +187 -0
  360. package/frontend/src/components/layout/SecondaryMenu.tsx +70 -0
  361. package/frontend/src/components/layout/index.ts +5 -0
  362. package/frontend/src/components/radix/Tooltip.tsx +24 -13
  363. package/frontend/src/components/radix/index.ts +22 -0
  364. package/frontend/src/features/ai/components/AIConfigCard.tsx +129 -83
  365. package/frontend/src/features/ai/components/AIEmptyState.tsx +12 -7
  366. package/frontend/src/features/ai/components/ModalityFilterSidebar.tsx +101 -0
  367. package/frontend/src/features/ai/components/ModelSelectionDialog.tsx +135 -0
  368. package/frontend/src/features/ai/components/ModelSelectionGrid.tsx +51 -0
  369. package/frontend/src/features/ai/components/SystemPromptDialog.tsx +118 -0
  370. package/frontend/src/features/ai/components/index.ts +6 -0
  371. package/frontend/src/features/ai/helpers.ts +57 -71
  372. package/frontend/src/features/ai/hooks/useAIConfigs.ts +39 -113
  373. package/frontend/src/features/ai/hooks/useAIUsage.ts +0 -2
  374. package/frontend/src/features/ai/pages/AIPage.tsx +166 -0
  375. package/frontend/src/features/ai/services/ai.service.ts +5 -5
  376. package/frontend/src/features/auth/components/AuthPreview.tsx +96 -0
  377. package/frontend/src/features/auth/components/OAuthConfigDialog.tsx +54 -30
  378. package/frontend/src/features/auth/components/UserFormDialog.tsx +13 -6
  379. package/frontend/src/features/auth/components/UsersDataGrid.tsx +50 -14
  380. package/frontend/src/features/auth/components/index.ts +5 -0
  381. package/frontend/src/features/auth/helpers.tsx +208 -0
  382. package/frontend/src/features/auth/hooks/useAnonToken.ts +30 -0
  383. package/frontend/src/features/auth/hooks/useAuthConfig.ts +48 -0
  384. package/frontend/src/features/auth/hooks/useOAuthConfig.ts +14 -10
  385. package/frontend/src/features/auth/hooks/useUsers.ts +43 -5
  386. package/frontend/src/features/auth/index.ts +3 -2
  387. package/frontend/src/features/auth/pages/AuthMethodsPage.tsx +275 -0
  388. package/frontend/src/features/auth/pages/ConfigurationPage.tsx +395 -0
  389. package/frontend/src/features/auth/pages/UsersPage.tsx +257 -0
  390. package/frontend/src/features/auth/services/anonToken.service.ts +11 -0
  391. package/frontend/src/features/auth/services/config.service.ts +19 -0
  392. package/frontend/src/features/auth/services/{oauth.service.ts → oauth-config.service.ts} +4 -4
  393. package/frontend/src/features/auth/services/{auth.service.ts → user.service.ts} +7 -53
  394. package/frontend/src/features/dashboard/components/ConnectionSuccessBanner.tsx +35 -0
  395. package/frontend/src/features/dashboard/components/PromptCard.tsx +21 -0
  396. package/frontend/src/features/dashboard/components/PromptDialog.tsx +103 -0
  397. package/frontend/src/features/dashboard/components/StatsCard.tsx +50 -0
  398. package/frontend/src/features/dashboard/components/index.ts +4 -0
  399. package/frontend/src/features/dashboard/pages/DashboardPage.tsx +212 -0
  400. package/frontend/src/features/dashboard/prompts/ai-chatbot.ts +13 -0
  401. package/frontend/src/features/dashboard/prompts/crm-system.ts +13 -0
  402. package/frontend/src/features/dashboard/prompts/ecommerce-platform.ts +12 -0
  403. package/frontend/src/features/dashboard/prompts/index.ts +31 -0
  404. package/frontend/src/features/dashboard/prompts/instagram-clone.ts +11 -0
  405. package/frontend/src/features/dashboard/prompts/notion-clone.ts +14 -0
  406. package/frontend/src/features/dashboard/prompts/reddit-clone.ts +12 -0
  407. package/frontend/src/features/database/components/DatabaseDataGrid.tsx +48 -17
  408. package/frontend/src/features/database/components/ForeignKeyCell.tsx +15 -34
  409. package/frontend/src/features/database/components/ForeignKeyPopover.tsx +19 -20
  410. package/frontend/src/features/database/components/LinkRecordModal.tsx +120 -125
  411. package/frontend/src/features/database/components/RecordFormDialog.tsx +22 -33
  412. package/frontend/src/features/database/components/RecordFormField.tsx +45 -47
  413. package/frontend/src/features/database/components/SQLModal.tsx +75 -0
  414. package/frontend/src/features/database/components/TableEmptyState.tsx +6 -5
  415. package/frontend/src/features/database/components/TableForm.tsx +28 -19
  416. package/frontend/src/features/database/components/TableFormColumn.tsx +2 -3
  417. package/frontend/src/features/database/components/TableSidebar.tsx +1 -1
  418. package/frontend/src/features/database/components/TablesEmptyState.tsx +48 -0
  419. package/frontend/src/features/database/components/TemplateCard.tsx +37 -0
  420. package/frontend/src/features/database/components/TemplatePreview.tsx +92 -0
  421. package/frontend/src/features/database/components/index.ts +19 -0
  422. package/frontend/src/features/database/constants.ts +28 -2
  423. package/frontend/src/features/database/contexts/SQLEditorContext.tsx +188 -0
  424. package/frontend/src/features/database/helpers.ts +2 -2
  425. package/frontend/src/features/database/hooks/useCSVImport.ts +29 -0
  426. package/frontend/src/features/database/hooks/useDatabase.ts +66 -0
  427. package/frontend/src/features/database/hooks/useRawSQL.ts +55 -0
  428. package/frontend/src/features/database/hooks/useRecords.ts +139 -0
  429. package/frontend/src/features/database/hooks/useTables.ts +135 -0
  430. package/frontend/src/features/database/index.ts +7 -1
  431. package/frontend/src/features/database/pages/FunctionsPage.tsx +203 -0
  432. package/frontend/src/features/database/pages/IndexesPage.tsx +228 -0
  433. package/frontend/src/features/database/pages/PoliciesPage.tsx +237 -0
  434. package/frontend/src/features/database/pages/SQLEditorPage.tsx +382 -0
  435. package/frontend/src/features/database/{page/DatabasePage.tsx → pages/TablesPage.tsx} +168 -209
  436. package/frontend/src/features/database/pages/TemplatesPage.tsx +39 -0
  437. package/frontend/src/features/database/pages/TriggersPage.tsx +230 -0
  438. package/frontend/src/features/database/services/advance.service.ts +40 -0
  439. package/frontend/src/features/database/services/database.service.ts +33 -194
  440. package/frontend/src/features/database/services/record.service.ts +219 -0
  441. package/frontend/src/features/database/services/table.service.ts +58 -0
  442. package/frontend/src/features/database/templates/ai-chatbot.ts +402 -0
  443. package/frontend/src/features/database/templates/crm-system.ts +528 -0
  444. package/frontend/src/features/database/templates/ecommerce-platform.ts +553 -0
  445. package/frontend/src/features/database/templates/index.ts +34 -0
  446. package/frontend/src/features/database/templates/instagram-clone.ts +222 -0
  447. package/frontend/src/features/database/templates/notion-clone.ts +483 -0
  448. package/frontend/src/features/database/templates/reddit-clone.ts +526 -0
  449. package/frontend/src/features/functions/components/FunctionRow.tsx +2 -1
  450. package/frontend/src/features/functions/components/FunctionsSidebar.tsx +1 -1
  451. package/frontend/src/features/functions/components/SecretRow.tsx +1 -1
  452. package/frontend/src/features/functions/components/index.ts +5 -0
  453. package/frontend/src/features/functions/hooks/useFunctions.ts +4 -4
  454. package/frontend/src/features/{secrets → functions}/hooks/useSecrets.ts +5 -5
  455. package/frontend/src/features/functions/pages/FunctionsPage.tsx +148 -0
  456. package/frontend/src/features/functions/{components/SecretsContent.tsx → pages/SecretsPage.tsx} +19 -21
  457. package/frontend/src/features/functions/services/{functions.service.ts → function.service.ts} +2 -2
  458. package/frontend/src/features/{secrets/services/secrets.service.ts → functions/services/secret.service.ts} +2 -2
  459. package/frontend/src/features/login/hooks/usePartnerOrigin.ts +27 -0
  460. package/frontend/src/features/login/pages/CloudLoginPage.tsx +118 -0
  461. package/frontend/src/features/login/{page → pages}/LoginPage.tsx +16 -23
  462. package/frontend/src/features/login/services/partnership.service.ts +65 -0
  463. package/frontend/src/features/logs/components/LogsDataGrid.tsx +89 -0
  464. package/frontend/src/features/logs/components/SeverityBadge.tsx +18 -0
  465. package/frontend/src/features/logs/components/index.ts +2 -0
  466. package/frontend/src/features/logs/helpers.ts +24 -0
  467. package/frontend/src/features/logs/hooks/useAuditLogs.ts +4 -4
  468. package/frontend/src/features/logs/hooks/useLogSources.ts +137 -0
  469. package/frontend/src/features/logs/hooks/useLogs.ts +163 -0
  470. package/frontend/src/features/logs/hooks/useMcpUsage.ts +128 -0
  471. package/frontend/src/features/logs/index.ts +8 -2
  472. package/frontend/src/features/logs/{page → pages}/AuditsPage.tsx +91 -38
  473. package/frontend/src/features/logs/pages/LogsPage.tsx +152 -0
  474. package/frontend/src/features/logs/pages/MCPLogsPage.tsx +84 -0
  475. package/frontend/src/features/logs/services/audit.service.ts +63 -0
  476. package/frontend/src/features/logs/services/log.service.ts +15 -110
  477. package/frontend/src/features/logs/services/usage.service.ts +31 -0
  478. package/frontend/src/features/onboard/components/McpConnectionStatus.tsx +68 -0
  479. package/frontend/src/features/onboard/components/OnboardingModal.tsx +267 -0
  480. package/frontend/src/features/onboard/components/VideoDemoModal.tsx +38 -0
  481. package/frontend/src/features/onboard/components/index.ts +4 -0
  482. package/frontend/src/features/onboard/components/mcp/CursorDeeplinkGenerator.tsx +2 -2
  483. package/frontend/src/features/onboard/components/mcp/{mcp-helper.tsx → helpers.tsx} +8 -8
  484. package/frontend/src/features/onboard/components/mcp/index.ts +2 -3
  485. package/frontend/src/features/onboard/index.ts +13 -3
  486. package/frontend/src/features/realtime/components/ChannelRow.tsx +83 -0
  487. package/frontend/src/features/realtime/components/EditChannelModal.tsx +246 -0
  488. package/frontend/src/features/realtime/components/MessageRow.tsx +85 -0
  489. package/frontend/src/features/realtime/components/RealtimeEmptyState.tsx +30 -0
  490. package/frontend/src/features/realtime/hooks/useRealtime.ts +218 -0
  491. package/frontend/src/features/realtime/index.ts +11 -0
  492. package/frontend/src/features/realtime/pages/RealtimeChannelsPage.tsx +172 -0
  493. package/frontend/src/features/realtime/pages/RealtimeMessagesPage.tsx +211 -0
  494. package/frontend/src/features/realtime/pages/RealtimePermissionsPage.tsx +191 -0
  495. package/frontend/src/features/realtime/services/realtime.service.ts +107 -0
  496. package/frontend/src/features/storage/components/BucketEmptyState.tsx +9 -6
  497. package/frontend/src/features/storage/components/BucketFormDialog.tsx +25 -41
  498. package/frontend/src/features/storage/components/FilePreviewDialog.tsx +20 -8
  499. package/frontend/src/features/storage/components/StorageDataGrid.tsx +4 -3
  500. package/frontend/src/features/storage/components/StorageManager.tsx +23 -34
  501. package/frontend/src/features/storage/components/index.ts +12 -0
  502. package/frontend/src/features/storage/hooks/useStorage.ts +208 -0
  503. package/frontend/src/features/storage/{page → pages}/StoragePage.tsx +41 -143
  504. package/frontend/src/features/storage/services/storage.service.ts +22 -1
  505. package/frontend/src/features/visualizer/components/AuthNode.tsx +72 -56
  506. package/frontend/src/features/visualizer/components/BucketNode.tsx +4 -4
  507. package/frontend/src/features/visualizer/components/SchemaVisualizer.tsx +108 -80
  508. package/frontend/src/features/visualizer/components/TableNode.tsx +34 -41
  509. package/frontend/src/features/visualizer/components/VisualizerSkeleton.tsx +12 -4
  510. package/frontend/src/features/visualizer/pages/VisualizerPage.tsx +97 -0
  511. package/frontend/src/index.css +1 -0
  512. package/frontend/src/lib/analytics/posthog.tsx +27 -0
  513. package/frontend/src/lib/contexts/AuthContext.tsx +38 -31
  514. package/frontend/src/lib/contexts/SocketContext.tsx +123 -80
  515. package/frontend/src/{features/metadata → lib}/hooks/useMetadata.ts +1 -1
  516. package/frontend/src/lib/hooks/useToast.tsx +6 -2
  517. package/frontend/src/lib/routing/AppRoutes.tsx +99 -0
  518. package/frontend/src/lib/routing/RequireAuth.tsx +27 -0
  519. package/frontend/src/lib/utils/cloudMessaging.ts +20 -0
  520. package/frontend/src/lib/utils/menuItems.ts +207 -0
  521. package/frontend/src/lib/utils/{validation-schemas.ts → schemaValidations.ts} +10 -5
  522. package/frontend/src/lib/utils/utils.ts +32 -1
  523. package/frontend/src/vite-env.d.ts +1 -0
  524. package/frontend/tsconfig.json +25 -25
  525. package/frontend/tsconfig.node.json +9 -9
  526. package/frontend/vite.config.ts +5 -3
  527. package/functions/deno.json +24 -24
  528. package/functions/server.ts +315 -290
  529. package/functions/worker-template.js +15 -4
  530. package/i18n/README.ar.md +130 -0
  531. package/i18n/README.de.md +130 -0
  532. package/i18n/README.es.md +154 -0
  533. package/i18n/README.fr.md +134 -0
  534. package/i18n/README.hi.md +129 -0
  535. package/i18n/README.ja.md +174 -0
  536. package/i18n/README.ko.md +137 -0
  537. package/i18n/README.pt-BR.md +131 -0
  538. package/i18n/README.ru.md +129 -0
  539. package/i18n/README.zh-CN.md +133 -0
  540. package/openapi/ai.yaml +715 -688
  541. package/openapi/auth.yaml +1244 -563
  542. package/openapi/email.yaml +158 -0
  543. package/openapi/functions.yaml +475 -475
  544. package/openapi/health.yaml +29 -29
  545. package/openapi/logs.yaml +223 -223
  546. package/openapi/metadata.yaml +177 -177
  547. package/openapi/realtime.yaml +699 -0
  548. package/openapi/records.yaml +381 -381
  549. package/openapi/secrets.yaml +370 -370
  550. package/openapi/storage.yaml +875 -875
  551. package/openapi/tables.yaml +463 -463
  552. package/package.json +97 -88
  553. package/shared-schemas/package.json +31 -31
  554. package/shared-schemas/src/ai-api.schema.ts +34 -58
  555. package/shared-schemas/src/ai.schema.ts +63 -54
  556. package/shared-schemas/src/auth-api.schema.ts +352 -193
  557. package/shared-schemas/src/auth.schema.ts +43 -7
  558. package/shared-schemas/src/cloud-events.schema.ts +57 -0
  559. package/shared-schemas/src/database-api.schema.ts +35 -4
  560. package/shared-schemas/src/database.schema.ts +40 -1
  561. package/shared-schemas/src/docs.schema.ts +26 -0
  562. package/shared-schemas/src/email-api.schema.ts +30 -0
  563. package/shared-schemas/src/index.ts +5 -0
  564. package/shared-schemas/src/logs-api.schema.ts +7 -1
  565. package/shared-schemas/src/logs.schema.ts +26 -0
  566. package/shared-schemas/src/metadata.schema.ts +18 -4
  567. package/shared-schemas/src/realtime-api.schema.ts +111 -0
  568. package/shared-schemas/src/realtime.schema.ts +143 -0
  569. package/shared-schemas/tsconfig.json +21 -21
  570. package/tsconfig.json +7 -7
  571. package/zeabur/README.md +13 -0
  572. package/zeabur/template.yml +1032 -0
  573. package/.github/workflows/deploy-aws.yml +0 -130
  574. package/backend/src/api/routes/agent.ts +0 -29
  575. package/backend/src/api/routes/auth.oauth.ts +0 -482
  576. package/backend/src/api/routes/auth.ts +0 -386
  577. package/backend/src/api/routes/docs.ts +0 -66
  578. package/backend/src/api/routes/functions.ts +0 -183
  579. package/backend/src/api/routes/openapi.ts +0 -82
  580. package/backend/src/api/routes/usage.ts +0 -96
  581. package/backend/src/core/ai/client.ts +0 -242
  582. package/backend/src/core/ai/model.ts +0 -117
  583. package/backend/src/core/auth/auth.ts +0 -780
  584. package/backend/src/core/database/manager.ts +0 -178
  585. package/backend/src/core/database/table.ts +0 -772
  586. package/backend/src/core/documentation/agent.ts +0 -689
  587. package/backend/src/core/documentation/openapi.ts +0 -856
  588. package/backend/src/core/logs/analytics.ts +0 -76
  589. package/backend/src/core/logs/providers/localdb.provider.ts +0 -246
  590. package/backend/src/core/socket/socket.ts +0 -388
  591. package/backend/src/core/storage/storage.ts +0 -923
  592. package/backend/src/utils/cloud-token.ts +0 -39
  593. package/backend/src/utils/helpers.ts +0 -49
  594. package/backend/src/utils/uuid.ts +0 -9
  595. package/backend/tests/manual/test-better-auth.sh +0 -303
  596. package/docker-init/db/logs.sql +0 -9
  597. package/frontend/README.md +0 -112
  598. package/frontend/src/components/datagrid/index.tsx +0 -20
  599. package/frontend/src/components/layout/CloudLayout.tsx +0 -95
  600. package/frontend/src/features/ai/components/AIConfigDialog.tsx +0 -76
  601. package/frontend/src/features/ai/components/AIConfigForm.tsx +0 -222
  602. package/frontend/src/features/ai/components/fields/ModalityField.tsx +0 -87
  603. package/frontend/src/features/ai/components/fields/ModelSelectionField.tsx +0 -134
  604. package/frontend/src/features/ai/components/fields/SystemPromptField.tsx +0 -33
  605. package/frontend/src/features/ai/page/AIPage.tsx +0 -178
  606. package/frontend/src/features/auth/components/AddOAuthDialog.tsx +0 -106
  607. package/frontend/src/features/auth/components/AuthMethodTab.tsx +0 -238
  608. package/frontend/src/features/auth/components/UsersTab.tsx +0 -114
  609. package/frontend/src/features/auth/page/AuthenticationPage.tsx +0 -169
  610. package/frontend/src/features/dashboard/page/DashboardPage.tsx +0 -194
  611. package/frontend/src/features/database/hooks/UseLinkModal.tsx +0 -78
  612. package/frontend/src/features/functions/components/FunctionViewer.tsx +0 -46
  613. package/frontend/src/features/functions/components/FunctionsContent.tsx +0 -88
  614. package/frontend/src/features/functions/page/FunctionsPage.tsx +0 -28
  615. package/frontend/src/features/login/components/AuthErrorBoundary.tsx +0 -87
  616. package/frontend/src/features/login/components/PrivateRoute.tsx +0 -24
  617. package/frontend/src/features/login/page/CloudLoginPage.tsx +0 -93
  618. package/frontend/src/features/logs/components/AnalyticsLogsTable.tsx +0 -313
  619. package/frontend/src/features/logs/components/LogsTable.tsx +0 -199
  620. package/frontend/src/features/logs/page/AnalyticsLogsPage.tsx +0 -530
  621. package/frontend/src/features/metadata/index.ts +0 -0
  622. package/frontend/src/features/metadata/page/MetadataPage.tsx +0 -136
  623. package/frontend/src/features/onboard/components/CompletionCard.tsx +0 -41
  624. package/frontend/src/features/onboard/components/OnboardButton.tsx +0 -84
  625. package/frontend/src/features/onboard/components/StepContent.tsx +0 -91
  626. package/frontend/src/features/onboard/components/TestConnectionStep.tsx +0 -53
  627. package/frontend/src/features/onboard/components/mcp/McpInstallation.tsx +0 -144
  628. package/frontend/src/features/onboard/page/OnBoardPage.tsx +0 -104
  629. package/frontend/src/features/onboard/types.ts +0 -8
  630. package/frontend/src/features/visualizer/page/VisualizerPage.tsx +0 -127
  631. package/frontend/src/lib/contexts/OnboardStepContext.tsx +0 -68
  632. package/frontend/src/lib/hooks/useOnboardingCompletion.ts +0 -29
  633. /package/backend/src/api/{middleware → middlewares}/error.ts +0 -0
  634. /package/backend/src/api/{middleware → middlewares}/upload.ts +0 -0
  635. /package/frontend/src/{features/metadata → lib}/services/metadata.service.ts +0 -0
@@ -0,0 +1,233 @@
1
+ -- Migration 017: Create Realtime Schema
2
+ --
3
+ -- Creates the realtime schema with:
4
+ -- 1. channels table - Channel definitions with webhook configuration
5
+ -- 2. messages table - All realtime messages with delivery statistics
6
+ -- 3. publish() function - Called by developer triggers to publish events
7
+ --
8
+ -- Permission Model (Supabase pattern):
9
+ -- - SELECT on channels = 'subscribe' permission (subscribe to channel)
10
+ -- - INSERT on messages = 'publish' permission (publish to channel)
11
+ -- Developers define RLS policies on channels/messages table to control access.
12
+
13
+ -- ============================================================================
14
+ -- CREATE SCHEMA
15
+ -- ============================================================================
16
+
17
+ CREATE SCHEMA IF NOT EXISTS realtime;
18
+
19
+ -- ============================================================================
20
+ -- CHANNELS TABLE
21
+ -- ============================================================================
22
+ -- Stores channel definitions with delivery configuration.
23
+ -- RLS policies control subscribe permissions.
24
+ -- - SELECT policy = 'subscribe' permission (can subscribe to channel)
25
+ -- Channel names use : as separator and % for wildcards (LIKE pattern).
26
+ -- Examples: "orders", "order:%", "chat:%:messages"
27
+
28
+ CREATE TABLE IF NOT EXISTS realtime.channels (
29
+ id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
30
+
31
+ -- Channel name pattern (e.g., "orders", "order:%", "chat:%:messages")
32
+ -- Convention: use : as separator, % for wildcards (LIKE pattern)
33
+ pattern TEXT UNIQUE NOT NULL,
34
+
35
+ -- Human-readable description
36
+ description TEXT,
37
+
38
+ -- Webhook URLs to POST events to (NULL or empty array = no webhooks)
39
+ webhook_urls TEXT[],
40
+
41
+ -- Whether this channel is active
42
+ enabled BOOLEAN DEFAULT TRUE NOT NULL,
43
+
44
+ created_at TIMESTAMPTZ DEFAULT NOW(),
45
+ updated_at TIMESTAMPTZ DEFAULT NOW()
46
+ );
47
+
48
+ -- ============================================================================
49
+ -- MESSAGES TABLE
50
+ -- ============================================================================
51
+ -- Stores all realtime messages published through the system.
52
+ -- RLS policies on this table control publish permissions:
53
+ -- - INSERT policy = 'publish' permission (can publish to channel)
54
+
55
+ CREATE TABLE IF NOT EXISTS realtime.messages (
56
+ id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
57
+
58
+ -- Event metadata
59
+ event_name TEXT NOT NULL,
60
+
61
+ -- Channel reference (SET NULL on delete to preserve history)
62
+ channel_id UUID REFERENCES realtime.channels(id) ON DELETE SET NULL,
63
+ channel_name TEXT NOT NULL, -- Denormalized for query convenience after channel deletion
64
+
65
+ -- Event payload (stored for audit/replay purposes)
66
+ payload JSONB DEFAULT '{}'::jsonb NOT NULL,
67
+
68
+ -- Sender information
69
+ -- 'system' = triggered by database trigger (via publish() function)
70
+ -- 'user' = published by client via WebSocket
71
+ sender_type TEXT DEFAULT 'system' NOT NULL CHECK (sender_type IN ('system', 'user')),
72
+ sender_id UUID, -- User ID for 'user' type, NULL for 'system' type
73
+
74
+ -- Delivery statistics for WebSocket
75
+ ws_audience_count INTEGER DEFAULT 0 NOT NULL, -- How many clients were subscribed
76
+
77
+ -- Delivery statistics for Webhooks
78
+ wh_audience_count INTEGER DEFAULT 0 NOT NULL, -- How many webhook URLs configured
79
+ wh_delivered_count INTEGER DEFAULT 0 NOT NULL, -- How many succeeded (2xx response)
80
+
81
+ created_at TIMESTAMPTZ DEFAULT NOW()
82
+ );
83
+
84
+ -- ============================================================================
85
+ -- INDEXES
86
+ -- ============================================================================
87
+
88
+ CREATE INDEX IF NOT EXISTS idx_realtime_channels_pattern ON realtime.channels(pattern);
89
+ CREATE INDEX IF NOT EXISTS idx_realtime_channels_enabled ON realtime.channels(enabled);
90
+ CREATE INDEX IF NOT EXISTS idx_realtime_messages_channel_id ON realtime.messages(channel_id);
91
+ CREATE INDEX IF NOT EXISTS idx_realtime_messages_channel_name ON realtime.messages(channel_name);
92
+ CREATE INDEX IF NOT EXISTS idx_realtime_messages_created_at ON realtime.messages(created_at DESC);
93
+ CREATE INDEX IF NOT EXISTS idx_realtime_messages_event_name ON realtime.messages(event_name);
94
+ CREATE INDEX IF NOT EXISTS idx_realtime_messages_sender ON realtime.messages(sender_type, sender_id);
95
+
96
+ -- ============================================================================
97
+ -- UPDATED_AT TRIGGER
98
+ -- ============================================================================
99
+
100
+ CREATE OR REPLACE FUNCTION realtime.update_updated_at()
101
+ RETURNS TRIGGER AS $$
102
+ BEGIN
103
+ NEW.updated_at = NOW();
104
+ RETURN NEW;
105
+ END;
106
+ $$ LANGUAGE plpgsql;
107
+
108
+ DROP TRIGGER IF EXISTS trg_channels_updated_at ON realtime.channels;
109
+ CREATE TRIGGER trg_channels_updated_at
110
+ BEFORE UPDATE ON realtime.channels
111
+ FOR EACH ROW EXECUTE FUNCTION realtime.update_updated_at();
112
+
113
+ -- ============================================================================
114
+ -- ROW LEVEL SECURITY (DISABLED BY DEFAULT)
115
+ -- ============================================================================
116
+ -- RLS is disabled by default for the best developer experience.
117
+ -- Channels and messages are open to all authenticated/anon users out of the box.
118
+ --
119
+ -- To enable access control, developers can:
120
+ -- 1. Enable RLS: ALTER TABLE realtime.channels ENABLE ROW LEVEL SECURITY;
121
+ -- 2. Add policies using the helper function realtime.channel_name()
122
+ --
123
+ -- See documentation for policy examples.
124
+
125
+ -- ============================================================================
126
+ -- HELPER FUNCTIONS FOR RLS POLICIES
127
+ -- ============================================================================
128
+
129
+ -- Returns the channel name being accessed (set by backend during permission checks)
130
+ -- Developers use this in policies instead of writing current_setting directly
131
+ CREATE OR REPLACE FUNCTION realtime.channel_name()
132
+ RETURNS TEXT AS $$
133
+ SELECT current_setting('realtime.channel_name', true);
134
+ $$ LANGUAGE SQL STABLE;
135
+
136
+ -- ============================================================================
137
+ -- PUBLISH FUNCTION
138
+ -- ============================================================================
139
+ -- Called by developer triggers to publish events to channels.
140
+ -- This function can only be executed by the backend (SECURITY DEFINER).
141
+ --
142
+ -- Usage in a trigger:
143
+ -- PERFORM realtime.publish(
144
+ -- 'order:' || NEW.id::text, -- channel name (resolved instance)
145
+ -- 'order_updated', -- event name
146
+ -- jsonb_build_object('id', NEW.id, 'status', NEW.status) -- payload
147
+ -- );
148
+
149
+ CREATE OR REPLACE FUNCTION realtime.publish(
150
+ p_channel_name TEXT,
151
+ p_event_name TEXT,
152
+ p_payload JSONB
153
+ )
154
+ RETURNS UUID AS $$
155
+ DECLARE
156
+ v_channel_id UUID;
157
+ v_message_id UUID;
158
+ BEGIN
159
+ -- Find matching channel: exact match first, then wildcard pattern match
160
+ -- For wildcard patterns like "order:%", check if p_channel_name LIKE pattern
161
+ SELECT id INTO v_channel_id
162
+ FROM realtime.channels
163
+ WHERE enabled = TRUE
164
+ AND (pattern = p_channel_name OR p_channel_name LIKE pattern)
165
+ ORDER BY pattern = p_channel_name DESC
166
+ LIMIT 1;
167
+
168
+ -- If no channel found, raise a warning and return NULL
169
+ IF v_channel_id IS NULL THEN
170
+ RAISE WARNING 'Realtime: No matching channel found for "%"', p_channel_name;
171
+ RETURN NULL;
172
+ END IF;
173
+
174
+ -- Insert message record (system-triggered, so sender_type = 'system')
175
+ INSERT INTO realtime.messages (
176
+ event_name,
177
+ channel_id,
178
+ channel_name,
179
+ payload,
180
+ sender_type
181
+ ) VALUES (
182
+ p_event_name,
183
+ v_channel_id,
184
+ p_channel_name,
185
+ p_payload,
186
+ 'system'
187
+ )
188
+ RETURNING id INTO v_message_id;
189
+
190
+ RETURN v_message_id;
191
+ END;
192
+ $$ LANGUAGE plpgsql SECURITY DEFINER;
193
+
194
+ -- Revoke execute from public, only backend can call this
195
+ REVOKE ALL ON FUNCTION realtime.publish FROM PUBLIC;
196
+
197
+ -- ============================================================================
198
+ -- TRIGGER FOR PG_NOTIFY
199
+ -- ============================================================================
200
+ -- Trigger function that sends pg_notify for every new message (both system and client).
201
+
202
+ CREATE OR REPLACE FUNCTION realtime.notify_on_message_insert()
203
+ RETURNS TRIGGER AS $$
204
+ BEGIN
205
+ -- Send only message_id to bypass pg_notify 8KB payload limit
206
+ -- Backend will fetch full message from DB
207
+ PERFORM pg_notify('realtime_message', NEW.id::text);
208
+ RETURN NEW;
209
+ END;
210
+ $$ LANGUAGE plpgsql;
211
+
212
+ -- Create trigger on messages table
213
+ DROP TRIGGER IF EXISTS trg_message_notify ON realtime.messages;
214
+ CREATE TRIGGER trg_message_notify
215
+ AFTER INSERT ON realtime.messages
216
+ FOR EACH ROW
217
+ EXECUTE FUNCTION realtime.notify_on_message_insert();
218
+
219
+ -- ============================================================================
220
+ -- GRANTS
221
+ -- ============================================================================
222
+
223
+ -- Grant schema access to both authenticated and anonymous users
224
+ GRANT USAGE ON SCHEMA realtime TO authenticated, anon;
225
+
226
+ -- Grant SELECT on channels table (allows subscribe)
227
+ GRANT SELECT ON realtime.channels TO authenticated, anon;
228
+
229
+ -- Grant INSERT on messages table (allows publish)
230
+ GRANT INSERT ON realtime.messages TO authenticated, anon;
231
+
232
+ -- Grant execution permission on helper function (used when RLS is enabled)
233
+ GRANT EXECUTE ON FUNCTION realtime.channel_name() TO authenticated, anon;
@@ -0,0 +1,246 @@
1
+ import type { Client } from 'pg';
2
+ import { SocketManager } from '@/infra/socket/socket.manager.js';
3
+ import { WebhookSender } from './webhook-sender.js';
4
+ import { DatabaseManager } from '@/infra/database/database.manager.js';
5
+ import { RealtimeChannelService } from '@/services/realtime/realtime-channel.service.js';
6
+ import { RealtimeMessageService } from '@/services/realtime/realtime-message.service.js';
7
+ import logger from '@/utils/logger.js';
8
+ import type { RealtimeMessage, RealtimeChannel, WebhookMessage } from '@insforge/shared-schemas';
9
+ import type { DeliveryResult } from '@/types/realtime.js';
10
+
11
+ /**
12
+ * RealtimeManager - Listens to pg_notify and publishes messages to WebSocket/webhooks
13
+ *
14
+ * This is a singleton that:
15
+ * 1. Maintains a dedicated PostgreSQL connection for LISTEN
16
+ * 2. Receives notifications from realtime.publish() function
17
+ * 3. Publishes messages to WebSocket clients (via Socket.IO rooms)
18
+ * 4. Publishes messages to webhook URLs (via HTTP POST)
19
+ * 5. Updates message records with delivery statistics
20
+ */
21
+ export class RealtimeManager {
22
+ private static instance: RealtimeManager;
23
+ private listenerClient: Client | null = null;
24
+ private isConnected = false;
25
+ private reconnectTimeout: NodeJS.Timeout | null = null;
26
+ private reconnectAttempts = 0;
27
+ private readonly maxReconnectAttempts = 10;
28
+ private readonly baseReconnectDelay = 5000;
29
+ private webhookSender: WebhookSender;
30
+
31
+ private constructor() {
32
+ this.webhookSender = new WebhookSender();
33
+ }
34
+
35
+ static getInstance(): RealtimeManager {
36
+ if (!RealtimeManager.instance) {
37
+ RealtimeManager.instance = new RealtimeManager();
38
+ }
39
+ return RealtimeManager.instance;
40
+ }
41
+
42
+ /**
43
+ * Initialize the realtime manager and start listening for pg_notify
44
+ */
45
+ async initialize(): Promise<void> {
46
+ if (this.isConnected) {
47
+ return;
48
+ }
49
+
50
+ // Create a dedicated client for LISTEN (cannot use pooled connections)
51
+ this.listenerClient = DatabaseManager.getInstance().createClient();
52
+
53
+ try {
54
+ await this.listenerClient.connect();
55
+ await this.listenerClient.query('LISTEN realtime_message');
56
+ this.isConnected = true;
57
+ this.reconnectAttempts = 0;
58
+
59
+ this.listenerClient.on('notification', (msg) => {
60
+ if (msg.channel === 'realtime_message' && msg.payload) {
61
+ void this.handlePGNotification(msg.payload);
62
+ }
63
+ });
64
+
65
+ this.listenerClient.on('error', (error) => {
66
+ logger.error('RealtimeManager connection error', { error: error.message });
67
+ this.handleDisconnect();
68
+ });
69
+
70
+ this.listenerClient.on('end', () => {
71
+ logger.warn('RealtimeManager connection ended');
72
+ this.handleDisconnect();
73
+ });
74
+
75
+ logger.info('RealtimeManager initialized and listening');
76
+ } catch (error) {
77
+ logger.error('Failed to initialize RealtimeManager', { error });
78
+ this.handleDisconnect();
79
+ }
80
+ }
81
+
82
+ /**
83
+ * Handle incoming pg_notify notification
84
+ * Payload is just the message_id (UUID string) to bypass 8KB limit
85
+ */
86
+ private async handlePGNotification(messageId: string): Promise<void> {
87
+ try {
88
+ // 1. Fetch message and channel in parallel
89
+ // channelId is guaranteed non-null for fresh messages (publish/insertMessage validate channel)
90
+ const message = await RealtimeMessageService.getInstance().getById(messageId);
91
+
92
+ if (!message || !message.channelId) {
93
+ logger.warn('Message not found or invalid for realtime notification', { messageId });
94
+ return;
95
+ }
96
+
97
+ // 2. Look up channel configuration (for enabled check and webhook URLs)
98
+ const channel = await RealtimeChannelService.getInstance().getById(message.channelId);
99
+
100
+ if (!channel?.enabled) {
101
+ logger.debug('Channel not found or disabled, skipping', { channelId: message.channelId });
102
+ return;
103
+ }
104
+
105
+ // 3. Publish to WebSocket and/or Webhooks
106
+ const result = await this.publishMessage(message, channel);
107
+
108
+ // 4. Update message record with delivery stats
109
+ await RealtimeMessageService.getInstance().updateDeliveryStats(messageId, result);
110
+
111
+ logger.debug('Realtime message published', {
112
+ messageId,
113
+ channelName: message.channelName,
114
+ eventName: message.eventName,
115
+ ...result,
116
+ });
117
+ } catch (error) {
118
+ logger.error('Failed to publish realtime message', { error, messageId });
119
+ }
120
+ }
121
+
122
+ /**
123
+ * Publish message to WebSocket clients and webhook URLs
124
+ */
125
+ private async publishMessage(
126
+ message: RealtimeMessage,
127
+ channel: RealtimeChannel
128
+ ): Promise<DeliveryResult> {
129
+ const result: DeliveryResult = {
130
+ wsAudienceCount: 0,
131
+ whAudienceCount: 0,
132
+ whDeliveredCount: 0,
133
+ };
134
+
135
+ // Publish to WebSocket clients
136
+ result.wsAudienceCount = this.publishToWebSocket(message);
137
+
138
+ // Publish to Webhook URLs if configured
139
+ if (channel.webhookUrls && channel.webhookUrls.length > 0) {
140
+ const webhookPayload: WebhookMessage = {
141
+ messageId: message.id,
142
+ channel: message.channelName,
143
+ eventName: message.eventName,
144
+ payload: message.payload,
145
+ };
146
+ const whResult = await this.publishToWebhooks(channel.webhookUrls, webhookPayload);
147
+ result.whAudienceCount = whResult.audienceCount;
148
+ result.whDeliveredCount = whResult.deliveredCount;
149
+ }
150
+
151
+ return result;
152
+ }
153
+
154
+ /**
155
+ * Publish message to WebSocket clients subscribed to the channel
156
+ * Returns the number of clients in the room (audience count)
157
+ */
158
+ private publishToWebSocket(message: RealtimeMessage): number {
159
+ const socketManager = SocketManager.getInstance();
160
+ const roomName = `realtime:${message.channelName}`;
161
+
162
+ const audienceCount = socketManager.getRoomSize(roomName);
163
+
164
+ if (audienceCount > 0) {
165
+ socketManager.broadcastToRoom(
166
+ roomName,
167
+ message.eventName,
168
+ message.payload,
169
+ message.senderType,
170
+ message.senderId ?? undefined,
171
+ message.id
172
+ );
173
+ }
174
+
175
+ return audienceCount;
176
+ }
177
+
178
+ /**
179
+ * Publish message to all configured webhook URLs
180
+ */
181
+ private async publishToWebhooks(
182
+ urls: string[],
183
+ message: WebhookMessage
184
+ ): Promise<{ audienceCount: number; deliveredCount: number }> {
185
+ const audienceCount = urls.length;
186
+ const results = await this.webhookSender.sendToAll(urls, message);
187
+ const deliveredCount = results.filter((r) => r.success).length;
188
+
189
+ return { audienceCount, deliveredCount };
190
+ }
191
+
192
+ /**
193
+ * Handle disconnection and attempt reconnection
194
+ */
195
+ private handleDisconnect(): void {
196
+ this.isConnected = false;
197
+
198
+ if (this.listenerClient) {
199
+ this.listenerClient.removeAllListeners();
200
+ this.listenerClient = null;
201
+ }
202
+
203
+ // Reconnect with exponential backoff
204
+ if (this.reconnectAttempts < this.maxReconnectAttempts) {
205
+ const delay = this.baseReconnectDelay * Math.pow(2, this.reconnectAttempts);
206
+ this.reconnectAttempts++;
207
+
208
+ if (!this.reconnectTimeout) {
209
+ this.reconnectTimeout = setTimeout(() => {
210
+ this.reconnectTimeout = null;
211
+ logger.info(
212
+ `Attempting to reconnect RealtimeManager (attempt ${this.reconnectAttempts})...`
213
+ );
214
+ void this.initialize();
215
+ }, delay);
216
+ }
217
+ } else {
218
+ logger.error('RealtimeManager max reconnect attempts reached');
219
+ }
220
+ }
221
+
222
+ /**
223
+ * Close the realtime manager connection
224
+ */
225
+ async close(): Promise<void> {
226
+ if (this.reconnectTimeout) {
227
+ clearTimeout(this.reconnectTimeout);
228
+ this.reconnectTimeout = null;
229
+ }
230
+
231
+ if (this.listenerClient) {
232
+ this.listenerClient.removeAllListeners();
233
+ await this.listenerClient.end();
234
+ this.listenerClient = null;
235
+ this.isConnected = false;
236
+ logger.info('RealtimeManager closed');
237
+ }
238
+ }
239
+
240
+ /**
241
+ * Check if the manager is connected and healthy
242
+ */
243
+ isHealthy(): boolean {
244
+ return this.isConnected;
245
+ }
246
+ }
@@ -0,0 +1,82 @@
1
+ import axios, { AxiosError } from 'axios';
2
+ import logger from '@/utils/logger.js';
3
+ import type { WebhookMessage } from '@insforge/shared-schemas';
4
+
5
+ export interface WebhookResult {
6
+ url: string;
7
+ success: boolean;
8
+ statusCode?: number;
9
+ error?: string;
10
+ }
11
+
12
+ /**
13
+ * WebhookSender - Handles HTTP delivery of realtime messages to webhook endpoints
14
+ */
15
+ export class WebhookSender {
16
+ private readonly timeout = 10000; // 10 seconds
17
+ private readonly maxRetries = 2;
18
+
19
+ /**
20
+ * Send message to all webhook URLs in parallel
21
+ */
22
+ async sendToAll(urls: string[], message: WebhookMessage): Promise<WebhookResult[]> {
23
+ const promises = urls.map((url) => this.send(url, message));
24
+ return Promise.all(promises);
25
+ }
26
+
27
+ /**
28
+ * Send message to a single webhook URL with retry logic
29
+ */
30
+ private async send(url: string, message: WebhookMessage): Promise<WebhookResult> {
31
+ let lastError: string | undefined;
32
+
33
+ for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
34
+ try {
35
+ const response = await axios.post(url, message.payload, {
36
+ timeout: this.timeout,
37
+ headers: {
38
+ 'Content-Type': 'application/json',
39
+ 'X-InsForge-Event': message.eventName,
40
+ 'X-InsForge-Channel': message.channel,
41
+ 'X-InsForge-Message-Id': message.messageId,
42
+ },
43
+ });
44
+
45
+ return {
46
+ url,
47
+ success: response.status >= 200 && response.status < 300,
48
+ statusCode: response.status,
49
+ };
50
+ } catch (error) {
51
+ const axiosError = error as AxiosError;
52
+ lastError = axiosError.message;
53
+
54
+ if (axiosError.response) {
55
+ // Server responded with error status - don't retry
56
+ return {
57
+ url,
58
+ success: false,
59
+ statusCode: axiosError.response.status,
60
+ error: `HTTP ${axiosError.response.status}`,
61
+ };
62
+ }
63
+
64
+ // Network error - retry with backoff
65
+ if (attempt < this.maxRetries) {
66
+ await this.delay(1000 * (attempt + 1)); // 1s, 2s
67
+ }
68
+ }
69
+ }
70
+ logger.warn('Webhook delivery failed after retries', { url, error: lastError });
71
+
72
+ return {
73
+ url,
74
+ success: false,
75
+ error: lastError,
76
+ };
77
+ }
78
+
79
+ private delay(ms: number): Promise<void> {
80
+ return new Promise((resolve) => setTimeout(resolve, ms));
81
+ }
82
+ }
@@ -1,9 +1,10 @@
1
1
  import crypto from 'crypto';
2
2
 
3
3
  /**
4
- * Encryption utilities for secrets management
4
+ * EncryptionManager - Handles encryption/decryption operations
5
+ * Infrastructure layer for secrets encryption
5
6
  */
6
- export class EncryptionUtils {
7
+ export class EncryptionManager {
7
8
  private static encryptionKey: Buffer | null = null;
8
9
 
9
10
  private static getEncryptionKey(): Buffer {