insforge 0.3.3 → 1.2.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 -780
- 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,26 +1,25 @@
|
|
|
1
1
|
import { useState, useEffect, useMemo } from 'react';
|
|
2
2
|
import { useForm } from 'react-hook-form';
|
|
3
3
|
import { zodResolver } from '@hookform/resolvers/zod';
|
|
4
|
-
import {
|
|
4
|
+
import { useQueryClient } from '@tanstack/react-query';
|
|
5
5
|
import { AlertCircle } from 'lucide-react';
|
|
6
6
|
import {
|
|
7
|
+
Alert,
|
|
8
|
+
AlertDescription,
|
|
9
|
+
Button,
|
|
7
10
|
Dialog,
|
|
8
11
|
DialogContent,
|
|
9
12
|
DialogHeader,
|
|
10
13
|
DialogTitle,
|
|
11
14
|
DialogFooter,
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
import {
|
|
15
|
-
import { ScrollArea } from '@/components/radix/ScrollArea';
|
|
16
|
-
import { databaseService } from '@/features/database/services/database.service';
|
|
15
|
+
ScrollArea,
|
|
16
|
+
} from '@/components';
|
|
17
|
+
import { useRecords } from '@/features/database/hooks/useRecords';
|
|
17
18
|
import { buildDynamicSchema, getInitialValues } from '@/features/database';
|
|
18
19
|
import { RecordFormField } from '@/features/database/components/RecordFormField';
|
|
19
20
|
import { cn } from '@/lib/utils/utils';
|
|
20
|
-
import { useToast } from '@/lib/hooks/useToast';
|
|
21
21
|
import { ColumnSchema } from '@insforge/shared-schemas';
|
|
22
22
|
import { SYSTEM_FIELDS } from '../helpers';
|
|
23
|
-
import { ConvertedValue } from '@/components/datagrid/datagridTypes';
|
|
24
23
|
|
|
25
24
|
interface RecordFormDialogProps {
|
|
26
25
|
open: boolean;
|
|
@@ -39,7 +38,7 @@ export function RecordFormDialog({
|
|
|
39
38
|
}: RecordFormDialogProps) {
|
|
40
39
|
const [error, setError] = useState<string | null>(null);
|
|
41
40
|
const queryClient = useQueryClient();
|
|
42
|
-
const {
|
|
41
|
+
const { createRecord, isCreating } = useRecords(tableName);
|
|
43
42
|
|
|
44
43
|
const displayFields = useMemo(() => {
|
|
45
44
|
const filteredFields = schema.filter((field) => !SYSTEM_FIELDS.includes(field.columnName));
|
|
@@ -72,31 +71,21 @@ export function RecordFormDialog({
|
|
|
72
71
|
}
|
|
73
72
|
}, [open]);
|
|
74
73
|
|
|
75
|
-
const createRecordMutation = useMutation({
|
|
76
|
-
mutationFn: (data: { [key: string]: ConvertedValue }) => {
|
|
77
|
-
return databaseService.createRecord(tableName, data);
|
|
78
|
-
},
|
|
79
|
-
onSuccess: () => {
|
|
80
|
-
void queryClient.invalidateQueries({ queryKey: ['records', tableName] });
|
|
81
|
-
void queryClient.invalidateQueries({ queryKey: ['table', tableName] });
|
|
82
|
-
onOpenChange(false);
|
|
83
|
-
form.reset();
|
|
84
|
-
setError(null);
|
|
85
|
-
if (onSuccess) {
|
|
86
|
-
onSuccess();
|
|
87
|
-
}
|
|
88
|
-
showToast('Record created successfully', 'success');
|
|
89
|
-
},
|
|
90
|
-
onError: (err: Error) => {
|
|
91
|
-
setError(err.message || 'Failed to create record');
|
|
92
|
-
},
|
|
93
|
-
});
|
|
94
|
-
|
|
95
74
|
const handleSubmit = form.handleSubmit(
|
|
96
75
|
async (data) => {
|
|
97
76
|
try {
|
|
98
|
-
await
|
|
77
|
+
await createRecord(data);
|
|
78
|
+
void queryClient.invalidateQueries({ queryKey: ['records', tableName] });
|
|
79
|
+
void queryClient.invalidateQueries({ queryKey: ['table', tableName] });
|
|
80
|
+
onOpenChange(false);
|
|
81
|
+
form.reset();
|
|
82
|
+
setError(null);
|
|
83
|
+
if (onSuccess) {
|
|
84
|
+
onSuccess();
|
|
85
|
+
}
|
|
99
86
|
} catch (err) {
|
|
87
|
+
const errorMessage = err instanceof Error ? err.message : 'Failed to create record';
|
|
88
|
+
setError(errorMessage);
|
|
100
89
|
console.error('Form submission error:', err);
|
|
101
90
|
}
|
|
102
91
|
},
|
|
@@ -148,13 +137,13 @@ export function RecordFormDialog({
|
|
|
148
137
|
</Button>
|
|
149
138
|
<Button
|
|
150
139
|
type="submit"
|
|
151
|
-
disabled={
|
|
140
|
+
disabled={isCreating}
|
|
152
141
|
className={cn(
|
|
153
142
|
'h-10 px-4 bg-zinc-950 text-white hover:bg-zinc-800 dark:bg-emerald-300 dark:text-zinc-950 dark:hover:bg-emerald-400',
|
|
154
|
-
|
|
143
|
+
isCreating && 'opacity-40'
|
|
155
144
|
)}
|
|
156
145
|
>
|
|
157
|
-
{
|
|
146
|
+
{isCreating ? 'Saving...' : 'Add Record'}
|
|
158
147
|
</Button>
|
|
159
148
|
</DialogFooter>
|
|
160
149
|
</form>
|
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
import React, { useState } from 'react';
|
|
2
2
|
import { Control, Controller, FieldError, UseFormReturn } from 'react-hook-form';
|
|
3
|
-
import { Input } from '@/components/radix/Input';
|
|
4
|
-
import { Label } from '@/components/radix/Label';
|
|
5
|
-
import { Button } from '@/components/radix/Button';
|
|
6
3
|
import { Calendar, Clock, Link2, X } from 'lucide-react';
|
|
7
4
|
import {
|
|
5
|
+
Button,
|
|
6
|
+
Label,
|
|
7
|
+
Input,
|
|
8
8
|
BooleanCellEditor,
|
|
9
9
|
DateCellEditor,
|
|
10
10
|
JsonCellEditor,
|
|
11
11
|
type DatabaseRecord,
|
|
12
12
|
type ConvertedValue,
|
|
13
13
|
type UserInputValue,
|
|
14
|
-
|
|
14
|
+
TypeBadge,
|
|
15
|
+
} from '@/components';
|
|
15
16
|
import { ColumnSchema, ColumnType } from '@insforge/shared-schemas';
|
|
16
|
-
import { useLinkModal } from '@/features/database/hooks/UseLinkModal';
|
|
17
17
|
import { convertValueForColumn, cn, formatValueForDisplay } from '@/lib/utils/utils';
|
|
18
|
-
import {
|
|
18
|
+
import { LinkRecordModal } from '@/features/database/components/LinkRecordModal';
|
|
19
19
|
import { isValid, parseISO } from 'date-fns';
|
|
20
20
|
|
|
21
21
|
// Helper function to get appropriate placeholder text
|
|
@@ -184,7 +184,7 @@ function FormNumberEditor({ value, type, onChange, tableName, field }: FormNumbe
|
|
|
184
184
|
}
|
|
185
185
|
}}
|
|
186
186
|
placeholder={getPlaceholderText(field)}
|
|
187
|
-
className={`dark:text-white dark:placeholder:text-neutral-400 dark:bg-neutral-900 dark:border-neutral-700 ${field.foreignKey ? 'pr-
|
|
187
|
+
className={`dark:text-white dark:placeholder:text-neutral-400 dark:bg-neutral-900 dark:border-neutral-700 ${field.foreignKey ? 'pr-18' : ''}`}
|
|
188
188
|
/>
|
|
189
189
|
);
|
|
190
190
|
}
|
|
@@ -278,13 +278,14 @@ interface FieldWithLinkProps {
|
|
|
278
278
|
}
|
|
279
279
|
|
|
280
280
|
function FieldWithLink({ field, control, children }: FieldWithLinkProps) {
|
|
281
|
-
const { openModal } = useLinkModal();
|
|
282
|
-
|
|
283
281
|
if (!field.foreignKey) {
|
|
284
282
|
// Regular field without foreign key
|
|
285
283
|
return <>{children}</>;
|
|
286
284
|
}
|
|
287
285
|
|
|
286
|
+
// Store foreignKey in a const to help TypeScript narrow the type
|
|
287
|
+
const foreignKey = field.foreignKey;
|
|
288
|
+
|
|
288
289
|
// Field with foreign key linking capability - integrated design
|
|
289
290
|
return (
|
|
290
291
|
<>
|
|
@@ -309,56 +310,53 @@ function FieldWithLink({ field, control, children }: FieldWithLinkProps) {
|
|
|
309
310
|
<div className="space-y-1">
|
|
310
311
|
<div className="relative">
|
|
311
312
|
{modifiedChildren}
|
|
312
|
-
<div className="absolute right-0 top-1/2 -translate-y-1/2 flex items-center">
|
|
313
|
-
{hasLinkedValue && (
|
|
313
|
+
<div className="absolute right-0 top-1/2 -translate-y-1/2 flex items-center gap-1">
|
|
314
|
+
{(hasLinkedValue || hasLinkedValue === 0) && (
|
|
314
315
|
<Button
|
|
315
316
|
type="button"
|
|
316
317
|
variant="ghost"
|
|
317
318
|
size="icon"
|
|
318
319
|
onClick={() => formField.onChange('')}
|
|
319
|
-
className="h-7 w-7 p-1 flex-shrink-0 text-zinc-500 hover:text-
|
|
320
|
+
className="h-7 w-7 p-1 flex-shrink-0 text-zinc-500 hover:text-zinc-700 hover:bg-zinc-100 dark:text-neutral-400 dark:hover:text-neutral-200 dark:hover:bg-neutral-700"
|
|
320
321
|
title="Clear linked record"
|
|
321
322
|
>
|
|
322
323
|
<X className="h-4 w-4" />
|
|
323
324
|
</Button>
|
|
324
325
|
)}
|
|
325
|
-
<
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
field.type,
|
|
340
|
-
String(referenceValue || '')
|
|
341
|
-
);
|
|
342
|
-
if (result.success) {
|
|
343
|
-
formField.onChange(result.value);
|
|
344
|
-
} else {
|
|
345
|
-
// Fallback to string if conversion fails
|
|
346
|
-
formField.onChange(String(referenceValue || ''));
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
},
|
|
350
|
-
});
|
|
326
|
+
<LinkRecordModal
|
|
327
|
+
referenceTable={foreignKey.referenceTable}
|
|
328
|
+
referenceColumn={foreignKey.referenceColumn}
|
|
329
|
+
onSelectRecord={(record: DatabaseRecord) => {
|
|
330
|
+
const referenceValue = record[foreignKey.referenceColumn];
|
|
331
|
+
const result = convertValueForColumn(
|
|
332
|
+
field.type,
|
|
333
|
+
String(referenceValue || '')
|
|
334
|
+
);
|
|
335
|
+
if (result.success) {
|
|
336
|
+
formField.onChange(result.value);
|
|
337
|
+
} else {
|
|
338
|
+
// Fallback to string if conversion fails
|
|
339
|
+
formField.onChange(String(referenceValue || ''));
|
|
351
340
|
}
|
|
352
341
|
}}
|
|
353
|
-
className="rounded-l-none h-9 w-9 p-2 flex-shrink-0 text-zinc-500 hover:text-zinc-700 hover:bg-zinc-100 dark:text-neutral-400 dark:hover:text-neutral-200 dark:hover:bg-neutral-700 border-l border-zinc-200 dark:border-neutral-700"
|
|
354
|
-
title={
|
|
355
|
-
hasLinkedValue
|
|
356
|
-
? `Change linked ${field.foreignKey?.referenceTable} record`
|
|
357
|
-
: `Link to ${field.foreignKey?.referenceTable} record`
|
|
358
|
-
}
|
|
359
342
|
>
|
|
360
|
-
|
|
361
|
-
|
|
343
|
+
{(openModal) => (
|
|
344
|
+
<Button
|
|
345
|
+
type="button"
|
|
346
|
+
variant="ghost"
|
|
347
|
+
size="icon"
|
|
348
|
+
onClick={openModal}
|
|
349
|
+
className="rounded-l-none h-9 w-9 p-2 flex-shrink-0 text-zinc-500 hover:text-zinc-700 hover:bg-zinc-100 dark:text-neutral-400 dark:hover:text-neutral-200 dark:hover:bg-neutral-700 border-l border-zinc-200 dark:border-neutral-700"
|
|
350
|
+
title={
|
|
351
|
+
hasLinkedValue
|
|
352
|
+
? `Change linked ${foreignKey.referenceTable} record`
|
|
353
|
+
: `Link to ${foreignKey.referenceTable} record`
|
|
354
|
+
}
|
|
355
|
+
>
|
|
356
|
+
<Link2 className="h-5 w-5" />
|
|
357
|
+
</Button>
|
|
358
|
+
)}
|
|
359
|
+
</LinkRecordModal>
|
|
362
360
|
</div>
|
|
363
361
|
</div>
|
|
364
362
|
|
|
@@ -366,7 +364,7 @@ function FieldWithLink({ field, control, children }: FieldWithLinkProps) {
|
|
|
366
364
|
<div className="text-xs text-medium text-black dark:text-neutral-400 flex items-center gap-1.5">
|
|
367
365
|
<span>Has a Foreign Key relation to</span>
|
|
368
366
|
<TypeBadge
|
|
369
|
-
type={`${
|
|
367
|
+
type={`${foreignKey.referenceTable}.${foreignKey.referenceColumn}`}
|
|
370
368
|
className="dark:bg-neutral-700"
|
|
371
369
|
/>
|
|
372
370
|
</div>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Database } from 'lucide-react';
|
|
2
|
+
import { ConnectCTA } from '@/components/ConnectCTA';
|
|
2
3
|
|
|
3
4
|
interface TableEmptyStateProps {
|
|
4
5
|
searchTerm: string;
|
|
@@ -6,14 +7,14 @@ interface TableEmptyStateProps {
|
|
|
6
7
|
|
|
7
8
|
export function TableEmptyState({ searchTerm }: TableEmptyStateProps) {
|
|
8
9
|
return (
|
|
9
|
-
<div className="
|
|
10
|
-
<Database className="
|
|
11
|
-
<p className="text-sm text-
|
|
10
|
+
<div className="flex flex-col items-center justify-center py-4 text-center">
|
|
11
|
+
<Database className="h-10 w-10 text-gray-400 dark:text-neutral-600 mb-3" />
|
|
12
|
+
<p className="text-sm text-gray-600 dark:text-neutral-400 font-medium">
|
|
12
13
|
{searchTerm ? 'No tables found' : 'No tables yet'}
|
|
13
14
|
</p>
|
|
14
15
|
{!searchTerm && (
|
|
15
|
-
<p className="text-xs text-
|
|
16
|
-
Create your first table to get started
|
|
16
|
+
<p className="text-xs text-gray-500 dark:text-neutral-400 font-medium mt-1 mx-10">
|
|
17
|
+
<ConnectCTA fallback="Create your first table to get started" />
|
|
17
18
|
</p>
|
|
18
19
|
)}
|
|
19
20
|
</div>
|
|
@@ -3,10 +3,8 @@ import { useForm, useFieldArray } from 'react-hook-form';
|
|
|
3
3
|
import { zodResolver } from '@hookform/resolvers/zod';
|
|
4
4
|
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
|
5
5
|
import { AlertCircle, Plus, X, Link, MoveRight } from 'lucide-react';
|
|
6
|
-
import { Button } from '@/components
|
|
7
|
-
import {
|
|
8
|
-
import { Alert, AlertDescription } from '@/components/radix/Alert';
|
|
9
|
-
import { databaseService } from '@/features/database/services/database.service';
|
|
6
|
+
import { Alert, AlertDescription, Button, Input } from '@/components';
|
|
7
|
+
import { tableService } from '@/features/database/services/table.service';
|
|
10
8
|
import {
|
|
11
9
|
TableFormColumnSchema,
|
|
12
10
|
TableFormForeignKeySchema,
|
|
@@ -50,6 +48,7 @@ export function TableForm({
|
|
|
50
48
|
const [showForeignKeyDialog, setShowForeignKeyDialog] = useState(false);
|
|
51
49
|
const [editingForeignKey, setEditingForeignKey] = useState<string>();
|
|
52
50
|
const [foreignKeys, setForeignKeys] = useState<TableFormForeignKeySchema[]>([]);
|
|
51
|
+
const [foreignKeysDirty, setForeignKeysDirty] = useState(false);
|
|
53
52
|
const queryClient = useQueryClient();
|
|
54
53
|
const { showToast } = useToast();
|
|
55
54
|
|
|
@@ -220,7 +219,7 @@ export function TableForm({
|
|
|
220
219
|
};
|
|
221
220
|
});
|
|
222
221
|
|
|
223
|
-
return
|
|
222
|
+
return tableService.createTable(data.tableName, columns);
|
|
224
223
|
},
|
|
225
224
|
onSuccess: (data) => {
|
|
226
225
|
void queryClient.invalidateQueries({ queryKey: ['database-metadata'] });
|
|
@@ -232,12 +231,13 @@ export function TableForm({
|
|
|
232
231
|
form.reset();
|
|
233
232
|
setError(null);
|
|
234
233
|
setForeignKeys([]);
|
|
234
|
+
setForeignKeysDirty(false);
|
|
235
235
|
onSuccess?.(data.tableName);
|
|
236
236
|
},
|
|
237
237
|
onError: (err) => {
|
|
238
238
|
const errorMessage = err.message || 'Failed to create table';
|
|
239
239
|
setError(errorMessage);
|
|
240
|
-
showToast(
|
|
240
|
+
showToast(errorMessage, 'error');
|
|
241
241
|
},
|
|
242
242
|
});
|
|
243
243
|
|
|
@@ -350,7 +350,7 @@ export function TableForm({
|
|
|
350
350
|
operations.renameTable = { newTableName: data.tableName };
|
|
351
351
|
}
|
|
352
352
|
|
|
353
|
-
return
|
|
353
|
+
return tableService.updateTableSchema(editTable.tableName, operations);
|
|
354
354
|
},
|
|
355
355
|
onSuccess: (_, data) => {
|
|
356
356
|
void queryClient.invalidateQueries({ queryKey: ['database-metadata'] });
|
|
@@ -377,11 +377,21 @@ export function TableForm({
|
|
|
377
377
|
|
|
378
378
|
const errorMessage = err.message || 'Failed to update table';
|
|
379
379
|
setError(errorMessage);
|
|
380
|
-
showToast(
|
|
380
|
+
showToast(errorMessage, 'error');
|
|
381
381
|
},
|
|
382
382
|
});
|
|
383
383
|
|
|
384
384
|
const handleSubmit = form.handleSubmit((data) => {
|
|
385
|
+
const userColumns = data.columns.filter((col) => !col.isSystemColumn);
|
|
386
|
+
if (!userColumns.length) {
|
|
387
|
+
const msg =
|
|
388
|
+
mode === 'create'
|
|
389
|
+
? 'Please add at least one user-defined column to create a table.'
|
|
390
|
+
: 'Please ensure the table has at least one user-defined column.';
|
|
391
|
+
setError(msg);
|
|
392
|
+
showToast(msg, 'error');
|
|
393
|
+
return;
|
|
394
|
+
}
|
|
385
395
|
if (mode === 'edit') {
|
|
386
396
|
updateTableMutation.mutate(data);
|
|
387
397
|
} else {
|
|
@@ -402,6 +412,7 @@ export function TableForm({
|
|
|
402
412
|
)
|
|
403
413
|
);
|
|
404
414
|
setEditingForeignKey(undefined);
|
|
415
|
+
setForeignKeysDirty(true);
|
|
405
416
|
} else {
|
|
406
417
|
// Add new foreign key
|
|
407
418
|
setForeignKeys([
|
|
@@ -411,10 +422,12 @@ export function TableForm({
|
|
|
411
422
|
},
|
|
412
423
|
]);
|
|
413
424
|
}
|
|
425
|
+
setForeignKeysDirty(true);
|
|
414
426
|
};
|
|
415
427
|
|
|
416
428
|
const handleRemoveForeignKey = (columnName?: string) => {
|
|
417
429
|
setForeignKeys(foreignKeys.filter((fk) => fk.columnName !== columnName));
|
|
430
|
+
setForeignKeysDirty(true);
|
|
418
431
|
};
|
|
419
432
|
|
|
420
433
|
if (!open) {
|
|
@@ -470,7 +483,7 @@ export function TableForm({
|
|
|
470
483
|
{/* Columns Table */}
|
|
471
484
|
<div className="px-3 overflow-x-auto">
|
|
472
485
|
{/* Table Headers */}
|
|
473
|
-
<div className="flex items-center gap-6 px-4 py-2 bg-slate-50 rounded-t text-sm font-medium text-zinc-950 dark:bg-neutral-700 dark:text-white">
|
|
486
|
+
<div className="flex items-center gap-6 px-4 py-2 w-min xl:w-full bg-slate-50 rounded-t text-sm font-medium text-zinc-950 dark:bg-neutral-700 dark:text-white">
|
|
474
487
|
<div className="flex-1 min-w-[175px]">Name</div>
|
|
475
488
|
<div className="flex-1 min-w-[175px]">Type</div>
|
|
476
489
|
<div className="flex-1 min-w-[175px]">Default Value</div>
|
|
@@ -511,7 +524,7 @@ export function TableForm({
|
|
|
511
524
|
</div>
|
|
512
525
|
|
|
513
526
|
{/* Foreign Keys Section */}
|
|
514
|
-
<div className="bg-white pb-3 rounded-xl border border-zinc-200 dark:bg-neutral-800 dark:border-transparent">
|
|
527
|
+
<div className="bg-white pb-3 rounded-xl border border-zinc-200 overflow-hidden dark:bg-neutral-800 dark:border-transparent">
|
|
515
528
|
<div className="p-6">
|
|
516
529
|
<h2 className="text-base font-semibold text-black dark:text-white">Foreign Keys</h2>
|
|
517
530
|
<p className="text-sm text-zinc-500 dark:text-neutral-400">
|
|
@@ -521,11 +534,11 @@ export function TableForm({
|
|
|
521
534
|
|
|
522
535
|
{/* Existing foreign keys */}
|
|
523
536
|
{foreignKeys.length > 0 && (
|
|
524
|
-
<div className="px-6 pb-6 space-y-3">
|
|
537
|
+
<div className="px-6 pb-6 space-y-3 overflow-x-auto">
|
|
525
538
|
{foreignKeys.map((fk) => (
|
|
526
539
|
<div
|
|
527
540
|
key={fk.columnName}
|
|
528
|
-
className="group flex items-center gap-6 2xl:gap-8 pl-4 pr-2 py-2 rounded-lg border border-zinc-200 bg-white hover:bg-zinc-100 transition-colors duration-150 dark:bg-neutral-700 dark:border-transparent dark:hover:bg-neutral-600"
|
|
541
|
+
className="group flex items-center gap-6 2xl:gap-8 pl-4 pr-2 py-2 w-min xl:w-full rounded-lg border border-zinc-200 bg-white hover:bg-zinc-100 transition-colors duration-150 dark:bg-neutral-700 dark:border-transparent dark:hover:bg-neutral-600"
|
|
529
542
|
>
|
|
530
543
|
<div className="flex items-center gap-2 flex-1 min-w-[188px] overflow-hidden">
|
|
531
544
|
<Link className="flex-shrink-0 w-5 h-5 text-zinc-500 dark:text-neutral-400" />
|
|
@@ -632,9 +645,8 @@ export function TableForm({
|
|
|
632
645
|
<div className="flex justify-end gap-3 max-w-[1080px] mx-auto px-6">
|
|
633
646
|
<Button
|
|
634
647
|
type="button"
|
|
635
|
-
variant="outline"
|
|
636
648
|
onClick={() => onOpenChange(false)}
|
|
637
|
-
className="h-10 px-4 text-sm font-medium border-zinc-200 shadow-
|
|
649
|
+
className="h-10 px-4 text-sm font-medium bg-white border border-zinc-200 shadow-[0px_1px_2px_0px_rgba(0,0,0,0.1)] text-zinc-950 hover:bg-zinc-50 dark:bg-neutral-600 dark:border-neutral-600 dark:text-white dark:hover:bg-neutral-700"
|
|
638
650
|
>
|
|
639
651
|
Cancel
|
|
640
652
|
</Button>
|
|
@@ -643,7 +655,8 @@ export function TableForm({
|
|
|
643
655
|
disabled={
|
|
644
656
|
!form.formState.isValid ||
|
|
645
657
|
createTableMutation.isPending ||
|
|
646
|
-
updateTableMutation.isPending
|
|
658
|
+
updateTableMutation.isPending ||
|
|
659
|
+
(!form.formState.isDirty && !foreignKeysDirty)
|
|
647
660
|
}
|
|
648
661
|
className="h-10 px-4 text-sm font-medium bg-zinc-950 text-neutral-50 shadow-sm disabled:opacity-40 dark:bg-emerald-300 dark:text-zinc-950 dark:hover:bg-emerald-400"
|
|
649
662
|
>
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { memo } from 'react';
|
|
2
2
|
import { Controller, Control } from 'react-hook-form';
|
|
3
3
|
import { X, Key } from 'lucide-react';
|
|
4
|
-
import { Input } from '@/components
|
|
5
|
-
import { Checkbox } from '@/components';
|
|
4
|
+
import { Input, Checkbox } from '@/components';
|
|
6
5
|
import { TableFormColumnSchema, TableFormSchema } from '../schema';
|
|
7
6
|
import { ColumnTypeSelect } from './ColumnTypeSelect';
|
|
8
7
|
|
|
@@ -25,7 +24,7 @@ export const TableFormColumn = memo(function TableFormColumn({
|
|
|
25
24
|
}: TableFormColumnProps) {
|
|
26
25
|
return (
|
|
27
26
|
<div
|
|
28
|
-
className={`flex items-center gap-6 px-4 py-2 ${
|
|
27
|
+
className={`flex items-center gap-6 px-4 py-2 w-min xl:w-full ${
|
|
29
28
|
isNewColumn ? 'bg-slate-50 dark:bg-neutral-800' : 'bg-white dark:bg-[#2D2D2D]'
|
|
30
29
|
}`}
|
|
31
30
|
>
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { Plus } from 'lucide-react';
|
|
2
|
+
import { Button } from '@/components/radix/Button';
|
|
3
|
+
import { DatabaseTemplate } from '@/features/database/templates';
|
|
4
|
+
import { TemplateCard } from './TemplateCard';
|
|
5
|
+
|
|
6
|
+
interface TablesEmptyStateProps {
|
|
7
|
+
templates: DatabaseTemplate[];
|
|
8
|
+
onCreateTable: () => void;
|
|
9
|
+
onTemplateClick: (template: DatabaseTemplate) => void;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function TablesEmptyState({
|
|
13
|
+
templates,
|
|
14
|
+
onCreateTable,
|
|
15
|
+
onTemplateClick,
|
|
16
|
+
}: TablesEmptyStateProps) {
|
|
17
|
+
return (
|
|
18
|
+
<div className="flex justify-center w-full h-full bg-bg-gray dark:bg-neutral-800 px-6">
|
|
19
|
+
<div className="flex flex-col gap-6 max-w-[1024px] w-full pb-9 pt-6">
|
|
20
|
+
<h2 className="text-xl font-semibold text-zinc-950 dark:text-white leading-7 tracking-[-0.1px]">
|
|
21
|
+
Create Your First Table
|
|
22
|
+
</h2>
|
|
23
|
+
<Button
|
|
24
|
+
className="h-9 w-50 gap-2 font-medium dark:bg-emerald-300 dark:hover:bg-emerald-400 dark:text-black"
|
|
25
|
+
onClick={onCreateTable}
|
|
26
|
+
>
|
|
27
|
+
<Plus className="w-5 h-5" />
|
|
28
|
+
Create Table
|
|
29
|
+
</Button>
|
|
30
|
+
<div className="flex flex-col gap-3">
|
|
31
|
+
<p className="text-sm font-normal text-zinc-500 dark:text-neutral-400 leading-6">
|
|
32
|
+
or choose a template to start
|
|
33
|
+
</p>
|
|
34
|
+
<div className="grid grid-cols-2 xl:grid-cols-3 gap-6">
|
|
35
|
+
{templates.map((template) => (
|
|
36
|
+
<TemplateCard
|
|
37
|
+
key={template.id}
|
|
38
|
+
template={template}
|
|
39
|
+
onClick={() => onTemplateClick(template)}
|
|
40
|
+
showTableCount
|
|
41
|
+
/>
|
|
42
|
+
))}
|
|
43
|
+
</div>
|
|
44
|
+
</div>
|
|
45
|
+
</div>
|
|
46
|
+
</div>
|
|
47
|
+
);
|
|
48
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { Table } from 'lucide-react';
|
|
2
|
+
import { DatabaseTemplate } from '@/features/database/templates';
|
|
3
|
+
|
|
4
|
+
interface TemplateCardProps {
|
|
5
|
+
template: DatabaseTemplate;
|
|
6
|
+
onClick: () => void;
|
|
7
|
+
showTableCount?: boolean;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function TemplateCard({ template, onClick, showTableCount = false }: TemplateCardProps) {
|
|
11
|
+
return (
|
|
12
|
+
<button
|
|
13
|
+
onClick={onClick}
|
|
14
|
+
className="bg-white dark:bg-[#363636] border border-gray-200 dark:border-[#414141] rounded-[4px] pl-6 pr-4 pt-4 pb-6 text-left transition-colors hover:bg-gray-50 hover:border-gray-300 dark:hover:bg-neutral-700 dark:hover:border-[#525252] hover:shadow-sm flex flex-col gap-3"
|
|
15
|
+
>
|
|
16
|
+
<div className="flex flex-col gap-2">
|
|
17
|
+
<h3 className="text-base font-normal text-zinc-950 dark:text-white leading-6">
|
|
18
|
+
{template.title}
|
|
19
|
+
</h3>
|
|
20
|
+
{/* Fixed height container for description with line clamp */}
|
|
21
|
+
<div className="h-[72px]">
|
|
22
|
+
<p className="text-sm font-normal text-zinc-500 dark:text-neutral-400 leading-6 line-clamp-3">
|
|
23
|
+
{template.description}
|
|
24
|
+
</p>
|
|
25
|
+
</div>
|
|
26
|
+
</div>
|
|
27
|
+
{showTableCount && (
|
|
28
|
+
<div className="flex items-center gap-2">
|
|
29
|
+
<Table className="w-5 h-5 text-zinc-500 dark:text-neutral-400" />
|
|
30
|
+
<p className="text-sm font-normal text-zinc-500 dark:text-neutral-400 leading-6">
|
|
31
|
+
{template.tableCount} {template.tableCount === 1 ? 'Table' : 'Tables'}
|
|
32
|
+
</p>
|
|
33
|
+
</div>
|
|
34
|
+
)}
|
|
35
|
+
</button>
|
|
36
|
+
);
|
|
37
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { Button } from '@/components/radix/Button';
|
|
2
|
+
import { DatabaseTemplate } from '@/features/database/templates';
|
|
3
|
+
import { SchemaVisualizer } from '@/features/visualizer/components/SchemaVisualizer';
|
|
4
|
+
import { useRawSQL } from '@/features/database/hooks/useRawSQL';
|
|
5
|
+
|
|
6
|
+
interface TemplatePreviewProps {
|
|
7
|
+
template: DatabaseTemplate;
|
|
8
|
+
onCancel: () => void;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function TemplatePreview({ template, onCancel }: TemplatePreviewProps) {
|
|
12
|
+
const { executeSQL, isPending } = useRawSQL({
|
|
13
|
+
showSuccessToast: true,
|
|
14
|
+
showErrorToast: true,
|
|
15
|
+
onSuccess: () => {
|
|
16
|
+
// Close preview after successful implementation
|
|
17
|
+
onCancel();
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
const handleImplementTemplate = () => {
|
|
22
|
+
executeSQL({ query: template.sql });
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
return (
|
|
26
|
+
<div className="flex flex-col h-full bg-bg-gray dark:bg-neutral-800">
|
|
27
|
+
{/* Top Bar */}
|
|
28
|
+
<div className="flex items-center justify-center gap-3 h-12 px-4 border-b border-gray-200 dark:border-neutral-700 bg-white dark:bg-neutral-800">
|
|
29
|
+
<p className="text-sm font-normal text-zinc-600 dark:text-neutral-400">
|
|
30
|
+
You are previewing a template
|
|
31
|
+
</p>
|
|
32
|
+
<Button
|
|
33
|
+
variant="outline"
|
|
34
|
+
onClick={onCancel}
|
|
35
|
+
className="h-8 px-4 dark:bg-neutral-600 dark:text-zinc-300 dark:border-neutral-600 dark:hover:bg-neutral-700"
|
|
36
|
+
>
|
|
37
|
+
Cancel
|
|
38
|
+
</Button>
|
|
39
|
+
<Button
|
|
40
|
+
className="h-8 px-4 font-medium bg-emerald-300 hover:bg-emerald-400 text-black dark:bg-emerald-300 dark:hover:bg-emerald-400"
|
|
41
|
+
onClick={handleImplementTemplate}
|
|
42
|
+
disabled={isPending}
|
|
43
|
+
>
|
|
44
|
+
{isPending ? 'Implementing...' : 'Implement Template'}
|
|
45
|
+
</Button>
|
|
46
|
+
</div>
|
|
47
|
+
|
|
48
|
+
{/* Visualizer Content */}
|
|
49
|
+
<div className="relative flex-1 overflow-hidden">
|
|
50
|
+
{/* Dot Matrix Background - Light Mode */}
|
|
51
|
+
<div
|
|
52
|
+
className="absolute inset-0 opacity-50 dark:hidden"
|
|
53
|
+
style={{
|
|
54
|
+
backgroundImage: `radial-gradient(circle, #D1D5DB 1px, transparent 1px)`,
|
|
55
|
+
backgroundSize: '12px 12px',
|
|
56
|
+
}}
|
|
57
|
+
/>
|
|
58
|
+
{/* Dot Matrix Background - Dark Mode */}
|
|
59
|
+
<div
|
|
60
|
+
className="absolute inset-0 opacity-50 hidden dark:block"
|
|
61
|
+
style={{
|
|
62
|
+
backgroundImage: `radial-gradient(circle, #3B3B3B 1px, transparent 1px)`,
|
|
63
|
+
backgroundSize: '12px 12px',
|
|
64
|
+
}}
|
|
65
|
+
/>
|
|
66
|
+
|
|
67
|
+
{/* SchemaVisualizer */}
|
|
68
|
+
<div className="relative z-10 w-full h-full">
|
|
69
|
+
<SchemaVisualizer
|
|
70
|
+
externalSchemas={template.visualizerSchema}
|
|
71
|
+
metadata={{
|
|
72
|
+
auth: {
|
|
73
|
+
oauths: [],
|
|
74
|
+
},
|
|
75
|
+
database: {
|
|
76
|
+
tables: [],
|
|
77
|
+
totalSizeInGB: 0,
|
|
78
|
+
},
|
|
79
|
+
storage: {
|
|
80
|
+
buckets: [],
|
|
81
|
+
totalSizeInGB: 0,
|
|
82
|
+
},
|
|
83
|
+
functions: [],
|
|
84
|
+
}}
|
|
85
|
+
showControls={false}
|
|
86
|
+
showMiniMap={false}
|
|
87
|
+
/>
|
|
88
|
+
</div>
|
|
89
|
+
</div>
|
|
90
|
+
</div>
|
|
91
|
+
);
|
|
92
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export { ColumnTypeSelect } from './ColumnTypeSelect';
|
|
2
|
+
export {
|
|
3
|
+
convertSchemaToColumns,
|
|
4
|
+
DatabaseDataGrid,
|
|
5
|
+
type DatabaseDataGridProps,
|
|
6
|
+
} from './DatabaseDataGrid';
|
|
7
|
+
export { ForeignKeyCell } from './ForeignKeyCell';
|
|
8
|
+
export { ForeignKeyPopover } from './ForeignKeyPopover';
|
|
9
|
+
export { LinkRecordModal } from './LinkRecordModal';
|
|
10
|
+
export { RecordFormDialog } from './RecordFormDialog';
|
|
11
|
+
export { RecordFormField } from './RecordFormField';
|
|
12
|
+
export { TableEmptyState } from './TableEmptyState';
|
|
13
|
+
export { TableForm } from './TableForm';
|
|
14
|
+
export { TableFormColumn } from './TableFormColumn';
|
|
15
|
+
export { TableListSkeleton } from './TableListSkeleton';
|
|
16
|
+
export { TableSidebar } from './TableSidebar';
|
|
17
|
+
export { TablesEmptyState } from './TablesEmptyState';
|
|
18
|
+
export { TemplateCard } from './TemplateCard';
|
|
19
|
+
export { TemplatePreview } from './TemplatePreview';
|