insforge 0.3.3 → 1.2.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +20 -0
- package/.cursor/rules/cursor-rules.mdc +94 -0
- package/.dockerignore +3 -0
- package/.env.example +33 -4
- package/.github/ISSUE_TEMPLATE/bug_report.yml +13 -60
- package/.github/ISSUE_TEMPLATE/config.yml +2 -2
- package/.github/ISSUE_TEMPLATE/feature_request.yml +10 -63
- package/.github/PULL_REQUEST_TEMPLATE.md +7 -0
- package/.github/workflows/build-image.yml +2 -1
- package/.github/workflows/e2e.yml +63 -0
- package/CHANGELOG.md +41 -0
- package/CLAUDE_PLUGIN.md +104 -0
- package/CODE_OF_CONDUCT.md +128 -0
- package/CONTRIBUTING.md +1 -1
- package/Dockerfile +4 -1
- package/README.md +66 -18
- package/assets/mcpInstallv2.png +0 -0
- package/assets/sampleResponse.png +0 -0
- package/auth/index.html +13 -0
- package/auth/package.json +28 -0
- package/auth/public/favicon.ico +0 -0
- package/auth/src/App.tsx +33 -0
- package/auth/src/components/ErrorCard.tsx +37 -0
- package/auth/src/components/Layout.tsx +13 -0
- package/auth/src/index.css +19 -0
- package/auth/src/lib/broadcastService.ts +115 -0
- package/auth/src/lib/utils.ts +11 -0
- package/auth/src/main.tsx +22 -0
- package/auth/src/pages/ForgotPasswordPage.tsx +11 -0
- package/auth/src/pages/ResetPasswordPage.tsx +11 -0
- package/auth/src/pages/SignInPage.tsx +57 -0
- package/auth/src/pages/SignUpPage.tsx +57 -0
- package/auth/src/pages/VerifyEmailPage.tsx +20 -0
- package/auth/src/vite-env.d.ts +10 -0
- package/auth/tsconfig.json +32 -0
- package/auth/tsconfig.node.json +11 -0
- package/auth/vite.config.ts +25 -0
- package/backend/package.json +9 -9
- package/backend/src/api/{middleware → middlewares}/auth.ts +8 -9
- package/backend/src/api/middlewares/rate-limiters.ts +127 -0
- package/backend/src/api/routes/{ai.ts → ai/index.routes.ts} +20 -24
- package/backend/src/api/routes/auth/index.routes.ts +570 -0
- package/backend/src/api/routes/auth/oauth.routes.ts +448 -0
- package/backend/src/api/routes/{database.advance.ts → database/advance.routes.ts} +107 -65
- package/backend/src/api/routes/database/index.routes.ts +13 -0
- package/backend/src/api/routes/{database.records.ts → database/records.routes.ts} +22 -8
- package/backend/src/api/routes/{database.tables.ts → database/tables.routes.ts} +20 -23
- package/backend/src/api/routes/docs/index.routes.ts +76 -0
- package/backend/src/api/routes/functions/index.routes.ts +188 -0
- package/backend/src/api/routes/{logs.ts → logs/index.routes.ts} +25 -30
- package/backend/src/api/routes/{metadata.ts → metadata/index.routes.ts} +21 -31
- package/backend/src/api/routes/{secrets.ts → secrets/index.routes.ts} +27 -22
- package/backend/src/api/routes/{storage.ts → storage/index.routes.ts} +34 -53
- package/backend/src/api/routes/usage/index.routes.ts +89 -0
- package/backend/src/infra/config/app.config.ts +51 -0
- package/backend/src/{core/database/manager.ts → infra/database/database.manager.ts} +76 -85
- package/backend/src/infra/database/migrations/013_create-auth-schema-functions.sql +44 -0
- package/backend/src/infra/database/migrations/014_add-updated-at-trigger-user-table.sql +8 -0
- package/backend/src/infra/database/migrations/015_create-auth-config-and-email-otp-tables.sql +60 -0
- package/backend/src/infra/database/migrations/016_update-auth-config-and-email-otp.sql +24 -0
- package/backend/src/{core/secrets/encryption.ts → infra/security/encryption.manager.ts} +3 -2
- package/backend/src/infra/security/token.manager.ts +125 -0
- package/backend/src/{core/socket/socket.ts → infra/socket/socket.manager.ts} +15 -15
- package/backend/src/providers/ai/openrouter.provider.ts +377 -0
- package/backend/src/providers/email/base.provider.ts +41 -0
- package/backend/src/providers/email/cloud.provider.ts +187 -0
- package/backend/src/{core/logs/providers → providers/logs}/base.provider.ts +11 -11
- package/backend/src/{core/logs/providers → providers/logs}/cloudwatch.provider.ts +61 -38
- package/backend/src/providers/logs/local.provider.ts +185 -0
- package/backend/src/providers/oauth/base.provider.ts +29 -0
- package/backend/src/providers/oauth/discord.provider.ts +195 -0
- package/backend/src/providers/oauth/facebook.provider.ts +194 -0
- package/backend/src/providers/oauth/github.provider.ts +208 -0
- package/backend/src/providers/oauth/google.provider.ts +249 -0
- package/backend/src/providers/oauth/index.ts +7 -0
- package/backend/src/providers/oauth/linkedin.provider.ts +240 -0
- package/backend/src/providers/oauth/microsoft.provider.ts +169 -0
- package/backend/src/providers/oauth/x.provider.ts +202 -0
- package/backend/src/providers/storage/base.provider.ts +29 -0
- package/backend/src/providers/storage/local.provider.ts +103 -0
- package/backend/src/providers/storage/s3.provider.ts +313 -0
- package/backend/src/server.ts +70 -74
- package/backend/src/{core/ai/config.ts → services/ai/ai-config.service.ts} +19 -24
- package/backend/src/services/ai/ai-model.service.ts +60 -0
- package/backend/src/{core/ai/usage.ts → services/ai/ai-usage.service.ts} +28 -35
- package/backend/src/{core/ai/chat.ts → services/ai/chat-completion.service.ts} +37 -24
- package/backend/src/services/ai/helpers.ts +64 -0
- package/backend/src/{core/ai/image.ts → services/ai/image-generation.service.ts} +17 -19
- package/backend/src/services/ai/index.ts +13 -0
- package/backend/src/services/auth/auth-config.service.ts +250 -0
- package/backend/src/services/auth/auth-otp.service.ts +424 -0
- package/backend/src/services/auth/auth.service.ts +1136 -0
- package/backend/src/services/auth/index.ts +4 -0
- package/backend/src/{core/auth/oauth.ts → services/auth/oauth-config.service.ts} +106 -52
- package/backend/src/{core/database/advance.ts → services/database/database-advance.service.ts} +97 -131
- package/backend/src/services/database/database-table.service.ts +811 -0
- package/backend/src/services/email/email.service.ts +75 -0
- package/backend/src/{core/functions/functions.ts → services/functions/function.service.ts} +95 -88
- package/backend/src/{core/logs/audit.ts → services/logs/audit.service.ts} +92 -75
- package/backend/src/services/logs/log.service.ts +73 -0
- package/backend/src/{core/secrets/secrets.ts → services/secrets/secret.service.ts} +48 -66
- package/backend/src/services/storage/storage.service.ts +617 -0
- package/backend/src/services/usage/usage.service.ts +149 -0
- package/backend/src/types/auth.ts +66 -2
- package/backend/src/types/email.ts +8 -0
- package/backend/src/types/error-constants.ts +4 -0
- package/backend/src/types/logs.ts +0 -29
- package/backend/src/{core/socket/types.ts → types/socket.ts} +5 -6
- package/backend/src/utils/environment.ts +9 -3
- package/backend/src/utils/logger.ts +20 -2
- package/backend/src/utils/seed.ts +150 -57
- package/backend/src/utils/sql-parser.ts +1 -1
- package/backend/src/utils/utils.ts +114 -0
- package/backend/src/utils/validations.ts +40 -4
- package/backend/tests/local/test-ai-config.sh +129 -0
- package/backend/tests/local/test-ai-usage.sh +80 -0
- package/backend/tests/local/test-auth-router.sh +1 -1
- package/backend/tests/local/test-e2e.sh +1 -1
- package/backend/tests/local/test-functions.sh +123 -0
- package/backend/tests/local/test-logs.sh +132 -0
- package/backend/tests/local/test-public-bucket.sh +3 -3
- package/backend/tests/local/test-secrets.sh +14 -12
- package/backend/tests/local/test-traditional-rest.sh +2 -2
- package/backend/tests/manual/test-rawsql-modes.sh +244 -0
- package/backend/tests/test-config.sh +37 -1
- package/backend/tests/unit/cloud-token.test.ts +48 -0
- package/backend/tests/unit/constant.test.ts +8 -0
- package/backend/tests/unit/email.test.ts +372 -0
- package/backend/tests/unit/environment.test.ts +59 -0
- package/backend/tests/unit/helpers.test.ts +63 -0
- package/backend/tests/unit/logger.test.ts +22 -0
- package/backend/tests/unit/rate-limit.test.ts +154 -0
- package/backend/tests/unit/response.test.ts +58 -0
- package/backend/tests/unit/sql-parser.test.ts +74 -0
- package/backend/tests/unit/uuid.test.ts +21 -0
- package/backend/tests/unit/validations.test.ts +80 -0
- package/backend/tsconfig.json +1 -1
- package/backend/vitest.config.ts +11 -0
- package/claude-plugin/.claude-plugin/plugin.json +24 -0
- package/claude-plugin/README.md +133 -0
- package/claude-plugin/skills/insforge-schema-patterns/SKILL.md +270 -0
- package/docker-compose.prod.yml +60 -4
- package/docker-compose.yml +65 -4
- package/docker-init/db/db-init.sql +6 -34
- package/docker-init/logs/vector.yml +236 -0
- package/docs/README.md +44 -0
- package/docs/changelog.mdx +67 -0
- package/docs/core-concepts/ai/architecture.mdx +373 -0
- package/docs/core-concepts/ai/sdk.mdx +213 -0
- package/docs/core-concepts/authentication/architecture.mdx +278 -0
- package/docs/core-concepts/authentication/sdk.mdx +414 -0
- package/docs/core-concepts/authentication/ui-components/customization.mdx +529 -0
- package/docs/core-concepts/authentication/ui-components/nextjs.mdx +221 -0
- package/docs/core-concepts/authentication/ui-components/react-router.mdx +184 -0
- package/docs/core-concepts/authentication/ui-components/react.mdx +129 -0
- package/docs/core-concepts/database/architecture.mdx +256 -0
- package/docs/core-concepts/database/sdk.mdx +382 -0
- package/docs/core-concepts/functions/architecture.mdx +105 -0
- package/docs/core-concepts/functions/sdk.mdx +184 -0
- package/docs/core-concepts/storage/architecture.mdx +243 -0
- package/docs/core-concepts/storage/sdk.mdx +253 -0
- package/docs/deployment/README.md +94 -0
- package/docs/deployment/deploy-to-aws-ec2.md +565 -0
- package/docs/deployment/deploy-to-azure-virtual-machines.md +313 -0
- package/docs/deployment/deploy-to-google-cloud-compute-engine.md +613 -0
- package/docs/deployment/deploy-to-render.md +441 -0
- package/docs/docs.json +210 -0
- package/docs/examples/framework-guides/nextjs.mdx +131 -0
- package/docs/examples/framework-guides/nuxt.mdx +165 -0
- package/docs/examples/framework-guides/react.mdx +165 -0
- package/docs/examples/framework-guides/svelte.mdx +153 -0
- package/docs/examples/framework-guides/vue.mdx +159 -0
- package/docs/examples/overview.mdx +67 -0
- package/docs/favicon.svg +19 -0
- package/docs/images/changelog/nov-2025/auth-components.webp +0 -0
- package/docs/images/changelog/nov-2025/database-metadata.webp +0 -0
- package/docs/images/changelog/nov-2025/quickstart-prompts.webp +0 -0
- package/docs/images/changelog/nov-2025/sql-editor.webp +0 -0
- package/docs/images/changelog/nov-2025/usage-page.webp +0 -0
- package/docs/images/changelog/october-2025/csv-upload.webp +0 -0
- package/docs/images/changelog/october-2025/logs-feature.webp +0 -0
- package/docs/images/changelog/october-2025/oauth-providers.webp +0 -0
- package/docs/images/checks-passed.png +0 -0
- package/docs/images/dashboard-connect-expanded.png +0 -0
- package/docs/images/dashboard-connect.png +0 -0
- package/docs/images/hero-dark.png +0 -0
- package/docs/images/hero-light.png +0 -0
- package/docs/images/icons/ai.svg +4 -0
- package/docs/images/icons/auth.svg +1 -0
- package/docs/images/icons/database.svg +1 -0
- package/docs/images/icons/function.svg +1 -0
- package/docs/images/icons/storage.svg +1 -0
- package/docs/images/logos/nextjs.svg +4 -0
- package/docs/images/logos/nuxt.svg +4 -0
- package/docs/images/logos/react.svg +5 -0
- package/docs/images/logos/svelte.svg +4 -0
- package/docs/images/logos/vue.svg +5 -0
- package/docs/images/mcp-install.png +0 -0
- package/docs/images/onboarding-mcp.png +0 -0
- package/docs/insforge-instructions-sdk.md +55 -374
- package/docs/introduction.mdx +45 -0
- package/docs/logo/dark.svg +22 -0
- package/docs/logo/light.svg +20 -0
- package/docs/partnership.mdx +647 -0
- package/docs/quickstart.mdx +83 -0
- package/docs/showcase/2048-arena.png +0 -0
- package/docs/showcase/framegen-cloud.png +0 -0
- package/docs/showcase/line-connect-race.png +0 -0
- package/docs/showcase/moment-vibe.png +0 -0
- package/docs/showcase/national-flags.png +0 -0
- package/docs/showcase/pokemon-vibe.png +0 -0
- package/docs/showcase/pure-browse-buy.png +0 -0
- package/docs/showcase.mdx +52 -0
- package/docs/snippets/sdk-installation.mdx +22 -0
- package/docs/snippets/service-icons.mdx +27 -0
- package/eslint.config.js +10 -3
- package/frontend/package.json +10 -4
- package/frontend/src/App.tsx +13 -82
- package/frontend/src/assets/icons/connected.svg +3 -0
- package/frontend/src/assets/icons/loader.svg +9 -0
- package/frontend/src/assets/logos/apple.svg +4 -0
- package/frontend/src/assets/logos/discord.svg +1 -1
- package/frontend/src/assets/logos/facebook.svg +3 -0
- package/frontend/src/assets/logos/instagram.svg +2 -0
- package/frontend/src/assets/logos/linkedin.svg +3 -0
- package/frontend/src/assets/logos/microsoft.svg +1 -0
- package/frontend/src/assets/logos/spotify.svg +17 -0
- package/frontend/src/assets/logos/tiktok.svg +6 -0
- package/frontend/src/assets/logos/x.svg +3 -0
- package/frontend/src/components/Checkbox.tsx +27 -29
- package/frontend/src/components/CodeBlock.tsx +55 -2
- package/frontend/src/components/CodeEditor.tsx +92 -0
- package/frontend/src/components/ConfirmDialog.tsx +1 -1
- package/frontend/src/components/ConnectCTA.tsx +38 -0
- package/frontend/src/components/CopyButton.tsx +52 -15
- package/frontend/src/components/ErrorState.tsx +1 -2
- package/frontend/src/components/FeatureSidebar.tsx +6 -6
- package/frontend/src/components/FeatureSidebarItem.tsx +2 -2
- package/frontend/src/components/JsonHighlight.tsx +21 -9
- package/frontend/src/components/ProjectInfoModal.tsx +128 -0
- package/frontend/src/components/PromptDialog.tsx +1 -4
- package/frontend/src/components/SearchInput.tsx +1 -2
- package/frontend/src/components/Stepper.tsx +53 -0
- package/frontend/src/components/ThemeToggle.tsx +3 -3
- package/frontend/src/components/datagrid/DataGrid.tsx +25 -32
- package/frontend/src/components/datagrid/cell-editors/DateCellEditor.tsx +1 -2
- package/frontend/src/components/datagrid/cell-editors/JsonCellEditor.tsx +2 -4
- package/frontend/src/components/datagrid/index.ts +23 -0
- package/frontend/src/components/index.ts +23 -30
- package/frontend/src/components/layout/AppHeader.tsx +133 -92
- package/frontend/src/components/layout/AppSidebar.tsx +80 -170
- package/frontend/src/components/layout/Layout.tsx +12 -23
- package/frontend/src/components/layout/PrimaryMenu.tsx +187 -0
- package/frontend/src/components/layout/SecondaryMenu.tsx +70 -0
- package/frontend/src/components/layout/index.ts +5 -0
- package/frontend/src/components/radix/Tooltip.tsx +24 -13
- package/frontend/src/components/radix/index.ts +22 -0
- package/frontend/src/features/ai/components/AIConfigCard.tsx +129 -83
- package/frontend/src/features/ai/components/AIEmptyState.tsx +12 -7
- package/frontend/src/features/ai/components/ModalityFilterSidebar.tsx +101 -0
- package/frontend/src/features/ai/components/ModelSelectionDialog.tsx +135 -0
- package/frontend/src/features/ai/components/ModelSelectionGrid.tsx +51 -0
- package/frontend/src/features/ai/components/SystemPromptDialog.tsx +118 -0
- package/frontend/src/features/ai/components/index.ts +6 -0
- package/frontend/src/features/ai/helpers.ts +57 -71
- package/frontend/src/features/ai/hooks/useAIConfigs.ts +39 -113
- package/frontend/src/features/ai/hooks/useAIUsage.ts +0 -2
- package/frontend/src/features/ai/page/AIPage.tsx +67 -79
- package/frontend/src/features/ai/services/ai.service.ts +5 -5
- package/frontend/src/features/auth/components/AuthPreview.tsx +96 -0
- package/frontend/src/features/auth/components/OAuthConfigDialog.tsx +53 -30
- package/frontend/src/features/auth/components/UserFormDialog.tsx +13 -6
- package/frontend/src/features/auth/components/UsersDataGrid.tsx +44 -14
- package/frontend/src/features/auth/components/index.ts +5 -0
- package/frontend/src/features/auth/helpers.tsx +200 -0
- package/frontend/src/features/auth/hooks/useAnonToken.ts +30 -0
- package/frontend/src/features/auth/hooks/useAuthConfig.ts +48 -0
- package/frontend/src/features/auth/hooks/useOAuthConfig.ts +14 -10
- package/frontend/src/features/auth/hooks/useUsers.ts +43 -5
- package/frontend/src/features/auth/index.ts +3 -2
- package/frontend/src/features/auth/page/AuthMethodsPage.tsx +275 -0
- package/frontend/src/features/auth/page/ConfigurationPage.tsx +395 -0
- package/frontend/src/features/auth/page/UsersPage.tsx +285 -0
- package/frontend/src/features/auth/services/anonToken.service.ts +11 -0
- package/frontend/src/features/auth/services/config.service.ts +19 -0
- package/frontend/src/features/auth/services/{oauth.service.ts → oauth-config.service.ts} +4 -4
- package/frontend/src/features/auth/services/{auth.service.ts → user.service.ts} +7 -53
- package/frontend/src/features/dashboard/components/ConnectionSuccessBanner.tsx +35 -0
- package/frontend/src/features/dashboard/components/PromptCard.tsx +21 -0
- package/frontend/src/features/dashboard/components/PromptDialog.tsx +103 -0
- package/frontend/src/features/dashboard/components/StatsCard.tsx +50 -0
- package/frontend/src/features/dashboard/components/index.ts +4 -0
- package/frontend/src/features/dashboard/page/DashboardPage.tsx +187 -169
- package/frontend/src/features/dashboard/prompts/ai-chatbot.ts +13 -0
- package/frontend/src/features/dashboard/prompts/crm-system.ts +13 -0
- package/frontend/src/features/dashboard/prompts/ecommerce-platform.ts +12 -0
- package/frontend/src/features/dashboard/prompts/index.ts +31 -0
- package/frontend/src/features/dashboard/prompts/instagram-clone.ts +11 -0
- package/frontend/src/features/dashboard/prompts/notion-clone.ts +14 -0
- package/frontend/src/features/dashboard/prompts/reddit-clone.ts +12 -0
- package/frontend/src/features/database/components/DatabaseDataGrid.tsx +48 -17
- package/frontend/src/features/database/components/ForeignKeyCell.tsx +15 -34
- package/frontend/src/features/database/components/ForeignKeyPopover.tsx +19 -20
- package/frontend/src/features/database/components/LinkRecordModal.tsx +120 -125
- package/frontend/src/features/database/components/RecordFormDialog.tsx +22 -33
- package/frontend/src/features/database/components/RecordFormField.tsx +45 -47
- package/frontend/src/features/database/components/TableEmptyState.tsx +6 -5
- package/frontend/src/features/database/components/TableForm.tsx +28 -15
- package/frontend/src/features/database/components/TableFormColumn.tsx +2 -3
- package/frontend/src/features/database/components/TableSidebar.tsx +1 -1
- package/frontend/src/features/database/components/TablesEmptyState.tsx +48 -0
- package/frontend/src/features/database/components/TemplateCard.tsx +37 -0
- package/frontend/src/features/database/components/TemplatePreview.tsx +92 -0
- package/frontend/src/features/database/components/index.ts +19 -0
- package/frontend/src/features/database/constants.ts +28 -2
- package/frontend/src/features/database/contexts/SQLEditorContext.tsx +188 -0
- package/frontend/src/features/database/helpers.ts +2 -2
- package/frontend/src/features/database/hooks/useCSVImport.ts +29 -0
- package/frontend/src/features/database/hooks/useFullMetadata.ts +18 -0
- package/frontend/src/features/database/hooks/useRawSQL.ts +55 -0
- package/frontend/src/features/database/hooks/useRecords.ts +139 -0
- package/frontend/src/features/database/hooks/useTables.ts +131 -0
- package/frontend/src/features/database/index.ts +6 -1
- package/frontend/src/features/database/page/FunctionsPage.tsx +211 -0
- package/frontend/src/features/database/page/IndexesPage.tsx +240 -0
- package/frontend/src/features/database/page/PoliciesPage.tsx +248 -0
- package/frontend/src/features/database/page/SQLEditorPage.tsx +382 -0
- package/frontend/src/features/database/page/{DatabasePage.tsx → TablesPage.tsx} +186 -185
- package/frontend/src/features/database/page/TemplatesPage.tsx +39 -0
- package/frontend/src/features/database/page/TriggersPage.tsx +242 -0
- package/frontend/src/features/database/services/advance.service.ts +66 -0
- package/frontend/src/features/database/services/{database.service.ts → record.service.ts} +67 -64
- package/frontend/src/features/database/services/table.service.ts +64 -0
- package/frontend/src/features/database/templates/ai-chatbot.ts +402 -0
- package/frontend/src/features/database/templates/crm-system.ts +528 -0
- package/frontend/src/features/database/templates/ecommerce-platform.ts +553 -0
- package/frontend/src/features/database/templates/index.ts +34 -0
- package/frontend/src/features/database/templates/instagram-clone.ts +222 -0
- package/frontend/src/features/database/templates/notion-clone.ts +483 -0
- package/frontend/src/features/database/templates/reddit-clone.ts +526 -0
- package/frontend/src/features/functions/components/FunctionRow.tsx +2 -1
- package/frontend/src/features/functions/components/FunctionsSidebar.tsx +1 -1
- package/frontend/src/features/functions/components/SecretRow.tsx +1 -1
- package/frontend/src/features/functions/components/index.ts +5 -0
- package/frontend/src/features/functions/hooks/useFunctions.ts +4 -4
- package/frontend/src/features/{secrets → functions}/hooks/useSecrets.ts +5 -5
- package/frontend/src/features/functions/page/FunctionsPage.tsx +160 -17
- package/frontend/src/features/functions/{components/SecretsContent.tsx → page/SecretsPage.tsx} +8 -12
- package/frontend/src/features/functions/services/{functions.service.ts → function.service.ts} +2 -2
- package/frontend/src/features/{secrets/services/secrets.service.ts → functions/services/secret.service.ts} +2 -2
- package/frontend/src/features/login/hooks/usePartnerOrigin.ts +27 -0
- package/frontend/src/features/login/page/CloudLoginPage.tsx +79 -54
- package/frontend/src/features/login/page/LoginPage.tsx +16 -23
- package/frontend/src/features/login/services/partnership.service.ts +65 -0
- package/frontend/src/features/logs/components/LogsDataGrid.tsx +89 -0
- package/frontend/src/features/logs/components/SeverityBadge.tsx +18 -0
- package/frontend/src/features/logs/components/index.ts +2 -0
- package/frontend/src/features/logs/helpers.ts +24 -0
- package/frontend/src/features/logs/hooks/useAuditLogs.ts +4 -4
- package/frontend/src/features/logs/hooks/useLogSources.ts +137 -0
- package/frontend/src/features/logs/hooks/useLogs.ts +163 -0
- package/frontend/src/features/logs/hooks/useMcpUsage.ts +181 -0
- package/frontend/src/features/logs/index.ts +8 -2
- package/frontend/src/features/logs/page/AuditsPage.tsx +91 -38
- package/frontend/src/features/logs/page/LogsPage.tsx +152 -0
- package/frontend/src/features/logs/page/MCPLogsPage.tsx +84 -0
- package/frontend/src/features/logs/services/audit.service.ts +63 -0
- package/frontend/src/features/logs/services/log.service.ts +15 -110
- package/frontend/src/features/logs/services/usage.service.ts +31 -0
- package/frontend/src/features/onboard/components/McpConnectionStatus.tsx +68 -0
- package/frontend/src/features/onboard/components/OnboardingModal.tsx +267 -0
- package/frontend/src/features/onboard/components/VideoDemoModal.tsx +38 -0
- package/frontend/src/features/onboard/components/index.ts +4 -0
- package/frontend/src/features/onboard/components/mcp/CursorDeeplinkGenerator.tsx +2 -2
- package/frontend/src/features/onboard/components/mcp/{mcp-helper.tsx → helpers.tsx} +8 -8
- package/frontend/src/features/onboard/components/mcp/index.ts +2 -3
- package/frontend/src/features/onboard/index.ts +13 -3
- package/frontend/src/features/storage/components/BucketEmptyState.tsx +9 -6
- package/frontend/src/features/storage/components/BucketFormDialog.tsx +25 -41
- package/frontend/src/features/storage/components/FilePreviewDialog.tsx +20 -8
- package/frontend/src/features/storage/components/StorageDataGrid.tsx +4 -3
- package/frontend/src/features/storage/components/StorageManager.tsx +23 -34
- package/frontend/src/features/storage/components/index.ts +12 -0
- package/frontend/src/features/storage/hooks/useStorage.ts +208 -0
- package/frontend/src/features/storage/page/StoragePage.tsx +41 -115
- package/frontend/src/features/storage/services/storage.service.ts +22 -1
- package/frontend/src/features/visualizer/components/AuthNode.tsx +72 -56
- package/frontend/src/features/visualizer/components/BucketNode.tsx +4 -4
- package/frontend/src/features/visualizer/components/SchemaVisualizer.tsx +108 -80
- package/frontend/src/features/visualizer/components/TableNode.tsx +34 -41
- package/frontend/src/features/visualizer/components/VisualizerSkeleton.tsx +12 -4
- package/frontend/src/features/visualizer/page/VisualizerPage.tsx +33 -29
- package/frontend/src/index.css +1 -0
- package/frontend/src/lib/analytics/posthog.tsx +27 -0
- package/frontend/src/lib/contexts/AuthContext.tsx +38 -31
- package/frontend/src/lib/contexts/SocketContext.tsx +5 -6
- package/frontend/src/{features/metadata → lib}/hooks/useMetadata.ts +1 -1
- package/frontend/src/lib/hooks/useToast.tsx +6 -2
- package/frontend/src/lib/routing/AppRoutes.tsx +84 -0
- package/frontend/src/lib/routing/RequireAuth.tsx +27 -0
- package/frontend/src/lib/utils/cloudMessaging.ts +20 -0
- package/frontend/src/lib/utils/menuItems.ts +183 -0
- package/frontend/src/lib/utils/{validation-schemas.ts → schemaValidations.ts} +10 -5
- package/frontend/src/lib/utils/utils.ts +19 -1
- package/frontend/src/vite-env.d.ts +1 -0
- package/frontend/vite.config.ts +5 -3
- package/functions/server.ts +28 -3
- package/functions/worker-template.js +15 -4
- package/i18n/README.ar.md +130 -0
- package/i18n/README.de.md +130 -0
- package/i18n/README.es.md +154 -0
- package/i18n/README.fr.md +134 -0
- package/i18n/README.hi.md +129 -0
- package/i18n/README.ja.md +174 -0
- package/i18n/README.ko.md +137 -0
- package/i18n/README.pt-BR.md +131 -0
- package/i18n/README.ru.md +129 -0
- package/i18n/README.zh-CN.md +133 -0
- package/openapi/ai.yaml +31 -4
- package/openapi/auth.yaml +827 -146
- package/package.json +16 -7
- package/shared-schemas/package.json +1 -1
- package/shared-schemas/src/ai-api.schema.ts +34 -58
- package/shared-schemas/src/ai.schema.ts +5 -0
- package/shared-schemas/src/auth-api.schema.ts +154 -8
- package/shared-schemas/src/auth.schema.ts +42 -6
- package/shared-schemas/src/cloud-events.schema.ts +57 -0
- package/shared-schemas/src/database-api.schema.ts +3 -3
- package/shared-schemas/src/database.schema.ts +1 -1
- package/shared-schemas/src/index.ts +1 -0
- package/shared-schemas/src/logs-api.schema.ts +7 -1
- package/shared-schemas/src/logs.schema.ts +26 -0
- package/shared-schemas/src/metadata.schema.ts +9 -4
- package/test-gemini.sh +35 -0
- package/test-usage-admin.sh +57 -0
- package/test-usage.sh +50 -0
- package/zeabur/README.md +13 -0
- package/zeabur/template.yml +1032 -0
- package/.github/workflows/deploy-aws.yml +0 -130
- package/backend/src/api/routes/agent.ts +0 -29
- package/backend/src/api/routes/auth.oauth.ts +0 -482
- package/backend/src/api/routes/auth.ts +0 -386
- package/backend/src/api/routes/docs.ts +0 -66
- package/backend/src/api/routes/functions.ts +0 -183
- package/backend/src/api/routes/openapi.ts +0 -82
- package/backend/src/api/routes/usage.ts +0 -96
- package/backend/src/core/ai/client.ts +0 -242
- package/backend/src/core/ai/model.ts +0 -117
- package/backend/src/core/auth/auth.ts +0 -780
- package/backend/src/core/database/table.ts +0 -772
- package/backend/src/core/documentation/agent.ts +0 -689
- package/backend/src/core/documentation/openapi.ts +0 -856
- package/backend/src/core/logs/analytics.ts +0 -76
- package/backend/src/core/logs/providers/localdb.provider.ts +0 -246
- package/backend/src/core/storage/storage.ts +0 -923
- package/backend/src/utils/cloud-token.ts +0 -39
- package/backend/src/utils/helpers.ts +0 -49
- package/backend/src/utils/uuid.ts +0 -9
- package/backend/tests/manual/test-better-auth.sh +0 -303
- package/docker-init/db/logs.sql +0 -9
- package/frontend/README.md +0 -112
- package/frontend/src/components/datagrid/index.tsx +0 -20
- package/frontend/src/components/layout/CloudLayout.tsx +0 -95
- package/frontend/src/features/ai/components/AIConfigDialog.tsx +0 -76
- package/frontend/src/features/ai/components/AIConfigForm.tsx +0 -222
- package/frontend/src/features/ai/components/fields/ModalityField.tsx +0 -87
- package/frontend/src/features/ai/components/fields/ModelSelectionField.tsx +0 -134
- package/frontend/src/features/ai/components/fields/SystemPromptField.tsx +0 -33
- package/frontend/src/features/auth/components/AddOAuthDialog.tsx +0 -106
- package/frontend/src/features/auth/components/AuthMethodTab.tsx +0 -238
- package/frontend/src/features/auth/components/UsersTab.tsx +0 -114
- package/frontend/src/features/auth/page/AuthenticationPage.tsx +0 -169
- package/frontend/src/features/database/hooks/UseLinkModal.tsx +0 -78
- package/frontend/src/features/functions/components/FunctionViewer.tsx +0 -46
- package/frontend/src/features/functions/components/FunctionsContent.tsx +0 -88
- package/frontend/src/features/login/components/AuthErrorBoundary.tsx +0 -87
- package/frontend/src/features/login/components/PrivateRoute.tsx +0 -24
- package/frontend/src/features/logs/components/AnalyticsLogsTable.tsx +0 -313
- package/frontend/src/features/logs/components/LogsTable.tsx +0 -199
- package/frontend/src/features/logs/page/AnalyticsLogsPage.tsx +0 -530
- package/frontend/src/features/metadata/index.ts +0 -0
- package/frontend/src/features/metadata/page/MetadataPage.tsx +0 -136
- package/frontend/src/features/onboard/components/CompletionCard.tsx +0 -41
- package/frontend/src/features/onboard/components/OnboardButton.tsx +0 -84
- package/frontend/src/features/onboard/components/StepContent.tsx +0 -91
- package/frontend/src/features/onboard/components/TestConnectionStep.tsx +0 -53
- package/frontend/src/features/onboard/components/mcp/McpInstallation.tsx +0 -144
- package/frontend/src/features/onboard/page/OnBoardPage.tsx +0 -104
- package/frontend/src/features/onboard/types.ts +0 -8
- package/frontend/src/lib/contexts/OnboardStepContext.tsx +0 -68
- package/frontend/src/lib/hooks/useOnboardingCompletion.ts +0 -29
- /package/backend/src/api/{middleware → middlewares}/error.ts +0 -0
- /package/backend/src/api/{middleware → middlewares}/upload.ts +0 -0
- /package/backend/{migrations → src/infra/database/migrations}/000_create-base-tables.sql +0 -0
- /package/backend/{migrations → src/infra/database/migrations}/001_create-helper-functions.sql +0 -0
- /package/backend/{migrations → src/infra/database/migrations}/002_rename-auth-tables.sql +0 -0
- /package/backend/{migrations → src/infra/database/migrations}/003_create-users-table.sql +0 -0
- /package/backend/{migrations → src/infra/database/migrations}/004_add-reload-postgrest-func.sql +0 -0
- /package/backend/{migrations → src/infra/database/migrations}/005_enable-project-admin-modify-users.sql +0 -0
- /package/backend/{migrations → src/infra/database/migrations}/006_modify-ai-usage-table.sql +0 -0
- /package/backend/{migrations → src/infra/database/migrations}/007_drop-metadata-table.sql +0 -0
- /package/backend/{migrations → src/infra/database/migrations}/008_add-system-tables.sql +0 -0
- /package/backend/{migrations → src/infra/database/migrations}/009_add-function-secrets.sql +0 -0
- /package/backend/{migrations → src/infra/database/migrations}/010_modify-ai-config-modalities.sql +0 -0
- /package/backend/{migrations → src/infra/database/migrations}/011_refactor-secrets-table.sql +0 -0
- /package/backend/{migrations → src/infra/database/migrations}/012_add-storage-uploaded-by.sql +0 -0
- /package/frontend/src/{features/metadata → lib}/services/metadata.service.ts +0 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { successResponse, errorResponse, paginatedResponse } from '../../src/utils/response';
|
|
2
|
+
import { Response } from 'express';
|
|
3
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
4
|
+
|
|
5
|
+
describe('Response Utilities', () => {
|
|
6
|
+
let res: Partial<Response>;
|
|
7
|
+
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
res = {
|
|
10
|
+
status: vi.fn().mockReturnThis(),
|
|
11
|
+
json: vi.fn().mockReturnThis(),
|
|
12
|
+
setHeader: vi.fn().mockReturnThis(),
|
|
13
|
+
};
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it('successResponse returns data with correct status', () => {
|
|
17
|
+
const data = { message: 'ok' };
|
|
18
|
+
successResponse(res as Response, data, 201);
|
|
19
|
+
expect(res.status).toHaveBeenCalledWith(201);
|
|
20
|
+
expect(res.json).toHaveBeenCalledWith(data);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('errorResponse returns error with correct status', () => {
|
|
24
|
+
const error = 'ERROR';
|
|
25
|
+
const message = 'Something went wrong';
|
|
26
|
+
errorResponse(res as Response, error, message, 400, 'Retry');
|
|
27
|
+
expect(res.status).toHaveBeenCalledWith(400);
|
|
28
|
+
expect(res.json).toHaveBeenCalledWith({
|
|
29
|
+
error,
|
|
30
|
+
message,
|
|
31
|
+
statusCode: 400,
|
|
32
|
+
nextActions: 'Retry',
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('paginatedResponse sets headers and status correctly', () => {
|
|
37
|
+
const data = [1, 2, 3];
|
|
38
|
+
const total = 10;
|
|
39
|
+
const offset = 0;
|
|
40
|
+
|
|
41
|
+
paginatedResponse(res as Response, data, total, offset);
|
|
42
|
+
|
|
43
|
+
expect(res.setHeader).toHaveBeenCalledWith('Content-Range', '0-2/10');
|
|
44
|
+
expect(res.setHeader).toHaveBeenCalledWith('Preference-Applied', 'count=exact');
|
|
45
|
+
expect(res.status).toHaveBeenCalledWith(206); // partial content
|
|
46
|
+
expect(res.json).toHaveBeenCalledWith(data);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('paginatedResponse returns 200 when all items returned', () => {
|
|
50
|
+
const data = [1, 2, 3];
|
|
51
|
+
const total = 3;
|
|
52
|
+
const offset = 0;
|
|
53
|
+
|
|
54
|
+
paginatedResponse(res as Response, data, total, offset);
|
|
55
|
+
|
|
56
|
+
expect(res.status).toHaveBeenCalledWith(200);
|
|
57
|
+
});
|
|
58
|
+
});
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { parseSQLStatements } from '../../src/utils/sql-parser';
|
|
3
|
+
|
|
4
|
+
describe('parseSQLStatements', () => {
|
|
5
|
+
it('splits multiple statements by semicolon', () => {
|
|
6
|
+
const sql = `
|
|
7
|
+
SELECT * FROM users;
|
|
8
|
+
INSERT INTO users (name) VALUES ('John');
|
|
9
|
+
DELETE FROM users WHERE id = 1;
|
|
10
|
+
`;
|
|
11
|
+
const result = parseSQLStatements(sql);
|
|
12
|
+
expect(result).toEqual([
|
|
13
|
+
'SELECT * FROM users',
|
|
14
|
+
"INSERT INTO users (name) VALUES ('John')",
|
|
15
|
+
'DELETE FROM users WHERE id = 1',
|
|
16
|
+
]);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it('ignores line comments', () => {
|
|
20
|
+
const sql = `
|
|
21
|
+
-- This is a comment
|
|
22
|
+
SELECT * FROM users; -- Inline comment
|
|
23
|
+
`;
|
|
24
|
+
const result = parseSQLStatements(sql);
|
|
25
|
+
// Parser returns the statement with comments filtered out
|
|
26
|
+
expect(result).toHaveLength(1);
|
|
27
|
+
expect(result[0]).toContain('SELECT * FROM users');
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('ignores block comments', () => {
|
|
31
|
+
const sql = `
|
|
32
|
+
/* Block comment */
|
|
33
|
+
SELECT * FROM users;
|
|
34
|
+
/* Another comment */
|
|
35
|
+
`;
|
|
36
|
+
const result = parseSQLStatements(sql);
|
|
37
|
+
// Parser returns the statement with comments filtered out
|
|
38
|
+
expect(result).toHaveLength(1);
|
|
39
|
+
expect(result[0]).toContain('SELECT * FROM users');
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('handles semicolons inside string literals', () => {
|
|
43
|
+
const sql = `INSERT INTO messages (text) VALUES ('Hello; World')`;
|
|
44
|
+
const result = parseSQLStatements(sql);
|
|
45
|
+
// Parser includes the trailing semicolon
|
|
46
|
+
expect(result).toEqual([`INSERT INTO messages (text) VALUES ('Hello; World')`]);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('throws error on empty input', () => {
|
|
50
|
+
expect(() => parseSQLStatements('')).toThrow();
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it('returns empty array for comments-only SQL', () => {
|
|
54
|
+
const sql = `
|
|
55
|
+
-- Only comment
|
|
56
|
+
/* Another comment */
|
|
57
|
+
`;
|
|
58
|
+
const result = parseSQLStatements(sql);
|
|
59
|
+
// Parser filters out comment-only content
|
|
60
|
+
expect(result).toEqual([]);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it('trims statements and removes empty results', () => {
|
|
64
|
+
const sql = `
|
|
65
|
+
SELECT * FROM users;
|
|
66
|
+
-- comment
|
|
67
|
+
INSERT INTO users (id) VALUES (1);
|
|
68
|
+
`;
|
|
69
|
+
const result = parseSQLStatements(sql);
|
|
70
|
+
expect(result.length).toBeGreaterThan(0);
|
|
71
|
+
expect(result[0]).toContain('SELECT * FROM users');
|
|
72
|
+
expect(result[result.length - 1] || result[0]).toContain('INSERT INTO users');
|
|
73
|
+
});
|
|
74
|
+
});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { describe, test, expect } from 'vitest';
|
|
2
|
+
import { generateUUID } from '../../src/utils/utils';
|
|
3
|
+
|
|
4
|
+
describe('generateUUID', () => {
|
|
5
|
+
const uuidV4Regex = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
6
|
+
|
|
7
|
+
test('returns a string', () => {
|
|
8
|
+
const uuid = generateUUID();
|
|
9
|
+
expect(typeof uuid).toBe('string');
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
test('returns a valid UUID v4', () => {
|
|
13
|
+
const uuid = generateUUID();
|
|
14
|
+
expect(uuid).toMatch(uuidV4Regex);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
test('generates unique UUIDs on multiple calls', () => {
|
|
18
|
+
const uuids = new Set(Array.from({ length: 10 }, () => generateUUID()));
|
|
19
|
+
expect(uuids.size).toBe(10);
|
|
20
|
+
});
|
|
21
|
+
});
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import {
|
|
2
|
+
validateEmail,
|
|
3
|
+
validateIdentifier,
|
|
4
|
+
isValidIdentifier,
|
|
5
|
+
validateTableName,
|
|
6
|
+
getIdentifierErrorMessage,
|
|
7
|
+
escapeSqlLikePattern,
|
|
8
|
+
escapeRegexPattern,
|
|
9
|
+
} from '../../src/utils/validations';
|
|
10
|
+
import { AppError } from '../../src/api/middleware/error';
|
|
11
|
+
import { describe, test, expect } from 'vitest';
|
|
12
|
+
|
|
13
|
+
describe('Validations Utils', () => {
|
|
14
|
+
describe('validateEmail', () => {
|
|
15
|
+
test('valid email returns true', () => {
|
|
16
|
+
expect(validateEmail('test@example.com')).toBe(true);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
test('invalid email returns false', () => {
|
|
20
|
+
expect(validateEmail('invalid-email')).toBe(false);
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
describe('validateIdentifier', () => {
|
|
25
|
+
test('valid identifier returns true', () => {
|
|
26
|
+
expect(validateIdentifier('my_table')).toBe(true);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
test('empty identifier throws AppError', () => {
|
|
30
|
+
expect(() => validateIdentifier('')).toThrow(AppError);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
test('identifier with quotes throws AppError', () => {
|
|
34
|
+
expect(() => validateIdentifier('bad"identifier')).toThrow(AppError);
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
describe('isValidIdentifier', () => {
|
|
39
|
+
test('valid identifier returns true', () => {
|
|
40
|
+
expect(isValidIdentifier('column1')).toBe(true);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
test('invalid identifier returns false', () => {
|
|
44
|
+
expect(isValidIdentifier('')).toBe(false);
|
|
45
|
+
expect(isValidIdentifier('bad"identifier')).toBe(false);
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
describe('validateTableName', () => {
|
|
50
|
+
test('valid table name returns true', () => {
|
|
51
|
+
expect(validateTableName('users')).toBe(true);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
test('table name starting with _ throws AppError', () => {
|
|
55
|
+
expect(() => validateTableName('_internal')).toThrow(AppError);
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
describe('getIdentifierErrorMessage', () => {
|
|
60
|
+
test('empty identifier returns proper message', () => {
|
|
61
|
+
expect(getIdentifierErrorMessage('')).toContain('cannot be empty');
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
test('bad identifier returns proper message', () => {
|
|
65
|
+
expect(getIdentifierErrorMessage('bad"identifier')).toContain('cannot contain quotes');
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
describe('escapeSqlLikePattern', () => {
|
|
70
|
+
test('escapes % and _ and \\', () => {
|
|
71
|
+
expect(escapeSqlLikePattern('50%_test\\')).toBe('50\\%\\_test\\\\');
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
describe('escapeRegexPattern', () => {
|
|
76
|
+
test('escapes regex metacharacters', () => {
|
|
77
|
+
expect(escapeRegexPattern('test.file(1)')).toBe('test\\.file\\(1\\)');
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
});
|
package/backend/tsconfig.json
CHANGED
package/backend/vitest.config.ts
CHANGED
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
import { defineConfig } from 'vitest/config';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
|
|
5
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
2
6
|
|
|
3
7
|
export default defineConfig({
|
|
8
|
+
resolve: {
|
|
9
|
+
alias: {
|
|
10
|
+
'@': path.resolve(__dirname, './src'),
|
|
11
|
+
'@insforge/shared-schemas': path.resolve(__dirname, '../shared-schemas/src'),
|
|
12
|
+
},
|
|
13
|
+
},
|
|
4
14
|
test: {
|
|
5
15
|
environment: 'node',
|
|
6
16
|
globals: true,
|
|
@@ -10,6 +20,7 @@ export default defineConfig({
|
|
|
10
20
|
reporter: ['text', 'json', 'html'],
|
|
11
21
|
exclude: ['node_modules/', 'dist/', 'frontend/', 'tests/', '**/*.d.ts', '**/*.config.*'],
|
|
12
22
|
},
|
|
23
|
+
|
|
13
24
|
testTimeout: 10000,
|
|
14
25
|
// Run tests sequentially to avoid database conflicts
|
|
15
26
|
pool: 'forks',
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "insforge",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Official InsForge plugin for Claude Code with skills, templates, and commands for building full-stack applications with InsForge BaaS",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "InsForge Team"
|
|
7
|
+
},
|
|
8
|
+
"repository": "https://github.com/InsForge/InsForge",
|
|
9
|
+
"homepage": "https://insforge.com",
|
|
10
|
+
"keywords": [
|
|
11
|
+
"insforge",
|
|
12
|
+
"baas",
|
|
13
|
+
"backend-as-a-service",
|
|
14
|
+
"postgresql",
|
|
15
|
+
"postgrest",
|
|
16
|
+
"full-stack",
|
|
17
|
+
"react",
|
|
18
|
+
"database",
|
|
19
|
+
"storage",
|
|
20
|
+
"edge-functions",
|
|
21
|
+
"authentication"
|
|
22
|
+
],
|
|
23
|
+
"license": "MIT"
|
|
24
|
+
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# InsForge Claude Plugin
|
|
2
|
+
|
|
3
|
+
Official Claude Code plugin for building with InsForge.
|
|
4
|
+
|
|
5
|
+
## What's Included
|
|
6
|
+
|
|
7
|
+
**Skill: `insforge-schema-patterns`**
|
|
8
|
+
- Social graph patterns (follows, likes)
|
|
9
|
+
- Nested comments (self-referential)
|
|
10
|
+
- Multi-tenant patterns
|
|
11
|
+
- Best practices for foreign keys, indexes, and RLS
|
|
12
|
+
|
|
13
|
+
This skill automatically activates when you're designing database schemas with Claude.
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
### Method 1: From Marketplace (Recommended)
|
|
18
|
+
|
|
19
|
+
The easiest way to install:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
# In Claude Code, run:
|
|
23
|
+
/plugin marketplace add InsForge/InsForge
|
|
24
|
+
|
|
25
|
+
# Then browse available plugins:
|
|
26
|
+
/plugin
|
|
27
|
+
|
|
28
|
+
# Select "insforge" to install
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Method 2: Direct Install
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
# Create user plugins directory if needed
|
|
35
|
+
mkdir -p ~/.claude/plugins/user
|
|
36
|
+
|
|
37
|
+
# Clone the repository
|
|
38
|
+
git clone https://github.com/InsForge/InsForge.git
|
|
39
|
+
|
|
40
|
+
# Create symlink
|
|
41
|
+
ln -s "$(pwd)/InsForge/claude-plugin" ~/.claude/plugins/user/insforge
|
|
42
|
+
|
|
43
|
+
# Verify installation
|
|
44
|
+
ls -la ~/.claude/plugins/user/insforge/
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Method 3: Local Development
|
|
48
|
+
|
|
49
|
+
For contributing or testing local changes:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
# Navigate to your local InsForge repo
|
|
53
|
+
cd /path/to/your/InsForge
|
|
54
|
+
|
|
55
|
+
# Create user plugins directory
|
|
56
|
+
mkdir -p ~/.claude/plugins/user
|
|
57
|
+
|
|
58
|
+
# Symlink your local development version
|
|
59
|
+
ln -s "$(pwd)/claude-plugin" ~/.claude/plugins/user/insforge
|
|
60
|
+
|
|
61
|
+
# Verify
|
|
62
|
+
ls -la ~/.claude/plugins/user/insforge/
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Usage
|
|
66
|
+
|
|
67
|
+
Once installed, the skill automatically activates when you ask Claude about database design:
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
You: "I need to build a social media app with follows and likes"
|
|
71
|
+
|
|
72
|
+
Claude: [Automatically loads insforge-schema-patterns skill]
|
|
73
|
+
"I'll use the Social Graph pattern from InsForge best practices..."
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
No special commands needed - Claude knows when to use it!
|
|
77
|
+
|
|
78
|
+
## What's a Skill?
|
|
79
|
+
|
|
80
|
+
Skills are folders with instructions that Claude automatically loads when relevant. They're like giving Claude domain expertise.
|
|
81
|
+
|
|
82
|
+
## Verification
|
|
83
|
+
|
|
84
|
+
Check if the plugin is installed correctly:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
# Check plugin installation
|
|
88
|
+
ls -la ~/.claude/plugins/user/insforge/
|
|
89
|
+
|
|
90
|
+
# Should show:
|
|
91
|
+
# .claude-plugin/
|
|
92
|
+
# skills/
|
|
93
|
+
# README.md
|
|
94
|
+
|
|
95
|
+
# Check the skill is present
|
|
96
|
+
cat ~/.claude/plugins/user/insforge/skills/insforge-schema-patterns/SKILL.md
|
|
97
|
+
|
|
98
|
+
# Should display database schema patterns
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Test the Plugin
|
|
102
|
+
|
|
103
|
+
In Claude Code, ask a database design question:
|
|
104
|
+
|
|
105
|
+
```
|
|
106
|
+
"Help me design a database for a social media app with follows and likes"
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Claude should automatically load the `insforge-schema-patterns` skill and provide expert schema patterns with RLS policies, indexes, and SDK examples.
|
|
110
|
+
|
|
111
|
+
## Troubleshooting
|
|
112
|
+
|
|
113
|
+
**Plugin not found:**
|
|
114
|
+
```bash
|
|
115
|
+
# Remove old symlink if exists
|
|
116
|
+
rm ~/.claude/plugins/user/insforge
|
|
117
|
+
|
|
118
|
+
# Recreate with absolute path
|
|
119
|
+
ln -s /absolute/path/to/InsForge/claude-plugin ~/.claude/plugins/user/insforge
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
**Skill not loading:**
|
|
123
|
+
1. Verify SKILL.md has proper frontmatter (name and description)
|
|
124
|
+
2. Restart Claude Code
|
|
125
|
+
3. Ask a database design question explicitly
|
|
126
|
+
|
|
127
|
+
## Contributing
|
|
128
|
+
|
|
129
|
+
Want to add more skills? Check the [main InsForge repository](https://github.com/InsForge/InsForge).
|
|
130
|
+
|
|
131
|
+
## License
|
|
132
|
+
|
|
133
|
+
MIT
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: insforge-schema-patterns
|
|
3
|
+
description: Database schema patterns for InsForge including social graphs, e-commerce, content publishing, and multi-tenancy with RLS policies. Use when designing data models with relationships, foreign keys, or Row Level Security.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# InsForge Schema Patterns
|
|
7
|
+
|
|
8
|
+
Expert patterns for designing PostgreSQL schemas optimized for InsForge's PostgREST backend.
|
|
9
|
+
|
|
10
|
+
## Pattern 1: Social Graph (Follows)
|
|
11
|
+
|
|
12
|
+
**Use when:** Building social features like Twitter, Instagram, LinkedIn connections
|
|
13
|
+
|
|
14
|
+
**Schema:**
|
|
15
|
+
```sql
|
|
16
|
+
CREATE TABLE follows (
|
|
17
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
18
|
+
follower_id UUID REFERENCES users(id) ON DELETE CASCADE,
|
|
19
|
+
following_id UUID REFERENCES users(id) ON DELETE CASCADE,
|
|
20
|
+
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
21
|
+
UNIQUE(follower_id, following_id)
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
-- Index for fast lookups
|
|
25
|
+
CREATE INDEX idx_follows_follower ON follows(follower_id);
|
|
26
|
+
CREATE INDEX idx_follows_following ON follows(following_id);
|
|
27
|
+
|
|
28
|
+
-- RLS: Users can read all follows but only create their own
|
|
29
|
+
ALTER TABLE follows ENABLE ROW LEVEL SECURITY;
|
|
30
|
+
|
|
31
|
+
CREATE POLICY "Anyone can read follows" ON follows
|
|
32
|
+
FOR SELECT USING (true);
|
|
33
|
+
|
|
34
|
+
CREATE POLICY "Users can follow others" ON follows
|
|
35
|
+
FOR INSERT
|
|
36
|
+
TO authenticated
|
|
37
|
+
WITH CHECK (uid() = follower_id);
|
|
38
|
+
|
|
39
|
+
CREATE POLICY "Users can unfollow" ON follows
|
|
40
|
+
FOR DELETE
|
|
41
|
+
TO authenticated
|
|
42
|
+
USING (uid() = follower_id);
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**Query with InsForge SDK:**
|
|
46
|
+
```javascript
|
|
47
|
+
// Get users I follow with their profiles
|
|
48
|
+
const { data: following } = await client.database
|
|
49
|
+
.from('follows')
|
|
50
|
+
.select('*, following:following_id(id, nickname, avatar_url, bio)')
|
|
51
|
+
.eq('follower_id', currentUserId);
|
|
52
|
+
|
|
53
|
+
// Get my followers
|
|
54
|
+
const { data: followers } = await client.database
|
|
55
|
+
.from('follows')
|
|
56
|
+
.select('*, follower:follower_id(id, nickname, avatar_url, bio)')
|
|
57
|
+
.eq('following_id', currentUserId);
|
|
58
|
+
|
|
59
|
+
// Check if user1 follows user2
|
|
60
|
+
const { data: isFollowing } = await client.database
|
|
61
|
+
.from('follows')
|
|
62
|
+
.select()
|
|
63
|
+
.eq('follower_id', user1Id)
|
|
64
|
+
.eq('following_id', user2Id)
|
|
65
|
+
.single();
|
|
66
|
+
|
|
67
|
+
// Follow a user
|
|
68
|
+
await client.database
|
|
69
|
+
.from('follows')
|
|
70
|
+
.insert([{ follower_id: currentUserId, following_id: targetUserId }]);
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Pattern 2: Likes (Many-to-Many Junction Table)
|
|
76
|
+
|
|
77
|
+
**Use when:** Users can like posts, comments, or other content
|
|
78
|
+
|
|
79
|
+
**Schema:**
|
|
80
|
+
```sql
|
|
81
|
+
CREATE TABLE likes (
|
|
82
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
83
|
+
user_id UUID REFERENCES users(id) ON DELETE CASCADE,
|
|
84
|
+
post_id UUID REFERENCES posts(id) ON DELETE CASCADE,
|
|
85
|
+
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
86
|
+
UNIQUE(user_id, post_id) -- Prevent duplicate likes
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
CREATE INDEX idx_likes_post ON likes(post_id);
|
|
90
|
+
CREATE INDEX idx_likes_user ON likes(user_id);
|
|
91
|
+
|
|
92
|
+
ALTER TABLE likes ENABLE ROW LEVEL SECURITY;
|
|
93
|
+
|
|
94
|
+
CREATE POLICY "Anyone can read likes" ON likes
|
|
95
|
+
FOR SELECT USING (true);
|
|
96
|
+
|
|
97
|
+
CREATE POLICY "Users can like posts" ON likes
|
|
98
|
+
FOR INSERT
|
|
99
|
+
TO authenticated
|
|
100
|
+
WITH CHECK (uid() = user_id);
|
|
101
|
+
|
|
102
|
+
CREATE POLICY "Users can unlike their likes" ON likes
|
|
103
|
+
FOR DELETE
|
|
104
|
+
TO authenticated
|
|
105
|
+
USING (uid() = user_id);
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
**Query with InsForge SDK:**
|
|
109
|
+
```javascript
|
|
110
|
+
// Get post with like count and whether current user liked it
|
|
111
|
+
const { data: post } = await client.database
|
|
112
|
+
.from('posts')
|
|
113
|
+
.select(`
|
|
114
|
+
*,
|
|
115
|
+
likes(count),
|
|
116
|
+
user_like:likes!inner(id, user_id)
|
|
117
|
+
`)
|
|
118
|
+
.eq('id', postId)
|
|
119
|
+
.eq('user_like.user_id', currentUserId)
|
|
120
|
+
.single();
|
|
121
|
+
|
|
122
|
+
// Like a post
|
|
123
|
+
await client.database
|
|
124
|
+
.from('likes')
|
|
125
|
+
.insert([{ user_id: currentUserId, post_id: postId }]);
|
|
126
|
+
|
|
127
|
+
// Unlike a post
|
|
128
|
+
await client.database
|
|
129
|
+
.from('likes')
|
|
130
|
+
.delete()
|
|
131
|
+
.eq('user_id', currentUserId)
|
|
132
|
+
.eq('post_id', postId);
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## Pattern 3: Nested Comments (Self-Referential)
|
|
138
|
+
|
|
139
|
+
**Use when:** Building comment threads, nested replies
|
|
140
|
+
|
|
141
|
+
**Schema:**
|
|
142
|
+
```sql
|
|
143
|
+
CREATE TABLE comments (
|
|
144
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
145
|
+
post_id UUID REFERENCES posts(id) ON DELETE CASCADE,
|
|
146
|
+
user_id UUID REFERENCES users(id) ON DELETE CASCADE,
|
|
147
|
+
parent_comment_id UUID REFERENCES comments(id) ON DELETE CASCADE,
|
|
148
|
+
content TEXT NOT NULL,
|
|
149
|
+
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
150
|
+
updated_at TIMESTAMPTZ DEFAULT NOW()
|
|
151
|
+
);
|
|
152
|
+
|
|
153
|
+
CREATE INDEX idx_comments_post ON comments(post_id);
|
|
154
|
+
CREATE INDEX idx_comments_parent ON comments(parent_comment_id);
|
|
155
|
+
|
|
156
|
+
ALTER TABLE comments ENABLE ROW LEVEL SECURITY;
|
|
157
|
+
|
|
158
|
+
CREATE POLICY "Anyone can read comments" ON comments
|
|
159
|
+
FOR SELECT USING (true);
|
|
160
|
+
|
|
161
|
+
CREATE POLICY "Authenticated users can comment" ON comments
|
|
162
|
+
FOR INSERT
|
|
163
|
+
TO authenticated
|
|
164
|
+
WITH CHECK (uid() = user_id);
|
|
165
|
+
|
|
166
|
+
CREATE POLICY "Users can edit their comments" ON comments
|
|
167
|
+
FOR UPDATE
|
|
168
|
+
TO authenticated
|
|
169
|
+
USING (uid() = user_id)
|
|
170
|
+
WITH CHECK (uid() = user_id);
|
|
171
|
+
|
|
172
|
+
CREATE POLICY "Users can delete their comments" ON comments
|
|
173
|
+
FOR DELETE
|
|
174
|
+
TO authenticated
|
|
175
|
+
USING (uid() = user_id);
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
**Query with InsForge SDK:**
|
|
179
|
+
```javascript
|
|
180
|
+
// Get top-level comments with author info
|
|
181
|
+
const { data: comments } = await client.database
|
|
182
|
+
.from('comments')
|
|
183
|
+
.select('*, author:user_id(nickname, avatar_url)')
|
|
184
|
+
.eq('post_id', postId)
|
|
185
|
+
.is('parent_comment_id', null)
|
|
186
|
+
.order('created_at', { ascending: false });
|
|
187
|
+
|
|
188
|
+
// Get replies to a comment
|
|
189
|
+
const { data: replies } = await client.database
|
|
190
|
+
.from('comments')
|
|
191
|
+
.select('*, author:user_id(nickname, avatar_url)')
|
|
192
|
+
.eq('parent_comment_id', commentId)
|
|
193
|
+
.order('created_at', { ascending: true });
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
## Pattern 4: Multi-Tenant (Organization Scoped)
|
|
199
|
+
|
|
200
|
+
**Use when:** Building SaaS apps where data is scoped to organizations/workspaces
|
|
201
|
+
|
|
202
|
+
**Schema:**
|
|
203
|
+
```sql
|
|
204
|
+
CREATE TABLE organizations (
|
|
205
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
206
|
+
name TEXT NOT NULL,
|
|
207
|
+
created_at TIMESTAMPTZ DEFAULT NOW()
|
|
208
|
+
);
|
|
209
|
+
|
|
210
|
+
CREATE TABLE organization_members (
|
|
211
|
+
organization_id UUID REFERENCES organizations(id) ON DELETE CASCADE,
|
|
212
|
+
user_id UUID REFERENCES users(id) ON DELETE CASCADE,
|
|
213
|
+
role TEXT NOT NULL CHECK (role IN ('owner', 'admin', 'member')),
|
|
214
|
+
joined_at TIMESTAMPTZ DEFAULT NOW(),
|
|
215
|
+
PRIMARY KEY (organization_id, user_id)
|
|
216
|
+
);
|
|
217
|
+
|
|
218
|
+
CREATE TABLE projects (
|
|
219
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
220
|
+
organization_id UUID REFERENCES organizations(id) ON DELETE CASCADE,
|
|
221
|
+
name TEXT NOT NULL,
|
|
222
|
+
created_at TIMESTAMPTZ DEFAULT NOW()
|
|
223
|
+
);
|
|
224
|
+
|
|
225
|
+
-- RLS: Users can only see projects in their organizations
|
|
226
|
+
ALTER TABLE projects ENABLE ROW LEVEL SECURITY;
|
|
227
|
+
|
|
228
|
+
CREATE POLICY "Users see org projects" ON projects
|
|
229
|
+
FOR SELECT
|
|
230
|
+
TO authenticated
|
|
231
|
+
USING (
|
|
232
|
+
organization_id IN (
|
|
233
|
+
SELECT organization_id
|
|
234
|
+
FROM organization_members
|
|
235
|
+
WHERE user_id = uid()
|
|
236
|
+
)
|
|
237
|
+
);
|
|
238
|
+
|
|
239
|
+
CREATE POLICY "Admins can create projects" ON projects
|
|
240
|
+
FOR INSERT
|
|
241
|
+
TO authenticated
|
|
242
|
+
WITH CHECK (
|
|
243
|
+
organization_id IN (
|
|
244
|
+
SELECT organization_id
|
|
245
|
+
FROM organization_members
|
|
246
|
+
WHERE user_id = uid()
|
|
247
|
+
AND role IN ('owner', 'admin')
|
|
248
|
+
)
|
|
249
|
+
);
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
## Best Practices
|
|
255
|
+
|
|
256
|
+
1. **Always add indexes** on foreign key columns for performance
|
|
257
|
+
2. **Use UNIQUE constraints** on junction tables to prevent duplicates
|
|
258
|
+
3. **Enable RLS** on all user-facing tables
|
|
259
|
+
4. **Use ON DELETE CASCADE** for automatic cleanup
|
|
260
|
+
5. **Foreign key expansion** in SDK uses the syntax: `table:column(fields)`
|
|
261
|
+
6. **Count aggregations** use: `table(count)`
|
|
262
|
+
7. **Filter nested tables** with: `nested_table!inner()` for inner join behavior
|
|
263
|
+
|
|
264
|
+
## Common Mistakes to Avoid
|
|
265
|
+
|
|
266
|
+
- ❌ Forgetting indexes on foreign keys → Slow queries
|
|
267
|
+
- ❌ Not using UNIQUE on junction tables → Duplicate likes/follows
|
|
268
|
+
- ❌ Missing RLS policies → Data leaks
|
|
269
|
+
- ❌ Using `.single()` on queries that might return multiple rows → Errors
|
|
270
|
+
- ❌ Not wrapping INSERT data in arrays → PostgREST error
|