insforge 0.3.3 → 1.3.0
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/.dockerignore +60 -57
- package/.env.example +84 -49
- package/.github/ISSUE_TEMPLATE/bug_report.yml +36 -83
- package/.github/ISSUE_TEMPLATE/config.yml +11 -11
- package/.github/ISSUE_TEMPLATE/feature_request.yml +26 -79
- package/.github/PULL_REQUEST_TEMPLATE.md +7 -0
- package/.github/copilot-instructions.md +146 -146
- package/.github/workflows/build-image.yml +66 -65
- package/.github/workflows/ci-premerge-check.yml +23 -23
- package/.github/workflows/e2e.yml +63 -0
- package/.github/workflows/lint-and-format.yml +32 -32
- package/.prettierignore +64 -64
- package/CHANGELOG.md +44 -3
- package/CLAUDE_PLUGIN.md +104 -0
- package/CODE_OF_CONDUCT.md +128 -0
- package/CONTRIBUTING.md +125 -125
- package/Dockerfile +30 -27
- package/GITHUB_OAUTH_SETUP.md +49 -49
- package/GOOGLE_OAUTH_SETUP.md +148 -148
- package/LICENSE +201 -201
- package/README.md +182 -134
- package/assets/Dark.svg +23 -23
- 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 +117 -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 +60 -0
- package/auth/src/pages/SignUpPage.tsx +60 -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 +78 -75
- 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} +22 -26
- package/backend/src/api/routes/auth/index.routes.ts +667 -0
- package/backend/src/api/routes/auth/oauth.routes.ts +473 -0
- package/backend/src/api/routes/{database.advance.ts → database/advance.routes.ts} +128 -65
- package/backend/src/api/routes/database/index.routes.ts +90 -0
- package/backend/src/api/routes/{database.records.ts → database/records.routes.ts} +26 -12
- package/backend/src/api/routes/{database.tables.ts → database/tables.routes.ts} +6 -23
- package/backend/src/api/routes/docs/index.routes.ts +75 -0
- package/backend/src/api/routes/email/index.routes.ts +35 -0
- package/backend/src/api/routes/functions/index.routes.ts +194 -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} +33 -31
- package/backend/src/api/routes/realtime/channels.routes.ts +81 -0
- package/backend/src/api/routes/realtime/index.routes.ts +12 -0
- package/backend/src/api/routes/realtime/messages.routes.ts +48 -0
- package/backend/src/api/routes/realtime/permissions.routes.ts +19 -0
- package/backend/src/api/routes/{secrets.ts → secrets/index.routes.ts} +27 -22
- package/backend/src/api/routes/{storage.ts → storage/index.routes.ts} +48 -61
- package/backend/src/api/routes/usage/index.routes.ts +91 -0
- package/backend/src/infra/config/app.config.ts +51 -0
- package/backend/src/infra/database/database.manager.ts +182 -0
- package/backend/{migrations → src/infra/database/migrations}/000_create-base-tables.sql +141 -141
- package/backend/{migrations → src/infra/database/migrations}/001_create-helper-functions.sql +40 -40
- package/backend/{migrations → src/infra/database/migrations}/002_rename-auth-tables.sql +29 -29
- package/backend/{migrations → src/infra/database/migrations}/003_create-users-table.sql +55 -55
- package/backend/{migrations → src/infra/database/migrations}/004_add-reload-postgrest-func.sql +23 -23
- package/backend/{migrations → src/infra/database/migrations}/005_enable-project-admin-modify-users.sql +29 -29
- package/backend/{migrations → src/infra/database/migrations}/006_modify-ai-usage-table.sql +24 -24
- package/backend/{migrations → src/infra/database/migrations}/007_drop-metadata-table.sql +1 -1
- package/backend/{migrations → src/infra/database/migrations}/008_add-system-tables.sql +76 -76
- package/backend/{migrations → src/infra/database/migrations}/009_add-function-secrets.sql +23 -23
- package/backend/{migrations → src/infra/database/migrations}/010_modify-ai-config-modalities.sql +93 -93
- package/backend/{migrations → src/infra/database/migrations}/011_refactor-secrets-table.sql +15 -15
- package/backend/{migrations → src/infra/database/migrations}/012_add-storage-uploaded-by.sql +7 -7
- 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/infra/database/migrations/017_create-realtime-schema.sql +233 -0
- package/backend/src/infra/realtime/realtime.manager.ts +246 -0
- package/backend/src/infra/realtime/webhook-sender.ts +82 -0
- package/backend/src/{core/secrets/encryption.ts → infra/security/encryption.manager.ts} +3 -2
- package/backend/src/infra/security/token.manager.ts +219 -0
- package/backend/src/infra/socket/socket.manager.ts +522 -0
- package/backend/src/providers/ai/openrouter.provider.ts +380 -0
- package/backend/src/providers/email/base.provider.ts +38 -0
- package/backend/src/providers/email/cloud.provider.ts +271 -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/apple.provider.ts +266 -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 +8 -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 +317 -288
- 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 +1150 -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 +802 -0
- package/backend/src/services/database/database.service.ts +127 -0
- package/backend/src/services/email/email.service.ts +73 -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/services/realtime/index.ts +3 -0
- package/backend/src/services/realtime/realtime-auth.service.ts +104 -0
- package/backend/src/services/realtime/realtime-channel.service.ts +237 -0
- package/backend/src/services/realtime/realtime-message.service.ts +260 -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 +77 -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/types/realtime.ts +18 -0
- package/backend/src/{core/socket/types.ts → types/socket.ts} +11 -36
- package/backend/src/utils/cookies.ts +35 -0
- package/backend/src/utils/environment.ts +9 -3
- package/backend/src/utils/logger.ts +20 -2
- package/backend/src/utils/s3-config-loader.ts +64 -0
- package/backend/src/utils/seed.ts +301 -205
- package/backend/src/utils/sql-parser.ts +91 -1
- package/backend/src/utils/utils.ts +114 -0
- package/backend/src/utils/validations.ts +40 -4
- package/backend/tests/README.md +133 -133
- package/backend/tests/cleanup-all-test-data.sh +230 -230
- package/backend/tests/cloud/test-s3-multitenant.sh +131 -131
- package/backend/tests/local/comprehensive-curl-tests.sh +155 -155
- 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 +143 -143
- package/backend/tests/local/test-database-router.sh +222 -222
- package/backend/tests/local/test-e2e.sh +240 -240
- package/backend/tests/local/test-fk-errors.sh +96 -96
- package/backend/tests/local/test-functions.sh +123 -0
- package/backend/tests/local/test-id-field.sh +200 -200
- package/backend/tests/local/test-logs.sh +132 -0
- package/backend/tests/local/test-public-bucket.sh +264 -264
- package/backend/tests/local/test-secrets.sh +249 -247
- package/backend/tests/local/test-serverless-functions.sh.disabled +325 -325
- package/backend/tests/local/test-traditional-rest.sh +208 -208
- package/backend/tests/manual/README.md +50 -50
- package/backend/tests/manual/create-large-table-simple.sql +10 -10
- package/backend/tests/manual/seed-large-table.sql +100 -100
- package/backend/tests/manual/setup-large-table-extras.sql +33 -33
- package/backend/tests/manual/test-bulk-upsert.sh +409 -409
- package/backend/tests/manual/test-database-advance.sh +296 -296
- package/backend/tests/manual/test-postgrest-stability.sh +191 -191
- package/backend/tests/manual/test-rawsql-export-import.sh +411 -411
- package/backend/tests/manual/test-rawsql-modes.sh +244 -0
- package/backend/tests/manual/test-universal-storage.sh +263 -263
- package/backend/tests/manual/test-users.sql +17 -17
- package/backend/tests/run-all-tests.sh +139 -139
- package/backend/tests/setup.ts +0 -0
- package/backend/tests/test-config.sh +338 -302
- package/backend/tests/unit/analyze-query.test.ts +697 -0
- 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 +22 -22
- 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 +204 -144
- package/docker-compose.yml +232 -167
- package/docker-init/db/db-init.sql +97 -125
- package/docker-init/db/jwt.sql +5 -5
- package/docker-init/db/postgresql.conf +16 -16
- package/docker-init/logs/vector.yml +236 -0
- package/docs/README.md +44 -0
- package/docs/agent-docs/real-time.md +269 -0
- package/docs/changelog.mdx +119 -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/email/architecture.mdx +101 -0
- package/docs/core-concepts/email/sdk.mdx +53 -0
- package/docs/core-concepts/functions/architecture.mdx +105 -0
- package/docs/core-concepts/functions/sdk.mdx +184 -0
- package/docs/core-concepts/realtime/architecture.mdx +446 -0
- package/docs/core-concepts/realtime/sdk.mdx +409 -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/deprecated/insforge-auth-api.md +214 -214
- package/docs/deprecated/insforge-auth-sdk.md +99 -99
- package/docs/deprecated/insforge-db-api.md +358 -358
- package/docs/deprecated/insforge-db-sdk.md +139 -139
- package/docs/deprecated/insforge-debug-sdk.md +156 -156
- package/docs/deprecated/insforge-debug.md +64 -64
- package/docs/deprecated/insforge-instructions.md +123 -123
- package/docs/deprecated/insforge-project.md +117 -117
- package/docs/deprecated/insforge-storage-api.md +278 -278
- package/docs/deprecated/insforge-storage-sdk.md +158 -158
- package/docs/docs.json +232 -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/dec-2025/ai-integration.png +0 -0
- package/docs/images/changelog/dec-2025/ai-models.webp +0 -0
- package/docs/images/changelog/dec-2025/alipay-payment.webp +0 -0
- package/docs/images/changelog/dec-2025/apple-login.jpg +0 -0
- package/docs/images/changelog/dec-2025/mcp-installer.png +0 -0
- package/docs/images/changelog/dec-2025/realtime-module.jpg +0 -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 +89 -407
- package/docs/introduction.mdx +45 -0
- package/docs/logo/dark.svg +22 -0
- package/docs/logo/light.svg +20 -0
- package/docs/partnership.mdx +652 -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/examples/oauth/frontend-oauth-example.html +250 -250
- package/examples/response-examples.md +443 -443
- package/frontend/components.json +17 -17
- package/frontend/package.json +69 -63
- package/frontend/src/App.tsx +13 -82
- package/frontend/src/assets/icons/checkbox_checked.svg +6 -6
- package/frontend/src/assets/icons/checkbox_undetermined.svg +6 -6
- package/frontend/src/assets/icons/checked.svg +3 -3
- package/frontend/src/assets/icons/connected.svg +3 -0
- package/frontend/src/assets/icons/error.svg +3 -3
- package/frontend/src/assets/icons/loader.svg +9 -0
- package/frontend/src/assets/icons/pencil.svg +4 -4
- package/frontend/src/assets/icons/refresh.svg +4 -4
- package/frontend/src/assets/icons/step_active.svg +3 -3
- package/frontend/src/assets/icons/step_inactive.svg +11 -11
- package/frontend/src/assets/icons/warning.svg +3 -3
- package/frontend/src/assets/logos/apple.svg +4 -0
- package/frontend/src/assets/logos/claude_code.svg +3 -3
- package/frontend/src/assets/logos/cline.svg +6 -6
- package/frontend/src/assets/logos/cursor.svg +20 -20
- package/frontend/src/assets/logos/discord.svg +8 -8
- package/frontend/src/assets/logos/facebook.svg +3 -0
- package/frontend/src/assets/logos/gemini.svg +19 -19
- package/frontend/src/assets/logos/github.svg +5 -5
- package/frontend/src/assets/logos/google.svg +13 -13
- package/frontend/src/assets/logos/grok.svg +10 -10
- package/frontend/src/assets/logos/insforge_dark.svg +15 -15
- package/frontend/src/assets/logos/insforge_light.svg +15 -15
- 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/openai.svg +10 -10
- package/frontend/src/assets/logos/roo_code.svg +9 -9
- package/frontend/src/assets/logos/spotify.svg +17 -0
- package/frontend/src/assets/logos/tiktok.svg +6 -0
- package/frontend/src/assets/logos/trae.svg +3 -3
- package/frontend/src/assets/logos/windsurf.svg +10 -10
- 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 +131 -91
- 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/pages/AIPage.tsx +166 -0
- 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 +54 -30
- package/frontend/src/features/auth/components/UserFormDialog.tsx +13 -6
- package/frontend/src/features/auth/components/UsersDataGrid.tsx +50 -14
- package/frontend/src/features/auth/components/index.ts +5 -0
- package/frontend/src/features/auth/helpers.tsx +208 -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/pages/AuthMethodsPage.tsx +275 -0
- package/frontend/src/features/auth/pages/ConfigurationPage.tsx +395 -0
- package/frontend/src/features/auth/pages/UsersPage.tsx +257 -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/pages/DashboardPage.tsx +212 -0
- 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/SQLModal.tsx +75 -0
- package/frontend/src/features/database/components/TableEmptyState.tsx +6 -5
- package/frontend/src/features/database/components/TableForm.tsx +28 -19
- 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/useDatabase.ts +66 -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 +135 -0
- package/frontend/src/features/database/index.ts +7 -1
- package/frontend/src/features/database/pages/FunctionsPage.tsx +203 -0
- package/frontend/src/features/database/pages/IndexesPage.tsx +228 -0
- package/frontend/src/features/database/pages/PoliciesPage.tsx +237 -0
- package/frontend/src/features/database/pages/SQLEditorPage.tsx +382 -0
- package/frontend/src/features/database/{page/DatabasePage.tsx → pages/TablesPage.tsx} +168 -209
- package/frontend/src/features/database/pages/TemplatesPage.tsx +39 -0
- package/frontend/src/features/database/pages/TriggersPage.tsx +230 -0
- package/frontend/src/features/database/services/advance.service.ts +40 -0
- package/frontend/src/features/database/services/database.service.ts +33 -194
- package/frontend/src/features/database/services/record.service.ts +219 -0
- package/frontend/src/features/database/services/table.service.ts +58 -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/pages/FunctionsPage.tsx +148 -0
- package/frontend/src/features/functions/{components/SecretsContent.tsx → pages/SecretsPage.tsx} +19 -21
- 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/pages/CloudLoginPage.tsx +118 -0
- package/frontend/src/features/login/{page → pages}/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 +128 -0
- package/frontend/src/features/logs/index.ts +8 -2
- package/frontend/src/features/logs/{page → pages}/AuditsPage.tsx +91 -38
- package/frontend/src/features/logs/pages/LogsPage.tsx +152 -0
- package/frontend/src/features/logs/pages/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/realtime/components/ChannelRow.tsx +83 -0
- package/frontend/src/features/realtime/components/EditChannelModal.tsx +246 -0
- package/frontend/src/features/realtime/components/MessageRow.tsx +85 -0
- package/frontend/src/features/realtime/components/RealtimeEmptyState.tsx +30 -0
- package/frontend/src/features/realtime/hooks/useRealtime.ts +218 -0
- package/frontend/src/features/realtime/index.ts +11 -0
- package/frontend/src/features/realtime/pages/RealtimeChannelsPage.tsx +172 -0
- package/frontend/src/features/realtime/pages/RealtimeMessagesPage.tsx +211 -0
- package/frontend/src/features/realtime/pages/RealtimePermissionsPage.tsx +191 -0
- package/frontend/src/features/realtime/services/realtime.service.ts +107 -0
- 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 → pages}/StoragePage.tsx +41 -143
- 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/pages/VisualizerPage.tsx +97 -0
- 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 +123 -80
- 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 +99 -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 +207 -0
- package/frontend/src/lib/utils/{validation-schemas.ts → schemaValidations.ts} +10 -5
- package/frontend/src/lib/utils/utils.ts +32 -1
- package/frontend/src/vite-env.d.ts +1 -0
- package/frontend/tsconfig.json +25 -25
- package/frontend/tsconfig.node.json +9 -9
- package/frontend/vite.config.ts +5 -3
- package/functions/deno.json +24 -24
- package/functions/server.ts +315 -290
- 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 +715 -688
- package/openapi/auth.yaml +1244 -563
- package/openapi/email.yaml +158 -0
- package/openapi/functions.yaml +475 -475
- package/openapi/health.yaml +29 -29
- package/openapi/logs.yaml +223 -223
- package/openapi/metadata.yaml +177 -177
- package/openapi/realtime.yaml +699 -0
- package/openapi/records.yaml +381 -381
- package/openapi/secrets.yaml +370 -370
- package/openapi/storage.yaml +875 -875
- package/openapi/tables.yaml +463 -463
- package/package.json +97 -88
- package/shared-schemas/package.json +31 -31
- package/shared-schemas/src/ai-api.schema.ts +34 -58
- package/shared-schemas/src/ai.schema.ts +63 -54
- package/shared-schemas/src/auth-api.schema.ts +352 -193
- package/shared-schemas/src/auth.schema.ts +43 -7
- package/shared-schemas/src/cloud-events.schema.ts +57 -0
- package/shared-schemas/src/database-api.schema.ts +35 -4
- package/shared-schemas/src/database.schema.ts +40 -1
- package/shared-schemas/src/docs.schema.ts +26 -0
- package/shared-schemas/src/email-api.schema.ts +30 -0
- package/shared-schemas/src/index.ts +5 -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 +18 -4
- package/shared-schemas/src/realtime-api.schema.ts +111 -0
- package/shared-schemas/src/realtime.schema.ts +143 -0
- package/shared-schemas/tsconfig.json +21 -21
- package/tsconfig.json +7 -7
- 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/manager.ts +0 -178
- 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/socket/socket.ts +0 -388
- 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/ai/page/AIPage.tsx +0 -178
- 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/dashboard/page/DashboardPage.tsx +0 -194
- 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/functions/page/FunctionsPage.tsx +0 -28
- package/frontend/src/features/login/components/AuthErrorBoundary.tsx +0 -87
- package/frontend/src/features/login/components/PrivateRoute.tsx +0 -24
- package/frontend/src/features/login/page/CloudLoginPage.tsx +0 -93
- 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/features/visualizer/page/VisualizerPage.tsx +0 -127
- 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/frontend/src/{features/metadata → lib}/services/metadata.service.ts +0 -0
package/backend/src/{core/database/advance.ts → services/database/database-advance.service.ts}
RENAMED
|
@@ -1,29 +1,39 @@
|
|
|
1
|
-
import { DatabaseManager } from '@/
|
|
2
|
-
import { AppError } from '@/api/
|
|
1
|
+
import { DatabaseManager } from '@/infra/database/database.manager.js';
|
|
2
|
+
import { AppError } from '@/api/middlewares/error.js';
|
|
3
3
|
import {
|
|
4
4
|
type RawSQLResponse,
|
|
5
5
|
type ExportDatabaseResponse,
|
|
6
6
|
type ExportDatabaseJsonData,
|
|
7
7
|
type ImportDatabaseResponse,
|
|
8
8
|
type BulkUpsertResponse,
|
|
9
|
-
type DatabaseMetadataSchema,
|
|
10
9
|
} from '@insforge/shared-schemas';
|
|
11
10
|
import logger from '@/utils/logger.js';
|
|
12
|
-
import { ERROR_CODES } from '@/types/error-constants';
|
|
11
|
+
import { ERROR_CODES } from '@/types/error-constants.js';
|
|
13
12
|
import { parseSQLStatements } from '@/utils/sql-parser.js';
|
|
14
13
|
import { validateTableName } from '@/utils/validations.js';
|
|
15
14
|
import format from 'pg-format';
|
|
16
15
|
import { parse } from 'csv-parse/sync';
|
|
16
|
+
import { DatabaseError, type PoolClient } from 'pg';
|
|
17
17
|
|
|
18
18
|
export class DatabaseAdvanceService {
|
|
19
|
+
private static instance: DatabaseAdvanceService;
|
|
19
20
|
private dbManager = DatabaseManager.getInstance();
|
|
20
21
|
|
|
22
|
+
private constructor() {}
|
|
23
|
+
|
|
24
|
+
public static getInstance(): DatabaseAdvanceService {
|
|
25
|
+
if (!DatabaseAdvanceService.instance) {
|
|
26
|
+
DatabaseAdvanceService.instance = new DatabaseAdvanceService();
|
|
27
|
+
}
|
|
28
|
+
return DatabaseAdvanceService.instance;
|
|
29
|
+
}
|
|
30
|
+
|
|
21
31
|
/**
|
|
22
32
|
* Get table data using simple SELECT query
|
|
23
33
|
* More reliable than streaming for moderate datasets
|
|
24
34
|
*/
|
|
25
35
|
private async getTableData(
|
|
26
|
-
client:
|
|
36
|
+
client: PoolClient,
|
|
27
37
|
table: string,
|
|
28
38
|
rowLimit: number | undefined
|
|
29
39
|
): Promise<{ rows: Record<string, unknown>[]; totalRows: number; wasTruncated: boolean }> {
|
|
@@ -53,8 +63,25 @@ export class DatabaseAdvanceService {
|
|
|
53
63
|
return { rows, totalRows, wasTruncated };
|
|
54
64
|
}
|
|
55
65
|
|
|
56
|
-
|
|
57
|
-
|
|
66
|
+
/**
|
|
67
|
+
* Sanitize query with strict or relaxed mode
|
|
68
|
+
*
|
|
69
|
+
* BOTH MODES block:
|
|
70
|
+
* - DROP DATABASE, CREATE DATABASE, ALTER DATABASE
|
|
71
|
+
* - pg_catalog and information_schema access
|
|
72
|
+
*
|
|
73
|
+
* STRICT MODE blocks:
|
|
74
|
+
* - ALL operations on system tables (tables starting with _)
|
|
75
|
+
* - DROP or RENAME operations on users table
|
|
76
|
+
*
|
|
77
|
+
* RELAXED MODE allows:
|
|
78
|
+
* - SELECT and INSERT into system tables and users table
|
|
79
|
+
* RELAXED MODE blocks:
|
|
80
|
+
* - UPDATE/DELETE/DROP/CREATE/ALTER system tables
|
|
81
|
+
* - UPDATE/DELETE/DROP/RENAME users table
|
|
82
|
+
*/
|
|
83
|
+
sanitizeQuery(query: string, mode: 'strict' | 'relaxed' = 'strict'): string {
|
|
84
|
+
// Both modes: Block database-level operations
|
|
58
85
|
const dangerousPatterns = [
|
|
59
86
|
/DROP\s+DATABASE/i,
|
|
60
87
|
/CREATE\s+DATABASE/i,
|
|
@@ -69,18 +96,6 @@ export class DatabaseAdvanceService {
|
|
|
69
96
|
}
|
|
70
97
|
}
|
|
71
98
|
|
|
72
|
-
// Check for system table operations (tables starting with underscore)
|
|
73
|
-
// This pattern checks each statement in multi-statement queries, including schema-qualified names
|
|
74
|
-
const systemTablePattern =
|
|
75
|
-
/(?:^|\n|;)\s*(?:CREATE|ALTER|DROP|INSERT\s+INTO|UPDATE|DELETE\s+FROM|TRUNCATE)\s+(?:TABLE\s+)?(?:IF\s+(?:NOT\s+)?EXISTS\s+)?(?:\w+\.)?["']?_\w+/im;
|
|
76
|
-
if (systemTablePattern.test(query)) {
|
|
77
|
-
throw new AppError(
|
|
78
|
-
'Cannot modify or create system tables (tables starting with underscore)',
|
|
79
|
-
403,
|
|
80
|
-
ERROR_CODES.FORBIDDEN
|
|
81
|
-
);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
99
|
// Check for RENAME TO system table
|
|
85
100
|
const renameToSystemTablePattern = /RENAME\s+TO\s+(?:\w+\.)?["']?_\w+/im;
|
|
86
101
|
if (renameToSystemTablePattern.test(query)) {
|
|
@@ -98,20 +113,45 @@ export class DatabaseAdvanceService {
|
|
|
98
113
|
throw new AppError('Cannot drop or rename the users table', 403, ERROR_CODES.FORBIDDEN);
|
|
99
114
|
}
|
|
100
115
|
|
|
116
|
+
if (mode === 'strict') {
|
|
117
|
+
// Check for system table operations (tables starting with underscore)
|
|
118
|
+
// This pattern checks each statement in multi-statement queries, including schema-qualified names
|
|
119
|
+
const systemTablePattern =
|
|
120
|
+
/(?:^|\n|;)\s*(?:CREATE|ALTER|DROP|INSERT\s+INTO|UPDATE|DELETE\s+FROM|TRUNCATE)\s+(?:TABLE\s+)?(?:IF\s+(?:NOT\s+)?EXISTS\s+)?(?:\w+\.)?["']?_\w+/im;
|
|
121
|
+
if (systemTablePattern.test(query)) {
|
|
122
|
+
throw new AppError(
|
|
123
|
+
'Cannot modify or create system tables (tables starting with underscore)',
|
|
124
|
+
403,
|
|
125
|
+
ERROR_CODES.FORBIDDEN
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
} else {
|
|
129
|
+
// Relaxed mode: Allow only SELECT and INSERT into system tables and users table
|
|
130
|
+
// Block UPDATE, DELETE, DROP, CREATE, ALTER, TRUNCATE
|
|
131
|
+
const systemTableDestructivePattern =
|
|
132
|
+
/(?:^|\n|;)\s*(?:CREATE|ALTER|DROP|TRUNCATE|UPDATE|DELETE\s+FROM)\s+(?:TABLE\s+)?(?:IF\s+(?:NOT\s+)?EXISTS\s+)?(?:\w+\.)?["']?_\w+/im;
|
|
133
|
+
if (systemTableDestructivePattern.test(query)) {
|
|
134
|
+
throw new AppError(
|
|
135
|
+
'Cannot UPDATE/DELETE/DROP/CREATE/ALTER system tables (tables starting with underscore)',
|
|
136
|
+
403,
|
|
137
|
+
ERROR_CODES.FORBIDDEN
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
101
142
|
return query;
|
|
102
143
|
}
|
|
103
144
|
|
|
104
|
-
async executeRawSQL(
|
|
105
|
-
const query = this.sanitizeQuery(input_query);
|
|
145
|
+
async executeRawSQL(query: string, params: unknown[] = []): Promise<RawSQLResponse> {
|
|
106
146
|
const pool = this.dbManager.getPool();
|
|
107
147
|
const client = await pool.connect();
|
|
108
148
|
|
|
109
149
|
try {
|
|
110
|
-
//
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
150
|
+
// Set statement timeout at session level (30 seconds)
|
|
151
|
+
await client.query('SET statement_timeout = 30000');
|
|
152
|
+
|
|
153
|
+
// Execute query - database will enforce the timeout
|
|
154
|
+
const result = await client.query(query, params);
|
|
115
155
|
|
|
116
156
|
// Refresh schema cache if it was a DDL operation
|
|
117
157
|
if (/CREATE|ALTER|DROP/i.test(query)) {
|
|
@@ -129,13 +169,21 @@ export class DatabaseAdvanceService {
|
|
|
129
169
|
};
|
|
130
170
|
|
|
131
171
|
return response;
|
|
172
|
+
} catch (error) {
|
|
173
|
+
// Handle timeout errors specifically for better error messages
|
|
174
|
+
if (error instanceof DatabaseError && error.code === '57014') {
|
|
175
|
+
throw new Error('Query timeout: The query took longer than 30 seconds to execute');
|
|
176
|
+
}
|
|
177
|
+
// Re-throw other errors as-is
|
|
178
|
+
throw error;
|
|
132
179
|
} finally {
|
|
180
|
+
// Reset timeout to default before releasing client back to pool
|
|
181
|
+
await client.query('SET statement_timeout = 0');
|
|
133
182
|
client.release();
|
|
134
183
|
}
|
|
135
184
|
}
|
|
136
185
|
|
|
137
|
-
|
|
138
|
-
private async exportTableSchemaBySQL(client: any, table: string): Promise<string> {
|
|
186
|
+
private async exportTableSchemaBySQL(client: PoolClient, table: string): Promise<string> {
|
|
139
187
|
let sqlExport = '';
|
|
140
188
|
// Always export table schema with defaults
|
|
141
189
|
const schemaResult = await client.query(
|
|
@@ -157,7 +205,7 @@ export class DatabaseAdvanceService {
|
|
|
157
205
|
[table]
|
|
158
206
|
);
|
|
159
207
|
|
|
160
|
-
if (schemaResult.rows.length
|
|
208
|
+
if (schemaResult.rows.length) {
|
|
161
209
|
sqlExport += `-- Table: ${table}\n`;
|
|
162
210
|
sqlExport += schemaResult.rows[0].create_statement + '\n\n';
|
|
163
211
|
}
|
|
@@ -177,7 +225,7 @@ export class DatabaseAdvanceService {
|
|
|
177
225
|
[table]
|
|
178
226
|
);
|
|
179
227
|
|
|
180
|
-
if (indexesResult.rows.length
|
|
228
|
+
if (indexesResult.rows.length) {
|
|
181
229
|
sqlExport += `-- Indexes for table: ${table}\n`;
|
|
182
230
|
for (const indexRow of indexesResult.rows) {
|
|
183
231
|
sqlExport += indexRow.indexdef + ';\n';
|
|
@@ -222,7 +270,7 @@ export class DatabaseAdvanceService {
|
|
|
222
270
|
[table]
|
|
223
271
|
);
|
|
224
272
|
|
|
225
|
-
if (foreignKeysResult.rows.length
|
|
273
|
+
if (foreignKeysResult.rows.length) {
|
|
226
274
|
sqlExport += `-- Foreign key constraints for table: ${table}\n`;
|
|
227
275
|
for (const fkRow of foreignKeysResult.rows) {
|
|
228
276
|
sqlExport += fkRow.fk_statement + '\n';
|
|
@@ -241,7 +289,7 @@ export class DatabaseAdvanceService {
|
|
|
241
289
|
[table]
|
|
242
290
|
);
|
|
243
291
|
const rlsEnabled =
|
|
244
|
-
rlsResult.rows.length
|
|
292
|
+
!!rlsResult.rows.length &&
|
|
245
293
|
(rlsResult.rows[0].relrowsecurity === true || rlsResult.rows[0].relrowsecurity === 1);
|
|
246
294
|
if (rlsEnabled) {
|
|
247
295
|
sqlExport += `-- RLS enabled for table: ${table}\n`;
|
|
@@ -273,7 +321,7 @@ export class DatabaseAdvanceService {
|
|
|
273
321
|
[table]
|
|
274
322
|
);
|
|
275
323
|
|
|
276
|
-
if (policiesResult.rows.length
|
|
324
|
+
if (policiesResult.rows.length) {
|
|
277
325
|
sqlExport += `-- RLS policies for table: ${table}\n`;
|
|
278
326
|
for (const policyRow of policiesResult.rows) {
|
|
279
327
|
sqlExport += policyRow.policy_statement + '\n';
|
|
@@ -316,7 +364,7 @@ export class DatabaseAdvanceService {
|
|
|
316
364
|
[table]
|
|
317
365
|
);
|
|
318
366
|
|
|
319
|
-
if (triggersResult.rows.length
|
|
367
|
+
if (triggersResult.rows.length) {
|
|
320
368
|
sqlExport += `-- Triggers for table: ${table}\n`;
|
|
321
369
|
for (const triggerRow of triggersResult.rows) {
|
|
322
370
|
sqlExport += triggerRow.trigger_statement + '\n';
|
|
@@ -341,7 +389,7 @@ export class DatabaseAdvanceService {
|
|
|
341
389
|
try {
|
|
342
390
|
// Get tables to export
|
|
343
391
|
let tablesToExport: string[];
|
|
344
|
-
if (tables && tables.length
|
|
392
|
+
if (tables && tables.length) {
|
|
345
393
|
tablesToExport = tables;
|
|
346
394
|
} else {
|
|
347
395
|
const tablesResult = await client.query(`
|
|
@@ -375,7 +423,7 @@ export class DatabaseAdvanceService {
|
|
|
375
423
|
|
|
376
424
|
const { rows, wasTruncated } = await this.getTableData(client, table, rowLimit);
|
|
377
425
|
|
|
378
|
-
if (rows.length
|
|
426
|
+
if (rows.length) {
|
|
379
427
|
tableDataSql += `-- Data for table: ${table}\n`;
|
|
380
428
|
|
|
381
429
|
for (const row of rows) {
|
|
@@ -433,7 +481,7 @@ export class DatabaseAdvanceService {
|
|
|
433
481
|
ORDER BY p.proname
|
|
434
482
|
`);
|
|
435
483
|
|
|
436
|
-
if (functionsResult.rows.length
|
|
484
|
+
if (functionsResult.rows.length) {
|
|
437
485
|
sqlExport += `-- Functions and Procedures\n`;
|
|
438
486
|
for (const funcRow of functionsResult.rows) {
|
|
439
487
|
sqlExport += `-- Function: ${funcRow.function_name}\n`;
|
|
@@ -459,7 +507,7 @@ export class DatabaseAdvanceService {
|
|
|
459
507
|
ORDER BY sequence_name
|
|
460
508
|
`);
|
|
461
509
|
|
|
462
|
-
if (sequencesResult.rows.length
|
|
510
|
+
if (sequencesResult.rows.length) {
|
|
463
511
|
sqlExport += `-- Sequences\n`;
|
|
464
512
|
for (const seqRow of sequencesResult.rows) {
|
|
465
513
|
sqlExport += seqRow.sequence_statement + '\n';
|
|
@@ -480,7 +528,7 @@ export class DatabaseAdvanceService {
|
|
|
480
528
|
ORDER BY table_name
|
|
481
529
|
`);
|
|
482
530
|
|
|
483
|
-
if (viewsResult.rows.length
|
|
531
|
+
if (viewsResult.rows.length) {
|
|
484
532
|
sqlExport += `-- Views\n`;
|
|
485
533
|
for (const viewRow of viewsResult.rows) {
|
|
486
534
|
sqlExport += `-- View: ${viewRow.view_name}\n`;
|
|
@@ -493,7 +541,7 @@ export class DatabaseAdvanceService {
|
|
|
493
541
|
format: 'sql',
|
|
494
542
|
data: sqlExport,
|
|
495
543
|
timestamp,
|
|
496
|
-
...(truncatedTables.length
|
|
544
|
+
...(truncatedTables.length && {
|
|
497
545
|
truncatedTables,
|
|
498
546
|
rowLimit,
|
|
499
547
|
}),
|
|
@@ -585,7 +633,7 @@ export class DatabaseAdvanceService {
|
|
|
585
633
|
);
|
|
586
634
|
|
|
587
635
|
const rlsEnabled =
|
|
588
|
-
rlsResult.rows.length
|
|
636
|
+
!!rlsResult.rows.length &&
|
|
589
637
|
(rlsResult.rows[0].relrowsecurity === true || rlsResult.rows[0].relrowsecurity === 1);
|
|
590
638
|
|
|
591
639
|
// Get policies
|
|
@@ -624,7 +672,7 @@ export class DatabaseAdvanceService {
|
|
|
624
672
|
);
|
|
625
673
|
|
|
626
674
|
// Get data if requested - using streaming to avoid memory issues
|
|
627
|
-
const rows: unknown[] = [];
|
|
675
|
+
const rows: Record<string, unknown>[] = [];
|
|
628
676
|
let truncated = false;
|
|
629
677
|
let totalRowCount: number | undefined;
|
|
630
678
|
|
|
@@ -711,7 +759,7 @@ export class DatabaseAdvanceService {
|
|
|
711
759
|
format: 'json',
|
|
712
760
|
data: jsonData,
|
|
713
761
|
timestamp,
|
|
714
|
-
...(truncatedTables.length
|
|
762
|
+
...(truncatedTables.length && {
|
|
715
763
|
truncatedTables,
|
|
716
764
|
rowLimit,
|
|
717
765
|
}),
|
|
@@ -856,6 +904,7 @@ export class DatabaseAdvanceService {
|
|
|
856
904
|
records = parse(fileBuffer, {
|
|
857
905
|
columns: true,
|
|
858
906
|
skip_empty_lines: true,
|
|
907
|
+
bom: true,
|
|
859
908
|
});
|
|
860
909
|
} else if (fileExtension === '.json') {
|
|
861
910
|
const jsonContent = fileBuffer.toString('utf-8');
|
|
@@ -879,7 +928,7 @@ export class DatabaseAdvanceService {
|
|
|
879
928
|
);
|
|
880
929
|
}
|
|
881
930
|
|
|
882
|
-
if (!records || records.length
|
|
931
|
+
if (!records || !records.length) {
|
|
883
932
|
throw new AppError('No records found in file', 400, ERROR_CODES.INVALID_INPUT);
|
|
884
933
|
}
|
|
885
934
|
|
|
@@ -901,12 +950,11 @@ export class DatabaseAdvanceService {
|
|
|
901
950
|
records: Record<string, unknown>[],
|
|
902
951
|
upsertKey?: string
|
|
903
952
|
): Promise<{ rowCount: number; rows?: unknown[] }> {
|
|
904
|
-
if (!records || records.length
|
|
953
|
+
if (!records || !records.length) {
|
|
905
954
|
throw new AppError('No records to insert', 400, ERROR_CODES.INVALID_INPUT);
|
|
906
955
|
}
|
|
907
956
|
|
|
908
957
|
const pool = this.dbManager.getPool();
|
|
909
|
-
const client = await pool.connect();
|
|
910
958
|
|
|
911
959
|
try {
|
|
912
960
|
// Get column names from first record
|
|
@@ -937,7 +985,7 @@ export class DatabaseAdvanceService {
|
|
|
937
985
|
// Build upsert query with pg-format
|
|
938
986
|
const updateColumns = columns.filter((c) => c !== upsertKey);
|
|
939
987
|
|
|
940
|
-
if (updateColumns.length
|
|
988
|
+
if (updateColumns.length) {
|
|
941
989
|
// Build UPDATE SET clause
|
|
942
990
|
const updateClause = updateColumns
|
|
943
991
|
.map((col) => format('%I = EXCLUDED.%I', col, col))
|
|
@@ -967,10 +1015,10 @@ export class DatabaseAdvanceService {
|
|
|
967
1015
|
}
|
|
968
1016
|
|
|
969
1017
|
// Execute query
|
|
970
|
-
const result = await
|
|
1018
|
+
const result = await pool.query(query);
|
|
971
1019
|
|
|
972
1020
|
// Refresh schema cache if needed
|
|
973
|
-
await
|
|
1021
|
+
await pool.query(`NOTIFY pgrst, 'reload schema';`);
|
|
974
1022
|
|
|
975
1023
|
return {
|
|
976
1024
|
rowCount: result.rowCount || 0,
|
|
@@ -987,88 +1035,6 @@ export class DatabaseAdvanceService {
|
|
|
987
1035
|
|
|
988
1036
|
const message = error instanceof Error ? error.message : 'Bulk insert failed';
|
|
989
1037
|
throw new AppError(message, 400, ERROR_CODES.INVALID_INPUT);
|
|
990
|
-
} finally {
|
|
991
|
-
client.release();
|
|
992
|
-
}
|
|
993
|
-
}
|
|
994
|
-
|
|
995
|
-
/**
|
|
996
|
-
* Get database metadata
|
|
997
|
-
*/
|
|
998
|
-
async getMetadata(): Promise<DatabaseMetadataSchema> {
|
|
999
|
-
// Get all tables excluding system tables (those starting with _)
|
|
1000
|
-
const allTables = await this.dbManager.getUserTables();
|
|
1001
|
-
const dbMetadata = await this.exportDatabase(allTables, 'json', false, false, false, false);
|
|
1002
|
-
|
|
1003
|
-
const databaseSize = await this.getDatabaseSizeInGB();
|
|
1004
|
-
|
|
1005
|
-
// Get record counts for each table
|
|
1006
|
-
const tablesSchemas = (dbMetadata.data as ExportDatabaseJsonData).tables;
|
|
1007
|
-
const db = this.dbManager.getDb();
|
|
1008
|
-
|
|
1009
|
-
for (const tableName of allTables) {
|
|
1010
|
-
let recordCount = 0;
|
|
1011
|
-
try {
|
|
1012
|
-
// there is a race condition here, if the table is immeditely deleted, so added an extra check to see if the table exists
|
|
1013
|
-
const tableExists = (await db
|
|
1014
|
-
.prepare(
|
|
1015
|
-
`
|
|
1016
|
-
SELECT EXISTS (
|
|
1017
|
-
SELECT 1 FROM pg_class
|
|
1018
|
-
WHERE relname = ?
|
|
1019
|
-
AND relnamespace = (SELECT oid FROM pg_namespace WHERE nspname = 'public')
|
|
1020
|
-
AND relkind = 'r'
|
|
1021
|
-
) as exists
|
|
1022
|
-
`
|
|
1023
|
-
)
|
|
1024
|
-
.get(tableName)) as { exists: boolean } | null;
|
|
1025
|
-
|
|
1026
|
-
if (tableExists?.exists) {
|
|
1027
|
-
const countResult = (await db
|
|
1028
|
-
.prepare(`SELECT COUNT(*) as count FROM "${tableName}"`)
|
|
1029
|
-
.get()) as { count: number } | null;
|
|
1030
|
-
recordCount = countResult?.count || 0;
|
|
1031
|
-
}
|
|
1032
|
-
} catch (error) {
|
|
1033
|
-
// Handle any unexpected errors
|
|
1034
|
-
logger.warn('Could not get record count for table', {
|
|
1035
|
-
table: tableName,
|
|
1036
|
-
error: error instanceof Error ? error.message : String(error),
|
|
1037
|
-
});
|
|
1038
|
-
recordCount = 0;
|
|
1039
|
-
}
|
|
1040
|
-
|
|
1041
|
-
// Only add recordCount if the table exists in tablesSchemas
|
|
1042
|
-
if (tablesSchemas[tableName]) {
|
|
1043
|
-
tablesSchemas[tableName].recordCount = recordCount;
|
|
1044
|
-
}
|
|
1045
|
-
}
|
|
1046
|
-
|
|
1047
|
-
return {
|
|
1048
|
-
tables: tablesSchemas,
|
|
1049
|
-
totalSize: databaseSize,
|
|
1050
|
-
};
|
|
1051
|
-
}
|
|
1052
|
-
|
|
1053
|
-
async getDatabaseSizeInGB(): Promise<number> {
|
|
1054
|
-
try {
|
|
1055
|
-
const db = this.dbManager.getDb();
|
|
1056
|
-
// Query PostgreSQL for database size
|
|
1057
|
-
const result = (await db
|
|
1058
|
-
.prepare(
|
|
1059
|
-
`
|
|
1060
|
-
SELECT pg_database_size(current_database()) as size
|
|
1061
|
-
`
|
|
1062
|
-
)
|
|
1063
|
-
.get()) as { size: number } | null;
|
|
1064
|
-
|
|
1065
|
-
// PostgreSQL returns size in bytes, convert to GB
|
|
1066
|
-
return (result?.size || 0) / (1024 * 1024 * 1024);
|
|
1067
|
-
} catch (error) {
|
|
1068
|
-
logger.error('Error getting database size', {
|
|
1069
|
-
error: error instanceof Error ? error.message : String(error),
|
|
1070
|
-
});
|
|
1071
|
-
return 0;
|
|
1072
1038
|
}
|
|
1073
1039
|
}
|
|
1074
1040
|
}
|