insforge 0.3.1
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/.dockerignore +58 -0
- package/.env.example +49 -0
- package/.github/ISSUE_TEMPLATE/bug_report.yml +83 -0
- package/.github/ISSUE_TEMPLATE/config.yml +11 -0
- package/.github/ISSUE_TEMPLATE/feature_request.yml +79 -0
- package/.github/copilot-instructions.md +147 -0
- package/.github/workflows/build-image.yml +65 -0
- package/.github/workflows/ci-premerge-check.yml +24 -0
- package/.github/workflows/deploy-aws.yml +130 -0
- package/.github/workflows/lint-and-format.yml +33 -0
- package/.prettierignore +65 -0
- package/.prettierrc +9 -0
- package/CHANGELOG.md +3 -0
- package/CONTRIBUTING.md +126 -0
- package/Dockerfile +27 -0
- package/GITHUB_OAUTH_SETUP.md +49 -0
- package/GOOGLE_OAUTH_SETUP.md +148 -0
- package/LICENSE +201 -0
- package/README.md +134 -0
- package/assets/Dark.svg +23 -0
- package/assets/archDiagram.png +0 -0
- package/assets/banner.png +0 -0
- package/assets/mcpInstallv2.png +0 -0
- package/assets/sampleResponse.png +0 -0
- package/assets/signin.png +0 -0
- package/assets/userflow.png +0 -0
- package/backend/migrations/000_create-base-tables.sql +142 -0
- package/backend/migrations/001_create-helper-functions.sql +41 -0
- package/backend/migrations/002_rename-auth-tables.sql +30 -0
- package/backend/migrations/003_create-users-table.sql +56 -0
- package/backend/migrations/004_add-reload-postgrest-func.sql +24 -0
- package/backend/migrations/005_enable-project-admin-modify-users.sql +30 -0
- package/backend/migrations/006_modify-ai-usage-table.sql +25 -0
- package/backend/migrations/007_drop-metadata-table.sql +2 -0
- package/backend/migrations/008_add-system-tables.sql +77 -0
- package/backend/migrations/009_add-function-secrets.sql +24 -0
- package/backend/migrations/010_modify-ai-config-modalities.sql +93 -0
- package/backend/migrations/011_refactor-secrets-table.sql +15 -0
- package/backend/migrations/012_add-storage-uploaded-by.sql +8 -0
- package/backend/package.json +75 -0
- package/backend/src/api/middleware/auth.ts +240 -0
- package/backend/src/api/middleware/error.ts +231 -0
- package/backend/src/api/middleware/upload.ts +59 -0
- package/backend/src/api/routes/agent.ts +29 -0
- package/backend/src/api/routes/ai.ts +472 -0
- package/backend/src/api/routes/auth.oauth.ts +482 -0
- package/backend/src/api/routes/auth.ts +386 -0
- package/backend/src/api/routes/database.advance.ts +275 -0
- package/backend/src/api/routes/database.records.ts +246 -0
- package/backend/src/api/routes/database.tables.ts +161 -0
- package/backend/src/api/routes/docs.ts +66 -0
- package/backend/src/api/routes/functions.ts +183 -0
- package/backend/src/api/routes/logs.ts +150 -0
- package/backend/src/api/routes/metadata.ts +160 -0
- package/backend/src/api/routes/openapi.ts +82 -0
- package/backend/src/api/routes/secrets.ts +199 -0
- package/backend/src/api/routes/storage.ts +547 -0
- package/backend/src/api/routes/usage.ts +96 -0
- package/backend/src/core/ai/chat.ts +207 -0
- package/backend/src/core/ai/client.ts +242 -0
- package/backend/src/core/ai/config.ts +187 -0
- package/backend/src/core/ai/image.ts +156 -0
- package/backend/src/core/ai/model.ts +117 -0
- package/backend/src/core/ai/usage.ts +290 -0
- package/backend/src/core/auth/auth.ts +781 -0
- package/backend/src/core/auth/oauth.ts +398 -0
- package/backend/src/core/database/advance.ts +1074 -0
- package/backend/src/core/database/manager.ts +178 -0
- package/backend/src/core/database/table.ts +772 -0
- package/backend/src/core/documentation/agent.ts +689 -0
- package/backend/src/core/documentation/openapi.ts +856 -0
- package/backend/src/core/functions/functions.ts +310 -0
- package/backend/src/core/logs/analytics.ts +76 -0
- package/backend/src/core/logs/audit.ts +255 -0
- package/backend/src/core/logs/providers/base.provider.ts +83 -0
- package/backend/src/core/logs/providers/cloudwatch.provider.ts +510 -0
- package/backend/src/core/logs/providers/localdb.provider.ts +246 -0
- package/backend/src/core/secrets/encryption.ts +58 -0
- package/backend/src/core/secrets/secrets.ts +410 -0
- package/backend/src/core/socket/socket.ts +388 -0
- package/backend/src/core/socket/types.ts +79 -0
- package/backend/src/core/storage/storage.ts +923 -0
- package/backend/src/server.ts +288 -0
- package/backend/src/types/ai.ts +46 -0
- package/backend/src/types/auth.ts +90 -0
- package/backend/src/types/database.ts +136 -0
- package/backend/src/types/error-constants.ts +86 -0
- package/backend/src/types/logs.ts +47 -0
- package/backend/src/types/profile.ts +55 -0
- package/backend/src/types/storage.ts +23 -0
- package/backend/src/utils/cloud-token.ts +39 -0
- package/backend/src/utils/constants.ts +1 -0
- package/backend/src/utils/environment.ts +35 -0
- package/backend/src/utils/helpers.ts +49 -0
- package/backend/src/utils/logger.ts +13 -0
- package/backend/src/utils/response.ts +62 -0
- package/backend/src/utils/seed.ts +205 -0
- package/backend/src/utils/sql-parser.ts +63 -0
- package/backend/src/utils/uuid.ts +9 -0
- package/backend/src/utils/validations.ts +129 -0
- package/backend/tests/README.md +134 -0
- package/backend/tests/cleanup-all-test-data.sh +231 -0
- package/backend/tests/cloud/test-s3-multitenant.sh +132 -0
- package/backend/tests/local/comprehensive-curl-tests.sh +156 -0
- package/backend/tests/local/test-auth-router.sh +144 -0
- package/backend/tests/local/test-database-router.sh +222 -0
- package/backend/tests/local/test-e2e.sh +241 -0
- package/backend/tests/local/test-fk-errors.sh +97 -0
- package/backend/tests/local/test-id-field.sh +201 -0
- package/backend/tests/local/test-public-bucket.sh +265 -0
- package/backend/tests/local/test-secrets.sh +248 -0
- package/backend/tests/local/test-serverless-functions.sh.disabled +325 -0
- package/backend/tests/local/test-traditional-rest.sh +209 -0
- package/backend/tests/manual/README.md +51 -0
- package/backend/tests/manual/create-large-table-simple.sql +11 -0
- package/backend/tests/manual/seed-large-table.sql +101 -0
- package/backend/tests/manual/setup-large-table-extras.sql +34 -0
- package/backend/tests/manual/test-better-auth.sh +303 -0
- package/backend/tests/manual/test-bulk-upsert.sh +410 -0
- package/backend/tests/manual/test-database-advance.sh +297 -0
- package/backend/tests/manual/test-postgrest-stability.sh +192 -0
- package/backend/tests/manual/test-rawsql-export-import.sh +412 -0
- package/backend/tests/manual/test-universal-storage.sh +264 -0
- package/backend/tests/manual/test-users.sql +18 -0
- package/backend/tests/run-all-tests.sh +140 -0
- package/backend/tests/setup.ts +22 -0
- package/backend/tests/test-config.sh +303 -0
- package/backend/tsconfig.json +23 -0
- package/backend/tsup.config.ts +18 -0
- package/backend/vitest.config.ts +22 -0
- package/docker-compose.prod.yml +145 -0
- package/docker-compose.yml +167 -0
- package/docker-init/db/db-init.sql +125 -0
- package/docker-init/db/jwt.sql +5 -0
- package/docker-init/db/logs.sql +9 -0
- package/docker-init/db/postgresql.conf +17 -0
- package/docs/deprecated/insforge-auth-api.md +215 -0
- package/docs/deprecated/insforge-auth-sdk.md +100 -0
- package/docs/deprecated/insforge-db-api.md +359 -0
- package/docs/deprecated/insforge-db-sdk.md +140 -0
- package/docs/deprecated/insforge-debug-sdk.md +157 -0
- package/docs/deprecated/insforge-debug.md +65 -0
- package/docs/deprecated/insforge-instructions.md +124 -0
- package/docs/deprecated/insforge-project.md +118 -0
- package/docs/deprecated/insforge-storage-api.md +279 -0
- package/docs/deprecated/insforge-storage-sdk.md +159 -0
- package/docs/insforge-instructions-sdk.md +407 -0
- package/eslint.config.js +317 -0
- package/examples/oauth/frontend-oauth-example.html +251 -0
- package/examples/response-examples.md +444 -0
- package/frontend/README.md +112 -0
- package/frontend/components.json +17 -0
- package/frontend/index.html +13 -0
- package/frontend/package.json +63 -0
- package/frontend/public/favicon.ico +0 -0
- package/frontend/src/App.tsx +106 -0
- package/frontend/src/assets/icons/checkbox_checked.svg +6 -0
- package/frontend/src/assets/icons/checkbox_undetermined.svg +6 -0
- package/frontend/src/assets/icons/checked.svg +3 -0
- package/frontend/src/assets/icons/error.svg +3 -0
- package/frontend/src/assets/icons/pencil.svg +4 -0
- package/frontend/src/assets/icons/refresh.svg +4 -0
- package/frontend/src/assets/icons/step_active.svg +3 -0
- package/frontend/src/assets/icons/step_inactive.svg +11 -0
- package/frontend/src/assets/icons/warning.svg +3 -0
- package/frontend/src/assets/logos/amazon.svg +1 -0
- package/frontend/src/assets/logos/claude_code.svg +3 -0
- package/frontend/src/assets/logos/cline.svg +6 -0
- package/frontend/src/assets/logos/cursor.svg +20 -0
- package/frontend/src/assets/logos/discord.svg +9 -0
- package/frontend/src/assets/logos/gemini.svg +19 -0
- package/frontend/src/assets/logos/github.svg +5 -0
- package/frontend/src/assets/logos/google.svg +13 -0
- package/frontend/src/assets/logos/grok.svg +10 -0
- package/frontend/src/assets/logos/insforge_dark.svg +15 -0
- package/frontend/src/assets/logos/insforge_light.svg +15 -0
- package/frontend/src/assets/logos/openai.svg +10 -0
- package/frontend/src/assets/logos/roo_code.svg +9 -0
- package/frontend/src/assets/logos/trae.svg +3 -0
- package/frontend/src/assets/logos/windsurf.svg +10 -0
- package/frontend/src/components/ButtonWithLoading.tsx +27 -0
- package/frontend/src/components/Checkbox.tsx +61 -0
- package/frontend/src/components/CodeBlock.tsx +32 -0
- package/frontend/src/components/ConfirmDialog.tsx +96 -0
- package/frontend/src/components/CopyButton.tsx +69 -0
- package/frontend/src/components/DeleteActionButton.tsx +42 -0
- package/frontend/src/components/EmptyState.tsx +41 -0
- package/frontend/src/components/ErrorState.tsx +35 -0
- package/frontend/src/components/FeatureSidebar.tsx +126 -0
- package/frontend/src/components/FeatureSidebarItem.tsx +101 -0
- package/frontend/src/components/JsonHighlight.tsx +61 -0
- package/frontend/src/components/LoadingState.tsx +16 -0
- package/frontend/src/components/PaginationControls.tsx +54 -0
- package/frontend/src/components/PromptDialog.tsx +68 -0
- package/frontend/src/components/SearchInput.tsx +90 -0
- package/frontend/src/components/SelectionClearButton.tsx +26 -0
- package/frontend/src/components/Stepper.tsx +139 -0
- package/frontend/src/components/ThemeToggle.tsx +58 -0
- package/frontend/src/components/TypeBadge.tsx +20 -0
- package/frontend/src/components/datagrid/DataGrid.tsx +264 -0
- package/frontend/src/components/datagrid/DefaultCellRenderer.tsx +114 -0
- package/frontend/src/components/datagrid/IdCell.tsx +44 -0
- package/frontend/src/components/datagrid/SortableHeader.tsx +74 -0
- package/frontend/src/components/datagrid/cell-editors/BooleanCellEditor.tsx +54 -0
- package/frontend/src/components/datagrid/cell-editors/DateCellEditor.tsx +483 -0
- package/frontend/src/components/datagrid/cell-editors/JsonCellEditor.tsx +362 -0
- package/frontend/src/components/datagrid/cell-editors/TextCellEditor.tsx +38 -0
- package/frontend/src/components/datagrid/cell-editors/index.ts +14 -0
- package/frontend/src/components/datagrid/cell-editors/types.ts +43 -0
- package/frontend/src/components/datagrid/datagridTypes.tsx +72 -0
- package/frontend/src/components/datagrid/index.tsx +20 -0
- package/frontend/src/components/index.ts +39 -0
- package/frontend/src/components/layout/AppHeader.tsx +146 -0
- package/frontend/src/components/layout/AppSidebar.tsx +190 -0
- package/frontend/src/components/layout/CloudLayout.tsx +95 -0
- package/frontend/src/components/layout/Layout.tsx +43 -0
- package/frontend/src/components/radix/Alert.tsx +45 -0
- package/frontend/src/components/radix/AlertDialog.tsx +115 -0
- package/frontend/src/components/radix/Avatar.tsx +45 -0
- package/frontend/src/components/radix/Badge.tsx +33 -0
- package/frontend/src/components/radix/Button.tsx +50 -0
- package/frontend/src/components/radix/Card.tsx +58 -0
- package/frontend/src/components/radix/Dialog.tsx +98 -0
- package/frontend/src/components/radix/DropdownMenu.tsx +185 -0
- package/frontend/src/components/radix/Form.tsx +167 -0
- package/frontend/src/components/radix/Input.tsx +22 -0
- package/frontend/src/components/radix/Label.tsx +19 -0
- package/frontend/src/components/radix/Popover.tsx +29 -0
- package/frontend/src/components/radix/ScrollArea.tsx +44 -0
- package/frontend/src/components/radix/Select.tsx +151 -0
- package/frontend/src/components/radix/Separator.tsx +26 -0
- package/frontend/src/components/radix/Sheet.tsx +119 -0
- package/frontend/src/components/radix/Skeleton.tsx +7 -0
- package/frontend/src/components/radix/Switch.tsx +29 -0
- package/frontend/src/components/radix/Tabs.tsx +50 -0
- package/frontend/src/components/radix/Textarea.tsx +21 -0
- package/frontend/src/components/radix/Tooltip.tsx +28 -0
- package/frontend/src/features/ai/components/AIConfigCard.tsx +154 -0
- package/frontend/src/features/ai/components/AIConfigDialog.tsx +76 -0
- package/frontend/src/features/ai/components/AIConfigForm.tsx +222 -0
- package/frontend/src/features/ai/components/AIEmptyState.tsx +18 -0
- package/frontend/src/features/ai/components/fields/ModalityField.tsx +87 -0
- package/frontend/src/features/ai/components/fields/ModelSelectionField.tsx +134 -0
- package/frontend/src/features/ai/components/fields/SystemPromptField.tsx +33 -0
- package/frontend/src/features/ai/helpers.ts +155 -0
- package/frontend/src/features/ai/hooks/useAIConfigs.ts +221 -0
- package/frontend/src/features/ai/hooks/useAIUsage.ts +77 -0
- package/frontend/src/features/ai/page/AIPage.tsx +178 -0
- package/frontend/src/features/ai/services/ai.service.ts +148 -0
- package/frontend/src/features/auth/components/AddOAuthDialog.tsx +106 -0
- package/frontend/src/features/auth/components/AuthMethodTab.tsx +238 -0
- package/frontend/src/features/auth/components/OAuthConfigDialog.tsx +303 -0
- package/frontend/src/features/auth/components/OAuthEmptyState.tsx +15 -0
- package/frontend/src/features/auth/components/UserFormDialog.tsx +248 -0
- package/frontend/src/features/auth/components/UsersDataGrid.tsx +183 -0
- package/frontend/src/features/auth/components/UsersTab.tsx +114 -0
- package/frontend/src/features/auth/hooks/useOAuthConfig.ts +129 -0
- package/frontend/src/features/auth/hooks/useUsers.ts +57 -0
- package/frontend/src/features/auth/index.ts +9 -0
- package/frontend/src/features/auth/page/AuthenticationPage.tsx +169 -0
- package/frontend/src/features/auth/services/auth.service.ts +112 -0
- package/frontend/src/features/auth/services/oauth.service.ts +49 -0
- package/frontend/src/features/dashboard/page/DashboardPage.tsx +194 -0
- package/frontend/src/features/database/components/ColumnTypeSelect.tsx +64 -0
- package/frontend/src/features/database/components/DatabaseDataGrid.tsx +282 -0
- package/frontend/src/features/database/components/ForeignKeyCell.tsx +187 -0
- package/frontend/src/features/database/components/ForeignKeyPopover.tsx +378 -0
- package/frontend/src/features/database/components/LinkRecordModal.tsx +288 -0
- package/frontend/src/features/database/components/RecordFormDialog.tsx +164 -0
- package/frontend/src/features/database/components/RecordFormField.tsx +568 -0
- package/frontend/src/features/database/components/TableEmptyState.tsx +21 -0
- package/frontend/src/features/database/components/TableForm.tsx +656 -0
- package/frontend/src/features/database/components/TableFormColumn.tsx +137 -0
- package/frontend/src/features/database/components/TableListSkeleton.tsx +9 -0
- package/frontend/src/features/database/components/TableSidebar.tsx +47 -0
- package/frontend/src/features/database/constants.ts +26 -0
- package/frontend/src/features/database/helpers.ts +125 -0
- package/frontend/src/features/database/hooks/UseLinkModal.tsx +78 -0
- package/frontend/src/features/database/index.ts +12 -0
- package/frontend/src/features/database/page/DatabasePage.tsx +626 -0
- package/frontend/src/features/database/schema.ts +25 -0
- package/frontend/src/features/database/services/database.service.ts +216 -0
- package/frontend/src/features/functions/components/FunctionEmptyState.tsx +15 -0
- package/frontend/src/features/functions/components/FunctionRow.tsx +71 -0
- package/frontend/src/features/functions/components/FunctionViewer.tsx +46 -0
- package/frontend/src/features/functions/components/FunctionsContent.tsx +88 -0
- package/frontend/src/features/functions/components/FunctionsSidebar.tsx +56 -0
- package/frontend/src/features/functions/components/SecretEmptyState.tsx +23 -0
- package/frontend/src/features/functions/components/SecretRow.tsx +68 -0
- package/frontend/src/features/functions/components/SecretsContent.tsx +120 -0
- package/frontend/src/features/functions/hooks/useFunctions.ts +106 -0
- package/frontend/src/features/functions/page/FunctionsPage.tsx +28 -0
- package/frontend/src/features/functions/services/functions.service.ts +48 -0
- package/frontend/src/features/login/components/AuthErrorBoundary.tsx +87 -0
- package/frontend/src/features/login/components/PrivateRoute.tsx +24 -0
- package/frontend/src/features/login/page/CloudLoginPage.tsx +93 -0
- package/frontend/src/features/login/page/LoginPage.tsx +174 -0
- package/frontend/src/features/logs/components/AnalyticsLogsTable.tsx +313 -0
- package/frontend/src/features/logs/components/LogsTable.tsx +199 -0
- package/frontend/src/features/logs/hooks/useAuditLogs.ts +39 -0
- package/frontend/src/features/logs/index.ts +5 -0
- package/frontend/src/features/logs/page/AnalyticsLogsPage.tsx +530 -0
- package/frontend/src/features/logs/page/AuditsPage.tsx +192 -0
- package/frontend/src/features/logs/services/log.service.ts +171 -0
- package/frontend/src/features/metadata/hooks/useMetadata.ts +53 -0
- package/frontend/src/features/metadata/index.ts +0 -0
- package/frontend/src/features/metadata/page/MetadataPage.tsx +136 -0
- package/frontend/src/features/metadata/services/metadata.service.ts +17 -0
- package/frontend/src/features/onboard/components/CompletionCard.tsx +41 -0
- package/frontend/src/features/onboard/components/OnboardButton.tsx +84 -0
- package/frontend/src/features/onboard/components/StepContent.tsx +91 -0
- package/frontend/src/features/onboard/components/TestConnectionStep.tsx +53 -0
- package/frontend/src/features/onboard/components/mcp/CursorDeeplinkGenerator.tsx +35 -0
- package/frontend/src/features/onboard/components/mcp/McpInstallation.tsx +144 -0
- package/frontend/src/features/onboard/components/mcp/index.ts +4 -0
- package/frontend/src/features/onboard/components/mcp/mcp-helper.tsx +98 -0
- package/frontend/src/features/onboard/index.ts +3 -0
- package/frontend/src/features/onboard/page/OnBoardPage.tsx +104 -0
- package/frontend/src/features/onboard/types.ts +8 -0
- package/frontend/src/features/secrets/hooks/useSecrets.ts +139 -0
- package/frontend/src/features/secrets/services/secrets.service.ts +57 -0
- package/frontend/src/features/storage/components/BucketEmptyState.tsx +19 -0
- package/frontend/src/features/storage/components/BucketFormDialog.tsx +194 -0
- package/frontend/src/features/storage/components/BucketListSkeleton.tsx +17 -0
- package/frontend/src/features/storage/components/FilePreviewDialog.tsx +287 -0
- package/frontend/src/features/storage/components/StorageDataGrid.tsx +239 -0
- package/frontend/src/features/storage/components/StorageManager.tsx +236 -0
- package/frontend/src/features/storage/components/StorageSidebar.tsx +44 -0
- package/frontend/src/features/storage/components/UploadToast.tsx +46 -0
- package/frontend/src/features/storage/index.ts +3 -0
- package/frontend/src/features/storage/page/StoragePage.tsx +553 -0
- package/frontend/src/features/storage/services/storage.service.ts +144 -0
- package/frontend/src/features/visualizer/components/AuthNode.tsx +107 -0
- package/frontend/src/features/visualizer/components/BucketNode.tsx +34 -0
- package/frontend/src/features/visualizer/components/SchemaVisualizer.tsx +359 -0
- package/frontend/src/features/visualizer/components/TableNode.tsx +152 -0
- package/frontend/src/features/visualizer/components/VisualizerSkeleton.tsx +24 -0
- package/frontend/src/features/visualizer/components/index.ts +5 -0
- package/frontend/src/features/visualizer/page/VisualizerPage.tsx +127 -0
- package/frontend/src/index.css +248 -0
- package/frontend/src/lib/api/client.ts +163 -0
- package/frontend/src/lib/contexts/AuthContext.tsx +157 -0
- package/frontend/src/lib/contexts/OnboardStepContext.tsx +68 -0
- package/frontend/src/lib/contexts/SocketContext.tsx +303 -0
- package/frontend/src/lib/contexts/ThemeContext.tsx +125 -0
- package/frontend/src/lib/hooks/useAuth.ts +4 -0
- package/frontend/src/lib/hooks/useConfirm.ts +55 -0
- package/frontend/src/lib/hooks/useInterval.ts +27 -0
- package/frontend/src/lib/hooks/useMediaQuery.ts +59 -0
- package/frontend/src/lib/hooks/useOnboardingCompletion.ts +29 -0
- package/frontend/src/lib/hooks/usePagination.ts +27 -0
- package/frontend/src/lib/hooks/useTimeout.ts +27 -0
- package/frontend/src/lib/hooks/useToast.tsx +229 -0
- package/frontend/src/lib/utils/constants.ts +38 -0
- package/frontend/src/lib/utils/utils.ts +165 -0
- package/frontend/src/lib/utils/validation-schemas.ts +126 -0
- package/frontend/src/main.tsx +16 -0
- package/frontend/src/rdg.css +194 -0
- package/frontend/src/vite-env.d.ts +12 -0
- package/frontend/tailwind.config.js +97 -0
- package/frontend/tsconfig.json +26 -0
- package/frontend/tsconfig.node.json +10 -0
- package/frontend/vite.config.ts +37 -0
- package/frontend/vitest.config.ts +36 -0
- package/functions/deno.json +25 -0
- package/functions/server.ts +290 -0
- package/functions/worker-template.js +126 -0
- package/openapi/ai.yaml +689 -0
- package/openapi/auth.yaml +563 -0
- package/openapi/functions.yaml +476 -0
- package/openapi/health.yaml +30 -0
- package/openapi/logs.yaml +224 -0
- package/openapi/metadata.yaml +178 -0
- package/openapi/records.yaml +382 -0
- package/openapi/secrets.yaml +371 -0
- package/openapi/storage.yaml +876 -0
- package/openapi/tables.yaml +464 -0
- package/package.json +88 -0
- package/shared-schemas/package.json +31 -0
- package/shared-schemas/src/ai-api.schema.ts +167 -0
- package/shared-schemas/src/ai.schema.ts +54 -0
- package/shared-schemas/src/auth-api.schema.ts +193 -0
- package/shared-schemas/src/auth.schema.ts +94 -0
- package/shared-schemas/src/database-api.schema.ts +259 -0
- package/shared-schemas/src/database.schema.ts +69 -0
- package/shared-schemas/src/functions-api.schema.ts +25 -0
- package/shared-schemas/src/functions.schema.ts +16 -0
- package/shared-schemas/src/index.ts +13 -0
- package/shared-schemas/src/logs-api.schema.ts +49 -0
- package/shared-schemas/src/logs.schema.ts +14 -0
- package/shared-schemas/src/metadata.schema.ts +56 -0
- package/shared-schemas/src/storage-api.schema.ts +65 -0
- package/shared-schemas/src/storage.schema.ts +19 -0
- package/shared-schemas/tsconfig.json +21 -0
- package/tsconfig.json +8 -0
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { useState, useEffect } from 'react';
|
|
2
|
+
import { RefreshCw, Search, FileText, Trash2 } from 'lucide-react';
|
|
3
|
+
import { Button } from '@/components/radix/Button';
|
|
4
|
+
import { Input } from '@/components/radix/Input';
|
|
5
|
+
import { Alert, AlertDescription } from '@/components/radix/Alert';
|
|
6
|
+
import { LogsTable } from '@/features/logs/components/LogsTable';
|
|
7
|
+
import { ConfirmDialog } from '@/components/ConfirmDialog';
|
|
8
|
+
import { useConfirm } from '@/lib/hooks/useConfirm';
|
|
9
|
+
import {
|
|
10
|
+
Tooltip,
|
|
11
|
+
TooltipContent,
|
|
12
|
+
TooltipProvider,
|
|
13
|
+
TooltipTrigger,
|
|
14
|
+
} from '@/components/radix/Tooltip';
|
|
15
|
+
import { useAuditLogs, useClearAuditLogs } from '@/features/logs/hooks/useAuditLogs';
|
|
16
|
+
import type { GetAuditLogsRequest } from '@insforge/shared-schemas';
|
|
17
|
+
|
|
18
|
+
export default function AuditsPage() {
|
|
19
|
+
const [searchQuery, setSearchQuery] = useState('');
|
|
20
|
+
const [currentPage, setCurrentPage] = useState(1);
|
|
21
|
+
const [filters, setFilters] = useState<Partial<GetAuditLogsRequest>>({});
|
|
22
|
+
const pageSize = 50;
|
|
23
|
+
const { confirm, confirmDialogProps } = useConfirm();
|
|
24
|
+
|
|
25
|
+
// Calculate offset based on current page
|
|
26
|
+
const offset = (currentPage - 1) * pageSize;
|
|
27
|
+
|
|
28
|
+
// Fetch logs with pagination and filters
|
|
29
|
+
const {
|
|
30
|
+
data: logsResponse,
|
|
31
|
+
isLoading,
|
|
32
|
+
error,
|
|
33
|
+
refetch,
|
|
34
|
+
} = useAuditLogs({
|
|
35
|
+
limit: pageSize,
|
|
36
|
+
offset,
|
|
37
|
+
...filters,
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
const clearMutation = useClearAuditLogs();
|
|
41
|
+
|
|
42
|
+
const handleRefresh = () => {
|
|
43
|
+
void refetch();
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const handleClearLogs = () => {
|
|
47
|
+
void confirm({
|
|
48
|
+
title: 'Clear Audit Logs',
|
|
49
|
+
description:
|
|
50
|
+
'Are you sure you want to clear old audit logs? This will keep the last 90 days of logs.',
|
|
51
|
+
confirmText: 'Clear Logs',
|
|
52
|
+
cancelText: 'Cancel',
|
|
53
|
+
}).then((confirmed) => {
|
|
54
|
+
if (confirmed) {
|
|
55
|
+
clearMutation.mutate(90);
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
// Apply search filter
|
|
61
|
+
useEffect(() => {
|
|
62
|
+
setCurrentPage(1);
|
|
63
|
+
if (searchQuery) {
|
|
64
|
+
// Search can filter by actor, action, or module
|
|
65
|
+
setFilters({
|
|
66
|
+
actor: searchQuery,
|
|
67
|
+
});
|
|
68
|
+
} else {
|
|
69
|
+
setFilters({});
|
|
70
|
+
}
|
|
71
|
+
}, [searchQuery]);
|
|
72
|
+
|
|
73
|
+
// Extract data from response
|
|
74
|
+
const logsData = logsResponse?.data || [];
|
|
75
|
+
const totalRecords = logsResponse?.pagination?.total || 0;
|
|
76
|
+
return (
|
|
77
|
+
<div className="flex h-full bg-bg-gray dark:bg-neutral-800">
|
|
78
|
+
<div className="flex-1 min-w-0 flex flex-col overflow-hidden">
|
|
79
|
+
{/* Sticky Header Section */}
|
|
80
|
+
<div className="sticky top-0 z-30 bg-bg-gray dark:bg-neutral-800">
|
|
81
|
+
<div className="px-8 pt-6 pb-4">
|
|
82
|
+
{/* Page Header */}
|
|
83
|
+
<div className="flex items-center justify-between">
|
|
84
|
+
<div className="flex items-center">
|
|
85
|
+
<nav className="flex items-center text-[22px] font-semibold">
|
|
86
|
+
<span className="text-gray-900 dark:text-white">Audit Logs</span>
|
|
87
|
+
</nav>
|
|
88
|
+
|
|
89
|
+
{/* Separator */}
|
|
90
|
+
<div className="mx-4 h-6 w-px bg-gray-200 dark:bg-neutral-700" />
|
|
91
|
+
|
|
92
|
+
{/* Action buttons group */}
|
|
93
|
+
<div className="flex items-center gap-1">
|
|
94
|
+
<TooltipProvider>
|
|
95
|
+
<Tooltip>
|
|
96
|
+
<TooltipTrigger asChild>
|
|
97
|
+
<Button
|
|
98
|
+
variant="ghost"
|
|
99
|
+
size="icon"
|
|
100
|
+
className="h-9 w-9 hover:bg-gray-100 dark:hover:bg-neutral-700"
|
|
101
|
+
onClick={handleRefresh}
|
|
102
|
+
disabled={isLoading}
|
|
103
|
+
>
|
|
104
|
+
<RefreshCw
|
|
105
|
+
className={`h-4 w-4 text-gray-600 dark:text-neutral-400 ${isLoading ? 'animate-spin' : ''}`}
|
|
106
|
+
/>
|
|
107
|
+
</Button>
|
|
108
|
+
</TooltipTrigger>
|
|
109
|
+
<TooltipContent side="bottom" align="center">
|
|
110
|
+
<p>Refresh</p>
|
|
111
|
+
</TooltipContent>
|
|
112
|
+
</Tooltip>
|
|
113
|
+
</TooltipProvider>
|
|
114
|
+
|
|
115
|
+
<TooltipProvider>
|
|
116
|
+
<Tooltip>
|
|
117
|
+
<TooltipTrigger asChild>
|
|
118
|
+
<Button
|
|
119
|
+
variant="ghost"
|
|
120
|
+
size="icon"
|
|
121
|
+
className="h-9 w-9 hover:bg-gray-100 dark:hover:bg-neutral-700"
|
|
122
|
+
onClick={handleClearLogs}
|
|
123
|
+
disabled={clearMutation.isPending || logsData.length === 0}
|
|
124
|
+
>
|
|
125
|
+
<Trash2 className="h-4 w-4 text-gray-600 dark:text-neutral-400" />
|
|
126
|
+
</Button>
|
|
127
|
+
</TooltipTrigger>
|
|
128
|
+
<TooltipContent side="bottom" align="center">
|
|
129
|
+
<p>Clear old logs</p>
|
|
130
|
+
</TooltipContent>
|
|
131
|
+
</Tooltip>
|
|
132
|
+
</TooltipProvider>
|
|
133
|
+
</div>
|
|
134
|
+
</div>
|
|
135
|
+
</div>
|
|
136
|
+
|
|
137
|
+
{/* Search Bar */}
|
|
138
|
+
<div className="relative mt-6">
|
|
139
|
+
<Search className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-500 dark:text-neutral-400" />
|
|
140
|
+
<Input
|
|
141
|
+
placeholder="Search logs..."
|
|
142
|
+
value={searchQuery}
|
|
143
|
+
onChange={(e) => setSearchQuery(e.target.value)}
|
|
144
|
+
className="pl-9 h-11 bg-white dark:bg-neutral-900 border-gray-200 dark:border-neutral-700 rounded-full text-sm"
|
|
145
|
+
/>
|
|
146
|
+
</div>
|
|
147
|
+
</div>
|
|
148
|
+
</div>
|
|
149
|
+
|
|
150
|
+
{/* Content */}
|
|
151
|
+
<div className="flex-1 flex flex-col overflow-hidden">
|
|
152
|
+
{error && (
|
|
153
|
+
<Alert variant="destructive" className="mb-4 mx-8 mt-4">
|
|
154
|
+
<AlertDescription>{String(error)}</AlertDescription>
|
|
155
|
+
</Alert>
|
|
156
|
+
)}
|
|
157
|
+
|
|
158
|
+
{logsData.length === 0 && !isLoading ? (
|
|
159
|
+
<div className="flex-1 flex items-center justify-center">
|
|
160
|
+
<div className="text-center">
|
|
161
|
+
<FileText className="mx-auto h-12 w-12 text-gray-400 dark:text-neutral-600 mb-4" />
|
|
162
|
+
<h3 className="text-lg font-medium text-gray-900 dark:text-white mb-2">
|
|
163
|
+
No Audit Logs Available
|
|
164
|
+
</h3>
|
|
165
|
+
<p className="text-sm text-gray-500 dark:text-neutral-400">
|
|
166
|
+
{searchQuery
|
|
167
|
+
? 'No logs found matching your search criteria'
|
|
168
|
+
: 'Audit logs will appear here once operations are performed'}
|
|
169
|
+
</p>
|
|
170
|
+
</div>
|
|
171
|
+
</div>
|
|
172
|
+
) : (
|
|
173
|
+
<LogsTable
|
|
174
|
+
logs={logsData}
|
|
175
|
+
loading={isLoading}
|
|
176
|
+
searchQuery={searchQuery}
|
|
177
|
+
onRefresh={() => void refetch()}
|
|
178
|
+
onConfirm={confirm}
|
|
179
|
+
currentPage={currentPage}
|
|
180
|
+
totalRecords={totalRecords}
|
|
181
|
+
pageSize={pageSize}
|
|
182
|
+
onPageChange={setCurrentPage}
|
|
183
|
+
/>
|
|
184
|
+
)}
|
|
185
|
+
</div>
|
|
186
|
+
</div>
|
|
187
|
+
|
|
188
|
+
{/* Confirm Dialog */}
|
|
189
|
+
<ConfirmDialog {...confirmDialogProps} />
|
|
190
|
+
</div>
|
|
191
|
+
);
|
|
192
|
+
}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { apiClient } from '@/lib/api/client';
|
|
2
|
+
import {
|
|
3
|
+
GetAuditLogsResponse,
|
|
4
|
+
ClearAuditLogsResponse,
|
|
5
|
+
GetAuditLogsRequest,
|
|
6
|
+
GetAuditLogStatsResponse,
|
|
7
|
+
} from '@insforge/shared-schemas';
|
|
8
|
+
|
|
9
|
+
export class LogsService {
|
|
10
|
+
async getAuditLogs({
|
|
11
|
+
limit = 100,
|
|
12
|
+
offset = 0,
|
|
13
|
+
...filters
|
|
14
|
+
}: GetAuditLogsRequest): Promise<GetAuditLogsResponse> {
|
|
15
|
+
const params = new URLSearchParams({
|
|
16
|
+
limit: limit.toString(),
|
|
17
|
+
offset: offset.toString(),
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
if (filters?.actor) {
|
|
21
|
+
params.append('actor', filters.actor);
|
|
22
|
+
}
|
|
23
|
+
if (filters?.action) {
|
|
24
|
+
params.append('action', filters.action);
|
|
25
|
+
}
|
|
26
|
+
if (filters?.module) {
|
|
27
|
+
params.append('module', filters.module);
|
|
28
|
+
}
|
|
29
|
+
if (filters?.startDate) {
|
|
30
|
+
params.append('start_date', filters.startDate);
|
|
31
|
+
}
|
|
32
|
+
if (filters?.endDate) {
|
|
33
|
+
params.append('end_date', filters.endDate);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return apiClient.request(`/logs/audits?${params.toString()}`, {
|
|
37
|
+
headers: apiClient.withAccessToken(),
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
async getAuditLogStats(days = 7): Promise<GetAuditLogStatsResponse> {
|
|
42
|
+
const params = new URLSearchParams({
|
|
43
|
+
days: days.toString(),
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
return apiClient.request(`/logs/audits/stats?${params.toString()}`, {
|
|
47
|
+
headers: apiClient.withAccessToken(),
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async clearAuditLogs(daysToKeep = 90): Promise<ClearAuditLogsResponse> {
|
|
52
|
+
const params = new URLSearchParams({
|
|
53
|
+
days_to_keep: daysToKeep.toString(),
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
return apiClient.request(`/logs/audits?${params.toString()}`, {
|
|
57
|
+
method: 'DELETE',
|
|
58
|
+
headers: apiClient.withAccessToken(),
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Analytics types
|
|
64
|
+
export interface LogSource {
|
|
65
|
+
id: string;
|
|
66
|
+
name: string;
|
|
67
|
+
token: string;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export interface AnalyticsLogBody {
|
|
71
|
+
status_code?: number;
|
|
72
|
+
duration?: string;
|
|
73
|
+
size?: number;
|
|
74
|
+
log_type?: string;
|
|
75
|
+
ip?: string;
|
|
76
|
+
user_agent?: string;
|
|
77
|
+
path?: string;
|
|
78
|
+
error?: string;
|
|
79
|
+
stack?: string;
|
|
80
|
+
[key: string]: unknown;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export interface AnalyticsLogRecord {
|
|
84
|
+
id: string;
|
|
85
|
+
event_message: string;
|
|
86
|
+
timestamp: string;
|
|
87
|
+
body: AnalyticsLogBody;
|
|
88
|
+
source?: string; // Added for search results
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export interface AnalyticsLogResponse {
|
|
92
|
+
logs: AnalyticsLogRecord[];
|
|
93
|
+
total: number;
|
|
94
|
+
tableName: string;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export interface LogSourceStats {
|
|
98
|
+
source: string;
|
|
99
|
+
count: number;
|
|
100
|
+
lastActivity: string;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
class AnalyticsService {
|
|
104
|
+
// Get all available log sources
|
|
105
|
+
async getLogSources(): Promise<LogSource[]> {
|
|
106
|
+
return apiClient.request('/logs/analytics/sources');
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Get statistics for all log sources
|
|
110
|
+
async getLogSourceStats(): Promise<LogSourceStats[]> {
|
|
111
|
+
return apiClient.request('/logs/analytics/stats');
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Get logs from a specific source with timestamp-based pagination
|
|
115
|
+
async getLogsBySource(
|
|
116
|
+
sourceName: string,
|
|
117
|
+
limit = 100,
|
|
118
|
+
beforeTimestamp?: string
|
|
119
|
+
): Promise<AnalyticsLogResponse> {
|
|
120
|
+
const params = new URLSearchParams({
|
|
121
|
+
limit: limit.toString(),
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
if (beforeTimestamp) {
|
|
125
|
+
params.append('before_timestamp', beforeTimestamp);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return apiClient.request(`/logs/analytics/${sourceName}?${params.toString()}`);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Search across all logs or specific source
|
|
132
|
+
async searchLogs(
|
|
133
|
+
query: string,
|
|
134
|
+
sourceName?: string,
|
|
135
|
+
limit = 100,
|
|
136
|
+
offset = 0
|
|
137
|
+
): Promise<{
|
|
138
|
+
records: AnalyticsLogRecord[];
|
|
139
|
+
total: number;
|
|
140
|
+
}> {
|
|
141
|
+
const params = new URLSearchParams({
|
|
142
|
+
q: query,
|
|
143
|
+
limit: limit.toString(),
|
|
144
|
+
offset: offset.toString(),
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
if (sourceName) {
|
|
148
|
+
params.append('source', sourceName);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const response = await apiClient.request(`/logs/analytics/search?${params.toString()}`, {
|
|
152
|
+
returnFullResponse: true,
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
// Handle response - search returns {logs: [], total: number}
|
|
156
|
+
if (response.logs && Array.isArray(response.logs)) {
|
|
157
|
+
return {
|
|
158
|
+
records: response.logs,
|
|
159
|
+
total: response.total || response.logs.length,
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
return {
|
|
164
|
+
records: [],
|
|
165
|
+
total: 0,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export const logsService = new LogsService();
|
|
171
|
+
export const analyticsService = new AnalyticsService();
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { useQuery } from '@tanstack/react-query';
|
|
2
|
+
import { metadataService } from '../services/metadata.service';
|
|
3
|
+
|
|
4
|
+
interface UseMetadataOptions {
|
|
5
|
+
enabled?: boolean;
|
|
6
|
+
staleTime?: number;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function useMetadata(options?: UseMetadataOptions) {
|
|
10
|
+
const {
|
|
11
|
+
data: metadata,
|
|
12
|
+
isLoading,
|
|
13
|
+
error,
|
|
14
|
+
refetch,
|
|
15
|
+
} = useQuery({
|
|
16
|
+
queryKey: ['metadata', 'full'],
|
|
17
|
+
queryFn: () => metadataService.getFullMetadata(),
|
|
18
|
+
staleTime: options?.staleTime ?? 5 * 60 * 1000, // Cache for 5 minutes by default
|
|
19
|
+
enabled: options?.enabled ?? true,
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
return {
|
|
23
|
+
metadata,
|
|
24
|
+
auth: metadata?.auth,
|
|
25
|
+
tables: Object.keys(metadata?.database.tables ?? {}),
|
|
26
|
+
storage: metadata?.storage,
|
|
27
|
+
version: metadata?.version || 'Unknown',
|
|
28
|
+
isLoading,
|
|
29
|
+
error,
|
|
30
|
+
refetch,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function useApiKey(options?: UseMetadataOptions) {
|
|
35
|
+
const {
|
|
36
|
+
data: apiKey,
|
|
37
|
+
isLoading,
|
|
38
|
+
error,
|
|
39
|
+
refetch,
|
|
40
|
+
} = useQuery({
|
|
41
|
+
queryKey: ['metadata', 'apiKey'],
|
|
42
|
+
queryFn: () => metadataService.fetchApiKey(),
|
|
43
|
+
staleTime: options?.staleTime ?? 10 * 60 * 1000, // Cache for 10 minutes by default
|
|
44
|
+
enabled: options?.enabled ?? true,
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
return {
|
|
48
|
+
apiKey,
|
|
49
|
+
isLoading,
|
|
50
|
+
error,
|
|
51
|
+
refetch,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { RefreshCw, Info } from 'lucide-react';
|
|
2
|
+
import { useMetadata } from '../hooks/useMetadata';
|
|
3
|
+
import { Skeleton } from '@/components/radix/Skeleton';
|
|
4
|
+
import { Button } from '@/components/radix/Button';
|
|
5
|
+
import { Alert, AlertDescription } from '@/components/radix/Alert';
|
|
6
|
+
import {
|
|
7
|
+
Tooltip,
|
|
8
|
+
TooltipContent,
|
|
9
|
+
TooltipProvider,
|
|
10
|
+
TooltipTrigger,
|
|
11
|
+
} from '@/components/radix/Tooltip';
|
|
12
|
+
import { JsonHighlight } from '@/components';
|
|
13
|
+
|
|
14
|
+
export default function MetadataPage() {
|
|
15
|
+
const { metadata, isLoading, error, refetch: refetchMetadata } = useMetadata();
|
|
16
|
+
|
|
17
|
+
const handleRefresh = () => {
|
|
18
|
+
void refetchMetadata();
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
if (error) {
|
|
22
|
+
return (
|
|
23
|
+
<main className="min-h-screen bg-bg-gray">
|
|
24
|
+
<div className="px-8 pt-6 pb-4">
|
|
25
|
+
<div className="flex items-center">
|
|
26
|
+
<nav className="flex items-center text-[22px] font-semibold">
|
|
27
|
+
<span className="text-gray-900 dark:text-white">Metadata</span>
|
|
28
|
+
</nav>
|
|
29
|
+
</div>
|
|
30
|
+
</div>
|
|
31
|
+
<div className="px-8 py-8">
|
|
32
|
+
<Alert variant="destructive">
|
|
33
|
+
<AlertDescription>
|
|
34
|
+
Failed to load metadata. Please try refreshing the page.
|
|
35
|
+
</AlertDescription>
|
|
36
|
+
</Alert>
|
|
37
|
+
</div>
|
|
38
|
+
</main>
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (isLoading) {
|
|
43
|
+
return <MetadataSkeleton />;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<main className="min-h-screen bg-bg-gray dark:bg-neutral-800">
|
|
48
|
+
{/* Header */}
|
|
49
|
+
<div className="sticky top-0 z-30 bg-bg-gray border-b border-gray-200 dark:border-neutral-700 dark:bg-neutral-800">
|
|
50
|
+
<div className="px-8 pt-6 pb-4">
|
|
51
|
+
<div className="flex items-center">
|
|
52
|
+
<nav className="flex items-center text-[22px] font-semibold">
|
|
53
|
+
<span className="text-gray-900 dark:text-white">Metadata</span>
|
|
54
|
+
</nav>
|
|
55
|
+
|
|
56
|
+
{/* Separator */}
|
|
57
|
+
<div className="mx-4 h-6 w-px bg-gray-200 dark:bg-neutral-500" />
|
|
58
|
+
|
|
59
|
+
{/* Action buttons group */}
|
|
60
|
+
<div className="flex items-center gap-1">
|
|
61
|
+
<TooltipProvider>
|
|
62
|
+
<Tooltip>
|
|
63
|
+
<TooltipTrigger asChild>
|
|
64
|
+
<Button variant="ghost" size="icon" className="h-9 w-9" onClick={handleRefresh}>
|
|
65
|
+
<RefreshCw className="h-4 w-4 text-zinc-900 dark:text-white" />
|
|
66
|
+
</Button>
|
|
67
|
+
</TooltipTrigger>
|
|
68
|
+
<TooltipContent>
|
|
69
|
+
<p>Refresh Metadata</p>
|
|
70
|
+
</TooltipContent>
|
|
71
|
+
</Tooltip>
|
|
72
|
+
</TooltipProvider>
|
|
73
|
+
</div>
|
|
74
|
+
</div>
|
|
75
|
+
</div>
|
|
76
|
+
</div>
|
|
77
|
+
|
|
78
|
+
<div className="px-8 py-8">
|
|
79
|
+
{/* Metadata Section */}
|
|
80
|
+
<div className="space-y-6">
|
|
81
|
+
<div>
|
|
82
|
+
<h2 className="text-2xl font-semibold text-gray-900 dark:text-white mb-2">
|
|
83
|
+
System Metadata
|
|
84
|
+
</h2>
|
|
85
|
+
<p className="text-gray-600 dark:text-zinc-400">
|
|
86
|
+
Complete metadata information for the InsForge system
|
|
87
|
+
</p>
|
|
88
|
+
</div>
|
|
89
|
+
|
|
90
|
+
<div className="bg-white dark:bg-neutral-800 rounded-lg border border-gray-200 dark:border-neutral-700 overflow-hidden">
|
|
91
|
+
<div className="flex items-center justify-between px-6 pt-4 bg-white dark:bg-neutral-800">
|
|
92
|
+
<div className="flex items-center gap-2">
|
|
93
|
+
<Info className="h-5 w-5 text-gray-700 dark:text-white" />
|
|
94
|
+
<span className="font-medium text-gray-900 dark:text-white">Raw JSON Data</span>
|
|
95
|
+
</div>
|
|
96
|
+
</div>
|
|
97
|
+
|
|
98
|
+
<div className="px-4 pb-4 pt-4">
|
|
99
|
+
{!metadata && (
|
|
100
|
+
<Alert className="border-yellow-200 bg-yellow-50 mb-4">
|
|
101
|
+
<AlertDescription className="text-yellow-800">
|
|
102
|
+
No metadata available. Please ensure the backend is running and you're
|
|
103
|
+
logged in as an admin.
|
|
104
|
+
</AlertDescription>
|
|
105
|
+
</Alert>
|
|
106
|
+
)}
|
|
107
|
+
|
|
108
|
+
{metadata && <JsonHighlight json={JSON.stringify(metadata, null, 2)} />}
|
|
109
|
+
</div>
|
|
110
|
+
</div>
|
|
111
|
+
</div>
|
|
112
|
+
</div>
|
|
113
|
+
</main>
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function MetadataSkeleton() {
|
|
118
|
+
return (
|
|
119
|
+
<main className="min-h-screen bg-bg-gray">
|
|
120
|
+
<div className="px-8 pt-6 pb-4">
|
|
121
|
+
<div className="flex items-center">
|
|
122
|
+
<nav className="flex items-center text-[22px] font-semibold">
|
|
123
|
+
<span className="text-gray-900">Metadata</span>
|
|
124
|
+
</nav>
|
|
125
|
+
</div>
|
|
126
|
+
</div>
|
|
127
|
+
<div className="px-8 py-8">
|
|
128
|
+
<div className="space-y-6">
|
|
129
|
+
<Skeleton className="h-8 w-48" />
|
|
130
|
+
<Skeleton className="h-4 w-96" />
|
|
131
|
+
<Skeleton className="h-100" />
|
|
132
|
+
</div>
|
|
133
|
+
</div>
|
|
134
|
+
</main>
|
|
135
|
+
);
|
|
136
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { apiClient } from '@/lib/api/client';
|
|
2
|
+
import { AppMetadataSchema } from '@insforge/shared-schemas';
|
|
3
|
+
|
|
4
|
+
export class MetadataService {
|
|
5
|
+
async fetchApiKey() {
|
|
6
|
+
const data = await apiClient.request('/metadata/api-key');
|
|
7
|
+
return data.apiKey;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
async getFullMetadata(): Promise<AppMetadataSchema> {
|
|
11
|
+
return apiClient.request('/metadata', {
|
|
12
|
+
headers: apiClient.withAccessToken(),
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const metadataService = new MetadataService();
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Button } from '@/components/radix/Button';
|
|
2
|
+
import CheckedIcon from '@/assets/icons/checked.svg';
|
|
3
|
+
import { useNavigate } from 'react-router-dom';
|
|
4
|
+
import { useOnboardingCompletion } from '@/lib/hooks/useOnboardingCompletion';
|
|
5
|
+
import { useEffect } from 'react';
|
|
6
|
+
|
|
7
|
+
export function CompletionCard() {
|
|
8
|
+
const navigate = useNavigate();
|
|
9
|
+
const { markAsCompleted } = useOnboardingCompletion();
|
|
10
|
+
|
|
11
|
+
// Mark as completed when this component is mounted
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
markAsCompleted();
|
|
14
|
+
}, [markAsCompleted]);
|
|
15
|
+
|
|
16
|
+
const handleNavigate = async () => {
|
|
17
|
+
await navigate('/dashboard');
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<div className="border border-transparent dark:border-neutral-700 rounded-xl bg-white dark:bg-neutral-800 py-8 px-6">
|
|
22
|
+
<div className="flex flex-col items-center justify-center gap-8">
|
|
23
|
+
<div className="flex flex-col items-center justify-center gap-4 text-center">
|
|
24
|
+
<img src={CheckedIcon} alt="Checked" className="w-10 h-10" />
|
|
25
|
+
<p className="text-lg font-semibold text-black dark:text-white">You are all set!</p>
|
|
26
|
+
<p className="text-zinc-500 dark:text-zinc-400 text-sm">
|
|
27
|
+
Your AI agent is now full-stack — powered by <b>InsForge</b>.
|
|
28
|
+
<br /> Let's build something <b>real</b>.
|
|
29
|
+
</p>
|
|
30
|
+
</div>
|
|
31
|
+
<Button
|
|
32
|
+
variant="default"
|
|
33
|
+
className="px-4 py-2 h-10 text-sm font-medium dark:bg-emerald-300 dark:text-black dark:hover:bg-emerald-200"
|
|
34
|
+
onClick={() => void handleNavigate()}
|
|
35
|
+
>
|
|
36
|
+
Go to Dashboard
|
|
37
|
+
</Button>
|
|
38
|
+
</div>
|
|
39
|
+
</div>
|
|
40
|
+
);
|
|
41
|
+
}
|