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,248 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# Test secrets API endpoints (refactored to use _secrets table)
|
|
4
|
+
# Tests CRUD operations for secrets and edge function integration
|
|
5
|
+
|
|
6
|
+
set -e # Exit on error
|
|
7
|
+
|
|
8
|
+
# Get the directory where this script is located
|
|
9
|
+
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
10
|
+
source "$SCRIPT_DIR/../test-config.sh"
|
|
11
|
+
|
|
12
|
+
# API base URL
|
|
13
|
+
API_BASE="${TEST_API_BASE:-http://localhost:7130/api}"
|
|
14
|
+
DENO_BASE="${DENO_BASE:-http://localhost:7133}"
|
|
15
|
+
|
|
16
|
+
print_blue "🔐 Testing Secrets API (refactored)..."
|
|
17
|
+
|
|
18
|
+
# 1. Test authentication requirement
|
|
19
|
+
print_info "1. Testing authentication requirement for secrets"
|
|
20
|
+
response=$(curl -s -o /dev/null -w "%{http_code}" "$API_BASE/secrets")
|
|
21
|
+
if [ "$response" = "401" ]; then
|
|
22
|
+
print_success "Unauthorized without auth"
|
|
23
|
+
else
|
|
24
|
+
print_fail "Expected 401, got $response"
|
|
25
|
+
track_test_failure
|
|
26
|
+
fi
|
|
27
|
+
|
|
28
|
+
# Get admin token
|
|
29
|
+
print_info "2. Logging in as admin"
|
|
30
|
+
ADMIN_TOKEN=$(get_admin_token)
|
|
31
|
+
if [ -z "$ADMIN_TOKEN" ]; then
|
|
32
|
+
print_fail "Failed to get admin token"
|
|
33
|
+
exit 1
|
|
34
|
+
fi
|
|
35
|
+
print_success "Admin logged in"
|
|
36
|
+
|
|
37
|
+
# 3. List initial secrets (should include BACKEND_INTERNAL_URL)
|
|
38
|
+
print_info "3. Listing initial secrets"
|
|
39
|
+
response=$(curl -s "$API_BASE/secrets" \
|
|
40
|
+
-H "Authorization: Bearer $ADMIN_TOKEN")
|
|
41
|
+
|
|
42
|
+
if echo "$response" | jq -e '.secrets | map(select(.key == "INSFORGE_INTERNAL_URL")) | length == 1' >/dev/null 2>&1; then
|
|
43
|
+
print_success "System secret INSFORGE_INTERNAL_URL exists"
|
|
44
|
+
else
|
|
45
|
+
print_fail "Expected INSFORGE_INTERNAL_URL secret to exist"
|
|
46
|
+
echo "Response: $response"
|
|
47
|
+
track_test_failure
|
|
48
|
+
fi
|
|
49
|
+
|
|
50
|
+
# 4. Create a test secret
|
|
51
|
+
print_info "4. Creating a test secret"
|
|
52
|
+
TEST_KEY="TEST_SECRET_$(date +%s)"
|
|
53
|
+
TEST_VALUE="test_value_12345"
|
|
54
|
+
|
|
55
|
+
response=$(curl -s "$API_BASE/secrets" \
|
|
56
|
+
-X POST \
|
|
57
|
+
-H "Authorization: Bearer $ADMIN_TOKEN" \
|
|
58
|
+
-H "Content-Type: application/json" \
|
|
59
|
+
-d "{\"key\": \"$TEST_KEY\", \"value\": \"$TEST_VALUE\"}")
|
|
60
|
+
|
|
61
|
+
if echo "$response" | grep -q "success.*true"; then
|
|
62
|
+
print_success "Secret created successfully"
|
|
63
|
+
SECRET_ID=$(echo "$response" | jq -r '.id')
|
|
64
|
+
else
|
|
65
|
+
print_fail "Failed to create secret"
|
|
66
|
+
echo "Response: $response"
|
|
67
|
+
track_test_failure
|
|
68
|
+
fi
|
|
69
|
+
|
|
70
|
+
# 5. Get the secret value
|
|
71
|
+
print_info "5. Getting the test secret value"
|
|
72
|
+
response=$(curl -s "$API_BASE/secrets/$TEST_KEY" \
|
|
73
|
+
-H "Authorization: Bearer $ADMIN_TOKEN")
|
|
74
|
+
|
|
75
|
+
if echo "$response" | jq -e ".value == \"$TEST_VALUE\"" >/dev/null 2>&1; then
|
|
76
|
+
print_success "Secret value retrieved correctly"
|
|
77
|
+
else
|
|
78
|
+
print_fail "Failed to retrieve secret value"
|
|
79
|
+
echo "Response: $response"
|
|
80
|
+
track_test_failure
|
|
81
|
+
fi
|
|
82
|
+
|
|
83
|
+
# 6. Update the secret
|
|
84
|
+
print_info "6. Updating the test secret"
|
|
85
|
+
UPDATE_VALUE="updated_value_67890"
|
|
86
|
+
|
|
87
|
+
response=$(curl -s "$API_BASE/secrets/$TEST_KEY" \
|
|
88
|
+
-X PUT \
|
|
89
|
+
-H "Authorization: Bearer $ADMIN_TOKEN" \
|
|
90
|
+
-H "Content-Type: application/json" \
|
|
91
|
+
-d "{\"value\": \"$UPDATE_VALUE\"}")
|
|
92
|
+
|
|
93
|
+
if echo "$response" | grep -q "success.*true"; then
|
|
94
|
+
print_success "Secret updated successfully"
|
|
95
|
+
else
|
|
96
|
+
print_fail "Failed to update secret"
|
|
97
|
+
echo "Response: $response"
|
|
98
|
+
track_test_failure
|
|
99
|
+
fi
|
|
100
|
+
|
|
101
|
+
# 7. Verify update
|
|
102
|
+
print_info "7. Verifying secret update"
|
|
103
|
+
response=$(curl -s "$API_BASE/secrets/$TEST_KEY" \
|
|
104
|
+
-H "Authorization: Bearer $ADMIN_TOKEN")
|
|
105
|
+
|
|
106
|
+
if echo "$response" | jq -e ".value == \"$UPDATE_VALUE\"" >/dev/null 2>&1; then
|
|
107
|
+
print_success "Secret value updated correctly"
|
|
108
|
+
else
|
|
109
|
+
print_fail "Secret value not updated"
|
|
110
|
+
echo "Response: $response"
|
|
111
|
+
track_test_failure
|
|
112
|
+
fi
|
|
113
|
+
|
|
114
|
+
# 8. List secrets and verify our test secret exists
|
|
115
|
+
print_info "8. Verifying secret exists in list"
|
|
116
|
+
response=$(curl -s "$API_BASE/secrets" \
|
|
117
|
+
-H "Authorization: Bearer $ADMIN_TOKEN")
|
|
118
|
+
|
|
119
|
+
if echo "$response" | jq -e ".secrets[] | select(.key == \"$TEST_KEY\")" >/dev/null 2>&1; then
|
|
120
|
+
print_success "Test secret found in list"
|
|
121
|
+
IS_ACTIVE=$(echo "$response" | jq -r ".secrets[] | select(.key == \"$TEST_KEY\") | .isActive")
|
|
122
|
+
if [ "$IS_ACTIVE" = "true" ]; then
|
|
123
|
+
print_success "Secret is active"
|
|
124
|
+
else
|
|
125
|
+
print_fail "Secret is not active"
|
|
126
|
+
track_test_failure
|
|
127
|
+
fi
|
|
128
|
+
else
|
|
129
|
+
print_fail "Test secret not found in list"
|
|
130
|
+
echo "Response: $response"
|
|
131
|
+
track_test_failure
|
|
132
|
+
fi
|
|
133
|
+
|
|
134
|
+
# 9. Test edge function with secret
|
|
135
|
+
print_info "9. Creating edge function to test secret access"
|
|
136
|
+
|
|
137
|
+
# Create a simple function that returns the secret
|
|
138
|
+
cat > /tmp/test-secrets-function.js << EOF
|
|
139
|
+
module.exports = async function(request) {
|
|
140
|
+
const testSecret = Deno.env.get('$TEST_KEY');
|
|
141
|
+
const systemSecret = Deno.env.get('INSFORGE_INTERNAL_URL');
|
|
142
|
+
|
|
143
|
+
return new Response(JSON.stringify({
|
|
144
|
+
testSecretFound: !!testSecret,
|
|
145
|
+
testSecretValue: testSecret === '$UPDATE_VALUE',
|
|
146
|
+
systemSecretFound: !!systemSecret,
|
|
147
|
+
denoEnvWorks: typeof Deno.env.get === 'function'
|
|
148
|
+
}), {
|
|
149
|
+
headers: { 'Content-Type': 'application/json' }
|
|
150
|
+
});
|
|
151
|
+
};
|
|
152
|
+
EOF
|
|
153
|
+
|
|
154
|
+
# Create the function
|
|
155
|
+
FUNCTION_SLUG="test-secrets-fn-$(date +%s)"
|
|
156
|
+
response=$(curl -s -X POST "$API_BASE/functions" \
|
|
157
|
+
-H "Authorization: Bearer $ADMIN_TOKEN" \
|
|
158
|
+
-H "Content-Type: application/json" \
|
|
159
|
+
-d "{
|
|
160
|
+
\"slug\": \"$FUNCTION_SLUG\",
|
|
161
|
+
\"name\": \"Test Secrets Function\",
|
|
162
|
+
\"code\": $(jq -Rs . < /tmp/test-secrets-function.js),
|
|
163
|
+
\"status\": \"active\"
|
|
164
|
+
}")
|
|
165
|
+
|
|
166
|
+
if echo "$response" | grep -q "id"; then
|
|
167
|
+
print_success "Edge function created"
|
|
168
|
+
|
|
169
|
+
# Restart Deno to pick up new secrets
|
|
170
|
+
docker compose restart deno >/dev/null 2>&1
|
|
171
|
+
sleep 3
|
|
172
|
+
|
|
173
|
+
# Test the function
|
|
174
|
+
print_info "10. Testing edge function secret access"
|
|
175
|
+
response=$(curl -s "$DENO_BASE/$FUNCTION_SLUG")
|
|
176
|
+
|
|
177
|
+
if echo "$response" | jq -e '.testSecretValue == true and .systemSecretFound == true' >/dev/null 2>&1; then
|
|
178
|
+
print_success "Edge function can access secrets"
|
|
179
|
+
else
|
|
180
|
+
print_fail "Edge function cannot access secrets properly"
|
|
181
|
+
echo "Response: $response"
|
|
182
|
+
track_test_failure
|
|
183
|
+
fi
|
|
184
|
+
|
|
185
|
+
# Clean up function
|
|
186
|
+
curl -s -X DELETE "$API_BASE/functions/$FUNCTION_SLUG" \
|
|
187
|
+
-H "Authorization: Bearer $ADMIN_TOKEN" >/dev/null 2>&1
|
|
188
|
+
else
|
|
189
|
+
print_fail "Failed to create edge function"
|
|
190
|
+
echo "Response: $response"
|
|
191
|
+
track_test_failure
|
|
192
|
+
fi
|
|
193
|
+
|
|
194
|
+
# 11. Test soft delete (mark as inactive)
|
|
195
|
+
print_info "11. Deleting test secret (soft delete)"
|
|
196
|
+
response=$(curl -s -X DELETE "$API_BASE/secrets/$TEST_KEY" \
|
|
197
|
+
-H "Authorization: Bearer $ADMIN_TOKEN")
|
|
198
|
+
|
|
199
|
+
if echo "$response" | grep -q "success.*true\|deleted"; then
|
|
200
|
+
print_success "Secret deleted successfully"
|
|
201
|
+
else
|
|
202
|
+
print_fail "Failed to delete secret"
|
|
203
|
+
echo "Response: $response"
|
|
204
|
+
track_test_failure
|
|
205
|
+
fi
|
|
206
|
+
|
|
207
|
+
# 12. Verify secret is marked as inactive
|
|
208
|
+
print_info "12. Verifying secret is marked as inactive"
|
|
209
|
+
response=$(curl -s "$API_BASE/secrets" \
|
|
210
|
+
-H "Authorization: Bearer $ADMIN_TOKEN")
|
|
211
|
+
|
|
212
|
+
if echo "$response" | jq -e ".secrets[] | select(.key == \"$TEST_KEY\")" >/dev/null 2>&1; then
|
|
213
|
+
IS_ACTIVE=$(echo "$response" | jq -r ".secrets[] | select(.key == \"$TEST_KEY\") | .isActive")
|
|
214
|
+
if [ "$IS_ACTIVE" = "false" ]; then
|
|
215
|
+
print_success "Secret is marked as inactive (soft delete)"
|
|
216
|
+
else
|
|
217
|
+
print_fail "Secret is still active after deletion"
|
|
218
|
+
echo "isActive: $IS_ACTIVE"
|
|
219
|
+
track_test_failure
|
|
220
|
+
fi
|
|
221
|
+
else
|
|
222
|
+
# Secret might be completely hidden after deletion, which is also fine
|
|
223
|
+
print_success "Secret no longer visible after deletion"
|
|
224
|
+
fi
|
|
225
|
+
|
|
226
|
+
# 13. Test that deleted secret returns 404
|
|
227
|
+
print_info "13. Testing that deleted secret returns 404"
|
|
228
|
+
response_code=$(curl -s -o /dev/null -w "%{http_code}" "$API_BASE/secrets/$TEST_KEY" \
|
|
229
|
+
-H "Authorization: Bearer $ADMIN_TOKEN")
|
|
230
|
+
|
|
231
|
+
if [ "$response_code" = "404" ]; then
|
|
232
|
+
print_success "Deleted secret returns 404"
|
|
233
|
+
else
|
|
234
|
+
print_fail "Expected 404 for deleted secret, got $response_code"
|
|
235
|
+
track_test_failure
|
|
236
|
+
fi
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
# Clean up
|
|
240
|
+
rm -f /tmp/test-secrets-function.js
|
|
241
|
+
|
|
242
|
+
# Summary
|
|
243
|
+
echo ""
|
|
244
|
+
print_blue "=========================================="
|
|
245
|
+
print_blue "Secrets API Test Complete"
|
|
246
|
+
print_blue "=========================================="
|
|
247
|
+
|
|
248
|
+
exit $TEST_FAILED
|
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# Fixed Test Script for InsForge Serverless Functions
|
|
4
|
+
|
|
5
|
+
# Get the directory where this script is located
|
|
6
|
+
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
7
|
+
|
|
8
|
+
# Source the test configuration
|
|
9
|
+
source "$SCRIPT_DIR/../test-config.sh"
|
|
10
|
+
|
|
11
|
+
echo "🧪 InsForge Serverless Functions Test Suite"
|
|
12
|
+
echo "========================================"
|
|
13
|
+
echo ""
|
|
14
|
+
|
|
15
|
+
# Use configuration from test-config.sh
|
|
16
|
+
API_BASE="$TEST_API_BASE"
|
|
17
|
+
# Base URL without /api prefix for function execution
|
|
18
|
+
BASE_URL="${TEST_API_BASE%/api}"
|
|
19
|
+
|
|
20
|
+
# Helper function for section headers
|
|
21
|
+
function section() {
|
|
22
|
+
echo -e "\n${BLUE}▶ $1${NC}"
|
|
23
|
+
echo "----------------------------------------"
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
# Start tests
|
|
27
|
+
section "1. Authentication"
|
|
28
|
+
|
|
29
|
+
TOKEN=$(get_admin_token)
|
|
30
|
+
|
|
31
|
+
if [ -n "$TOKEN" ]; then
|
|
32
|
+
print_success "Admin login"
|
|
33
|
+
else
|
|
34
|
+
print_fail "Admin login - Could not obtain admin token"
|
|
35
|
+
exit 1
|
|
36
|
+
fi
|
|
37
|
+
|
|
38
|
+
section "2. Function CRUD Operations"
|
|
39
|
+
|
|
40
|
+
# Use unique names with timestamp
|
|
41
|
+
TIMESTAMP=$(date +%s)
|
|
42
|
+
FUNC_NAME="test-func-$TIMESTAMP"
|
|
43
|
+
FUNC_SLUG="test-func-$TIMESTAMP" # slug matches name
|
|
44
|
+
|
|
45
|
+
# Create function
|
|
46
|
+
CREATE_RESPONSE=$(curl -s -w "\n%{http_code}" -X POST "$API_BASE/functions" \
|
|
47
|
+
-H "Content-Type: application/json" \
|
|
48
|
+
-H "Authorization: Bearer $TOKEN" \
|
|
49
|
+
-d "{
|
|
50
|
+
\"name\": \"$FUNC_NAME\",
|
|
51
|
+
\"slug\": \"$FUNC_SLUG\",
|
|
52
|
+
\"code\": \"module.exports = async function(req) { return new Response('Hello World'); }\",
|
|
53
|
+
\"status\": \"active\"
|
|
54
|
+
}")
|
|
55
|
+
|
|
56
|
+
HTTP_CODE=$(echo "$CREATE_RESPONSE" | tail -n1)
|
|
57
|
+
if [ "$HTTP_CODE" = "201" ]; then
|
|
58
|
+
print_success "Create function"
|
|
59
|
+
else
|
|
60
|
+
print_fail "Create function - Status: $HTTP_CODE"
|
|
61
|
+
BODY=$(echo "$CREATE_RESPONSE" | sed '$d')
|
|
62
|
+
echo " Response: $BODY"
|
|
63
|
+
fi
|
|
64
|
+
|
|
65
|
+
# Get function
|
|
66
|
+
GET_RESPONSE=$(curl -s -w "\n%{http_code}" -X GET "$API_BASE/functions/$FUNC_SLUG" \
|
|
67
|
+
-H "Authorization: Bearer $TOKEN")
|
|
68
|
+
|
|
69
|
+
HTTP_CODE=$(echo "$GET_RESPONSE" | tail -n1)
|
|
70
|
+
BODY=$(echo "$GET_RESPONSE" | sed '$d')
|
|
71
|
+
if [ "$HTTP_CODE" = "200" ] && echo "$BODY" | grep -q '"code"'; then
|
|
72
|
+
print_success "Get function"
|
|
73
|
+
else
|
|
74
|
+
print_fail "Get function - Status: $HTTP_CODE"
|
|
75
|
+
fi
|
|
76
|
+
|
|
77
|
+
# Update function
|
|
78
|
+
UPDATE_RESPONSE=$(curl -s -w "\n%{http_code}" -X PUT "$API_BASE/functions/$FUNC_SLUG" \
|
|
79
|
+
-H "Content-Type: application/json" \
|
|
80
|
+
-H "Authorization: Bearer $TOKEN" \
|
|
81
|
+
-d '{"code": "module.exports = async function(req) { return new Response(\"Updated!\"); }"}')
|
|
82
|
+
|
|
83
|
+
HTTP_CODE=$(echo "$UPDATE_RESPONSE" | tail -n1)
|
|
84
|
+
if [ "$HTTP_CODE" = "200" ]; then
|
|
85
|
+
print_success "Update function"
|
|
86
|
+
else
|
|
87
|
+
print_fail "Update function - Status: $HTTP_CODE"
|
|
88
|
+
fi
|
|
89
|
+
|
|
90
|
+
# List functions
|
|
91
|
+
LIST_RESPONSE=$(curl -s -w "\n%{http_code}" -X GET "$API_BASE/functions" \
|
|
92
|
+
-H "Authorization: Bearer $TOKEN")
|
|
93
|
+
|
|
94
|
+
HTTP_CODE=$(echo "$LIST_RESPONSE" | tail -n1)
|
|
95
|
+
BODY=$(echo "$LIST_RESPONSE" | sed '$d')
|
|
96
|
+
if [ "$HTTP_CODE" = "200" ] && echo "$BODY" | grep -q "$FUNC_SLUG"; then
|
|
97
|
+
print_success "List functions"
|
|
98
|
+
else
|
|
99
|
+
print_fail "List functions - Status: $HTTP_CODE or missing function"
|
|
100
|
+
fi
|
|
101
|
+
|
|
102
|
+
section "3. Function Execution"
|
|
103
|
+
|
|
104
|
+
# Execute updated function
|
|
105
|
+
EXEC_RESPONSE=$(curl -s -w "\n%{http_code}" "$BASE_URL/functions/$FUNC_SLUG")
|
|
106
|
+
HTTP_CODE=$(echo "$EXEC_RESPONSE" | tail -n1)
|
|
107
|
+
BODY=$(echo "$EXEC_RESPONSE" | sed '$d')
|
|
108
|
+
if [ "$HTTP_CODE" = "200" ] && echo "$BODY" | grep -q "Updated!"; then
|
|
109
|
+
print_success "Execute function"
|
|
110
|
+
else
|
|
111
|
+
print_fail "Execute function - Status: $HTTP_CODE, Body: $BODY"
|
|
112
|
+
fi
|
|
113
|
+
|
|
114
|
+
# Create POST function
|
|
115
|
+
POST_FUNC="post-func-$TIMESTAMP"
|
|
116
|
+
POST_CREATE=$(curl -s -w "\n%{http_code}" -X POST "$API_BASE/functions" \
|
|
117
|
+
-H "Content-Type: application/json" \
|
|
118
|
+
-H "Authorization: Bearer $TOKEN" \
|
|
119
|
+
-d "{
|
|
120
|
+
\"name\": \"$POST_FUNC\",
|
|
121
|
+
\"slug\": \"$POST_FUNC\",
|
|
122
|
+
\"code\": \"module.exports = async function(req) { if (req.method !== 'POST') return new Response('Method Not Allowed', { status: 405 }); const data = await req.json(); return new Response(JSON.stringify({ result: data.value * 2 }), { headers: { 'Content-Type': 'application/json' } }); }\",
|
|
123
|
+
\"status\": \"active\"
|
|
124
|
+
}")
|
|
125
|
+
|
|
126
|
+
HTTP_CODE=$(echo "$POST_CREATE" | tail -n1)
|
|
127
|
+
if [ "$HTTP_CODE" = "201" ]; then
|
|
128
|
+
print_success "Create POST function"
|
|
129
|
+
else
|
|
130
|
+
print_fail "Create POST function - Status: $HTTP_CODE"
|
|
131
|
+
fi
|
|
132
|
+
|
|
133
|
+
# Test POST execution
|
|
134
|
+
POST_EXEC=$(curl -s -w "\n%{http_code}" -X POST "$BASE_URL/functions/$POST_FUNC" \
|
|
135
|
+
-H "Content-Type: application/json" \
|
|
136
|
+
-d '{"value": 21}')
|
|
137
|
+
|
|
138
|
+
HTTP_CODE=$(echo "$POST_EXEC" | tail -n1)
|
|
139
|
+
BODY=$(echo "$POST_EXEC" | sed '$d')
|
|
140
|
+
if [ "$HTTP_CODE" = "200" ] && echo "$BODY" | grep -q '"result":42'; then
|
|
141
|
+
print_success "POST execution"
|
|
142
|
+
else
|
|
143
|
+
print_fail "POST execution - Status: $HTTP_CODE, Body: $BODY"
|
|
144
|
+
fi
|
|
145
|
+
|
|
146
|
+
section "4. Error Status Code Preservation"
|
|
147
|
+
|
|
148
|
+
# Create function that returns 403 Forbidden
|
|
149
|
+
FORBIDDEN_FUNC="forbidden-func-$TIMESTAMP"
|
|
150
|
+
FORBIDDEN_CREATE=$(curl -s -w "\n%{http_code}" -X POST "$API_BASE/functions" \
|
|
151
|
+
-H "Content-Type: application/json" \
|
|
152
|
+
-H "Authorization: Bearer $TOKEN" \
|
|
153
|
+
-d "{
|
|
154
|
+
\"name\": \"$FORBIDDEN_FUNC\",
|
|
155
|
+
\"slug\": \"$FORBIDDEN_FUNC\",
|
|
156
|
+
\"code\": \"module.exports = async function(req) { return new Response(JSON.stringify({ error: 'Access Forbidden' }), { status: 403, headers: { 'Content-Type': 'application/json' } }); }\",
|
|
157
|
+
\"status\": \"active\"
|
|
158
|
+
}")
|
|
159
|
+
|
|
160
|
+
HTTP_CODE=$(echo "$FORBIDDEN_CREATE" | tail -n1)
|
|
161
|
+
if [ "$HTTP_CODE" = "201" ]; then
|
|
162
|
+
# Test execution returns 403
|
|
163
|
+
EXEC_403=$(curl -s -w "\n%{http_code}" "$BASE_URL/functions/$FORBIDDEN_FUNC")
|
|
164
|
+
HTTP_CODE=$(echo "$EXEC_403" | tail -n1)
|
|
165
|
+
BODY=$(echo "$EXEC_403" | sed '$d')
|
|
166
|
+
if [ "$HTTP_CODE" = "403" ] && echo "$BODY" | grep -q "Access Forbidden"; then
|
|
167
|
+
print_success "403 status preserved"
|
|
168
|
+
else
|
|
169
|
+
print_fail "403 status preserved - Expected 403, got $HTTP_CODE"
|
|
170
|
+
fi
|
|
171
|
+
else
|
|
172
|
+
print_fail "Create 403 function - Status: $HTTP_CODE"
|
|
173
|
+
fi
|
|
174
|
+
|
|
175
|
+
# Create function that throws 401 Unauthorized
|
|
176
|
+
UNAUTH_FUNC="unauth-func-$TIMESTAMP"
|
|
177
|
+
UNAUTH_CREATE=$(curl -s -w "\n%{http_code}" -X POST "$API_BASE/functions" \
|
|
178
|
+
-H "Content-Type: application/json" \
|
|
179
|
+
-H "Authorization: Bearer $TOKEN" \
|
|
180
|
+
-d "{
|
|
181
|
+
\"name\": \"$UNAUTH_FUNC\",
|
|
182
|
+
\"slug\": \"$UNAUTH_FUNC\",
|
|
183
|
+
\"code\": \"module.exports = async function(req) { throw new Response(JSON.stringify({ error: 'Unauthorized' }), { status: 401, headers: { 'Content-Type': 'application/json' } }); }\",
|
|
184
|
+
\"status\": \"active\"
|
|
185
|
+
}")
|
|
186
|
+
|
|
187
|
+
HTTP_CODE=$(echo "$UNAUTH_CREATE" | tail -n1)
|
|
188
|
+
if [ "$HTTP_CODE" = "201" ]; then
|
|
189
|
+
# Test execution returns 401
|
|
190
|
+
EXEC_401=$(curl -s -w "\n%{http_code}" "$BASE_URL/functions/$UNAUTH_FUNC")
|
|
191
|
+
HTTP_CODE=$(echo "$EXEC_401" | tail -n1)
|
|
192
|
+
BODY=$(echo "$EXEC_401" | sed '$d')
|
|
193
|
+
if [ "$HTTP_CODE" = "401" ] && echo "$BODY" | grep -q "Unauthorized"; then
|
|
194
|
+
print_success "401 status preserved (thrown)"
|
|
195
|
+
else
|
|
196
|
+
print_fail "401 status preserved (thrown) - Expected 401, got $HTTP_CODE"
|
|
197
|
+
fi
|
|
198
|
+
else
|
|
199
|
+
print_fail "Create 401 function - Status: $HTTP_CODE"
|
|
200
|
+
fi
|
|
201
|
+
|
|
202
|
+
# Create validation function that returns 400 Bad Request
|
|
203
|
+
VALIDATION_FUNC="validation-func-$TIMESTAMP"
|
|
204
|
+
VALIDATION_CREATE=$(curl -s -w "\n%{http_code}" -X POST "$API_BASE/functions" \
|
|
205
|
+
-H "Content-Type: application/json" \
|
|
206
|
+
-H "Authorization: Bearer $TOKEN" \
|
|
207
|
+
-d "{
|
|
208
|
+
\"name\": \"$VALIDATION_FUNC\",
|
|
209
|
+
\"slug\": \"$VALIDATION_FUNC\",
|
|
210
|
+
\"code\": \"module.exports = async function(req) { const url = new URL(req.url); const name = url.searchParams.get('name'); if (!name) { return new Response(JSON.stringify({ error: 'Name parameter required' }), { status: 400, headers: { 'Content-Type': 'application/json' } }); } return new Response(JSON.stringify({ message: 'Hello ' + name }), { headers: { 'Content-Type': 'application/json' } }); }\",
|
|
211
|
+
\"status\": \"active\"
|
|
212
|
+
}")
|
|
213
|
+
|
|
214
|
+
HTTP_CODE=$(echo "$VALIDATION_CREATE" | tail -n1)
|
|
215
|
+
if [ "$HTTP_CODE" = "201" ]; then
|
|
216
|
+
# Test execution without param returns 400
|
|
217
|
+
EXEC_400=$(curl -s -w "\n%{http_code}" "$BASE_URL/functions/$VALIDATION_FUNC")
|
|
218
|
+
HTTP_CODE=$(echo "$EXEC_400" | tail -n1)
|
|
219
|
+
BODY=$(echo "$EXEC_400" | sed '$d')
|
|
220
|
+
if [ "$HTTP_CODE" = "400" ] && echo "$BODY" | grep -q "Name parameter required"; then
|
|
221
|
+
print_success "400 status preserved"
|
|
222
|
+
else
|
|
223
|
+
print_fail "400 status preserved - Expected 400, got $HTTP_CODE"
|
|
224
|
+
fi
|
|
225
|
+
|
|
226
|
+
# Test with valid param returns 200
|
|
227
|
+
EXEC_200=$(curl -s -w "\n%{http_code}" "$BASE_URL/functions/$VALIDATION_FUNC?name=World")
|
|
228
|
+
HTTP_CODE=$(echo "$EXEC_200" | tail -n1)
|
|
229
|
+
BODY=$(echo "$EXEC_200" | sed '$d')
|
|
230
|
+
if [ "$HTTP_CODE" = "200" ] && echo "$BODY" | grep -q "Hello World"; then
|
|
231
|
+
print_success "Validation success (200)"
|
|
232
|
+
else
|
|
233
|
+
print_fail "Validation success - Expected 200, got $HTTP_CODE"
|
|
234
|
+
fi
|
|
235
|
+
else
|
|
236
|
+
print_fail "Create validation function - Status: $HTTP_CODE"
|
|
237
|
+
fi
|
|
238
|
+
|
|
239
|
+
# Create function with real JavaScript error (should be 500)
|
|
240
|
+
ERROR_FUNC="error-func-$TIMESTAMP"
|
|
241
|
+
ERROR_CREATE=$(curl -s -w "\n%{http_code}" -X POST "$API_BASE/functions" \
|
|
242
|
+
-H "Content-Type: application/json" \
|
|
243
|
+
-H "Authorization: Bearer $TOKEN" \
|
|
244
|
+
-d "{
|
|
245
|
+
\"name\": \"$ERROR_FUNC\",
|
|
246
|
+
\"slug\": \"$ERROR_FUNC\",
|
|
247
|
+
\"code\": \"module.exports = async function(req) { throw new Error('Something went wrong'); }\",
|
|
248
|
+
\"status\": \"active\"
|
|
249
|
+
}")
|
|
250
|
+
|
|
251
|
+
HTTP_CODE=$(echo "$ERROR_CREATE" | tail -n1)
|
|
252
|
+
if [ "$HTTP_CODE" = "201" ]; then
|
|
253
|
+
# Test execution returns 500
|
|
254
|
+
EXEC_500=$(curl -s -w "\n%{http_code}" "$BASE_URL/functions/$ERROR_FUNC")
|
|
255
|
+
HTTP_CODE=$(echo "$EXEC_500" | tail -n1)
|
|
256
|
+
BODY=$(echo "$EXEC_500" | sed '$d')
|
|
257
|
+
if [ "$HTTP_CODE" = "500" ] && echo "$BODY" | grep -q "Something went wrong"; then
|
|
258
|
+
print_success "500 for real errors"
|
|
259
|
+
else
|
|
260
|
+
print_fail "500 for real errors - Expected 500, got $HTTP_CODE"
|
|
261
|
+
fi
|
|
262
|
+
else
|
|
263
|
+
print_fail "Create error function - Status: $HTTP_CODE"
|
|
264
|
+
fi
|
|
265
|
+
|
|
266
|
+
section "5. Error Handling"
|
|
267
|
+
|
|
268
|
+
# Duplicate function
|
|
269
|
+
DUP_RESPONSE=$(curl -s -w "\n%{http_code}" -X POST "$API_BASE/functions" \
|
|
270
|
+
-H "Content-Type: application/json" \
|
|
271
|
+
-H "Authorization: Bearer $TOKEN" \
|
|
272
|
+
-d "{
|
|
273
|
+
\"name\": \"$FUNC_NAME\",
|
|
274
|
+
\"slug\": \"$FUNC_SLUG\",
|
|
275
|
+
\"code\": \"module.exports = async function(req) { return new Response('Dup'); }\"
|
|
276
|
+
}")
|
|
277
|
+
|
|
278
|
+
HTTP_CODE=$(echo "$DUP_RESPONSE" | tail -n1)
|
|
279
|
+
if [ "$HTTP_CODE" = "409" ]; then
|
|
280
|
+
print_success "Duplicate rejection"
|
|
281
|
+
else
|
|
282
|
+
print_fail "Duplicate rejection - Expected 409, got $HTTP_CODE"
|
|
283
|
+
fi
|
|
284
|
+
|
|
285
|
+
# No auth
|
|
286
|
+
NO_AUTH=$(curl -s -w "\n%{http_code}" -X GET "$API_BASE/functions")
|
|
287
|
+
HTTP_CODE=$(echo "$NO_AUTH" | tail -n1)
|
|
288
|
+
if [ "$HTTP_CODE" = "401" ]; then
|
|
289
|
+
print_success "Auth required"
|
|
290
|
+
else
|
|
291
|
+
print_fail "Auth required - Expected 401, got $HTTP_CODE"
|
|
292
|
+
fi
|
|
293
|
+
|
|
294
|
+
# Non-existent function
|
|
295
|
+
NOT_FOUND=$(curl -s -w "\n%{http_code}" "$BASE_URL/functions/does-not-exist-$TIMESTAMP")
|
|
296
|
+
HTTP_CODE=$(echo "$NOT_FOUND" | tail -n1)
|
|
297
|
+
if [ "$HTTP_CODE" = "404" ]; then
|
|
298
|
+
print_success "Function not found"
|
|
299
|
+
else
|
|
300
|
+
print_fail "Function not found - Expected 404, got $HTTP_CODE"
|
|
301
|
+
fi
|
|
302
|
+
|
|
303
|
+
section "6. Cleanup"
|
|
304
|
+
|
|
305
|
+
# Delete all test functions
|
|
306
|
+
for slug in "$FUNC_SLUG" "$POST_FUNC" "$FORBIDDEN_FUNC" "$UNAUTH_FUNC" "$VALIDATION_FUNC" "$ERROR_FUNC"; do
|
|
307
|
+
DELETE_RESPONSE=$(curl -s -w "\n%{http_code}" -X DELETE "$API_BASE/functions/$slug" \
|
|
308
|
+
-H "Authorization: Bearer $TOKEN")
|
|
309
|
+
|
|
310
|
+
HTTP_CODE=$(echo "$DELETE_RESPONSE" | tail -n1)
|
|
311
|
+
if [ "$HTTP_CODE" = "200" ]; then
|
|
312
|
+
echo " Deleted: $slug"
|
|
313
|
+
fi
|
|
314
|
+
done
|
|
315
|
+
|
|
316
|
+
# Verify cleanup
|
|
317
|
+
VERIFY=$(curl -s -w "\n%{http_code}" "$BASE_URL/functions/$FUNC_SLUG")
|
|
318
|
+
HTTP_CODE=$(echo "$VERIFY" | tail -n1)
|
|
319
|
+
if [ "$HTTP_CODE" = "404" ]; then
|
|
320
|
+
print_success "Cleanup verified"
|
|
321
|
+
else
|
|
322
|
+
print_fail "Cleanup verification - Expected 404, got $HTTP_CODE"
|
|
323
|
+
fi
|
|
324
|
+
|
|
325
|
+
# Test summary is handled by test-config.sh cleanup function
|