insforge 0.3.2 → 1.2.10

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 (507) hide show
  1. package/.claude-plugin/marketplace.json +20 -0
  2. package/.cursor/rules/cursor-rules.mdc +94 -0
  3. package/.dockerignore +3 -0
  4. package/.env.example +33 -4
  5. package/.github/ISSUE_TEMPLATE/bug_report.yml +13 -60
  6. package/.github/ISSUE_TEMPLATE/config.yml +2 -2
  7. package/.github/ISSUE_TEMPLATE/feature_request.yml +10 -63
  8. package/.github/PULL_REQUEST_TEMPLATE.md +7 -0
  9. package/.github/workflows/build-image.yml +2 -1
  10. package/.github/workflows/e2e.yml +63 -0
  11. package/CHANGELOG.md +41 -0
  12. package/CLAUDE_PLUGIN.md +104 -0
  13. package/CODE_OF_CONDUCT.md +128 -0
  14. package/CONTRIBUTING.md +1 -1
  15. package/Dockerfile +4 -1
  16. package/README.md +66 -18
  17. package/assets/mcpInstallv2.png +0 -0
  18. package/assets/sampleResponse.png +0 -0
  19. package/auth/index.html +13 -0
  20. package/auth/package.json +28 -0
  21. package/auth/public/favicon.ico +0 -0
  22. package/auth/src/App.tsx +33 -0
  23. package/auth/src/components/ErrorCard.tsx +37 -0
  24. package/auth/src/components/Layout.tsx +13 -0
  25. package/auth/src/index.css +19 -0
  26. package/auth/src/lib/broadcastService.ts +115 -0
  27. package/auth/src/lib/utils.ts +11 -0
  28. package/auth/src/main.tsx +22 -0
  29. package/auth/src/pages/ForgotPasswordPage.tsx +11 -0
  30. package/auth/src/pages/ResetPasswordPage.tsx +11 -0
  31. package/auth/src/pages/SignInPage.tsx +57 -0
  32. package/auth/src/pages/SignUpPage.tsx +57 -0
  33. package/auth/src/pages/VerifyEmailPage.tsx +20 -0
  34. package/auth/src/vite-env.d.ts +10 -0
  35. package/auth/tsconfig.json +32 -0
  36. package/auth/tsconfig.node.json +11 -0
  37. package/auth/vite.config.ts +25 -0
  38. package/backend/package.json +9 -9
  39. package/backend/src/api/{middleware → middlewares}/auth.ts +8 -9
  40. package/backend/src/api/middlewares/rate-limiters.ts +127 -0
  41. package/backend/src/api/routes/{ai.ts → ai/index.routes.ts} +20 -24
  42. package/backend/src/api/routes/auth/index.routes.ts +570 -0
  43. package/backend/src/api/routes/auth/oauth.routes.ts +448 -0
  44. package/backend/src/api/routes/{database.advance.ts → database/advance.routes.ts} +107 -65
  45. package/backend/src/api/routes/database/index.routes.ts +13 -0
  46. package/backend/src/api/routes/{database.records.ts → database/records.routes.ts} +22 -8
  47. package/backend/src/api/routes/{database.tables.ts → database/tables.routes.ts} +20 -23
  48. package/backend/src/api/routes/docs/index.routes.ts +76 -0
  49. package/backend/src/api/routes/functions/index.routes.ts +188 -0
  50. package/backend/src/api/routes/{logs.ts → logs/index.routes.ts} +25 -30
  51. package/backend/src/api/routes/{metadata.ts → metadata/index.routes.ts} +21 -31
  52. package/backend/src/api/routes/{secrets.ts → secrets/index.routes.ts} +27 -22
  53. package/backend/src/api/routes/{storage.ts → storage/index.routes.ts} +34 -53
  54. package/backend/src/api/routes/usage/index.routes.ts +89 -0
  55. package/backend/src/infra/config/app.config.ts +51 -0
  56. package/backend/src/{core/database/manager.ts → infra/database/database.manager.ts} +76 -85
  57. package/backend/src/infra/database/migrations/013_create-auth-schema-functions.sql +44 -0
  58. package/backend/src/infra/database/migrations/014_add-updated-at-trigger-user-table.sql +8 -0
  59. package/backend/src/infra/database/migrations/015_create-auth-config-and-email-otp-tables.sql +60 -0
  60. package/backend/src/infra/database/migrations/016_update-auth-config-and-email-otp.sql +24 -0
  61. package/backend/src/{core/secrets/encryption.ts → infra/security/encryption.manager.ts} +3 -2
  62. package/backend/src/infra/security/token.manager.ts +125 -0
  63. package/backend/src/{core/socket/socket.ts → infra/socket/socket.manager.ts} +15 -15
  64. package/backend/src/providers/ai/openrouter.provider.ts +377 -0
  65. package/backend/src/providers/email/base.provider.ts +41 -0
  66. package/backend/src/providers/email/cloud.provider.ts +187 -0
  67. package/backend/src/{core/logs/providers → providers/logs}/base.provider.ts +11 -11
  68. package/backend/src/{core/logs/providers → providers/logs}/cloudwatch.provider.ts +61 -38
  69. package/backend/src/providers/logs/local.provider.ts +185 -0
  70. package/backend/src/providers/oauth/base.provider.ts +29 -0
  71. package/backend/src/providers/oauth/discord.provider.ts +195 -0
  72. package/backend/src/providers/oauth/facebook.provider.ts +194 -0
  73. package/backend/src/providers/oauth/github.provider.ts +208 -0
  74. package/backend/src/providers/oauth/google.provider.ts +249 -0
  75. package/backend/src/providers/oauth/index.ts +7 -0
  76. package/backend/src/providers/oauth/linkedin.provider.ts +240 -0
  77. package/backend/src/providers/oauth/microsoft.provider.ts +169 -0
  78. package/backend/src/providers/oauth/x.provider.ts +202 -0
  79. package/backend/src/providers/storage/base.provider.ts +29 -0
  80. package/backend/src/providers/storage/local.provider.ts +103 -0
  81. package/backend/src/providers/storage/s3.provider.ts +313 -0
  82. package/backend/src/server.ts +70 -74
  83. package/backend/src/{core/ai/config.ts → services/ai/ai-config.service.ts} +19 -24
  84. package/backend/src/services/ai/ai-model.service.ts +60 -0
  85. package/backend/src/{core/ai/usage.ts → services/ai/ai-usage.service.ts} +28 -35
  86. package/backend/src/{core/ai/chat.ts → services/ai/chat-completion.service.ts} +37 -24
  87. package/backend/src/services/ai/helpers.ts +64 -0
  88. package/backend/src/{core/ai/image.ts → services/ai/image-generation.service.ts} +17 -19
  89. package/backend/src/services/ai/index.ts +13 -0
  90. package/backend/src/services/auth/auth-config.service.ts +250 -0
  91. package/backend/src/services/auth/auth-otp.service.ts +424 -0
  92. package/backend/src/services/auth/auth.service.ts +1136 -0
  93. package/backend/src/services/auth/index.ts +4 -0
  94. package/backend/src/{core/auth/oauth.ts → services/auth/oauth-config.service.ts} +106 -52
  95. package/backend/src/{core/database/advance.ts → services/database/database-advance.service.ts} +97 -131
  96. package/backend/src/services/database/database-table.service.ts +811 -0
  97. package/backend/src/services/email/email.service.ts +75 -0
  98. package/backend/src/{core/functions/functions.ts → services/functions/function.service.ts} +95 -88
  99. package/backend/src/{core/logs/audit.ts → services/logs/audit.service.ts} +92 -75
  100. package/backend/src/services/logs/log.service.ts +73 -0
  101. package/backend/src/{core/secrets/secrets.ts → services/secrets/secret.service.ts} +48 -66
  102. package/backend/src/services/storage/storage.service.ts +617 -0
  103. package/backend/src/services/usage/usage.service.ts +149 -0
  104. package/backend/src/types/auth.ts +66 -2
  105. package/backend/src/types/email.ts +8 -0
  106. package/backend/src/types/error-constants.ts +4 -0
  107. package/backend/src/types/logs.ts +0 -29
  108. package/backend/src/{core/socket/types.ts → types/socket.ts} +5 -6
  109. package/backend/src/utils/environment.ts +9 -3
  110. package/backend/src/utils/logger.ts +20 -2
  111. package/backend/src/utils/seed.ts +150 -57
  112. package/backend/src/utils/sql-parser.ts +1 -1
  113. package/backend/src/utils/utils.ts +114 -0
  114. package/backend/src/utils/validations.ts +40 -4
  115. package/backend/tests/local/test-ai-config.sh +129 -0
  116. package/backend/tests/local/test-ai-usage.sh +80 -0
  117. package/backend/tests/local/test-auth-router.sh +1 -1
  118. package/backend/tests/local/test-e2e.sh +1 -1
  119. package/backend/tests/local/test-functions.sh +123 -0
  120. package/backend/tests/local/test-logs.sh +132 -0
  121. package/backend/tests/local/test-public-bucket.sh +3 -3
  122. package/backend/tests/local/test-secrets.sh +14 -12
  123. package/backend/tests/local/test-traditional-rest.sh +2 -2
  124. package/backend/tests/manual/test-rawsql-modes.sh +244 -0
  125. package/backend/tests/test-config.sh +37 -1
  126. package/backend/tests/unit/cloud-token.test.ts +48 -0
  127. package/backend/tests/unit/constant.test.ts +8 -0
  128. package/backend/tests/unit/email.test.ts +372 -0
  129. package/backend/tests/unit/environment.test.ts +59 -0
  130. package/backend/tests/unit/helpers.test.ts +63 -0
  131. package/backend/tests/unit/logger.test.ts +22 -0
  132. package/backend/tests/unit/rate-limit.test.ts +154 -0
  133. package/backend/tests/unit/response.test.ts +58 -0
  134. package/backend/tests/unit/sql-parser.test.ts +74 -0
  135. package/backend/tests/unit/uuid.test.ts +21 -0
  136. package/backend/tests/unit/validations.test.ts +80 -0
  137. package/backend/tsconfig.json +1 -1
  138. package/backend/vitest.config.ts +11 -0
  139. package/claude-plugin/.claude-plugin/plugin.json +24 -0
  140. package/claude-plugin/README.md +133 -0
  141. package/claude-plugin/skills/insforge-schema-patterns/SKILL.md +270 -0
  142. package/docker-compose.prod.yml +60 -4
  143. package/docker-compose.yml +65 -4
  144. package/docker-init/db/db-init.sql +6 -34
  145. package/docker-init/logs/vector.yml +236 -0
  146. package/docs/README.md +44 -0
  147. package/docs/changelog.mdx +67 -0
  148. package/docs/core-concepts/ai/architecture.mdx +373 -0
  149. package/docs/core-concepts/ai/sdk.mdx +213 -0
  150. package/docs/core-concepts/authentication/architecture.mdx +278 -0
  151. package/docs/core-concepts/authentication/sdk.mdx +414 -0
  152. package/docs/core-concepts/authentication/ui-components/customization.mdx +529 -0
  153. package/docs/core-concepts/authentication/ui-components/nextjs.mdx +221 -0
  154. package/docs/core-concepts/authentication/ui-components/react-router.mdx +184 -0
  155. package/docs/core-concepts/authentication/ui-components/react.mdx +129 -0
  156. package/docs/core-concepts/database/architecture.mdx +256 -0
  157. package/docs/core-concepts/database/sdk.mdx +382 -0
  158. package/docs/core-concepts/functions/architecture.mdx +105 -0
  159. package/docs/core-concepts/functions/sdk.mdx +184 -0
  160. package/docs/core-concepts/storage/architecture.mdx +243 -0
  161. package/docs/core-concepts/storage/sdk.mdx +253 -0
  162. package/docs/deployment/README.md +94 -0
  163. package/docs/deployment/deploy-to-aws-ec2.md +565 -0
  164. package/docs/deployment/deploy-to-azure-virtual-machines.md +313 -0
  165. package/docs/deployment/deploy-to-google-cloud-compute-engine.md +613 -0
  166. package/docs/deployment/deploy-to-render.md +441 -0
  167. package/docs/docs.json +210 -0
  168. package/docs/examples/framework-guides/nextjs.mdx +131 -0
  169. package/docs/examples/framework-guides/nuxt.mdx +165 -0
  170. package/docs/examples/framework-guides/react.mdx +165 -0
  171. package/docs/examples/framework-guides/svelte.mdx +153 -0
  172. package/docs/examples/framework-guides/vue.mdx +159 -0
  173. package/docs/examples/overview.mdx +67 -0
  174. package/docs/favicon.svg +19 -0
  175. package/docs/images/changelog/nov-2025/auth-components.webp +0 -0
  176. package/docs/images/changelog/nov-2025/database-metadata.webp +0 -0
  177. package/docs/images/changelog/nov-2025/quickstart-prompts.webp +0 -0
  178. package/docs/images/changelog/nov-2025/sql-editor.webp +0 -0
  179. package/docs/images/changelog/nov-2025/usage-page.webp +0 -0
  180. package/docs/images/changelog/october-2025/csv-upload.webp +0 -0
  181. package/docs/images/changelog/october-2025/logs-feature.webp +0 -0
  182. package/docs/images/changelog/october-2025/oauth-providers.webp +0 -0
  183. package/docs/images/checks-passed.png +0 -0
  184. package/docs/images/dashboard-connect-expanded.png +0 -0
  185. package/docs/images/dashboard-connect.png +0 -0
  186. package/docs/images/hero-dark.png +0 -0
  187. package/docs/images/hero-light.png +0 -0
  188. package/docs/images/icons/ai.svg +4 -0
  189. package/docs/images/icons/auth.svg +1 -0
  190. package/docs/images/icons/database.svg +1 -0
  191. package/docs/images/icons/function.svg +1 -0
  192. package/docs/images/icons/storage.svg +1 -0
  193. package/docs/images/logos/nextjs.svg +4 -0
  194. package/docs/images/logos/nuxt.svg +4 -0
  195. package/docs/images/logos/react.svg +5 -0
  196. package/docs/images/logos/svelte.svg +4 -0
  197. package/docs/images/logos/vue.svg +5 -0
  198. package/docs/images/mcp-install.png +0 -0
  199. package/docs/images/onboarding-mcp.png +0 -0
  200. package/docs/insforge-instructions-sdk.md +55 -374
  201. package/docs/introduction.mdx +45 -0
  202. package/docs/logo/dark.svg +22 -0
  203. package/docs/logo/light.svg +20 -0
  204. package/docs/partnership.mdx +647 -0
  205. package/docs/quickstart.mdx +83 -0
  206. package/docs/showcase/2048-arena.png +0 -0
  207. package/docs/showcase/framegen-cloud.png +0 -0
  208. package/docs/showcase/line-connect-race.png +0 -0
  209. package/docs/showcase/moment-vibe.png +0 -0
  210. package/docs/showcase/national-flags.png +0 -0
  211. package/docs/showcase/pokemon-vibe.png +0 -0
  212. package/docs/showcase/pure-browse-buy.png +0 -0
  213. package/docs/showcase.mdx +52 -0
  214. package/docs/snippets/sdk-installation.mdx +22 -0
  215. package/docs/snippets/service-icons.mdx +27 -0
  216. package/eslint.config.js +10 -3
  217. package/frontend/package.json +10 -4
  218. package/frontend/src/App.tsx +13 -82
  219. package/frontend/src/assets/icons/connected.svg +3 -0
  220. package/frontend/src/assets/icons/loader.svg +9 -0
  221. package/frontend/src/assets/logos/apple.svg +4 -0
  222. package/frontend/src/assets/logos/discord.svg +1 -1
  223. package/frontend/src/assets/logos/facebook.svg +3 -0
  224. package/frontend/src/assets/logos/instagram.svg +2 -0
  225. package/frontend/src/assets/logos/linkedin.svg +3 -0
  226. package/frontend/src/assets/logos/microsoft.svg +1 -0
  227. package/frontend/src/assets/logos/spotify.svg +17 -0
  228. package/frontend/src/assets/logos/tiktok.svg +6 -0
  229. package/frontend/src/assets/logos/x.svg +3 -0
  230. package/frontend/src/components/Checkbox.tsx +27 -29
  231. package/frontend/src/components/CodeBlock.tsx +55 -2
  232. package/frontend/src/components/CodeEditor.tsx +92 -0
  233. package/frontend/src/components/ConfirmDialog.tsx +1 -1
  234. package/frontend/src/components/ConnectCTA.tsx +38 -0
  235. package/frontend/src/components/CopyButton.tsx +52 -15
  236. package/frontend/src/components/ErrorState.tsx +1 -2
  237. package/frontend/src/components/FeatureSidebar.tsx +6 -6
  238. package/frontend/src/components/FeatureSidebarItem.tsx +2 -2
  239. package/frontend/src/components/JsonHighlight.tsx +21 -9
  240. package/frontend/src/components/ProjectInfoModal.tsx +128 -0
  241. package/frontend/src/components/PromptDialog.tsx +1 -4
  242. package/frontend/src/components/SearchInput.tsx +1 -2
  243. package/frontend/src/components/Stepper.tsx +53 -0
  244. package/frontend/src/components/ThemeToggle.tsx +3 -3
  245. package/frontend/src/components/datagrid/DataGrid.tsx +25 -32
  246. package/frontend/src/components/datagrid/cell-editors/DateCellEditor.tsx +1 -2
  247. package/frontend/src/components/datagrid/cell-editors/JsonCellEditor.tsx +2 -4
  248. package/frontend/src/components/datagrid/index.ts +23 -0
  249. package/frontend/src/components/index.ts +23 -30
  250. package/frontend/src/components/layout/AppHeader.tsx +133 -92
  251. package/frontend/src/components/layout/AppSidebar.tsx +80 -170
  252. package/frontend/src/components/layout/Layout.tsx +12 -23
  253. package/frontend/src/components/layout/PrimaryMenu.tsx +187 -0
  254. package/frontend/src/components/layout/SecondaryMenu.tsx +70 -0
  255. package/frontend/src/components/layout/index.ts +5 -0
  256. package/frontend/src/components/radix/Tooltip.tsx +24 -13
  257. package/frontend/src/components/radix/index.ts +22 -0
  258. package/frontend/src/features/ai/components/AIConfigCard.tsx +129 -83
  259. package/frontend/src/features/ai/components/AIEmptyState.tsx +12 -7
  260. package/frontend/src/features/ai/components/ModalityFilterSidebar.tsx +101 -0
  261. package/frontend/src/features/ai/components/ModelSelectionDialog.tsx +135 -0
  262. package/frontend/src/features/ai/components/ModelSelectionGrid.tsx +51 -0
  263. package/frontend/src/features/ai/components/SystemPromptDialog.tsx +118 -0
  264. package/frontend/src/features/ai/components/index.ts +6 -0
  265. package/frontend/src/features/ai/helpers.ts +57 -71
  266. package/frontend/src/features/ai/hooks/useAIConfigs.ts +39 -113
  267. package/frontend/src/features/ai/hooks/useAIUsage.ts +0 -2
  268. package/frontend/src/features/ai/page/AIPage.tsx +67 -79
  269. package/frontend/src/features/ai/services/ai.service.ts +5 -5
  270. package/frontend/src/features/auth/components/AuthPreview.tsx +96 -0
  271. package/frontend/src/features/auth/components/OAuthConfigDialog.tsx +53 -30
  272. package/frontend/src/features/auth/components/UserFormDialog.tsx +13 -6
  273. package/frontend/src/features/auth/components/UsersDataGrid.tsx +44 -14
  274. package/frontend/src/features/auth/components/index.ts +5 -0
  275. package/frontend/src/features/auth/helpers.tsx +200 -0
  276. package/frontend/src/features/auth/hooks/useAnonToken.ts +30 -0
  277. package/frontend/src/features/auth/hooks/useAuthConfig.ts +48 -0
  278. package/frontend/src/features/auth/hooks/useOAuthConfig.ts +14 -10
  279. package/frontend/src/features/auth/hooks/useUsers.ts +43 -5
  280. package/frontend/src/features/auth/index.ts +3 -2
  281. package/frontend/src/features/auth/page/AuthMethodsPage.tsx +275 -0
  282. package/frontend/src/features/auth/page/ConfigurationPage.tsx +395 -0
  283. package/frontend/src/features/auth/page/UsersPage.tsx +285 -0
  284. package/frontend/src/features/auth/services/anonToken.service.ts +11 -0
  285. package/frontend/src/features/auth/services/config.service.ts +19 -0
  286. package/frontend/src/features/auth/services/{oauth.service.ts → oauth-config.service.ts} +4 -4
  287. package/frontend/src/features/auth/services/{auth.service.ts → user.service.ts} +7 -53
  288. package/frontend/src/features/dashboard/components/ConnectionSuccessBanner.tsx +35 -0
  289. package/frontend/src/features/dashboard/components/PromptCard.tsx +21 -0
  290. package/frontend/src/features/dashboard/components/PromptDialog.tsx +103 -0
  291. package/frontend/src/features/dashboard/components/StatsCard.tsx +50 -0
  292. package/frontend/src/features/dashboard/components/index.ts +4 -0
  293. package/frontend/src/features/dashboard/page/DashboardPage.tsx +187 -169
  294. package/frontend/src/features/dashboard/prompts/ai-chatbot.ts +13 -0
  295. package/frontend/src/features/dashboard/prompts/crm-system.ts +13 -0
  296. package/frontend/src/features/dashboard/prompts/ecommerce-platform.ts +12 -0
  297. package/frontend/src/features/dashboard/prompts/index.ts +31 -0
  298. package/frontend/src/features/dashboard/prompts/instagram-clone.ts +11 -0
  299. package/frontend/src/features/dashboard/prompts/notion-clone.ts +14 -0
  300. package/frontend/src/features/dashboard/prompts/reddit-clone.ts +12 -0
  301. package/frontend/src/features/database/components/DatabaseDataGrid.tsx +48 -17
  302. package/frontend/src/features/database/components/ForeignKeyCell.tsx +15 -34
  303. package/frontend/src/features/database/components/ForeignKeyPopover.tsx +19 -20
  304. package/frontend/src/features/database/components/LinkRecordModal.tsx +120 -125
  305. package/frontend/src/features/database/components/RecordFormDialog.tsx +22 -33
  306. package/frontend/src/features/database/components/RecordFormField.tsx +45 -47
  307. package/frontend/src/features/database/components/TableEmptyState.tsx +6 -5
  308. package/frontend/src/features/database/components/TableForm.tsx +28 -15
  309. package/frontend/src/features/database/components/TableFormColumn.tsx +2 -3
  310. package/frontend/src/features/database/components/TableSidebar.tsx +1 -1
  311. package/frontend/src/features/database/components/TablesEmptyState.tsx +48 -0
  312. package/frontend/src/features/database/components/TemplateCard.tsx +37 -0
  313. package/frontend/src/features/database/components/TemplatePreview.tsx +92 -0
  314. package/frontend/src/features/database/components/index.ts +19 -0
  315. package/frontend/src/features/database/constants.ts +28 -2
  316. package/frontend/src/features/database/contexts/SQLEditorContext.tsx +188 -0
  317. package/frontend/src/features/database/helpers.ts +2 -2
  318. package/frontend/src/features/database/hooks/useCSVImport.ts +29 -0
  319. package/frontend/src/features/database/hooks/useFullMetadata.ts +18 -0
  320. package/frontend/src/features/database/hooks/useRawSQL.ts +55 -0
  321. package/frontend/src/features/database/hooks/useRecords.ts +139 -0
  322. package/frontend/src/features/database/hooks/useTables.ts +131 -0
  323. package/frontend/src/features/database/index.ts +6 -1
  324. package/frontend/src/features/database/page/FunctionsPage.tsx +211 -0
  325. package/frontend/src/features/database/page/IndexesPage.tsx +240 -0
  326. package/frontend/src/features/database/page/PoliciesPage.tsx +248 -0
  327. package/frontend/src/features/database/page/SQLEditorPage.tsx +382 -0
  328. package/frontend/src/features/database/page/{DatabasePage.tsx → TablesPage.tsx} +186 -185
  329. package/frontend/src/features/database/page/TemplatesPage.tsx +39 -0
  330. package/frontend/src/features/database/page/TriggersPage.tsx +242 -0
  331. package/frontend/src/features/database/services/advance.service.ts +66 -0
  332. package/frontend/src/features/database/services/{database.service.ts → record.service.ts} +67 -64
  333. package/frontend/src/features/database/services/table.service.ts +64 -0
  334. package/frontend/src/features/database/templates/ai-chatbot.ts +402 -0
  335. package/frontend/src/features/database/templates/crm-system.ts +528 -0
  336. package/frontend/src/features/database/templates/ecommerce-platform.ts +553 -0
  337. package/frontend/src/features/database/templates/index.ts +34 -0
  338. package/frontend/src/features/database/templates/instagram-clone.ts +222 -0
  339. package/frontend/src/features/database/templates/notion-clone.ts +483 -0
  340. package/frontend/src/features/database/templates/reddit-clone.ts +526 -0
  341. package/frontend/src/features/functions/components/FunctionRow.tsx +2 -1
  342. package/frontend/src/features/functions/components/FunctionsSidebar.tsx +1 -1
  343. package/frontend/src/features/functions/components/SecretRow.tsx +1 -1
  344. package/frontend/src/features/functions/components/index.ts +5 -0
  345. package/frontend/src/features/functions/hooks/useFunctions.ts +4 -4
  346. package/frontend/src/features/{secrets → functions}/hooks/useSecrets.ts +5 -5
  347. package/frontend/src/features/functions/page/FunctionsPage.tsx +160 -17
  348. package/frontend/src/features/functions/{components/SecretsContent.tsx → page/SecretsPage.tsx} +8 -12
  349. package/frontend/src/features/functions/services/{functions.service.ts → function.service.ts} +2 -2
  350. package/frontend/src/features/{secrets/services/secrets.service.ts → functions/services/secret.service.ts} +2 -2
  351. package/frontend/src/features/login/hooks/usePartnerOrigin.ts +27 -0
  352. package/frontend/src/features/login/page/CloudLoginPage.tsx +79 -54
  353. package/frontend/src/features/login/page/LoginPage.tsx +16 -23
  354. package/frontend/src/features/login/services/partnership.service.ts +65 -0
  355. package/frontend/src/features/logs/components/LogsDataGrid.tsx +89 -0
  356. package/frontend/src/features/logs/components/SeverityBadge.tsx +18 -0
  357. package/frontend/src/features/logs/components/index.ts +2 -0
  358. package/frontend/src/features/logs/helpers.ts +24 -0
  359. package/frontend/src/features/logs/hooks/useAuditLogs.ts +4 -4
  360. package/frontend/src/features/logs/hooks/useLogSources.ts +137 -0
  361. package/frontend/src/features/logs/hooks/useLogs.ts +163 -0
  362. package/frontend/src/features/logs/hooks/useMcpUsage.ts +181 -0
  363. package/frontend/src/features/logs/index.ts +8 -2
  364. package/frontend/src/features/logs/page/AuditsPage.tsx +91 -38
  365. package/frontend/src/features/logs/page/LogsPage.tsx +152 -0
  366. package/frontend/src/features/logs/page/MCPLogsPage.tsx +84 -0
  367. package/frontend/src/features/logs/services/audit.service.ts +63 -0
  368. package/frontend/src/features/logs/services/log.service.ts +15 -110
  369. package/frontend/src/features/logs/services/usage.service.ts +31 -0
  370. package/frontend/src/features/onboard/components/McpConnectionStatus.tsx +68 -0
  371. package/frontend/src/features/onboard/components/OnboardingModal.tsx +267 -0
  372. package/frontend/src/features/onboard/components/VideoDemoModal.tsx +38 -0
  373. package/frontend/src/features/onboard/components/index.ts +4 -0
  374. package/frontend/src/features/onboard/components/mcp/CursorDeeplinkGenerator.tsx +2 -2
  375. package/frontend/src/features/onboard/components/mcp/{mcp-helper.tsx → helpers.tsx} +8 -8
  376. package/frontend/src/features/onboard/components/mcp/index.ts +2 -3
  377. package/frontend/src/features/onboard/index.ts +13 -3
  378. package/frontend/src/features/storage/components/BucketEmptyState.tsx +9 -6
  379. package/frontend/src/features/storage/components/BucketFormDialog.tsx +25 -41
  380. package/frontend/src/features/storage/components/FilePreviewDialog.tsx +20 -8
  381. package/frontend/src/features/storage/components/StorageDataGrid.tsx +4 -3
  382. package/frontend/src/features/storage/components/StorageManager.tsx +23 -34
  383. package/frontend/src/features/storage/components/index.ts +12 -0
  384. package/frontend/src/features/storage/hooks/useStorage.ts +208 -0
  385. package/frontend/src/features/storage/page/StoragePage.tsx +41 -115
  386. package/frontend/src/features/storage/services/storage.service.ts +22 -1
  387. package/frontend/src/features/visualizer/components/AuthNode.tsx +72 -56
  388. package/frontend/src/features/visualizer/components/BucketNode.tsx +4 -4
  389. package/frontend/src/features/visualizer/components/SchemaVisualizer.tsx +108 -80
  390. package/frontend/src/features/visualizer/components/TableNode.tsx +34 -41
  391. package/frontend/src/features/visualizer/components/VisualizerSkeleton.tsx +12 -4
  392. package/frontend/src/features/visualizer/page/VisualizerPage.tsx +33 -29
  393. package/frontend/src/index.css +1 -0
  394. package/frontend/src/lib/analytics/posthog.tsx +27 -0
  395. package/frontend/src/lib/contexts/AuthContext.tsx +38 -31
  396. package/frontend/src/lib/contexts/SocketContext.tsx +5 -6
  397. package/frontend/src/{features/metadata → lib}/hooks/useMetadata.ts +1 -1
  398. package/frontend/src/lib/hooks/useToast.tsx +6 -2
  399. package/frontend/src/lib/routing/AppRoutes.tsx +84 -0
  400. package/frontend/src/lib/routing/RequireAuth.tsx +27 -0
  401. package/frontend/src/lib/utils/cloudMessaging.ts +20 -0
  402. package/frontend/src/lib/utils/menuItems.ts +183 -0
  403. package/frontend/src/lib/utils/{validation-schemas.ts → schemaValidations.ts} +10 -5
  404. package/frontend/src/lib/utils/utils.ts +19 -1
  405. package/frontend/src/vite-env.d.ts +1 -0
  406. package/frontend/vite.config.ts +5 -3
  407. package/functions/server.ts +28 -3
  408. package/functions/worker-template.js +15 -4
  409. package/i18n/README.ar.md +130 -0
  410. package/i18n/README.de.md +130 -0
  411. package/i18n/README.es.md +154 -0
  412. package/i18n/README.fr.md +134 -0
  413. package/i18n/README.hi.md +129 -0
  414. package/i18n/README.ja.md +174 -0
  415. package/i18n/README.ko.md +137 -0
  416. package/i18n/README.pt-BR.md +131 -0
  417. package/i18n/README.ru.md +129 -0
  418. package/i18n/README.zh-CN.md +133 -0
  419. package/openapi/ai.yaml +31 -4
  420. package/openapi/auth.yaml +827 -146
  421. package/package.json +16 -7
  422. package/shared-schemas/package.json +1 -1
  423. package/shared-schemas/src/ai-api.schema.ts +34 -58
  424. package/shared-schemas/src/ai.schema.ts +5 -0
  425. package/shared-schemas/src/auth-api.schema.ts +154 -8
  426. package/shared-schemas/src/auth.schema.ts +42 -6
  427. package/shared-schemas/src/cloud-events.schema.ts +57 -0
  428. package/shared-schemas/src/database-api.schema.ts +3 -3
  429. package/shared-schemas/src/database.schema.ts +1 -1
  430. package/shared-schemas/src/index.ts +1 -0
  431. package/shared-schemas/src/logs-api.schema.ts +7 -1
  432. package/shared-schemas/src/logs.schema.ts +26 -0
  433. package/shared-schemas/src/metadata.schema.ts +9 -4
  434. package/test-gemini.sh +35 -0
  435. package/test-usage-admin.sh +57 -0
  436. package/test-usage.sh +50 -0
  437. package/zeabur/README.md +13 -0
  438. package/zeabur/template.yml +1032 -0
  439. package/.github/workflows/deploy-aws.yml +0 -130
  440. package/backend/src/api/routes/agent.ts +0 -29
  441. package/backend/src/api/routes/auth.oauth.ts +0 -482
  442. package/backend/src/api/routes/auth.ts +0 -386
  443. package/backend/src/api/routes/docs.ts +0 -66
  444. package/backend/src/api/routes/functions.ts +0 -183
  445. package/backend/src/api/routes/openapi.ts +0 -82
  446. package/backend/src/api/routes/usage.ts +0 -96
  447. package/backend/src/core/ai/client.ts +0 -242
  448. package/backend/src/core/ai/model.ts +0 -117
  449. package/backend/src/core/auth/auth.ts +0 -781
  450. package/backend/src/core/database/table.ts +0 -772
  451. package/backend/src/core/documentation/agent.ts +0 -689
  452. package/backend/src/core/documentation/openapi.ts +0 -856
  453. package/backend/src/core/logs/analytics.ts +0 -76
  454. package/backend/src/core/logs/providers/localdb.provider.ts +0 -246
  455. package/backend/src/core/storage/storage.ts +0 -923
  456. package/backend/src/utils/cloud-token.ts +0 -39
  457. package/backend/src/utils/helpers.ts +0 -49
  458. package/backend/src/utils/uuid.ts +0 -9
  459. package/backend/tests/manual/test-better-auth.sh +0 -303
  460. package/docker-init/db/logs.sql +0 -9
  461. package/frontend/README.md +0 -112
  462. package/frontend/src/components/datagrid/index.tsx +0 -20
  463. package/frontend/src/components/layout/CloudLayout.tsx +0 -95
  464. package/frontend/src/features/ai/components/AIConfigDialog.tsx +0 -76
  465. package/frontend/src/features/ai/components/AIConfigForm.tsx +0 -222
  466. package/frontend/src/features/ai/components/fields/ModalityField.tsx +0 -87
  467. package/frontend/src/features/ai/components/fields/ModelSelectionField.tsx +0 -134
  468. package/frontend/src/features/ai/components/fields/SystemPromptField.tsx +0 -33
  469. package/frontend/src/features/auth/components/AddOAuthDialog.tsx +0 -106
  470. package/frontend/src/features/auth/components/AuthMethodTab.tsx +0 -238
  471. package/frontend/src/features/auth/components/UsersTab.tsx +0 -114
  472. package/frontend/src/features/auth/page/AuthenticationPage.tsx +0 -169
  473. package/frontend/src/features/database/hooks/UseLinkModal.tsx +0 -78
  474. package/frontend/src/features/functions/components/FunctionViewer.tsx +0 -46
  475. package/frontend/src/features/functions/components/FunctionsContent.tsx +0 -88
  476. package/frontend/src/features/login/components/AuthErrorBoundary.tsx +0 -87
  477. package/frontend/src/features/login/components/PrivateRoute.tsx +0 -24
  478. package/frontend/src/features/logs/components/AnalyticsLogsTable.tsx +0 -313
  479. package/frontend/src/features/logs/components/LogsTable.tsx +0 -199
  480. package/frontend/src/features/logs/page/AnalyticsLogsPage.tsx +0 -530
  481. package/frontend/src/features/metadata/index.ts +0 -0
  482. package/frontend/src/features/metadata/page/MetadataPage.tsx +0 -136
  483. package/frontend/src/features/onboard/components/CompletionCard.tsx +0 -41
  484. package/frontend/src/features/onboard/components/OnboardButton.tsx +0 -84
  485. package/frontend/src/features/onboard/components/StepContent.tsx +0 -91
  486. package/frontend/src/features/onboard/components/TestConnectionStep.tsx +0 -53
  487. package/frontend/src/features/onboard/components/mcp/McpInstallation.tsx +0 -144
  488. package/frontend/src/features/onboard/page/OnBoardPage.tsx +0 -104
  489. package/frontend/src/features/onboard/types.ts +0 -8
  490. package/frontend/src/lib/contexts/OnboardStepContext.tsx +0 -68
  491. package/frontend/src/lib/hooks/useOnboardingCompletion.ts +0 -29
  492. /package/backend/src/api/{middleware → middlewares}/error.ts +0 -0
  493. /package/backend/src/api/{middleware → middlewares}/upload.ts +0 -0
  494. /package/backend/{migrations → src/infra/database/migrations}/000_create-base-tables.sql +0 -0
  495. /package/backend/{migrations → src/infra/database/migrations}/001_create-helper-functions.sql +0 -0
  496. /package/backend/{migrations → src/infra/database/migrations}/002_rename-auth-tables.sql +0 -0
  497. /package/backend/{migrations → src/infra/database/migrations}/003_create-users-table.sql +0 -0
  498. /package/backend/{migrations → src/infra/database/migrations}/004_add-reload-postgrest-func.sql +0 -0
  499. /package/backend/{migrations → src/infra/database/migrations}/005_enable-project-admin-modify-users.sql +0 -0
  500. /package/backend/{migrations → src/infra/database/migrations}/006_modify-ai-usage-table.sql +0 -0
  501. /package/backend/{migrations → src/infra/database/migrations}/007_drop-metadata-table.sql +0 -0
  502. /package/backend/{migrations → src/infra/database/migrations}/008_add-system-tables.sql +0 -0
  503. /package/backend/{migrations → src/infra/database/migrations}/009_add-function-secrets.sql +0 -0
  504. /package/backend/{migrations → src/infra/database/migrations}/010_modify-ai-config-modalities.sql +0 -0
  505. /package/backend/{migrations → src/infra/database/migrations}/011_refactor-secrets-table.sql +0 -0
  506. /package/backend/{migrations → src/infra/database/migrations}/012_add-storage-uploaded-by.sql +0 -0
  507. /package/frontend/src/{features/metadata → lib}/services/metadata.service.ts +0 -0
@@ -0,0 +1,1032 @@
1
+ # yaml-language-server: $schema=https://schema.zeabur.app/template.json
2
+ apiVersion: zeabur.com/v1
3
+ kind: Template
4
+ metadata:
5
+ name: InsForge
6
+ spec:
7
+ description: InsForge is the Agent-Native Supabase Alternative, enabling AI agents to build and manage full-stack applications autonomously.
8
+ coverImage: https://cdn.zeabur.com/insforge.png
9
+ icon: https://avatars.githubusercontent.com/u/198419463?s=96&v=4
10
+ variables:
11
+ - key: PUBLIC_DOMAIN
12
+ type: DOMAIN
13
+ name: InsForge Domain
14
+ description: The domain for accessing your InsForge application.
15
+ - key: ADMIN_EMAIL
16
+ type: STRING
17
+ name: Admin Email
18
+ description: Email address for the admin user.
19
+ - key: ADMIN_PASSWORD
20
+ type: STRING
21
+ name: Admin Password
22
+ description: Password for admin. Must be at least 8 characters.
23
+ - key: OPENROUTER_API_KEY
24
+ type: STRING
25
+ name: OpenRouter API Key
26
+ description: API key for OpenRouter LLM services (optional).
27
+ tags:
28
+ - Development
29
+ - Database
30
+ - API
31
+ - Platform
32
+ readme: |-
33
+ # InsForge
34
+
35
+ InsForge is the Agent-Native Supabase Alternative, enabling AI agents to build and manage full-stack applications autonomously.
36
+
37
+ ## Features
38
+
39
+ - **Authentication System** - User management and secure authentication
40
+ - **Database Storage** - Flexible PostgreSQL database with automatic schema management
41
+ - **File Management** - Secure file upload and storage capabilities
42
+ - **PostgREST API** - Automatic REST API generation from database schema
43
+ - **Serverless Functions** - Edge functions for custom business logic
44
+ - **AI Agent Integration** - Connect AI agents like Claude or GPT to manage your backend
45
+
46
+ ## Quick Start
47
+
48
+ This template provides **one-click deployment** of the complete InsForge platform:
49
+
50
+ 1. **Deploy** - Click deploy and bind a domain
51
+ 2. **Login** - Use your admin credentials to access the dashboard
52
+ 3. **Connect AI Agent** - Link your AI agent (Claude, GPT, etc.) through the dashboard
53
+ 4. **Build Apps** - Use natural language prompts to create applications:
54
+ - "Build a todo app with user authentication"
55
+ - "Create an Instagram clone with image upload"
56
+ - "Build a blog with comments and likes"
57
+
58
+ ## Use Cases
59
+
60
+ - **AI-Generated Frontends** - Rapidly create backends for AI-generated frontend projects
61
+ - **Agent-Driven Development** - Let AI agents manage your entire backend infrastructure
62
+ - **Rapid Prototyping** - Build full-stack applications using natural language
63
+
64
+ ## Community
65
+
66
+ - [Discord](https://discord.gg/MPxwj5xVvW) - Join our community
67
+ - [GitHub](https://github.com/InsForge/InsForge) - Contribute to the project
68
+ - Email: info@insforge.dev
69
+
70
+ services:
71
+ - name: postgres
72
+ icon: https://raw.githubusercontent.com/zeabur/service-icons/main/marketplace/postgresql.svg
73
+ template: PREBUILT
74
+ spec:
75
+ source:
76
+ image: postgres:15.13
77
+ command:
78
+ - docker-entrypoint.sh
79
+ - -c
80
+ - config_file=/etc/postgresql/postgresql.conf
81
+ ports:
82
+ - id: database
83
+ port: 5432
84
+ type: TCP
85
+ volumes:
86
+ - id: data
87
+ dir: /var/lib/postgresql/data
88
+ instructions:
89
+ - title: Connection String
90
+ content: postgres://postgres:${POSTGRES_PASSWORD}@${PORT_FORWARDED_HOSTNAME}:${DATABASE_PORT_FORWARDED_PORT}/insforge
91
+ - title: PostgreSQL Connect Command
92
+ content: psql "postgres://postgres:${POSTGRES_PASSWORD}@${PORT_FORWARDED_HOSTNAME}:${DATABASE_PORT_FORWARDED_PORT}/insforge"
93
+ - title: PostgreSQL username
94
+ content: postgres
95
+ - title: PostgresSQL password
96
+ content: ${POSTGRES_PASSWORD}
97
+ - title: PostgresSQL database
98
+ content: insforge
99
+ - title: PostgreSQL host
100
+ content: ${PORT_FORWARDED_HOSTNAME}
101
+ - title: PostgreSQL port
102
+ content: ${DATABASE_PORT_FORWARDED_PORT}
103
+ env:
104
+ PGDATA:
105
+ default: /var/lib/postgresql/data/pgdata
106
+ POSTGRES_CONNECTION_STRING:
107
+ default: postgres://postgres:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/insforge
108
+ expose: true
109
+ POSTGRES_DATABASE:
110
+ default: insforge
111
+ expose: true
112
+ POSTGRES_DB:
113
+ default: insforge
114
+ POSTGRES_HOST:
115
+ default: ${CONTAINER_HOSTNAME}
116
+ expose: true
117
+ POSTGRES_PASSWORD:
118
+ default: ${PASSWORD}
119
+ expose: true
120
+ readonly: true
121
+ POSTGRES_PORT:
122
+ default: ${DATABASE_PORT}
123
+ expose: true
124
+ POSTGRES_URI:
125
+ default: ${POSTGRES_CONNECTION_STRING}
126
+ expose: true
127
+ POSTGRES_USER:
128
+ default: postgres
129
+ POSTGRES_USERNAME:
130
+ default: postgres
131
+ expose: true
132
+ JWT_SECRET:
133
+ default: ${PASSWORD}
134
+ expose: true
135
+ readonly: true
136
+ JWT_EXP:
137
+ default: "3600"
138
+ configs:
139
+ - path: /etc/postgresql/postgresql.conf
140
+ template: |
141
+ # PostgreSQL configuration for InsForge
142
+ # Enable logical replication for Logflare
143
+
144
+ # Listen on all interfaces to allow container connections
145
+ listen_addresses = '*'
146
+
147
+ # Set WAL level to logical for Logflare replication
148
+ wal_level = logical
149
+
150
+ # Set max replication slots (needed for logical replication)
151
+ max_replication_slots = 10
152
+
153
+ # Set max WAL senders
154
+ max_wal_senders = 10
155
+
156
+ # Shared preload libraries (if needed)
157
+ # shared_preload_libraries = 'pg_stat_statements'
158
+ - path: /docker-entrypoint-initdb.d/01-init.sql
159
+ template: |
160
+ -- init.sql
161
+ -- Create role for anonymous user
162
+ CREATE ROLE anon NOLOGIN;
163
+
164
+ -- Create role for authenticator
165
+ CREATE ROLE authenticated NOLOGIN;
166
+
167
+ -- Create project admin role for admin users
168
+ CREATE ROLE project_admin NOLOGIN;
169
+
170
+ GRANT USAGE ON SCHEMA public TO anon;
171
+ GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO anon;
172
+ GRANT USAGE ON SCHEMA public TO authenticated;
173
+ GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO authenticated;
174
+ GRANT USAGE ON SCHEMA public TO project_admin;
175
+ GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO project_admin;
176
+
177
+ -- Grant permissions to roles
178
+ -- NOTICE: The anon role is intended for unauthenticated users, so it should only have read access.
179
+ GRANT SELECT ON ALL TABLES IN SCHEMA public TO anon;
180
+ ALTER DEFAULT PRIVILEGES IN SCHEMA public
181
+ GRANT SELECT ON TABLES TO anon;
182
+
183
+ GRANT SELECT ON ALL TABLES IN SCHEMA public TO authenticated;
184
+ ALTER DEFAULT PRIVILEGES IN SCHEMA public
185
+ GRANT SELECT ON TABLES TO authenticated;
186
+
187
+ GRANT INSERT ON ALL TABLES IN SCHEMA public TO authenticated;
188
+ ALTER DEFAULT PRIVILEGES IN SCHEMA public
189
+ GRANT INSERT ON TABLES TO authenticated;
190
+
191
+ GRANT UPDATE ON ALL TABLES IN SCHEMA public TO authenticated;
192
+ ALTER DEFAULT PRIVILEGES IN SCHEMA public
193
+ GRANT UPDATE ON TABLES TO authenticated;
194
+
195
+ GRANT DELETE ON ALL TABLES IN SCHEMA public TO authenticated;
196
+ ALTER DEFAULT PRIVILEGES IN SCHEMA public
197
+ GRANT DELETE ON TABLES TO authenticated;
198
+
199
+ GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO project_admin;
200
+ ALTER DEFAULT PRIVILEGES IN SCHEMA public
201
+ GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO project_admin;
202
+
203
+ -- Create function to automatically create RLS policies for new tables
204
+ CREATE OR REPLACE FUNCTION public.create_default_policies()
205
+ RETURNS event_trigger AS $$
206
+ DECLARE
207
+ obj record;
208
+ table_schema text;
209
+ table_name text;
210
+ has_rls boolean;
211
+ BEGIN
212
+ FOR obj IN SELECT * FROM pg_event_trigger_ddl_commands() WHERE command_tag = 'CREATE TABLE'
213
+ LOOP
214
+ -- Extract schema and table name from object_identity
215
+ -- Handle quoted identifiers by removing quotes
216
+ SELECT INTO table_schema, table_name
217
+ split_part(obj.object_identity, '.', 1),
218
+ trim(both '"' from split_part(obj.object_identity, '.', 2));
219
+ -- Check if RLS is enabled on the table
220
+ SELECT INTO has_rls
221
+ rowsecurity
222
+ FROM pg_tables
223
+ WHERE schemaname = table_schema
224
+ AND tablename = table_name;
225
+ -- Only create policies if RLS is enabled
226
+ IF has_rls THEN
227
+ -- Create policies for each role
228
+ -- anon: read-only access
229
+ EXECUTE format('CREATE POLICY "anon_policy" ON %s FOR SELECT TO anon USING (true)', obj.object_identity);
230
+ -- authenticated: full access
231
+ EXECUTE format('CREATE POLICY "authenticated_policy" ON %s FOR ALL TO authenticated USING (true) WITH CHECK (true)', obj.object_identity);
232
+ -- project_admin: full access
233
+ EXECUTE format('CREATE POLICY "project_admin_policy" ON %s FOR ALL TO project_admin USING (true) WITH CHECK (true)', obj.object_identity);
234
+ END IF;
235
+ END LOOP;
236
+ END;
237
+ $$ LANGUAGE plpgsql;
238
+
239
+ -- Create event trigger to run the function when new tables are created
240
+ CREATE EVENT TRIGGER create_policies_on_table_create
241
+ ON ddl_command_end
242
+ WHEN TAG IN ('CREATE TABLE')
243
+ EXECUTE FUNCTION public.create_default_policies();
244
+
245
+ -- Create function to handle RLS enablement
246
+ CREATE OR REPLACE FUNCTION public.create_policies_after_rls()
247
+ RETURNS event_trigger AS $$
248
+ DECLARE
249
+ obj record;
250
+ table_schema text;
251
+ table_name text;
252
+ BEGIN
253
+ FOR obj IN SELECT * FROM pg_event_trigger_ddl_commands() WHERE command_tag = 'ALTER TABLE'
254
+ LOOP
255
+ -- Extract schema and table name
256
+ -- Handle quoted identifiers by removing quotes
257
+ SELECT INTO table_schema, table_name
258
+ split_part(obj.object_identity, '.', 1),
259
+ trim(both '"' from split_part(obj.object_identity, '.', 2));
260
+ -- Check if table has RLS enabled and no policies yet
261
+ IF EXISTS (
262
+ SELECT 1 FROM pg_tables
263
+ WHERE schemaname = table_schema
264
+ AND tablename = table_name
265
+ AND rowsecurity = true
266
+ ) AND NOT EXISTS (
267
+ SELECT 1 FROM pg_policies
268
+ WHERE schemaname = table_schema
269
+ AND tablename = table_name
270
+ ) THEN
271
+ -- Create default policies
272
+ EXECUTE format('CREATE POLICY "anon_policy" ON %s FOR SELECT TO anon USING (true)', obj.object_identity);
273
+ EXECUTE format('CREATE POLICY "authenticated_policy" ON %s FOR ALL TO authenticated USING (true) WITH CHECK (true)', obj.object_identity);
274
+ EXECUTE format('CREATE POLICY "project_admin_policy" ON %s FOR ALL TO project_admin USING (true) WITH CHECK (true)', obj.object_identity);
275
+ END IF;
276
+ END LOOP;
277
+ END;
278
+ $$ LANGUAGE plpgsql;
279
+
280
+ -- Create event trigger for ALTER TABLE commands
281
+ CREATE EVENT TRIGGER create_policies_on_rls_enable
282
+ ON ddl_command_end
283
+ WHEN TAG IN ('ALTER TABLE')
284
+ EXECUTE FUNCTION public.create_policies_after_rls();
285
+ - path: /docker-entrypoint-initdb.d/02-jwt.sql
286
+ template: |
287
+ \set jwt_secret `echo "$JWT_SECRET"`
288
+ \set jwt_exp `echo "$JWT_EXP"`
289
+
290
+ ALTER DATABASE insforge SET "app.settings.jwt_secret" TO :'jwt_secret';
291
+ ALTER DATABASE insforge SET "app.settings.jwt_exp" TO :'jwt_exp';
292
+ healthCheck:
293
+ type: TCP
294
+ port: database
295
+
296
+ - name: postgrest
297
+ icon: https://avatars.githubusercontent.com/u/15115011?s=96&v=4
298
+ dependencies:
299
+ - postgres
300
+ template: PREBUILT
301
+ spec:
302
+ source:
303
+ image: postgrest/postgrest:v12.2.12
304
+ ports:
305
+ - id: api
306
+ port: 3000
307
+ type: HTTP
308
+ env:
309
+ PGHOST:
310
+ default: postgres
311
+ PGPORT:
312
+ default: "5432"
313
+ PGDATABASE:
314
+ default: insforge
315
+ PGUSER:
316
+ default: postgres
317
+ PGPASSWORD:
318
+ default: ${POSTGRES_PASSWORD}
319
+ expose: true
320
+ PGRST_OPENAPI_SERVER_PROXY_URI:
321
+ default: http://localhost:3000
322
+ PGRST_DB_SCHEMA:
323
+ default: public
324
+ PGRST_DB_ANON_ROLE:
325
+ default: anon
326
+ PGRST_JWT_SECRET:
327
+ default: ${JWT_SECRET}
328
+ expose: true
329
+ readonly: true
330
+ PGRST_DB_CHANNEL_ENABLED:
331
+ default: "true"
332
+ PGRST_DB_CHANNEL:
333
+ default: pgrst
334
+ healthCheck:
335
+ type: HTTP
336
+ port: api
337
+ http:
338
+ path: /
339
+
340
+ - name: deno
341
+ icon: https://avatars.githubusercontent.com/u/42048915?s=96&v=4
342
+ dependencies:
343
+ - postgres
344
+ - postgrest
345
+ template: PREBUILT
346
+ spec:
347
+ source:
348
+ image: denoland/deno:alpine-2.0.6
349
+ command:
350
+ - sh
351
+ - -c
352
+ - |
353
+ cd /app &&
354
+ echo 'Downloading Deno dependencies...' &&
355
+ deno cache functions/server.ts &&
356
+ echo 'Starting Deno server on port 7133...' &&
357
+ deno run --allow-net --allow-env --allow-read=./functions/worker-template.js --watch functions/server.ts
358
+ ports:
359
+ - id: runtime
360
+ port: 7133
361
+ type: HTTP
362
+ volumes:
363
+ - id: cache
364
+ dir: /deno-dir
365
+ env:
366
+ PORT:
367
+ default: "7133"
368
+ DENO_ENV:
369
+ default: development
370
+ DENO_DIR:
371
+ default: /deno-dir
372
+ POSTGRES_HOST:
373
+ default: postgres
374
+ POSTGRES_PORT:
375
+ default: "5432"
376
+ POSTGRES_DB:
377
+ default: insforge
378
+ POSTGRES_USER:
379
+ default: postgres
380
+ POSTGRES_PASSWORD:
381
+ default: ${PGPASSWORD}
382
+ POSTGREST_BASE_URL:
383
+ default: http://postgrest:3000
384
+ WORKER_TIMEOUT_MS:
385
+ default: "30000"
386
+ ENCRYPTION_KEY:
387
+ default: ${PASSWORD}
388
+ JWT_SECRET:
389
+ default: ${PGRST_JWT_SECRET}
390
+ configs:
391
+ - path: /app/functions/server.ts
392
+ template: |
393
+ import { Client } from 'https://deno.land/x/postgres@v0.17.0/mod.ts';
394
+ import { join, dirname, fromFileUrl } from 'https://deno.land/std@0.224.0/path/mod.ts';
395
+
396
+ /* eslint-disable no-console */
397
+ const port = parseInt(Deno.env.get('PORT') ?? '7133');
398
+
399
+ console.log(`Deno serverless runtime running on port ${port}`);
400
+
401
+ // Configuration
402
+ const WORKER_TIMEOUT_MS = parseInt(Deno.env.get('WORKER_TIMEOUT_MS') ?? '30000');
403
+
404
+ // Worker template code - loaded on first use
405
+ let workerTemplateCode: string | null = null;
406
+
407
+ async function getWorkerTemplateCode(): Promise<string> {
408
+ if (!workerTemplateCode) {
409
+ const currentDir = dirname(fromFileUrl(import.meta.url));
410
+ workerTemplateCode = await Deno.readTextFile(join(currentDir, 'worker-template.js'));
411
+ }
412
+ return workerTemplateCode;
413
+ }
414
+
415
+ // Decrypt function for Deno (compatible with Node.js encryption)
416
+ async function decryptSecret(ciphertext: string, key: string): Promise<string> {
417
+ try {
418
+ const parts = ciphertext.split(':');
419
+ if (parts.length !== 3) {
420
+ throw new Error('Invalid ciphertext format');
421
+ }
422
+
423
+ // Get the encryption key by hashing the JWT secret
424
+ const keyData = new TextEncoder().encode(key);
425
+ const hashBuffer = await crypto.subtle.digest('SHA-256', keyData);
426
+ const cryptoKey = await crypto.subtle.importKey(
427
+ 'raw',
428
+ hashBuffer,
429
+ { name: 'AES-GCM' },
430
+ false,
431
+ ['decrypt']
432
+ );
433
+
434
+ // Extract IV, auth tag, and encrypted data
435
+ const iv = Uint8Array.from(parts[0].match(/.{2}/g)!.map(byte => parseInt(byte, 16)));
436
+ const authTag = Uint8Array.from(parts[1].match(/.{2}/g)!.map(byte => parseInt(byte, 16)));
437
+ const encrypted = Uint8Array.from(parts[2].match(/.{2}/g)!.map(byte => parseInt(byte, 16)));
438
+
439
+ // Combine encrypted data and auth tag (GCM expects them together)
440
+ const cipherData = new Uint8Array(encrypted.length + authTag.length);
441
+ cipherData.set(encrypted);
442
+ cipherData.set(authTag, encrypted.length);
443
+
444
+ // Decrypt
445
+ const decryptedBuffer = await crypto.subtle.decrypt(
446
+ { name: 'AES-GCM', iv },
447
+ cryptoKey,
448
+ cipherData
449
+ );
450
+
451
+ return new TextDecoder().decode(decryptedBuffer);
452
+ } catch (error) {
453
+ console.error('Failed to decrypt secret:', error);
454
+ throw error;
455
+ }
456
+ }
457
+
458
+ // Database connection
459
+ const dbConfig = {
460
+ user: Deno.env.get('POSTGRES_USER') || 'postgres',
461
+ password: Deno.env.get('POSTGRES_PASSWORD') || 'postgres',
462
+ database: Deno.env.get('POSTGRES_DB') || 'insforge',
463
+ hostname: Deno.env.get('POSTGRES_HOST') || 'postgres',
464
+ port: parseInt(Deno.env.get('POSTGRES_PORT') || '5432', 10),
465
+ };
466
+
467
+ // Get function code from database
468
+ async function getFunctionCode(slug: string): Promise<string | null> {
469
+ const client = new Client(dbConfig);
470
+
471
+ try {
472
+ await client.connect();
473
+
474
+ const result = await client.queryObject<{ code: string }>`
475
+ SELECT code FROM _functions
476
+ WHERE slug = ${slug} AND status = 'active'
477
+ `;
478
+
479
+ if (!result.rows.length) {
480
+ return null;
481
+ }
482
+
483
+ return result.rows[0].code;
484
+ } catch (error) {
485
+ console.error(`Error fetching function ${slug}:`, error);
486
+ return null;
487
+ } finally {
488
+ await client.end();
489
+ }
490
+ }
491
+
492
+ // Get all secrets from main secrets table and decrypt them
493
+ async function getFunctionSecrets(): Promise<Record<string, string>> {
494
+ const client = new Client(dbConfig);
495
+
496
+ try {
497
+ await client.connect();
498
+
499
+ // Get the encryption key from environment
500
+ const encryptionKey = Deno.env.get('ENCRYPTION_KEY') || Deno.env.get('JWT_SECRET');
501
+ if (!encryptionKey) {
502
+ console.error('No encryption key available for decrypting secrets');
503
+ return {};
504
+ }
505
+
506
+ // Fetch all active secrets from _secrets table
507
+ const result = await client.queryObject<{
508
+ key: string;
509
+ value_ciphertext: string;
510
+ }>`
511
+ SELECT key, value_ciphertext
512
+ FROM _secrets
513
+ WHERE is_active = true
514
+ AND (expires_at IS NULL OR expires_at > NOW())
515
+ `;
516
+
517
+ const secrets: Record<string, string> = {};
518
+
519
+ // Decrypt each secret
520
+ for (const row of result.rows) {
521
+ try {
522
+ secrets[row.key] = await decryptSecret(row.value_ciphertext, encryptionKey);
523
+ } catch (error) {
524
+ console.error(`Failed to decrypt secret ${row.key}:`, error);
525
+ // Skip this secret if decryption fails
526
+ }
527
+ }
528
+
529
+ return secrets;
530
+ } catch (error) {
531
+ console.error('Error fetching secrets:', error);
532
+ return {};
533
+ } finally {
534
+ await client.end();
535
+ }
536
+ }
537
+
538
+ // Execute function in isolated worker
539
+ async function executeInWorker(code: string, request: Request): Promise<Response> {
540
+ // Get worker template
541
+ const template = await getWorkerTemplateCode();
542
+
543
+ // Fetch all function secrets
544
+ const secrets = await getFunctionSecrets();
545
+
546
+ // Create blob for worker
547
+ const workerBlob = new Blob([template], { type: 'application/javascript' });
548
+ const workerUrl = URL.createObjectURL(workerBlob);
549
+
550
+ return new Promise(async (resolve) => {
551
+ const worker = new Worker(workerUrl, { type: 'module' });
552
+
553
+ // Set timeout for worker execution
554
+ const timeout = setTimeout(() => {
555
+ worker.terminate();
556
+ URL.revokeObjectURL(workerUrl);
557
+ resolve(
558
+ new Response(JSON.stringify({ error: 'Function timeout' }), {
559
+ status: 504,
560
+ headers: { 'Content-Type': 'application/json' },
561
+ })
562
+ );
563
+ }, WORKER_TIMEOUT_MS);
564
+
565
+ // Handle worker response
566
+ worker.onmessage = (e) => {
567
+ clearTimeout(timeout);
568
+ worker.terminate();
569
+ URL.revokeObjectURL(workerUrl);
570
+
571
+ if (e.data.success) {
572
+ const { response } = e.data;
573
+ // The worker now properly sends null for bodyless responses
574
+ resolve(
575
+ new Response(response.body, {
576
+ status: response.status,
577
+ statusText: response.statusText,
578
+ headers: response.headers,
579
+ })
580
+ );
581
+ } else {
582
+ resolve(
583
+ new Response(JSON.stringify({ error: e.data.error }), {
584
+ status: e.data.status || 500,
585
+ headers: { 'Content-Type': 'application/json' },
586
+ })
587
+ );
588
+ }
589
+ };
590
+
591
+ // Handle worker errors
592
+ worker.onerror = (error) => {
593
+ clearTimeout(timeout);
594
+ worker.terminate();
595
+ URL.revokeObjectURL(workerUrl);
596
+ console.error('Worker error:', error);
597
+ resolve(
598
+ new Response(JSON.stringify({ error: 'Worker execution error' }), {
599
+ status: 500,
600
+ headers: { 'Content-Type': 'application/json' },
601
+ })
602
+ );
603
+ };
604
+
605
+ // Prepare request data
606
+ const body = request.body ? await request.text() : null;
607
+ const requestData = {
608
+ url: request.url,
609
+ method: request.method,
610
+ headers: Object.fromEntries(request.headers),
611
+ body,
612
+ };
613
+
614
+ // Send message with code, request data, and secrets
615
+ worker.postMessage({ code, requestData, secrets });
616
+ });
617
+ }
618
+
619
+ Deno.serve({ port }, async (req: Request) => {
620
+ const url = new URL(req.url);
621
+ const pathname = url.pathname;
622
+
623
+ // Health check
624
+ if (pathname === '/health') {
625
+ return new Response(
626
+ JSON.stringify({
627
+ status: 'ok',
628
+ runtime: 'deno',
629
+ version: Deno.version.deno,
630
+ typescript: Deno.version.typescript,
631
+ v8: Deno.version.v8,
632
+ }),
633
+ {
634
+ headers: { 'Content-Type': 'application/json' },
635
+ }
636
+ );
637
+ }
638
+
639
+ // Function execution - match ONLY exact slug, no subpaths
640
+ const slugMatch = pathname.match(/^\/([a-zA-Z0-9_-]+)$/);
641
+ if (slugMatch) {
642
+ const slug = slugMatch[1];
643
+ const startTime = Date.now();
644
+
645
+ // Get function code from database
646
+ const code = await getFunctionCode(slug);
647
+
648
+ if (!code) {
649
+ return new Response(JSON.stringify({ error: 'Function not found or not active' }), {
650
+ status: 404,
651
+ headers: { 'Content-Type': 'application/json' },
652
+ });
653
+ }
654
+
655
+ // Execute in worker with original request
656
+ try {
657
+ const response = await executeInWorker(code, req);
658
+ const duration = Date.now() - startTime;
659
+
660
+ // Log completed invocations only
661
+ console.log(
662
+ JSON.stringify({
663
+ timestamp: new Date().toISOString(),
664
+ level: 'info',
665
+ slug,
666
+ method: req.method,
667
+ status: response.status,
668
+ duration: `${duration}ms`,
669
+ })
670
+ );
671
+
672
+ return response;
673
+ } catch (error) {
674
+ const duration = Date.now() - startTime;
675
+ console.error(
676
+ JSON.stringify({
677
+ timestamp: new Date().toISOString(),
678
+ level: 'error',
679
+ slug,
680
+ error: error instanceof Error ? error.message : String(error),
681
+ duration: `${duration}ms`,
682
+ })
683
+ );
684
+ return new Response(JSON.stringify({ error: 'Function execution failed' }), {
685
+ status: 500,
686
+ headers: { 'Content-Type': 'application/json' },
687
+ });
688
+ }
689
+ }
690
+
691
+ // Runtime info
692
+ if (pathname === '/info') {
693
+ return new Response(
694
+ JSON.stringify({
695
+ runtime: 'deno',
696
+ version: Deno.version,
697
+ env: Deno.env.get('DENO_ENV') || 'production',
698
+ database: {
699
+ host: dbConfig.hostname,
700
+ database: dbConfig.database,
701
+ },
702
+ }),
703
+ {
704
+ headers: { 'Content-Type': 'application/json' },
705
+ }
706
+ );
707
+ }
708
+
709
+ // 404
710
+ return new Response('Not Found', { status: 404 });
711
+ });
712
+ - path: /app/functions/deno.json
713
+ template: |
714
+ {
715
+ "compilerOptions": {
716
+ "lib": ["deno.window", "deno.worker"],
717
+ "strict": true
718
+ },
719
+ "lint": {
720
+ "files": {
721
+ "include": ["./**/*.ts", "./**/*.js"]
722
+ },
723
+ "rules": {
724
+ "tags": ["recommended"]
725
+ }
726
+ },
727
+ "fmt": {
728
+ "files": {
729
+ "include": ["./**/*.ts", "./**/*.js"]
730
+ },
731
+ "options": {
732
+ "useTabs": false,
733
+ "lineWidth": 100,
734
+ "indentWidth": 2,
735
+ "singleQuote": true
736
+ }
737
+ }
738
+ }
739
+ - path: /app/functions/worker-template.js
740
+ template: |
741
+ /**
742
+ * Worker Template for Serverless Functions
743
+ *
744
+ * This code runs inside a Web Worker environment created by Deno.
745
+ * Each worker is created fresh for a single request, executes once, and terminates.
746
+ */
747
+ /* eslint-env worker */
748
+ /* global self, Request, Deno */
749
+
750
+ // Import SDK at worker level - this will be available to all functions
751
+ import { createClient } from 'npm:@insforge/sdk';
752
+ // Import base64 utilities for encoding/decoding
753
+ import { encodeBase64, decodeBase64 } from 'https://deno.land/std@0.224.0/encoding/base64.ts';
754
+
755
+ // Handle the single message with code, request data, and secrets
756
+ self.onmessage = async (e) => {
757
+ const { code, requestData, secrets = {} } = e.data;
758
+
759
+ try {
760
+ /**
761
+ * MOCK DENO OBJECT EXPLANATION:
762
+ *
763
+ * Why we need a mock Deno object:
764
+ * - Edge functions run in isolated Web Workers (sandboxed environments)
765
+ * - Web Workers don't have access to the real Deno global object for security
766
+ * - We need to provide Deno.env functionality so functions can access secrets
767
+ *
768
+ * How it works:
769
+ * 1. The main server (server.ts) fetches all active secrets from the _secrets table
770
+ * 2. Only active (is_active=true) and non-expired secrets are included
771
+ * 3. Secrets are decrypted and passed to this worker via the 'secrets' object
772
+ * 4. We create a mock Deno object that provides Deno.env.get()
773
+ * 5. When user code calls Deno.env.get('MY_SECRET'), it reads from our secrets object
774
+ *
775
+ * This allows edge functions to use familiar Deno.env syntax while maintaining security
776
+ * Secrets are managed via the /api/secrets endpoint
777
+ */
778
+ const mockDeno = {
779
+ // Mock the Deno.env API - only get() is needed for reading secrets
780
+ env: {
781
+ get: (key) => secrets[key] || undefined,
782
+ },
783
+ };
784
+
785
+ /**
786
+ * FUNCTION WRAPPING EXPLANATION:
787
+ *
788
+ * Here we create a wrapper function that will execute the user's code.
789
+ * The user's function expects to have access to:
790
+ * - module.exports (to export their function)
791
+ * - createClient (the Insforge SDK)
792
+ * - Deno (for Deno.env.get() etc.)
793
+ * - encodeBase64, decodeBase64 (base64 encoding utilities)
794
+ *
795
+ * We inject our mockDeno as the 'Deno' parameter, so when the user's code
796
+ * calls Deno.env.get('MY_SECRET'), it's actually calling mockDeno.env.get('MY_SECRET')
797
+ */
798
+ const wrapper = new Function(
799
+ 'exports',
800
+ 'module',
801
+ 'createClient',
802
+ 'Deno',
803
+ 'encodeBase64',
804
+ 'decodeBase64',
805
+ code
806
+ );
807
+ const exports = {};
808
+ const module = { exports };
809
+
810
+ // Execute the wrapper, passing mockDeno as the Deno global and utility functions
811
+ // This makes Deno.env.get(), encodeBase64(), and decodeBase64() available inside the user's function
812
+ wrapper(exports, module, createClient, mockDeno, encodeBase64, decodeBase64);
813
+
814
+ // Get the exported function
815
+ const functionHandler = module.exports || exports.default || exports;
816
+
817
+ if (typeof functionHandler !== 'function') {
818
+ throw new Error(
819
+ 'No function exported. Expected: module.exports = async function(req) { ... }'
820
+ );
821
+ }
822
+
823
+ // Create Request object from data
824
+ const request = new Request(requestData.url, {
825
+ method: requestData.method,
826
+ headers: requestData.headers,
827
+ body: requestData.body,
828
+ });
829
+
830
+ // Execute the function
831
+ const response = await functionHandler(request);
832
+
833
+ // Serialize and send response
834
+ // Properly handle responses with no body
835
+ let body = null;
836
+
837
+ // Only read body if response has content
838
+ // Status codes 204, 205, and 304 should not have a body
839
+ if (![204, 205, 304].includes(response.status)) {
840
+ body = await response.text();
841
+ }
842
+
843
+ const responseData = {
844
+ status: response.status,
845
+ statusText: response.statusText,
846
+ headers: Object.fromEntries(response.headers),
847
+ body: body,
848
+ };
849
+
850
+ self.postMessage({ success: true, response: responseData });
851
+ } catch (error) {
852
+ // Check if the error is actually a Response object (thrown by the function)
853
+ if (error instanceof Response) {
854
+ // Handle error responses the same way
855
+ let body = null;
856
+
857
+ if (![204, 205, 304].includes(error.status)) {
858
+ body = await error.text();
859
+ }
860
+
861
+ const responseData = {
862
+ status: error.status,
863
+ statusText: error.statusText,
864
+ headers: Object.fromEntries(error.headers),
865
+ body: body,
866
+ };
867
+ self.postMessage({ success: true, response: responseData });
868
+ } else {
869
+ // For actual errors, include status if available
870
+ self.postMessage({
871
+ success: false,
872
+ error: error.message || 'Unknown error',
873
+ status: error.status || 500,
874
+ });
875
+ }
876
+ }
877
+ };
878
+ healthCheck:
879
+ type: HTTP
880
+ port: runtime
881
+ http:
882
+ path: /health
883
+
884
+ - name: insforge
885
+ icon: https://avatars.githubusercontent.com/u/198419463?s=96&v=4
886
+ dependencies:
887
+ - postgres
888
+ - postgrest
889
+ - deno
890
+ template: PREBUILT
891
+ spec:
892
+ source:
893
+ image: ghcr.io/insforge/insforge-oss:v1.2.6
894
+ ports:
895
+ - id: web
896
+ port: 7130
897
+ type: HTTP
898
+ - id: dev
899
+ port: 7131
900
+ type: HTTP
901
+ env:
902
+ PORT:
903
+ default: "7130"
904
+ PROJECT_ROOT:
905
+ default: /app
906
+ API_BASE_URL:
907
+ default: ${ZEABUR_WEB_URL}
908
+ VITE_API_BASE_URL:
909
+ default: ${ZEABUR_WEB_URL}
910
+ JWT_SECRET:
911
+ default: ${PGRST_JWT_SECRET}
912
+ ADMIN_EMAIL:
913
+ default: ${ADMIN_EMAIL}
914
+ ADMIN_PASSWORD:
915
+ default: ${ADMIN_PASSWORD}
916
+ # PostgreSQL connection
917
+ POSTGRES_HOST:
918
+ default: postgres
919
+ POSTGRES_PORT:
920
+ default: "5432"
921
+ POSTGRES_DB:
922
+ default: insforge
923
+ POSTGRES_USER:
924
+ default: postgres
925
+ POSTGRESDB_PASSWORD:
926
+ default: ${PGPASSWORD}
927
+ DATABASE_URL:
928
+ default: postgres://postgres:${PGPASSWORD}@postgres:5432/insforge
929
+ POSTGREST_BASE_URL:
930
+ default: http://postgrest:3000
931
+ # Deno Runtime URL for serverless functions
932
+ DENO_RUNTIME_URL:
933
+ default: http://deno:7133
934
+ # OAuth Configuration (optional)
935
+ GOOGLE_CLIENT_ID:
936
+ default: ""
937
+ GOOGLE_CLIENT_SECRET:
938
+ default: ""
939
+ GOOGLE_REDIRECT_URI:
940
+ default: ${ZEABUR_WEB_URL}/api/auth/v1/callback
941
+ GITHUB_CLIENT_ID:
942
+ default: ""
943
+ GITHUB_CLIENT_SECRET:
944
+ default: ""
945
+ GITHUB_REDIRECT_URI:
946
+ default: ${ZEABUR_WEB_URL}/api/auth/v1/callback
947
+ # Multi-tenant Cloud Configuration
948
+ DEPLOYMENT_ID:
949
+ default: ${ZEABUR_SERVICE_ID}
950
+ PROJECT_ID:
951
+ default: ${ZEABUR_PROJECT_ID}
952
+ APP_KEY:
953
+ default: ""
954
+ ACCESS_API_KEY:
955
+ default: ""
956
+ OPENROUTER_API_KEY:
957
+ default: ${OPENROUTER_API_KEY}
958
+ healthCheck:
959
+ type: HTTP
960
+ port: web
961
+ http:
962
+ path: /
963
+ domainKey: PUBLIC_DOMAIN
964
+
965
+ localization:
966
+ zh-CN:
967
+ description: InsForge 是 Agent-Native 的 Supabase 替代方案,让 AI 智能体能够自主构建和管理全栈应用程序。
968
+ readme: |
969
+ # InsForge
970
+
971
+ InsForge 是 Agent-Native 的 Supabase 替代方案,让 AI 智能体能够自主构建和管理全栈应用程序。
972
+
973
+ ## 功能特性
974
+
975
+ - **身份验证系统** - 用户管理和安全认证
976
+ - **数据库存储** - 灵活的 PostgreSQL 数据库,支持自动模式管理
977
+ - **文件管理** - 安全的文件上传和存储功能
978
+ - **PostgREST API** - 从数据库模式自动生成 REST API
979
+ - **无服务器函数** - 用于自定义业务逻辑的边缘函数
980
+ - **AI 智能体集成** - 连接 Claude 或 GPT 等 AI 智能体来管理后端
981
+
982
+ ## 快速开始
983
+
984
+ 此模板提供 InsForge 平台的**一键部署**:
985
+
986
+ 1. **部署** - 点击部署并绑定域名
987
+ 2. **登录** - 使用管理员凭据访问控制台
988
+ 3. **连接 AI 智能体** - 通过控制台连接您的 AI 智能体(Claude、GPT 等)
989
+ 4. **构建应用** - 使用自然语言提示创建应用程序:
990
+ - "构建一个带用户认证的待办事项应用"
991
+ - "创建一个带图片上传的 Instagram 克隆"
992
+ - "构建一个带评论和点赞的博客"
993
+
994
+ ## 使用场景
995
+
996
+ - **AI 生成的前端** - 为 AI 生成的前端项目快速创建后端
997
+ - **智能体驱动开发** - 让 AI 智能体管理您的整个后端基础设施
998
+ - **快速原型设计** - 使用自然语言构建全栈应用程序
999
+
1000
+ zh-TW:
1001
+ description: InsForge 是 Agent-Native 的 Supabase 替代方案,讓 AI 智慧體能夠自主建構和管理全端應用程式。
1002
+ readme: |
1003
+ # InsForge
1004
+
1005
+ InsForge 是 Agent-Native 的 Supabase 替代方案,讓 AI 智慧體能夠自主建構和管理全端應用程式。
1006
+
1007
+ ## 功能特色
1008
+
1009
+ - **身份驗證系統** - 使用者管理和安全認證
1010
+ - **資料庫儲存** - 靈活的 PostgreSQL 資料庫,支援自動模式管理
1011
+ - **檔案管理** - 安全的檔案上傳和儲存功能
1012
+ - **PostgREST API** - 從資料庫模式自動產生 REST API
1013
+ - **無伺服器函數** - 用於自訂業務邏輯的邊緣函數
1014
+ - **AI 智慧體整合** - 連接 Claude 或 GPT 等 AI 智慧體來管理後端
1015
+
1016
+ ## 快速開始
1017
+
1018
+ 此模版提供 InsForge 平台的**一鍵部署**:
1019
+
1020
+ 1. **部署** - 點擊部署並綁定網域
1021
+ 2. **登入** - 使用管理員憑證存取控制台
1022
+ 3. **連接 AI 智慧體** - 透過控制台連接您的 AI 智慧體(Claude、GPT 等)
1023
+ 4. **建構應用** - 使用自然語言提示建立應用程式:
1024
+ - "建構一個帶使用者認證的待辦事項應用"
1025
+ - "建立一個帶圖片上傳的 Instagram 複製品"
1026
+ - "建構一個帶評論和按讚的部落格"
1027
+
1028
+ ## 使用情境
1029
+
1030
+ - **AI 產生的前端** - 為 AI 產生的前端專案快速建立後端
1031
+ - **智慧體驅動開發** - 讓 AI 智慧體管理您的整個後端基礎設施
1032
+ - **快速原型設計** - 使用自然語言建構全端應用程式