insforge 1.2.10 → 1.4.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (506) hide show
  1. package/.claude-plugin/marketplace.json +20 -20
  2. package/.dockerignore +60 -60
  3. package/.env.example +83 -77
  4. package/.github/ISSUE_TEMPLATE/bug_report.yml +36 -36
  5. package/.github/ISSUE_TEMPLATE/config.yml +11 -11
  6. package/.github/ISSUE_TEMPLATE/feature_request.yml +26 -26
  7. package/.github/PULL_REQUEST_TEMPLATE.md +7 -7
  8. package/.github/copilot-instructions.md +146 -146
  9. package/.github/workflows/build-image.yml +65 -65
  10. package/.github/workflows/ci-premerge-check.yml +23 -23
  11. package/.github/workflows/e2e.yml +63 -63
  12. package/.github/workflows/lint-and-format.yml +32 -32
  13. package/.prettierignore +64 -64
  14. package/CHANGELOG.md +46 -44
  15. package/CLAUDE_PLUGIN.md +104 -104
  16. package/CODE_OF_CONDUCT.md +128 -128
  17. package/CONTRIBUTING.md +125 -125
  18. package/Dockerfile +30 -30
  19. package/GITHUB_OAUTH_SETUP.md +49 -49
  20. package/GOOGLE_OAUTH_SETUP.md +148 -148
  21. package/LICENSE +201 -201
  22. package/README.md +182 -182
  23. package/assets/Dark.svg +23 -23
  24. package/auth/package.json +30 -28
  25. package/auth/src/lib/broadcastService.ts +4 -4
  26. package/auth/src/lib/insforge.ts +8 -0
  27. package/auth/src/main.tsx +2 -4
  28. package/auth/src/pages/SignInPage.tsx +5 -2
  29. package/auth/src/pages/SignUpPage.tsx +5 -2
  30. package/auth/src/pages/VerifyEmailPage.tsx +18 -0
  31. package/auth/tsconfig.json +33 -32
  32. package/auth/tsconfig.node.json +11 -11
  33. package/backend/package.json +82 -75
  34. package/backend/src/api/middlewares/rate-limiters.ts +127 -127
  35. package/backend/src/api/routes/ai/index.routes.ts +475 -468
  36. package/backend/src/api/routes/auth/index.routes.ts +720 -570
  37. package/backend/src/api/routes/auth/oauth.routes.ts +478 -448
  38. package/backend/src/api/routes/database/advance.routes.ts +37 -16
  39. package/backend/src/api/routes/database/index.routes.ts +80 -1
  40. package/backend/src/api/routes/database/records.routes.ts +48 -184
  41. package/backend/src/api/routes/database/rpc.routes.ts +69 -0
  42. package/backend/src/api/routes/database/tables.routes.ts +0 -14
  43. package/backend/src/api/routes/deployments/index.routes.ts +192 -0
  44. package/backend/src/api/routes/docs/index.routes.ts +76 -76
  45. package/backend/src/api/routes/email/index.routes.ts +35 -0
  46. package/backend/src/api/routes/functions/index.routes.ts +21 -15
  47. package/backend/src/api/routes/metadata/index.routes.ts +38 -0
  48. package/backend/src/api/routes/realtime/channels.routes.ts +81 -0
  49. package/backend/src/api/routes/realtime/index.routes.ts +12 -0
  50. package/backend/src/api/routes/realtime/messages.routes.ts +48 -0
  51. package/backend/src/api/routes/realtime/permissions.routes.ts +19 -0
  52. package/backend/src/api/routes/storage/index.routes.ts +18 -12
  53. package/backend/src/api/routes/usage/index.routes.ts +6 -4
  54. package/backend/src/api/routes/webhooks/index.routes.ts +109 -0
  55. package/backend/src/infra/database/database.manager.ts +14 -11
  56. package/backend/src/infra/database/migrations/000_create-base-tables.sql +141 -141
  57. package/backend/src/infra/database/migrations/001_create-helper-functions.sql +40 -40
  58. package/backend/src/infra/database/migrations/002_rename-auth-tables.sql +29 -29
  59. package/backend/src/infra/database/migrations/003_create-users-table.sql +55 -55
  60. package/backend/src/infra/database/migrations/004_add-reload-postgrest-func.sql +23 -23
  61. package/backend/src/infra/database/migrations/005_enable-project-admin-modify-users.sql +29 -29
  62. package/backend/src/infra/database/migrations/006_modify-ai-usage-table.sql +24 -24
  63. package/backend/src/infra/database/migrations/007_drop-metadata-table.sql +1 -1
  64. package/backend/src/infra/database/migrations/008_add-system-tables.sql +76 -76
  65. package/backend/src/infra/database/migrations/009_add-function-secrets.sql +23 -23
  66. package/backend/src/infra/database/migrations/010_modify-ai-config-modalities.sql +93 -93
  67. package/backend/src/infra/database/migrations/011_refactor-secrets-table.sql +15 -15
  68. package/backend/src/infra/database/migrations/012_add-storage-uploaded-by.sql +7 -7
  69. package/backend/src/infra/database/migrations/013_create-auth-schema-functions.sql +44 -44
  70. package/backend/src/infra/database/migrations/014_add-updated-at-trigger-user-table.sql +7 -7
  71. package/backend/src/infra/database/migrations/015_create-auth-config-and-email-otp-tables.sql +59 -59
  72. package/backend/src/infra/database/migrations/016_update-auth-config-and-email-otp.sql +24 -24
  73. package/backend/src/infra/database/migrations/017_create-realtime-schema.sql +233 -0
  74. package/backend/src/infra/database/migrations/018_schema-rework.sql +441 -0
  75. package/backend/src/infra/database/migrations/019_create-deployments-table.sql +36 -0
  76. package/backend/src/infra/database/migrations/020_add-audio-modality.sql +11 -0
  77. package/backend/src/infra/database/migrations/bootstrap/bootstrap-migrations.js +103 -0
  78. package/backend/src/infra/realtime/realtime.manager.ts +246 -0
  79. package/backend/src/infra/realtime/webhook-sender.ts +82 -0
  80. package/backend/src/infra/security/token.manager.ts +216 -125
  81. package/backend/src/infra/socket/socket.manager.ts +198 -64
  82. package/backend/src/providers/ai/openrouter.provider.ts +24 -12
  83. package/backend/src/providers/database/base.provider.ts +39 -0
  84. package/backend/src/providers/database/cloud.provider.ts +159 -0
  85. package/backend/src/providers/deployments/vercel.provider.ts +516 -0
  86. package/backend/src/providers/email/base.provider.ts +4 -7
  87. package/backend/src/providers/email/cloud.provider.ts +84 -0
  88. package/backend/src/providers/oauth/apple.provider.ts +266 -0
  89. package/backend/src/providers/oauth/index.ts +1 -0
  90. package/backend/src/server.ts +329 -284
  91. package/backend/src/services/ai/ai-config.service.ts +6 -6
  92. package/backend/src/services/ai/ai-model.service.ts +60 -60
  93. package/backend/src/services/ai/ai-usage.service.ts +7 -7
  94. package/backend/src/services/ai/chat-completion.service.ts +415 -220
  95. package/backend/src/services/ai/helpers.ts +64 -64
  96. package/backend/src/services/ai/image-generation.service.ts +3 -3
  97. package/backend/src/services/ai/index.ts +13 -13
  98. package/backend/src/services/auth/auth-config.service.ts +4 -4
  99. package/backend/src/services/auth/auth-otp.service.ts +6 -6
  100. package/backend/src/services/auth/auth.service.ts +148 -74
  101. package/backend/src/services/auth/index.ts +4 -4
  102. package/backend/src/services/auth/oauth-config.service.ts +12 -12
  103. package/backend/src/services/database/database-advance.service.ts +19 -55
  104. package/backend/src/services/database/database-table.service.ts +38 -94
  105. package/backend/src/services/database/database.service.ts +127 -0
  106. package/backend/src/services/database/postgrest-proxy.service.ts +165 -0
  107. package/backend/src/services/deployments/deployment.service.ts +693 -0
  108. package/backend/src/services/email/email.service.ts +5 -7
  109. package/backend/src/services/functions/function.service.ts +61 -41
  110. package/backend/src/services/logs/audit.service.ts +10 -10
  111. package/backend/src/services/realtime/index.ts +3 -0
  112. package/backend/src/services/realtime/realtime-auth.service.ts +104 -0
  113. package/backend/src/services/realtime/realtime-channel.service.ts +237 -0
  114. package/backend/src/services/realtime/realtime-message.service.ts +260 -0
  115. package/backend/src/services/secrets/secret.service.ts +101 -27
  116. package/backend/src/services/storage/storage.service.ts +30 -30
  117. package/backend/src/services/usage/usage.service.ts +6 -6
  118. package/backend/src/types/ai.ts +8 -0
  119. package/backend/src/types/auth.ts +16 -1
  120. package/backend/src/types/database.ts +2 -0
  121. package/backend/src/types/deployments.ts +33 -0
  122. package/backend/src/types/realtime.ts +18 -0
  123. package/backend/src/types/socket.ts +7 -31
  124. package/backend/src/types/storage.ts +1 -1
  125. package/backend/src/types/webhooks.ts +45 -0
  126. package/backend/src/utils/cookies.ts +34 -0
  127. package/backend/src/utils/environment.ts +0 -14
  128. package/backend/src/utils/s3-config-loader.ts +64 -0
  129. package/backend/src/utils/seed.ts +79 -43
  130. package/backend/src/utils/sql-parser.ts +216 -0
  131. package/backend/src/utils/utils.ts +114 -114
  132. package/backend/src/utils/validations.ts +10 -10
  133. package/backend/tests/README.md +133 -133
  134. package/backend/tests/cleanup-all-test-data.sh +230 -230
  135. package/backend/tests/cloud/test-s3-multitenant.sh +131 -131
  136. package/backend/tests/local/comprehensive-curl-tests.sh +155 -155
  137. package/backend/tests/local/test-ai-config.sh +129 -129
  138. package/backend/tests/local/test-ai-usage.sh +80 -80
  139. package/backend/tests/local/test-auth-router.sh +143 -143
  140. package/backend/tests/local/test-database-router.sh +222 -222
  141. package/backend/tests/local/test-e2e.sh +240 -240
  142. package/backend/tests/local/test-fk-errors.sh +96 -96
  143. package/backend/tests/local/test-functions.sh +123 -123
  144. package/backend/tests/local/test-id-field.sh +200 -200
  145. package/backend/tests/local/test-logs.sh +132 -132
  146. package/backend/tests/local/test-public-bucket.sh +264 -264
  147. package/backend/tests/local/test-rpc.sh +141 -0
  148. package/backend/tests/local/test-secrets.sh +249 -249
  149. package/backend/tests/local/test-serverless-functions.sh.disabled +325 -325
  150. package/backend/tests/local/test-traditional-rest.sh +208 -208
  151. package/backend/tests/manual/README.md +50 -50
  152. package/backend/tests/manual/create-large-table-simple.sql +10 -10
  153. package/backend/tests/manual/seed-large-table.sql +100 -100
  154. package/backend/tests/manual/setup-large-table-extras.sql +33 -33
  155. package/backend/tests/manual/test-ai-model-plugins.sh +258 -0
  156. package/backend/tests/manual/test-bulk-upsert.sh +409 -409
  157. package/backend/tests/manual/test-database-advance.sh +296 -296
  158. package/backend/tests/manual/test-postgrest-stability.sh +191 -191
  159. package/backend/tests/manual/test-rawsql-export-import.sh +411 -411
  160. package/backend/tests/manual/test-rawsql-modes.sh +244 -244
  161. package/backend/tests/manual/test-universal-storage.sh +263 -263
  162. package/backend/tests/manual/test-users.sql +17 -17
  163. package/backend/tests/run-all-tests.sh +139 -139
  164. package/backend/tests/setup.ts +0 -0
  165. package/backend/tests/test-config.sh +338 -338
  166. package/backend/tests/unit/analyze-query.test.ts +697 -0
  167. package/backend/tests/unit/database-advance.test.ts +326 -0
  168. package/backend/tests/unit/helpers.test.ts +2 -2
  169. package/backend/tsconfig.json +22 -22
  170. package/claude-plugin/.claude-plugin/plugin.json +24 -24
  171. package/claude-plugin/README.md +133 -133
  172. package/claude-plugin/skills/insforge-schema-patterns/SKILL.md +273 -270
  173. package/docker-compose.prod.yml +204 -200
  174. package/docker-compose.yml +232 -228
  175. package/docker-init/db/db-init.sql +97 -97
  176. package/docker-init/db/jwt.sql +5 -5
  177. package/docker-init/db/postgresql.conf +16 -16
  178. package/docker-init/logs/vector.yml +236 -236
  179. package/docs/README.md +44 -44
  180. package/docs/agent-docs/deployment.md +79 -0
  181. package/docs/agent-docs/real-time.md +269 -0
  182. package/docs/changelog.mdx +212 -67
  183. package/docs/core-concepts/ai/architecture.mdx +350 -372
  184. package/docs/core-concepts/ai/sdk.mdx +238 -213
  185. package/docs/core-concepts/authentication/architecture.mdx +276 -278
  186. package/docs/core-concepts/authentication/sdk.mdx +710 -414
  187. package/docs/core-concepts/authentication/ui-components/customization.mdx +733 -529
  188. package/docs/core-concepts/authentication/ui-components/nextjs.mdx +247 -221
  189. package/docs/core-concepts/authentication/ui-components/react-router.mdx +183 -184
  190. package/docs/core-concepts/authentication/ui-components/react.mdx +136 -129
  191. package/docs/core-concepts/database/architecture.mdx +292 -255
  192. package/docs/core-concepts/database/pgvector.mdx +138 -0
  193. package/docs/core-concepts/database/sdk.mdx +382 -382
  194. package/docs/core-concepts/deployments/architecture.mdx +152 -0
  195. package/docs/core-concepts/email/architecture.mdx +103 -0
  196. package/docs/core-concepts/email/sdk.mdx +53 -0
  197. package/docs/core-concepts/functions/architecture.mdx +105 -105
  198. package/docs/core-concepts/functions/sdk.mdx +183 -184
  199. package/docs/core-concepts/realtime/architecture.mdx +446 -0
  200. package/docs/core-concepts/realtime/sdk.mdx +409 -0
  201. package/docs/core-concepts/storage/architecture.mdx +243 -243
  202. package/docs/core-concepts/storage/sdk.mdx +253 -253
  203. package/docs/deployment/README.md +94 -94
  204. package/docs/deployment/deploy-to-aws-ec2.md +564 -564
  205. package/docs/deployment/deploy-to-azure-virtual-machines.md +312 -312
  206. package/docs/deployment/deploy-to-google-cloud-compute-engine.md +613 -613
  207. package/docs/deployment/deploy-to-render.md +441 -441
  208. package/docs/deprecated/insforge-auth-api.md +214 -214
  209. package/docs/deprecated/insforge-auth-sdk.md +99 -99
  210. package/docs/deprecated/insforge-db-api.md +358 -358
  211. package/docs/deprecated/insforge-db-sdk.md +139 -139
  212. package/docs/deprecated/insforge-debug-sdk.md +156 -156
  213. package/docs/deprecated/insforge-debug.md +64 -64
  214. package/docs/deprecated/insforge-instructions.md +123 -123
  215. package/docs/deprecated/insforge-project.md +117 -117
  216. package/docs/deprecated/insforge-storage-api.md +278 -278
  217. package/docs/deprecated/insforge-storage-sdk.md +158 -158
  218. package/docs/docs.json +240 -210
  219. package/docs/examples/framework-guides/nextjs.mdx +131 -131
  220. package/docs/examples/framework-guides/nuxt.mdx +165 -165
  221. package/docs/examples/framework-guides/react.mdx +165 -165
  222. package/docs/examples/framework-guides/svelte.mdx +153 -153
  223. package/docs/examples/framework-guides/vue.mdx +159 -159
  224. package/docs/examples/overview.mdx +67 -67
  225. package/docs/favicon.png +0 -0
  226. package/docs/favicon.svg +4 -19
  227. package/docs/images/changelog/dec-2025/ai-integration.png +0 -0
  228. package/docs/images/changelog/dec-2025/ai-models.webp +0 -0
  229. package/docs/images/changelog/dec-2025/alipay-payment.webp +0 -0
  230. package/docs/images/changelog/dec-2025/apple-login.jpg +0 -0
  231. package/docs/images/changelog/dec-2025/apple-oauth.mp4 +0 -0
  232. package/docs/images/changelog/dec-2025/mcp-installer.png +0 -0
  233. package/docs/images/changelog/dec-2025/moreModels.png +0 -0
  234. package/docs/images/changelog/dec-2025/multi-region.webp +0 -0
  235. package/docs/images/changelog/dec-2025/postgres-connection.webp +0 -0
  236. package/docs/images/changelog/dec-2025/realtime-module.jpg +0 -0
  237. package/docs/images/changelog/dec-2025/realtime2.png +0 -0
  238. package/docs/images/icons/ai.svg +4 -4
  239. package/docs/images/logos/nextjs.svg +4 -4
  240. package/docs/images/logos/nuxt.svg +4 -4
  241. package/docs/images/logos/react.svg +5 -5
  242. package/docs/images/logos/svelte.svg +4 -4
  243. package/docs/images/logos/vue.svg +5 -5
  244. package/docs/images/mcp-setup/CC-MCP-1.mp4 +0 -0
  245. package/docs/images/mcp-setup/CC-MCP-2.mp4 +0 -0
  246. package/docs/images/mcp-setup/Cursor-MCP-1.mp4 +0 -0
  247. package/docs/images/mcp-setup/Cursor-MCP-2.mp4 +0 -0
  248. package/docs/images/mcp-setup/Cursor-MCP-3.mp4 +0 -0
  249. package/docs/images/mcp-setup/claude-code-connect.png +0 -0
  250. package/docs/images/mcp-setup/cline-1.png +0 -0
  251. package/docs/images/mcp-setup/cline-2.png +0 -0
  252. package/docs/images/mcp-setup/cline-3.png +0 -0
  253. package/docs/images/mcp-setup/connect-project.png +0 -0
  254. package/docs/images/mcp-setup/copilot-1.png +0 -0
  255. package/docs/images/mcp-setup/copilot-2.png +0 -0
  256. package/docs/images/mcp-setup/copilot-3.png +0 -0
  257. package/docs/images/mcp-setup/mcp-json-1.png +0 -0
  258. package/docs/images/mcp-setup/mcp-json-2.png +0 -0
  259. package/docs/images/mcp-setup/qoder-1.png +0 -0
  260. package/docs/images/mcp-setup/qoder-2.png +0 -0
  261. package/docs/images/mcp-setup/roocode-1.png +0 -0
  262. package/docs/images/mcp-setup/roocode-2.png +0 -0
  263. package/docs/images/mcp-setup/trae-1.png +0 -0
  264. package/docs/images/mcp-setup/trae-2.png +0 -0
  265. package/docs/images/mcp-setup/trae-3.png +0 -0
  266. package/docs/images/mcp-setup/trae-4.png +0 -0
  267. package/docs/images/mcp-setup/trae-5.png +0 -0
  268. package/docs/images/mcp-setup/windsurf-1.png +0 -0
  269. package/docs/images/mcp-setup/windsurf-2.png +0 -0
  270. package/docs/insforge-instructions-sdk.md +93 -88
  271. package/docs/introduction.mdx +46 -45
  272. package/docs/logo/dark.svg +22 -22
  273. package/docs/logo/light.svg +20 -20
  274. package/docs/mcp-setup.mdx +332 -0
  275. package/docs/oauth-server.mdx +563 -0
  276. package/docs/partnership.mdx +720 -646
  277. package/docs/quickstart.mdx +82 -82
  278. package/docs/showcase.mdx +52 -52
  279. package/docs/snippets/sdk-installation.mdx +21 -21
  280. package/docs/snippets/service-icons.mdx +27 -27
  281. package/docs/vscode-extension.mdx +74 -0
  282. package/eslint.config.js +1 -0
  283. package/examples/oauth/frontend-oauth-example.html +250 -250
  284. package/examples/response-examples.md +443 -443
  285. package/frontend/components.json +17 -17
  286. package/frontend/package.json +69 -69
  287. package/frontend/src/App.tsx +8 -3
  288. package/frontend/src/assets/icons/checkbox_checked.svg +6 -6
  289. package/frontend/src/assets/icons/checkbox_undetermined.svg +6 -6
  290. package/frontend/src/assets/icons/checked.svg +3 -3
  291. package/frontend/src/assets/icons/connected.svg +3 -3
  292. package/frontend/src/assets/icons/error.svg +3 -3
  293. package/frontend/src/assets/icons/loader.svg +9 -9
  294. package/frontend/src/assets/icons/pencil.svg +4 -4
  295. package/frontend/src/assets/icons/refresh.svg +4 -4
  296. package/frontend/src/assets/icons/step_active.svg +3 -3
  297. package/frontend/src/assets/icons/step_inactive.svg +11 -11
  298. package/frontend/src/assets/icons/warning.svg +3 -3
  299. package/frontend/src/assets/logos/antigravity.svg +1 -0
  300. package/frontend/src/assets/logos/apple.svg +3 -3
  301. package/frontend/src/assets/logos/claude_code.svg +3 -3
  302. package/frontend/src/assets/logos/cline.svg +6 -6
  303. package/frontend/src/assets/logos/copilot.svg +10 -0
  304. package/frontend/src/assets/logos/cursor.svg +20 -20
  305. package/frontend/src/assets/logos/deepseek.svg +139 -0
  306. package/frontend/src/assets/logos/discord.svg +8 -8
  307. package/frontend/src/assets/logos/facebook.svg +3 -3
  308. package/frontend/src/assets/logos/gemini.svg +19 -19
  309. package/frontend/src/assets/logos/github.svg +5 -5
  310. package/frontend/src/assets/logos/google.svg +13 -13
  311. package/frontend/src/assets/logos/grok.svg +10 -10
  312. package/frontend/src/assets/logos/insforge_dark.svg +15 -15
  313. package/frontend/src/assets/logos/insforge_light.svg +15 -15
  314. package/frontend/src/assets/logos/instagram.svg +1 -1
  315. package/frontend/src/assets/logos/kiro.svg +9 -0
  316. package/frontend/src/assets/logos/linkedin.svg +3 -3
  317. package/frontend/src/assets/logos/openai.svg +10 -10
  318. package/frontend/src/assets/logos/qoder.svg +4 -0
  319. package/frontend/src/assets/logos/qwen.svg +15 -0
  320. package/frontend/src/assets/logos/roo_code.svg +9 -9
  321. package/frontend/src/assets/logos/spotify.svg +16 -16
  322. package/frontend/src/assets/logos/tiktok.svg +5 -5
  323. package/frontend/src/assets/logos/trae.svg +3 -3
  324. package/frontend/src/assets/logos/windsurf.svg +10 -10
  325. package/frontend/src/assets/logos/x.svg +3 -3
  326. package/frontend/src/components/CodeBlock.tsx +2 -2
  327. package/frontend/src/components/ConnectCTA.tsx +3 -2
  328. package/frontend/src/components/datagrid/DataGrid.tsx +90 -62
  329. package/frontend/src/components/datagrid/datagridTypes.tsx +2 -1
  330. package/frontend/src/components/datagrid/index.ts +1 -1
  331. package/frontend/src/components/index.ts +0 -1
  332. package/frontend/src/components/layout/AppHeader.tsx +13 -37
  333. package/frontend/src/components/layout/AppSidebar.tsx +85 -100
  334. package/frontend/src/components/layout/Layout.tsx +34 -32
  335. package/frontend/src/components/layout/PrimaryMenu.tsx +12 -4
  336. package/frontend/src/components/radix/Select.tsx +151 -151
  337. package/frontend/src/features/ai/components/AIConfigCard.tsx +200 -200
  338. package/frontend/src/features/ai/components/AIEmptyState.tsx +23 -23
  339. package/frontend/src/features/ai/components/ModalityFilterSidebar.tsx +102 -101
  340. package/frontend/src/features/ai/components/ModelSelectionDialog.tsx +135 -135
  341. package/frontend/src/features/ai/components/ModelSelectionGrid.tsx +51 -51
  342. package/frontend/src/features/ai/components/SystemPromptDialog.tsx +118 -118
  343. package/frontend/src/features/ai/components/index.ts +6 -6
  344. package/frontend/src/features/ai/helpers.ts +147 -141
  345. package/frontend/src/features/ai/{page → pages}/AIPage.tsx +166 -166
  346. package/frontend/src/features/auth/components/AuthPreview.tsx +96 -96
  347. package/frontend/src/features/auth/components/OAuthConfigDialog.tsx +1 -0
  348. package/frontend/src/features/auth/components/UsersDataGrid.tsx +61 -31
  349. package/frontend/src/features/auth/components/index.ts +5 -5
  350. package/frontend/src/features/auth/helpers.tsx +8 -0
  351. package/frontend/src/features/auth/{page → pages}/AuthMethodsPage.tsx +275 -275
  352. package/frontend/src/features/auth/{page → pages}/UsersPage.tsx +0 -28
  353. package/frontend/src/features/dashboard/{page → pages}/DashboardPage.tsx +1 -1
  354. package/frontend/src/features/database/components/DatabaseDataGrid.tsx +0 -2
  355. package/frontend/src/features/database/components/ForeignKeyCell.tsx +38 -11
  356. package/frontend/src/features/database/components/ForeignKeyPopover.tsx +18 -8
  357. package/frontend/src/features/database/components/LinkRecordModal.tsx +61 -13
  358. package/frontend/src/features/database/components/RecordFormField.tsx +1 -1
  359. package/frontend/src/features/database/components/SQLModal.tsx +75 -0
  360. package/frontend/src/features/database/components/TableForm.tsx +0 -4
  361. package/frontend/src/features/database/components/TableSidebar.tsx +0 -3
  362. package/frontend/src/features/database/components/TablesEmptyState.tsx +1 -1
  363. package/frontend/src/features/database/components/TemplatePreview.tsx +1 -2
  364. package/frontend/src/features/database/constants.ts +16 -28
  365. package/frontend/src/features/database/hooks/useCSVImport.ts +3 -2
  366. package/frontend/src/features/database/hooks/useDatabase.ts +66 -0
  367. package/frontend/src/features/database/hooks/useRawSQL.ts +3 -2
  368. package/frontend/src/features/database/hooks/useTables.ts +30 -28
  369. package/frontend/src/features/database/index.ts +1 -0
  370. package/frontend/src/features/database/{page → pages}/FunctionsPage.tsx +29 -42
  371. package/frontend/src/features/database/{page → pages}/IndexesPage.tsx +34 -51
  372. package/frontend/src/features/database/{page → pages}/PoliciesPage.tsx +42 -58
  373. package/frontend/src/features/database/{page → pages}/SQLEditorPage.tsx +2 -2
  374. package/frontend/src/features/database/{page → pages}/TablesPage.tsx +0 -42
  375. package/frontend/src/features/database/{page → pages}/TriggersPage.tsx +34 -51
  376. package/frontend/src/features/database/services/advance.service.ts +1 -41
  377. package/frontend/src/features/database/services/database.service.ts +55 -0
  378. package/frontend/src/features/database/services/record.service.ts +4 -20
  379. package/frontend/src/features/database/services/table.service.ts +1 -10
  380. package/frontend/src/features/database/templates/ai-chatbot.ts +6 -6
  381. package/frontend/src/features/database/templates/ecommerce-platform.ts +2 -2
  382. package/frontend/src/features/database/templates/instagram-clone.ts +10 -10
  383. package/frontend/src/features/database/templates/notion-clone.ts +8 -8
  384. package/frontend/src/features/database/templates/reddit-clone.ts +10 -10
  385. package/frontend/src/features/deployments/components/DeploymentRow.tsx +93 -0
  386. package/frontend/src/features/deployments/components/DeploymentsEmptyState.tsx +15 -0
  387. package/frontend/src/features/deployments/hooks/useDeployments.ts +157 -0
  388. package/frontend/src/features/deployments/pages/DeploymentsPage.tsx +318 -0
  389. package/frontend/src/features/deployments/services/deployments.service.ts +63 -0
  390. package/frontend/src/features/functions/components/FunctionRow.tsx +72 -72
  391. package/frontend/src/features/functions/components/FunctionsSidebar.tsx +56 -56
  392. package/frontend/src/features/functions/components/SecretRow.tsx +3 -3
  393. package/frontend/src/features/functions/components/index.ts +5 -5
  394. package/frontend/src/features/functions/hooks/useFunctions.ts +5 -4
  395. package/frontend/src/features/functions/hooks/useSecrets.ts +6 -9
  396. package/frontend/src/features/functions/{page → pages}/FunctionsPage.tsx +21 -44
  397. package/frontend/src/features/functions/{page → pages}/SecretsPage.tsx +118 -116
  398. package/frontend/src/features/functions/services/function.service.ts +8 -25
  399. package/frontend/src/features/functions/services/secret.service.ts +23 -41
  400. package/frontend/src/features/login/{page → pages}/CloudLoginPage.tsx +125 -118
  401. package/frontend/src/features/logs/components/LogDetailPanel.tsx +41 -0
  402. package/frontend/src/features/logs/components/LogsDataGrid.tsx +32 -1
  403. package/frontend/src/features/logs/components/index.ts +1 -0
  404. package/frontend/src/features/logs/hooks/useMcpUsage.ts +13 -66
  405. package/frontend/src/features/logs/{page → pages}/LogsPage.tsx +36 -6
  406. package/frontend/src/features/onboard/components/ApiCredentialsSection.tsx +59 -0
  407. package/frontend/src/features/onboard/components/ConnectionStringSection.tsx +180 -0
  408. package/frontend/src/features/onboard/components/McpConnectionSection.tsx +159 -0
  409. package/frontend/src/features/onboard/components/OnboardingController.tsx +68 -0
  410. package/frontend/src/features/onboard/components/OnboardingModal.tsx +121 -267
  411. package/frontend/src/features/onboard/components/ShowPasswordButton.tsx +21 -0
  412. package/frontend/src/features/onboard/components/index.ts +9 -4
  413. package/frontend/src/features/onboard/components/mcp/CursorDeeplinkGenerator.tsx +1 -1
  414. package/frontend/src/features/onboard/components/mcp/QoderDeeplinkGenerator.tsx +36 -0
  415. package/frontend/src/features/onboard/components/mcp/helpers.tsx +123 -98
  416. package/frontend/src/features/onboard/components/mcp/index.ts +4 -3
  417. package/frontend/src/features/onboard/index.ts +17 -13
  418. package/frontend/src/features/realtime/components/ChannelRow.tsx +83 -0
  419. package/frontend/src/features/realtime/components/EditChannelModal.tsx +246 -0
  420. package/frontend/src/features/realtime/components/MessageRow.tsx +85 -0
  421. package/frontend/src/features/realtime/components/RealtimeEmptyState.tsx +30 -0
  422. package/frontend/src/features/realtime/hooks/useRealtime.ts +218 -0
  423. package/frontend/src/features/realtime/index.ts +11 -0
  424. package/frontend/src/features/realtime/pages/RealtimeChannelsPage.tsx +172 -0
  425. package/frontend/src/features/realtime/pages/RealtimeMessagesPage.tsx +211 -0
  426. package/frontend/src/features/realtime/pages/RealtimePermissionsPage.tsx +191 -0
  427. package/frontend/src/features/realtime/services/realtime.service.ts +107 -0
  428. package/frontend/src/features/settings/pages/SettingsPage.tsx +349 -0
  429. package/frontend/src/features/storage/{page → pages}/StoragePage.tsx +1 -29
  430. package/frontend/src/features/visualizer/components/AuthNode.tsx +4 -4
  431. package/frontend/src/features/visualizer/components/SchemaVisualizer.tsx +24 -11
  432. package/frontend/src/features/visualizer/{page → pages}/VisualizerPage.tsx +11 -36
  433. package/frontend/src/index.css +249 -249
  434. package/frontend/src/lib/contexts/ModalContext.tsx +35 -0
  435. package/frontend/src/lib/contexts/SocketContext.tsx +119 -75
  436. package/frontend/src/lib/hooks/useMetadata.ts +45 -1
  437. package/frontend/src/lib/hooks/useModal.tsx +2 -0
  438. package/frontend/src/lib/routing/AppRoutes.tsx +103 -84
  439. package/frontend/src/lib/services/metadata.service.ts +20 -3
  440. package/frontend/src/lib/utils/cloudMessaging.ts +1 -1
  441. package/frontend/src/lib/utils/menuItems.ts +223 -183
  442. package/frontend/src/lib/utils/utils.ts +196 -183
  443. package/frontend/tsconfig.json +25 -25
  444. package/frontend/tsconfig.node.json +9 -9
  445. package/functions/deno.json +24 -24
  446. package/functions/server.ts +6 -6
  447. package/functions/worker-template.js +1 -1
  448. package/i18n/README.ar.md +130 -130
  449. package/i18n/README.de.md +130 -130
  450. package/i18n/README.es.md +154 -154
  451. package/i18n/README.fr.md +134 -134
  452. package/i18n/README.hi.md +129 -129
  453. package/i18n/README.ja.md +174 -174
  454. package/i18n/README.ko.md +136 -136
  455. package/i18n/README.pt-BR.md +131 -131
  456. package/i18n/README.ru.md +129 -129
  457. package/i18n/README.zh-CN.md +133 -133
  458. package/openapi/ai.yaml +825 -715
  459. package/openapi/auth.yaml +1324 -1244
  460. package/openapi/email.yaml +158 -0
  461. package/openapi/functions.yaml +475 -475
  462. package/openapi/health.yaml +29 -29
  463. package/openapi/logs.yaml +221 -223
  464. package/openapi/metadata.yaml +175 -177
  465. package/openapi/realtime.yaml +699 -0
  466. package/openapi/records.yaml +381 -381
  467. package/openapi/secrets.yaml +370 -370
  468. package/openapi/storage.yaml +875 -875
  469. package/openapi/tables.yaml +462 -463
  470. package/package.json +97 -97
  471. package/shared-schemas/package.json +31 -31
  472. package/shared-schemas/src/ai-api.schema.ts +251 -143
  473. package/shared-schemas/src/ai.schema.ts +8 -4
  474. package/shared-schemas/src/auth-api.schema.ts +380 -339
  475. package/shared-schemas/src/auth.schema.ts +18 -11
  476. package/shared-schemas/src/cloud-events.schema.ts +26 -0
  477. package/shared-schemas/src/database-api.schema.ts +32 -1
  478. package/shared-schemas/src/database.schema.ts +39 -0
  479. package/shared-schemas/src/deployments-api.schema.ts +55 -0
  480. package/shared-schemas/src/deployments.schema.ts +30 -0
  481. package/shared-schemas/src/docs.schema.ts +32 -0
  482. package/shared-schemas/src/email-api.schema.ts +30 -0
  483. package/shared-schemas/src/functions-api.schema.ts +13 -4
  484. package/shared-schemas/src/functions.schema.ts +1 -1
  485. package/shared-schemas/src/index.ts +22 -14
  486. package/shared-schemas/src/metadata.schema.ts +39 -4
  487. package/shared-schemas/src/realtime-api.schema.ts +111 -0
  488. package/shared-schemas/src/realtime.schema.ts +143 -0
  489. package/shared-schemas/src/secrets-api.schema.ts +44 -0
  490. package/shared-schemas/src/secrets.schema.ts +15 -0
  491. package/shared-schemas/tsconfig.json +21 -21
  492. package/tsconfig.json +7 -7
  493. package/zeabur/README.md +26 -13
  494. package/zeabur/template.yml +1001 -1032
  495. package/.cursor/rules/cursor-rules.mdc +0 -94
  496. package/backend/src/types/profile.ts +0 -55
  497. package/frontend/src/components/ProjectInfoModal.tsx +0 -128
  498. package/frontend/src/features/database/hooks/useFullMetadata.ts +0 -18
  499. package/test-gemini.sh +0 -35
  500. package/test-usage-admin.sh +0 -57
  501. package/test-usage.sh +0 -50
  502. /package/frontend/src/features/auth/{page → pages}/ConfigurationPage.tsx +0 -0
  503. /package/frontend/src/features/database/{page → pages}/TemplatesPage.tsx +0 -0
  504. /package/frontend/src/features/login/{page → pages}/LoginPage.tsx +0 -0
  505. /package/frontend/src/features/logs/{page → pages}/AuditsPage.tsx +0 -0
  506. /package/frontend/src/features/logs/{page → pages}/MCPLogsPage.tsx +0 -0
@@ -1,284 +1,329 @@
1
- import express, { Request, Response, NextFunction } from 'express';
2
- import cors from 'cors';
3
- import rateLimit from 'express-rate-limit';
4
- import dotenv from 'dotenv';
5
- import path from 'path';
6
- import { fileURLToPath } from 'url';
7
- import fs from 'fs';
8
- import authRouter from '@/api/routes/auth/index.routes.js';
9
- import databaseRouter from '@/api/routes/database/index.routes.js';
10
- import { storageRouter } from '@/api/routes/storage/index.routes.js';
11
- import { metadataRouter } from '@/api/routes/metadata/index.routes.js';
12
- import { logsRouter } from '@/api/routes/logs/index.routes.js';
13
- import { docsRouter } from '@/api/routes/docs/index.routes.js';
14
- import functionsRouter from '@/api/routes/functions/index.routes.js';
15
- import secretsRouter from '@/api/routes/secrets/index.routes.js';
16
- import { usageRouter } from '@/api/routes/usage/index.routes.js';
17
- import { aiRouter } from '@/api/routes/ai/index.routes.js';
18
- import { errorMiddleware } from '@/api/middlewares/error.js';
19
- import fetch, { HeadersInit } from 'node-fetch';
20
- import { DatabaseManager } from '@/infra/database/database.manager.js';
21
- import { LogService } from '@/services/logs/log.service.js';
22
- import { StorageService } from '@/services/storage/storage.service.js';
23
- import { SocketManager } from '@/infra/socket/socket.manager.js';
24
- import { seedBackend } from '@/utils/seed.js';
25
- import logger from '@/utils/logger.js';
26
- import { isProduction } from './utils/environment.js';
27
- import packageJson from '../../package.json';
28
-
29
- const __filename = fileURLToPath(import.meta.url);
30
- const __dirname = path.dirname(__filename);
31
-
32
- // Load .env file from the root directory (parent of backend)
33
- const envPath = path.resolve(__dirname, '../../.env');
34
- if (fs.existsSync(envPath)) {
35
- dotenv.config({ path: envPath });
36
- } else {
37
- // Fallback to default behavior (looks in current working directory)
38
- dotenv.config();
39
- }
40
-
41
- export async function createApp() {
42
- // Initialize database first
43
- const dbManager = DatabaseManager.getInstance();
44
- await dbManager.initialize(); // create data/app.db
45
-
46
- // Initialize storage service
47
- const storageService = StorageService.getInstance();
48
- await storageService.initialize(); // create data/storage
49
-
50
- // Initialize logs service
51
- const logService = LogService.getInstance();
52
- await logService.initialize(); // connect to CloudWatch
53
-
54
- const app = express();
55
-
56
- // Enable trust proxy setting for rate limiting behind proxies/load balancers
57
- app.set('trust proxy', true);
58
-
59
- const limiter = rateLimit({
60
- windowMs: 15 * 60 * 1000,
61
- max: 1000,
62
- message: 'Too many requests from this IP',
63
- });
64
-
65
- // Basic middleware
66
- app.use(
67
- cors({
68
- origin: true, // Allow all origins (matches Better Auth's trustedOrigins: ['*'])
69
- credentials: true, // Allow cookies/credentials
70
- })
71
- );
72
- if (isProduction()) {
73
- app.use(limiter);
74
- }
75
- app.use((req: Request, res: Response, next: NextFunction) => {
76
- const startTime = Date.now();
77
- const originalSend = res.send;
78
- const originalJson = res.json;
79
-
80
- // Track response size
81
- let responseSize = 0;
82
-
83
- // Override send method
84
- res.send = function (
85
- data: string | Buffer | Record<string, unknown> | unknown[] | number | boolean
86
- ) {
87
- if (data !== undefined && data !== null) {
88
- if (typeof data === 'string') {
89
- responseSize = Buffer.byteLength(data);
90
- } else if (Buffer.isBuffer(data)) {
91
- responseSize = data.length;
92
- } else if (typeof data === 'number' || typeof data === 'boolean') {
93
- responseSize = Buffer.byteLength(String(data));
94
- } else {
95
- try {
96
- responseSize = Buffer.byteLength(JSON.stringify(data));
97
- } catch {
98
- // Handle circular references or unstringifiable objects
99
- responseSize = 0;
100
- }
101
- }
102
- }
103
- return originalSend.call(this, data);
104
- };
105
-
106
- // Override json method
107
- res.json = function (
108
- data: Record<string, unknown> | unknown[] | string | number | boolean | null
109
- ) {
110
- if (data !== undefined) {
111
- try {
112
- responseSize = Buffer.byteLength(JSON.stringify(data));
113
- } catch {
114
- // Handle circular references or unstringifiable objects
115
- responseSize = 0;
116
- }
117
- }
118
- return originalJson.call(this, data);
119
- };
120
-
121
- // Log after response is finished
122
- res.on('finish', () => {
123
- // Skip logging for logs endpoints to avoid infinite loops
124
- if (req.path.includes('/logs/')) {
125
- return;
126
- }
127
-
128
- const duration = Date.now() - startTime;
129
- logger.info('HTTP Request', {
130
- method: req.method,
131
- path: req.path,
132
- status: res.statusCode,
133
- size: responseSize,
134
- duration: `${duration}ms`,
135
- ip: req.ip || req.socket.remoteAddress,
136
- userAgent: req.headers['user-agent'],
137
- timestamp: new Date().toISOString(),
138
- });
139
- });
140
-
141
- next();
142
- });
143
-
144
- // Apply JSON middleware
145
- app.use(express.json({ limit: '100mb' }));
146
- app.use(express.urlencoded({ extended: true, limit: '10mb' }));
147
-
148
- // Create API router and mount all API routes under /api
149
- const apiRouter = express.Router();
150
-
151
- apiRouter.get('/health', (_req: Request, res: Response) => {
152
- // Traditional REST: return data directly
153
- const version = packageJson.version;
154
- res.json({
155
- status: 'ok',
156
- version,
157
- service: 'Insforge OSS Backend',
158
- timestamp: new Date().toISOString(),
159
- });
160
- });
161
-
162
- // Mount all routes
163
- apiRouter.use('/auth', authRouter);
164
- apiRouter.use('/database', databaseRouter);
165
- apiRouter.use('/storage', storageRouter);
166
- apiRouter.use('/metadata', metadataRouter);
167
- apiRouter.use('/logs', logsRouter);
168
- apiRouter.use('/docs', docsRouter);
169
- apiRouter.use('/functions', functionsRouter);
170
- apiRouter.use('/secrets', secretsRouter);
171
- apiRouter.use('/usage', usageRouter);
172
- apiRouter.use('/ai', aiRouter);
173
-
174
- // Mount all API routes under /api prefix
175
- app.use('/api', apiRouter);
176
-
177
- // Proxy function execution to Deno runtime
178
- app.all('/functions/:slug', async (req: Request, res: Response) => {
179
- try {
180
- const { slug } = req.params;
181
- const denoUrl = process.env.DENO_RUNTIME_URL || 'http://localhost:7133';
182
-
183
- // Simple direct proxy - just pass everything through
184
- const response = await fetch(
185
- `${denoUrl}/${slug}${req.url.includes('?') ? req.url.substring(req.url.indexOf('?')) : ''}`,
186
- {
187
- method: req.method,
188
- headers: req.headers as HeadersInit,
189
- body: ['GET', 'HEAD'].includes(req.method) ? undefined : JSON.stringify(req.body),
190
- }
191
- );
192
-
193
- // Get response text
194
- const responseText = await response.text();
195
-
196
- res
197
- .status(response.status)
198
- .set('Content-Type', response.headers.get('content-type') || 'application/json')
199
- .set('Access-Control-Allow-Origin', '*')
200
- .send(responseText);
201
- } catch (error) {
202
- logger.error('Failed to proxy to Deno runtime', {
203
- error: error instanceof Error ? error.message : String(error),
204
- stack: error instanceof Error ? error.stack : undefined,
205
- slug: req.params.slug,
206
- });
207
-
208
- // Return the actual error from Deno or connection error
209
- const errorMessage = error instanceof Error ? error.message : String(error);
210
- res.status(502).json({
211
- error: errorMessage,
212
- });
213
- }
214
- });
215
-
216
- // Serve auth app
217
- const authAppPath = path.join(__dirname, 'auth');
218
- if (fs.existsSync(authAppPath)) {
219
- app.use('/auth', express.static(authAppPath));
220
- app.get('/auth*', (_req: Request, res: Response) => {
221
- res.sendFile(path.join(authAppPath, 'index.html'));
222
- });
223
- } else if (!isProduction()) {
224
- const authAppUrl = process.env.AUTH_APP_URL || 'http://localhost:7132';
225
- logger.info('Auth app not built, proxying to development server', { authAppUrl });
226
- }
227
-
228
- // Serve main frontend if it exists
229
- const frontendPath = path.join(__dirname, 'frontend');
230
- if (fs.existsSync(frontendPath)) {
231
- app.use(express.static(frontendPath, { index: false }));
232
- // Catch all handler for SPA routes
233
- app.get(['/cloud*', '/dashboard*'], (_req: Request, res: Response) => {
234
- res.sendFile(path.join(frontendPath, 'index.html'));
235
- });
236
- } else {
237
- // Catch-all for 404 errors - Traditional REST format
238
- app.use('*', (req: Request, res: Response) => {
239
- res.status(404).json({
240
- error: 'NOT_FOUND',
241
- message: `Endpoint ${req.originalUrl} not found`,
242
- statusCode: 404,
243
- nextActions: 'Please check the API documentation for available endpoints',
244
- });
245
- });
246
- }
247
-
248
- app.use(errorMiddleware);
249
- await seedBackend();
250
-
251
- return app;
252
- }
253
-
254
- // Use PORT from environment variable, fallback to 7130
255
- const PORT = parseInt(process.env.PORT || '7130');
256
-
257
- async function initializeServer() {
258
- try {
259
- const app = await createApp();
260
- const server = app.listen(PORT, () => {
261
- logger.info(`Backend API service listening on port ${PORT}`);
262
- });
263
-
264
- // Initialize Socket.IO service
265
- const socketService = SocketManager.getInstance();
266
- socketService.initialize(server);
267
- } catch (error) {
268
- logger.error('Failed to initialize server', {
269
- error: error instanceof Error ? error.message : String(error),
270
- stack: error instanceof Error ? error.stack : undefined,
271
- });
272
- process.exit(1);
273
- }
274
- }
275
-
276
- void initializeServer();
277
-
278
- function cleanup() {
279
- logger.info('Shutting down gracefully...');
280
- process.exit(0);
281
- }
282
-
283
- process.on('SIGINT', cleanup);
284
- process.on('SIGTERM', cleanup);
1
+ import express, { Request, Response, NextFunction } from 'express';
2
+ import cors from 'cors';
3
+ import cookieParser from 'cookie-parser';
4
+ import rateLimit from 'express-rate-limit';
5
+ import dotenv from 'dotenv';
6
+ import path from 'path';
7
+ import { fileURLToPath } from 'url';
8
+ import fs from 'fs';
9
+ import authRouter from '@/api/routes/auth/index.routes.js';
10
+ import databaseRouter from '@/api/routes/database/index.routes.js';
11
+ import { storageRouter } from '@/api/routes/storage/index.routes.js';
12
+ import { metadataRouter } from '@/api/routes/metadata/index.routes.js';
13
+ import { logsRouter } from '@/api/routes/logs/index.routes.js';
14
+ import { docsRouter } from '@/api/routes/docs/index.routes.js';
15
+ import functionsRouter from '@/api/routes/functions/index.routes.js';
16
+ import secretsRouter from '@/api/routes/secrets/index.routes.js';
17
+ import { usageRouter } from '@/api/routes/usage/index.routes.js';
18
+ import { aiRouter } from '@/api/routes/ai/index.routes.js';
19
+ import { realtimeRouter } from '@/api/routes/realtime/index.routes.js';
20
+ import { emailRouter } from '@/api/routes/email/index.routes.js';
21
+ import { deploymentsRouter } from '@/api/routes/deployments/index.routes.js';
22
+ import { webhooksRouter } from '@/api/routes/webhooks/index.routes.js';
23
+ import { errorMiddleware } from '@/api/middlewares/error.js';
24
+ import { isCloudEnvironment } from '@/utils/environment.js';
25
+ import { RealtimeManager } from '@/infra/realtime/realtime.manager.js';
26
+ import fetch, { HeadersInit } from 'node-fetch';
27
+ import { DatabaseManager } from '@/infra/database/database.manager.js';
28
+ import { LogService } from '@/services/logs/log.service.js';
29
+ import { StorageService } from '@/services/storage/storage.service.js';
30
+ import { SocketManager } from '@/infra/socket/socket.manager.js';
31
+ import { seedBackend } from '@/utils/seed.js';
32
+ import logger from '@/utils/logger.js';
33
+ import { initSqlParser } from '@/utils/sql-parser.js';
34
+ import packageJson from '../../package.json';
35
+
36
+ const __filename = fileURLToPath(import.meta.url);
37
+ const __dirname = path.dirname(__filename);
38
+
39
+ // Load .env file from the root directory (parent of backend)
40
+ const envPath = path.resolve(__dirname, '../../.env');
41
+ if (fs.existsSync(envPath)) {
42
+ dotenv.config({ path: envPath });
43
+ } else {
44
+ // Fallback to default behavior (looks in current working directory)
45
+ dotenv.config();
46
+ }
47
+
48
+ export async function createApp() {
49
+ // Initialize database first
50
+ const dbManager = DatabaseManager.getInstance();
51
+ await dbManager.initialize(); // create data/app.db
52
+
53
+ // Initialize storage service
54
+ const storageService = StorageService.getInstance();
55
+ await storageService.initialize(); // create data/storage
56
+
57
+ // Initialize logs service
58
+ const logService = LogService.getInstance();
59
+ await logService.initialize(); // connect to CloudWatch
60
+
61
+ // Initialize SQL parser WASM module
62
+ await initSqlParser();
63
+
64
+ const app = express();
65
+
66
+ // Enable trust proxy setting for rate limiting behind proxies/load balancers
67
+ app.set('trust proxy', 2);
68
+
69
+ const limiter = rateLimit({
70
+ windowMs: 15 * 60 * 1000,
71
+ max: 1000,
72
+ message: 'Too many requests from this IP',
73
+ });
74
+
75
+ // Basic middleware
76
+ app.use(
77
+ cors({
78
+ origin: true, // Allow all origins (matches Better Auth's trustedOrigins: ['*'])
79
+ credentials: true, // Allow cookies/credentials
80
+ })
81
+ );
82
+ app.use(cookieParser()); // Parse cookies for refresh token handling
83
+ app.use(limiter);
84
+ app.use((req: Request, res: Response, next: NextFunction) => {
85
+ const startTime = Date.now();
86
+ const originalSend = res.send;
87
+ const originalJson = res.json;
88
+
89
+ // Track response size
90
+ let responseSize = 0;
91
+
92
+ // Override send method
93
+ res.send = function (
94
+ data: string | Buffer | Record<string, unknown> | unknown[] | number | boolean
95
+ ) {
96
+ if (data !== undefined && data !== null) {
97
+ if (typeof data === 'string') {
98
+ responseSize = Buffer.byteLength(data);
99
+ } else if (Buffer.isBuffer(data)) {
100
+ responseSize = data.length;
101
+ } else if (typeof data === 'number' || typeof data === 'boolean') {
102
+ responseSize = Buffer.byteLength(String(data));
103
+ } else {
104
+ try {
105
+ responseSize = Buffer.byteLength(JSON.stringify(data));
106
+ } catch {
107
+ // Handle circular references or unstringifiable objects
108
+ responseSize = 0;
109
+ }
110
+ }
111
+ }
112
+ return originalSend.call(this, data);
113
+ };
114
+
115
+ // Override json method
116
+ res.json = function (
117
+ data: Record<string, unknown> | unknown[] | string | number | boolean | null
118
+ ) {
119
+ if (data !== undefined) {
120
+ try {
121
+ responseSize = Buffer.byteLength(JSON.stringify(data));
122
+ } catch {
123
+ // Handle circular references or unstringifiable objects
124
+ responseSize = 0;
125
+ }
126
+ }
127
+ return originalJson.call(this, data);
128
+ };
129
+
130
+ // Log after response is finished
131
+ res.on('finish', () => {
132
+ // Skip logging for logs endpoints to avoid infinite loops
133
+ if (req.path.includes('/logs/')) {
134
+ return;
135
+ }
136
+
137
+ const duration = Date.now() - startTime;
138
+ logger.info('HTTP Request', {
139
+ method: req.method,
140
+ path: req.path,
141
+ status: res.statusCode,
142
+ size: responseSize,
143
+ duration: `${duration}ms`,
144
+ ip: req.ip || req.socket.remoteAddress,
145
+ userAgent: req.headers['user-agent'],
146
+ timestamp: new Date().toISOString(),
147
+ });
148
+ });
149
+
150
+ next();
151
+ });
152
+
153
+ // Mount webhooks with raw body parser BEFORE JSON middleware
154
+ // This ensures signature verification uses the original bytes
155
+ app.use('/api/webhooks', express.raw({ type: 'application/json' }), webhooksRouter);
156
+
157
+ // Apply JSON middleware for all other routes
158
+ app.use(express.json({ limit: '100mb' }));
159
+ app.use(express.urlencoded({ extended: true, limit: '10mb' }));
160
+
161
+ // Create API router and mount all API routes under /api
162
+ const apiRouter = express.Router();
163
+
164
+ apiRouter.get('/health', (_req: Request, res: Response) => {
165
+ const version = packageJson.version;
166
+ res.json({
167
+ status: 'ok',
168
+ version,
169
+ service: 'Insforge OSS Backend',
170
+ timestamp: new Date().toISOString(),
171
+ });
172
+ });
173
+
174
+ // Mount all routes
175
+ apiRouter.use('/auth', authRouter);
176
+ apiRouter.use('/database', databaseRouter);
177
+ apiRouter.use('/storage', storageRouter);
178
+ apiRouter.use('/metadata', metadataRouter);
179
+ apiRouter.use('/logs', logsRouter);
180
+ apiRouter.use('/docs', docsRouter);
181
+ apiRouter.use('/functions', functionsRouter);
182
+ apiRouter.use('/secrets', secretsRouter);
183
+ apiRouter.use('/usage', usageRouter);
184
+ apiRouter.use('/ai', aiRouter);
185
+ apiRouter.use('/realtime', realtimeRouter);
186
+ apiRouter.use('/email', emailRouter);
187
+ apiRouter.use('/deployments', deploymentsRouter);
188
+
189
+ // Mount all API routes under /api prefix
190
+ app.use('/api', apiRouter);
191
+
192
+ // Proxy function execution to Deno runtime
193
+ app.all('/functions/:slug', async (req: Request, res: Response) => {
194
+ try {
195
+ const { slug } = req.params;
196
+ const denoUrl = process.env.DENO_RUNTIME_URL || 'http://localhost:7133';
197
+
198
+ // Simple direct proxy - just pass everything through
199
+ const response = await fetch(
200
+ `${denoUrl}/${slug}${req.url.includes('?') ? req.url.substring(req.url.indexOf('?')) : ''}`,
201
+ {
202
+ method: req.method,
203
+ headers: req.headers as HeadersInit,
204
+ body: ['GET', 'HEAD'].includes(req.method) ? undefined : JSON.stringify(req.body),
205
+ }
206
+ );
207
+
208
+ // Get response text
209
+ const responseText = await response.text();
210
+
211
+ res
212
+ .status(response.status)
213
+ .set('Content-Type', response.headers.get('content-type') || 'application/json')
214
+ .set('Access-Control-Allow-Origin', '*')
215
+ .send(responseText);
216
+ } catch (error) {
217
+ logger.error('Failed to proxy to Deno runtime', {
218
+ error: error instanceof Error ? error.message : String(error),
219
+ stack: error instanceof Error ? error.stack : undefined,
220
+ slug: req.params.slug,
221
+ });
222
+
223
+ // Return the actual error from Deno or connection error
224
+ const errorMessage = error instanceof Error ? error.message : String(error);
225
+ res.status(502).json({
226
+ error: errorMessage,
227
+ });
228
+ }
229
+ });
230
+
231
+ // Serve auth app
232
+ const authAppPath = path.join(__dirname, 'auth');
233
+ if (fs.existsSync(authAppPath)) {
234
+ app.use('/auth', express.static(authAppPath));
235
+ app.get('/auth*', (_req: Request, res: Response) => {
236
+ res.sendFile(path.join(authAppPath, 'index.html'));
237
+ });
238
+ } else {
239
+ const authAppUrl = process.env.AUTH_APP_URL || 'http://localhost:7132';
240
+ logger.info('Auth app not built, proxying to development server', { authAppUrl });
241
+ }
242
+
243
+ // Redirect root to dashboard login (only for non-insforge cloud environments)
244
+ if (!isCloudEnvironment()) {
245
+ app.get('/', (_req: Request, res: Response) => {
246
+ res.redirect('/dashboard/login');
247
+ });
248
+ }
249
+
250
+ // Serve main frontend if it exists
251
+ const frontendPath = path.join(__dirname, 'frontend');
252
+ if (fs.existsSync(frontendPath)) {
253
+ app.use(express.static(frontendPath, { index: false }));
254
+ // Catch all handler for SPA routes
255
+ app.get(['/cloud*', '/dashboard*'], (_req: Request, res: Response) => {
256
+ res.sendFile(path.join(frontendPath, 'index.html'));
257
+ });
258
+ } else {
259
+ // Catch-all for 404 errors - Traditional REST format
260
+ app.use('*', (req: Request, res: Response) => {
261
+ res.status(404).json({
262
+ error: 'NOT_FOUND',
263
+ message: `Endpoint ${req.originalUrl} not found`,
264
+ statusCode: 404,
265
+ nextActions: 'Please check the API documentation for available endpoints',
266
+ });
267
+ });
268
+ }
269
+
270
+ app.use(errorMiddleware);
271
+ await seedBackend();
272
+
273
+ return app;
274
+ }
275
+
276
+ // Use PORT from environment variable, fallback to 7130
277
+ const PORT = parseInt(process.env.PORT || '7130');
278
+
279
+ async function initializeServer() {
280
+ try {
281
+ const app = await createApp();
282
+ const server = app.listen(PORT, () => {
283
+ logger.info(`Backend API service listening on port ${PORT}`);
284
+ });
285
+
286
+ // Initialize Socket.IO service
287
+ const socketService = SocketManager.getInstance();
288
+ socketService.initialize(server);
289
+
290
+ // Initialize RealtimeManager (pg_notify listener)
291
+ const realtimeManager = RealtimeManager.getInstance();
292
+ await realtimeManager.initialize();
293
+ } catch (error) {
294
+ logger.error('Failed to initialize server', {
295
+ error: error instanceof Error ? error.message : String(error),
296
+ stack: error instanceof Error ? error.stack : undefined,
297
+ });
298
+ process.exit(1);
299
+ }
300
+ }
301
+
302
+ void initializeServer();
303
+
304
+ async function cleanup() {
305
+ logger.info('Shutting down gracefully...');
306
+
307
+ try {
308
+ const realtimeManager = RealtimeManager.getInstance();
309
+ await realtimeManager.close();
310
+ } catch (error) {
311
+ logger.error('Error closing RealtimeManager', {
312
+ error: error instanceof Error ? error.message : String(error),
313
+ });
314
+ }
315
+
316
+ try {
317
+ const socketService = SocketManager.getInstance();
318
+ socketService.close();
319
+ } catch (error) {
320
+ logger.error('Error closing SocketManager', {
321
+ error: error instanceof Error ? error.message : String(error),
322
+ });
323
+ }
324
+
325
+ process.exit(0);
326
+ }
327
+
328
+ process.on('SIGINT', () => void cleanup());
329
+ process.on('SIGTERM', () => void cleanup());