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
|
@@ -1,530 +0,0 @@
|
|
|
1
|
-
import { useState, useEffect, useRef, useCallback } from 'react';
|
|
2
|
-
import { useQuery } from '@tanstack/react-query';
|
|
3
|
-
import { RefreshCw, Search, FileText, Play, Pause, ChevronUp } from 'lucide-react';
|
|
4
|
-
import { analyticsService } from '@/features/logs/services/log.service';
|
|
5
|
-
import { Button } from '@/components/radix/Button';
|
|
6
|
-
import { Input } from '@/components/radix/Input';
|
|
7
|
-
import { Alert, AlertDescription } from '@/components/radix/Alert';
|
|
8
|
-
import { Card, CardContent, CardHeader, CardTitle } from '@/components/radix/Card';
|
|
9
|
-
import { Tabs, TabsList, TabsTrigger } from '@/components/radix/Tabs';
|
|
10
|
-
import {
|
|
11
|
-
Select,
|
|
12
|
-
SelectContent,
|
|
13
|
-
SelectItem,
|
|
14
|
-
SelectTrigger,
|
|
15
|
-
SelectValue,
|
|
16
|
-
} from '@/components/radix/Select';
|
|
17
|
-
import { AnalyticsLogsTable } from '@/features/logs/components/AnalyticsLogsTable';
|
|
18
|
-
import {
|
|
19
|
-
Tooltip,
|
|
20
|
-
TooltipContent,
|
|
21
|
-
TooltipProvider,
|
|
22
|
-
TooltipTrigger,
|
|
23
|
-
} from '@/components/radix/Tooltip';
|
|
24
|
-
|
|
25
|
-
export default function AnalyticsLogsPage() {
|
|
26
|
-
const [searchQuery, setSearchQuery] = useState('');
|
|
27
|
-
const [selectedSource, setSelectedSource] = useState<string>('');
|
|
28
|
-
const [activeTab, setActiveTab] = useState('overview');
|
|
29
|
-
const [autoRefresh, setAutoRefresh] = useState(false);
|
|
30
|
-
const [refreshInterval, setRefreshInterval] = useState(3000); // 3 seconds
|
|
31
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
32
|
-
const [loadedLogs, setLoadedLogs] = useState<any[]>([]);
|
|
33
|
-
const [hasMore, setHasMore] = useState(true);
|
|
34
|
-
const [isLoadingMore, setIsLoadingMore] = useState(false);
|
|
35
|
-
const [isAutoScrolling, setIsAutoScrolling] = useState(false);
|
|
36
|
-
|
|
37
|
-
const scrollRef = useRef<HTMLDivElement>(null);
|
|
38
|
-
// intervalRef is used for auto-refresh but currently not actively used
|
|
39
|
-
// const _intervalRef = useRef<NodeJS.Timeout | null>(null);
|
|
40
|
-
const pageSize = 100;
|
|
41
|
-
|
|
42
|
-
// Fetch log sources
|
|
43
|
-
const {
|
|
44
|
-
data: sources,
|
|
45
|
-
// sourcesLoading is available but not currently used in the UI
|
|
46
|
-
isLoading: _sourcesLoading,
|
|
47
|
-
error: sourcesError,
|
|
48
|
-
refetch: refetchSources,
|
|
49
|
-
} = useQuery({
|
|
50
|
-
queryKey: ['analytics-sources'],
|
|
51
|
-
queryFn: () => analyticsService.getLogSources(),
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
// Fetch stats
|
|
55
|
-
const {
|
|
56
|
-
data: stats,
|
|
57
|
-
isLoading: statsLoading,
|
|
58
|
-
error: statsError,
|
|
59
|
-
refetch: refetchStats,
|
|
60
|
-
} = useQuery({
|
|
61
|
-
queryKey: ['analytics-stats'],
|
|
62
|
-
queryFn: () => analyticsService.getLogSourceStats(),
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
// Fetch initial logs for selected source
|
|
66
|
-
const {
|
|
67
|
-
data: initialLogsData,
|
|
68
|
-
isLoading: logsLoading,
|
|
69
|
-
error: logsError,
|
|
70
|
-
refetch: refetchInitialLogs,
|
|
71
|
-
} = useQuery({
|
|
72
|
-
queryKey: ['analytics-logs-initial', selectedSource],
|
|
73
|
-
queryFn: async () => {
|
|
74
|
-
if (!selectedSource) {
|
|
75
|
-
return null;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// Get initial logs without beforeTimestamp (gets newest logs)
|
|
79
|
-
const data = await analyticsService.getLogsBySource(selectedSource, pageSize);
|
|
80
|
-
|
|
81
|
-
// Backend now returns logs in correct chronological order (oldest first, newest last)
|
|
82
|
-
return {
|
|
83
|
-
logs: data.logs || [],
|
|
84
|
-
total: data.total || 0,
|
|
85
|
-
tableName: data.tableName,
|
|
86
|
-
};
|
|
87
|
-
},
|
|
88
|
-
enabled: !!selectedSource,
|
|
89
|
-
refetchInterval: autoRefresh ? refreshInterval : false,
|
|
90
|
-
retry: 1, // Retry failed requests once
|
|
91
|
-
staleTime: 0, // Always refetch when switching sources
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
// Search logs (no pagination for search, just show first results)
|
|
95
|
-
const {
|
|
96
|
-
data: searchResults,
|
|
97
|
-
isLoading: searchLoading,
|
|
98
|
-
error: searchError,
|
|
99
|
-
refetch: refetchSearch,
|
|
100
|
-
} = useQuery({
|
|
101
|
-
queryKey: ['analytics-search', searchQuery, pageSize],
|
|
102
|
-
queryFn: async () => {
|
|
103
|
-
if (!searchQuery.trim()) {
|
|
104
|
-
return null;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
const data = await analyticsService.searchLogs(searchQuery, undefined, pageSize, 0);
|
|
108
|
-
return {
|
|
109
|
-
records: data.records || [],
|
|
110
|
-
total: data.total || 0,
|
|
111
|
-
};
|
|
112
|
-
},
|
|
113
|
-
enabled: !!searchQuery.trim(),
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
// Combined effect to handle source changes and data updates
|
|
117
|
-
useEffect(() => {
|
|
118
|
-
// If we have data for the current selected source, update the logs
|
|
119
|
-
if (initialLogsData?.logs !== undefined) {
|
|
120
|
-
setLoadedLogs(initialLogsData.logs);
|
|
121
|
-
setHasMore(initialLogsData.logs.length === pageSize);
|
|
122
|
-
setIsLoadingMore(false);
|
|
123
|
-
|
|
124
|
-
// Only auto-scroll if we have logs
|
|
125
|
-
if (initialLogsData.logs.length > 0) {
|
|
126
|
-
// Scroll to bottom on initial load to show newest logs
|
|
127
|
-
setIsAutoScrolling(true);
|
|
128
|
-
|
|
129
|
-
const scrollToBottom = () => {
|
|
130
|
-
if (scrollRef.current) {
|
|
131
|
-
scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
|
|
132
|
-
}
|
|
133
|
-
};
|
|
134
|
-
|
|
135
|
-
requestAnimationFrame(() => {
|
|
136
|
-
scrollToBottom();
|
|
137
|
-
setTimeout(scrollToBottom, 50);
|
|
138
|
-
setTimeout(scrollToBottom, 200);
|
|
139
|
-
setTimeout(() => {
|
|
140
|
-
scrollToBottom();
|
|
141
|
-
setIsAutoScrolling(false);
|
|
142
|
-
}, 500);
|
|
143
|
-
});
|
|
144
|
-
} else {
|
|
145
|
-
setIsAutoScrolling(false);
|
|
146
|
-
}
|
|
147
|
-
} else if (selectedSource && !initialLogsData) {
|
|
148
|
-
// If we have a selected source but no data yet, reset state
|
|
149
|
-
setLoadedLogs([]);
|
|
150
|
-
setHasMore(true);
|
|
151
|
-
setIsLoadingMore(false);
|
|
152
|
-
setIsAutoScrolling(false);
|
|
153
|
-
|
|
154
|
-
// Reset scroll position when source changes
|
|
155
|
-
if (scrollRef.current) {
|
|
156
|
-
scrollRef.current.scrollTop = 0;
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
}, [selectedSource, initialLogsData, pageSize]);
|
|
160
|
-
|
|
161
|
-
// Auto scroll to bottom when new logs arrive and auto-refresh is on
|
|
162
|
-
useEffect(() => {
|
|
163
|
-
if (autoRefresh && scrollRef.current && loadedLogs.length > 0) {
|
|
164
|
-
scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
|
|
165
|
-
}
|
|
166
|
-
}, [loadedLogs.length, autoRefresh]);
|
|
167
|
-
|
|
168
|
-
// Load more older logs (prepend to the beginning of the list)
|
|
169
|
-
const loadMoreLogs = useCallback(async () => {
|
|
170
|
-
if (!selectedSource || !hasMore || isLoadingMore) {
|
|
171
|
-
return;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
setIsLoadingMore(true);
|
|
175
|
-
try {
|
|
176
|
-
// Get the timestamp of the oldest log currently loaded
|
|
177
|
-
// Since logs are in chronological order (oldest first), loadedLogs[0] is the oldest
|
|
178
|
-
const oldestTimestamp = loadedLogs.length > 0 ? loadedLogs[0]?.timestamp : undefined;
|
|
179
|
-
|
|
180
|
-
const data = await analyticsService.getLogsBySource(
|
|
181
|
-
selectedSource,
|
|
182
|
-
pageSize,
|
|
183
|
-
oldestTimestamp
|
|
184
|
-
);
|
|
185
|
-
|
|
186
|
-
if (data.logs && data.logs.length > 0) {
|
|
187
|
-
// Backend returns logs in chronological order (oldest first, newest last)
|
|
188
|
-
// Prepend older logs to the beginning of the list
|
|
189
|
-
setLoadedLogs((prev) => [...data.logs, ...prev]);
|
|
190
|
-
setHasMore(data.logs.length === pageSize);
|
|
191
|
-
} else {
|
|
192
|
-
setHasMore(false);
|
|
193
|
-
}
|
|
194
|
-
} catch (error) {
|
|
195
|
-
console.error('Failed to load more logs:', error);
|
|
196
|
-
} finally {
|
|
197
|
-
setIsLoadingMore(false);
|
|
198
|
-
}
|
|
199
|
-
}, [selectedSource, loadedLogs, hasMore, isLoadingMore, pageSize]);
|
|
200
|
-
|
|
201
|
-
// Handle scroll to load more
|
|
202
|
-
const handleScroll = useCallback(
|
|
203
|
-
(e: React.UIEvent<HTMLDivElement>) => {
|
|
204
|
-
// Skip scroll handling during auto-scroll to prevent unwanted loads
|
|
205
|
-
if (isAutoScrolling) {
|
|
206
|
-
return;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
const { scrollTop } = e.currentTarget;
|
|
210
|
-
|
|
211
|
-
// Load more when scrolled to top (for older logs)
|
|
212
|
-
// Since logs are in chronological order (oldest to newest), older logs go at the top
|
|
213
|
-
if (scrollTop <= 100 && hasMore && !isLoadingMore) {
|
|
214
|
-
void loadMoreLogs();
|
|
215
|
-
}
|
|
216
|
-
},
|
|
217
|
-
[hasMore, isLoadingMore, loadMoreLogs, isAutoScrolling]
|
|
218
|
-
);
|
|
219
|
-
|
|
220
|
-
const handleRefresh = () => {
|
|
221
|
-
void refetchSources();
|
|
222
|
-
void refetchStats();
|
|
223
|
-
void refetchInitialLogs();
|
|
224
|
-
void refetchSearch();
|
|
225
|
-
};
|
|
226
|
-
|
|
227
|
-
const toggleAutoRefresh = () => {
|
|
228
|
-
setAutoRefresh(!autoRefresh);
|
|
229
|
-
};
|
|
230
|
-
|
|
231
|
-
const scrollToBottom = () => {
|
|
232
|
-
if (scrollRef.current) {
|
|
233
|
-
scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
|
|
234
|
-
}
|
|
235
|
-
};
|
|
236
|
-
|
|
237
|
-
const formatLastActivity = (timestamp: string) => {
|
|
238
|
-
if (!timestamp) {
|
|
239
|
-
return 'Never';
|
|
240
|
-
}
|
|
241
|
-
return new Date(timestamp).toLocaleString();
|
|
242
|
-
};
|
|
243
|
-
|
|
244
|
-
return (
|
|
245
|
-
<div className="flex h-full bg-bg-gray dark:bg-neutral-800">
|
|
246
|
-
<div className="flex-1 min-w-0 flex flex-col overflow-hidden">
|
|
247
|
-
{/* Sticky Header Section */}
|
|
248
|
-
<div className="sticky top-0 z-30 bg-bg-gray dark:bg-neutral-800">
|
|
249
|
-
<div className="px-8 pt-6 pb-4">
|
|
250
|
-
{/* Page Header */}
|
|
251
|
-
<div className="flex items-center justify-between">
|
|
252
|
-
<div className="flex items-center">
|
|
253
|
-
<nav className="flex items-center text-[22px] font-semibold">
|
|
254
|
-
<span className="text-gray-900 dark:text-white">Analytics Logs</span>
|
|
255
|
-
</nav>
|
|
256
|
-
|
|
257
|
-
{/* Separator */}
|
|
258
|
-
<div className="mx-4 h-6 w-px bg-gray-200 dark:bg-neutral-500" />
|
|
259
|
-
|
|
260
|
-
{/* Action buttons group */}
|
|
261
|
-
<div className="flex items-center gap-2">
|
|
262
|
-
<TooltipProvider>
|
|
263
|
-
<Tooltip>
|
|
264
|
-
<TooltipTrigger asChild>
|
|
265
|
-
<Button
|
|
266
|
-
variant="ghost"
|
|
267
|
-
size="icon"
|
|
268
|
-
className="h-9 w-9"
|
|
269
|
-
onClick={handleRefresh}
|
|
270
|
-
>
|
|
271
|
-
<RefreshCw className="h-4 w-4 text-zinc-900 dark:text-white" />
|
|
272
|
-
</Button>
|
|
273
|
-
</TooltipTrigger>
|
|
274
|
-
<TooltipContent side="bottom" align="center">
|
|
275
|
-
<p>Refresh</p>
|
|
276
|
-
</TooltipContent>
|
|
277
|
-
</Tooltip>
|
|
278
|
-
</TooltipProvider>
|
|
279
|
-
|
|
280
|
-
{/* Auto-refresh toggle */}
|
|
281
|
-
<div className="flex items-center space-x-1">
|
|
282
|
-
<TooltipProvider>
|
|
283
|
-
<Tooltip>
|
|
284
|
-
<TooltipTrigger asChild>
|
|
285
|
-
<Button
|
|
286
|
-
variant={autoRefresh ? 'default' : 'ghost'}
|
|
287
|
-
size="sm"
|
|
288
|
-
className="h-9 px-3 dark:bg-emerald-300 dark:text-black dark:hover:bg-emerald-200"
|
|
289
|
-
onClick={toggleAutoRefresh}
|
|
290
|
-
>
|
|
291
|
-
{autoRefresh ? (
|
|
292
|
-
<Pause className="h-4 w-4 mr-1" />
|
|
293
|
-
) : (
|
|
294
|
-
<Play className="h-4 w-4 mr-1" />
|
|
295
|
-
)}
|
|
296
|
-
<span className="text-xs">{refreshInterval / 1000}s</span>
|
|
297
|
-
</Button>
|
|
298
|
-
</TooltipTrigger>
|
|
299
|
-
<TooltipContent side="bottom" align="center">
|
|
300
|
-
<p>{autoRefresh ? 'Stop' : 'Start'} auto-refresh</p>
|
|
301
|
-
</TooltipContent>
|
|
302
|
-
</Tooltip>
|
|
303
|
-
</TooltipProvider>
|
|
304
|
-
|
|
305
|
-
{/* Refresh interval selector */}
|
|
306
|
-
<Select
|
|
307
|
-
value={refreshInterval.toString()}
|
|
308
|
-
onValueChange={(value) => setRefreshInterval(parseInt(value))}
|
|
309
|
-
disabled={autoRefresh}
|
|
310
|
-
>
|
|
311
|
-
<SelectTrigger className="w-16 h-9 text-xs dark:bg-neutral-700 dark:text-white">
|
|
312
|
-
<SelectValue />
|
|
313
|
-
</SelectTrigger>
|
|
314
|
-
<SelectContent>
|
|
315
|
-
<SelectItem value="1000">1s</SelectItem>
|
|
316
|
-
<SelectItem value="3000">3s</SelectItem>
|
|
317
|
-
<SelectItem value="5000">5s</SelectItem>
|
|
318
|
-
<SelectItem value="10000">10s</SelectItem>
|
|
319
|
-
</SelectContent>
|
|
320
|
-
</Select>
|
|
321
|
-
</div>
|
|
322
|
-
|
|
323
|
-
{/* Scroll to bottom button */}
|
|
324
|
-
{activeTab === 'logs' && selectedSource && (
|
|
325
|
-
<TooltipProvider>
|
|
326
|
-
<Tooltip>
|
|
327
|
-
<TooltipTrigger asChild>
|
|
328
|
-
<Button
|
|
329
|
-
variant="ghost"
|
|
330
|
-
size="icon"
|
|
331
|
-
className="h-9 w-9 dark:bg-emerald-300 dark:text-black dark:hover:bg-emerald-200"
|
|
332
|
-
onClick={scrollToBottom}
|
|
333
|
-
>
|
|
334
|
-
<ChevronUp className="h-4 w-4 rotate-180" />
|
|
335
|
-
</Button>
|
|
336
|
-
</TooltipTrigger>
|
|
337
|
-
<TooltipContent side="bottom" align="center">
|
|
338
|
-
<p>Scroll to latest</p>
|
|
339
|
-
</TooltipContent>
|
|
340
|
-
</Tooltip>
|
|
341
|
-
</TooltipProvider>
|
|
342
|
-
)}
|
|
343
|
-
</div>
|
|
344
|
-
</div>
|
|
345
|
-
</div>
|
|
346
|
-
|
|
347
|
-
{/* Tabs */}
|
|
348
|
-
<div className="mt-6">
|
|
349
|
-
<Tabs value={activeTab} onValueChange={setActiveTab}>
|
|
350
|
-
<TabsList className="grid w-full grid-cols-2 lg:w-[400px] dark:bg-neutral-700 dark:text-white">
|
|
351
|
-
<TabsTrigger
|
|
352
|
-
value="overview"
|
|
353
|
-
className="dark:data-[state=active]:bg-emerald-300 dark:data-[state=active]:text-black"
|
|
354
|
-
>
|
|
355
|
-
Overview
|
|
356
|
-
</TabsTrigger>
|
|
357
|
-
<TabsTrigger
|
|
358
|
-
value="logs"
|
|
359
|
-
className="dark:data-[state=active]:bg-emerald-300 dark:data-[state=active]:text-black"
|
|
360
|
-
>
|
|
361
|
-
Logs
|
|
362
|
-
</TabsTrigger>
|
|
363
|
-
{/* <TabsTrigger value="search" className="dark:data-[state=active]:bg-emerald-300 dark:data-[state=active]:text-black">Search</TabsTrigger> */}
|
|
364
|
-
</TabsList>
|
|
365
|
-
</Tabs>
|
|
366
|
-
</div>
|
|
367
|
-
</div>
|
|
368
|
-
</div>
|
|
369
|
-
|
|
370
|
-
{/* Content */}
|
|
371
|
-
<div className="flex-1 flex flex-col overflow-hidden">
|
|
372
|
-
{(sourcesError || statsError || logsError || searchError) && (
|
|
373
|
-
<Alert
|
|
374
|
-
variant="destructive"
|
|
375
|
-
className="mb-4 mx-8 mt-4 dark:bg-neutral-700 dark:text-white"
|
|
376
|
-
>
|
|
377
|
-
<AlertDescription>
|
|
378
|
-
{String(sourcesError || statsError || logsError || searchError)}
|
|
379
|
-
</AlertDescription>
|
|
380
|
-
</Alert>
|
|
381
|
-
)}
|
|
382
|
-
|
|
383
|
-
{activeTab === 'overview' && (
|
|
384
|
-
<div className="flex-1 overflow-auto px-8 py-6 dark:bg-neutral-800">
|
|
385
|
-
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4 mb-6">
|
|
386
|
-
{/* Stats Cards - only show sources that are available */}
|
|
387
|
-
{stats
|
|
388
|
-
?.filter((stat) => sources?.some((source) => source.name === stat.source))
|
|
389
|
-
.map((stat) => (
|
|
390
|
-
<Card
|
|
391
|
-
key={stat.source}
|
|
392
|
-
className="cursor-pointer hover:shadow-md transition-shadow dark:bg-neutral-800 dark:hover:bg-neutral-700"
|
|
393
|
-
onClick={() => {
|
|
394
|
-
setSelectedSource(stat.source);
|
|
395
|
-
setActiveTab('logs');
|
|
396
|
-
}}
|
|
397
|
-
>
|
|
398
|
-
<CardHeader className="pb-3 pt-4">
|
|
399
|
-
<CardTitle className="text-sm font-medium flex items-center justify-between">
|
|
400
|
-
<span className="truncate">{stat.source}</span>
|
|
401
|
-
{/* <Badge
|
|
402
|
-
variant={stat.count > 0 ? 'default' : 'secondary'}
|
|
403
|
-
className="ml-2"
|
|
404
|
-
>
|
|
405
|
-
{stat.count.toLocaleString()}
|
|
406
|
-
</Badge> */}
|
|
407
|
-
</CardTitle>
|
|
408
|
-
</CardHeader>
|
|
409
|
-
<CardContent className="pt-0">
|
|
410
|
-
<div className="space-y-2">
|
|
411
|
-
{/* <div className="flex items-center text-xs text-gray-600 dark:text-zinc-400">
|
|
412
|
-
<BarChart3 className="h-3 w-3 text-blue-600 dark:text-blue-400 mr-1.5" />
|
|
413
|
-
<span>{stat.count > 0 ? 'Active' : 'No data'}</span>
|
|
414
|
-
</div> */}
|
|
415
|
-
<div className="text-xs text-gray-500 dark:text-zinc-400">
|
|
416
|
-
Last: {formatLastActivity(stat.lastActivity)}
|
|
417
|
-
</div>
|
|
418
|
-
</div>
|
|
419
|
-
</CardContent>
|
|
420
|
-
</Card>
|
|
421
|
-
))}
|
|
422
|
-
</div>
|
|
423
|
-
|
|
424
|
-
{statsLoading && (
|
|
425
|
-
<div className="flex justify-center items-center py-12">
|
|
426
|
-
<div className="text-center">
|
|
427
|
-
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600 dark:border-blue-400 mx-auto mb-4" />
|
|
428
|
-
<p className="text-sm text-gray-500 dark:text-zinc-400">
|
|
429
|
-
Loading analytics data...
|
|
430
|
-
</p>
|
|
431
|
-
</div>
|
|
432
|
-
</div>
|
|
433
|
-
)}
|
|
434
|
-
</div>
|
|
435
|
-
)}
|
|
436
|
-
|
|
437
|
-
{activeTab === 'logs' && (
|
|
438
|
-
<div className="flex-1 flex flex-col overflow-hidden">
|
|
439
|
-
{/* Source selector */}
|
|
440
|
-
<div className="px-8 pb-2 border-b bg-gray-50 dark:bg-neutral-800 dark:border-neutral-700 dark:text-white">
|
|
441
|
-
<Select value={selectedSource} onValueChange={setSelectedSource}>
|
|
442
|
-
<SelectTrigger className="w-full max-w-sm h-8 text-sm dark:bg-neutral-800 dark:text-white dark:border-neutral-700">
|
|
443
|
-
<SelectValue placeholder="Select a log source..." />
|
|
444
|
-
</SelectTrigger>
|
|
445
|
-
<SelectContent>
|
|
446
|
-
{sources?.map((source) => (
|
|
447
|
-
<SelectItem key={source.id} value={source.name}>
|
|
448
|
-
{source.name}
|
|
449
|
-
</SelectItem>
|
|
450
|
-
))}
|
|
451
|
-
</SelectContent>
|
|
452
|
-
</Select>
|
|
453
|
-
</div>
|
|
454
|
-
|
|
455
|
-
{!selectedSource ? (
|
|
456
|
-
<div className="flex-1 flex items-center justify-center">
|
|
457
|
-
<div className="text-center">
|
|
458
|
-
<FileText className="mx-auto h-12 w-12 text-gray-400 mb-4" />
|
|
459
|
-
<h3 className="text-lg font-medium text-gray-900 mb-2">Select a Log Source</h3>
|
|
460
|
-
<p className="text-sm text-gray-500">
|
|
461
|
-
Choose a log source from the dropdown above to view logs
|
|
462
|
-
</p>
|
|
463
|
-
</div>
|
|
464
|
-
</div>
|
|
465
|
-
) : (
|
|
466
|
-
<AnalyticsLogsTable
|
|
467
|
-
logs={loadedLogs}
|
|
468
|
-
loading={logsLoading && loadedLogs.length === 0}
|
|
469
|
-
source={selectedSource}
|
|
470
|
-
onRefresh={() => void refetchInitialLogs()}
|
|
471
|
-
onScroll={handleScroll}
|
|
472
|
-
scrollRef={scrollRef}
|
|
473
|
-
hasMore={hasMore}
|
|
474
|
-
isLoadingMore={isLoadingMore}
|
|
475
|
-
autoRefresh={autoRefresh}
|
|
476
|
-
onScrollToBottom={scrollToBottom}
|
|
477
|
-
/>
|
|
478
|
-
)}
|
|
479
|
-
</div>
|
|
480
|
-
)}
|
|
481
|
-
|
|
482
|
-
{activeTab === 'search' && (
|
|
483
|
-
<div className="flex-1 flex flex-col overflow-hidden">
|
|
484
|
-
{/* Search Bar */}
|
|
485
|
-
<div className="px-8 pb-2 border-b bg-gray-50 dark:bg-neutral-800 dark:border-neutral-700">
|
|
486
|
-
<div className="relative">
|
|
487
|
-
<Search className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-500" />
|
|
488
|
-
<Input
|
|
489
|
-
placeholder="Search across all logs..."
|
|
490
|
-
value={searchQuery}
|
|
491
|
-
onChange={(e) => setSearchQuery(e.target.value)}
|
|
492
|
-
className="pl-9 h-8 bg-white border-gray-200 rounded text-sm dark:bg-neutral-800 dark:text-white dark:border-neutral-700"
|
|
493
|
-
/>
|
|
494
|
-
</div>
|
|
495
|
-
</div>
|
|
496
|
-
|
|
497
|
-
{!searchQuery.trim() ? (
|
|
498
|
-
<div className="flex-1 flex items-center justify-center">
|
|
499
|
-
<div className="text-center">
|
|
500
|
-
<Search className="mx-auto h-12 w-12 text-gray-400 mb-4" />
|
|
501
|
-
<h3 className="text-lg font-medium text-zinc-900 dark:text-white mb-2">
|
|
502
|
-
Search Analytics Logs
|
|
503
|
-
</h3>
|
|
504
|
-
<p className="text-sm text-gray-500 dark:text-zinc-400">
|
|
505
|
-
Enter a search term to find logs across all sources
|
|
506
|
-
</p>
|
|
507
|
-
</div>
|
|
508
|
-
</div>
|
|
509
|
-
) : (
|
|
510
|
-
<AnalyticsLogsTable
|
|
511
|
-
logs={searchResults?.records || []}
|
|
512
|
-
loading={searchLoading}
|
|
513
|
-
source="search"
|
|
514
|
-
onRefresh={() => void refetchSearch()}
|
|
515
|
-
showSource={true}
|
|
516
|
-
onScroll={() => {}}
|
|
517
|
-
scrollRef={scrollRef}
|
|
518
|
-
hasMore={false}
|
|
519
|
-
isLoadingMore={false}
|
|
520
|
-
autoRefresh={false}
|
|
521
|
-
onScrollToBottom={scrollToBottom}
|
|
522
|
-
/>
|
|
523
|
-
)}
|
|
524
|
-
</div>
|
|
525
|
-
)}
|
|
526
|
-
</div>
|
|
527
|
-
</div>
|
|
528
|
-
</div>
|
|
529
|
-
);
|
|
530
|
-
}
|
|
File without changes
|
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
import { RefreshCw, Info } from 'lucide-react';
|
|
2
|
-
import { useMetadata } from '../hooks/useMetadata';
|
|
3
|
-
import { Skeleton } from '@/components/radix/Skeleton';
|
|
4
|
-
import { Button } from '@/components/radix/Button';
|
|
5
|
-
import { Alert, AlertDescription } from '@/components/radix/Alert';
|
|
6
|
-
import {
|
|
7
|
-
Tooltip,
|
|
8
|
-
TooltipContent,
|
|
9
|
-
TooltipProvider,
|
|
10
|
-
TooltipTrigger,
|
|
11
|
-
} from '@/components/radix/Tooltip';
|
|
12
|
-
import { JsonHighlight } from '@/components';
|
|
13
|
-
|
|
14
|
-
export default function MetadataPage() {
|
|
15
|
-
const { metadata, isLoading, error, refetch: refetchMetadata } = useMetadata();
|
|
16
|
-
|
|
17
|
-
const handleRefresh = () => {
|
|
18
|
-
void refetchMetadata();
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
if (error) {
|
|
22
|
-
return (
|
|
23
|
-
<main className="min-h-screen bg-bg-gray">
|
|
24
|
-
<div className="px-8 pt-6 pb-4">
|
|
25
|
-
<div className="flex items-center">
|
|
26
|
-
<nav className="flex items-center text-[22px] font-semibold">
|
|
27
|
-
<span className="text-gray-900 dark:text-white">Metadata</span>
|
|
28
|
-
</nav>
|
|
29
|
-
</div>
|
|
30
|
-
</div>
|
|
31
|
-
<div className="px-8 py-8">
|
|
32
|
-
<Alert variant="destructive">
|
|
33
|
-
<AlertDescription>
|
|
34
|
-
Failed to load metadata. Please try refreshing the page.
|
|
35
|
-
</AlertDescription>
|
|
36
|
-
</Alert>
|
|
37
|
-
</div>
|
|
38
|
-
</main>
|
|
39
|
-
);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
if (isLoading) {
|
|
43
|
-
return <MetadataSkeleton />;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
return (
|
|
47
|
-
<main className="min-h-screen bg-bg-gray dark:bg-neutral-800">
|
|
48
|
-
{/* Header */}
|
|
49
|
-
<div className="sticky top-0 z-30 bg-bg-gray border-b border-gray-200 dark:border-neutral-700 dark:bg-neutral-800">
|
|
50
|
-
<div className="px-8 pt-6 pb-4">
|
|
51
|
-
<div className="flex items-center">
|
|
52
|
-
<nav className="flex items-center text-[22px] font-semibold">
|
|
53
|
-
<span className="text-gray-900 dark:text-white">Metadata</span>
|
|
54
|
-
</nav>
|
|
55
|
-
|
|
56
|
-
{/* Separator */}
|
|
57
|
-
<div className="mx-4 h-6 w-px bg-gray-200 dark:bg-neutral-500" />
|
|
58
|
-
|
|
59
|
-
{/* Action buttons group */}
|
|
60
|
-
<div className="flex items-center gap-1">
|
|
61
|
-
<TooltipProvider>
|
|
62
|
-
<Tooltip>
|
|
63
|
-
<TooltipTrigger asChild>
|
|
64
|
-
<Button variant="ghost" size="icon" className="h-9 w-9" onClick={handleRefresh}>
|
|
65
|
-
<RefreshCw className="h-4 w-4 text-zinc-900 dark:text-white" />
|
|
66
|
-
</Button>
|
|
67
|
-
</TooltipTrigger>
|
|
68
|
-
<TooltipContent>
|
|
69
|
-
<p>Refresh Metadata</p>
|
|
70
|
-
</TooltipContent>
|
|
71
|
-
</Tooltip>
|
|
72
|
-
</TooltipProvider>
|
|
73
|
-
</div>
|
|
74
|
-
</div>
|
|
75
|
-
</div>
|
|
76
|
-
</div>
|
|
77
|
-
|
|
78
|
-
<div className="px-8 py-8">
|
|
79
|
-
{/* Metadata Section */}
|
|
80
|
-
<div className="space-y-6">
|
|
81
|
-
<div>
|
|
82
|
-
<h2 className="text-2xl font-semibold text-gray-900 dark:text-white mb-2">
|
|
83
|
-
System Metadata
|
|
84
|
-
</h2>
|
|
85
|
-
<p className="text-gray-600 dark:text-zinc-400">
|
|
86
|
-
Complete metadata information for the InsForge system
|
|
87
|
-
</p>
|
|
88
|
-
</div>
|
|
89
|
-
|
|
90
|
-
<div className="bg-white dark:bg-neutral-800 rounded-lg border border-gray-200 dark:border-neutral-700 overflow-hidden">
|
|
91
|
-
<div className="flex items-center justify-between px-6 pt-4 bg-white dark:bg-neutral-800">
|
|
92
|
-
<div className="flex items-center gap-2">
|
|
93
|
-
<Info className="h-5 w-5 text-gray-700 dark:text-white" />
|
|
94
|
-
<span className="font-medium text-gray-900 dark:text-white">Raw JSON Data</span>
|
|
95
|
-
</div>
|
|
96
|
-
</div>
|
|
97
|
-
|
|
98
|
-
<div className="px-4 pb-4 pt-4">
|
|
99
|
-
{!metadata && (
|
|
100
|
-
<Alert className="border-yellow-200 bg-yellow-50 mb-4">
|
|
101
|
-
<AlertDescription className="text-yellow-800">
|
|
102
|
-
No metadata available. Please ensure the backend is running and you're
|
|
103
|
-
logged in as an admin.
|
|
104
|
-
</AlertDescription>
|
|
105
|
-
</Alert>
|
|
106
|
-
)}
|
|
107
|
-
|
|
108
|
-
{metadata && <JsonHighlight json={JSON.stringify(metadata, null, 2)} />}
|
|
109
|
-
</div>
|
|
110
|
-
</div>
|
|
111
|
-
</div>
|
|
112
|
-
</div>
|
|
113
|
-
</main>
|
|
114
|
-
);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
function MetadataSkeleton() {
|
|
118
|
-
return (
|
|
119
|
-
<main className="min-h-screen bg-bg-gray">
|
|
120
|
-
<div className="px-8 pt-6 pb-4">
|
|
121
|
-
<div className="flex items-center">
|
|
122
|
-
<nav className="flex items-center text-[22px] font-semibold">
|
|
123
|
-
<span className="text-gray-900">Metadata</span>
|
|
124
|
-
</nav>
|
|
125
|
-
</div>
|
|
126
|
-
</div>
|
|
127
|
-
<div className="px-8 py-8">
|
|
128
|
-
<div className="space-y-6">
|
|
129
|
-
<Skeleton className="h-8 w-48" />
|
|
130
|
-
<Skeleton className="h-4 w-96" />
|
|
131
|
-
<Skeleton className="h-100" />
|
|
132
|
-
</div>
|
|
133
|
-
</div>
|
|
134
|
-
</main>
|
|
135
|
-
);
|
|
136
|
-
}
|