insforge 0.3.2 → 1.2.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (507) hide show
  1. package/.claude-plugin/marketplace.json +20 -0
  2. package/.cursor/rules/cursor-rules.mdc +94 -0
  3. package/.dockerignore +3 -0
  4. package/.env.example +33 -4
  5. package/.github/ISSUE_TEMPLATE/bug_report.yml +13 -60
  6. package/.github/ISSUE_TEMPLATE/config.yml +2 -2
  7. package/.github/ISSUE_TEMPLATE/feature_request.yml +10 -63
  8. package/.github/PULL_REQUEST_TEMPLATE.md +7 -0
  9. package/.github/workflows/build-image.yml +2 -1
  10. package/.github/workflows/e2e.yml +63 -0
  11. package/CHANGELOG.md +41 -0
  12. package/CLAUDE_PLUGIN.md +104 -0
  13. package/CODE_OF_CONDUCT.md +128 -0
  14. package/CONTRIBUTING.md +1 -1
  15. package/Dockerfile +4 -1
  16. package/README.md +66 -18
  17. package/assets/mcpInstallv2.png +0 -0
  18. package/assets/sampleResponse.png +0 -0
  19. package/auth/index.html +13 -0
  20. package/auth/package.json +28 -0
  21. package/auth/public/favicon.ico +0 -0
  22. package/auth/src/App.tsx +33 -0
  23. package/auth/src/components/ErrorCard.tsx +37 -0
  24. package/auth/src/components/Layout.tsx +13 -0
  25. package/auth/src/index.css +19 -0
  26. package/auth/src/lib/broadcastService.ts +115 -0
  27. package/auth/src/lib/utils.ts +11 -0
  28. package/auth/src/main.tsx +22 -0
  29. package/auth/src/pages/ForgotPasswordPage.tsx +11 -0
  30. package/auth/src/pages/ResetPasswordPage.tsx +11 -0
  31. package/auth/src/pages/SignInPage.tsx +57 -0
  32. package/auth/src/pages/SignUpPage.tsx +57 -0
  33. package/auth/src/pages/VerifyEmailPage.tsx +20 -0
  34. package/auth/src/vite-env.d.ts +10 -0
  35. package/auth/tsconfig.json +32 -0
  36. package/auth/tsconfig.node.json +11 -0
  37. package/auth/vite.config.ts +25 -0
  38. package/backend/package.json +9 -9
  39. package/backend/src/api/{middleware → middlewares}/auth.ts +8 -9
  40. package/backend/src/api/middlewares/rate-limiters.ts +127 -0
  41. package/backend/src/api/routes/{ai.ts → ai/index.routes.ts} +20 -24
  42. package/backend/src/api/routes/auth/index.routes.ts +570 -0
  43. package/backend/src/api/routes/auth/oauth.routes.ts +448 -0
  44. package/backend/src/api/routes/{database.advance.ts → database/advance.routes.ts} +107 -65
  45. package/backend/src/api/routes/database/index.routes.ts +13 -0
  46. package/backend/src/api/routes/{database.records.ts → database/records.routes.ts} +22 -8
  47. package/backend/src/api/routes/{database.tables.ts → database/tables.routes.ts} +20 -23
  48. package/backend/src/api/routes/docs/index.routes.ts +76 -0
  49. package/backend/src/api/routes/functions/index.routes.ts +188 -0
  50. package/backend/src/api/routes/{logs.ts → logs/index.routes.ts} +25 -30
  51. package/backend/src/api/routes/{metadata.ts → metadata/index.routes.ts} +21 -31
  52. package/backend/src/api/routes/{secrets.ts → secrets/index.routes.ts} +27 -22
  53. package/backend/src/api/routes/{storage.ts → storage/index.routes.ts} +34 -53
  54. package/backend/src/api/routes/usage/index.routes.ts +89 -0
  55. package/backend/src/infra/config/app.config.ts +51 -0
  56. package/backend/src/{core/database/manager.ts → infra/database/database.manager.ts} +76 -85
  57. package/backend/src/infra/database/migrations/013_create-auth-schema-functions.sql +44 -0
  58. package/backend/src/infra/database/migrations/014_add-updated-at-trigger-user-table.sql +8 -0
  59. package/backend/src/infra/database/migrations/015_create-auth-config-and-email-otp-tables.sql +60 -0
  60. package/backend/src/infra/database/migrations/016_update-auth-config-and-email-otp.sql +24 -0
  61. package/backend/src/{core/secrets/encryption.ts → infra/security/encryption.manager.ts} +3 -2
  62. package/backend/src/infra/security/token.manager.ts +125 -0
  63. package/backend/src/{core/socket/socket.ts → infra/socket/socket.manager.ts} +15 -15
  64. package/backend/src/providers/ai/openrouter.provider.ts +377 -0
  65. package/backend/src/providers/email/base.provider.ts +41 -0
  66. package/backend/src/providers/email/cloud.provider.ts +187 -0
  67. package/backend/src/{core/logs/providers → providers/logs}/base.provider.ts +11 -11
  68. package/backend/src/{core/logs/providers → providers/logs}/cloudwatch.provider.ts +61 -38
  69. package/backend/src/providers/logs/local.provider.ts +185 -0
  70. package/backend/src/providers/oauth/base.provider.ts +29 -0
  71. package/backend/src/providers/oauth/discord.provider.ts +195 -0
  72. package/backend/src/providers/oauth/facebook.provider.ts +194 -0
  73. package/backend/src/providers/oauth/github.provider.ts +208 -0
  74. package/backend/src/providers/oauth/google.provider.ts +249 -0
  75. package/backend/src/providers/oauth/index.ts +7 -0
  76. package/backend/src/providers/oauth/linkedin.provider.ts +240 -0
  77. package/backend/src/providers/oauth/microsoft.provider.ts +169 -0
  78. package/backend/src/providers/oauth/x.provider.ts +202 -0
  79. package/backend/src/providers/storage/base.provider.ts +29 -0
  80. package/backend/src/providers/storage/local.provider.ts +103 -0
  81. package/backend/src/providers/storage/s3.provider.ts +313 -0
  82. package/backend/src/server.ts +70 -74
  83. package/backend/src/{core/ai/config.ts → services/ai/ai-config.service.ts} +19 -24
  84. package/backend/src/services/ai/ai-model.service.ts +60 -0
  85. package/backend/src/{core/ai/usage.ts → services/ai/ai-usage.service.ts} +28 -35
  86. package/backend/src/{core/ai/chat.ts → services/ai/chat-completion.service.ts} +37 -24
  87. package/backend/src/services/ai/helpers.ts +64 -0
  88. package/backend/src/{core/ai/image.ts → services/ai/image-generation.service.ts} +17 -19
  89. package/backend/src/services/ai/index.ts +13 -0
  90. package/backend/src/services/auth/auth-config.service.ts +250 -0
  91. package/backend/src/services/auth/auth-otp.service.ts +424 -0
  92. package/backend/src/services/auth/auth.service.ts +1136 -0
  93. package/backend/src/services/auth/index.ts +4 -0
  94. package/backend/src/{core/auth/oauth.ts → services/auth/oauth-config.service.ts} +106 -52
  95. package/backend/src/{core/database/advance.ts → services/database/database-advance.service.ts} +97 -131
  96. package/backend/src/services/database/database-table.service.ts +811 -0
  97. package/backend/src/services/email/email.service.ts +75 -0
  98. package/backend/src/{core/functions/functions.ts → services/functions/function.service.ts} +95 -88
  99. package/backend/src/{core/logs/audit.ts → services/logs/audit.service.ts} +92 -75
  100. package/backend/src/services/logs/log.service.ts +73 -0
  101. package/backend/src/{core/secrets/secrets.ts → services/secrets/secret.service.ts} +48 -66
  102. package/backend/src/services/storage/storage.service.ts +617 -0
  103. package/backend/src/services/usage/usage.service.ts +149 -0
  104. package/backend/src/types/auth.ts +66 -2
  105. package/backend/src/types/email.ts +8 -0
  106. package/backend/src/types/error-constants.ts +4 -0
  107. package/backend/src/types/logs.ts +0 -29
  108. package/backend/src/{core/socket/types.ts → types/socket.ts} +5 -6
  109. package/backend/src/utils/environment.ts +9 -3
  110. package/backend/src/utils/logger.ts +20 -2
  111. package/backend/src/utils/seed.ts +150 -57
  112. package/backend/src/utils/sql-parser.ts +1 -1
  113. package/backend/src/utils/utils.ts +114 -0
  114. package/backend/src/utils/validations.ts +40 -4
  115. package/backend/tests/local/test-ai-config.sh +129 -0
  116. package/backend/tests/local/test-ai-usage.sh +80 -0
  117. package/backend/tests/local/test-auth-router.sh +1 -1
  118. package/backend/tests/local/test-e2e.sh +1 -1
  119. package/backend/tests/local/test-functions.sh +123 -0
  120. package/backend/tests/local/test-logs.sh +132 -0
  121. package/backend/tests/local/test-public-bucket.sh +3 -3
  122. package/backend/tests/local/test-secrets.sh +14 -12
  123. package/backend/tests/local/test-traditional-rest.sh +2 -2
  124. package/backend/tests/manual/test-rawsql-modes.sh +244 -0
  125. package/backend/tests/test-config.sh +37 -1
  126. package/backend/tests/unit/cloud-token.test.ts +48 -0
  127. package/backend/tests/unit/constant.test.ts +8 -0
  128. package/backend/tests/unit/email.test.ts +372 -0
  129. package/backend/tests/unit/environment.test.ts +59 -0
  130. package/backend/tests/unit/helpers.test.ts +63 -0
  131. package/backend/tests/unit/logger.test.ts +22 -0
  132. package/backend/tests/unit/rate-limit.test.ts +154 -0
  133. package/backend/tests/unit/response.test.ts +58 -0
  134. package/backend/tests/unit/sql-parser.test.ts +74 -0
  135. package/backend/tests/unit/uuid.test.ts +21 -0
  136. package/backend/tests/unit/validations.test.ts +80 -0
  137. package/backend/tsconfig.json +1 -1
  138. package/backend/vitest.config.ts +11 -0
  139. package/claude-plugin/.claude-plugin/plugin.json +24 -0
  140. package/claude-plugin/README.md +133 -0
  141. package/claude-plugin/skills/insforge-schema-patterns/SKILL.md +270 -0
  142. package/docker-compose.prod.yml +60 -4
  143. package/docker-compose.yml +65 -4
  144. package/docker-init/db/db-init.sql +6 -34
  145. package/docker-init/logs/vector.yml +236 -0
  146. package/docs/README.md +44 -0
  147. package/docs/changelog.mdx +67 -0
  148. package/docs/core-concepts/ai/architecture.mdx +373 -0
  149. package/docs/core-concepts/ai/sdk.mdx +213 -0
  150. package/docs/core-concepts/authentication/architecture.mdx +278 -0
  151. package/docs/core-concepts/authentication/sdk.mdx +414 -0
  152. package/docs/core-concepts/authentication/ui-components/customization.mdx +529 -0
  153. package/docs/core-concepts/authentication/ui-components/nextjs.mdx +221 -0
  154. package/docs/core-concepts/authentication/ui-components/react-router.mdx +184 -0
  155. package/docs/core-concepts/authentication/ui-components/react.mdx +129 -0
  156. package/docs/core-concepts/database/architecture.mdx +256 -0
  157. package/docs/core-concepts/database/sdk.mdx +382 -0
  158. package/docs/core-concepts/functions/architecture.mdx +105 -0
  159. package/docs/core-concepts/functions/sdk.mdx +184 -0
  160. package/docs/core-concepts/storage/architecture.mdx +243 -0
  161. package/docs/core-concepts/storage/sdk.mdx +253 -0
  162. package/docs/deployment/README.md +94 -0
  163. package/docs/deployment/deploy-to-aws-ec2.md +565 -0
  164. package/docs/deployment/deploy-to-azure-virtual-machines.md +313 -0
  165. package/docs/deployment/deploy-to-google-cloud-compute-engine.md +613 -0
  166. package/docs/deployment/deploy-to-render.md +441 -0
  167. package/docs/docs.json +210 -0
  168. package/docs/examples/framework-guides/nextjs.mdx +131 -0
  169. package/docs/examples/framework-guides/nuxt.mdx +165 -0
  170. package/docs/examples/framework-guides/react.mdx +165 -0
  171. package/docs/examples/framework-guides/svelte.mdx +153 -0
  172. package/docs/examples/framework-guides/vue.mdx +159 -0
  173. package/docs/examples/overview.mdx +67 -0
  174. package/docs/favicon.svg +19 -0
  175. package/docs/images/changelog/nov-2025/auth-components.webp +0 -0
  176. package/docs/images/changelog/nov-2025/database-metadata.webp +0 -0
  177. package/docs/images/changelog/nov-2025/quickstart-prompts.webp +0 -0
  178. package/docs/images/changelog/nov-2025/sql-editor.webp +0 -0
  179. package/docs/images/changelog/nov-2025/usage-page.webp +0 -0
  180. package/docs/images/changelog/october-2025/csv-upload.webp +0 -0
  181. package/docs/images/changelog/october-2025/logs-feature.webp +0 -0
  182. package/docs/images/changelog/october-2025/oauth-providers.webp +0 -0
  183. package/docs/images/checks-passed.png +0 -0
  184. package/docs/images/dashboard-connect-expanded.png +0 -0
  185. package/docs/images/dashboard-connect.png +0 -0
  186. package/docs/images/hero-dark.png +0 -0
  187. package/docs/images/hero-light.png +0 -0
  188. package/docs/images/icons/ai.svg +4 -0
  189. package/docs/images/icons/auth.svg +1 -0
  190. package/docs/images/icons/database.svg +1 -0
  191. package/docs/images/icons/function.svg +1 -0
  192. package/docs/images/icons/storage.svg +1 -0
  193. package/docs/images/logos/nextjs.svg +4 -0
  194. package/docs/images/logos/nuxt.svg +4 -0
  195. package/docs/images/logos/react.svg +5 -0
  196. package/docs/images/logos/svelte.svg +4 -0
  197. package/docs/images/logos/vue.svg +5 -0
  198. package/docs/images/mcp-install.png +0 -0
  199. package/docs/images/onboarding-mcp.png +0 -0
  200. package/docs/insforge-instructions-sdk.md +55 -374
  201. package/docs/introduction.mdx +45 -0
  202. package/docs/logo/dark.svg +22 -0
  203. package/docs/logo/light.svg +20 -0
  204. package/docs/partnership.mdx +647 -0
  205. package/docs/quickstart.mdx +83 -0
  206. package/docs/showcase/2048-arena.png +0 -0
  207. package/docs/showcase/framegen-cloud.png +0 -0
  208. package/docs/showcase/line-connect-race.png +0 -0
  209. package/docs/showcase/moment-vibe.png +0 -0
  210. package/docs/showcase/national-flags.png +0 -0
  211. package/docs/showcase/pokemon-vibe.png +0 -0
  212. package/docs/showcase/pure-browse-buy.png +0 -0
  213. package/docs/showcase.mdx +52 -0
  214. package/docs/snippets/sdk-installation.mdx +22 -0
  215. package/docs/snippets/service-icons.mdx +27 -0
  216. package/eslint.config.js +10 -3
  217. package/frontend/package.json +10 -4
  218. package/frontend/src/App.tsx +13 -82
  219. package/frontend/src/assets/icons/connected.svg +3 -0
  220. package/frontend/src/assets/icons/loader.svg +9 -0
  221. package/frontend/src/assets/logos/apple.svg +4 -0
  222. package/frontend/src/assets/logos/discord.svg +1 -1
  223. package/frontend/src/assets/logos/facebook.svg +3 -0
  224. package/frontend/src/assets/logos/instagram.svg +2 -0
  225. package/frontend/src/assets/logos/linkedin.svg +3 -0
  226. package/frontend/src/assets/logos/microsoft.svg +1 -0
  227. package/frontend/src/assets/logos/spotify.svg +17 -0
  228. package/frontend/src/assets/logos/tiktok.svg +6 -0
  229. package/frontend/src/assets/logos/x.svg +3 -0
  230. package/frontend/src/components/Checkbox.tsx +27 -29
  231. package/frontend/src/components/CodeBlock.tsx +55 -2
  232. package/frontend/src/components/CodeEditor.tsx +92 -0
  233. package/frontend/src/components/ConfirmDialog.tsx +1 -1
  234. package/frontend/src/components/ConnectCTA.tsx +38 -0
  235. package/frontend/src/components/CopyButton.tsx +52 -15
  236. package/frontend/src/components/ErrorState.tsx +1 -2
  237. package/frontend/src/components/FeatureSidebar.tsx +6 -6
  238. package/frontend/src/components/FeatureSidebarItem.tsx +2 -2
  239. package/frontend/src/components/JsonHighlight.tsx +21 -9
  240. package/frontend/src/components/ProjectInfoModal.tsx +128 -0
  241. package/frontend/src/components/PromptDialog.tsx +1 -4
  242. package/frontend/src/components/SearchInput.tsx +1 -2
  243. package/frontend/src/components/Stepper.tsx +53 -0
  244. package/frontend/src/components/ThemeToggle.tsx +3 -3
  245. package/frontend/src/components/datagrid/DataGrid.tsx +25 -32
  246. package/frontend/src/components/datagrid/cell-editors/DateCellEditor.tsx +1 -2
  247. package/frontend/src/components/datagrid/cell-editors/JsonCellEditor.tsx +2 -4
  248. package/frontend/src/components/datagrid/index.ts +23 -0
  249. package/frontend/src/components/index.ts +23 -30
  250. package/frontend/src/components/layout/AppHeader.tsx +133 -92
  251. package/frontend/src/components/layout/AppSidebar.tsx +80 -170
  252. package/frontend/src/components/layout/Layout.tsx +12 -23
  253. package/frontend/src/components/layout/PrimaryMenu.tsx +187 -0
  254. package/frontend/src/components/layout/SecondaryMenu.tsx +70 -0
  255. package/frontend/src/components/layout/index.ts +5 -0
  256. package/frontend/src/components/radix/Tooltip.tsx +24 -13
  257. package/frontend/src/components/radix/index.ts +22 -0
  258. package/frontend/src/features/ai/components/AIConfigCard.tsx +129 -83
  259. package/frontend/src/features/ai/components/AIEmptyState.tsx +12 -7
  260. package/frontend/src/features/ai/components/ModalityFilterSidebar.tsx +101 -0
  261. package/frontend/src/features/ai/components/ModelSelectionDialog.tsx +135 -0
  262. package/frontend/src/features/ai/components/ModelSelectionGrid.tsx +51 -0
  263. package/frontend/src/features/ai/components/SystemPromptDialog.tsx +118 -0
  264. package/frontend/src/features/ai/components/index.ts +6 -0
  265. package/frontend/src/features/ai/helpers.ts +57 -71
  266. package/frontend/src/features/ai/hooks/useAIConfigs.ts +39 -113
  267. package/frontend/src/features/ai/hooks/useAIUsage.ts +0 -2
  268. package/frontend/src/features/ai/page/AIPage.tsx +67 -79
  269. package/frontend/src/features/ai/services/ai.service.ts +5 -5
  270. package/frontend/src/features/auth/components/AuthPreview.tsx +96 -0
  271. package/frontend/src/features/auth/components/OAuthConfigDialog.tsx +53 -30
  272. package/frontend/src/features/auth/components/UserFormDialog.tsx +13 -6
  273. package/frontend/src/features/auth/components/UsersDataGrid.tsx +44 -14
  274. package/frontend/src/features/auth/components/index.ts +5 -0
  275. package/frontend/src/features/auth/helpers.tsx +200 -0
  276. package/frontend/src/features/auth/hooks/useAnonToken.ts +30 -0
  277. package/frontend/src/features/auth/hooks/useAuthConfig.ts +48 -0
  278. package/frontend/src/features/auth/hooks/useOAuthConfig.ts +14 -10
  279. package/frontend/src/features/auth/hooks/useUsers.ts +43 -5
  280. package/frontend/src/features/auth/index.ts +3 -2
  281. package/frontend/src/features/auth/page/AuthMethodsPage.tsx +275 -0
  282. package/frontend/src/features/auth/page/ConfigurationPage.tsx +395 -0
  283. package/frontend/src/features/auth/page/UsersPage.tsx +285 -0
  284. package/frontend/src/features/auth/services/anonToken.service.ts +11 -0
  285. package/frontend/src/features/auth/services/config.service.ts +19 -0
  286. package/frontend/src/features/auth/services/{oauth.service.ts → oauth-config.service.ts} +4 -4
  287. package/frontend/src/features/auth/services/{auth.service.ts → user.service.ts} +7 -53
  288. package/frontend/src/features/dashboard/components/ConnectionSuccessBanner.tsx +35 -0
  289. package/frontend/src/features/dashboard/components/PromptCard.tsx +21 -0
  290. package/frontend/src/features/dashboard/components/PromptDialog.tsx +103 -0
  291. package/frontend/src/features/dashboard/components/StatsCard.tsx +50 -0
  292. package/frontend/src/features/dashboard/components/index.ts +4 -0
  293. package/frontend/src/features/dashboard/page/DashboardPage.tsx +187 -169
  294. package/frontend/src/features/dashboard/prompts/ai-chatbot.ts +13 -0
  295. package/frontend/src/features/dashboard/prompts/crm-system.ts +13 -0
  296. package/frontend/src/features/dashboard/prompts/ecommerce-platform.ts +12 -0
  297. package/frontend/src/features/dashboard/prompts/index.ts +31 -0
  298. package/frontend/src/features/dashboard/prompts/instagram-clone.ts +11 -0
  299. package/frontend/src/features/dashboard/prompts/notion-clone.ts +14 -0
  300. package/frontend/src/features/dashboard/prompts/reddit-clone.ts +12 -0
  301. package/frontend/src/features/database/components/DatabaseDataGrid.tsx +48 -17
  302. package/frontend/src/features/database/components/ForeignKeyCell.tsx +15 -34
  303. package/frontend/src/features/database/components/ForeignKeyPopover.tsx +19 -20
  304. package/frontend/src/features/database/components/LinkRecordModal.tsx +120 -125
  305. package/frontend/src/features/database/components/RecordFormDialog.tsx +22 -33
  306. package/frontend/src/features/database/components/RecordFormField.tsx +45 -47
  307. package/frontend/src/features/database/components/TableEmptyState.tsx +6 -5
  308. package/frontend/src/features/database/components/TableForm.tsx +28 -15
  309. package/frontend/src/features/database/components/TableFormColumn.tsx +2 -3
  310. package/frontend/src/features/database/components/TableSidebar.tsx +1 -1
  311. package/frontend/src/features/database/components/TablesEmptyState.tsx +48 -0
  312. package/frontend/src/features/database/components/TemplateCard.tsx +37 -0
  313. package/frontend/src/features/database/components/TemplatePreview.tsx +92 -0
  314. package/frontend/src/features/database/components/index.ts +19 -0
  315. package/frontend/src/features/database/constants.ts +28 -2
  316. package/frontend/src/features/database/contexts/SQLEditorContext.tsx +188 -0
  317. package/frontend/src/features/database/helpers.ts +2 -2
  318. package/frontend/src/features/database/hooks/useCSVImport.ts +29 -0
  319. package/frontend/src/features/database/hooks/useFullMetadata.ts +18 -0
  320. package/frontend/src/features/database/hooks/useRawSQL.ts +55 -0
  321. package/frontend/src/features/database/hooks/useRecords.ts +139 -0
  322. package/frontend/src/features/database/hooks/useTables.ts +131 -0
  323. package/frontend/src/features/database/index.ts +6 -1
  324. package/frontend/src/features/database/page/FunctionsPage.tsx +211 -0
  325. package/frontend/src/features/database/page/IndexesPage.tsx +240 -0
  326. package/frontend/src/features/database/page/PoliciesPage.tsx +248 -0
  327. package/frontend/src/features/database/page/SQLEditorPage.tsx +382 -0
  328. package/frontend/src/features/database/page/{DatabasePage.tsx → TablesPage.tsx} +186 -185
  329. package/frontend/src/features/database/page/TemplatesPage.tsx +39 -0
  330. package/frontend/src/features/database/page/TriggersPage.tsx +242 -0
  331. package/frontend/src/features/database/services/advance.service.ts +66 -0
  332. package/frontend/src/features/database/services/{database.service.ts → record.service.ts} +67 -64
  333. package/frontend/src/features/database/services/table.service.ts +64 -0
  334. package/frontend/src/features/database/templates/ai-chatbot.ts +402 -0
  335. package/frontend/src/features/database/templates/crm-system.ts +528 -0
  336. package/frontend/src/features/database/templates/ecommerce-platform.ts +553 -0
  337. package/frontend/src/features/database/templates/index.ts +34 -0
  338. package/frontend/src/features/database/templates/instagram-clone.ts +222 -0
  339. package/frontend/src/features/database/templates/notion-clone.ts +483 -0
  340. package/frontend/src/features/database/templates/reddit-clone.ts +526 -0
  341. package/frontend/src/features/functions/components/FunctionRow.tsx +2 -1
  342. package/frontend/src/features/functions/components/FunctionsSidebar.tsx +1 -1
  343. package/frontend/src/features/functions/components/SecretRow.tsx +1 -1
  344. package/frontend/src/features/functions/components/index.ts +5 -0
  345. package/frontend/src/features/functions/hooks/useFunctions.ts +4 -4
  346. package/frontend/src/features/{secrets → functions}/hooks/useSecrets.ts +5 -5
  347. package/frontend/src/features/functions/page/FunctionsPage.tsx +160 -17
  348. package/frontend/src/features/functions/{components/SecretsContent.tsx → page/SecretsPage.tsx} +8 -12
  349. package/frontend/src/features/functions/services/{functions.service.ts → function.service.ts} +2 -2
  350. package/frontend/src/features/{secrets/services/secrets.service.ts → functions/services/secret.service.ts} +2 -2
  351. package/frontend/src/features/login/hooks/usePartnerOrigin.ts +27 -0
  352. package/frontend/src/features/login/page/CloudLoginPage.tsx +79 -54
  353. package/frontend/src/features/login/page/LoginPage.tsx +16 -23
  354. package/frontend/src/features/login/services/partnership.service.ts +65 -0
  355. package/frontend/src/features/logs/components/LogsDataGrid.tsx +89 -0
  356. package/frontend/src/features/logs/components/SeverityBadge.tsx +18 -0
  357. package/frontend/src/features/logs/components/index.ts +2 -0
  358. package/frontend/src/features/logs/helpers.ts +24 -0
  359. package/frontend/src/features/logs/hooks/useAuditLogs.ts +4 -4
  360. package/frontend/src/features/logs/hooks/useLogSources.ts +137 -0
  361. package/frontend/src/features/logs/hooks/useLogs.ts +163 -0
  362. package/frontend/src/features/logs/hooks/useMcpUsage.ts +181 -0
  363. package/frontend/src/features/logs/index.ts +8 -2
  364. package/frontend/src/features/logs/page/AuditsPage.tsx +91 -38
  365. package/frontend/src/features/logs/page/LogsPage.tsx +152 -0
  366. package/frontend/src/features/logs/page/MCPLogsPage.tsx +84 -0
  367. package/frontend/src/features/logs/services/audit.service.ts +63 -0
  368. package/frontend/src/features/logs/services/log.service.ts +15 -110
  369. package/frontend/src/features/logs/services/usage.service.ts +31 -0
  370. package/frontend/src/features/onboard/components/McpConnectionStatus.tsx +68 -0
  371. package/frontend/src/features/onboard/components/OnboardingModal.tsx +267 -0
  372. package/frontend/src/features/onboard/components/VideoDemoModal.tsx +38 -0
  373. package/frontend/src/features/onboard/components/index.ts +4 -0
  374. package/frontend/src/features/onboard/components/mcp/CursorDeeplinkGenerator.tsx +2 -2
  375. package/frontend/src/features/onboard/components/mcp/{mcp-helper.tsx → helpers.tsx} +8 -8
  376. package/frontend/src/features/onboard/components/mcp/index.ts +2 -3
  377. package/frontend/src/features/onboard/index.ts +13 -3
  378. package/frontend/src/features/storage/components/BucketEmptyState.tsx +9 -6
  379. package/frontend/src/features/storage/components/BucketFormDialog.tsx +25 -41
  380. package/frontend/src/features/storage/components/FilePreviewDialog.tsx +20 -8
  381. package/frontend/src/features/storage/components/StorageDataGrid.tsx +4 -3
  382. package/frontend/src/features/storage/components/StorageManager.tsx +23 -34
  383. package/frontend/src/features/storage/components/index.ts +12 -0
  384. package/frontend/src/features/storage/hooks/useStorage.ts +208 -0
  385. package/frontend/src/features/storage/page/StoragePage.tsx +41 -115
  386. package/frontend/src/features/storage/services/storage.service.ts +22 -1
  387. package/frontend/src/features/visualizer/components/AuthNode.tsx +72 -56
  388. package/frontend/src/features/visualizer/components/BucketNode.tsx +4 -4
  389. package/frontend/src/features/visualizer/components/SchemaVisualizer.tsx +108 -80
  390. package/frontend/src/features/visualizer/components/TableNode.tsx +34 -41
  391. package/frontend/src/features/visualizer/components/VisualizerSkeleton.tsx +12 -4
  392. package/frontend/src/features/visualizer/page/VisualizerPage.tsx +33 -29
  393. package/frontend/src/index.css +1 -0
  394. package/frontend/src/lib/analytics/posthog.tsx +27 -0
  395. package/frontend/src/lib/contexts/AuthContext.tsx +38 -31
  396. package/frontend/src/lib/contexts/SocketContext.tsx +5 -6
  397. package/frontend/src/{features/metadata → lib}/hooks/useMetadata.ts +1 -1
  398. package/frontend/src/lib/hooks/useToast.tsx +6 -2
  399. package/frontend/src/lib/routing/AppRoutes.tsx +84 -0
  400. package/frontend/src/lib/routing/RequireAuth.tsx +27 -0
  401. package/frontend/src/lib/utils/cloudMessaging.ts +20 -0
  402. package/frontend/src/lib/utils/menuItems.ts +183 -0
  403. package/frontend/src/lib/utils/{validation-schemas.ts → schemaValidations.ts} +10 -5
  404. package/frontend/src/lib/utils/utils.ts +19 -1
  405. package/frontend/src/vite-env.d.ts +1 -0
  406. package/frontend/vite.config.ts +5 -3
  407. package/functions/server.ts +28 -3
  408. package/functions/worker-template.js +15 -4
  409. package/i18n/README.ar.md +130 -0
  410. package/i18n/README.de.md +130 -0
  411. package/i18n/README.es.md +154 -0
  412. package/i18n/README.fr.md +134 -0
  413. package/i18n/README.hi.md +129 -0
  414. package/i18n/README.ja.md +174 -0
  415. package/i18n/README.ko.md +137 -0
  416. package/i18n/README.pt-BR.md +131 -0
  417. package/i18n/README.ru.md +129 -0
  418. package/i18n/README.zh-CN.md +133 -0
  419. package/openapi/ai.yaml +31 -4
  420. package/openapi/auth.yaml +827 -146
  421. package/package.json +16 -7
  422. package/shared-schemas/package.json +1 -1
  423. package/shared-schemas/src/ai-api.schema.ts +34 -58
  424. package/shared-schemas/src/ai.schema.ts +5 -0
  425. package/shared-schemas/src/auth-api.schema.ts +154 -8
  426. package/shared-schemas/src/auth.schema.ts +42 -6
  427. package/shared-schemas/src/cloud-events.schema.ts +57 -0
  428. package/shared-schemas/src/database-api.schema.ts +3 -3
  429. package/shared-schemas/src/database.schema.ts +1 -1
  430. package/shared-schemas/src/index.ts +1 -0
  431. package/shared-schemas/src/logs-api.schema.ts +7 -1
  432. package/shared-schemas/src/logs.schema.ts +26 -0
  433. package/shared-schemas/src/metadata.schema.ts +9 -4
  434. package/test-gemini.sh +35 -0
  435. package/test-usage-admin.sh +57 -0
  436. package/test-usage.sh +50 -0
  437. package/zeabur/README.md +13 -0
  438. package/zeabur/template.yml +1032 -0
  439. package/.github/workflows/deploy-aws.yml +0 -130
  440. package/backend/src/api/routes/agent.ts +0 -29
  441. package/backend/src/api/routes/auth.oauth.ts +0 -482
  442. package/backend/src/api/routes/auth.ts +0 -386
  443. package/backend/src/api/routes/docs.ts +0 -66
  444. package/backend/src/api/routes/functions.ts +0 -183
  445. package/backend/src/api/routes/openapi.ts +0 -82
  446. package/backend/src/api/routes/usage.ts +0 -96
  447. package/backend/src/core/ai/client.ts +0 -242
  448. package/backend/src/core/ai/model.ts +0 -117
  449. package/backend/src/core/auth/auth.ts +0 -781
  450. package/backend/src/core/database/table.ts +0 -772
  451. package/backend/src/core/documentation/agent.ts +0 -689
  452. package/backend/src/core/documentation/openapi.ts +0 -856
  453. package/backend/src/core/logs/analytics.ts +0 -76
  454. package/backend/src/core/logs/providers/localdb.provider.ts +0 -246
  455. package/backend/src/core/storage/storage.ts +0 -923
  456. package/backend/src/utils/cloud-token.ts +0 -39
  457. package/backend/src/utils/helpers.ts +0 -49
  458. package/backend/src/utils/uuid.ts +0 -9
  459. package/backend/tests/manual/test-better-auth.sh +0 -303
  460. package/docker-init/db/logs.sql +0 -9
  461. package/frontend/README.md +0 -112
  462. package/frontend/src/components/datagrid/index.tsx +0 -20
  463. package/frontend/src/components/layout/CloudLayout.tsx +0 -95
  464. package/frontend/src/features/ai/components/AIConfigDialog.tsx +0 -76
  465. package/frontend/src/features/ai/components/AIConfigForm.tsx +0 -222
  466. package/frontend/src/features/ai/components/fields/ModalityField.tsx +0 -87
  467. package/frontend/src/features/ai/components/fields/ModelSelectionField.tsx +0 -134
  468. package/frontend/src/features/ai/components/fields/SystemPromptField.tsx +0 -33
  469. package/frontend/src/features/auth/components/AddOAuthDialog.tsx +0 -106
  470. package/frontend/src/features/auth/components/AuthMethodTab.tsx +0 -238
  471. package/frontend/src/features/auth/components/UsersTab.tsx +0 -114
  472. package/frontend/src/features/auth/page/AuthenticationPage.tsx +0 -169
  473. package/frontend/src/features/database/hooks/UseLinkModal.tsx +0 -78
  474. package/frontend/src/features/functions/components/FunctionViewer.tsx +0 -46
  475. package/frontend/src/features/functions/components/FunctionsContent.tsx +0 -88
  476. package/frontend/src/features/login/components/AuthErrorBoundary.tsx +0 -87
  477. package/frontend/src/features/login/components/PrivateRoute.tsx +0 -24
  478. package/frontend/src/features/logs/components/AnalyticsLogsTable.tsx +0 -313
  479. package/frontend/src/features/logs/components/LogsTable.tsx +0 -199
  480. package/frontend/src/features/logs/page/AnalyticsLogsPage.tsx +0 -530
  481. package/frontend/src/features/metadata/index.ts +0 -0
  482. package/frontend/src/features/metadata/page/MetadataPage.tsx +0 -136
  483. package/frontend/src/features/onboard/components/CompletionCard.tsx +0 -41
  484. package/frontend/src/features/onboard/components/OnboardButton.tsx +0 -84
  485. package/frontend/src/features/onboard/components/StepContent.tsx +0 -91
  486. package/frontend/src/features/onboard/components/TestConnectionStep.tsx +0 -53
  487. package/frontend/src/features/onboard/components/mcp/McpInstallation.tsx +0 -144
  488. package/frontend/src/features/onboard/page/OnBoardPage.tsx +0 -104
  489. package/frontend/src/features/onboard/types.ts +0 -8
  490. package/frontend/src/lib/contexts/OnboardStepContext.tsx +0 -68
  491. package/frontend/src/lib/hooks/useOnboardingCompletion.ts +0 -29
  492. /package/backend/src/api/{middleware → middlewares}/error.ts +0 -0
  493. /package/backend/src/api/{middleware → middlewares}/upload.ts +0 -0
  494. /package/backend/{migrations → src/infra/database/migrations}/000_create-base-tables.sql +0 -0
  495. /package/backend/{migrations → src/infra/database/migrations}/001_create-helper-functions.sql +0 -0
  496. /package/backend/{migrations → src/infra/database/migrations}/002_rename-auth-tables.sql +0 -0
  497. /package/backend/{migrations → src/infra/database/migrations}/003_create-users-table.sql +0 -0
  498. /package/backend/{migrations → src/infra/database/migrations}/004_add-reload-postgrest-func.sql +0 -0
  499. /package/backend/{migrations → src/infra/database/migrations}/005_enable-project-admin-modify-users.sql +0 -0
  500. /package/backend/{migrations → src/infra/database/migrations}/006_modify-ai-usage-table.sql +0 -0
  501. /package/backend/{migrations → src/infra/database/migrations}/007_drop-metadata-table.sql +0 -0
  502. /package/backend/{migrations → src/infra/database/migrations}/008_add-system-tables.sql +0 -0
  503. /package/backend/{migrations → src/infra/database/migrations}/009_add-function-secrets.sql +0 -0
  504. /package/backend/{migrations → src/infra/database/migrations}/010_modify-ai-config-modalities.sql +0 -0
  505. /package/backend/{migrations → src/infra/database/migrations}/011_refactor-secrets-table.sql +0 -0
  506. /package/backend/{migrations → src/infra/database/migrations}/012_add-storage-uploaded-by.sql +0 -0
  507. /package/frontend/src/{features/metadata → lib}/services/metadata.service.ts +0 -0
@@ -0,0 +1,41 @@
1
+ import { EmailTemplate } from '@/types/email.js';
2
+
3
+ /**
4
+ * Email provider interface
5
+ * Defines the contract that all email providers must implement
6
+ */
7
+ export interface EmailProvider {
8
+ /**
9
+ * Initialize the email provider (optional)
10
+ */
11
+ initialize?(): void | Promise<void>;
12
+
13
+ /**
14
+ * Send email using predefined template
15
+ * @param email - Recipient email address
16
+ * @param name - Recipient name
17
+ * @param template - Template type
18
+ * @param variables - Variables to use in the email template
19
+ */
20
+ sendWithTemplate(
21
+ email: string,
22
+ name: string,
23
+ template: EmailTemplate,
24
+ variables?: Record<string, string>
25
+ ): Promise<void>;
26
+
27
+ /**
28
+ * Send raw email with custom subject and body
29
+ * Optional - not all providers may support this
30
+ * @param to - Recipient email address
31
+ * @param subject - Email subject
32
+ * @param html - HTML email body
33
+ * @param text - Plain text email body (optional)
34
+ */
35
+ sendRaw?(to: string, subject: string, html: string, text?: string): Promise<void>;
36
+
37
+ /**
38
+ * Check if provider supports template-based emails
39
+ */
40
+ supportsTemplates(): boolean;
41
+ }
@@ -0,0 +1,187 @@
1
+ import jwt from 'jsonwebtoken';
2
+ import axios from 'axios';
3
+ import { config } from '@/infra/config/app.config.js';
4
+ import logger from '@/utils/logger.js';
5
+ import { AppError } from '@/api/middlewares/error.js';
6
+ import { ERROR_CODES } from '@/types/error-constants.js';
7
+ import { EmailTemplate } from '@/types/email.js';
8
+ import { EmailProvider } from './base.provider.js';
9
+
10
+ /**
11
+ * Cloud email provider for sending emails via Insforge cloud backend
12
+ */
13
+ export class CloudEmailProvider implements EmailProvider {
14
+ /**
15
+ * Generate JWT sign token for cloud API authentication
16
+ * @returns JWT token signed with project secret
17
+ */
18
+ private generateSignToken(): string {
19
+ const projectId = config.cloud.projectId;
20
+ const jwtSecret = config.app.jwtSecret;
21
+
22
+ if (!projectId || projectId === 'local') {
23
+ throw new AppError(
24
+ 'PROJECT_ID is not configured. Cannot send emails without cloud project setup.',
25
+ 500,
26
+ ERROR_CODES.INTERNAL_ERROR
27
+ );
28
+ }
29
+
30
+ if (!jwtSecret) {
31
+ throw new AppError(
32
+ 'JWT_SECRET is not configured. Cannot generate sign token.',
33
+ 500,
34
+ ERROR_CODES.INTERNAL_ERROR
35
+ );
36
+ }
37
+
38
+ const payload = {
39
+ sub: projectId,
40
+ };
41
+
42
+ return jwt.sign(payload, jwtSecret, {
43
+ expiresIn: '10m', // Short-lived token for API request
44
+ });
45
+ }
46
+
47
+ /**
48
+ * Check if provider supports templates
49
+ */
50
+ supportsTemplates(): boolean {
51
+ return true;
52
+ }
53
+
54
+ /**
55
+ * Send email using predefined template
56
+ * @param email - Recipient email address
57
+ * @param name - Recipient name
58
+ * @param template - Template type (email-verification or reset-password)
59
+ * @param variables - Variables to use in the email template
60
+ * @returns Promise that resolves when email is sent successfully
61
+ */
62
+ async sendWithTemplate(
63
+ email: string,
64
+ name: string,
65
+ template: EmailTemplate,
66
+ variables?: Record<string, string>
67
+ ): Promise<void> {
68
+ try {
69
+ const projectId = config.cloud.projectId;
70
+ const apiHost = config.cloud.apiHost;
71
+ const signToken = this.generateSignToken();
72
+
73
+ // Validate inputs
74
+ if (!email || !name || !template) {
75
+ throw new AppError(
76
+ 'Missing required parameters for sending email',
77
+ 400,
78
+ ERROR_CODES.INVALID_INPUT
79
+ );
80
+ }
81
+
82
+ const validTemplates: EmailTemplate[] = [
83
+ 'email-verification-code',
84
+ 'email-verification-link',
85
+ 'reset-password-code',
86
+ 'reset-password-link',
87
+ ];
88
+ if (!validTemplates.includes(template)) {
89
+ throw new AppError(
90
+ `Invalid template type: ${template}. Must be one of: ${validTemplates.join(', ')}`,
91
+ 400,
92
+ ERROR_CODES.INVALID_INPUT
93
+ );
94
+ }
95
+
96
+ const url = `${apiHost}/email/v1/${projectId}/send-with-template`;
97
+ const response = await axios.post(
98
+ url,
99
+ {
100
+ email,
101
+ name,
102
+ template,
103
+ variables,
104
+ },
105
+ {
106
+ headers: {
107
+ 'Content-Type': 'application/json',
108
+ sign: signToken,
109
+ },
110
+ timeout: 10000, // 10 second timeout
111
+ }
112
+ );
113
+
114
+ if (response.data?.success) {
115
+ logger.info('Email sent successfully', {
116
+ projectId,
117
+ template,
118
+ });
119
+ } else {
120
+ throw new AppError(
121
+ 'Email service returned unsuccessful response',
122
+ 500,
123
+ ERROR_CODES.INTERNAL_ERROR
124
+ );
125
+ }
126
+ } catch (error) {
127
+ // Handle axios errors
128
+ if (axios.isAxiosError(error)) {
129
+ const status = error.response?.status;
130
+ const message = error.response?.data?.message || error.message;
131
+
132
+ logger.error('Failed to send email via cloud backend', {
133
+ projectId: config.cloud.projectId,
134
+ template,
135
+ status,
136
+ message,
137
+ error: error.response?.data,
138
+ });
139
+
140
+ // Provide more specific error messages
141
+ if (status === 401 || status === 403) {
142
+ throw new AppError(
143
+ 'Authentication failed with cloud email service. Check PROJECT_ID and JWT_SECRET.',
144
+ status,
145
+ ERROR_CODES.AUTH_UNAUTHORIZED
146
+ );
147
+ } else if (status === 429) {
148
+ throw new AppError(
149
+ 'Email rate limit exceeded. Free plans are limited to 3000 emails per month.',
150
+ status,
151
+ ERROR_CODES.RATE_LIMITED
152
+ );
153
+ } else if (status === 400) {
154
+ throw new AppError(
155
+ `Invalid email request: ${message}`,
156
+ status,
157
+ ERROR_CODES.INVALID_INPUT
158
+ );
159
+ } else {
160
+ throw new AppError(
161
+ `Failed to send email: ${message}`,
162
+ status || 500,
163
+ ERROR_CODES.INTERNAL_ERROR
164
+ );
165
+ }
166
+ }
167
+
168
+ // Re-throw AppError
169
+ if (error instanceof AppError) {
170
+ throw error;
171
+ }
172
+
173
+ // Handle other errors
174
+ logger.error('Unexpected error sending email', {
175
+ projectId: config.cloud.projectId,
176
+ template,
177
+ error: error instanceof Error ? error.message : 'Unknown error',
178
+ });
179
+
180
+ throw new AppError(
181
+ `Failed to send email: ${error instanceof Error ? error.message : 'Unknown error'}`,
182
+ 500,
183
+ ERROR_CODES.INTERNAL_ERROR
184
+ );
185
+ }
186
+ }
187
+ }
@@ -1,21 +1,21 @@
1
- import { LogSource, AnalyticsLogRecord, LogSourceStats } from '@/types/logs.js';
1
+ import { LogSchema, LogSourceSchema, LogStatsSchema } from '@insforge/shared-schemas';
2
2
 
3
- export interface AnalyticsProvider {
3
+ export interface LogProvider {
4
4
  initialize(): Promise<void>;
5
5
 
6
- getLogSources(): Promise<LogSource[]>;
6
+ getLogSources(): Promise<LogSourceSchema[]>;
7
7
 
8
8
  getLogsBySource(
9
9
  sourceName: string,
10
10
  limit?: number,
11
11
  beforeTimestamp?: string
12
12
  ): Promise<{
13
- logs: AnalyticsLogRecord[];
13
+ logs: LogSchema[];
14
14
  total: number;
15
15
  tableName: string;
16
16
  }>;
17
17
 
18
- getLogSourceStats(): Promise<LogSourceStats[]>;
18
+ getLogSourceStats(): Promise<LogStatsSchema[]>;
19
19
 
20
20
  searchLogs(
21
21
  query: string,
@@ -23,7 +23,7 @@ export interface AnalyticsProvider {
23
23
  limit?: number,
24
24
  offset?: number
25
25
  ): Promise<{
26
- logs: (AnalyticsLogRecord & { source: string })[];
26
+ logs: (LogSchema & { source: string })[];
27
27
  total: number;
28
28
  }>;
29
29
 
@@ -31,7 +31,7 @@ export interface AnalyticsProvider {
31
31
  }
32
32
 
33
33
  // Base class with common functionality
34
- export abstract class BaseAnalyticsProvider implements AnalyticsProvider {
34
+ export abstract class BaseLogProvider implements LogProvider {
35
35
  // Source name mapping for user-friendly display
36
36
  protected sourceNameMap: Record<string, string> = {
37
37
  'cloudflare.logs.prod': 'insforge.logs',
@@ -59,24 +59,24 @@ export abstract class BaseAnalyticsProvider implements AnalyticsProvider {
59
59
  }
60
60
 
61
61
  abstract initialize(): Promise<void>;
62
- abstract getLogSources(): Promise<LogSource[]>;
62
+ abstract getLogSources(): Promise<LogSourceSchema[]>;
63
63
  abstract getLogsBySource(
64
64
  sourceName: string,
65
65
  limit?: number,
66
66
  beforeTimestamp?: string
67
67
  ): Promise<{
68
- logs: AnalyticsLogRecord[];
68
+ logs: LogSchema[];
69
69
  total: number;
70
70
  tableName: string;
71
71
  }>;
72
- abstract getLogSourceStats(): Promise<LogSourceStats[]>;
72
+ abstract getLogSourceStats(): Promise<LogStatsSchema[]>;
73
73
  abstract searchLogs(
74
74
  query: string,
75
75
  sourceName?: string,
76
76
  limit?: number,
77
77
  offset?: number
78
78
  ): Promise<{
79
- logs: (AnalyticsLogRecord & { source: string })[];
79
+ logs: (LogSchema & { source: string })[];
80
80
  total: number;
81
81
  }>;
82
82
  abstract close(): Promise<void>;
@@ -4,23 +4,23 @@ import {
4
4
  FilterLogEventsCommand,
5
5
  StartQueryCommand,
6
6
  GetQueryResultsCommand,
7
+ CreateLogGroupCommand,
8
+ ResourceAlreadyExistsException,
7
9
  } from '@aws-sdk/client-cloudwatch-logs';
8
- import { LogSource, AnalyticsLogRecord, LogSourceStats } from '@/types/logs.js';
9
10
  import logger from '@/utils/logger.js';
10
- import { BaseAnalyticsProvider } from './base.provider.js';
11
+ import { BaseLogProvider } from './base.provider.js';
12
+ import { AppError } from '@/api/middlewares/error.js';
13
+ import { ERROR_CODES } from '@/types/error-constants.js';
14
+ import { LogSchema, LogSourceSchema, LogStatsSchema } from '@insforge/shared-schemas';
11
15
 
12
- export class CloudWatchProvider extends BaseAnalyticsProvider {
16
+ export class CloudWatchProvider extends BaseLogProvider {
13
17
  private cwClient: CloudWatchLogsClient | null = null;
14
18
  private cwLogGroup: string | null = null;
15
19
  private cwRegion: string | null = null;
16
20
 
17
- initialize(): Promise<void> {
21
+ async initialize(): Promise<void> {
18
22
  this.cwRegion = process.env.AWS_REGION || process.env.AWS_DEFAULT_REGION || 'us-east-2';
19
- this.cwLogGroup = process.env.CLOUDWATCH_LOG_GROUP || null;
20
-
21
- if (!this.cwLogGroup) {
22
- throw new Error('CLOUDWATCH_LOG_GROUP is required when using CloudWatch analytics');
23
- }
23
+ this.cwLogGroup = process.env.CLOUDWATCH_LOG_GROUP || '/insforge/local';
24
24
 
25
25
  const cloudwatchOpts: {
26
26
  region: string;
@@ -34,8 +34,18 @@ export class CloudWatchProvider extends BaseAnalyticsProvider {
34
34
  }
35
35
 
36
36
  this.cwClient = new CloudWatchLogsClient({ ...cloudwatchOpts });
37
- logger.info(`Using analytics provider: ${this.cwLogGroup ? 'CloudWatch' : 'LocalDB/Postgres'}`);
38
- return Promise.resolve();
37
+
38
+ // Create log group if it doesn't exist
39
+ try {
40
+ await this.cwClient.send(new CreateLogGroupCommand({ logGroupName: this.cwLogGroup }));
41
+ logger.info(`Created CloudWatch log group: ${this.cwLogGroup}`);
42
+ } catch (error) {
43
+ if (error instanceof ResourceAlreadyExistsException) {
44
+ logger.info(`CloudWatch log group already exists: ${this.cwLogGroup}`);
45
+ } else {
46
+ logger.warn(`Could not create CloudWatch log group: ${error}`);
47
+ }
48
+ }
39
49
  }
40
50
 
41
51
  private getSuffixMapping(): Record<string, string> {
@@ -47,9 +57,13 @@ export class CloudWatchProvider extends BaseAnalyticsProvider {
47
57
  };
48
58
  }
49
59
 
50
- async getLogSources(): Promise<LogSource[]> {
60
+ async getLogSources(): Promise<LogSourceSchema[]> {
51
61
  if (!this.cwLogGroup || !this.cwClient) {
52
- throw new Error('CloudWatch not initialized');
62
+ throw new AppError(
63
+ 'AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY not found in environment variables',
64
+ 500,
65
+ ERROR_CODES.LOGS_AWS_NOT_CONFIGURED
66
+ );
53
67
  }
54
68
  const logGroup = this.cwLogGroup;
55
69
  const client = this.cwClient;
@@ -59,13 +73,13 @@ export class CloudWatchProvider extends BaseAnalyticsProvider {
59
73
  const result = await client.send(cmd);
60
74
  const streams = result.logStreams || [];
61
75
 
62
- const available: LogSource[] = [];
76
+ const available: LogSourceSchema[] = [];
63
77
  let idCounter = 1;
64
78
 
65
79
  for (const [displayName, suffix] of Object.entries(suffixMapping)) {
66
80
  const have = streams.some((s) => (s.logStreamName || '').includes(suffix));
67
81
  if (have) {
68
- available.push({ id: idCounter++, name: displayName, token: suffix });
82
+ available.push({ id: String(idCounter++), name: displayName, token: suffix });
69
83
  }
70
84
  }
71
85
 
@@ -77,12 +91,16 @@ export class CloudWatchProvider extends BaseAnalyticsProvider {
77
91
  limit: number = 100,
78
92
  beforeTimestamp?: string
79
93
  ): Promise<{
80
- logs: AnalyticsLogRecord[];
94
+ logs: LogSchema[];
81
95
  total: number;
82
96
  tableName: string;
83
97
  }> {
84
98
  if (!this.cwLogGroup || !this.cwClient) {
85
- throw new Error('CloudWatch not initialized');
99
+ throw new AppError(
100
+ 'AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY not found in environment variables',
101
+ 500,
102
+ ERROR_CODES.LOGS_AWS_NOT_CONFIGURED
103
+ );
86
104
  }
87
105
  const client = this.cwClient;
88
106
  const logGroup = this.cwLogGroup;
@@ -127,7 +145,7 @@ export class CloudWatchProvider extends BaseAnalyticsProvider {
127
145
  const fle = await client.send(
128
146
  new FilterLogEventsCommand({
129
147
  logGroupName: logGroup,
130
- logStreamNames: streams.length > 0 ? streams.slice(0, 100) : undefined,
148
+ logStreamNames: streams.length ? streams.slice(0, 100) : undefined,
131
149
  startTime: startMs,
132
150
  endTime: endMs,
133
151
  nextToken,
@@ -185,7 +203,7 @@ export class CloudWatchProvider extends BaseAnalyticsProvider {
185
203
  await sleep(300);
186
204
  }
187
205
 
188
- if (results && results.length > 0) {
206
+ if (results && results.length) {
189
207
  // Convert Insights results to our format
190
208
  events = results.map((row) => {
191
209
  const obj = Object.fromEntries(row.map((c) => [c.field || '', c.value || '']));
@@ -225,7 +243,7 @@ export class CloudWatchProvider extends BaseAnalyticsProvider {
225
243
  const fle = await client.send(
226
244
  new FilterLogEventsCommand({
227
245
  logGroupName: logGroup,
228
- logStreamNames: streams.length > 0 ? streams.slice(0, 100) : undefined,
246
+ logStreamNames: streams.length ? streams.slice(0, 100) : undefined,
229
247
  startTime: fallbackStartMs,
230
248
  endTime: beforeMs,
231
249
  limit: limit * 2, // Get a bit more to ensure we have enough
@@ -238,7 +256,7 @@ export class CloudWatchProvider extends BaseAnalyticsProvider {
238
256
  }
239
257
  }
240
258
  // Keep CloudWatch's default order (oldest first, newest last)
241
- const logs: AnalyticsLogRecord[] = events.map((e) => {
259
+ const logs: LogSchema[] = events.map((e) => {
242
260
  const message = e.message || '';
243
261
  let parsed: Record<string, unknown> = {};
244
262
  try {
@@ -251,7 +269,7 @@ export class CloudWatchProvider extends BaseAnalyticsProvider {
251
269
  id: e.eventId || `${e.logStreamName || ''}-${e.timestamp || ''}`,
252
270
  // CloudWatch timestamp is in milliseconds
253
271
  timestamp: e.timestamp ? new Date(e.timestamp).toISOString() : new Date().toISOString(),
254
- event_message:
272
+ eventMessage:
255
273
  typeof parsed === 'object' && parsed && (parsed as Record<string, unknown>).msg
256
274
  ? String((parsed as Record<string, unknown>).msg)
257
275
  : typeof message === 'string'
@@ -268,14 +286,18 @@ export class CloudWatchProvider extends BaseAnalyticsProvider {
268
286
  };
269
287
  }
270
288
 
271
- async getLogSourceStats(): Promise<LogSourceStats[]> {
289
+ async getLogSourceStats(): Promise<LogStatsSchema[]> {
272
290
  if (!this.cwLogGroup || !this.cwClient) {
273
- throw new Error('CloudWatch not initialized');
291
+ throw new AppError(
292
+ 'AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY not found in environment variables',
293
+ 500,
294
+ ERROR_CODES.LOGS_AWS_NOT_CONFIGURED
295
+ );
274
296
  }
275
297
  const client = this.cwClient;
276
298
  const logGroup = this.cwLogGroup;
277
299
  const sources = await this.getLogSources();
278
- const stats: LogSourceStats[] = [];
300
+ const stats: LogStatsSchema[] = [];
279
301
  const suffixMapping = this.getSuffixMapping();
280
302
 
281
303
  const dls = await client.send(new DescribeLogStreamsCommand({ logGroupName: logGroup }));
@@ -289,7 +311,7 @@ export class CloudWatchProvider extends BaseAnalyticsProvider {
289
311
 
290
312
  let lastActivity = '';
291
313
 
292
- if (sourceStreams.length > 0) {
314
+ if (sourceStreams.length) {
293
315
  try {
294
316
  // Use EXACTLY the same approach as getLogsBySource to get consistent results
295
317
  const endMs = Date.now();
@@ -297,16 +319,13 @@ export class CloudWatchProvider extends BaseAnalyticsProvider {
297
319
 
298
320
  // Use CloudWatch Insights to efficiently get the latest timestamp
299
321
  try {
300
- const end = Date.now();
301
- const start = end - 24 * 60 * 60 * 1000; // Last 24 hours
302
-
303
322
  const insights = `fields @timestamp | filter @logStream like /${suffix}/ | sort @timestamp desc | limit 1`;
304
323
 
305
324
  const startQuery = await client.send(
306
325
  new StartQueryCommand({
307
326
  logGroupName: logGroup,
308
- startTime: Math.floor(start / 1000),
309
- endTime: Math.floor(end / 1000),
327
+ startTime: Math.floor(startMs / 1000),
328
+ endTime: Math.floor(endMs / 1000),
310
329
  queryString: insights,
311
330
  limit: 1,
312
331
  })
@@ -326,7 +345,7 @@ export class CloudWatchProvider extends BaseAnalyticsProvider {
326
345
  await sleep(200);
327
346
  }
328
347
 
329
- if (results && results.length > 0) {
348
+ if (results && results.length) {
330
349
  const row = results[0];
331
350
  const timestampField = row.find((field) => field.field === '@timestamp');
332
351
  if (timestampField && timestampField.value) {
@@ -357,7 +376,7 @@ export class CloudWatchProvider extends BaseAnalyticsProvider {
357
376
  const fle = await client.send(
358
377
  new FilterLogEventsCommand({
359
378
  logGroupName: logGroup,
360
- logStreamNames: sourceStreams.length > 0 ? sourceStreams.slice(0, 100) : undefined,
379
+ logStreamNames: sourceStreams.length ? sourceStreams.slice(0, 100) : undefined,
361
380
  startTime: startMs,
362
381
  endTime: endMs,
363
382
  limit: 1000, // Reasonable limit for fallback
@@ -365,7 +384,7 @@ export class CloudWatchProvider extends BaseAnalyticsProvider {
365
384
  );
366
385
 
367
386
  const events = fle.events || [];
368
- if (events.length > 0) {
387
+ if (events.length) {
369
388
  const latestEvent = events[events.length - 1];
370
389
  if (latestEvent.timestamp) {
371
390
  lastActivity = new Date(latestEvent.timestamp).toISOString();
@@ -409,11 +428,15 @@ export class CloudWatchProvider extends BaseAnalyticsProvider {
409
428
  limit: number = 100,
410
429
  _offset = 0 // CloudWatch doesn't support offset-based pagination
411
430
  ): Promise<{
412
- logs: (AnalyticsLogRecord & { source: string })[];
431
+ logs: (LogSchema & { source: string })[];
413
432
  total: number;
414
433
  }> {
415
434
  if (!this.cwLogGroup || !this.cwClient) {
416
- throw new Error('CloudWatch not initialized');
435
+ throw new AppError(
436
+ 'AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY not found in environment variables',
437
+ 500,
438
+ ERROR_CODES.LOGS_AWS_NOT_CONFIGURED
439
+ );
417
440
  }
418
441
  const client = this.cwClient;
419
442
  const logGroup = this.cwLogGroup;
@@ -462,7 +485,7 @@ export class CloudWatchProvider extends BaseAnalyticsProvider {
462
485
  const toObj = (row: Array<{ field?: string; value?: string }>) =>
463
486
  Object.fromEntries(row.map((c) => [c.field || '', c.value || '']));
464
487
 
465
- const mapped: (AnalyticsLogRecord & { source: string })[] = rows.map((r) => {
488
+ const mapped: (LogSchema & { source: string })[] = rows.map((r) => {
466
489
  const o = toObj(r);
467
490
  const msg = o['@message'] || '';
468
491
  let parsed: Record<string, unknown> = {};
@@ -487,7 +510,7 @@ export class CloudWatchProvider extends BaseAnalyticsProvider {
487
510
  timestamp: o['@timestamp']
488
511
  ? new Date(parseInt(o['@timestamp'])).toISOString()
489
512
  : new Date().toISOString(),
490
- event_message:
513
+ eventMessage:
491
514
  typeof parsed === 'object' && (parsed as Record<string, unknown>).msg
492
515
  ? String((parsed as Record<string, unknown>).msg)
493
516
  : typeof msg === 'string'