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
@@ -1,12 +1,13 @@
1
1
  import { Router, Response, NextFunction } from 'express';
2
- import { SecretsService } from '@/core/secrets/secrets.js';
3
- import { verifyAdmin, AuthRequest } from '@/api/middleware/auth.js';
4
- import { AuditService } from '@/core/logs/audit.js';
5
- import { AppError } from '@/api/middleware/error.js';
2
+ import { SecretService } from '@/services/secrets/secret.service.js';
3
+ import { verifyAdmin, AuthRequest } from '@/api/middlewares/auth.js';
4
+ import { AuditService } from '@/services/logs/audit.service.js';
5
+ import { AppError } from '@/api/middlewares/error.js';
6
6
  import { ERROR_CODES } from '@/types/error-constants.js';
7
+ import { successResponse } from '@/utils/response.js';
7
8
 
8
9
  const router = Router();
9
- const secretsService = new SecretsService();
10
+ const secretService = SecretService.getInstance();
10
11
  const auditService = AuditService.getInstance();
11
12
 
12
13
  /**
@@ -15,8 +16,8 @@ const auditService = AuditService.getInstance();
15
16
  */
16
17
  router.get('/', verifyAdmin, async (_req: AuthRequest, res: Response, next: NextFunction) => {
17
18
  try {
18
- const secrets = await secretsService.listSecrets();
19
- res.json({ secrets });
19
+ const secrets = await secretService.listSecrets();
20
+ successResponse(res, { secrets });
20
21
  } catch (error) {
21
22
  next(error);
22
23
  }
@@ -29,7 +30,7 @@ router.get('/', verifyAdmin, async (_req: AuthRequest, res: Response, next: Next
29
30
  router.get('/:key', verifyAdmin, async (req: AuthRequest, res: Response, next: NextFunction) => {
30
31
  try {
31
32
  const { key } = req.params;
32
- const value = await secretsService.getSecretByKey(key);
33
+ const value = await secretService.getSecretByKey(key);
33
34
 
34
35
  if (value === null) {
35
36
  throw new AppError(`Secret not found: ${key}`, 404, ERROR_CODES.NOT_FOUND);
@@ -44,7 +45,7 @@ router.get('/:key', verifyAdmin, async (req: AuthRequest, res: Response, next: N
44
45
  ip_address: req.ip,
45
46
  });
46
47
 
47
- res.json({ key, value });
48
+ successResponse(res, { key, value });
48
49
  } catch (error) {
49
50
  next(error);
50
51
  }
@@ -73,12 +74,12 @@ router.post('/', verifyAdmin, async (req: AuthRequest, res: Response, next: Next
73
74
  }
74
75
 
75
76
  // Check if secret already exists
76
- const existing = await secretsService.getSecretByKey(key);
77
+ const existing = await secretService.getSecretByKey(key);
77
78
  if (existing !== null) {
78
79
  throw new AppError(`Secret already exists: ${key}`, 409, ERROR_CODES.INVALID_INPUT);
79
80
  }
80
81
 
81
- const result = await secretsService.createSecret({
82
+ const result = await secretService.createSecret({
82
83
  key,
83
84
  value,
84
85
  isReserved: isReserved || false,
@@ -94,11 +95,15 @@ router.post('/', verifyAdmin, async (req: AuthRequest, res: Response, next: Next
94
95
  ip_address: req.ip,
95
96
  });
96
97
 
97
- res.status(201).json({
98
- success: true,
99
- message: `Secret ${key} has been created successfully`,
100
- id: result.id,
101
- });
98
+ successResponse(
99
+ res,
100
+ {
101
+ success: true,
102
+ message: `Secret ${key} has been created successfully`,
103
+ id: result.id,
104
+ },
105
+ 201
106
+ );
102
107
  } catch (error) {
103
108
  next(error);
104
109
  }
@@ -114,14 +119,14 @@ router.put('/:key', verifyAdmin, async (req: AuthRequest, res: Response, next: N
114
119
  const { value, isActive, isReserved, expiresAt } = req.body;
115
120
 
116
121
  // Get existing secret
117
- const secrets = await secretsService.listSecrets();
122
+ const secrets = await secretService.listSecrets();
118
123
  const secret = secrets.find((s) => s.key === key);
119
124
 
120
125
  if (!secret) {
121
126
  throw new AppError(`Secret not found: ${key}`, 404, ERROR_CODES.NOT_FOUND);
122
127
  }
123
128
 
124
- const success = await secretsService.updateSecret(secret.id, {
129
+ const success = await secretService.updateSecret(secret.id, {
125
130
  value,
126
131
  isActive,
127
132
  isReserved,
@@ -141,7 +146,7 @@ router.put('/:key', verifyAdmin, async (req: AuthRequest, res: Response, next: N
141
146
  ip_address: req.ip,
142
147
  });
143
148
 
144
- res.json({
149
+ successResponse(res, {
145
150
  success: true,
146
151
  message: `Secret ${key} has been updated successfully`,
147
152
  });
@@ -159,7 +164,7 @@ router.delete('/:key', verifyAdmin, async (req: AuthRequest, res: Response, next
159
164
  const { key } = req.params;
160
165
 
161
166
  // Get existing secret
162
- const secrets = await secretsService.listSecrets();
167
+ const secrets = await secretService.listSecrets();
163
168
  const secret = secrets.find((s) => s.key === key);
164
169
 
165
170
  if (!secret) {
@@ -172,7 +177,7 @@ router.delete('/:key', verifyAdmin, async (req: AuthRequest, res: Response, next
172
177
  }
173
178
 
174
179
  // Mark as inactive instead of hard delete
175
- const success = await secretsService.updateSecret(secret.id, { isActive: false });
180
+ const success = await secretService.updateSecret(secret.id, { isActive: false });
176
181
 
177
182
  if (!success) {
178
183
  throw new AppError(`Failed to delete secret: ${key}`, 500, ERROR_CODES.INTERNAL_ERROR);
@@ -187,7 +192,7 @@ router.delete('/:key', verifyAdmin, async (req: AuthRequest, res: Response, next
187
192
  ip_address: req.ip,
188
193
  });
189
194
 
190
- res.json({
195
+ successResponse(res, {
191
196
  success: true,
192
197
  message: `Secret ${key} has been deleted successfully`,
193
198
  });
@@ -1,20 +1,14 @@
1
1
  import { Router, Request, Response, NextFunction } from 'express';
2
- import path from 'path';
3
- import { verifyAdmin, AuthRequest, verifyUser } from '@/api/middleware/auth.js';
4
- import { AppError } from '@/api/middleware/error.js';
5
- import { StorageService } from '@/core/storage/storage.js';
6
- import { DatabaseManager } from '@/core/database/manager.js';
2
+ import { verifyAdmin, AuthRequest, verifyUser } from '@/api/middlewares/auth.js';
3
+ import { AppError } from '@/api/middlewares/error.js';
4
+ import { StorageService } from '@/services/storage/storage.service.js';
7
5
  import { successResponse } from '@/utils/response.js';
8
- import { upload, handleUploadError } from '@/api/middleware/upload.js';
6
+ import { upload, handleUploadError } from '@/api/middlewares/upload.js';
9
7
  import { ERROR_CODES } from '@/types/error-constants.js';
10
- import {
11
- StorageBucketSchema,
12
- createBucketRequestSchema,
13
- updateBucketRequestSchema,
14
- } from '@insforge/shared-schemas';
15
- import { SocketService } from '@/core/socket/socket';
16
- import { DataUpdateResourceType, ServerEvents } from '@/core/socket/types';
17
- import { AuditService } from '@/core/logs/audit.js';
8
+ import { createBucketRequestSchema, updateBucketRequestSchema } from '@insforge/shared-schemas';
9
+ import { SocketManager } from '@/infra/socket/socket.manager.js';
10
+ import { DataUpdateResourceType, ServerEvents } from '@/types/socket.js';
11
+ import { AuditService } from '@/services/logs/audit.service.js';
18
12
 
19
13
  const router = Router();
20
14
  const auditService = AuditService.getInstance();
@@ -40,24 +34,19 @@ const conditionalAuth = async (req: Request, res: Response, next: NextFunction)
40
34
  return verifyUser(req, res, next);
41
35
  };
42
36
 
43
- // GET /api/storage/buckets - List all buckets (requires auth)
37
+ // GET /api/storage/buckets - List all buckets (requires admin)
44
38
  router.get('/buckets', verifyAdmin, async (req: AuthRequest, res: Response, next: NextFunction) => {
45
39
  try {
46
- const db = DatabaseManager.getInstance().getDb();
40
+ const storageService = StorageService.getInstance();
41
+ const buckets = await storageService.listBuckets();
47
42
 
48
- // Get all buckets with their metadata from _storage_buckets table
49
- const buckets = (await db
50
- .prepare('SELECT name, public, created_at FROM _storage_buckets ORDER BY name')
51
- .all()) as StorageBucketSchema[];
52
-
53
- // Traditional REST: return array directly
54
43
  successResponse(res, buckets);
55
44
  } catch (error) {
56
45
  next(error);
57
46
  }
58
47
  });
59
48
 
60
- // POST /api/storage/buckets - Create a new bucket (requires auth)
49
+ // POST /api/storage/buckets - Create a new bucket (requires admin)
61
50
  router.post(
62
51
  '/buckets',
63
52
  verifyAdmin,
@@ -89,9 +78,9 @@ router.post(
89
78
  ip_address: req.ip,
90
79
  });
91
80
 
92
- const socket = SocketService.getInstance();
81
+ const socket = SocketManager.getInstance();
93
82
  socket.broadcastToRoom('role:project_admin', ServerEvents.DATA_UPDATE, {
94
- resource: DataUpdateResourceType.STORAGE_SCHEMA,
83
+ resource: DataUpdateResourceType.BUCKETS,
95
84
  });
96
85
 
97
86
  const accessInfo = isPublic
@@ -160,11 +149,11 @@ router.patch(
160
149
  ip_address: req.ip,
161
150
  });
162
151
 
163
- const socket = SocketService.getInstance();
152
+ const socket = SocketManager.getInstance();
164
153
  socket.broadcastToRoom('role:project_admin', ServerEvents.DATA_UPDATE, {
165
- resource: DataUpdateResourceType.BUCKET_SCHEMA,
154
+ resource: DataUpdateResourceType.BUCKETS,
166
155
  data: {
167
- name: bucketName,
156
+ bucketName,
168
157
  },
169
158
  });
170
159
 
@@ -287,17 +276,11 @@ router.post(
287
276
  throw new AppError('File is required', 400, ERROR_CODES.STORAGE_INVALID_PARAMETER);
288
277
  }
289
278
 
290
- // Generate a unique key for the object
291
- const timestamp = Date.now();
292
- const randomStr = Math.random().toString(36).substring(2, 8);
293
- const fileExt = req.file.originalname ? path.extname(req.file.originalname) : '';
294
- const baseName = req.file.originalname
295
- ? path.basename(req.file.originalname, fileExt)
296
- : 'file';
297
- const sanitizedBaseName = baseName.replace(/[^a-zA-Z0-9-_]/g, '-').substring(0, 32);
298
- const objectKey = `${sanitizedBaseName}-${timestamp}-${randomStr}${fileExt}`;
299
-
300
279
  const storageService = StorageService.getInstance();
280
+
281
+ // Generate a unique key for the object using service
282
+ const objectKey = storageService.generateObjectKey(req.file.originalname);
283
+
301
284
  const storedFile = await storageService.putObject(
302
285
  bucketName,
303
286
  objectKey,
@@ -339,12 +322,10 @@ router.get(
339
322
  }
340
323
 
341
324
  const storageService = StorageService.getInstance();
342
- const expiresIn = (await storageService.isBucketPublic(bucketName)) ? 0 : 3600;
343
- const strategy = await storageService.getDownloadStrategy(
344
- bucketName,
345
- objectKey,
346
- Number(expiresIn)
347
- );
325
+
326
+ // Get download strategy (service auto-calculates expiry based on bucket visibility)
327
+ const strategy = await storageService.getDownloadStrategy(bucketName, objectKey);
328
+
348
329
  if (strategy.method === 'presigned') {
349
330
  return res.redirect(strategy.url);
350
331
  }
@@ -397,9 +378,9 @@ router.delete(
397
378
  ip_address: req.ip,
398
379
  });
399
380
 
400
- const socket = SocketService.getInstance();
381
+ const socket = SocketManager.getInstance();
401
382
  socket.broadcastToRoom('role:project_admin', ServerEvents.DATA_UPDATE, {
402
- resource: DataUpdateResourceType.STORAGE_SCHEMA,
383
+ resource: DataUpdateResourceType.BUCKETS,
403
384
  });
404
385
 
405
386
  successResponse(
@@ -432,7 +413,12 @@ router.delete(
432
413
 
433
414
  // Delete specific object
434
415
  const storageService = StorageService.getInstance();
435
- const deleted = await storageService.deleteObject(bucketName, objectKey, req.user?.id);
416
+ const deleted = await storageService.deleteObject(
417
+ bucketName,
418
+ objectKey,
419
+ req.user?.id,
420
+ req.user?.role === 'project_admin'
421
+ );
436
422
 
437
423
  if (!deleted) {
438
424
  throw new AppError('Object not found', 404, ERROR_CODES.NOT_FOUND);
@@ -525,14 +511,9 @@ router.post(
525
511
  async (req: AuthRequest | Request, res: Response, next: NextFunction) => {
526
512
  try {
527
513
  const { bucketName, objectKey } = req.params;
528
- const { expiresIn = 3600 } = req.body;
529
514
 
530
515
  const storageService = StorageService.getInstance();
531
- const strategy = await storageService.getDownloadStrategy(
532
- bucketName,
533
- objectKey,
534
- Number(expiresIn)
535
- );
516
+ const strategy = await storageService.getDownloadStrategy(bucketName, objectKey);
536
517
 
537
518
  successResponse(res, strategy);
538
519
  } catch (error) {
@@ -0,0 +1,89 @@
1
+ import { Router, NextFunction, Response } from 'express';
2
+ import {
3
+ verifyCloudBackend,
4
+ verifyApiKey,
5
+ verifyAdmin,
6
+ AuthRequest,
7
+ } from '@/api/middlewares/auth.js';
8
+ import { SocketManager } from '@/infra/socket/socket.manager.js';
9
+ import { ServerEvents } from '@/types/socket.js';
10
+ import { UsageService } from '@/services/usage/usage.service.js';
11
+ import { successResponse } from '@/utils/response.js';
12
+ import { AppError } from '@/api/middlewares/error.js';
13
+ import { ERROR_CODES } from '@/types/error-constants.js';
14
+
15
+ export const usageRouter = Router();
16
+ const usageService = UsageService.getInstance();
17
+
18
+ // Create MCP tool usage record
19
+ usageRouter.post(
20
+ '/mcp',
21
+ verifyApiKey,
22
+ async (req: AuthRequest, res: Response, next: NextFunction) => {
23
+ try {
24
+ const { tool_name, success = true } = req.body;
25
+
26
+ if (!tool_name) {
27
+ throw new AppError('tool_name is required', 400, ERROR_CODES.INVALID_INPUT);
28
+ }
29
+
30
+ // Create MCP usage record via service
31
+ const result = await usageService.recordMCPUsage(tool_name, success);
32
+
33
+ // Broadcast MCP tool usage to frontend via socket
34
+ const socketService = SocketManager.getInstance();
35
+
36
+ socketService.broadcastToRoom('role:project_admin', ServerEvents.MCP_CONNECTED, {
37
+ tool_name,
38
+ created_at: result.created_at,
39
+ });
40
+
41
+ successResponse(res, { success: true });
42
+ } catch (error) {
43
+ next(error);
44
+ }
45
+ }
46
+ );
47
+
48
+ // Get MCP usage records
49
+ usageRouter.get(
50
+ '/mcp',
51
+ verifyAdmin,
52
+ async (req: AuthRequest, res: Response, next: NextFunction) => {
53
+ try {
54
+ const { limit = '5', success = 'true' } = req.query;
55
+
56
+ // Get MCP usage records via service
57
+ const records = await usageService.getMCPUsage(parseInt(limit as string), success === 'true');
58
+
59
+ successResponse(res, { records });
60
+ } catch (error) {
61
+ next(error);
62
+ }
63
+ }
64
+ );
65
+
66
+ // Get usage statistics (called by cloud backend)
67
+ usageRouter.get(
68
+ '/stats',
69
+ verifyCloudBackend,
70
+ async (req: AuthRequest, res: Response, next: NextFunction) => {
71
+ try {
72
+ const { start_date, end_date } = req.query;
73
+
74
+ if (!start_date || !end_date) {
75
+ throw new AppError('start_date and end_date are required', 400, ERROR_CODES.INVALID_INPUT);
76
+ }
77
+
78
+ // Get usage statistics via service
79
+ const stats = await usageService.getUsageStats(
80
+ new Date(start_date as string),
81
+ new Date(end_date as string)
82
+ );
83
+
84
+ successResponse(res, stats);
85
+ } catch (error) {
86
+ next(error);
87
+ }
88
+ }
89
+ );
@@ -0,0 +1,51 @@
1
+ export interface AppConfig {
2
+ app: {
3
+ port: number;
4
+ jwtSecret: string;
5
+ apiKey: string;
6
+ logLevel: string;
7
+ };
8
+ database: {
9
+ host: string;
10
+ port: number;
11
+ username: string;
12
+ password: string;
13
+ databaseName: string;
14
+ };
15
+ cloud: {
16
+ storageBucket: string;
17
+ instanceProfile: string;
18
+ apiHost: string;
19
+ projectId: string;
20
+ appKey: string;
21
+ cloudFrontUrl: string;
22
+ cloudFrontKeyPairId: string;
23
+ cloudFrontPrivateKey: string;
24
+ };
25
+ }
26
+
27
+ export const config: AppConfig = {
28
+ app: {
29
+ port: parseInt(process.env.PORT || '3000', 10),
30
+ jwtSecret: process.env.JWT_SECRET || 'your_jwt_secret',
31
+ apiKey: process.env.ACCESS_API_KEY || 'your_api_key',
32
+ logLevel: process.env.LOG_LEVEL || 'info',
33
+ },
34
+ database: {
35
+ host: process.env.POSTGRES_HOST || 'localhost',
36
+ port: parseInt(process.env.POSTGRES_PORT || '5432', 10),
37
+ username: process.env.POSTGRES_USERNAME || 'user',
38
+ password: process.env.POSTGRES_PASSWORD || 'password',
39
+ databaseName: process.env.POSTGRES_NAME || 'insforge',
40
+ },
41
+ cloud: {
42
+ storageBucket: process.env.AWS_S3_BUCKET || 'insforge-test-bucket',
43
+ instanceProfile: process.env.AWS_INSTANCE_PROFILE_NAME || 'insforge-instance-profile',
44
+ apiHost: process.env.CLOUD_API_HOST || 'https://api.insforge.dev',
45
+ projectId: process.env.PROJECT_ID || 'local',
46
+ appKey: process.env.APP_KEY || 'default-app-key',
47
+ cloudFrontUrl: process.env.AWS_CLOUDFRONT_URL || '',
48
+ cloudFrontKeyPairId: process.env.AWS_CLOUDFRONT_KEY_PAIR_ID || '',
49
+ cloudFrontPrivateKey: process.env.AWS_CLOUDFRONT_PRIVATE_KEY || '',
50
+ },
51
+ };
@@ -2,6 +2,7 @@ import { Pool } from 'pg';
2
2
  import path from 'path';
3
3
  import fs from 'fs/promises';
4
4
  import { fileURLToPath } from 'url';
5
+ import { DatabaseMetadataSchema } from '@insforge/shared-schemas';
5
6
 
6
7
  const __filename = fileURLToPath(import.meta.url);
7
8
  const __dirname = path.dirname(__filename);
@@ -46,91 +47,6 @@ export class DatabaseManager {
46
47
  await client.query('COMMIT');
47
48
  }
48
49
 
49
- // PostgreSQL-specific prepare method that returns a query object similar to better-sqlite3
50
- prepare(sql: string) {
51
- return {
52
- all: async (...params: unknown[]) => {
53
- const client = await this.pool.connect();
54
- try {
55
- // Convert SQLite parameter placeholders (?) to PostgreSQL ($1, $2, etc.)
56
- let pgSql = sql;
57
- let paramIndex = 1;
58
- while (pgSql.includes('?')) {
59
- pgSql = pgSql.replace('?', `$${paramIndex}`);
60
- paramIndex++;
61
- }
62
-
63
- const result = await client.query(pgSql, params);
64
- return result.rows;
65
- } finally {
66
- client.release();
67
- }
68
- },
69
-
70
- get: async (...params: unknown[]) => {
71
- const client = await this.pool.connect();
72
- try {
73
- // Convert SQLite parameter placeholders
74
- let pgSql = sql;
75
- let paramIndex = 1;
76
- while (pgSql.includes('?')) {
77
- pgSql = pgSql.replace('?', `$${paramIndex}`);
78
- paramIndex++;
79
- }
80
-
81
- const result = await client.query(pgSql, params);
82
- return result.rows[0] || null;
83
- } finally {
84
- client.release();
85
- }
86
- },
87
-
88
- run: async (...params: unknown[]) => {
89
- const client = await this.pool.connect();
90
- try {
91
- // Convert SQLite parameter placeholders
92
- let pgSql = sql;
93
- let paramIndex = 1;
94
- while (pgSql.includes('?')) {
95
- pgSql = pgSql.replace('?', `$${paramIndex}`);
96
- paramIndex++;
97
- }
98
-
99
- const result = await client.query(pgSql, params);
100
- return {
101
- changes: result.rowCount || 0,
102
- lastInsertRowid: null, // PostgreSQL doesn't have this concept
103
- };
104
- } finally {
105
- client.release();
106
- }
107
- },
108
-
109
- exec: async () => {
110
- const client = await this.pool.connect();
111
- try {
112
- await client.query(sql);
113
- } finally {
114
- client.release();
115
- }
116
- },
117
- };
118
- }
119
-
120
- getDb() {
121
- return {
122
- prepare: (sql: string) => this.prepare(sql),
123
- exec: async (sql: string) => {
124
- const client = await this.pool.connect();
125
- try {
126
- await client.query(sql);
127
- } finally {
128
- client.release();
129
- }
130
- },
131
- };
132
- }
133
-
134
50
  static async getColumnTypeMap(tableName: string): Promise<Record<string, string>> {
135
51
  const instance = DatabaseManager.getInstance();
136
52
  const client = await instance.pool.connect();
@@ -168,6 +84,81 @@ export class DatabaseManager {
168
84
  }
169
85
  }
170
86
 
87
+ async getMetadata(): Promise<DatabaseMetadataSchema> {
88
+ const client = await this.pool.connect();
89
+ try {
90
+ // Fetch all tables, database size, and record counts in parallel
91
+ const [allTables, databaseSize, countResults] = await Promise.all([
92
+ this.getUserTables(),
93
+ this.getDatabaseSizeInGB(),
94
+ // Get all counts in a single query using UNION ALL
95
+ (async () => {
96
+ try {
97
+ const tablesResult = await client.query(
98
+ `
99
+ SELECT table_name as name
100
+ FROM information_schema.tables
101
+ WHERE table_schema = 'public'
102
+ AND table_type = 'BASE TABLE'
103
+ AND (table_name NOT LIKE '\\_%')
104
+ ORDER BY table_name
105
+ `
106
+ );
107
+ const tableNames = tablesResult.rows.map((row: { name: string }) => row.name);
108
+
109
+ if (tableNames.length === 0) {
110
+ return [];
111
+ }
112
+
113
+ // Build a UNION ALL query to get all counts in one query
114
+ const unionQuery = tableNames
115
+ .map(
116
+ (tableName) =>
117
+ `SELECT '${tableName.replace(/'/g, "''")}' as table_name, COUNT(*) as count FROM "${tableName}"`
118
+ )
119
+ .join(' UNION ALL ');
120
+
121
+ const result = await client.query(unionQuery);
122
+ return result.rows as { table_name: string; count: number }[];
123
+ } catch {
124
+ return [];
125
+ }
126
+ })(),
127
+ ]);
128
+
129
+ // Map the count results to a lookup object
130
+ const countMap = new Map(countResults.map((r) => [r.table_name, Number(r.count)]));
131
+
132
+ const tableMetadatas = allTables.map((tableName) => ({
133
+ tableName,
134
+ recordCount: countMap.get(tableName) || 0,
135
+ }));
136
+
137
+ return {
138
+ tables: tableMetadatas,
139
+ totalSizeInGB: databaseSize,
140
+ hint: 'To retrieve detailed schema information for a specific table, call the get-table-schema tool with the table name.',
141
+ };
142
+ } finally {
143
+ client.release();
144
+ }
145
+ }
146
+
147
+ async getDatabaseSizeInGB(): Promise<number> {
148
+ const client = await this.pool.connect();
149
+ try {
150
+ // Query PostgreSQL for database size
151
+ const result = await client.query(`SELECT pg_database_size(current_database()) as size`);
152
+
153
+ // PostgreSQL returns size in bytes, convert to GB
154
+ return (result.rows[0]?.size || 0) / (1024 * 1024 * 1024);
155
+ } catch {
156
+ return 0;
157
+ } finally {
158
+ client.release();
159
+ }
160
+ }
161
+
171
162
  getPool(): Pool {
172
163
  return this.pool;
173
164
  }
@@ -0,0 +1,44 @@
1
+ -- Migration: 013 - Create auth schema and copy helper functions
2
+ -- Creates auth schema if it doesn't exist and copies JWT helper functions
3
+
4
+ -- Create auth schema if not exists
5
+ CREATE SCHEMA IF NOT EXISTS auth;
6
+
7
+ -- Function to get current user ID from JWT (in auth schema)
8
+ CREATE OR REPLACE FUNCTION auth.uid()
9
+ RETURNS uuid
10
+ LANGUAGE sql STABLE
11
+ AS $$
12
+ SELECT
13
+ nullif(
14
+ coalesce(
15
+ current_setting('request.jwt.claim.sub', true),
16
+ (current_setting('request.jwt.claims', true)::jsonb ->> 'sub')
17
+ ),
18
+ ''
19
+ )::uuid
20
+ $$;
21
+
22
+ -- Function to get current user role from JWT (in auth schema)
23
+ CREATE OR REPLACE FUNCTION auth.role()
24
+ RETURNS text
25
+ LANGUAGE sql STABLE
26
+ AS $$
27
+ SELECT
28
+ coalesce(
29
+ current_setting('request.jwt.claim.role', true),
30
+ (current_setting('request.jwt.claims', true)::jsonb ->> 'role')
31
+ )::text
32
+ $$;
33
+
34
+ -- Function to get current user email from JWT (in auth schema)
35
+ CREATE OR REPLACE FUNCTION auth.email()
36
+ RETURNS text
37
+ LANGUAGE sql STABLE
38
+ AS $$
39
+ SELECT
40
+ coalesce(
41
+ current_setting('request.jwt.claim.email', true),
42
+ (current_setting('request.jwt.claims', true)::jsonb ->> 'email')
43
+ )::text
44
+ $$;
@@ -0,0 +1,8 @@
1
+ -- Migration: 014 - Add updated_at trigger to users table
2
+ -- Adds the updated_at trigger to the users table for automatic timestamp management
3
+
4
+
5
+ DROP TRIGGER IF EXISTS update_users_updated_at ON users;
6
+ CREATE TRIGGER update_users_updated_at
7
+ BEFORE UPDATE ON users
8
+ FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();