insforge 0.3.3 → 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 -780
  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,169 @@
1
+ import axios from 'axios';
2
+ import logger from '@/utils/logger.js';
3
+ import { getApiBaseUrl } from '@/utils/environment.js';
4
+ import { OAuthConfigService } from '@/services/auth/oauth-config.service.js';
5
+ import { OAuthProvider } from './base.provider.js';
6
+ import type { MicrosoftUserInfo, OAuthUserData } from '@/types/auth.js';
7
+
8
+ /**
9
+ * Microsoft OAuth Service
10
+ * Handles all Microsoft OAuth operations including URL generation, token exchange, and user info retrieval
11
+ */
12
+ export class MicrosoftOAuthProvider implements OAuthProvider {
13
+ private static instance: MicrosoftOAuthProvider;
14
+
15
+ private constructor() {
16
+ // Initialize OAuth helpers if needed
17
+ }
18
+
19
+ public static getInstance(): MicrosoftOAuthProvider {
20
+ if (!MicrosoftOAuthProvider.instance) {
21
+ MicrosoftOAuthProvider.instance = new MicrosoftOAuthProvider();
22
+ }
23
+ return MicrosoftOAuthProvider.instance;
24
+ }
25
+
26
+ /**
27
+ * Generate Microsoft OAuth authorization URL
28
+ */
29
+ async generateOAuthUrl(state?: string): Promise<string> {
30
+ const oAuthConfigService = OAuthConfigService.getInstance();
31
+ const config = await oAuthConfigService.getConfigByProvider('microsoft');
32
+ if (!config) {
33
+ throw new Error('Microsoft OAuth not configured');
34
+ }
35
+
36
+ const selfBaseUrl = getApiBaseUrl();
37
+
38
+ logger.debug('Microsoft OAuth Config (fresh from DB):', {
39
+ clientId: config.clientId ? 'SET' : 'NOT SET',
40
+ });
41
+
42
+ // Note: shared-keys path not implemented for Microsoft; configure local keys
43
+ const authUrl = new URL('https://login.microsoftonline.com/common/oauth2/v2.0/authorize');
44
+ authUrl.searchParams.set('client_id', config.clientId ?? '');
45
+ authUrl.searchParams.set('response_type', 'code');
46
+ authUrl.searchParams.set('redirect_uri', `${selfBaseUrl}/api/auth/oauth/microsoft/callback`);
47
+ authUrl.searchParams.set(
48
+ 'scope',
49
+ config.scopes && config.scopes.length > 0
50
+ ? config.scopes.join(' ')
51
+ : 'openid email profile offline_access User.Read'
52
+ );
53
+ if (state) {
54
+ authUrl.searchParams.set('state', state);
55
+ }
56
+ return authUrl.toString();
57
+ }
58
+
59
+ /**
60
+ * Exchange Microsoft code for tokens
61
+ */
62
+ async exchangeCodeToToken(code: string): Promise<{ access_token: string; id_token?: string }> {
63
+ const oAuthConfigService = OAuthConfigService.getInstance();
64
+ const config = await oAuthConfigService.getConfigByProvider('microsoft');
65
+ if (!config) {
66
+ throw new Error('Microsoft OAuth not configured');
67
+ }
68
+
69
+ try {
70
+ logger.info('Exchanging Microsoft code for tokens', {
71
+ hasCode: !!code,
72
+ clientId: config.clientId?.substring(0, 10) + '...',
73
+ });
74
+
75
+ const clientSecret = await oAuthConfigService.getClientSecretByProvider('microsoft');
76
+ const selfBaseUrl = getApiBaseUrl();
77
+
78
+ const body = new URLSearchParams({
79
+ client_id: config.clientId ?? '',
80
+ client_secret: clientSecret ?? '',
81
+ code,
82
+ redirect_uri: `${selfBaseUrl}/api/auth/oauth/microsoft/callback`,
83
+ grant_type: 'authorization_code',
84
+ scope:
85
+ config.scopes && config.scopes.length > 0
86
+ ? config.scopes.join(' ')
87
+ : 'openid email profile offline_access User.Read',
88
+ });
89
+
90
+ const response = await axios.post(
91
+ 'https://login.microsoftonline.com/common/oauth2/v2.0/token',
92
+ body.toString(),
93
+ {
94
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
95
+ }
96
+ );
97
+
98
+ if (!response.data.access_token) {
99
+ throw new Error('Failed to get access token from Microsoft');
100
+ }
101
+ return {
102
+ access_token: response.data.access_token,
103
+ id_token: response.data.id_token, // optional
104
+ };
105
+ } catch (error) {
106
+ if (axios.isAxiosError(error) && error.response) {
107
+ logger.error('Microsoft token exchange failed', {
108
+ status: error.response.status,
109
+ error: error.response.data,
110
+ });
111
+ throw new Error(`Microsoft OAuth error: ${JSON.stringify(error.response.data)}`);
112
+ }
113
+ throw error;
114
+ }
115
+ }
116
+
117
+ /**
118
+ * Get Microsoft user info via Graph API
119
+ */
120
+ async getUserInfo(accessToken: string): Promise<MicrosoftUserInfo> {
121
+ try {
122
+ const userResp = await axios.get('https://graph.microsoft.com/v1.0/me', {
123
+ headers: { Authorization: `Bearer ${accessToken}` },
124
+ });
125
+
126
+ const data = userResp.data as {
127
+ id: string;
128
+ displayName?: string;
129
+ userPrincipalName?: string;
130
+ mail?: string | null;
131
+ };
132
+
133
+ const email = data.mail || data.userPrincipalName || `${data.id}@users.noreply.microsoft.com`;
134
+ const name = data.displayName || data.userPrincipalName || email;
135
+
136
+ return {
137
+ id: data.id,
138
+ email,
139
+ name,
140
+ };
141
+ } catch (error) {
142
+ logger.error('Microsoft user info retrieval failed:', error);
143
+ throw new Error(`Failed to get Microsoft user info: ${error}`);
144
+ }
145
+ }
146
+
147
+ /**
148
+ * Handle Microsoft OAuth callback
149
+ */
150
+ async handleCallback(payload: { code?: string; token?: string }): Promise<OAuthUserData> {
151
+ if (!payload.code) {
152
+ throw new Error('No authorization code provided');
153
+ }
154
+
155
+ const tokens = await this.exchangeCodeToToken(payload.code);
156
+ const microsoftUserInfo = await this.getUserInfo(tokens.access_token);
157
+
158
+ // Transform Microsoft user info to generic format
159
+ const userName = microsoftUserInfo.name || microsoftUserInfo.email.split('@')[0] || 'user';
160
+ return {
161
+ provider: 'microsoft',
162
+ providerId: microsoftUserInfo.id,
163
+ email: microsoftUserInfo.email,
164
+ userName,
165
+ avatarUrl: '', // Microsoft doesn't provide avatar in basic profile
166
+ identityData: microsoftUserInfo,
167
+ };
168
+ }
169
+ }
@@ -0,0 +1,202 @@
1
+ import crypto from 'crypto';
2
+ import { XUserInfo, OAuthUserData } from '@/types/auth.js';
3
+ import { getApiBaseUrl } from '@/utils/environment.js';
4
+ import logger from '@/utils/logger.js';
5
+ import { OAuthProvider } from './base.provider.js';
6
+ import axios from 'axios';
7
+ import { OAuthConfigService } from '@/services/auth/oauth-config.service.js';
8
+
9
+ export class XOAuthProvider implements OAuthProvider {
10
+ private static instance: XOAuthProvider;
11
+ // OAuth helper for X(Twitter)
12
+ private verifierCodes: Map<string, string>;
13
+
14
+ private constructor() {
15
+ this.verifierCodes = new Map();
16
+ }
17
+
18
+ public static getInstance(): XOAuthProvider {
19
+ if (!XOAuthProvider.instance) {
20
+ XOAuthProvider.instance = new XOAuthProvider();
21
+ }
22
+ return XOAuthProvider.instance;
23
+ }
24
+
25
+ /**
26
+ * Generate X OAuth authorization URL
27
+ */
28
+ async generateOAuthUrl(state?: string): Promise<string> {
29
+ const oauthConfigService = OAuthConfigService.getInstance();
30
+ const config = await oauthConfigService.getConfigByProvider('x');
31
+ const verifier = crypto.randomBytes(32).toString('base64url');
32
+ const challenge = crypto.createHash('sha256').update(verifier).digest('base64url');
33
+
34
+ if (!config) {
35
+ throw new Error('X OAuth not configured');
36
+ }
37
+
38
+ const selfBaseUrl = getApiBaseUrl();
39
+
40
+ if (!state) {
41
+ throw new Error('State parameter is required.');
42
+ }
43
+ this.verifierCodes.set(state, verifier);
44
+ setTimeout(() => {
45
+ this.verifierCodes.delete(state);
46
+ }, 600000);
47
+
48
+ if (config?.useSharedKey) {
49
+ // Use shared keys if configured
50
+ const cloudBasedUrl = process.env.CLOUD_API_HOST || 'https://api.insforge.dev';
51
+ const redirectUri = `${selfBaseUrl}/api/auth/oauth/shared/callback/${state}`;
52
+ const response = await axios.get(
53
+ `${cloudBasedUrl}/oauth/twitter?redirect_uri=${encodeURIComponent(redirectUri)}`,
54
+ {
55
+ headers: {
56
+ 'Content-Type': 'application/json',
57
+ },
58
+ }
59
+ );
60
+ return response.data.auth_url || response.data.url || '';
61
+ }
62
+
63
+ logger.debug('X OAuth Config (fresh from DB):', {
64
+ clientId: config.clientId ? 'SET' : 'NOT SET',
65
+ });
66
+
67
+ const authUrl = new URL('https://twitter.com/i/oauth2/authorize');
68
+ authUrl.searchParams.set('response_type', 'code');
69
+ authUrl.searchParams.set('client_id', config.clientId ?? '');
70
+ authUrl.searchParams.set('redirect_uri', `${selfBaseUrl}/api/auth/oauth/x/callback`);
71
+ authUrl.searchParams.set(
72
+ 'scope',
73
+ config.scopes ? config.scopes.join(' ') : 'tweet.read users.read'
74
+ );
75
+ authUrl.searchParams.set('state', state ?? '');
76
+ authUrl.searchParams.set('code_challenge', challenge);
77
+ authUrl.searchParams.set('code_challenge_method', 'S256');
78
+
79
+ return authUrl.toString();
80
+ }
81
+
82
+ /**
83
+ * Exchange X code for access token
84
+ */
85
+ async exchangeXCodeForToken(code: string, state: string): Promise<string> {
86
+ const verifier = this.verifierCodes.get(state);
87
+
88
+ if (!verifier) {
89
+ throw new Error('Missing or expired PKCE verifier for this state');
90
+ }
91
+
92
+ // Immediately remove it to prevent replay
93
+ this.verifierCodes.delete(state);
94
+
95
+ const oauthConfigService = OAuthConfigService.getInstance();
96
+ const config = await oauthConfigService.getConfigByProvider('x');
97
+
98
+ if (!config) {
99
+ throw new Error('X OAuth not configured');
100
+ }
101
+
102
+ const clientSecret = await oauthConfigService.getClientSecretByProvider('x');
103
+ const selfBaseUrl = getApiBaseUrl();
104
+
105
+ const body = new URLSearchParams({
106
+ code,
107
+ grant_type: 'authorization_code',
108
+ client_id: config.clientId ?? '',
109
+ redirect_uri: `${selfBaseUrl}/api/auth/oauth/x/callback`,
110
+ code_verifier: verifier,
111
+ });
112
+
113
+ const response = await axios.post('https://api.twitter.com/2/oauth2/token', body.toString(), {
114
+ headers: {
115
+ 'Content-Type': 'application/x-www-form-urlencoded',
116
+ Authorization:
117
+ 'Basic ' + Buffer.from(`${config.clientId}:${clientSecret}`).toString('base64'),
118
+ },
119
+ });
120
+
121
+ if (!response.data.access_token) {
122
+ throw new Error('Failed to get access token from X');
123
+ }
124
+
125
+ return response.data.access_token;
126
+ }
127
+
128
+ /**
129
+ * Get X user info
130
+ */
131
+ async getXUserInfo(accessToken: string): Promise<XUserInfo> {
132
+ const userResponse = await axios.get('https://api.twitter.com/2/users/me', {
133
+ headers: {
134
+ Authorization: `Bearer ${accessToken}`,
135
+ },
136
+ params: {
137
+ 'user.fields': 'id,name,username,profile_image_url,verified',
138
+ },
139
+ });
140
+
141
+ const userData = userResponse.data.data;
142
+
143
+ return {
144
+ id: userData.id,
145
+ name: userData.name,
146
+ username: userData.username,
147
+ profile_image_url: userData.profile_image_url,
148
+ verified: userData.verified,
149
+ };
150
+ }
151
+
152
+ /**
153
+ * Handle X OAuth callback
154
+ */
155
+ async handleCallback(payload: {
156
+ code?: string;
157
+ token?: string;
158
+ state?: string;
159
+ }): Promise<OAuthUserData> {
160
+ if (!payload.code || !payload.state) {
161
+ throw new Error('No authorization code or state provided');
162
+ }
163
+
164
+ const accessToken = await this.exchangeXCodeForToken(payload.code, payload.state);
165
+ const xUserInfo = await this.getXUserInfo(accessToken);
166
+
167
+ // Transform X user info to generic format
168
+ const userName = xUserInfo.username || xUserInfo.name || `user${xUserInfo.id.substring(0, 8)}`;
169
+ const email = `${userName}@users.noreply.x.local`;
170
+
171
+ return {
172
+ provider: 'x',
173
+ providerId: xUserInfo.id,
174
+ email,
175
+ userName,
176
+ avatarUrl: xUserInfo.profile_image_url || '',
177
+ identityData: xUserInfo,
178
+ };
179
+ }
180
+
181
+ /**
182
+ * Handle shared callback payload transformation
183
+ */
184
+ handleSharedCallback(payloadData: Record<string, unknown>): OAuthUserData {
185
+ const providerId = String(payloadData.providerId ?? '');
186
+ const username = String(payloadData.username ?? '');
187
+ const name = String(payloadData.name ?? '');
188
+ const profileImageUrl = String(payloadData.profile_image_url ?? '');
189
+
190
+ const userName = username || name || `user${providerId.substring(0, 8)}`;
191
+ const email = `${userName}@users.noreply.x.local`;
192
+
193
+ return {
194
+ provider: 'x',
195
+ providerId,
196
+ email,
197
+ userName,
198
+ avatarUrl: profileImageUrl,
199
+ identityData: payloadData,
200
+ };
201
+ }
202
+ }
@@ -0,0 +1,29 @@
1
+ import { UploadStrategyResponse, DownloadStrategyResponse } from '@insforge/shared-schemas';
2
+
3
+ /**
4
+ * Storage provider interface
5
+ * Defines the contract that all storage providers must implement
6
+ */
7
+ export interface StorageProvider {
8
+ initialize(): void | Promise<void>;
9
+ putObject(bucket: string, key: string, file: Express.Multer.File): Promise<void>;
10
+ getObject(bucket: string, key: string): Promise<Buffer | null>;
11
+ deleteObject(bucket: string, key: string): Promise<void>;
12
+ createBucket(bucket: string): Promise<void>;
13
+ deleteBucket(bucket: string): Promise<void>;
14
+
15
+ // Presigned URL support
16
+ supportsPresignedUrls(): boolean;
17
+ getUploadStrategy(
18
+ bucket: string,
19
+ key: string,
20
+ metadata: { contentType?: string; size?: number }
21
+ ): Promise<UploadStrategyResponse>;
22
+ getDownloadStrategy(
23
+ bucket: string,
24
+ key: string,
25
+ expiresIn?: number,
26
+ isPublic?: boolean
27
+ ): Promise<DownloadStrategyResponse>;
28
+ verifyObjectExists(bucket: string, key: string): Promise<boolean>;
29
+ }
@@ -0,0 +1,103 @@
1
+ import fs from 'fs/promises';
2
+ import path from 'path';
3
+ import { UploadStrategyResponse, DownloadStrategyResponse } from '@insforge/shared-schemas';
4
+ import { StorageProvider } from './base.provider.js';
5
+ import { getApiBaseUrl } from '@/utils/environment.js';
6
+
7
+ /**
8
+ * Local filesystem storage implementation
9
+ */
10
+ export class LocalStorageProvider implements StorageProvider {
11
+ constructor(private baseDir: string) {}
12
+
13
+ async initialize(): Promise<void> {
14
+ await fs.mkdir(this.baseDir, { recursive: true });
15
+ }
16
+
17
+ private getFilePath(bucket: string, key: string): string {
18
+ return path.join(this.baseDir, bucket, key);
19
+ }
20
+
21
+ async putObject(bucket: string, key: string, file: Express.Multer.File): Promise<void> {
22
+ const filePath = this.getFilePath(bucket, key);
23
+ await fs.mkdir(path.dirname(filePath), { recursive: true });
24
+ await fs.writeFile(filePath, file.buffer);
25
+ }
26
+
27
+ async getObject(bucket: string, key: string): Promise<Buffer | null> {
28
+ try {
29
+ const filePath = this.getFilePath(bucket, key);
30
+ return await fs.readFile(filePath);
31
+ } catch {
32
+ return null;
33
+ }
34
+ }
35
+
36
+ async deleteObject(bucket: string, key: string): Promise<void> {
37
+ try {
38
+ const filePath = this.getFilePath(bucket, key);
39
+ await fs.unlink(filePath);
40
+ } catch {
41
+ // File might not exist, continue
42
+ }
43
+ }
44
+
45
+ async createBucket(bucket: string): Promise<void> {
46
+ const bucketPath = path.join(this.baseDir, bucket);
47
+ await fs.mkdir(bucketPath, { recursive: true });
48
+ }
49
+
50
+ async deleteBucket(bucket: string): Promise<void> {
51
+ try {
52
+ await fs.rmdir(path.join(this.baseDir, bucket), { recursive: true });
53
+ } catch {
54
+ // Directory might not exist
55
+ }
56
+ }
57
+
58
+ // Local storage doesn't support presigned URLs
59
+ supportsPresignedUrls(): boolean {
60
+ return false;
61
+ }
62
+
63
+ getUploadStrategy(
64
+ bucket: string,
65
+ key: string,
66
+ _metadata: { contentType?: string; size?: number }
67
+ ): Promise<UploadStrategyResponse> {
68
+ // For local storage, return direct upload strategy with absolute URL
69
+ const baseUrl = getApiBaseUrl();
70
+ return Promise.resolve({
71
+ method: 'direct',
72
+ uploadUrl: `${baseUrl}/api/storage/buckets/${bucket}/objects/${encodeURIComponent(key)}`,
73
+ key,
74
+ confirmRequired: false,
75
+ });
76
+ }
77
+
78
+ getDownloadStrategy(
79
+ bucket: string,
80
+ key: string,
81
+ _expiresIn?: number,
82
+ _isPublic?: boolean
83
+ ): Promise<DownloadStrategyResponse> {
84
+ // For local storage, return direct download URL with absolute URL
85
+ const baseUrl = getApiBaseUrl();
86
+ return Promise.resolve({
87
+ method: 'direct',
88
+ url: `${baseUrl}/api/storage/buckets/${bucket}/objects/${encodeURIComponent(key)}`,
89
+ });
90
+ }
91
+
92
+ async verifyObjectExists(bucket: string, key: string): Promise<boolean> {
93
+ // For local storage, check if file exists on disk
94
+ try {
95
+ const filePath = this.getFilePath(bucket, key);
96
+ await fs.access(filePath);
97
+ return true;
98
+ } catch {
99
+ // File doesn't exist
100
+ return false;
101
+ }
102
+ }
103
+ }