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.
- package/.claude-plugin/marketplace.json +20 -0
- package/.cursor/rules/cursor-rules.mdc +94 -0
- package/.dockerignore +3 -0
- package/.env.example +33 -4
- package/.github/ISSUE_TEMPLATE/bug_report.yml +13 -60
- package/.github/ISSUE_TEMPLATE/config.yml +2 -2
- package/.github/ISSUE_TEMPLATE/feature_request.yml +10 -63
- package/.github/PULL_REQUEST_TEMPLATE.md +7 -0
- package/.github/workflows/build-image.yml +2 -1
- package/.github/workflows/e2e.yml +63 -0
- package/CHANGELOG.md +41 -0
- package/CLAUDE_PLUGIN.md +104 -0
- package/CODE_OF_CONDUCT.md +128 -0
- package/CONTRIBUTING.md +1 -1
- package/Dockerfile +4 -1
- package/README.md +66 -18
- package/assets/mcpInstallv2.png +0 -0
- package/assets/sampleResponse.png +0 -0
- package/auth/index.html +13 -0
- package/auth/package.json +28 -0
- package/auth/public/favicon.ico +0 -0
- package/auth/src/App.tsx +33 -0
- package/auth/src/components/ErrorCard.tsx +37 -0
- package/auth/src/components/Layout.tsx +13 -0
- package/auth/src/index.css +19 -0
- package/auth/src/lib/broadcastService.ts +115 -0
- package/auth/src/lib/utils.ts +11 -0
- package/auth/src/main.tsx +22 -0
- package/auth/src/pages/ForgotPasswordPage.tsx +11 -0
- package/auth/src/pages/ResetPasswordPage.tsx +11 -0
- package/auth/src/pages/SignInPage.tsx +57 -0
- package/auth/src/pages/SignUpPage.tsx +57 -0
- package/auth/src/pages/VerifyEmailPage.tsx +20 -0
- package/auth/src/vite-env.d.ts +10 -0
- package/auth/tsconfig.json +32 -0
- package/auth/tsconfig.node.json +11 -0
- package/auth/vite.config.ts +25 -0
- package/backend/package.json +9 -9
- package/backend/src/api/{middleware → middlewares}/auth.ts +8 -9
- package/backend/src/api/middlewares/rate-limiters.ts +127 -0
- package/backend/src/api/routes/{ai.ts → ai/index.routes.ts} +20 -24
- package/backend/src/api/routes/auth/index.routes.ts +570 -0
- package/backend/src/api/routes/auth/oauth.routes.ts +448 -0
- package/backend/src/api/routes/{database.advance.ts → database/advance.routes.ts} +107 -65
- package/backend/src/api/routes/database/index.routes.ts +13 -0
- package/backend/src/api/routes/{database.records.ts → database/records.routes.ts} +22 -8
- package/backend/src/api/routes/{database.tables.ts → database/tables.routes.ts} +20 -23
- package/backend/src/api/routes/docs/index.routes.ts +76 -0
- package/backend/src/api/routes/functions/index.routes.ts +188 -0
- package/backend/src/api/routes/{logs.ts → logs/index.routes.ts} +25 -30
- package/backend/src/api/routes/{metadata.ts → metadata/index.routes.ts} +21 -31
- package/backend/src/api/routes/{secrets.ts → secrets/index.routes.ts} +27 -22
- package/backend/src/api/routes/{storage.ts → storage/index.routes.ts} +34 -53
- package/backend/src/api/routes/usage/index.routes.ts +89 -0
- package/backend/src/infra/config/app.config.ts +51 -0
- package/backend/src/{core/database/manager.ts → infra/database/database.manager.ts} +76 -85
- package/backend/src/infra/database/migrations/013_create-auth-schema-functions.sql +44 -0
- package/backend/src/infra/database/migrations/014_add-updated-at-trigger-user-table.sql +8 -0
- package/backend/src/infra/database/migrations/015_create-auth-config-and-email-otp-tables.sql +60 -0
- package/backend/src/infra/database/migrations/016_update-auth-config-and-email-otp.sql +24 -0
- package/backend/src/{core/secrets/encryption.ts → infra/security/encryption.manager.ts} +3 -2
- package/backend/src/infra/security/token.manager.ts +125 -0
- package/backend/src/{core/socket/socket.ts → infra/socket/socket.manager.ts} +15 -15
- package/backend/src/providers/ai/openrouter.provider.ts +377 -0
- package/backend/src/providers/email/base.provider.ts +41 -0
- package/backend/src/providers/email/cloud.provider.ts +187 -0
- package/backend/src/{core/logs/providers → providers/logs}/base.provider.ts +11 -11
- package/backend/src/{core/logs/providers → providers/logs}/cloudwatch.provider.ts +61 -38
- package/backend/src/providers/logs/local.provider.ts +185 -0
- package/backend/src/providers/oauth/base.provider.ts +29 -0
- package/backend/src/providers/oauth/discord.provider.ts +195 -0
- package/backend/src/providers/oauth/facebook.provider.ts +194 -0
- package/backend/src/providers/oauth/github.provider.ts +208 -0
- package/backend/src/providers/oauth/google.provider.ts +249 -0
- package/backend/src/providers/oauth/index.ts +7 -0
- package/backend/src/providers/oauth/linkedin.provider.ts +240 -0
- package/backend/src/providers/oauth/microsoft.provider.ts +169 -0
- package/backend/src/providers/oauth/x.provider.ts +202 -0
- package/backend/src/providers/storage/base.provider.ts +29 -0
- package/backend/src/providers/storage/local.provider.ts +103 -0
- package/backend/src/providers/storage/s3.provider.ts +313 -0
- package/backend/src/server.ts +70 -74
- package/backend/src/{core/ai/config.ts → services/ai/ai-config.service.ts} +19 -24
- package/backend/src/services/ai/ai-model.service.ts +60 -0
- package/backend/src/{core/ai/usage.ts → services/ai/ai-usage.service.ts} +28 -35
- package/backend/src/{core/ai/chat.ts → services/ai/chat-completion.service.ts} +37 -24
- package/backend/src/services/ai/helpers.ts +64 -0
- package/backend/src/{core/ai/image.ts → services/ai/image-generation.service.ts} +17 -19
- package/backend/src/services/ai/index.ts +13 -0
- package/backend/src/services/auth/auth-config.service.ts +250 -0
- package/backend/src/services/auth/auth-otp.service.ts +424 -0
- package/backend/src/services/auth/auth.service.ts +1136 -0
- package/backend/src/services/auth/index.ts +4 -0
- package/backend/src/{core/auth/oauth.ts → services/auth/oauth-config.service.ts} +106 -52
- package/backend/src/{core/database/advance.ts → services/database/database-advance.service.ts} +97 -131
- package/backend/src/services/database/database-table.service.ts +811 -0
- package/backend/src/services/email/email.service.ts +75 -0
- package/backend/src/{core/functions/functions.ts → services/functions/function.service.ts} +95 -88
- package/backend/src/{core/logs/audit.ts → services/logs/audit.service.ts} +92 -75
- package/backend/src/services/logs/log.service.ts +73 -0
- package/backend/src/{core/secrets/secrets.ts → services/secrets/secret.service.ts} +48 -66
- package/backend/src/services/storage/storage.service.ts +617 -0
- package/backend/src/services/usage/usage.service.ts +149 -0
- package/backend/src/types/auth.ts +66 -2
- package/backend/src/types/email.ts +8 -0
- package/backend/src/types/error-constants.ts +4 -0
- package/backend/src/types/logs.ts +0 -29
- package/backend/src/{core/socket/types.ts → types/socket.ts} +5 -6
- package/backend/src/utils/environment.ts +9 -3
- package/backend/src/utils/logger.ts +20 -2
- package/backend/src/utils/seed.ts +150 -57
- package/backend/src/utils/sql-parser.ts +1 -1
- package/backend/src/utils/utils.ts +114 -0
- package/backend/src/utils/validations.ts +40 -4
- package/backend/tests/local/test-ai-config.sh +129 -0
- package/backend/tests/local/test-ai-usage.sh +80 -0
- package/backend/tests/local/test-auth-router.sh +1 -1
- package/backend/tests/local/test-e2e.sh +1 -1
- package/backend/tests/local/test-functions.sh +123 -0
- package/backend/tests/local/test-logs.sh +132 -0
- package/backend/tests/local/test-public-bucket.sh +3 -3
- package/backend/tests/local/test-secrets.sh +14 -12
- package/backend/tests/local/test-traditional-rest.sh +2 -2
- package/backend/tests/manual/test-rawsql-modes.sh +244 -0
- package/backend/tests/test-config.sh +37 -1
- package/backend/tests/unit/cloud-token.test.ts +48 -0
- package/backend/tests/unit/constant.test.ts +8 -0
- package/backend/tests/unit/email.test.ts +372 -0
- package/backend/tests/unit/environment.test.ts +59 -0
- package/backend/tests/unit/helpers.test.ts +63 -0
- package/backend/tests/unit/logger.test.ts +22 -0
- package/backend/tests/unit/rate-limit.test.ts +154 -0
- package/backend/tests/unit/response.test.ts +58 -0
- package/backend/tests/unit/sql-parser.test.ts +74 -0
- package/backend/tests/unit/uuid.test.ts +21 -0
- package/backend/tests/unit/validations.test.ts +80 -0
- package/backend/tsconfig.json +1 -1
- package/backend/vitest.config.ts +11 -0
- package/claude-plugin/.claude-plugin/plugin.json +24 -0
- package/claude-plugin/README.md +133 -0
- package/claude-plugin/skills/insforge-schema-patterns/SKILL.md +270 -0
- package/docker-compose.prod.yml +60 -4
- package/docker-compose.yml +65 -4
- package/docker-init/db/db-init.sql +6 -34
- package/docker-init/logs/vector.yml +236 -0
- package/docs/README.md +44 -0
- package/docs/changelog.mdx +67 -0
- package/docs/core-concepts/ai/architecture.mdx +373 -0
- package/docs/core-concepts/ai/sdk.mdx +213 -0
- package/docs/core-concepts/authentication/architecture.mdx +278 -0
- package/docs/core-concepts/authentication/sdk.mdx +414 -0
- package/docs/core-concepts/authentication/ui-components/customization.mdx +529 -0
- package/docs/core-concepts/authentication/ui-components/nextjs.mdx +221 -0
- package/docs/core-concepts/authentication/ui-components/react-router.mdx +184 -0
- package/docs/core-concepts/authentication/ui-components/react.mdx +129 -0
- package/docs/core-concepts/database/architecture.mdx +256 -0
- package/docs/core-concepts/database/sdk.mdx +382 -0
- package/docs/core-concepts/functions/architecture.mdx +105 -0
- package/docs/core-concepts/functions/sdk.mdx +184 -0
- package/docs/core-concepts/storage/architecture.mdx +243 -0
- package/docs/core-concepts/storage/sdk.mdx +253 -0
- package/docs/deployment/README.md +94 -0
- package/docs/deployment/deploy-to-aws-ec2.md +565 -0
- package/docs/deployment/deploy-to-azure-virtual-machines.md +313 -0
- package/docs/deployment/deploy-to-google-cloud-compute-engine.md +613 -0
- package/docs/deployment/deploy-to-render.md +441 -0
- package/docs/docs.json +210 -0
- package/docs/examples/framework-guides/nextjs.mdx +131 -0
- package/docs/examples/framework-guides/nuxt.mdx +165 -0
- package/docs/examples/framework-guides/react.mdx +165 -0
- package/docs/examples/framework-guides/svelte.mdx +153 -0
- package/docs/examples/framework-guides/vue.mdx +159 -0
- package/docs/examples/overview.mdx +67 -0
- package/docs/favicon.svg +19 -0
- package/docs/images/changelog/nov-2025/auth-components.webp +0 -0
- package/docs/images/changelog/nov-2025/database-metadata.webp +0 -0
- package/docs/images/changelog/nov-2025/quickstart-prompts.webp +0 -0
- package/docs/images/changelog/nov-2025/sql-editor.webp +0 -0
- package/docs/images/changelog/nov-2025/usage-page.webp +0 -0
- package/docs/images/changelog/october-2025/csv-upload.webp +0 -0
- package/docs/images/changelog/october-2025/logs-feature.webp +0 -0
- package/docs/images/changelog/october-2025/oauth-providers.webp +0 -0
- package/docs/images/checks-passed.png +0 -0
- package/docs/images/dashboard-connect-expanded.png +0 -0
- package/docs/images/dashboard-connect.png +0 -0
- package/docs/images/hero-dark.png +0 -0
- package/docs/images/hero-light.png +0 -0
- package/docs/images/icons/ai.svg +4 -0
- package/docs/images/icons/auth.svg +1 -0
- package/docs/images/icons/database.svg +1 -0
- package/docs/images/icons/function.svg +1 -0
- package/docs/images/icons/storage.svg +1 -0
- package/docs/images/logos/nextjs.svg +4 -0
- package/docs/images/logos/nuxt.svg +4 -0
- package/docs/images/logos/react.svg +5 -0
- package/docs/images/logos/svelte.svg +4 -0
- package/docs/images/logos/vue.svg +5 -0
- package/docs/images/mcp-install.png +0 -0
- package/docs/images/onboarding-mcp.png +0 -0
- package/docs/insforge-instructions-sdk.md +55 -374
- package/docs/introduction.mdx +45 -0
- package/docs/logo/dark.svg +22 -0
- package/docs/logo/light.svg +20 -0
- package/docs/partnership.mdx +647 -0
- package/docs/quickstart.mdx +83 -0
- package/docs/showcase/2048-arena.png +0 -0
- package/docs/showcase/framegen-cloud.png +0 -0
- package/docs/showcase/line-connect-race.png +0 -0
- package/docs/showcase/moment-vibe.png +0 -0
- package/docs/showcase/national-flags.png +0 -0
- package/docs/showcase/pokemon-vibe.png +0 -0
- package/docs/showcase/pure-browse-buy.png +0 -0
- package/docs/showcase.mdx +52 -0
- package/docs/snippets/sdk-installation.mdx +22 -0
- package/docs/snippets/service-icons.mdx +27 -0
- package/eslint.config.js +10 -3
- package/frontend/package.json +10 -4
- package/frontend/src/App.tsx +13 -82
- package/frontend/src/assets/icons/connected.svg +3 -0
- package/frontend/src/assets/icons/loader.svg +9 -0
- package/frontend/src/assets/logos/apple.svg +4 -0
- package/frontend/src/assets/logos/discord.svg +1 -1
- package/frontend/src/assets/logos/facebook.svg +3 -0
- package/frontend/src/assets/logos/instagram.svg +2 -0
- package/frontend/src/assets/logos/linkedin.svg +3 -0
- package/frontend/src/assets/logos/microsoft.svg +1 -0
- package/frontend/src/assets/logos/spotify.svg +17 -0
- package/frontend/src/assets/logos/tiktok.svg +6 -0
- package/frontend/src/assets/logos/x.svg +3 -0
- package/frontend/src/components/Checkbox.tsx +27 -29
- package/frontend/src/components/CodeBlock.tsx +55 -2
- package/frontend/src/components/CodeEditor.tsx +92 -0
- package/frontend/src/components/ConfirmDialog.tsx +1 -1
- package/frontend/src/components/ConnectCTA.tsx +38 -0
- package/frontend/src/components/CopyButton.tsx +52 -15
- package/frontend/src/components/ErrorState.tsx +1 -2
- package/frontend/src/components/FeatureSidebar.tsx +6 -6
- package/frontend/src/components/FeatureSidebarItem.tsx +2 -2
- package/frontend/src/components/JsonHighlight.tsx +21 -9
- package/frontend/src/components/ProjectInfoModal.tsx +128 -0
- package/frontend/src/components/PromptDialog.tsx +1 -4
- package/frontend/src/components/SearchInput.tsx +1 -2
- package/frontend/src/components/Stepper.tsx +53 -0
- package/frontend/src/components/ThemeToggle.tsx +3 -3
- package/frontend/src/components/datagrid/DataGrid.tsx +25 -32
- package/frontend/src/components/datagrid/cell-editors/DateCellEditor.tsx +1 -2
- package/frontend/src/components/datagrid/cell-editors/JsonCellEditor.tsx +2 -4
- package/frontend/src/components/datagrid/index.ts +23 -0
- package/frontend/src/components/index.ts +23 -30
- package/frontend/src/components/layout/AppHeader.tsx +133 -92
- package/frontend/src/components/layout/AppSidebar.tsx +80 -170
- package/frontend/src/components/layout/Layout.tsx +12 -23
- package/frontend/src/components/layout/PrimaryMenu.tsx +187 -0
- package/frontend/src/components/layout/SecondaryMenu.tsx +70 -0
- package/frontend/src/components/layout/index.ts +5 -0
- package/frontend/src/components/radix/Tooltip.tsx +24 -13
- package/frontend/src/components/radix/index.ts +22 -0
- package/frontend/src/features/ai/components/AIConfigCard.tsx +129 -83
- package/frontend/src/features/ai/components/AIEmptyState.tsx +12 -7
- package/frontend/src/features/ai/components/ModalityFilterSidebar.tsx +101 -0
- package/frontend/src/features/ai/components/ModelSelectionDialog.tsx +135 -0
- package/frontend/src/features/ai/components/ModelSelectionGrid.tsx +51 -0
- package/frontend/src/features/ai/components/SystemPromptDialog.tsx +118 -0
- package/frontend/src/features/ai/components/index.ts +6 -0
- package/frontend/src/features/ai/helpers.ts +57 -71
- package/frontend/src/features/ai/hooks/useAIConfigs.ts +39 -113
- package/frontend/src/features/ai/hooks/useAIUsage.ts +0 -2
- package/frontend/src/features/ai/page/AIPage.tsx +67 -79
- package/frontend/src/features/ai/services/ai.service.ts +5 -5
- package/frontend/src/features/auth/components/AuthPreview.tsx +96 -0
- package/frontend/src/features/auth/components/OAuthConfigDialog.tsx +53 -30
- package/frontend/src/features/auth/components/UserFormDialog.tsx +13 -6
- package/frontend/src/features/auth/components/UsersDataGrid.tsx +44 -14
- package/frontend/src/features/auth/components/index.ts +5 -0
- package/frontend/src/features/auth/helpers.tsx +200 -0
- package/frontend/src/features/auth/hooks/useAnonToken.ts +30 -0
- package/frontend/src/features/auth/hooks/useAuthConfig.ts +48 -0
- package/frontend/src/features/auth/hooks/useOAuthConfig.ts +14 -10
- package/frontend/src/features/auth/hooks/useUsers.ts +43 -5
- package/frontend/src/features/auth/index.ts +3 -2
- package/frontend/src/features/auth/page/AuthMethodsPage.tsx +275 -0
- package/frontend/src/features/auth/page/ConfigurationPage.tsx +395 -0
- package/frontend/src/features/auth/page/UsersPage.tsx +285 -0
- package/frontend/src/features/auth/services/anonToken.service.ts +11 -0
- package/frontend/src/features/auth/services/config.service.ts +19 -0
- package/frontend/src/features/auth/services/{oauth.service.ts → oauth-config.service.ts} +4 -4
- package/frontend/src/features/auth/services/{auth.service.ts → user.service.ts} +7 -53
- package/frontend/src/features/dashboard/components/ConnectionSuccessBanner.tsx +35 -0
- package/frontend/src/features/dashboard/components/PromptCard.tsx +21 -0
- package/frontend/src/features/dashboard/components/PromptDialog.tsx +103 -0
- package/frontend/src/features/dashboard/components/StatsCard.tsx +50 -0
- package/frontend/src/features/dashboard/components/index.ts +4 -0
- package/frontend/src/features/dashboard/page/DashboardPage.tsx +187 -169
- package/frontend/src/features/dashboard/prompts/ai-chatbot.ts +13 -0
- package/frontend/src/features/dashboard/prompts/crm-system.ts +13 -0
- package/frontend/src/features/dashboard/prompts/ecommerce-platform.ts +12 -0
- package/frontend/src/features/dashboard/prompts/index.ts +31 -0
- package/frontend/src/features/dashboard/prompts/instagram-clone.ts +11 -0
- package/frontend/src/features/dashboard/prompts/notion-clone.ts +14 -0
- package/frontend/src/features/dashboard/prompts/reddit-clone.ts +12 -0
- package/frontend/src/features/database/components/DatabaseDataGrid.tsx +48 -17
- package/frontend/src/features/database/components/ForeignKeyCell.tsx +15 -34
- package/frontend/src/features/database/components/ForeignKeyPopover.tsx +19 -20
- package/frontend/src/features/database/components/LinkRecordModal.tsx +120 -125
- package/frontend/src/features/database/components/RecordFormDialog.tsx +22 -33
- package/frontend/src/features/database/components/RecordFormField.tsx +45 -47
- package/frontend/src/features/database/components/TableEmptyState.tsx +6 -5
- package/frontend/src/features/database/components/TableForm.tsx +28 -15
- package/frontend/src/features/database/components/TableFormColumn.tsx +2 -3
- package/frontend/src/features/database/components/TableSidebar.tsx +1 -1
- package/frontend/src/features/database/components/TablesEmptyState.tsx +48 -0
- package/frontend/src/features/database/components/TemplateCard.tsx +37 -0
- package/frontend/src/features/database/components/TemplatePreview.tsx +92 -0
- package/frontend/src/features/database/components/index.ts +19 -0
- package/frontend/src/features/database/constants.ts +28 -2
- package/frontend/src/features/database/contexts/SQLEditorContext.tsx +188 -0
- package/frontend/src/features/database/helpers.ts +2 -2
- package/frontend/src/features/database/hooks/useCSVImport.ts +29 -0
- package/frontend/src/features/database/hooks/useFullMetadata.ts +18 -0
- package/frontend/src/features/database/hooks/useRawSQL.ts +55 -0
- package/frontend/src/features/database/hooks/useRecords.ts +139 -0
- package/frontend/src/features/database/hooks/useTables.ts +131 -0
- package/frontend/src/features/database/index.ts +6 -1
- package/frontend/src/features/database/page/FunctionsPage.tsx +211 -0
- package/frontend/src/features/database/page/IndexesPage.tsx +240 -0
- package/frontend/src/features/database/page/PoliciesPage.tsx +248 -0
- package/frontend/src/features/database/page/SQLEditorPage.tsx +382 -0
- package/frontend/src/features/database/page/{DatabasePage.tsx → TablesPage.tsx} +186 -185
- package/frontend/src/features/database/page/TemplatesPage.tsx +39 -0
- package/frontend/src/features/database/page/TriggersPage.tsx +242 -0
- package/frontend/src/features/database/services/advance.service.ts +66 -0
- package/frontend/src/features/database/services/{database.service.ts → record.service.ts} +67 -64
- package/frontend/src/features/database/services/table.service.ts +64 -0
- package/frontend/src/features/database/templates/ai-chatbot.ts +402 -0
- package/frontend/src/features/database/templates/crm-system.ts +528 -0
- package/frontend/src/features/database/templates/ecommerce-platform.ts +553 -0
- package/frontend/src/features/database/templates/index.ts +34 -0
- package/frontend/src/features/database/templates/instagram-clone.ts +222 -0
- package/frontend/src/features/database/templates/notion-clone.ts +483 -0
- package/frontend/src/features/database/templates/reddit-clone.ts +526 -0
- package/frontend/src/features/functions/components/FunctionRow.tsx +2 -1
- package/frontend/src/features/functions/components/FunctionsSidebar.tsx +1 -1
- package/frontend/src/features/functions/components/SecretRow.tsx +1 -1
- package/frontend/src/features/functions/components/index.ts +5 -0
- package/frontend/src/features/functions/hooks/useFunctions.ts +4 -4
- package/frontend/src/features/{secrets → functions}/hooks/useSecrets.ts +5 -5
- package/frontend/src/features/functions/page/FunctionsPage.tsx +160 -17
- package/frontend/src/features/functions/{components/SecretsContent.tsx → page/SecretsPage.tsx} +8 -12
- package/frontend/src/features/functions/services/{functions.service.ts → function.service.ts} +2 -2
- package/frontend/src/features/{secrets/services/secrets.service.ts → functions/services/secret.service.ts} +2 -2
- package/frontend/src/features/login/hooks/usePartnerOrigin.ts +27 -0
- package/frontend/src/features/login/page/CloudLoginPage.tsx +79 -54
- package/frontend/src/features/login/page/LoginPage.tsx +16 -23
- package/frontend/src/features/login/services/partnership.service.ts +65 -0
- package/frontend/src/features/logs/components/LogsDataGrid.tsx +89 -0
- package/frontend/src/features/logs/components/SeverityBadge.tsx +18 -0
- package/frontend/src/features/logs/components/index.ts +2 -0
- package/frontend/src/features/logs/helpers.ts +24 -0
- package/frontend/src/features/logs/hooks/useAuditLogs.ts +4 -4
- package/frontend/src/features/logs/hooks/useLogSources.ts +137 -0
- package/frontend/src/features/logs/hooks/useLogs.ts +163 -0
- package/frontend/src/features/logs/hooks/useMcpUsage.ts +181 -0
- package/frontend/src/features/logs/index.ts +8 -2
- package/frontend/src/features/logs/page/AuditsPage.tsx +91 -38
- package/frontend/src/features/logs/page/LogsPage.tsx +152 -0
- package/frontend/src/features/logs/page/MCPLogsPage.tsx +84 -0
- package/frontend/src/features/logs/services/audit.service.ts +63 -0
- package/frontend/src/features/logs/services/log.service.ts +15 -110
- package/frontend/src/features/logs/services/usage.service.ts +31 -0
- package/frontend/src/features/onboard/components/McpConnectionStatus.tsx +68 -0
- package/frontend/src/features/onboard/components/OnboardingModal.tsx +267 -0
- package/frontend/src/features/onboard/components/VideoDemoModal.tsx +38 -0
- package/frontend/src/features/onboard/components/index.ts +4 -0
- package/frontend/src/features/onboard/components/mcp/CursorDeeplinkGenerator.tsx +2 -2
- package/frontend/src/features/onboard/components/mcp/{mcp-helper.tsx → helpers.tsx} +8 -8
- package/frontend/src/features/onboard/components/mcp/index.ts +2 -3
- package/frontend/src/features/onboard/index.ts +13 -3
- package/frontend/src/features/storage/components/BucketEmptyState.tsx +9 -6
- package/frontend/src/features/storage/components/BucketFormDialog.tsx +25 -41
- package/frontend/src/features/storage/components/FilePreviewDialog.tsx +20 -8
- package/frontend/src/features/storage/components/StorageDataGrid.tsx +4 -3
- package/frontend/src/features/storage/components/StorageManager.tsx +23 -34
- package/frontend/src/features/storage/components/index.ts +12 -0
- package/frontend/src/features/storage/hooks/useStorage.ts +208 -0
- package/frontend/src/features/storage/page/StoragePage.tsx +41 -115
- package/frontend/src/features/storage/services/storage.service.ts +22 -1
- package/frontend/src/features/visualizer/components/AuthNode.tsx +72 -56
- package/frontend/src/features/visualizer/components/BucketNode.tsx +4 -4
- package/frontend/src/features/visualizer/components/SchemaVisualizer.tsx +108 -80
- package/frontend/src/features/visualizer/components/TableNode.tsx +34 -41
- package/frontend/src/features/visualizer/components/VisualizerSkeleton.tsx +12 -4
- package/frontend/src/features/visualizer/page/VisualizerPage.tsx +33 -29
- package/frontend/src/index.css +1 -0
- package/frontend/src/lib/analytics/posthog.tsx +27 -0
- package/frontend/src/lib/contexts/AuthContext.tsx +38 -31
- package/frontend/src/lib/contexts/SocketContext.tsx +5 -6
- package/frontend/src/{features/metadata → lib}/hooks/useMetadata.ts +1 -1
- package/frontend/src/lib/hooks/useToast.tsx +6 -2
- package/frontend/src/lib/routing/AppRoutes.tsx +84 -0
- package/frontend/src/lib/routing/RequireAuth.tsx +27 -0
- package/frontend/src/lib/utils/cloudMessaging.ts +20 -0
- package/frontend/src/lib/utils/menuItems.ts +183 -0
- package/frontend/src/lib/utils/{validation-schemas.ts → schemaValidations.ts} +10 -5
- package/frontend/src/lib/utils/utils.ts +19 -1
- package/frontend/src/vite-env.d.ts +1 -0
- package/frontend/vite.config.ts +5 -3
- package/functions/server.ts +28 -3
- package/functions/worker-template.js +15 -4
- package/i18n/README.ar.md +130 -0
- package/i18n/README.de.md +130 -0
- package/i18n/README.es.md +154 -0
- package/i18n/README.fr.md +134 -0
- package/i18n/README.hi.md +129 -0
- package/i18n/README.ja.md +174 -0
- package/i18n/README.ko.md +137 -0
- package/i18n/README.pt-BR.md +131 -0
- package/i18n/README.ru.md +129 -0
- package/i18n/README.zh-CN.md +133 -0
- package/openapi/ai.yaml +31 -4
- package/openapi/auth.yaml +827 -146
- package/package.json +16 -7
- package/shared-schemas/package.json +1 -1
- package/shared-schemas/src/ai-api.schema.ts +34 -58
- package/shared-schemas/src/ai.schema.ts +5 -0
- package/shared-schemas/src/auth-api.schema.ts +154 -8
- package/shared-schemas/src/auth.schema.ts +42 -6
- package/shared-schemas/src/cloud-events.schema.ts +57 -0
- package/shared-schemas/src/database-api.schema.ts +3 -3
- package/shared-schemas/src/database.schema.ts +1 -1
- package/shared-schemas/src/index.ts +1 -0
- package/shared-schemas/src/logs-api.schema.ts +7 -1
- package/shared-schemas/src/logs.schema.ts +26 -0
- package/shared-schemas/src/metadata.schema.ts +9 -4
- package/test-gemini.sh +35 -0
- package/test-usage-admin.sh +57 -0
- package/test-usage.sh +50 -0
- package/zeabur/README.md +13 -0
- package/zeabur/template.yml +1032 -0
- package/.github/workflows/deploy-aws.yml +0 -130
- package/backend/src/api/routes/agent.ts +0 -29
- package/backend/src/api/routes/auth.oauth.ts +0 -482
- package/backend/src/api/routes/auth.ts +0 -386
- package/backend/src/api/routes/docs.ts +0 -66
- package/backend/src/api/routes/functions.ts +0 -183
- package/backend/src/api/routes/openapi.ts +0 -82
- package/backend/src/api/routes/usage.ts +0 -96
- package/backend/src/core/ai/client.ts +0 -242
- package/backend/src/core/ai/model.ts +0 -117
- package/backend/src/core/auth/auth.ts +0 -781
- package/backend/src/core/database/table.ts +0 -772
- package/backend/src/core/documentation/agent.ts +0 -689
- package/backend/src/core/documentation/openapi.ts +0 -856
- package/backend/src/core/logs/analytics.ts +0 -76
- package/backend/src/core/logs/providers/localdb.provider.ts +0 -246
- package/backend/src/core/storage/storage.ts +0 -923
- package/backend/src/utils/cloud-token.ts +0 -39
- package/backend/src/utils/helpers.ts +0 -49
- package/backend/src/utils/uuid.ts +0 -9
- package/backend/tests/manual/test-better-auth.sh +0 -303
- package/docker-init/db/logs.sql +0 -9
- package/frontend/README.md +0 -112
- package/frontend/src/components/datagrid/index.tsx +0 -20
- package/frontend/src/components/layout/CloudLayout.tsx +0 -95
- package/frontend/src/features/ai/components/AIConfigDialog.tsx +0 -76
- package/frontend/src/features/ai/components/AIConfigForm.tsx +0 -222
- package/frontend/src/features/ai/components/fields/ModalityField.tsx +0 -87
- package/frontend/src/features/ai/components/fields/ModelSelectionField.tsx +0 -134
- package/frontend/src/features/ai/components/fields/SystemPromptField.tsx +0 -33
- package/frontend/src/features/auth/components/AddOAuthDialog.tsx +0 -106
- package/frontend/src/features/auth/components/AuthMethodTab.tsx +0 -238
- package/frontend/src/features/auth/components/UsersTab.tsx +0 -114
- package/frontend/src/features/auth/page/AuthenticationPage.tsx +0 -169
- package/frontend/src/features/database/hooks/UseLinkModal.tsx +0 -78
- package/frontend/src/features/functions/components/FunctionViewer.tsx +0 -46
- package/frontend/src/features/functions/components/FunctionsContent.tsx +0 -88
- package/frontend/src/features/login/components/AuthErrorBoundary.tsx +0 -87
- package/frontend/src/features/login/components/PrivateRoute.tsx +0 -24
- package/frontend/src/features/logs/components/AnalyticsLogsTable.tsx +0 -313
- package/frontend/src/features/logs/components/LogsTable.tsx +0 -199
- package/frontend/src/features/logs/page/AnalyticsLogsPage.tsx +0 -530
- package/frontend/src/features/metadata/index.ts +0 -0
- package/frontend/src/features/metadata/page/MetadataPage.tsx +0 -136
- package/frontend/src/features/onboard/components/CompletionCard.tsx +0 -41
- package/frontend/src/features/onboard/components/OnboardButton.tsx +0 -84
- package/frontend/src/features/onboard/components/StepContent.tsx +0 -91
- package/frontend/src/features/onboard/components/TestConnectionStep.tsx +0 -53
- package/frontend/src/features/onboard/components/mcp/McpInstallation.tsx +0 -144
- package/frontend/src/features/onboard/page/OnBoardPage.tsx +0 -104
- package/frontend/src/features/onboard/types.ts +0 -8
- package/frontend/src/lib/contexts/OnboardStepContext.tsx +0 -68
- package/frontend/src/lib/hooks/useOnboardingCompletion.ts +0 -29
- /package/backend/src/api/{middleware → middlewares}/error.ts +0 -0
- /package/backend/src/api/{middleware → middlewares}/upload.ts +0 -0
- /package/backend/{migrations → src/infra/database/migrations}/000_create-base-tables.sql +0 -0
- /package/backend/{migrations → src/infra/database/migrations}/001_create-helper-functions.sql +0 -0
- /package/backend/{migrations → src/infra/database/migrations}/002_rename-auth-tables.sql +0 -0
- /package/backend/{migrations → src/infra/database/migrations}/003_create-users-table.sql +0 -0
- /package/backend/{migrations → src/infra/database/migrations}/004_add-reload-postgrest-func.sql +0 -0
- /package/backend/{migrations → src/infra/database/migrations}/005_enable-project-admin-modify-users.sql +0 -0
- /package/backend/{migrations → src/infra/database/migrations}/006_modify-ai-usage-table.sql +0 -0
- /package/backend/{migrations → src/infra/database/migrations}/007_drop-metadata-table.sql +0 -0
- /package/backend/{migrations → src/infra/database/migrations}/008_add-system-tables.sql +0 -0
- /package/backend/{migrations → src/infra/database/migrations}/009_add-function-secrets.sql +0 -0
- /package/backend/{migrations → src/infra/database/migrations}/010_modify-ai-config-modalities.sql +0 -0
- /package/backend/{migrations → src/infra/database/migrations}/011_refactor-secrets-table.sql +0 -0
- /package/backend/{migrations → src/infra/database/migrations}/012_add-storage-uploaded-by.sql +0 -0
- /package/frontend/src/{features/metadata → lib}/services/metadata.service.ts +0 -0
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { Pool } from 'pg';
|
|
2
|
+
import { DatabaseManager } from '@/infra/database/database.manager.js';
|
|
3
|
+
import logger from '@/utils/logger.js';
|
|
4
|
+
|
|
5
|
+
export interface AIUsageByModel {
|
|
6
|
+
model: string;
|
|
7
|
+
total_input_tokens: number;
|
|
8
|
+
total_output_tokens: number;
|
|
9
|
+
total_images: number;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface UsageStats {
|
|
13
|
+
mcp_usage_count: number;
|
|
14
|
+
database_size_bytes: number;
|
|
15
|
+
storage_size_bytes: number;
|
|
16
|
+
ai_usage_by_model: AIUsageByModel[];
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface MCPUsageRecord {
|
|
20
|
+
tool_name: string;
|
|
21
|
+
success: boolean;
|
|
22
|
+
created_at: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* UsageService - Handles usage tracking and statistics
|
|
27
|
+
* Business logic layer for MCP usage, system resource tracking, and AI usage
|
|
28
|
+
*/
|
|
29
|
+
export class UsageService {
|
|
30
|
+
private static instance: UsageService;
|
|
31
|
+
private pool: Pool | null = null;
|
|
32
|
+
|
|
33
|
+
private constructor() {
|
|
34
|
+
logger.info('UsageService initialized');
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
private getPool(): Pool {
|
|
38
|
+
if (!this.pool) {
|
|
39
|
+
this.pool = DatabaseManager.getInstance().getPool();
|
|
40
|
+
}
|
|
41
|
+
return this.pool;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
public static getInstance(): UsageService {
|
|
45
|
+
if (!UsageService.instance) {
|
|
46
|
+
UsageService.instance = new UsageService();
|
|
47
|
+
}
|
|
48
|
+
return UsageService.instance;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Record MCP tool usage
|
|
53
|
+
*/
|
|
54
|
+
async recordMCPUsage(toolName: string, success: boolean = true): Promise<{ created_at: string }> {
|
|
55
|
+
try {
|
|
56
|
+
const result = await this.getPool().query(
|
|
57
|
+
`INSERT INTO _mcp_usage (tool_name, success)
|
|
58
|
+
VALUES ($1, $2)
|
|
59
|
+
RETURNING created_at`,
|
|
60
|
+
[toolName, success]
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
logger.info('MCP usage recorded', { toolName, success });
|
|
64
|
+
return { created_at: result.rows[0].created_at };
|
|
65
|
+
} catch (error) {
|
|
66
|
+
logger.error('Failed to record MCP usage', { error, toolName });
|
|
67
|
+
throw new Error('Failed to record MCP usage');
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Get recent MCP usage records
|
|
73
|
+
*/
|
|
74
|
+
async getMCPUsage(limit: number = 5, success: boolean = true): Promise<MCPUsageRecord[]> {
|
|
75
|
+
try {
|
|
76
|
+
const result = await this.getPool().query(
|
|
77
|
+
`SELECT tool_name, success, created_at
|
|
78
|
+
FROM _mcp_usage
|
|
79
|
+
WHERE success = $1
|
|
80
|
+
ORDER BY created_at DESC
|
|
81
|
+
LIMIT $2`,
|
|
82
|
+
[success, limit]
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
return result.rows as MCPUsageRecord[];
|
|
86
|
+
} catch (error) {
|
|
87
|
+
logger.error('Failed to get MCP usage', { error });
|
|
88
|
+
throw new Error('Failed to get MCP usage');
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Get comprehensive usage statistics for a date range
|
|
94
|
+
* Returns MCP usage, database size, storage size, and AI usage by model
|
|
95
|
+
*/
|
|
96
|
+
async getUsageStats(startDate: Date, endDate: Date): Promise<UsageStats> {
|
|
97
|
+
try {
|
|
98
|
+
// Get MCP tool usage count
|
|
99
|
+
const mcpResult = await this.getPool().query(
|
|
100
|
+
`SELECT COUNT(*) as count
|
|
101
|
+
FROM _mcp_usage
|
|
102
|
+
WHERE success = true
|
|
103
|
+
AND created_at >= $1
|
|
104
|
+
AND created_at < $2`,
|
|
105
|
+
[startDate, endDate]
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
// Get database size
|
|
109
|
+
const dbSizeResult = await this.getPool().query(
|
|
110
|
+
`SELECT pg_database_size(current_database()) as size`
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
// Get total storage size
|
|
114
|
+
const storageResult = await this.getPool().query(
|
|
115
|
+
`SELECT COALESCE(SUM(size), 0) as total_size FROM _storage`
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
// Get AI usage breakdown by model (only billable metrics)
|
|
119
|
+
const aiUsageByModel = await this.getPool().query(
|
|
120
|
+
`SELECT
|
|
121
|
+
COALESCE(u.model_id, c.model_id) as model,
|
|
122
|
+
COALESCE(SUM(u.input_tokens), 0) as total_input_tokens,
|
|
123
|
+
COALESCE(SUM(u.output_tokens), 0) as total_output_tokens,
|
|
124
|
+
COALESCE(SUM(u.image_count), 0) as total_images
|
|
125
|
+
FROM _ai_usage u
|
|
126
|
+
LEFT JOIN _ai_configs c ON u.config_id = c.id
|
|
127
|
+
WHERE u.created_at >= $1 AND u.created_at < $2
|
|
128
|
+
GROUP BY COALESCE(u.model_id, c.model_id)
|
|
129
|
+
ORDER BY (COALESCE(SUM(u.input_tokens), 0) + COALESCE(SUM(u.output_tokens), 0)) DESC`,
|
|
130
|
+
[startDate, endDate]
|
|
131
|
+
);
|
|
132
|
+
|
|
133
|
+
return {
|
|
134
|
+
mcp_usage_count: parseInt(mcpResult.rows[0]?.count || '0'),
|
|
135
|
+
database_size_bytes: parseInt(dbSizeResult.rows[0]?.size || '0'),
|
|
136
|
+
storage_size_bytes: parseInt(storageResult.rows[0]?.total_size || '0'),
|
|
137
|
+
ai_usage_by_model: aiUsageByModel.rows.map((row) => ({
|
|
138
|
+
model: (row.model as string) || 'unknown',
|
|
139
|
+
total_input_tokens: parseInt(String(row.total_input_tokens || '0')),
|
|
140
|
+
total_output_tokens: parseInt(String(row.total_output_tokens || '0')),
|
|
141
|
+
total_images: parseInt(String(row.total_images || '0')),
|
|
142
|
+
})),
|
|
143
|
+
};
|
|
144
|
+
} catch (error) {
|
|
145
|
+
logger.error('Failed to get usage stats', { error });
|
|
146
|
+
throw new Error('Failed to get usage stats');
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
@@ -6,8 +6,8 @@ export interface UserRecord {
|
|
|
6
6
|
email_verified: boolean;
|
|
7
7
|
created_at: string;
|
|
8
8
|
updated_at: string;
|
|
9
|
-
password
|
|
10
|
-
providers
|
|
9
|
+
password?: string;
|
|
10
|
+
providers?: string;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
// OAuth provider data from external providers
|
|
@@ -88,3 +88,67 @@ export interface GitHubEmailInfo {
|
|
|
88
88
|
verified: boolean;
|
|
89
89
|
visibility?: string;
|
|
90
90
|
}
|
|
91
|
+
|
|
92
|
+
export interface MicrosoftUserInfo {
|
|
93
|
+
id: string;
|
|
94
|
+
email: string;
|
|
95
|
+
name: string;
|
|
96
|
+
avatar_url?: string;
|
|
97
|
+
}
|
|
98
|
+
export interface DiscordUserInfo {
|
|
99
|
+
id: string;
|
|
100
|
+
username: string;
|
|
101
|
+
email?: string;
|
|
102
|
+
avatar?: string;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export interface LinkedInUserInfo {
|
|
106
|
+
sub: string;
|
|
107
|
+
email: string;
|
|
108
|
+
email_verified?: boolean;
|
|
109
|
+
name?: string;
|
|
110
|
+
picture?: string;
|
|
111
|
+
given_name?: string;
|
|
112
|
+
family_name?: string;
|
|
113
|
+
locale?: string;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export interface FacebookUserInfo {
|
|
117
|
+
id: string;
|
|
118
|
+
email: string;
|
|
119
|
+
name?: string;
|
|
120
|
+
picture?: {
|
|
121
|
+
data?: {
|
|
122
|
+
url?: string;
|
|
123
|
+
};
|
|
124
|
+
};
|
|
125
|
+
first_name?: string;
|
|
126
|
+
last_name?: string;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export interface XUserInfo {
|
|
130
|
+
id: string;
|
|
131
|
+
name: string;
|
|
132
|
+
username?: string;
|
|
133
|
+
profile_image_url?: string;
|
|
134
|
+
verified?: boolean;
|
|
135
|
+
created_at?: string;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Generic OAuth user data returned by provider services
|
|
139
|
+
export interface OAuthUserData {
|
|
140
|
+
provider: string;
|
|
141
|
+
providerId: string;
|
|
142
|
+
email: string;
|
|
143
|
+
userName: string;
|
|
144
|
+
avatarUrl: string;
|
|
145
|
+
identityData:
|
|
146
|
+
| GoogleUserInfo
|
|
147
|
+
| GitHubUserInfo
|
|
148
|
+
| DiscordUserInfo
|
|
149
|
+
| LinkedInUserInfo
|
|
150
|
+
| FacebookUserInfo
|
|
151
|
+
| MicrosoftUserInfo
|
|
152
|
+
| XUserInfo
|
|
153
|
+
| Record<string, unknown>;
|
|
154
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Email template types supported by email providers
|
|
3
|
+
*/
|
|
4
|
+
export type EmailTemplate =
|
|
5
|
+
| 'email-verification-code' // Numeric OTP for email verification
|
|
6
|
+
| 'email-verification-link' // Magic link for email verification
|
|
7
|
+
| 'reset-password-code' // Numeric OTP for password reset
|
|
8
|
+
| 'reset-password-link'; // Magic link for password reset
|
|
@@ -39,6 +39,9 @@ export enum ERROR_CODES {
|
|
|
39
39
|
// AI module
|
|
40
40
|
AI_INVALID_API_KEY = 'AI_INVALID_API_KEY',
|
|
41
41
|
|
|
42
|
+
// LOGS module
|
|
43
|
+
LOGS_AWS_NOT_CONFIGURED = 'LOGS_AWS_NOT_CONFIGURED',
|
|
44
|
+
|
|
42
45
|
// Billing module
|
|
43
46
|
BILLING_INSUFFICIENT_BALANCE = 'BILLING_INSUFFICIENT_BALANCE',
|
|
44
47
|
|
|
@@ -51,6 +54,7 @@ export enum ERROR_CODES {
|
|
|
51
54
|
INTERNAL_ERROR = 'INTERNAL_ERROR',
|
|
52
55
|
TOO_MANY_REQUESTS = 'TOO_MANY_REQUESTS',
|
|
53
56
|
FORBIDDEN = 'FORBIDDEN',
|
|
57
|
+
RATE_LIMITED = 'RATE_LIMITED',
|
|
54
58
|
}
|
|
55
59
|
|
|
56
60
|
// Next actions - what the user should do
|
|
@@ -16,32 +16,3 @@ export interface AuditLogQuery {
|
|
|
16
16
|
limit?: number;
|
|
17
17
|
offset?: number;
|
|
18
18
|
}
|
|
19
|
-
|
|
20
|
-
// Types for Logflare analytics logs
|
|
21
|
-
export interface LogSource {
|
|
22
|
-
id: number;
|
|
23
|
-
name: string;
|
|
24
|
-
token: string;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export interface AnalyticsLogRecord {
|
|
28
|
-
id: string;
|
|
29
|
-
event_message: string;
|
|
30
|
-
timestamp: string;
|
|
31
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
32
|
-
body: Record<string, any>;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export interface AnalyticsLogResponse {
|
|
36
|
-
source: string;
|
|
37
|
-
logs: AnalyticsLogRecord[];
|
|
38
|
-
total: number;
|
|
39
|
-
page: number;
|
|
40
|
-
pageSize: number;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export interface LogSourceStats {
|
|
44
|
-
source: string;
|
|
45
|
-
count: number;
|
|
46
|
-
lastActivity: string;
|
|
47
|
-
}
|
|
@@ -41,12 +41,11 @@ export interface NotificationPayload {
|
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
export enum DataUpdateResourceType {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
AUTH_SCHEMA = 'auth_schmea',
|
|
44
|
+
DATABASE = 'database',
|
|
45
|
+
USERS = 'users',
|
|
46
|
+
RECORDS = 'records',
|
|
47
|
+
BUCKETS = 'buckets',
|
|
48
|
+
FUNCTIONS = 'functions',
|
|
50
49
|
}
|
|
51
50
|
|
|
52
51
|
export interface DataUpdatePayload {
|
|
@@ -7,9 +7,7 @@
|
|
|
7
7
|
* Currently checks for AWS instance profile, but can be extended for other cloud providers
|
|
8
8
|
*/
|
|
9
9
|
export function isCloudEnvironment(): boolean {
|
|
10
|
-
return !!(
|
|
11
|
-
process.env.AWS_INSTANCE_PROFILE_NAME && process.env.AWS_INSTANCE_PROFILE_NAME.trim().length > 0
|
|
12
|
-
);
|
|
10
|
+
return !!(process.env.AWS_INSTANCE_PROFILE_NAME && process.env.AWS_INSTANCE_PROFILE_NAME.trim());
|
|
13
11
|
}
|
|
14
12
|
|
|
15
13
|
/**
|
|
@@ -33,3 +31,11 @@ export function isDevelopment(): boolean {
|
|
|
33
31
|
export function isProduction(): boolean {
|
|
34
32
|
return process.env.NODE_ENV === 'production';
|
|
35
33
|
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Get the API base URL from environment variable or default to localhost
|
|
37
|
+
* @returns The API base URL
|
|
38
|
+
*/
|
|
39
|
+
export function getApiBaseUrl(): string {
|
|
40
|
+
return process.env.API_BASE_URL || 'http://localhost:7130';
|
|
41
|
+
}
|
|
@@ -1,13 +1,31 @@
|
|
|
1
1
|
import winston from 'winston';
|
|
2
|
+
import path from 'path';
|
|
2
3
|
|
|
3
|
-
const
|
|
4
|
+
const logsDir = process.env.LOGS_DIR || path.join(process.cwd(), 'logs');
|
|
5
|
+
|
|
6
|
+
export const logger = winston.createLogger({
|
|
4
7
|
level: process.env.LOG_LEVEL || 'info',
|
|
5
8
|
format: winston.format.combine(
|
|
6
9
|
winston.format.timestamp(),
|
|
7
10
|
winston.format.errors({ stack: true }),
|
|
8
11
|
winston.format.json()
|
|
9
12
|
),
|
|
10
|
-
transports: [
|
|
13
|
+
transports: [
|
|
14
|
+
new winston.transports.Console(),
|
|
15
|
+
new winston.transports.File({
|
|
16
|
+
filename: path.join(logsDir, 'insforge.logs.jsonl'),
|
|
17
|
+
format: winston.format.printf((info) => {
|
|
18
|
+
const { timestamp, level, message, ...metadata } = info;
|
|
19
|
+
return JSON.stringify({
|
|
20
|
+
id: `${Date.now()}-${Math.random()}`,
|
|
21
|
+
timestamp,
|
|
22
|
+
message,
|
|
23
|
+
level,
|
|
24
|
+
metadata,
|
|
25
|
+
});
|
|
26
|
+
}),
|
|
27
|
+
}),
|
|
28
|
+
],
|
|
11
29
|
});
|
|
12
30
|
|
|
13
31
|
export default logger;
|
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
import { DatabaseManager } from '@/
|
|
2
|
-
import {
|
|
1
|
+
import { DatabaseManager } from '@/infra/database/database.manager.js';
|
|
2
|
+
import { TokenManager } from '@/infra/security/token.manager.js';
|
|
3
|
+
import { AIConfigService } from '@/services/ai/ai-config.service.js';
|
|
3
4
|
import { isCloudEnvironment } from '@/utils/environment.js';
|
|
4
5
|
import logger from '@/utils/logger.js';
|
|
5
|
-
import {
|
|
6
|
-
import { OAuthConfigService } from '@/
|
|
6
|
+
import { SecretService } from '@/services/secrets/secret.service.js';
|
|
7
|
+
import { OAuthConfigService } from '@/services/auth/oauth-config.service.js';
|
|
8
|
+
import { OAuthProvidersSchema } from '@insforge/shared-schemas';
|
|
9
|
+
import { AuthConfigService } from '@/services/auth/auth-config.service.js';
|
|
7
10
|
|
|
8
11
|
/**
|
|
9
12
|
* Validates admin credentials are configured
|
|
@@ -26,12 +29,12 @@ async function seedDefaultAIConfigs(): Promise<void> {
|
|
|
26
29
|
return;
|
|
27
30
|
}
|
|
28
31
|
|
|
29
|
-
const aiConfigService =
|
|
32
|
+
const aiConfigService = AIConfigService.getInstance();
|
|
30
33
|
|
|
31
34
|
// Check if AI configs already exist
|
|
32
35
|
const existingConfigs = await aiConfigService.findAll();
|
|
33
36
|
|
|
34
|
-
if (existingConfigs.length
|
|
37
|
+
if (existingConfigs.length) {
|
|
35
38
|
return;
|
|
36
39
|
}
|
|
37
40
|
|
|
@@ -47,39 +50,92 @@ async function seedDefaultAIConfigs(): Promise<void> {
|
|
|
47
50
|
['text', 'image'],
|
|
48
51
|
['text', 'image'],
|
|
49
52
|
'openrouter',
|
|
50
|
-
'google/gemini-
|
|
53
|
+
'google/gemini-3-pro-image-preview'
|
|
51
54
|
);
|
|
52
55
|
|
|
53
56
|
logger.info('✅ Default AI models configured (cloud environment)');
|
|
54
57
|
}
|
|
55
58
|
|
|
56
59
|
/**
|
|
57
|
-
* Seeds default
|
|
60
|
+
* Seeds default auth configuration for cloud environments
|
|
61
|
+
* Enables email verification with code-based verification method
|
|
62
|
+
* Only inserts config if table is empty (first startup, never configured)
|
|
63
|
+
*/
|
|
64
|
+
async function seedDefaultAuthConfig(): Promise<void> {
|
|
65
|
+
const dbManager = DatabaseManager.getInstance();
|
|
66
|
+
const pool = dbManager.getPool();
|
|
67
|
+
const client = await pool.connect();
|
|
68
|
+
|
|
69
|
+
try {
|
|
70
|
+
const result = await client.query('SELECT COUNT(*) as count FROM _auth_configs');
|
|
71
|
+
const hasConfig = result.rows.length > 0 && Number(result.rows[0].count) > 0;
|
|
72
|
+
|
|
73
|
+
if (hasConfig) {
|
|
74
|
+
const authConfigService = AuthConfigService.getInstance();
|
|
75
|
+
const currentConfig = await authConfigService.getAuthConfig();
|
|
76
|
+
logger.info(
|
|
77
|
+
'✅ Email verification configured:',
|
|
78
|
+
currentConfig.requireEmailVerification ? 'enabled' : 'disabled'
|
|
79
|
+
);
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Table is empty - this is first startup, insert default cloud configuration
|
|
84
|
+
// Note: Migration 016 will add verify_email_method, reset_password_method, sign_in_redirect_to
|
|
85
|
+
// so we only insert fields that exist in migration 015
|
|
86
|
+
await client.query(
|
|
87
|
+
`INSERT INTO _auth_configs (
|
|
88
|
+
require_email_verification,
|
|
89
|
+
password_min_length,
|
|
90
|
+
require_number,
|
|
91
|
+
require_lowercase,
|
|
92
|
+
require_uppercase,
|
|
93
|
+
require_special_char
|
|
94
|
+
) VALUES ($1, $2, $3, $4, $5, $6)
|
|
95
|
+
ON CONFLICT DO NOTHING`,
|
|
96
|
+
[
|
|
97
|
+
isCloudEnvironment(), // Enable email verification for cloud
|
|
98
|
+
6, // password_min_length
|
|
99
|
+
false, // require_number
|
|
100
|
+
false, // require_lowercase
|
|
101
|
+
false, // require_uppercase
|
|
102
|
+
false, // require_special_char
|
|
103
|
+
]
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
logger.info('✅ Email verification enabled (cloud environment)');
|
|
107
|
+
} catch (error) {
|
|
108
|
+
logger.error('Failed to seed default auth config', {
|
|
109
|
+
error: error instanceof Error ? error.message : String(error),
|
|
110
|
+
});
|
|
111
|
+
// Don't throw - this is not critical for app startup
|
|
112
|
+
} finally {
|
|
113
|
+
client.release();
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Seeds default OAuth configurations for supported providers
|
|
58
119
|
*/
|
|
59
120
|
async function seedDefaultOAuthConfigs(): Promise<void> {
|
|
60
|
-
const
|
|
121
|
+
const oauthConfigService = OAuthConfigService.getInstance();
|
|
61
122
|
|
|
62
123
|
try {
|
|
63
124
|
// Check if OAuth configs already exist
|
|
64
|
-
const existingConfigs = await
|
|
125
|
+
const existingConfigs = await oauthConfigService.getAllConfigs();
|
|
65
126
|
const existingProviders = existingConfigs.map((config) => config.provider.toLowerCase());
|
|
66
127
|
|
|
67
|
-
//
|
|
68
|
-
|
|
69
|
-
await oauthService.createConfig({
|
|
70
|
-
provider: 'google',
|
|
71
|
-
useSharedKey: true,
|
|
72
|
-
});
|
|
73
|
-
logger.info('✅ Default Google OAuth config created');
|
|
74
|
-
}
|
|
128
|
+
// Default providers to seed
|
|
129
|
+
const defaultProviders: OAuthProvidersSchema[] = ['google', 'github'];
|
|
75
130
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
131
|
+
for (const provider of defaultProviders) {
|
|
132
|
+
if (!existingProviders.includes(provider)) {
|
|
133
|
+
await oauthConfigService.createConfig({
|
|
134
|
+
provider,
|
|
135
|
+
useSharedKey: true,
|
|
136
|
+
});
|
|
137
|
+
logger.info(`✅ Default ${provider} OAuth config created`);
|
|
138
|
+
}
|
|
83
139
|
}
|
|
84
140
|
} catch (error) {
|
|
85
141
|
logger.warn('Failed to seed OAuth configs', {
|
|
@@ -93,41 +149,59 @@ async function seedDefaultOAuthConfigs(): Promise<void> {
|
|
|
93
149
|
* Seeds OAuth configurations from local environment variables
|
|
94
150
|
*/
|
|
95
151
|
async function seedLocalOAuthConfigs(): Promise<void> {
|
|
96
|
-
const
|
|
152
|
+
const oauthConfigService = OAuthConfigService.getInstance();
|
|
97
153
|
|
|
98
154
|
try {
|
|
99
155
|
// Check if OAuth configs already exist
|
|
100
|
-
const existingConfigs = await
|
|
156
|
+
const existingConfigs = await oauthConfigService.getAllConfigs();
|
|
101
157
|
const existingProviders = existingConfigs.map((config) => config.provider.toLowerCase());
|
|
102
158
|
|
|
103
|
-
//
|
|
104
|
-
const
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
159
|
+
// Environment variable mappings for OAuth providers
|
|
160
|
+
const envMappings: Array<{
|
|
161
|
+
provider: OAuthProvidersSchema;
|
|
162
|
+
clientIdEnv: string;
|
|
163
|
+
clientSecretEnv: string;
|
|
164
|
+
}> = [
|
|
165
|
+
{
|
|
109
166
|
provider: 'google',
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
167
|
+
clientIdEnv: 'GOOGLE_CLIENT_ID',
|
|
168
|
+
clientSecretEnv: 'GOOGLE_CLIENT_SECRET',
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
provider: 'github',
|
|
172
|
+
clientIdEnv: 'GITHUB_CLIENT_ID',
|
|
173
|
+
clientSecretEnv: 'GITHUB_CLIENT_SECRET',
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
provider: 'discord',
|
|
177
|
+
clientIdEnv: 'DISCORD_CLIENT_ID',
|
|
178
|
+
clientSecretEnv: 'DISCORD_CLIENT_SECRET',
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
provider: 'linkedin',
|
|
182
|
+
clientIdEnv: 'LINKEDIN_CLIENT_ID',
|
|
183
|
+
clientSecretEnv: 'LINKEDIN_CLIENT_SECRET',
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
provider: 'microsoft',
|
|
187
|
+
clientIdEnv: 'MICROSOFT_CLIENT_ID',
|
|
188
|
+
clientSecretEnv: 'MICROSOFT_CLIENT_SECRET',
|
|
189
|
+
},
|
|
190
|
+
];
|
|
117
191
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
192
|
+
for (const { provider, clientIdEnv, clientSecretEnv } of envMappings) {
|
|
193
|
+
const clientId = process.env[clientIdEnv];
|
|
194
|
+
const clientSecret = process.env[clientSecretEnv];
|
|
121
195
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
196
|
+
if (clientId && clientSecret && !existingProviders.includes(provider)) {
|
|
197
|
+
await oauthConfigService.createConfig({
|
|
198
|
+
provider,
|
|
199
|
+
clientId,
|
|
200
|
+
clientSecret,
|
|
201
|
+
useSharedKey: false,
|
|
202
|
+
});
|
|
203
|
+
logger.info(`✅ ${provider} OAuth config loaded from environment variables`);
|
|
204
|
+
}
|
|
131
205
|
}
|
|
132
206
|
} catch (error) {
|
|
133
207
|
logger.warn('Failed to seed local OAuth configs', {
|
|
@@ -138,7 +212,8 @@ async function seedLocalOAuthConfigs(): Promise<void> {
|
|
|
138
212
|
|
|
139
213
|
// Create api key, admin user, and default AI configs
|
|
140
214
|
export async function seedBackend(): Promise<void> {
|
|
141
|
-
const secretService =
|
|
215
|
+
const secretService = SecretService.getInstance();
|
|
216
|
+
|
|
142
217
|
const dbManager = DatabaseManager.getInstance();
|
|
143
218
|
|
|
144
219
|
const adminEmail = process.env.ADMIN_EMAIL || 'admin@example.com';
|
|
@@ -163,13 +238,16 @@ export async function seedBackend(): Promise<void> {
|
|
|
163
238
|
});
|
|
164
239
|
// Database connection info is already logged above
|
|
165
240
|
|
|
166
|
-
if (tables.length
|
|
241
|
+
if (tables.length) {
|
|
167
242
|
logger.info(`✅ Found ${tables.length} user tables`);
|
|
168
243
|
}
|
|
169
244
|
|
|
170
245
|
// seed AI configs for cloud environment
|
|
171
246
|
await seedDefaultAIConfigs();
|
|
172
247
|
|
|
248
|
+
// Enable email verification in cloud environment
|
|
249
|
+
await seedDefaultAuthConfig();
|
|
250
|
+
|
|
173
251
|
// add default OAuth configs in Cloud hosting
|
|
174
252
|
if (isCloudEnvironment()) {
|
|
175
253
|
await seedDefaultOAuthConfigs();
|
|
@@ -180,15 +258,30 @@ export async function seedBackend(): Promise<void> {
|
|
|
180
258
|
// Initialize reserved secrets for edge functions
|
|
181
259
|
// Add INSFORGE_INTERNAL_URL for Deno-to-backend container communication
|
|
182
260
|
const insforgInternalUrl = 'http://insforge:7130';
|
|
183
|
-
const
|
|
261
|
+
const existingInternalUrlSecret = await secretService.getSecretByKey('INSFORGE_INTERNAL_URL');
|
|
184
262
|
|
|
185
|
-
if (
|
|
263
|
+
if (existingInternalUrlSecret === null) {
|
|
186
264
|
await secretService.createSecret({
|
|
187
265
|
key: 'INSFORGE_INTERNAL_URL',
|
|
188
266
|
isReserved: true,
|
|
189
267
|
value: insforgInternalUrl,
|
|
190
268
|
});
|
|
191
|
-
logger.info('✅
|
|
269
|
+
logger.info('✅ INSFORGE_INTERNAL_URL secret initialized');
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// Add ANON_KEY for public edge function access
|
|
273
|
+
const existingAnonKeySecret = await secretService.getSecretByKey('ANON_KEY');
|
|
274
|
+
|
|
275
|
+
if (existingAnonKeySecret === null) {
|
|
276
|
+
const tokenManager = TokenManager.getInstance();
|
|
277
|
+
const anonToken = tokenManager.generateAnonToken();
|
|
278
|
+
|
|
279
|
+
await secretService.createSecret({
|
|
280
|
+
key: 'ANON_KEY',
|
|
281
|
+
isReserved: true,
|
|
282
|
+
value: anonToken,
|
|
283
|
+
});
|
|
284
|
+
logger.info('✅ ANON_KEY secret initialized');
|
|
192
285
|
}
|
|
193
286
|
|
|
194
287
|
logger.info(`API key generated: ${apiKey}`);
|
|
@@ -49,7 +49,7 @@ export function parseSQLStatements(sqlText: string): string[] {
|
|
|
49
49
|
.replace(/--.*$/gm, '') // Remove line comments
|
|
50
50
|
.replace(/\/\*[\s\S]*?\*\//g, '') // Remove block comments
|
|
51
51
|
.trim();
|
|
52
|
-
return withoutComments.length
|
|
52
|
+
return withoutComments.length;
|
|
53
53
|
});
|
|
54
54
|
|
|
55
55
|
logger.debug(`Parsed ${statements.length} SQL statements from input`);
|