insforge 1.2.10 → 1.4.8
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 -20
- package/.dockerignore +60 -60
- package/.env.example +83 -77
- package/.github/ISSUE_TEMPLATE/bug_report.yml +36 -36
- package/.github/ISSUE_TEMPLATE/config.yml +11 -11
- package/.github/ISSUE_TEMPLATE/feature_request.yml +26 -26
- package/.github/PULL_REQUEST_TEMPLATE.md +7 -7
- package/.github/copilot-instructions.md +146 -146
- package/.github/workflows/build-image.yml +65 -65
- package/.github/workflows/ci-premerge-check.yml +23 -23
- package/.github/workflows/e2e.yml +63 -63
- package/.github/workflows/lint-and-format.yml +32 -32
- package/.prettierignore +64 -64
- package/CHANGELOG.md +46 -44
- package/CLAUDE_PLUGIN.md +104 -104
- package/CODE_OF_CONDUCT.md +128 -128
- package/CONTRIBUTING.md +125 -125
- package/Dockerfile +30 -30
- package/GITHUB_OAUTH_SETUP.md +49 -49
- package/GOOGLE_OAUTH_SETUP.md +148 -148
- package/LICENSE +201 -201
- package/README.md +182 -182
- package/assets/Dark.svg +23 -23
- package/auth/package.json +30 -28
- package/auth/src/lib/broadcastService.ts +4 -4
- package/auth/src/lib/insforge.ts +8 -0
- package/auth/src/main.tsx +2 -4
- package/auth/src/pages/SignInPage.tsx +5 -2
- package/auth/src/pages/SignUpPage.tsx +5 -2
- package/auth/src/pages/VerifyEmailPage.tsx +18 -0
- package/auth/tsconfig.json +33 -32
- package/auth/tsconfig.node.json +11 -11
- package/backend/package.json +82 -75
- package/backend/src/api/middlewares/rate-limiters.ts +127 -127
- package/backend/src/api/routes/ai/index.routes.ts +475 -468
- package/backend/src/api/routes/auth/index.routes.ts +720 -570
- package/backend/src/api/routes/auth/oauth.routes.ts +478 -448
- package/backend/src/api/routes/database/advance.routes.ts +37 -16
- package/backend/src/api/routes/database/index.routes.ts +80 -1
- package/backend/src/api/routes/database/records.routes.ts +48 -184
- package/backend/src/api/routes/database/rpc.routes.ts +69 -0
- package/backend/src/api/routes/database/tables.routes.ts +0 -14
- package/backend/src/api/routes/deployments/index.routes.ts +192 -0
- package/backend/src/api/routes/docs/index.routes.ts +76 -76
- package/backend/src/api/routes/email/index.routes.ts +35 -0
- package/backend/src/api/routes/functions/index.routes.ts +21 -15
- package/backend/src/api/routes/metadata/index.routes.ts +38 -0
- 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/storage/index.routes.ts +18 -12
- package/backend/src/api/routes/usage/index.routes.ts +6 -4
- package/backend/src/api/routes/webhooks/index.routes.ts +109 -0
- package/backend/src/infra/database/database.manager.ts +14 -11
- package/backend/src/infra/database/migrations/000_create-base-tables.sql +141 -141
- package/backend/src/infra/database/migrations/001_create-helper-functions.sql +40 -40
- package/backend/src/infra/database/migrations/002_rename-auth-tables.sql +29 -29
- package/backend/src/infra/database/migrations/003_create-users-table.sql +55 -55
- package/backend/src/infra/database/migrations/004_add-reload-postgrest-func.sql +23 -23
- package/backend/src/infra/database/migrations/005_enable-project-admin-modify-users.sql +29 -29
- package/backend/src/infra/database/migrations/006_modify-ai-usage-table.sql +24 -24
- package/backend/src/infra/database/migrations/007_drop-metadata-table.sql +1 -1
- package/backend/src/infra/database/migrations/008_add-system-tables.sql +76 -76
- package/backend/src/infra/database/migrations/009_add-function-secrets.sql +23 -23
- package/backend/src/infra/database/migrations/010_modify-ai-config-modalities.sql +93 -93
- package/backend/src/infra/database/migrations/011_refactor-secrets-table.sql +15 -15
- package/backend/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 -44
- package/backend/src/infra/database/migrations/014_add-updated-at-trigger-user-table.sql +7 -7
- package/backend/src/infra/database/migrations/015_create-auth-config-and-email-otp-tables.sql +59 -59
- package/backend/src/infra/database/migrations/016_update-auth-config-and-email-otp.sql +24 -24
- package/backend/src/infra/database/migrations/017_create-realtime-schema.sql +233 -0
- package/backend/src/infra/database/migrations/018_schema-rework.sql +441 -0
- package/backend/src/infra/database/migrations/019_create-deployments-table.sql +36 -0
- package/backend/src/infra/database/migrations/020_add-audio-modality.sql +11 -0
- package/backend/src/infra/database/migrations/bootstrap/bootstrap-migrations.js +103 -0
- package/backend/src/infra/realtime/realtime.manager.ts +246 -0
- package/backend/src/infra/realtime/webhook-sender.ts +82 -0
- package/backend/src/infra/security/token.manager.ts +216 -125
- package/backend/src/infra/socket/socket.manager.ts +198 -64
- package/backend/src/providers/ai/openrouter.provider.ts +24 -12
- package/backend/src/providers/database/base.provider.ts +39 -0
- package/backend/src/providers/database/cloud.provider.ts +159 -0
- package/backend/src/providers/deployments/vercel.provider.ts +516 -0
- package/backend/src/providers/email/base.provider.ts +4 -7
- package/backend/src/providers/email/cloud.provider.ts +84 -0
- package/backend/src/providers/oauth/apple.provider.ts +266 -0
- package/backend/src/providers/oauth/index.ts +1 -0
- package/backend/src/server.ts +329 -284
- package/backend/src/services/ai/ai-config.service.ts +6 -6
- package/backend/src/services/ai/ai-model.service.ts +60 -60
- package/backend/src/services/ai/ai-usage.service.ts +7 -7
- package/backend/src/services/ai/chat-completion.service.ts +415 -220
- package/backend/src/services/ai/helpers.ts +64 -64
- package/backend/src/services/ai/image-generation.service.ts +3 -3
- package/backend/src/services/ai/index.ts +13 -13
- package/backend/src/services/auth/auth-config.service.ts +4 -4
- package/backend/src/services/auth/auth-otp.service.ts +6 -6
- package/backend/src/services/auth/auth.service.ts +148 -74
- package/backend/src/services/auth/index.ts +4 -4
- package/backend/src/services/auth/oauth-config.service.ts +12 -12
- package/backend/src/services/database/database-advance.service.ts +19 -55
- package/backend/src/services/database/database-table.service.ts +38 -94
- package/backend/src/services/database/database.service.ts +127 -0
- package/backend/src/services/database/postgrest-proxy.service.ts +165 -0
- package/backend/src/services/deployments/deployment.service.ts +693 -0
- package/backend/src/services/email/email.service.ts +5 -7
- package/backend/src/services/functions/function.service.ts +61 -41
- package/backend/src/services/logs/audit.service.ts +10 -10
- 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/services/secrets/secret.service.ts +101 -27
- package/backend/src/services/storage/storage.service.ts +30 -30
- package/backend/src/services/usage/usage.service.ts +6 -6
- package/backend/src/types/ai.ts +8 -0
- package/backend/src/types/auth.ts +16 -1
- package/backend/src/types/database.ts +2 -0
- package/backend/src/types/deployments.ts +33 -0
- package/backend/src/types/realtime.ts +18 -0
- package/backend/src/types/socket.ts +7 -31
- package/backend/src/types/storage.ts +1 -1
- package/backend/src/types/webhooks.ts +45 -0
- package/backend/src/utils/cookies.ts +34 -0
- package/backend/src/utils/environment.ts +0 -14
- package/backend/src/utils/s3-config-loader.ts +64 -0
- package/backend/src/utils/seed.ts +79 -43
- package/backend/src/utils/sql-parser.ts +216 -0
- package/backend/src/utils/utils.ts +114 -114
- package/backend/src/utils/validations.ts +10 -10
- 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 -129
- package/backend/tests/local/test-ai-usage.sh +80 -80
- 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 -123
- package/backend/tests/local/test-id-field.sh +200 -200
- package/backend/tests/local/test-logs.sh +132 -132
- package/backend/tests/local/test-public-bucket.sh +264 -264
- package/backend/tests/local/test-rpc.sh +141 -0
- package/backend/tests/local/test-secrets.sh +249 -249
- 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-ai-model-plugins.sh +258 -0
- 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 -244
- 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 -338
- package/backend/tests/unit/analyze-query.test.ts +697 -0
- package/backend/tests/unit/database-advance.test.ts +326 -0
- package/backend/tests/unit/helpers.test.ts +2 -2
- package/backend/tsconfig.json +22 -22
- package/claude-plugin/.claude-plugin/plugin.json +24 -24
- package/claude-plugin/README.md +133 -133
- package/claude-plugin/skills/insforge-schema-patterns/SKILL.md +273 -270
- package/docker-compose.prod.yml +204 -200
- package/docker-compose.yml +232 -228
- package/docker-init/db/db-init.sql +97 -97
- package/docker-init/db/jwt.sql +5 -5
- package/docker-init/db/postgresql.conf +16 -16
- package/docker-init/logs/vector.yml +236 -236
- package/docs/README.md +44 -44
- package/docs/agent-docs/deployment.md +79 -0
- package/docs/agent-docs/real-time.md +269 -0
- package/docs/changelog.mdx +212 -67
- package/docs/core-concepts/ai/architecture.mdx +350 -372
- package/docs/core-concepts/ai/sdk.mdx +238 -213
- package/docs/core-concepts/authentication/architecture.mdx +276 -278
- package/docs/core-concepts/authentication/sdk.mdx +710 -414
- package/docs/core-concepts/authentication/ui-components/customization.mdx +733 -529
- package/docs/core-concepts/authentication/ui-components/nextjs.mdx +247 -221
- package/docs/core-concepts/authentication/ui-components/react-router.mdx +183 -184
- package/docs/core-concepts/authentication/ui-components/react.mdx +136 -129
- package/docs/core-concepts/database/architecture.mdx +292 -255
- package/docs/core-concepts/database/pgvector.mdx +138 -0
- package/docs/core-concepts/database/sdk.mdx +382 -382
- package/docs/core-concepts/deployments/architecture.mdx +152 -0
- package/docs/core-concepts/email/architecture.mdx +103 -0
- package/docs/core-concepts/email/sdk.mdx +53 -0
- package/docs/core-concepts/functions/architecture.mdx +105 -105
- package/docs/core-concepts/functions/sdk.mdx +183 -184
- 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 -243
- package/docs/core-concepts/storage/sdk.mdx +253 -253
- package/docs/deployment/README.md +94 -94
- package/docs/deployment/deploy-to-aws-ec2.md +564 -564
- package/docs/deployment/deploy-to-azure-virtual-machines.md +312 -312
- package/docs/deployment/deploy-to-google-cloud-compute-engine.md +613 -613
- package/docs/deployment/deploy-to-render.md +441 -441
- 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 +240 -210
- package/docs/examples/framework-guides/nextjs.mdx +131 -131
- package/docs/examples/framework-guides/nuxt.mdx +165 -165
- package/docs/examples/framework-guides/react.mdx +165 -165
- package/docs/examples/framework-guides/svelte.mdx +153 -153
- package/docs/examples/framework-guides/vue.mdx +159 -159
- package/docs/examples/overview.mdx +67 -67
- package/docs/favicon.png +0 -0
- package/docs/favicon.svg +4 -19
- 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/apple-oauth.mp4 +0 -0
- package/docs/images/changelog/dec-2025/mcp-installer.png +0 -0
- package/docs/images/changelog/dec-2025/moreModels.png +0 -0
- package/docs/images/changelog/dec-2025/multi-region.webp +0 -0
- package/docs/images/changelog/dec-2025/postgres-connection.webp +0 -0
- package/docs/images/changelog/dec-2025/realtime-module.jpg +0 -0
- package/docs/images/changelog/dec-2025/realtime2.png +0 -0
- package/docs/images/icons/ai.svg +4 -4
- package/docs/images/logos/nextjs.svg +4 -4
- package/docs/images/logos/nuxt.svg +4 -4
- package/docs/images/logos/react.svg +5 -5
- package/docs/images/logos/svelte.svg +4 -4
- package/docs/images/logos/vue.svg +5 -5
- package/docs/images/mcp-setup/CC-MCP-1.mp4 +0 -0
- package/docs/images/mcp-setup/CC-MCP-2.mp4 +0 -0
- package/docs/images/mcp-setup/Cursor-MCP-1.mp4 +0 -0
- package/docs/images/mcp-setup/Cursor-MCP-2.mp4 +0 -0
- package/docs/images/mcp-setup/Cursor-MCP-3.mp4 +0 -0
- package/docs/images/mcp-setup/claude-code-connect.png +0 -0
- package/docs/images/mcp-setup/cline-1.png +0 -0
- package/docs/images/mcp-setup/cline-2.png +0 -0
- package/docs/images/mcp-setup/cline-3.png +0 -0
- package/docs/images/mcp-setup/connect-project.png +0 -0
- package/docs/images/mcp-setup/copilot-1.png +0 -0
- package/docs/images/mcp-setup/copilot-2.png +0 -0
- package/docs/images/mcp-setup/copilot-3.png +0 -0
- package/docs/images/mcp-setup/mcp-json-1.png +0 -0
- package/docs/images/mcp-setup/mcp-json-2.png +0 -0
- package/docs/images/mcp-setup/qoder-1.png +0 -0
- package/docs/images/mcp-setup/qoder-2.png +0 -0
- package/docs/images/mcp-setup/roocode-1.png +0 -0
- package/docs/images/mcp-setup/roocode-2.png +0 -0
- package/docs/images/mcp-setup/trae-1.png +0 -0
- package/docs/images/mcp-setup/trae-2.png +0 -0
- package/docs/images/mcp-setup/trae-3.png +0 -0
- package/docs/images/mcp-setup/trae-4.png +0 -0
- package/docs/images/mcp-setup/trae-5.png +0 -0
- package/docs/images/mcp-setup/windsurf-1.png +0 -0
- package/docs/images/mcp-setup/windsurf-2.png +0 -0
- package/docs/insforge-instructions-sdk.md +93 -88
- package/docs/introduction.mdx +46 -45
- package/docs/logo/dark.svg +22 -22
- package/docs/logo/light.svg +20 -20
- package/docs/mcp-setup.mdx +332 -0
- package/docs/oauth-server.mdx +563 -0
- package/docs/partnership.mdx +720 -646
- package/docs/quickstart.mdx +82 -82
- package/docs/showcase.mdx +52 -52
- package/docs/snippets/sdk-installation.mdx +21 -21
- package/docs/snippets/service-icons.mdx +27 -27
- package/docs/vscode-extension.mdx +74 -0
- package/eslint.config.js +1 -0
- 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 -69
- package/frontend/src/App.tsx +8 -3
- 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 -3
- package/frontend/src/assets/icons/error.svg +3 -3
- package/frontend/src/assets/icons/loader.svg +9 -9
- 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/antigravity.svg +1 -0
- package/frontend/src/assets/logos/apple.svg +3 -3
- package/frontend/src/assets/logos/claude_code.svg +3 -3
- package/frontend/src/assets/logos/cline.svg +6 -6
- package/frontend/src/assets/logos/copilot.svg +10 -0
- package/frontend/src/assets/logos/cursor.svg +20 -20
- package/frontend/src/assets/logos/deepseek.svg +139 -0
- package/frontend/src/assets/logos/discord.svg +8 -8
- package/frontend/src/assets/logos/facebook.svg +3 -3
- 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 +1 -1
- package/frontend/src/assets/logos/kiro.svg +9 -0
- package/frontend/src/assets/logos/linkedin.svg +3 -3
- package/frontend/src/assets/logos/openai.svg +10 -10
- package/frontend/src/assets/logos/qoder.svg +4 -0
- package/frontend/src/assets/logos/qwen.svg +15 -0
- package/frontend/src/assets/logos/roo_code.svg +9 -9
- package/frontend/src/assets/logos/spotify.svg +16 -16
- package/frontend/src/assets/logos/tiktok.svg +5 -5
- 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 -3
- package/frontend/src/components/CodeBlock.tsx +2 -2
- package/frontend/src/components/ConnectCTA.tsx +3 -2
- package/frontend/src/components/datagrid/DataGrid.tsx +90 -62
- package/frontend/src/components/datagrid/datagridTypes.tsx +2 -1
- package/frontend/src/components/datagrid/index.ts +1 -1
- package/frontend/src/components/index.ts +0 -1
- package/frontend/src/components/layout/AppHeader.tsx +13 -37
- package/frontend/src/components/layout/AppSidebar.tsx +85 -100
- package/frontend/src/components/layout/Layout.tsx +34 -32
- package/frontend/src/components/layout/PrimaryMenu.tsx +12 -4
- package/frontend/src/components/radix/Select.tsx +151 -151
- package/frontend/src/features/ai/components/AIConfigCard.tsx +200 -200
- package/frontend/src/features/ai/components/AIEmptyState.tsx +23 -23
- package/frontend/src/features/ai/components/ModalityFilterSidebar.tsx +102 -101
- package/frontend/src/features/ai/components/ModelSelectionDialog.tsx +135 -135
- package/frontend/src/features/ai/components/ModelSelectionGrid.tsx +51 -51
- package/frontend/src/features/ai/components/SystemPromptDialog.tsx +118 -118
- package/frontend/src/features/ai/components/index.ts +6 -6
- package/frontend/src/features/ai/helpers.ts +147 -141
- package/frontend/src/features/ai/{page → pages}/AIPage.tsx +166 -166
- package/frontend/src/features/auth/components/AuthPreview.tsx +96 -96
- package/frontend/src/features/auth/components/OAuthConfigDialog.tsx +1 -0
- package/frontend/src/features/auth/components/UsersDataGrid.tsx +61 -31
- package/frontend/src/features/auth/components/index.ts +5 -5
- package/frontend/src/features/auth/helpers.tsx +8 -0
- package/frontend/src/features/auth/{page → pages}/AuthMethodsPage.tsx +275 -275
- package/frontend/src/features/auth/{page → pages}/UsersPage.tsx +0 -28
- package/frontend/src/features/dashboard/{page → pages}/DashboardPage.tsx +1 -1
- package/frontend/src/features/database/components/DatabaseDataGrid.tsx +0 -2
- package/frontend/src/features/database/components/ForeignKeyCell.tsx +38 -11
- package/frontend/src/features/database/components/ForeignKeyPopover.tsx +18 -8
- package/frontend/src/features/database/components/LinkRecordModal.tsx +61 -13
- package/frontend/src/features/database/components/RecordFormField.tsx +1 -1
- package/frontend/src/features/database/components/SQLModal.tsx +75 -0
- package/frontend/src/features/database/components/TableForm.tsx +0 -4
- package/frontend/src/features/database/components/TableSidebar.tsx +0 -3
- package/frontend/src/features/database/components/TablesEmptyState.tsx +1 -1
- package/frontend/src/features/database/components/TemplatePreview.tsx +1 -2
- package/frontend/src/features/database/constants.ts +16 -28
- package/frontend/src/features/database/hooks/useCSVImport.ts +3 -2
- package/frontend/src/features/database/hooks/useDatabase.ts +66 -0
- package/frontend/src/features/database/hooks/useRawSQL.ts +3 -2
- package/frontend/src/features/database/hooks/useTables.ts +30 -28
- package/frontend/src/features/database/index.ts +1 -0
- package/frontend/src/features/database/{page → pages}/FunctionsPage.tsx +29 -42
- package/frontend/src/features/database/{page → pages}/IndexesPage.tsx +34 -51
- package/frontend/src/features/database/{page → pages}/PoliciesPage.tsx +42 -58
- package/frontend/src/features/database/{page → pages}/SQLEditorPage.tsx +2 -2
- package/frontend/src/features/database/{page → pages}/TablesPage.tsx +0 -42
- package/frontend/src/features/database/{page → pages}/TriggersPage.tsx +34 -51
- package/frontend/src/features/database/services/advance.service.ts +1 -41
- package/frontend/src/features/database/services/database.service.ts +55 -0
- package/frontend/src/features/database/services/record.service.ts +4 -20
- package/frontend/src/features/database/services/table.service.ts +1 -10
- package/frontend/src/features/database/templates/ai-chatbot.ts +6 -6
- package/frontend/src/features/database/templates/ecommerce-platform.ts +2 -2
- package/frontend/src/features/database/templates/instagram-clone.ts +10 -10
- package/frontend/src/features/database/templates/notion-clone.ts +8 -8
- package/frontend/src/features/database/templates/reddit-clone.ts +10 -10
- package/frontend/src/features/deployments/components/DeploymentRow.tsx +93 -0
- package/frontend/src/features/deployments/components/DeploymentsEmptyState.tsx +15 -0
- package/frontend/src/features/deployments/hooks/useDeployments.ts +157 -0
- package/frontend/src/features/deployments/pages/DeploymentsPage.tsx +318 -0
- package/frontend/src/features/deployments/services/deployments.service.ts +63 -0
- package/frontend/src/features/functions/components/FunctionRow.tsx +72 -72
- package/frontend/src/features/functions/components/FunctionsSidebar.tsx +56 -56
- package/frontend/src/features/functions/components/SecretRow.tsx +3 -3
- package/frontend/src/features/functions/components/index.ts +5 -5
- package/frontend/src/features/functions/hooks/useFunctions.ts +5 -4
- package/frontend/src/features/functions/hooks/useSecrets.ts +6 -9
- package/frontend/src/features/functions/{page → pages}/FunctionsPage.tsx +21 -44
- package/frontend/src/features/functions/{page → pages}/SecretsPage.tsx +118 -116
- package/frontend/src/features/functions/services/function.service.ts +8 -25
- package/frontend/src/features/functions/services/secret.service.ts +23 -41
- package/frontend/src/features/login/{page → pages}/CloudLoginPage.tsx +125 -118
- package/frontend/src/features/logs/components/LogDetailPanel.tsx +41 -0
- package/frontend/src/features/logs/components/LogsDataGrid.tsx +32 -1
- package/frontend/src/features/logs/components/index.ts +1 -0
- package/frontend/src/features/logs/hooks/useMcpUsage.ts +13 -66
- package/frontend/src/features/logs/{page → pages}/LogsPage.tsx +36 -6
- package/frontend/src/features/onboard/components/ApiCredentialsSection.tsx +59 -0
- package/frontend/src/features/onboard/components/ConnectionStringSection.tsx +180 -0
- package/frontend/src/features/onboard/components/McpConnectionSection.tsx +159 -0
- package/frontend/src/features/onboard/components/OnboardingController.tsx +68 -0
- package/frontend/src/features/onboard/components/OnboardingModal.tsx +121 -267
- package/frontend/src/features/onboard/components/ShowPasswordButton.tsx +21 -0
- package/frontend/src/features/onboard/components/index.ts +9 -4
- package/frontend/src/features/onboard/components/mcp/CursorDeeplinkGenerator.tsx +1 -1
- package/frontend/src/features/onboard/components/mcp/QoderDeeplinkGenerator.tsx +36 -0
- package/frontend/src/features/onboard/components/mcp/helpers.tsx +123 -98
- package/frontend/src/features/onboard/components/mcp/index.ts +4 -3
- package/frontend/src/features/onboard/index.ts +17 -13
- 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/settings/pages/SettingsPage.tsx +349 -0
- package/frontend/src/features/storage/{page → pages}/StoragePage.tsx +1 -29
- package/frontend/src/features/visualizer/components/AuthNode.tsx +4 -4
- package/frontend/src/features/visualizer/components/SchemaVisualizer.tsx +24 -11
- package/frontend/src/features/visualizer/{page → pages}/VisualizerPage.tsx +11 -36
- package/frontend/src/index.css +249 -249
- package/frontend/src/lib/contexts/ModalContext.tsx +35 -0
- package/frontend/src/lib/contexts/SocketContext.tsx +119 -75
- package/frontend/src/lib/hooks/useMetadata.ts +45 -1
- package/frontend/src/lib/hooks/useModal.tsx +2 -0
- package/frontend/src/lib/routing/AppRoutes.tsx +103 -84
- package/frontend/src/lib/services/metadata.service.ts +20 -3
- package/frontend/src/lib/utils/cloudMessaging.ts +1 -1
- package/frontend/src/lib/utils/menuItems.ts +223 -183
- package/frontend/src/lib/utils/utils.ts +196 -183
- package/frontend/tsconfig.json +25 -25
- package/frontend/tsconfig.node.json +9 -9
- package/functions/deno.json +24 -24
- package/functions/server.ts +6 -6
- package/functions/worker-template.js +1 -1
- package/i18n/README.ar.md +130 -130
- package/i18n/README.de.md +130 -130
- package/i18n/README.es.md +154 -154
- package/i18n/README.fr.md +134 -134
- package/i18n/README.hi.md +129 -129
- package/i18n/README.ja.md +174 -174
- package/i18n/README.ko.md +136 -136
- package/i18n/README.pt-BR.md +131 -131
- package/i18n/README.ru.md +129 -129
- package/i18n/README.zh-CN.md +133 -133
- package/openapi/ai.yaml +825 -715
- package/openapi/auth.yaml +1324 -1244
- package/openapi/email.yaml +158 -0
- package/openapi/functions.yaml +475 -475
- package/openapi/health.yaml +29 -29
- package/openapi/logs.yaml +221 -223
- package/openapi/metadata.yaml +175 -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 +462 -463
- package/package.json +97 -97
- package/shared-schemas/package.json +31 -31
- package/shared-schemas/src/ai-api.schema.ts +251 -143
- package/shared-schemas/src/ai.schema.ts +8 -4
- package/shared-schemas/src/auth-api.schema.ts +380 -339
- package/shared-schemas/src/auth.schema.ts +18 -11
- package/shared-schemas/src/cloud-events.schema.ts +26 -0
- package/shared-schemas/src/database-api.schema.ts +32 -1
- package/shared-schemas/src/database.schema.ts +39 -0
- package/shared-schemas/src/deployments-api.schema.ts +55 -0
- package/shared-schemas/src/deployments.schema.ts +30 -0
- package/shared-schemas/src/docs.schema.ts +32 -0
- package/shared-schemas/src/email-api.schema.ts +30 -0
- package/shared-schemas/src/functions-api.schema.ts +13 -4
- package/shared-schemas/src/functions.schema.ts +1 -1
- package/shared-schemas/src/index.ts +22 -14
- package/shared-schemas/src/metadata.schema.ts +39 -4
- package/shared-schemas/src/realtime-api.schema.ts +111 -0
- package/shared-schemas/src/realtime.schema.ts +143 -0
- package/shared-schemas/src/secrets-api.schema.ts +44 -0
- package/shared-schemas/src/secrets.schema.ts +15 -0
- package/shared-schemas/tsconfig.json +21 -21
- package/tsconfig.json +7 -7
- package/zeabur/README.md +26 -13
- package/zeabur/template.yml +1001 -1032
- package/.cursor/rules/cursor-rules.mdc +0 -94
- package/backend/src/types/profile.ts +0 -55
- package/frontend/src/components/ProjectInfoModal.tsx +0 -128
- package/frontend/src/features/database/hooks/useFullMetadata.ts +0 -18
- package/test-gemini.sh +0 -35
- package/test-usage-admin.sh +0 -57
- package/test-usage.sh +0 -50
- /package/frontend/src/features/auth/{page → pages}/ConfigurationPage.tsx +0 -0
- /package/frontend/src/features/database/{page → pages}/TemplatesPage.tsx +0 -0
- /package/frontend/src/features/login/{page → pages}/LoginPage.tsx +0 -0
- /package/frontend/src/features/logs/{page → pages}/AuditsPage.tsx +0 -0
- /package/frontend/src/features/logs/{page → pages}/MCPLogsPage.tsx +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useMemo } from 'react';
|
|
1
|
+
import { useMemo, useCallback } from 'react';
|
|
2
2
|
import {
|
|
3
3
|
DataGrid,
|
|
4
4
|
type DataGridProps,
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
type DataGridColumn,
|
|
7
7
|
type DataGridRowType,
|
|
8
8
|
} from '@/components/datagrid';
|
|
9
|
+
import type { CellClickArgs, CellMouseEvent } from 'react-data-grid';
|
|
9
10
|
|
|
10
11
|
// Column definition type for LogsDataGrid
|
|
11
12
|
export interface LogsColumnDef {
|
|
@@ -52,6 +53,9 @@ export interface LogsDataGridProps<T = Record<string, unknown>>
|
|
|
52
53
|
columnDefs: LogsColumnDef[];
|
|
53
54
|
data: T[];
|
|
54
55
|
noPadding?: boolean;
|
|
56
|
+
selectedRowId?: string | null;
|
|
57
|
+
onRowClick?: (row: T) => void;
|
|
58
|
+
rightPanel?: React.ReactNode;
|
|
55
59
|
}
|
|
56
60
|
|
|
57
61
|
// Specialized DataGrid for logs
|
|
@@ -59,6 +63,9 @@ export function LogsDataGrid<T = Record<string, unknown>>({
|
|
|
59
63
|
columnDefs,
|
|
60
64
|
data,
|
|
61
65
|
noPadding,
|
|
66
|
+
selectedRowId,
|
|
67
|
+
onRowClick,
|
|
68
|
+
rightPanel,
|
|
62
69
|
...restProps
|
|
63
70
|
}: LogsDataGridProps<T>) {
|
|
64
71
|
const columns = useMemo(() => {
|
|
@@ -76,6 +83,27 @@ export function LogsDataGrid<T = Record<string, unknown>>({
|
|
|
76
83
|
}) as DataGridRowType[];
|
|
77
84
|
}, [data]);
|
|
78
85
|
|
|
86
|
+
// Handle cell click to trigger row click
|
|
87
|
+
const handleCellClick = useCallback(
|
|
88
|
+
(args: CellClickArgs<DataGridRowType>, _event: CellMouseEvent) => {
|
|
89
|
+
if (onRowClick) {
|
|
90
|
+
onRowClick(args.row as T);
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
[onRowClick]
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
// Row class for highlighting selected row
|
|
97
|
+
const rowClass = useCallback(
|
|
98
|
+
(row: DataGridRowType) => {
|
|
99
|
+
if (selectedRowId && row.id === selectedRowId) {
|
|
100
|
+
return 'bg-gray-200 dark:bg-neutral-700';
|
|
101
|
+
}
|
|
102
|
+
return '';
|
|
103
|
+
},
|
|
104
|
+
[selectedRowId]
|
|
105
|
+
);
|
|
106
|
+
|
|
79
107
|
return (
|
|
80
108
|
<DataGrid<DataGridRowType>
|
|
81
109
|
{...restProps}
|
|
@@ -84,6 +112,9 @@ export function LogsDataGrid<T = Record<string, unknown>>({
|
|
|
84
112
|
showSelection={false}
|
|
85
113
|
showPagination={true}
|
|
86
114
|
noPadding={noPadding}
|
|
115
|
+
onCellClick={handleCellClick}
|
|
116
|
+
rowClass={rowClass}
|
|
117
|
+
rightPanel={rightPanel}
|
|
87
118
|
/>
|
|
88
119
|
);
|
|
89
120
|
}
|
|
@@ -1,40 +1,27 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { useQuery
|
|
3
|
-
import { useSocket, ServerEvents } from '@/lib/contexts/SocketContext';
|
|
1
|
+
import { useMemo, useEffect, useRef, useState } from 'react';
|
|
2
|
+
import { useQuery } from '@tanstack/react-query';
|
|
4
3
|
import { useAuth } from '@/lib/contexts/AuthContext';
|
|
5
4
|
import { usageService, McpUsageRecord } from '@/features/logs/services/usage.service';
|
|
6
5
|
import { isInsForgeCloudProject } from '@/lib/utils/utils';
|
|
7
|
-
import { LOGS_PAGE_SIZE } from '../helpers';
|
|
8
6
|
import { postMessageToParent } from '@/lib/utils/cloudMessaging';
|
|
9
|
-
|
|
10
|
-
// ============================================================================
|
|
11
|
-
// Types
|
|
12
|
-
// ============================================================================
|
|
13
|
-
|
|
14
|
-
export interface McpConnectedPayload {
|
|
15
|
-
tool_name: string;
|
|
16
|
-
created_at: string;
|
|
17
|
-
}
|
|
7
|
+
import { LOGS_PAGE_SIZE } from '../helpers';
|
|
18
8
|
|
|
19
9
|
// ============================================================================
|
|
20
10
|
// Main Hook
|
|
21
11
|
// ============================================================================
|
|
22
12
|
|
|
23
13
|
/**
|
|
24
|
-
* Hook to manage MCP usage data
|
|
14
|
+
* Hook to manage MCP usage data
|
|
25
15
|
*
|
|
26
16
|
* Features:
|
|
27
|
-
* - Fetches
|
|
28
|
-
* - Listens to real-time socket updates for new MCP calls
|
|
29
|
-
* - Invalidates queries on WebSocket events to refetch latest data
|
|
17
|
+
* - Fetches MCP logs from backend
|
|
30
18
|
* - Provides helper functions for data access
|
|
31
|
-
* - Handles parent window
|
|
19
|
+
* - Handles initial parent window notification for onboarding (if in iframe)
|
|
32
20
|
* - Supports search and pagination
|
|
21
|
+
*
|
|
33
22
|
*/
|
|
34
23
|
export function useMcpUsage() {
|
|
35
24
|
// Hooks
|
|
36
|
-
const queryClient = useQueryClient();
|
|
37
|
-
const { socket, isConnected } = useSocket();
|
|
38
25
|
const { isAuthenticated } = useAuth();
|
|
39
26
|
|
|
40
27
|
// State
|
|
@@ -100,54 +87,14 @@ export function useMcpUsage() {
|
|
|
100
87
|
hasNotifiedInitialStatus.current = true;
|
|
101
88
|
|
|
102
89
|
const latestRecord = records[0];
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
},
|
|
110
|
-
'*'
|
|
111
|
-
);
|
|
90
|
+
postMessageToParent({
|
|
91
|
+
type: 'MCP_CONNECTION_STATUS',
|
|
92
|
+
connected: true,
|
|
93
|
+
tool_name: latestRecord.tool_name,
|
|
94
|
+
timestamp: latestRecord.created_at,
|
|
95
|
+
});
|
|
112
96
|
}, [isLoading, records]);
|
|
113
97
|
|
|
114
|
-
// Handle real-time MCP connection events from socket
|
|
115
|
-
const handleMcpConnected = useCallback(
|
|
116
|
-
(data: { id: string; payload: McpConnectedPayload; timestamp: number; type: string }) => {
|
|
117
|
-
// Notify parent window with latest MCP call info
|
|
118
|
-
if (window.parent !== window) {
|
|
119
|
-
window.parent.postMessage(
|
|
120
|
-
{
|
|
121
|
-
type: 'MCP_CONNECTION_STATUS',
|
|
122
|
-
connected: true,
|
|
123
|
-
tool_name: data.payload.tool_name,
|
|
124
|
-
timestamp: data.payload.created_at,
|
|
125
|
-
},
|
|
126
|
-
'*'
|
|
127
|
-
);
|
|
128
|
-
if (!records.length) {
|
|
129
|
-
postMessageToParent({ type: 'ONBOARDING_SUCCESS' });
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
// Invalidate query to refetch latest data (follows codebase pattern)
|
|
133
|
-
void queryClient.invalidateQueries({ queryKey: ['mcp-usage'] });
|
|
134
|
-
},
|
|
135
|
-
[queryClient, records.length]
|
|
136
|
-
);
|
|
137
|
-
|
|
138
|
-
// Subscribe to socket MCP connection events
|
|
139
|
-
useEffect(() => {
|
|
140
|
-
if (!socket || !isConnected) {
|
|
141
|
-
return;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
socket.on(ServerEvents.MCP_CONNECTED, handleMcpConnected);
|
|
145
|
-
|
|
146
|
-
return () => {
|
|
147
|
-
socket.off(ServerEvents.MCP_CONNECTED, handleMcpConnected);
|
|
148
|
-
};
|
|
149
|
-
}, [socket, isConnected, handleMcpConnected]);
|
|
150
|
-
|
|
151
98
|
// Computed values
|
|
152
99
|
const hasCompletedOnboarding = useMemo(() => !!records.length, [records]);
|
|
153
100
|
const recordsCount = useMemo(() => records.length, [records]);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useMemo } from 'react';
|
|
1
|
+
import { useMemo, useState, useCallback, useEffect } from 'react';
|
|
2
2
|
import { useParams } from 'react-router-dom';
|
|
3
3
|
import { ChevronDown } from 'lucide-react';
|
|
4
4
|
import { useLogs } from '../hooks/useLogs';
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
} from '@/components';
|
|
14
14
|
import { LogsDataGrid, type LogsColumnDef } from '../components/LogsDataGrid';
|
|
15
15
|
import { SeverityBadge } from '../components/SeverityBadge';
|
|
16
|
+
import { LogDetailPanel } from '../components/LogDetailPanel';
|
|
16
17
|
import { SEVERITY_OPTIONS, LOGS_PAGE_SIZE } from '../helpers';
|
|
17
18
|
import { formatTime } from '@/lib/utils/utils';
|
|
18
19
|
import { LogSchema } from '@insforge/shared-schemas';
|
|
@@ -21,6 +22,9 @@ export default function LogsPage() {
|
|
|
21
22
|
// Get the source from the URL params
|
|
22
23
|
const { source = 'insforge.logs' } = useParams<{ source?: string }>();
|
|
23
24
|
|
|
25
|
+
// Selected log state for detail panel
|
|
26
|
+
const [selectedLog, setSelectedLog] = useState<LogSchema | null>(null);
|
|
27
|
+
|
|
24
28
|
const {
|
|
25
29
|
logs: paginatedLogs,
|
|
26
30
|
filteredLogs,
|
|
@@ -36,12 +40,29 @@ export default function LogsPage() {
|
|
|
36
40
|
getSeverity,
|
|
37
41
|
} = useLogs(source);
|
|
38
42
|
|
|
43
|
+
// Close detail panel when switching log sources or changing filters
|
|
44
|
+
useEffect(() => {
|
|
45
|
+
setSelectedLog(null);
|
|
46
|
+
}, [source, severityFilter]);
|
|
47
|
+
|
|
48
|
+
// Handle row click to show log details
|
|
49
|
+
const handleRowClick = useCallback((log: LogSchema) => {
|
|
50
|
+
setSelectedLog(log);
|
|
51
|
+
}, []);
|
|
52
|
+
|
|
53
|
+
// Handle closing the detail panel
|
|
54
|
+
const handleClosePanel = useCallback(() => {
|
|
55
|
+
setSelectedLog(null);
|
|
56
|
+
}, []);
|
|
57
|
+
|
|
58
|
+
// Adjust column widths based on panel state
|
|
39
59
|
const logsColumns: LogsColumnDef[] = useMemo(
|
|
40
60
|
() => [
|
|
41
61
|
{
|
|
42
62
|
key: 'event_message',
|
|
43
63
|
name: 'Logs',
|
|
44
|
-
width: '
|
|
64
|
+
width: selectedLog ? '1fr' : '5fr',
|
|
65
|
+
minWidth: 200,
|
|
45
66
|
renderCell: ({ row }) => (
|
|
46
67
|
<p className="text-sm text-gray-900 dark:text-white font-normal leading-6 truncate">
|
|
47
68
|
{String(row.eventMessage ?? '')}
|
|
@@ -51,7 +72,7 @@ export default function LogsPage() {
|
|
|
51
72
|
{
|
|
52
73
|
key: 'severity',
|
|
53
74
|
name: 'Severity',
|
|
54
|
-
width: '
|
|
75
|
+
width: '100px',
|
|
55
76
|
renderCell: ({ row }) => (
|
|
56
77
|
<SeverityBadge severity={getSeverity(row as unknown as LogSchema)} />
|
|
57
78
|
),
|
|
@@ -59,7 +80,7 @@ export default function LogsPage() {
|
|
|
59
80
|
{
|
|
60
81
|
key: 'timestamp',
|
|
61
82
|
name: 'Time',
|
|
62
|
-
width: '
|
|
83
|
+
width: '200px',
|
|
63
84
|
renderCell: ({ row }) => (
|
|
64
85
|
<p className="text-sm text-gray-900 dark:text-white font-normal leading-6 flex-1">
|
|
65
86
|
{formatTime(String(row.timestamp ?? ''))}
|
|
@@ -67,7 +88,7 @@ export default function LogsPage() {
|
|
|
67
88
|
),
|
|
68
89
|
},
|
|
69
90
|
],
|
|
70
|
-
[getSeverity]
|
|
91
|
+
[getSeverity, selectedLog]
|
|
71
92
|
);
|
|
72
93
|
|
|
73
94
|
return (
|
|
@@ -121,7 +142,7 @@ export default function LogsPage() {
|
|
|
121
142
|
</div>
|
|
122
143
|
</div>
|
|
123
144
|
|
|
124
|
-
{/* Table with
|
|
145
|
+
{/* Table with Detail Panel */}
|
|
125
146
|
<div className="flex-1 overflow-hidden">
|
|
126
147
|
{logsError ? (
|
|
127
148
|
<div className="flex items-center justify-center h-full">
|
|
@@ -137,6 +158,15 @@ export default function LogsPage() {
|
|
|
137
158
|
pageSize={LOGS_PAGE_SIZE}
|
|
138
159
|
totalRecords={filteredLogs.length}
|
|
139
160
|
onPageChange={setCurrentPage}
|
|
161
|
+
selectedRowId={selectedLog?.id ?? null}
|
|
162
|
+
onRowClick={handleRowClick}
|
|
163
|
+
rightPanel={
|
|
164
|
+
selectedLog && (
|
|
165
|
+
<div className="w-[480px] h-full shrink-0">
|
|
166
|
+
<LogDetailPanel log={selectedLog} onClose={handleClosePanel} />
|
|
167
|
+
</div>
|
|
168
|
+
)
|
|
169
|
+
}
|
|
140
170
|
emptyState={
|
|
141
171
|
<div className="text-sm text-zinc-500 dark:text-zinc-400">
|
|
142
172
|
{logsSearchQuery || severityFilter.length < 3
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { CopyButton } from '@/components';
|
|
2
|
+
import { cn } from '@/lib/utils/utils';
|
|
3
|
+
|
|
4
|
+
interface CredentialRowProps {
|
|
5
|
+
label: string;
|
|
6
|
+
value: string;
|
|
7
|
+
isLoading?: boolean;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function CredentialRow({ label, value, isLoading = false }: CredentialRowProps) {
|
|
11
|
+
return (
|
|
12
|
+
<div className="flex items-center gap-4 min-w-0">
|
|
13
|
+
<span className="text-gray-900 dark:text-white text-sm leading-6 w-25 shrink-0">{label}</span>
|
|
14
|
+
<div
|
|
15
|
+
className={cn(
|
|
16
|
+
'flex-1 h-9 min-w-0 flex items-center justify-between gap-2 bg-white dark:bg-neutral-900 border border-gray-200 dark:border-neutral-700 rounded-lg px-3 py-2',
|
|
17
|
+
isLoading && 'animate-pulse'
|
|
18
|
+
)}
|
|
19
|
+
>
|
|
20
|
+
<span className="text-gray-900 dark:text-white text-sm truncate min-w-0 flex-1">
|
|
21
|
+
{value}
|
|
22
|
+
</span>
|
|
23
|
+
<CopyButton
|
|
24
|
+
text={value}
|
|
25
|
+
disabled={isLoading}
|
|
26
|
+
showText={false}
|
|
27
|
+
className="h-6 w-6 p-1 min-w-0 shrink-0 text-black dark:text-white bg-white dark:bg-neutral-700 hover:bg-neutral-100 dark:hover:bg-neutral-600 border-none"
|
|
28
|
+
/>
|
|
29
|
+
</div>
|
|
30
|
+
</div>
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
interface ApiCredentialsSectionProps {
|
|
35
|
+
apiKey: string;
|
|
36
|
+
appUrl: string;
|
|
37
|
+
isLoading?: boolean;
|
|
38
|
+
className?: string;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function ApiCredentialsSection({
|
|
42
|
+
apiKey,
|
|
43
|
+
appUrl,
|
|
44
|
+
isLoading = false,
|
|
45
|
+
className,
|
|
46
|
+
}: ApiCredentialsSectionProps) {
|
|
47
|
+
return (
|
|
48
|
+
<div className={cn('flex flex-col gap-6', className)}>
|
|
49
|
+
<p className="text-gray-500 dark:text-neutral-400 text-base leading-7">
|
|
50
|
+
Use the project URL and API key to connect directly via REST API or any HTTP client.
|
|
51
|
+
</p>
|
|
52
|
+
|
|
53
|
+
<div className="flex flex-col gap-4">
|
|
54
|
+
<CredentialRow label="Project URL" value={appUrl} isLoading={isLoading} />
|
|
55
|
+
<CredentialRow label="API Key" value={apiKey} isLoading={isLoading} />
|
|
56
|
+
</div>
|
|
57
|
+
</div>
|
|
58
|
+
);
|
|
59
|
+
}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { useState, useCallback, useRef, useEffect, useMemo } from 'react';
|
|
2
|
+
import { CopyButton, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components';
|
|
3
|
+
import { ShowPasswordButton } from './ShowPasswordButton';
|
|
4
|
+
import { useDatabaseConnectionString, useDatabasePassword } from '@/lib/hooks/useMetadata';
|
|
5
|
+
import { cn } from '@/lib/utils/utils';
|
|
6
|
+
|
|
7
|
+
interface ParameterRowProps {
|
|
8
|
+
label: string;
|
|
9
|
+
value: string | number | undefined;
|
|
10
|
+
copyValue?: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const RESET_TIMEOUT_MS = 2000;
|
|
14
|
+
|
|
15
|
+
function ParameterRow({ label, value, copyValue }: ParameterRowProps) {
|
|
16
|
+
const [copied, setCopied] = useState(false);
|
|
17
|
+
const timeoutRef = useRef<NodeJS.Timeout | null>(null);
|
|
18
|
+
|
|
19
|
+
const textToCopy = copyValue ?? String(value ?? '');
|
|
20
|
+
const displayValue = value ?? '-';
|
|
21
|
+
const hasCopyableValue = value !== undefined && value !== null && value !== '';
|
|
22
|
+
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
return () => {
|
|
25
|
+
if (timeoutRef.current) {
|
|
26
|
+
clearTimeout(timeoutRef.current);
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
}, []);
|
|
30
|
+
|
|
31
|
+
const handleCopy = useCallback(() => {
|
|
32
|
+
if (!hasCopyableValue) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (timeoutRef.current) {
|
|
37
|
+
clearTimeout(timeoutRef.current);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
navigator.clipboard
|
|
41
|
+
.writeText(textToCopy)
|
|
42
|
+
.then(() => {
|
|
43
|
+
setCopied(true);
|
|
44
|
+
timeoutRef.current = setTimeout(() => {
|
|
45
|
+
setCopied(false);
|
|
46
|
+
timeoutRef.current = null;
|
|
47
|
+
}, RESET_TIMEOUT_MS);
|
|
48
|
+
})
|
|
49
|
+
.catch((error) => {
|
|
50
|
+
console.error('Failed to copy to clipboard:', error);
|
|
51
|
+
});
|
|
52
|
+
}, [hasCopyableValue, textToCopy]);
|
|
53
|
+
|
|
54
|
+
return (
|
|
55
|
+
<div className="group flex items-center gap-2">
|
|
56
|
+
<span className="text-gray-400 dark:text-neutral-500 text-sm">{label}:</span>
|
|
57
|
+
<TooltipProvider>
|
|
58
|
+
<Tooltip open={copied}>
|
|
59
|
+
<TooltipTrigger asChild>
|
|
60
|
+
<button
|
|
61
|
+
type="button"
|
|
62
|
+
className={cn(
|
|
63
|
+
'text-gray-700 dark:text-neutral-300 text-sm',
|
|
64
|
+
hasCopyableValue &&
|
|
65
|
+
'cursor-pointer hover:text-gray-900 dark:hover:text-neutral-100 transition-colors'
|
|
66
|
+
)}
|
|
67
|
+
disabled={!hasCopyableValue}
|
|
68
|
+
aria-label={`Copy ${label}`}
|
|
69
|
+
onClick={handleCopy}
|
|
70
|
+
>
|
|
71
|
+
{displayValue}
|
|
72
|
+
</button>
|
|
73
|
+
</TooltipTrigger>
|
|
74
|
+
<TooltipContent side="top" sideOffset={4}>
|
|
75
|
+
<p className="font-medium text-xs leading-5">Copied</p>
|
|
76
|
+
</TooltipContent>
|
|
77
|
+
</Tooltip>
|
|
78
|
+
</TooltipProvider>
|
|
79
|
+
{hasCopyableValue && (
|
|
80
|
+
<CopyButton
|
|
81
|
+
text={textToCopy}
|
|
82
|
+
showText={false}
|
|
83
|
+
className="h-6 w-6 p-1 min-w-0 shrink-0 text-black dark:text-white bg-white dark:bg-neutral-700 hover:bg-neutral-100 dark:hover:bg-neutral-600 border-none opacity-0 group-hover:opacity-100 transition-opacity"
|
|
84
|
+
/>
|
|
85
|
+
)}
|
|
86
|
+
</div>
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
interface ConnectionStringSectionProps {
|
|
91
|
+
className?: string;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export function ConnectionStringSection({ className }: ConnectionStringSectionProps) {
|
|
95
|
+
const [showConnectionPassword, setShowConnectionPassword] = useState(false);
|
|
96
|
+
const [showParamsPassword, setShowParamsPassword] = useState(false);
|
|
97
|
+
|
|
98
|
+
const { connectionData, isLoading: isConnectionLoading } = useDatabaseConnectionString();
|
|
99
|
+
const { passwordData } = useDatabasePassword();
|
|
100
|
+
|
|
101
|
+
const dbParams = connectionData?.parameters;
|
|
102
|
+
const dbPassword = passwordData?.databasePassword || '';
|
|
103
|
+
const maskedPassword = dbParams?.password || '********';
|
|
104
|
+
|
|
105
|
+
const connectionStringDisplay = useMemo(() => {
|
|
106
|
+
if (!connectionData?.connectionURL) {
|
|
107
|
+
return '';
|
|
108
|
+
}
|
|
109
|
+
if (showConnectionPassword && dbPassword) {
|
|
110
|
+
return connectionData.connectionURL.replace('********', dbPassword);
|
|
111
|
+
}
|
|
112
|
+
return connectionData.connectionURL;
|
|
113
|
+
}, [connectionData?.connectionURL, showConnectionPassword, dbPassword]);
|
|
114
|
+
|
|
115
|
+
const connectionStringClipboard = useMemo(() => {
|
|
116
|
+
if (!connectionData?.connectionURL || !dbPassword) {
|
|
117
|
+
return connectionData?.connectionURL || '';
|
|
118
|
+
}
|
|
119
|
+
return connectionData.connectionURL.replace('********', dbPassword);
|
|
120
|
+
}, [connectionData?.connectionURL, dbPassword]);
|
|
121
|
+
|
|
122
|
+
return (
|
|
123
|
+
<div className={cn('flex flex-col gap-6', isConnectionLoading && 'animate-pulse', className)}>
|
|
124
|
+
<p className="text-gray-500 dark:text-neutral-400 text-base leading-7">
|
|
125
|
+
Ideal for applications with persistent and long-lived connections, such as those running on
|
|
126
|
+
virtual machines or long-standing containers.
|
|
127
|
+
</p>
|
|
128
|
+
|
|
129
|
+
{/* Connection String */}
|
|
130
|
+
<div className="bg-gray-100 dark:bg-neutral-900 rounded p-3">
|
|
131
|
+
<div className="flex items-center justify-between mb-2">
|
|
132
|
+
<div className="bg-gray-200 dark:bg-neutral-700 rounded px-2 h-5 flex items-center justify-center">
|
|
133
|
+
<span className="text-gray-700 dark:text-neutral-50 text-xs">connection string</span>
|
|
134
|
+
</div>
|
|
135
|
+
<div className="flex items-center gap-2">
|
|
136
|
+
<ShowPasswordButton
|
|
137
|
+
show={showConnectionPassword}
|
|
138
|
+
onToggle={() => setShowConnectionPassword(!showConnectionPassword)}
|
|
139
|
+
/>
|
|
140
|
+
<CopyButton
|
|
141
|
+
text={connectionStringClipboard}
|
|
142
|
+
showText={false}
|
|
143
|
+
className="h-6 w-6 p-1 min-w-0 shrink-0 text-black dark:text-white bg-white dark:bg-neutral-700 hover:bg-neutral-100 dark:hover:bg-neutral-600 border-none"
|
|
144
|
+
/>
|
|
145
|
+
</div>
|
|
146
|
+
</div>
|
|
147
|
+
<p className="text-gray-700 dark:text-neutral-300 text-sm leading-6 break-words">
|
|
148
|
+
{connectionStringDisplay || 'Loading...'}
|
|
149
|
+
</p>
|
|
150
|
+
</div>
|
|
151
|
+
|
|
152
|
+
<div className="h-px bg-gray-200 dark:bg-neutral-700" />
|
|
153
|
+
|
|
154
|
+
{/* Parameters */}
|
|
155
|
+
<div className="bg-gray-100 dark:bg-neutral-900 rounded p-3">
|
|
156
|
+
<div className="flex items-center justify-between mb-4">
|
|
157
|
+
<div className="bg-gray-200 dark:bg-neutral-700 rounded px-2 h-5 flex items-center justify-center">
|
|
158
|
+
<span className="text-gray-700 dark:text-neutral-50 text-xs">parameters</span>
|
|
159
|
+
</div>
|
|
160
|
+
<ShowPasswordButton
|
|
161
|
+
show={showParamsPassword}
|
|
162
|
+
onToggle={() => setShowParamsPassword(!showParamsPassword)}
|
|
163
|
+
/>
|
|
164
|
+
</div>
|
|
165
|
+
<div className="flex flex-col gap-3">
|
|
166
|
+
<ParameterRow label="HOST" value={dbParams?.host} />
|
|
167
|
+
<ParameterRow label="DATABASE" value={dbParams?.database} />
|
|
168
|
+
<ParameterRow label="USER" value={dbParams?.user} />
|
|
169
|
+
<ParameterRow label="PORT" value={dbParams?.port} />
|
|
170
|
+
<ParameterRow
|
|
171
|
+
label="PASSWORD"
|
|
172
|
+
value={showParamsPassword ? dbPassword || maskedPassword : maskedPassword}
|
|
173
|
+
copyValue={dbPassword || maskedPassword}
|
|
174
|
+
/>
|
|
175
|
+
<ParameterRow label="SSL" value={dbParams?.sslmode} />
|
|
176
|
+
</div>
|
|
177
|
+
</div>
|
|
178
|
+
</div>
|
|
179
|
+
);
|
|
180
|
+
}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { useState, useMemo } from 'react';
|
|
2
|
+
import { ChevronDown } from 'lucide-react';
|
|
3
|
+
import {
|
|
4
|
+
CodeBlock,
|
|
5
|
+
CopyButton,
|
|
6
|
+
DropdownMenu,
|
|
7
|
+
DropdownMenuContent,
|
|
8
|
+
DropdownMenuItem,
|
|
9
|
+
DropdownMenuTrigger,
|
|
10
|
+
} from '@/components';
|
|
11
|
+
import { CursorDeeplinkGenerator } from './mcp/CursorDeeplinkGenerator';
|
|
12
|
+
import { QoderDeeplinkGenerator } from './mcp/QoderDeeplinkGenerator';
|
|
13
|
+
import { MCP_AGENTS, GenerateInstallCommand, createMCPConfig, type MCPAgent } from './mcp/helpers';
|
|
14
|
+
import { cn } from '@/lib/utils/utils';
|
|
15
|
+
|
|
16
|
+
interface McpConnectionSectionProps {
|
|
17
|
+
apiKey: string;
|
|
18
|
+
appUrl: string;
|
|
19
|
+
isLoading?: boolean;
|
|
20
|
+
className?: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function McpConnectionSection({
|
|
24
|
+
apiKey,
|
|
25
|
+
appUrl,
|
|
26
|
+
isLoading = false,
|
|
27
|
+
className,
|
|
28
|
+
}: McpConnectionSectionProps) {
|
|
29
|
+
const [selectedAgent, setSelectedAgent] = useState<MCPAgent>(MCP_AGENTS[0]);
|
|
30
|
+
|
|
31
|
+
const installCommand = useMemo(() => {
|
|
32
|
+
return GenerateInstallCommand(selectedAgent, apiKey);
|
|
33
|
+
}, [selectedAgent, apiKey]);
|
|
34
|
+
|
|
35
|
+
const mcpJsonConfig = useMemo(() => {
|
|
36
|
+
const config = createMCPConfig(apiKey, 'macos-linux', appUrl);
|
|
37
|
+
return JSON.stringify(config, null, 2);
|
|
38
|
+
}, [apiKey, appUrl]);
|
|
39
|
+
|
|
40
|
+
const testPrompt =
|
|
41
|
+
"I'm using InsForge as my backend platform, call InsForge MCP's fetch-docs tool to learn about InsForge instructions.";
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
<div className={cn('flex flex-col gap-6', className)}>
|
|
45
|
+
<p className="text-gray-500 dark:text-neutral-400 text-base leading-7">
|
|
46
|
+
Install the MCP server so your coding agent can access and build the backend.
|
|
47
|
+
</p>
|
|
48
|
+
|
|
49
|
+
{/* Agent Selector Dropdown */}
|
|
50
|
+
<DropdownMenu>
|
|
51
|
+
<DropdownMenuTrigger asChild>
|
|
52
|
+
<button className="w-40 bg-gray-100 dark:bg-[rgba(0,0,0,0.12)] border border-gray-300 dark:border-[rgba(255,255,255,0.24)] rounded flex items-center justify-between px-2 py-1 cursor-pointer">
|
|
53
|
+
<div className="flex items-center gap-2">
|
|
54
|
+
{selectedAgent.logo && (
|
|
55
|
+
<div className="w-6 h-6 flex items-center justify-center">{selectedAgent.logo}</div>
|
|
56
|
+
)}
|
|
57
|
+
<span className="text-gray-900 dark:text-white text-sm font-medium">
|
|
58
|
+
{selectedAgent.displayName}
|
|
59
|
+
</span>
|
|
60
|
+
</div>
|
|
61
|
+
<ChevronDown className="w-5 h-5 text-gray-400 dark:text-neutral-400" />
|
|
62
|
+
</button>
|
|
63
|
+
</DropdownMenuTrigger>
|
|
64
|
+
<DropdownMenuContent
|
|
65
|
+
align="start"
|
|
66
|
+
className="w-40 bg-white dark:bg-neutral-800 border border-gray-200 dark:border-neutral-700 rounded shadow-lg p-0"
|
|
67
|
+
>
|
|
68
|
+
{MCP_AGENTS.map((agent) => (
|
|
69
|
+
<DropdownMenuItem
|
|
70
|
+
key={agent.id}
|
|
71
|
+
onSelect={() => setSelectedAgent(agent)}
|
|
72
|
+
className="flex items-center gap-2 px-2 py-2 text-gray-900 dark:text-white text-sm hover:bg-gray-100 dark:hover:bg-neutral-700 cursor-pointer"
|
|
73
|
+
>
|
|
74
|
+
{agent.logo && (
|
|
75
|
+
<div className="w-6 h-6 flex items-center justify-center">{agent.logo}</div>
|
|
76
|
+
)}
|
|
77
|
+
<span className="font-medium">{agent.displayName}</span>
|
|
78
|
+
</DropdownMenuItem>
|
|
79
|
+
))}
|
|
80
|
+
</DropdownMenuContent>
|
|
81
|
+
</DropdownMenu>
|
|
82
|
+
|
|
83
|
+
{/* Step 1 - Conditional based on agent */}
|
|
84
|
+
{selectedAgent.id === 'cursor' ? (
|
|
85
|
+
<div className="flex flex-col gap-3">
|
|
86
|
+
<p className="text-gray-900 dark:text-white text-sm">
|
|
87
|
+
<span className="font-semibold leading-5">1.</span>
|
|
88
|
+
<span className="leading-6"> Install in one click</span>
|
|
89
|
+
</p>
|
|
90
|
+
<div className="w-fit">
|
|
91
|
+
<CursorDeeplinkGenerator apiKey={apiKey} os="macos-linux" />
|
|
92
|
+
</div>
|
|
93
|
+
</div>
|
|
94
|
+
) : selectedAgent.id === 'qoder' ? (
|
|
95
|
+
<div className="flex flex-col gap-3">
|
|
96
|
+
<p className="text-gray-900 dark:text-white text-sm">
|
|
97
|
+
<span className="font-semibold leading-5">1.</span>
|
|
98
|
+
<span className="leading-6"> Install in one click</span>
|
|
99
|
+
</p>
|
|
100
|
+
<div className="w-fit">
|
|
101
|
+
<QoderDeeplinkGenerator apiKey={apiKey} os="macos-linux" />
|
|
102
|
+
</div>
|
|
103
|
+
</div>
|
|
104
|
+
) : selectedAgent.id === 'mcp' ? (
|
|
105
|
+
<div className="flex flex-col gap-3">
|
|
106
|
+
<p className="text-gray-900 dark:text-white text-sm">
|
|
107
|
+
<span className="font-semibold leading-5">1.</span>
|
|
108
|
+
<span className="leading-6">
|
|
109
|
+
{' '}
|
|
110
|
+
Copy the configuration below and add it to your AI assistant.
|
|
111
|
+
</span>
|
|
112
|
+
</p>
|
|
113
|
+
<div className="bg-gray-100 dark:bg-neutral-900 rounded overflow-hidden flex flex-col h-[320px] w-full">
|
|
114
|
+
{/* Header - fixed at top */}
|
|
115
|
+
<div className="bg-gray-100 dark:bg-neutral-900 flex items-center justify-between p-3">
|
|
116
|
+
<div className="bg-gray-200 dark:bg-neutral-700 rounded px-2">
|
|
117
|
+
<span className="text-gray-700 dark:text-neutral-50 text-xs">
|
|
118
|
+
MCP Configuration
|
|
119
|
+
</span>
|
|
120
|
+
</div>
|
|
121
|
+
<CopyButton
|
|
122
|
+
text={mcpJsonConfig}
|
|
123
|
+
showText={false}
|
|
124
|
+
className="h-6 w-6 p-1 bg-white dark:bg-neutral-700 hover:bg-neutral-100 dark:hover:bg-neutral-600 border-none rounded-md shadow-sm min-w-0 text-black dark:text-white"
|
|
125
|
+
/>
|
|
126
|
+
</div>
|
|
127
|
+
{/* Scrollable content */}
|
|
128
|
+
<div className="flex-1 overflow-auto p-3">
|
|
129
|
+
<pre className="text-gray-700 dark:text-neutral-300 text-sm leading-6 m-0 whitespace-pre-wrap break-all">
|
|
130
|
+
<code>{mcpJsonConfig}</code>
|
|
131
|
+
</pre>
|
|
132
|
+
</div>
|
|
133
|
+
</div>
|
|
134
|
+
</div>
|
|
135
|
+
) : (
|
|
136
|
+
<div className="flex flex-col gap-3">
|
|
137
|
+
<p className="text-gray-900 dark:text-white text-sm">
|
|
138
|
+
<span className="font-semibold leading-5">1.</span>
|
|
139
|
+
<span className="leading-6"> Install in one click</span>
|
|
140
|
+
</p>
|
|
141
|
+
<CodeBlock
|
|
142
|
+
code={installCommand}
|
|
143
|
+
label="Terminal Command"
|
|
144
|
+
className={cn(isLoading && 'animate-pulse')}
|
|
145
|
+
/>
|
|
146
|
+
</div>
|
|
147
|
+
)}
|
|
148
|
+
|
|
149
|
+
{/* Step 2 */}
|
|
150
|
+
<div className="flex flex-col gap-3">
|
|
151
|
+
<p className="text-gray-900 dark:text-white text-sm">
|
|
152
|
+
<span className="font-semibold leading-5">2.</span>
|
|
153
|
+
<span className="leading-6"> Check for connection using this prompt</span>
|
|
154
|
+
</p>
|
|
155
|
+
<CodeBlock code={testPrompt} label="prompt" className="bg-gray-100 dark:bg-neutral-900" />
|
|
156
|
+
</div>
|
|
157
|
+
</div>
|
|
158
|
+
);
|
|
159
|
+
}
|