insforge 1.3.0 → 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/CHANGELOG.md +2 -0
- package/auth/package.json +5 -3
- package/auth/src/lib/broadcastService.ts +115 -117
- package/auth/src/lib/insforge.ts +8 -0
- package/auth/src/main.tsx +2 -4
- package/auth/src/pages/SignInPage.tsx +60 -60
- package/auth/src/pages/SignUpPage.tsx +60 -60
- package/auth/src/pages/VerifyEmailPage.tsx +18 -0
- package/auth/tsconfig.json +2 -1
- package/backend/package.json +10 -6
- 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 +85 -32
- package/backend/src/api/routes/auth/oauth.routes.ts +11 -6
- package/backend/src/api/routes/database/index.routes.ts +2 -0
- package/backend/src/api/routes/database/records.routes.ts +39 -175
- package/backend/src/api/routes/database/rpc.routes.ts +69 -0
- package/backend/src/api/routes/deployments/index.routes.ts +192 -0
- package/backend/src/api/routes/docs/index.routes.ts +3 -2
- package/backend/src/api/routes/email/index.routes.ts +35 -35
- package/backend/src/api/routes/functions/index.routes.ts +3 -3
- package/backend/src/api/routes/metadata/index.routes.ts +26 -0
- package/backend/src/api/routes/webhooks/index.routes.ts +109 -0
- package/backend/src/infra/database/database.manager.ts +0 -10
- 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/security/token.manager.ts +1 -4
- package/backend/src/providers/ai/openrouter.provider.ts +12 -3
- 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/server.ts +19 -7
- 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/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 +134 -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 -85
- 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/functions/function.service.ts +61 -41
- package/backend/src/services/logs/audit.service.ts +10 -10
- 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 +5 -1
- package/backend/src/types/database.ts +2 -0
- package/backend/src/types/deployments.ts +33 -0
- package/backend/src/types/storage.ts +1 -1
- package/backend/src/types/webhooks.ts +45 -0
- package/backend/src/utils/cookies.ts +34 -35
- package/backend/src/utils/environment.ts +0 -14
- package/backend/src/utils/s3-config-loader.ts +64 -64
- package/backend/src/utils/seed.ts +334 -301
- package/backend/src/utils/sql-parser.ts +126 -0
- package/backend/src/utils/utils.ts +114 -114
- package/backend/src/utils/validations.ts +10 -10
- package/backend/tests/local/test-rpc.sh +141 -0
- package/backend/tests/local/test-secrets.sh +1 -1
- package/backend/tests/manual/test-ai-model-plugins.sh +258 -0
- package/backend/tests/manual/test-rawsql-modes.sh +24 -24
- package/backend/tests/unit/database-advance.test.ts +326 -0
- package/backend/tests/unit/helpers.test.ts +2 -2
- package/claude-plugin/skills/insforge-schema-patterns/SKILL.md +13 -10
- package/docker-compose.prod.yml +1 -1
- package/docker-compose.yml +1 -1
- package/docs/agent-docs/deployment.md +79 -0
- package/docs/changelog.mdx +165 -72
- package/docs/core-concepts/ai/architecture.mdx +1 -23
- package/docs/core-concepts/ai/sdk.mdx +26 -1
- package/docs/core-concepts/authentication/architecture.mdx +6 -8
- package/docs/core-concepts/authentication/sdk.mdx +387 -91
- package/docs/core-concepts/authentication/ui-components/customization.mdx +460 -256
- package/docs/core-concepts/authentication/ui-components/nextjs.mdx +50 -24
- package/docs/core-concepts/authentication/ui-components/react-router.mdx +18 -19
- package/docs/core-concepts/authentication/ui-components/react.mdx +26 -19
- package/docs/core-concepts/database/architecture.mdx +58 -21
- package/docs/core-concepts/database/pgvector.mdx +138 -0
- package/docs/core-concepts/database/sdk.mdx +17 -17
- package/docs/core-concepts/deployments/architecture.mdx +152 -0
- package/docs/core-concepts/email/architecture.mdx +4 -2
- package/docs/core-concepts/functions/architecture.mdx +1 -1
- package/docs/core-concepts/functions/sdk.mdx +0 -1
- package/docs/core-concepts/realtime/architecture.mdx +1 -1
- package/docs/core-concepts/storage/architecture.mdx +1 -1
- package/docs/core-concepts/storage/sdk.mdx +25 -25
- package/docs/docs.json +14 -6
- package/docs/favicon.png +0 -0
- package/docs/favicon.svg +3 -18
- package/docs/images/changelog/dec-2025/apple-oauth.mp4 +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/realtime2.png +0 -0
- 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 +7 -3
- package/docs/introduction.mdx +9 -8
- package/docs/mcp-setup.mdx +332 -0
- package/docs/oauth-server.mdx +563 -0
- package/docs/partnership.mdx +79 -10
- package/docs/quickstart.mdx +1 -1
- package/docs/vscode-extension.mdx +74 -0
- package/eslint.config.js +1 -0
- package/examples/response-examples.md +1 -1
- package/frontend/package.json +1 -1
- package/frontend/src/App.tsx +8 -3
- package/frontend/src/assets/logos/antigravity.svg +1 -0
- package/frontend/src/assets/logos/copilot.svg +10 -0
- package/frontend/src/assets/logos/deepseek.svg +139 -0
- package/frontend/src/assets/logos/kiro.svg +9 -0
- package/frontend/src/assets/logos/qoder.svg +4 -0
- package/frontend/src/assets/logos/qwen.svg +15 -0
- 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 +4 -27
- 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/pages/AIPage.tsx +166 -166
- package/frontend/src/features/auth/components/AuthPreview.tsx +96 -96
- package/frontend/src/features/auth/components/UsersDataGrid.tsx +55 -31
- package/frontend/src/features/auth/components/index.ts +5 -5
- package/frontend/src/features/auth/pages/AuthMethodsPage.tsx +275 -275
- package/frontend/src/features/dashboard/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/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/useRawSQL.ts +3 -2
- package/frontend/src/features/database/hooks/useTables.ts +5 -7
- package/frontend/src/features/database/pages/FunctionsPage.tsx +0 -5
- package/frontend/src/features/database/pages/IndexesPage.tsx +0 -5
- package/frontend/src/features/database/pages/PoliciesPage.tsx +0 -5
- package/frontend/src/features/database/pages/SQLEditorPage.tsx +2 -2
- package/frontend/src/features/database/pages/TriggersPage.tsx +0 -5
- package/frontend/src/features/database/services/advance.service.ts +1 -15
- package/frontend/src/features/database/services/record.service.ts +4 -20
- package/frontend/src/features/database/services/table.service.ts +1 -4
- 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/pages/SecretsPage.tsx +118 -118
- 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/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/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/settings/pages/SettingsPage.tsx +349 -0
- package/frontend/src/features/visualizer/components/AuthNode.tsx +4 -4
- package/frontend/src/features/visualizer/components/SchemaVisualizer.tsx +21 -8
- package/frontend/src/features/visualizer/pages/VisualizerPage.tsx +10 -1
- package/frontend/src/index.css +249 -249
- package/frontend/src/lib/contexts/ModalContext.tsx +35 -0
- 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 -99
- package/frontend/src/lib/services/metadata.service.ts +20 -3
- package/frontend/src/lib/utils/menuItems.ts +223 -207
- package/frontend/src/lib/utils/utils.ts +196 -196
- package/functions/server.ts +315 -315
- package/functions/worker-template.js +1 -1
- package/openapi/ai.yaml +115 -5
- package/openapi/auth.yaml +97 -17
- package/openapi/logs.yaml +0 -2
- package/openapi/metadata.yaml +0 -2
- package/openapi/records.yaml +21 -21
- package/openapi/tables.yaml +1 -2
- package/package.json +1 -1
- package/shared-schemas/package.json +1 -1
- package/shared-schemas/src/ai-api.schema.ts +251 -143
- package/shared-schemas/src/ai.schema.ts +63 -63
- package/shared-schemas/src/auth-api.schema.ts +34 -6
- package/shared-schemas/src/auth.schema.ts +17 -10
- package/shared-schemas/src/cloud-events.schema.ts +26 -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 +8 -2
- package/shared-schemas/src/email-api.schema.ts +30 -30
- 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 -18
- package/shared-schemas/src/metadata.schema.ts +30 -4
- package/shared-schemas/src/secrets-api.schema.ts +44 -0
- package/shared-schemas/src/secrets.schema.ts +15 -0
- package/zeabur/README.md +13 -0
- package/zeabur/template.yml +20 -51
- package/backend/src/types/profile.ts +0 -55
- package/frontend/src/components/ProjectInfoModal.tsx +0 -128
|
@@ -1,118 +1,125 @@
|
|
|
1
|
-
import { useCallback, useEffect, useState } from 'react';
|
|
2
|
-
import { useNavigate } from 'react-router-dom';
|
|
3
|
-
import { LockIcon } from 'lucide-react';
|
|
4
|
-
import { useAuth } from '@/lib/contexts/AuthContext';
|
|
5
|
-
import { postMessageToParent } from '@/lib/utils/cloudMessaging';
|
|
6
|
-
import { useMcpUsage } from '@/features/logs/hooks/useMcpUsage';
|
|
7
|
-
import { usePartnerOrigin } from '../hooks/usePartnerOrigin';
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const
|
|
12
|
-
const {
|
|
13
|
-
const {
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
1
|
+
import { useCallback, useEffect, useState } from 'react';
|
|
2
|
+
import { useNavigate } from 'react-router-dom';
|
|
3
|
+
import { LockIcon } from 'lucide-react';
|
|
4
|
+
import { useAuth } from '@/lib/contexts/AuthContext';
|
|
5
|
+
import { postMessageToParent } from '@/lib/utils/cloudMessaging';
|
|
6
|
+
import { useMcpUsage } from '@/features/logs/hooks/useMcpUsage';
|
|
7
|
+
import { usePartnerOrigin } from '../hooks/usePartnerOrigin';
|
|
8
|
+
import { useModal } from '@/lib/hooks/useModal';
|
|
9
|
+
|
|
10
|
+
export default function CloudLoginPage() {
|
|
11
|
+
const navigate = useNavigate();
|
|
12
|
+
const { loginWithAuthorizationCode, isAuthenticated } = useAuth();
|
|
13
|
+
const { hasCompletedOnboarding, isLoading: isMcpUsageLoading } = useMcpUsage();
|
|
14
|
+
const { isPartnerOrigin } = usePartnerOrigin();
|
|
15
|
+
const [authError, setAuthError] = useState<string | null>(null);
|
|
16
|
+
const { setOnboardingModalOpen } = useModal();
|
|
17
|
+
// Handle authorization code from postMessage
|
|
18
|
+
const onAuthorizationCodeReceived = useCallback(
|
|
19
|
+
async (event: MessageEvent) => {
|
|
20
|
+
try {
|
|
21
|
+
// Validate origin - allow insforge.dev, *.insforge.dev, and partner domains
|
|
22
|
+
const isInsforgeOrigin =
|
|
23
|
+
event.origin.endsWith('.insforge.dev') || event.origin === 'https://insforge.dev';
|
|
24
|
+
|
|
25
|
+
if (!isInsforgeOrigin) {
|
|
26
|
+
const isPartner = await isPartnerOrigin(event.origin);
|
|
27
|
+
if (!isPartner) {
|
|
28
|
+
console.warn('Received message from unauthorized origin:', event.origin);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const authorizationCode = event.data.code;
|
|
34
|
+
|
|
35
|
+
setAuthError(null);
|
|
36
|
+
// Exchange the authorization code for an access token
|
|
37
|
+
const success = await loginWithAuthorizationCode(authorizationCode);
|
|
38
|
+
if (success) {
|
|
39
|
+
// Notify parent of success
|
|
40
|
+
postMessageToParent(
|
|
41
|
+
{
|
|
42
|
+
type: 'AUTH_SUCCESS',
|
|
43
|
+
},
|
|
44
|
+
event.origin
|
|
45
|
+
);
|
|
46
|
+
} else {
|
|
47
|
+
setAuthError('The authorization code may have expired or already been used.');
|
|
48
|
+
postMessageToParent(
|
|
49
|
+
{
|
|
50
|
+
type: 'AUTH_ERROR',
|
|
51
|
+
message: 'Authorization code validation failed',
|
|
52
|
+
},
|
|
53
|
+
event.origin
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
} catch (error) {
|
|
57
|
+
console.error('Authorization code exchange failed:', error);
|
|
58
|
+
setAuthError('The authorization code may have expired or already been used.');
|
|
59
|
+
postMessageToParent(
|
|
60
|
+
{
|
|
61
|
+
type: 'AUTH_ERROR',
|
|
62
|
+
message: 'Authorization code validation failed',
|
|
63
|
+
},
|
|
64
|
+
event.origin
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
[loginWithAuthorizationCode, isPartnerOrigin]
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
useEffect(() => {
|
|
72
|
+
const handleMessage = (event: MessageEvent) => {
|
|
73
|
+
if (event.data?.type === 'AUTHORIZATION_CODE' && event.data?.code) {
|
|
74
|
+
void onAuthorizationCodeReceived(event);
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
window.addEventListener('message', handleMessage);
|
|
79
|
+
|
|
80
|
+
return () => {
|
|
81
|
+
window.removeEventListener('message', handleMessage);
|
|
82
|
+
};
|
|
83
|
+
}, [onAuthorizationCodeReceived]);
|
|
84
|
+
|
|
85
|
+
useEffect(() => {
|
|
86
|
+
if (isAuthenticated && !isMcpUsageLoading) {
|
|
87
|
+
if (!hasCompletedOnboarding) {
|
|
88
|
+
setOnboardingModalOpen(true);
|
|
89
|
+
}
|
|
90
|
+
void navigate('/dashboard', { replace: true });
|
|
91
|
+
}
|
|
92
|
+
}, [
|
|
93
|
+
hasCompletedOnboarding,
|
|
94
|
+
isAuthenticated,
|
|
95
|
+
isMcpUsageLoading,
|
|
96
|
+
navigate,
|
|
97
|
+
setOnboardingModalOpen,
|
|
98
|
+
]);
|
|
99
|
+
|
|
100
|
+
// Show error state if authentication failed
|
|
101
|
+
if (authError) {
|
|
102
|
+
return (
|
|
103
|
+
<div className="min-h-screen bg-neutral-800 flex items-center justify-center px-4">
|
|
104
|
+
<div className="text-center text-white">
|
|
105
|
+
<LockIcon className="h-12 w-12 mx-auto mb-4 text-red-400" />
|
|
106
|
+
<h2 className="text-xl font-semibold mb-2">Authentication Failed</h2>
|
|
107
|
+
<p className="text-gray-400 text-sm max-w-md">{authError}</p>
|
|
108
|
+
</div>
|
|
109
|
+
</div>
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Show authenticating state
|
|
114
|
+
return (
|
|
115
|
+
<div className="min-h-screen bg-neutral-800 flex items-center justify-center px-4">
|
|
116
|
+
<div className="text-center">
|
|
117
|
+
<div className="animate-spin mb-4">
|
|
118
|
+
<LockIcon className="h-12 w-12 text-white mx-auto" />
|
|
119
|
+
</div>
|
|
120
|
+
<h2 className="text-xl font-semibold text-white mb-2">Authenticating...</h2>
|
|
121
|
+
<p className="text-sm text-gray-400">Please wait while we verify your identity</p>
|
|
122
|
+
</div>
|
|
123
|
+
</div>
|
|
124
|
+
);
|
|
125
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { X } from 'lucide-react';
|
|
2
|
+
import type { LogSchema } from '@insforge/shared-schemas';
|
|
3
|
+
|
|
4
|
+
interface LogDetailPanelProps {
|
|
5
|
+
log: LogSchema | null;
|
|
6
|
+
onClose: () => void;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function LogDetailPanel({ log, onClose }: LogDetailPanelProps) {
|
|
10
|
+
if (!log) {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// Format the log body as pretty JSON
|
|
15
|
+
const formattedContent = JSON.stringify(log.body, null, 2);
|
|
16
|
+
|
|
17
|
+
return (
|
|
18
|
+
<div className="flex flex-col h-full bg-gray-100 dark:bg-neutral-700 border border-gray-300 dark:border-neutral-600 overflow-hidden">
|
|
19
|
+
{/* Header */}
|
|
20
|
+
<div className="flex items-center justify-between px-3 py-2 border-b border-gray-300 dark:border-neutral-600">
|
|
21
|
+
<p className="text-sm text-gray-600 dark:text-neutral-300 font-normal leading-6">
|
|
22
|
+
Log Content
|
|
23
|
+
</p>
|
|
24
|
+
<button
|
|
25
|
+
onClick={onClose}
|
|
26
|
+
className="p-1 hover:bg-gray-200 dark:hover:bg-neutral-600 rounded transition-colors"
|
|
27
|
+
aria-label="Close panel"
|
|
28
|
+
>
|
|
29
|
+
<X className="w-4 h-4 text-gray-500 dark:text-neutral-400" />
|
|
30
|
+
</button>
|
|
31
|
+
</div>
|
|
32
|
+
|
|
33
|
+
{/* Content */}
|
|
34
|
+
<div className="flex-1 overflow-auto p-3">
|
|
35
|
+
<pre className="text-sm text-gray-900 dark:text-white font-normal leading-6 whitespace-pre-wrap break-all font-mono">
|
|
36
|
+
{formattedContent}
|
|
37
|
+
</pre>
|
|
38
|
+
</div>
|
|
39
|
+
</div>
|
|
40
|
+
);
|
|
41
|
+
}
|
|
@@ -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,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
|
+
}
|