@codemation/host 0.0.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/README.md +75 -0
- package/dist/CodemationConfig-XCkSV2dj.d.ts +168 -0
- package/dist/CodemationConsumerConfigLoader-Dmm2TzAA.d.ts +61 -0
- package/dist/CodemationConsumerConfigLoader-scS_RQMy.js +334 -0
- package/dist/CodemationConsumerConfigLoader-scS_RQMy.js.map +1 -0
- package/dist/CodemationFrontendBootstrapRequest-CE6DjOWJ.js +5768 -0
- package/dist/CodemationFrontendBootstrapRequest-CE6DjOWJ.js.map +1 -0
- package/dist/CodemationPluginListMerger-BNmaoXQL.js +49 -0
- package/dist/CodemationPluginListMerger-BNmaoXQL.js.map +1 -0
- package/dist/CodemationPluginListMerger-BRYqEk0y.d.ts +793 -0
- package/dist/CodemationWhitelabelConfig-DgbjgtrR.d.ts +48 -0
- package/dist/ConsoleLogger-ClPU7jtc.js +35 -0
- package/dist/ConsoleLogger-ClPU7jtc.js.map +1 -0
- package/dist/CredentialServices-BKBGe7l3.js +1030 -0
- package/dist/CredentialServices-BKBGe7l3.js.map +1 -0
- package/dist/CredentialServices-DpDpm8mL.d.ts +291 -0
- package/dist/LogLevelPolicy-4cq9z0TI.d.ts +37 -0
- package/dist/PrismaMigrationDeployer-B1E_gYz7.js +8212 -0
- package/dist/PrismaMigrationDeployer-B1E_gYz7.js.map +1 -0
- package/dist/ServerLoggerFactory-BRHxIDS7.js +340 -0
- package/dist/ServerLoggerFactory-BRHxIDS7.js.map +1 -0
- package/dist/WorkflowViewContracts-DCLpTn25.d.ts +47 -0
- package/dist/chunk-7V6ThxGB.js +39 -0
- package/dist/client-Yh7-CQud.d.ts +21995 -0
- package/dist/client.d.ts +12 -0
- package/dist/client.js +15 -0
- package/dist/client.js.map +1 -0
- package/dist/consumer.d.ts +5 -0
- package/dist/consumer.js +7 -0
- package/dist/credentials.d.ts +50 -0
- package/dist/credentials.js +11 -0
- package/dist/credentials.js.map +1 -0
- package/dist/decorate-B-N_5S4p.js +10 -0
- package/dist/decorateParam-BTcc3KNk.js +15 -0
- package/dist/devServerSidecar.d.ts +52 -0
- package/dist/devServerSidecar.js +131 -0
- package/dist/devServerSidecar.js.map +1 -0
- package/dist/index-Bs4F1IsC.d.ts +1044 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +14 -0
- package/dist/nextServer.d.ts +89 -0
- package/dist/nextServer.js +127 -0
- package/dist/nextServer.js.map +1 -0
- package/dist/persistenceServer-K5eqlZm3.d.ts +36 -0
- package/dist/persistenceServer-W9uRw0dJ.js +19 -0
- package/dist/persistenceServer-W9uRw0dJ.js.map +1 -0
- package/dist/persistenceServer.d.ts +6 -0
- package/dist/persistenceServer.js +6 -0
- package/dist/server-BBdsATju.d.ts +132 -0
- package/dist/server-BiHSuA13.js +175 -0
- package/dist/server-BiHSuA13.js.map +1 -0
- package/dist/server.d.ts +9 -0
- package/dist/server.js +13 -0
- package/package.json +152 -0
- package/playwright.config.ts +74 -0
- package/prisma/migrations/20260315063514_init/migration.sql +16 -0
- package/prisma/migrations/20260316090000_workflow_debugger_overlay/migration.sql +9 -0
- package/prisma/migrations/20260317120000_trigger_state_store/migration.sql +3 -0
- package/prisma/migrations/20260317153000_trigger_setup_state/migration.sql +8 -0
- package/prisma/migrations/20260318110000_credentials_v2/migration.sql +49 -0
- package/prisma/migrations/20260319110000_credential_oauth2_material/migration.sql +28 -0
- package/prisma/migrations/20260319200000_codemation_auth_tables/migration.sql +56 -0
- package/prisma/migrations/20260320140000_user_invites_account_status/migration.sql +20 -0
- package/prisma/migrations/20260325120000_workflow_activation/migration.sql +8 -0
- package/prisma/migrations/migration_lock.toml +3 -0
- package/prisma/schema.prisma +179 -0
- package/prisma.config.ts +12 -0
- package/scripts/ensure-prisma-runtime-sourcemaps.mjs +42 -0
- package/scripts/integration-database-global-setup.mjs +30 -0
- package/src/application/ApplicationRequestError.ts +12 -0
- package/src/application/auth/AuthenticatedPrincipal.ts +5 -0
- package/src/application/auth/SessionVerifier.ts +5 -0
- package/src/application/binary/OverlayPinnedBinaryUploadService.ts +119 -0
- package/src/application/binary/RunBinaryAttachmentLookupService.ts +139 -0
- package/src/application/binary/RunStateBinaryStorageKeysCollector.ts +57 -0
- package/src/application/bus/Command.ts +3 -0
- package/src/application/bus/CommandBus.ts +5 -0
- package/src/application/bus/CommandHandler.ts +5 -0
- package/src/application/bus/DomainEvent.ts +1 -0
- package/src/application/bus/DomainEventBus.ts +5 -0
- package/src/application/bus/DomainEventHandler.ts +5 -0
- package/src/application/bus/Query.ts +3 -0
- package/src/application/bus/QueryBus.ts +5 -0
- package/src/application/bus/QueryHandler.ts +5 -0
- package/src/application/commands/AcceptUserInviteCommand.ts +10 -0
- package/src/application/commands/AcceptUserInviteCommandHandler.ts +19 -0
- package/src/application/commands/CopyRunToWorkflowDebuggerCommand.ts +14 -0
- package/src/application/commands/CopyRunToWorkflowDebuggerCommandHandler.ts +56 -0
- package/src/application/commands/CreateCredentialInstanceCommand.ts +9 -0
- package/src/application/commands/CreateCredentialInstanceCommandHandler.ts +28 -0
- package/src/application/commands/CredentialCommandHandlers.ts +10 -0
- package/src/application/commands/DeleteCredentialInstanceCommand.ts +7 -0
- package/src/application/commands/DeleteCredentialInstanceCommandHandler.ts +27 -0
- package/src/application/commands/HandleWebhookInvocationCommand.ts +12 -0
- package/src/application/commands/HandleWebhookInvocationCommandHandler.ts +42 -0
- package/src/application/commands/InviteUserCommand.ts +12 -0
- package/src/application/commands/InviteUserCommandHandler.ts +22 -0
- package/src/application/commands/RegenerateUserInviteCommand.ts +12 -0
- package/src/application/commands/RegenerateUserInviteCommandHandler.ts +24 -0
- package/src/application/commands/ReplaceMutableRunWorkflowSnapshotCommand.ts +12 -0
- package/src/application/commands/ReplaceMutableRunWorkflowSnapshotCommandHandler.ts +47 -0
- package/src/application/commands/ReplaceWorkflowDebuggerOverlayCommand.ts +14 -0
- package/src/application/commands/ReplaceWorkflowDebuggerOverlayCommandHandler.ts +35 -0
- package/src/application/commands/ReplayWorkflowNodeCommand.ts +12 -0
- package/src/application/commands/ReplayWorkflowNodeCommandHandler.ts +164 -0
- package/src/application/commands/SetPinnedNodeInputCommand.ts +13 -0
- package/src/application/commands/SetPinnedNodeInputCommandHandler.ts +50 -0
- package/src/application/commands/SetWorkflowActivationCommand.ts +10 -0
- package/src/application/commands/SetWorkflowActivationCommandHandler.ts +39 -0
- package/src/application/commands/StartWorkflowRunCommand.ts +8 -0
- package/src/application/commands/StartWorkflowRunCommandHandler.ts +286 -0
- package/src/application/commands/TestCredentialInstanceCommand.ts +9 -0
- package/src/application/commands/TestCredentialInstanceCommandHandler.ts +28 -0
- package/src/application/commands/UpdateCredentialInstanceCommand.ts +12 -0
- package/src/application/commands/UpdateCredentialInstanceCommandHandler.ts +28 -0
- package/src/application/commands/UpdateUserAccountStatusCommand.ts +12 -0
- package/src/application/commands/UpdateUserAccountStatusCommandHandler.ts +24 -0
- package/src/application/commands/UploadOverlayPinnedBinaryCommand.ts +16 -0
- package/src/application/commands/UploadOverlayPinnedBinaryCommandHandler.ts +31 -0
- package/src/application/commands/UpsertCredentialBindingCommand.ts +11 -0
- package/src/application/commands/UpsertCredentialBindingCommandHandler.ts +28 -0
- package/src/application/commands/UpsertLocalBootstrapUserCommand.ts +12 -0
- package/src/application/commands/UpsertLocalBootstrapUserCommandHandler.ts +24 -0
- package/src/application/commands/UserAccountCommandHandlers.ts +10 -0
- package/src/application/contracts/CredentialContractsRegistry.ts +88 -0
- package/src/application/contracts/RunContracts.ts +41 -0
- package/src/application/contracts/WorkflowDebuggerContracts.ts +12 -0
- package/src/application/contracts/WorkflowViewContracts.ts +40 -0
- package/src/application/contracts/WorkflowWebsocketMessage.ts +8 -0
- package/src/application/contracts/userDirectoryContracts.types.ts +60 -0
- package/src/application/dev/BootRuntimeSnapshotHolder.ts +19 -0
- package/src/application/dev/BootRuntimeSummary.types.ts +11 -0
- package/src/application/dev/DevBootstrapSummaryAssembler.ts +84 -0
- package/src/application/dev/DevBootstrapSummaryJson.types.ts +9 -0
- package/src/application/logging/LogFilter.ts +7 -0
- package/src/application/logging/Logger.ts +10 -0
- package/src/application/mapping/DataMapper.ts +3 -0
- package/src/application/mapping/WorkflowDefinitionMapper.ts +171 -0
- package/src/application/mapping/WorkflowPolicyUiPresentationFactory.ts +39 -0
- package/src/application/queries/CredentialQueryHandlers.ts +12 -0
- package/src/application/queries/GetCredentialFieldEnvStatusQuery.ts +5 -0
- package/src/application/queries/GetCredentialFieldEnvStatusQueryHandler.ts +52 -0
- package/src/application/queries/GetCredentialInstanceQuery.ts +9 -0
- package/src/application/queries/GetCredentialInstanceQueryHandler.ts +27 -0
- package/src/application/queries/GetCredentialInstanceWithSecretsQuery.ts +9 -0
- package/src/application/queries/GetCredentialInstanceWithSecretsQueryHandler.ts +27 -0
- package/src/application/queries/GetRunBinaryAttachmentQuery.ts +11 -0
- package/src/application/queries/GetRunBinaryAttachmentQueryHandler.ts +23 -0
- package/src/application/queries/GetRunStateQuery.ts +8 -0
- package/src/application/queries/GetRunStateQueryHandler.ts +21 -0
- package/src/application/queries/GetWorkflowCredentialHealthQuery.ts +9 -0
- package/src/application/queries/GetWorkflowCredentialHealthQueryHandler.ts +27 -0
- package/src/application/queries/GetWorkflowDebuggerOverlayQuery.ts +8 -0
- package/src/application/queries/GetWorkflowDebuggerOverlayQueryHandler.ts +28 -0
- package/src/application/queries/GetWorkflowDetailQuery.ts +8 -0
- package/src/application/queries/GetWorkflowDetailQueryHandler.ts +24 -0
- package/src/application/queries/GetWorkflowOverlayBinaryAttachmentQuery.ts +11 -0
- package/src/application/queries/GetWorkflowOverlayBinaryAttachmentQueryHandler.ts +23 -0
- package/src/application/queries/GetWorkflowSummariesQuery.ts +4 -0
- package/src/application/queries/GetWorkflowSummariesQueryHandler.ts +23 -0
- package/src/application/queries/ListCredentialInstancesQuery.ts +5 -0
- package/src/application/queries/ListCredentialInstancesQueryHandler.ts +27 -0
- package/src/application/queries/ListCredentialTypesQuery.ts +5 -0
- package/src/application/queries/ListCredentialTypesQueryHandler.ts +28 -0
- package/src/application/queries/ListUserAccountsQuery.ts +5 -0
- package/src/application/queries/ListUserAccountsQueryHandler.ts +22 -0
- package/src/application/queries/ListWorkflowRunsQuery.ts +8 -0
- package/src/application/queries/ListWorkflowRunsQueryHandler.ts +21 -0
- package/src/application/queries/UserAccountQueryHandlers.ts +4 -0
- package/src/application/queries/VerifyUserInviteQuery.ts +9 -0
- package/src/application/queries/VerifyUserInviteQueryHandler.ts +21 -0
- package/src/application/runs/WorkflowRunRetentionPruneScheduler.ts +98 -0
- package/src/application/websocket/WorkflowRunEventWebsocketRelay.ts +36 -0
- package/src/application/websocket/WorkflowWebsocketPublisher.ts +5 -0
- package/src/application/workflows/WebhookEndpointPathValidator.ts +35 -0
- package/src/application/workflows/WorkflowDebuggerOverlayStateFactory.ts +122 -0
- package/src/applicationTokens.ts +72 -0
- package/src/bootstrap/CodemationBootstrapRequest.ts +27 -0
- package/src/bootstrap/CodemationContainerFactory.ts +310 -0
- package/src/bootstrap/CodemationContainerRegistration.ts +23 -0
- package/src/bootstrap/CodemationContainerRegistrationRegistrar.ts +42 -0
- package/src/bootstrap/CodemationFrontendBootstrapRequest.ts +16 -0
- package/src/bootstrap/CodemationWorkerBootstrapRequest.ts +19 -0
- package/src/bootstrap/PreparedCodemationRuntime.ts +37 -0
- package/src/bootstrap/PreparedCodemationRuntimeFactory.ts +308 -0
- package/src/bootstrap/boot/CliRuntimeBootService.ts +27 -0
- package/src/bootstrap/boot/FrontendRuntimeBootService.ts +86 -0
- package/src/bootstrap/boot/WorkerRuntimeBootService.ts +64 -0
- package/src/bootstrap/runtime/AppConfigFactory.ts +57 -0
- package/src/bootstrap/runtime/ResolvedImplementationSelectionFactory.ts +118 -0
- package/src/client.ts +3 -0
- package/src/codemationApplication.ts +311 -0
- package/src/consumer.ts +4 -0
- package/src/credentials.ts +24 -0
- package/src/devServerSidecar.ts +10 -0
- package/src/domain/credentials/CredentialBindingService.ts +139 -0
- package/src/domain/credentials/CredentialFieldEnvOverlayService.ts +60 -0
- package/src/domain/credentials/CredentialInstanceService.ts +391 -0
- package/src/domain/credentials/CredentialMaterialResolver.ts +55 -0
- package/src/domain/credentials/CredentialRuntimeMaterialService.ts +39 -0
- package/src/domain/credentials/CredentialSecretCipher.ts +70 -0
- package/src/domain/credentials/CredentialServices.ts +145 -0
- package/src/domain/credentials/CredentialSessionServiceImpl.ts +119 -0
- package/src/domain/credentials/CredentialTestService.ts +73 -0
- package/src/domain/credentials/CredentialTypeRegistryImpl.ts +29 -0
- package/src/domain/credentials/OAuth2ConnectServiceFactory.ts +396 -0
- package/src/domain/credentials/OAuth2ProviderRegistry.ts +75 -0
- package/src/domain/credentials/WorkflowCredentialNodeResolver.ts +246 -0
- package/src/domain/runs/WorkflowRunRepository.ts +11 -0
- package/src/domain/users/UserAccountServiceRegistry.ts +315 -0
- package/src/domain/users/userLoginMethodLabels.types.ts +29 -0
- package/src/domain/workflows/WorkflowActivationPreflight.ts +32 -0
- package/src/domain/workflows/WorkflowActivationPreflightRules.ts +77 -0
- package/src/domain/workflows/WorkflowActivationRepository.ts +9 -0
- package/src/domain/workflows/WorkflowDebuggerOverlayRepository.ts +7 -0
- package/src/domain/workflows/WorkflowDebuggerOverlayState.ts +8 -0
- package/src/domain/workflows/WorkflowDefinitionRepository.ts +11 -0
- package/src/index.ts +58 -0
- package/src/infrastructure/auth/AuthJsSessionVerifier.ts +26 -0
- package/src/infrastructure/auth/DevelopmentSessionBypassVerifier.ts +12 -0
- package/src/infrastructure/binary/BinaryBodyNodeReadableFactory.ts +22 -0
- package/src/infrastructure/binary/CountingSha256Transform.ts +26 -0
- package/src/infrastructure/binary/LocalFilesystemBinaryStorageRegistry.ts +86 -0
- package/src/infrastructure/config/CodemationPluginRegistrar.ts +44 -0
- package/src/infrastructure/credentials/FrameworkBuiltinCredentialTypesRegistrar.ts +21 -0
- package/src/infrastructure/credentials/OpenAiApiKeyCredentialHealthTester.ts +89 -0
- package/src/infrastructure/credentials/OpenAiApiKeyCredentialShapes.types.ts +15 -0
- package/src/infrastructure/credentials/OpenAiApiKeyCredentialTypeFactory.ts +47 -0
- package/src/infrastructure/di/HandlesCommandRegistry.ts +24 -0
- package/src/infrastructure/di/HandlesDomainEventRegistry.ts +24 -0
- package/src/infrastructure/di/HandlesQueryRegistry.ts +24 -0
- package/src/infrastructure/di/InMemoryCommandBus.ts +47 -0
- package/src/infrastructure/di/InMemoryDomainEventBus.ts +47 -0
- package/src/infrastructure/di/InMemoryQueryBus.ts +45 -0
- package/src/infrastructure/ids/CodemationIdFactory.ts +12 -0
- package/src/infrastructure/logging/BrowserLogger.ts +1 -0
- package/src/infrastructure/logging/BrowserLoggerFactory.ts +14 -0
- package/src/infrastructure/logging/ConsoleLogger.ts +41 -0
- package/src/infrastructure/logging/FilteringLogger.ts +38 -0
- package/src/infrastructure/logging/LogLevelPolicy.ts +148 -0
- package/src/infrastructure/logging/LogLevelPolicyFactory.ts +16 -0
- package/src/infrastructure/logging/PerformanceLogPolicy.ts +10 -0
- package/src/infrastructure/logging/PerformanceLogPolicyFactory.ts +14 -0
- package/src/infrastructure/logging/ServerLogger.ts +1 -0
- package/src/infrastructure/logging/ServerLoggerFactory.ts +28 -0
- package/src/infrastructure/persistence/CodemationPostgresPrismaClientFactory.ts +9 -0
- package/src/infrastructure/persistence/CredentialPersistenceStore.ts +139 -0
- package/src/infrastructure/persistence/DatabasePersistenceResolver.ts +91 -0
- package/src/infrastructure/persistence/InMemoryTriggerSetupStateRepository.ts +23 -0
- package/src/infrastructure/persistence/InMemoryWorkflowActivationRepository.ts +18 -0
- package/src/infrastructure/persistence/InMemoryWorkflowDebuggerOverlayRepository.ts +16 -0
- package/src/infrastructure/persistence/InMemoryWorkflowRunRepository.ts +94 -0
- package/src/infrastructure/persistence/PrismaClientFactory.ts +26 -0
- package/src/infrastructure/persistence/PrismaCredentialStore.ts +368 -0
- package/src/infrastructure/persistence/PrismaMigrationDeployer.ts +184 -0
- package/src/infrastructure/persistence/PrismaTriggerSetupStateRepository.ts +68 -0
- package/src/infrastructure/persistence/PrismaWorkflowActivationRepository.ts +36 -0
- package/src/infrastructure/persistence/PrismaWorkflowDebuggerOverlayRepository.ts +65 -0
- package/src/infrastructure/persistence/PrismaWorkflowRunRepository.ts +243 -0
- package/src/infrastructure/persistence/RuntimeWorkflowActivationPolicy.ts +27 -0
- package/src/infrastructure/persistence/SchedulerPersistenceCompatibilityValidator.ts +20 -0
- package/src/infrastructure/persistence/WorkflowDefinitionRepositoryAdapter.ts +31 -0
- package/src/infrastructure/persistence/WorkflowRunRepository.ts +46 -0
- package/src/infrastructure/persistence/generated/prisma/client.d.ts +1 -0
- package/src/infrastructure/persistence/generated/prisma/default.d.ts +1 -0
- package/src/infrastructure/persistence/generated/prisma/edge.d.ts +1 -0
- package/src/infrastructure/persistence/generated/prisma/index.d.ts +4766 -0
- package/src/infrastructure/persistence/generated/prisma/package.json +144 -0
- package/src/infrastructure/persistence/generated/prisma/query_compiler_fast_bg.wasm +0 -0
- package/src/infrastructure/persistence/generated/prisma/runtime/client.d.ts +3358 -0
- package/src/infrastructure/persistence/generated/prisma/runtime/index-browser.d.ts +90 -0
- package/src/infrastructure/persistence/generated/prisma/schema.prisma +35 -0
- package/src/infrastructure/persistence/generated/prisma/wasm-edge-light-loader.mjs +5 -0
- package/src/infrastructure/persistence/generated/prisma/wasm-worker-loader.mjs +5 -0
- package/src/infrastructure/persistence/generated/prisma-client/client.d.ts +1 -0
- package/src/infrastructure/persistence/generated/prisma-client/client.js +5 -0
- package/src/infrastructure/persistence/generated/prisma-client/default.d.ts +1 -0
- package/src/infrastructure/persistence/generated/prisma-client/default.js +5 -0
- package/src/infrastructure/persistence/generated/prisma-client/edge.d.ts +1 -0
- package/src/infrastructure/persistence/generated/prisma-client/edge.js +299 -0
- package/src/infrastructure/persistence/generated/prisma-client/index-browser.js +325 -0
- package/src/infrastructure/persistence/generated/prisma-client/index.d.ts +21623 -0
- package/src/infrastructure/persistence/generated/prisma-client/index.js +299 -0
- package/src/infrastructure/persistence/generated/prisma-client/package.json +144 -0
- package/src/infrastructure/persistence/generated/prisma-client/query_compiler_fast_bg.js +2 -0
- package/src/infrastructure/persistence/generated/prisma-client/query_compiler_fast_bg.wasm +0 -0
- package/src/infrastructure/persistence/generated/prisma-client/query_compiler_fast_bg.wasm-base64.js +2 -0
- package/src/infrastructure/persistence/generated/prisma-client/runtime/client.d.ts +3358 -0
- package/src/infrastructure/persistence/generated/prisma-client/runtime/client.js +86 -0
- package/src/infrastructure/persistence/generated/prisma-client/runtime/client.js.map +1 -0
- package/src/infrastructure/persistence/generated/prisma-client/runtime/index-browser.d.ts +90 -0
- package/src/infrastructure/persistence/generated/prisma-client/runtime/index-browser.js +6 -0
- package/src/infrastructure/persistence/generated/prisma-client/runtime/index-browser.js.map +1 -0
- package/src/infrastructure/persistence/generated/prisma-client/runtime/wasm-compiler-edge.js +76 -0
- package/src/infrastructure/persistence/generated/prisma-client/runtime/wasm-compiler-edge.js.map +1 -0
- package/src/infrastructure/persistence/generated/prisma-client/schema.prisma +179 -0
- package/src/infrastructure/persistence/generated/prisma-client/wasm-edge-light-loader.mjs +5 -0
- package/src/infrastructure/persistence/generated/prisma-client/wasm-worker-loader.mjs +5 -0
- package/src/infrastructure/runtime/LiveWorkflowRepository.ts +14 -0
- package/src/infrastructure/runtime/WorkerRuntimeScheduler.ts +35 -0
- package/src/infrastructure/server/http/ServerHttpRouteParams.ts +1 -0
- package/src/infrastructure/webhooks/RequestToWebhookItemMapper.ts +128 -0
- package/src/nextServer.ts +31 -0
- package/src/persistenceServer.ts +5 -0
- package/src/presentation/config/AppConfig.ts +25 -0
- package/src/presentation/config/CodemationAppContext.ts +19 -0
- package/src/presentation/config/CodemationApplicationFacade.ts +5 -0
- package/src/presentation/config/CodemationAuthConfig.ts +31 -0
- package/src/presentation/config/CodemationClassToken.ts +3 -0
- package/src/presentation/config/CodemationConfig.ts +86 -0
- package/src/presentation/config/CodemationConfigNormalizer.ts +179 -0
- package/src/presentation/config/CodemationLogConfig.ts +22 -0
- package/src/presentation/config/CodemationPackageManifest.ts +9 -0
- package/src/presentation/config/CodemationPlugin.ts +20 -0
- package/src/presentation/config/CodemationPluginListMerger.ts +46 -0
- package/src/presentation/config/CodemationWhitelabelConfig.ts +9 -0
- package/src/presentation/config/CodemationWorkflowDiscovery.ts +3 -0
- package/src/presentation/http/ApiPaths.ts +165 -0
- package/src/presentation/http/CodemationServerGatewayFactory.ts +120 -0
- package/src/presentation/http/HttpRequestJsonBodyReader.ts +12 -0
- package/src/presentation/http/ServerHttpErrorResponseFactory.ts +33 -0
- package/src/presentation/http/ServerHttpRouteParams.ts +1 -0
- package/src/presentation/http/hono/CodemationHonoApiAppFactory.ts +64 -0
- package/src/presentation/http/hono/HonoApiRouteRegistrar.ts +5 -0
- package/src/presentation/http/hono/HonoHttpAnonymousRoutePolicyRegistry.ts +27 -0
- package/src/presentation/http/hono/registrars/BinaryHonoApiRouteRegistrar.ts +21 -0
- package/src/presentation/http/hono/registrars/CredentialHonoApiRouteRegistrar.ts +34 -0
- package/src/presentation/http/hono/registrars/DevHonoApiRouteRegistrar.ts +17 -0
- package/src/presentation/http/hono/registrars/OAuth2HonoApiRouteRegistrar.ts +18 -0
- package/src/presentation/http/hono/registrars/RunHonoApiRouteRegistrar.ts +31 -0
- package/src/presentation/http/hono/registrars/UserHonoApiRouteRegistrar.ts +24 -0
- package/src/presentation/http/hono/registrars/WebhookHonoApiRouteRegistrar.ts +23 -0
- package/src/presentation/http/hono/registrars/WhitelabelHonoApiRouteRegistrar.ts +18 -0
- package/src/presentation/http/hono/registrars/WorkflowHonoApiRouteRegistrar.ts +33 -0
- package/src/presentation/http/routeHandlers/BinaryHttpRouteHandlerFactory.ts +101 -0
- package/src/presentation/http/routeHandlers/CredentialHttpRouteHandler.ts +129 -0
- package/src/presentation/http/routeHandlers/DevBootstrapSummaryHttpRouteHandler.ts +21 -0
- package/src/presentation/http/routeHandlers/OAuth2HttpRouteHandlerFactory.ts +129 -0
- package/src/presentation/http/routeHandlers/RunHttpRouteHandler.ts +82 -0
- package/src/presentation/http/routeHandlers/UserHttpRouteHandlerFactory.ts +109 -0
- package/src/presentation/http/routeHandlers/WebhookHttpRouteHandler.ts +42 -0
- package/src/presentation/http/routeHandlers/WhitelabelLogoHttpRouteHandler.ts +96 -0
- package/src/presentation/http/routeHandlers/WorkflowHttpRouteHandler.ts +104 -0
- package/src/presentation/server/CodemationConsumerAppResolver.ts +82 -0
- package/src/presentation/server/CodemationConsumerConfigExportsResolver.ts +33 -0
- package/src/presentation/server/CodemationConsumerConfigLoader.ts +270 -0
- package/src/presentation/server/CodemationPluginDiscovery.ts +151 -0
- package/src/presentation/server/CodemationTsyringeParamInfoReader.ts +26 -0
- package/src/presentation/server/CodemationTsyringeTypeInfoRegistrar.ts +121 -0
- package/src/presentation/server/DevelopmentRuntimeRouteGuard.ts +59 -0
- package/src/presentation/server/DiscoveredWorkflowsEmptyMessageFactory.ts +11 -0
- package/src/presentation/server/WorkflowDefinitionExportsResolver.ts +24 -0
- package/src/presentation/server/WorkflowDiscoveryPathSegmentsComputer.ts +53 -0
- package/src/presentation/server/WorkflowModulePathFinder.ts +47 -0
- package/src/presentation/websocket/WorkflowWebsocketServer.ts +169 -0
- package/src/server.ts +14 -0
- package/tsconfig.json +10 -0
- package/vitest.shared.ts +45 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import type { WorkflowCredentialHealthDto } from "../../application/contracts/CredentialContractsRegistry";
|
|
2
|
+
import { getPersistedRuntimeTypeMetadata, injectable, type WorkflowDefinition } from "@codemation/core";
|
|
3
|
+
import { MissingRuntimeTriggerToken } from "@codemation/core/bootstrap";
|
|
4
|
+
import { ManualTriggerNode } from "@codemation/core-nodes";
|
|
5
|
+
|
|
6
|
+
@injectable()
|
|
7
|
+
export class WorkflowActivationPreflightRules {
|
|
8
|
+
private readonly manualTriggerTypeName: string;
|
|
9
|
+
private readonly missingRuntimeTriggerTypeName: string;
|
|
10
|
+
|
|
11
|
+
constructor() {
|
|
12
|
+
this.manualTriggerTypeName = this.resolveRuntimeTypeTokenName(ManualTriggerNode);
|
|
13
|
+
this.missingRuntimeTriggerTypeName = this.resolveRuntimeTypeTokenName(MissingRuntimeTriggerToken);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Compare node runtime tokens by persisted decorator name (and constructor name fallback).
|
|
18
|
+
* Reference equality breaks when the host and consumer workflow each load a separate copy of
|
|
19
|
+
* `@codemation/core-nodes` (duplicate class identity for the same logical trigger type).
|
|
20
|
+
*/
|
|
21
|
+
private resolveRuntimeTypeTokenName(token: unknown): string {
|
|
22
|
+
const meta = getPersistedRuntimeTypeMetadata(token);
|
|
23
|
+
if (meta) {
|
|
24
|
+
return meta.persistedName;
|
|
25
|
+
}
|
|
26
|
+
if (typeof token === "function") {
|
|
27
|
+
return (token as { name?: string }).name ?? "";
|
|
28
|
+
}
|
|
29
|
+
return "";
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
private isManualTriggerType(token: unknown): boolean {
|
|
33
|
+
return this.resolveRuntimeTypeTokenName(token) === this.manualTriggerTypeName;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
private isMissingRuntimeTriggerType(token: unknown): boolean {
|
|
37
|
+
return this.resolveRuntimeTypeTokenName(token) === this.missingRuntimeTriggerTypeName;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
collectNonManualTriggerErrors(workflow: WorkflowDefinition): ReadonlyArray<string> {
|
|
41
|
+
const triggerNodes = workflow.nodes.filter((n) => n.kind === "trigger");
|
|
42
|
+
const hasActivatable = triggerNodes.some(
|
|
43
|
+
(n) => !this.isManualTriggerType(n.type) && !this.isMissingRuntimeTriggerType(n.type),
|
|
44
|
+
);
|
|
45
|
+
if (hasActivatable) {
|
|
46
|
+
return [];
|
|
47
|
+
}
|
|
48
|
+
if (triggerNodes.length === 0) {
|
|
49
|
+
return ["This workflow has no trigger node. Add a non-manual trigger (for example a webhook) before activating."];
|
|
50
|
+
}
|
|
51
|
+
const onlyManual = triggerNodes.every((n) => this.isManualTriggerType(n.type));
|
|
52
|
+
if (onlyManual) {
|
|
53
|
+
return [
|
|
54
|
+
"This workflow only has a manual run trigger. Add a non-manual trigger (for example a webhook) before activating.",
|
|
55
|
+
];
|
|
56
|
+
}
|
|
57
|
+
return [
|
|
58
|
+
"This workflow has no usable automatic trigger (the configured trigger may be missing or invalid). Fix the trigger before activating.",
|
|
59
|
+
];
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
collectRequiredCredentialErrors(health: WorkflowCredentialHealthDto): ReadonlyArray<string> {
|
|
63
|
+
const lines: string[] = [];
|
|
64
|
+
for (const slot of health.slots) {
|
|
65
|
+
if (slot.requirement.optional) {
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
if (slot.health.status === "unbound") {
|
|
69
|
+
const nodeLabel = slot.nodeName ?? slot.nodeId;
|
|
70
|
+
lines.push(
|
|
71
|
+
`Required credential "${slot.requirement.label}" (${slot.requirement.slotKey}) on "${nodeLabel}" is not bound.`,
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return lines;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type WorkflowActivationRow = Readonly<{
|
|
2
|
+
workflowId: string;
|
|
3
|
+
isActive: boolean;
|
|
4
|
+
}>;
|
|
5
|
+
|
|
6
|
+
export interface WorkflowActivationRepository {
|
|
7
|
+
loadAll(): Promise<ReadonlyArray<WorkflowActivationRow>>;
|
|
8
|
+
upsert(workflowId: string, active: boolean): Promise<void>;
|
|
9
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { WorkflowDebuggerOverlayState } from "./WorkflowDebuggerOverlayState";
|
|
2
|
+
|
|
3
|
+
export interface WorkflowDebuggerOverlayRepository {
|
|
4
|
+
load(workflowId: string): Promise<WorkflowDebuggerOverlayState | undefined>;
|
|
5
|
+
|
|
6
|
+
save(state: WorkflowDebuggerOverlayState): Promise<void>;
|
|
7
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { WorkflowDefinition } from "@codemation/core";
|
|
2
|
+
|
|
3
|
+
export interface WorkflowDefinitionRepository {
|
|
4
|
+
listDefinitions(): Promise<ReadonlyArray<WorkflowDefinition>>;
|
|
5
|
+
|
|
6
|
+
getDefinition(workflowId: string): Promise<WorkflowDefinition | undefined>;
|
|
7
|
+
|
|
8
|
+
resolveSnapshot(
|
|
9
|
+
args: Readonly<{ workflowId: string; workflowSnapshot?: unknown }>,
|
|
10
|
+
): Promise<WorkflowDefinition | undefined>;
|
|
11
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
export type { CommandBus } from "./application/bus/CommandBus";
|
|
2
|
+
export type { QueryBus } from "./application/bus/QueryBus";
|
|
3
|
+
export { ListUserAccountsQuery } from "./application/queries/ListUserAccountsQuery";
|
|
4
|
+
export { UpsertLocalBootstrapUserCommand } from "./application/commands/UpsertLocalBootstrapUserCommand";
|
|
5
|
+
export type { UpsertLocalBootstrapUserResultDto } from "./application/contracts/userDirectoryContracts.types";
|
|
6
|
+
export { CodemationApplication } from "./codemationApplication";
|
|
7
|
+
export type { CodemationApplicationConfig, CodemationStopHandle } from "./codemationApplication";
|
|
8
|
+
export { ApplicationTokens } from "./applicationTokens";
|
|
9
|
+
export { CodemationBootstrapRequest } from "./bootstrap/CodemationBootstrapRequest";
|
|
10
|
+
export { CodemationFrontendBootstrapRequest } from "./bootstrap/CodemationFrontendBootstrapRequest";
|
|
11
|
+
export { CodemationWorkerBootstrapRequest } from "./bootstrap/CodemationWorkerBootstrapRequest";
|
|
12
|
+
export type { CodemationWhitelabelConfig } from "./presentation/config/CodemationWhitelabelConfig";
|
|
13
|
+
export type { AppConfig } from "./presentation/config/AppConfig";
|
|
14
|
+
export type { CodemationApplicationFacade } from "./presentation/config/CodemationApplicationFacade";
|
|
15
|
+
export type {
|
|
16
|
+
CodemationAuthConfig,
|
|
17
|
+
CodemationAuthKind,
|
|
18
|
+
CodemationAuthOAuthProviderConfig,
|
|
19
|
+
CodemationAuthOidcProviderConfig,
|
|
20
|
+
} from "./presentation/config/CodemationAuthConfig";
|
|
21
|
+
export type { CodemationClassToken } from "./presentation/config/CodemationClassToken";
|
|
22
|
+
export type {
|
|
23
|
+
CodemationAppDefinition,
|
|
24
|
+
CodemationAppSchedulerConfig,
|
|
25
|
+
CodemationAppSchedulerKind,
|
|
26
|
+
CodemationApplicationRuntimeConfig,
|
|
27
|
+
CodemationConfig,
|
|
28
|
+
CodemationDatabaseConfig,
|
|
29
|
+
CodemationDatabaseKind,
|
|
30
|
+
CodemationEngineExecutionLimitsConfig,
|
|
31
|
+
CodemationEventBusConfig,
|
|
32
|
+
CodemationEventBusKind,
|
|
33
|
+
CodemationSchedulerConfig,
|
|
34
|
+
CodemationSchedulerKind,
|
|
35
|
+
} from "./presentation/config/CodemationConfig";
|
|
36
|
+
export type {
|
|
37
|
+
CodemationAppContext,
|
|
38
|
+
CodemationRegistrationContextBase,
|
|
39
|
+
} from "./presentation/config/CodemationAppContext";
|
|
40
|
+
export type {
|
|
41
|
+
CodemationLogConfig,
|
|
42
|
+
CodemationLogLevelName,
|
|
43
|
+
CodemationLogRule,
|
|
44
|
+
} from "./presentation/config/CodemationLogConfig";
|
|
45
|
+
export type {
|
|
46
|
+
CodemationPackageManifest,
|
|
47
|
+
CodemationPluginPackageManifest,
|
|
48
|
+
} from "./presentation/config/CodemationPackageManifest";
|
|
49
|
+
export type { CodemationPlugin, CodemationPluginContext } from "./presentation/config/CodemationPlugin";
|
|
50
|
+
export { CodemationPluginListMerger } from "./presentation/config/CodemationPluginListMerger";
|
|
51
|
+
export type { CodemationWorkflowDiscovery } from "./presentation/config/CodemationWorkflowDiscovery";
|
|
52
|
+
export {
|
|
53
|
+
ApiPaths,
|
|
54
|
+
CodemationConsumerConfigLoader,
|
|
55
|
+
CodemationPostgresPrismaClientFactory,
|
|
56
|
+
CodemationServerGateway,
|
|
57
|
+
PrismaClient,
|
|
58
|
+
} from "./server";
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { getToken } from "@auth/core/jwt";
|
|
2
|
+
import type { AuthenticatedPrincipal } from "../../application/auth/AuthenticatedPrincipal";
|
|
3
|
+
import type { SessionVerifier } from "../../application/auth/SessionVerifier";
|
|
4
|
+
|
|
5
|
+
export class AuthJsSessionVerifier implements SessionVerifier {
|
|
6
|
+
constructor(private readonly authSecret: string) {}
|
|
7
|
+
|
|
8
|
+
async verify(request: Request): Promise<AuthenticatedPrincipal | null> {
|
|
9
|
+
const requestUrl = new URL(request.url);
|
|
10
|
+
const secureCookie = requestUrl.protocol === "https:";
|
|
11
|
+
const token = await getToken({
|
|
12
|
+
req: request,
|
|
13
|
+
secret: this.authSecret,
|
|
14
|
+
secureCookie,
|
|
15
|
+
salt: "authjs.session-token",
|
|
16
|
+
});
|
|
17
|
+
if (!token?.sub || typeof token.sub !== "string") {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
return {
|
|
21
|
+
id: token.sub,
|
|
22
|
+
email: typeof token.email === "string" ? token.email : null,
|
|
23
|
+
name: typeof token.name === "string" ? token.name : null,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { AuthenticatedPrincipal } from "../../application/auth/AuthenticatedPrincipal";
|
|
2
|
+
import type { SessionVerifier } from "../../application/auth/SessionVerifier";
|
|
3
|
+
|
|
4
|
+
export class DevelopmentSessionBypassVerifier implements SessionVerifier {
|
|
5
|
+
async verify(): Promise<AuthenticatedPrincipal | null> {
|
|
6
|
+
return {
|
|
7
|
+
id: "codemation-development-bypass",
|
|
8
|
+
email: "development@codemation.local",
|
|
9
|
+
name: "Development bypass user",
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Readable } from "node:stream";
|
|
2
|
+
|
|
3
|
+
import { ReadableStream } from "node:stream/web";
|
|
4
|
+
|
|
5
|
+
import type { BinaryBody } from "@codemation/core";
|
|
6
|
+
|
|
7
|
+
export class BinaryBodyNodeReadableFactory {
|
|
8
|
+
constructor(private readonly body: BinaryBody) {}
|
|
9
|
+
|
|
10
|
+
create(): Readable {
|
|
11
|
+
if (this.body instanceof Uint8Array) {
|
|
12
|
+
return Readable.from([this.body]);
|
|
13
|
+
}
|
|
14
|
+
if (this.body instanceof ArrayBuffer) {
|
|
15
|
+
return Readable.from([new Uint8Array(this.body)]);
|
|
16
|
+
}
|
|
17
|
+
if (this.body instanceof ReadableStream) {
|
|
18
|
+
return Readable.fromWeb(this.body);
|
|
19
|
+
}
|
|
20
|
+
return Readable.from(this.body);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
|
|
3
|
+
import { Transform } from "node:stream";
|
|
4
|
+
|
|
5
|
+
export class CountingSha256Transform extends Transform {
|
|
6
|
+
private readonly hash = createHash("sha256");
|
|
7
|
+
private byteCount = 0;
|
|
8
|
+
|
|
9
|
+
get size(): number {
|
|
10
|
+
return this.byteCount;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
get sha256(): string {
|
|
14
|
+
return this.hash.digest("hex");
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
override _transform(
|
|
18
|
+
chunk: Buffer,
|
|
19
|
+
_encoding: BufferEncoding,
|
|
20
|
+
callback: (error?: Error | null, data?: Buffer) => void,
|
|
21
|
+
): void {
|
|
22
|
+
this.byteCount += chunk.byteLength;
|
|
23
|
+
this.hash.update(chunk);
|
|
24
|
+
callback(null, chunk);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { createReadStream, createWriteStream } from "node:fs";
|
|
2
|
+
|
|
3
|
+
import { mkdir, rm, stat } from "node:fs/promises";
|
|
4
|
+
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
|
|
7
|
+
import { Readable } from "node:stream";
|
|
8
|
+
|
|
9
|
+
import { ReadableStream } from "node:stream/web";
|
|
10
|
+
|
|
11
|
+
import { pipeline } from "node:stream/promises";
|
|
12
|
+
|
|
13
|
+
import type {
|
|
14
|
+
BinaryBody,
|
|
15
|
+
BinaryStorage,
|
|
16
|
+
BinaryStorageReadResult,
|
|
17
|
+
BinaryStorageStatResult,
|
|
18
|
+
BinaryStorageWriteResult,
|
|
19
|
+
} from "@codemation/core";
|
|
20
|
+
|
|
21
|
+
import { BinaryBodyNodeReadableFactory } from "./BinaryBodyNodeReadableFactory";
|
|
22
|
+
import { CountingSha256Transform } from "./CountingSha256Transform";
|
|
23
|
+
|
|
24
|
+
export class LocalFilesystemBinaryStorage implements BinaryStorage {
|
|
25
|
+
readonly driverName = "filesystem";
|
|
26
|
+
|
|
27
|
+
constructor(private readonly baseDirectory: string) {}
|
|
28
|
+
|
|
29
|
+
async write(args: { storageKey: string; body: BinaryBody }): Promise<BinaryStorageWriteResult> {
|
|
30
|
+
const targetPath = this.resolveAbsolutePath(args.storageKey);
|
|
31
|
+
await mkdir(path.dirname(targetPath), { recursive: true });
|
|
32
|
+
const readable = new BinaryBodyNodeReadableFactory(args.body).create();
|
|
33
|
+
const countingTransform = new CountingSha256Transform();
|
|
34
|
+
const writable = createWriteStream(targetPath);
|
|
35
|
+
await pipeline(readable, countingTransform, writable);
|
|
36
|
+
return {
|
|
37
|
+
storageKey: args.storageKey,
|
|
38
|
+
size: countingTransform.size,
|
|
39
|
+
sha256: countingTransform.sha256,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async openReadStream(storageKey: string): Promise<BinaryStorageReadResult | undefined> {
|
|
44
|
+
const targetPath = this.resolveAbsolutePath(storageKey);
|
|
45
|
+
try {
|
|
46
|
+
const fileStat = await stat(targetPath);
|
|
47
|
+
return {
|
|
48
|
+
body: Readable.toWeb(createReadStream(targetPath)) as ReadableStream<Uint8Array>,
|
|
49
|
+
size: fileStat.size,
|
|
50
|
+
};
|
|
51
|
+
} catch {
|
|
52
|
+
return undefined;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async stat(storageKey: string): Promise<BinaryStorageStatResult> {
|
|
57
|
+
const targetPath = this.resolveAbsolutePath(storageKey);
|
|
58
|
+
try {
|
|
59
|
+
const fileStat = await stat(targetPath);
|
|
60
|
+
return {
|
|
61
|
+
exists: true,
|
|
62
|
+
size: fileStat.size,
|
|
63
|
+
};
|
|
64
|
+
} catch {
|
|
65
|
+
return {
|
|
66
|
+
exists: false,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
async delete(storageKey: string): Promise<void> {
|
|
72
|
+
await rm(this.resolveAbsolutePath(storageKey), { force: true });
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
private resolveAbsolutePath(storageKey: string): string {
|
|
76
|
+
const absoluteBaseDirectory = path.resolve(this.baseDirectory);
|
|
77
|
+
const targetPath = path.resolve(absoluteBaseDirectory, storageKey);
|
|
78
|
+
if (!targetPath.startsWith(`${absoluteBaseDirectory}${path.sep}`) && targetPath !== absoluteBaseDirectory) {
|
|
79
|
+
throw new Error(`Refused to access binary storage path outside base directory: ${storageKey}`);
|
|
80
|
+
}
|
|
81
|
+
return targetPath;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export { BinaryBodyNodeReadableFactory } from "./BinaryBodyNodeReadableFactory";
|
|
86
|
+
export { CountingSha256Transform } from "./CountingSha256Transform";
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { Container } from "@codemation/core";
|
|
2
|
+
import type { LoggerFactory } from "../../application/logging/Logger";
|
|
3
|
+
import type { AppConfig } from "../../presentation/config/AppConfig";
|
|
4
|
+
import type { CodemationPlugin } from "../../presentation/config/CodemationPlugin";
|
|
5
|
+
import type { AnyCredentialType } from "@codemation/core";
|
|
6
|
+
|
|
7
|
+
export class CodemationPluginRegistrar {
|
|
8
|
+
async apply(
|
|
9
|
+
args: Readonly<{
|
|
10
|
+
plugins: ReadonlyArray<CodemationPlugin>;
|
|
11
|
+
container: Container;
|
|
12
|
+
appConfig: AppConfig;
|
|
13
|
+
registerCredentialType: (type: AnyCredentialType) => void;
|
|
14
|
+
loggerFactory: LoggerFactory;
|
|
15
|
+
}>,
|
|
16
|
+
): Promise<void> {
|
|
17
|
+
for (const plugin of args.plugins) {
|
|
18
|
+
await plugin.register({
|
|
19
|
+
container: args.container,
|
|
20
|
+
appConfig: args.appConfig,
|
|
21
|
+
loggerFactory: args.loggerFactory,
|
|
22
|
+
registerCredentialType: (type) => args.registerCredentialType(type),
|
|
23
|
+
registerNode: (token, implementation) => {
|
|
24
|
+
args.container.register(token, {
|
|
25
|
+
useClass: (implementation ?? token) as never,
|
|
26
|
+
});
|
|
27
|
+
},
|
|
28
|
+
registerValue: (token, value) => {
|
|
29
|
+
args.container.registerInstance(token, value);
|
|
30
|
+
},
|
|
31
|
+
registerClass: (token, implementation) => {
|
|
32
|
+
args.container.register(token, {
|
|
33
|
+
useClass: implementation as never,
|
|
34
|
+
});
|
|
35
|
+
},
|
|
36
|
+
registerFactory: (token, factory) => {
|
|
37
|
+
args.container.register(token, {
|
|
38
|
+
useFactory: (dependencyContainer) => factory(dependencyContainer),
|
|
39
|
+
});
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { CodemationApplication } from "../../codemationApplication";
|
|
2
|
+
import type { CodemationConfig } from "../../presentation/config/CodemationConfig";
|
|
3
|
+
|
|
4
|
+
import type { OpenAiApiKeyCredentialTypeFactory } from "./OpenAiApiKeyCredentialTypeFactory";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Registers framework-owned credential types that ship with the host (OpenAI-compatible API keys, etc.).
|
|
8
|
+
*/
|
|
9
|
+
export class FrameworkBuiltinCredentialTypesRegistrar {
|
|
10
|
+
constructor(private readonly openAiApiKeyCredentialTypeFactory: OpenAiApiKeyCredentialTypeFactory) {}
|
|
11
|
+
|
|
12
|
+
register(application: CodemationApplication, config?: CodemationConfig): void {
|
|
13
|
+
const openAiCredentialType = this.openAiApiKeyCredentialTypeFactory.createCredentialType();
|
|
14
|
+
const openAiProvidedInConsumerConfig =
|
|
15
|
+
config?.credentialTypes?.some((entry) => entry.definition.typeId === openAiCredentialType.definition.typeId) ??
|
|
16
|
+
false;
|
|
17
|
+
if (!openAiProvidedInConsumerConfig) {
|
|
18
|
+
application.registerCredentialType(openAiCredentialType);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import type { CredentialHealth, CredentialSessionFactoryArgs } from "@codemation/core";
|
|
2
|
+
|
|
3
|
+
import type { OpenAiApiKeyMaterial, OpenAiApiKeyPublicConfig } from "./OpenAiApiKeyCredentialShapes.types";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Verifies an OpenAI-compatible API key by calling the provider's models list endpoint
|
|
7
|
+
* (GET `/v1/models` relative to the configured base URL).
|
|
8
|
+
*/
|
|
9
|
+
export class OpenAiApiKeyCredentialHealthTester {
|
|
10
|
+
constructor(private readonly fetchImpl: typeof globalThis.fetch) {}
|
|
11
|
+
|
|
12
|
+
async test(
|
|
13
|
+
args: CredentialSessionFactoryArgs<OpenAiApiKeyPublicConfig, OpenAiApiKeyMaterial>,
|
|
14
|
+
): Promise<CredentialHealth> {
|
|
15
|
+
const testedAt = new Date().toISOString();
|
|
16
|
+
const apiKey = String(args.material.apiKey ?? "").trim();
|
|
17
|
+
if (apiKey.length === 0) {
|
|
18
|
+
return {
|
|
19
|
+
status: "failing",
|
|
20
|
+
message: "OpenAI API key is empty.",
|
|
21
|
+
testedAt,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const modelsUrl = this.resolveModelsListUrl(args.publicConfig.baseUrl);
|
|
26
|
+
|
|
27
|
+
try {
|
|
28
|
+
const response = await this.fetchImpl(modelsUrl, {
|
|
29
|
+
method: "GET",
|
|
30
|
+
headers: {
|
|
31
|
+
Authorization: `Bearer ${apiKey}`,
|
|
32
|
+
},
|
|
33
|
+
signal: AbortSignal.timeout(25_000),
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
if (response.ok) {
|
|
37
|
+
return {
|
|
38
|
+
status: "healthy",
|
|
39
|
+
message: "API key verified against the models endpoint.",
|
|
40
|
+
testedAt,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const message = await this.parseErrorMessage(response);
|
|
45
|
+
return {
|
|
46
|
+
status: "failing",
|
|
47
|
+
message,
|
|
48
|
+
testedAt,
|
|
49
|
+
};
|
|
50
|
+
} catch (error) {
|
|
51
|
+
return {
|
|
52
|
+
status: "failing",
|
|
53
|
+
message: error instanceof Error ? error.message : String(error),
|
|
54
|
+
testedAt,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
private resolveModelsListUrl(baseUrlRaw: unknown): string {
|
|
60
|
+
const defaultBase = "https://api.openai.com/v1";
|
|
61
|
+
const raw = typeof baseUrlRaw === "string" ? baseUrlRaw.trim() : "";
|
|
62
|
+
const base = raw === "" ? defaultBase : raw.replace(/\/+$/, "");
|
|
63
|
+
if (base.endsWith("/models")) {
|
|
64
|
+
return base;
|
|
65
|
+
}
|
|
66
|
+
if (base.endsWith("/v1")) {
|
|
67
|
+
return `${base}/models`;
|
|
68
|
+
}
|
|
69
|
+
return `${base}/v1/models`;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
private async parseErrorMessage(response: Response): Promise<string> {
|
|
73
|
+
const prefix = `HTTP ${response.status}`;
|
|
74
|
+
try {
|
|
75
|
+
const text = await response.text();
|
|
76
|
+
if (text.trim() === "") {
|
|
77
|
+
return prefix;
|
|
78
|
+
}
|
|
79
|
+
const parsed = JSON.parse(text) as { error?: { message?: string } };
|
|
80
|
+
const fromApi = parsed.error?.message;
|
|
81
|
+
if (typeof fromApi === "string" && fromApi.trim() !== "") {
|
|
82
|
+
return `${prefix}: ${fromApi.trim()}`;
|
|
83
|
+
}
|
|
84
|
+
return `${prefix}: ${text.length > 280 ? `${text.slice(0, 280)}…` : text}`;
|
|
85
|
+
} catch {
|
|
86
|
+
return prefix;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed shapes for the `openai.apiKey` credential (public fields, secret material, session object).
|
|
3
|
+
*/
|
|
4
|
+
export type OpenAiApiKeyPublicConfig = Readonly<{
|
|
5
|
+
baseUrl?: string;
|
|
6
|
+
}>;
|
|
7
|
+
|
|
8
|
+
export type OpenAiApiKeyMaterial = Readonly<{
|
|
9
|
+
apiKey?: string;
|
|
10
|
+
}>;
|
|
11
|
+
|
|
12
|
+
export type OpenAiApiKeySession = Readonly<{
|
|
13
|
+
apiKey: string;
|
|
14
|
+
baseUrl?: string;
|
|
15
|
+
}>;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { CredentialType } from "../../domain/credentials/CredentialServices";
|
|
2
|
+
|
|
3
|
+
import type { OpenAiApiKeyCredentialHealthTester } from "./OpenAiApiKeyCredentialHealthTester";
|
|
4
|
+
import type {
|
|
5
|
+
OpenAiApiKeyMaterial,
|
|
6
|
+
OpenAiApiKeyPublicConfig,
|
|
7
|
+
OpenAiApiKeySession,
|
|
8
|
+
} from "./OpenAiApiKeyCredentialShapes.types";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Builds the OpenAI-compatible API key credential (`openai.apiKey`) registration.
|
|
12
|
+
* Used by {@link FrameworkBuiltinCredentialTypesRegistrar} and may be listed in {@link CodemationConfig.credentialTypes}
|
|
13
|
+
* so consumer apps always register the type even when bootstrap order differs.
|
|
14
|
+
*/
|
|
15
|
+
export class OpenAiApiKeyCredentialTypeFactory {
|
|
16
|
+
constructor(private readonly healthTester: OpenAiApiKeyCredentialHealthTester) {}
|
|
17
|
+
|
|
18
|
+
createCredentialType(): CredentialType<OpenAiApiKeyPublicConfig, OpenAiApiKeyMaterial, OpenAiApiKeySession> {
|
|
19
|
+
return {
|
|
20
|
+
definition: {
|
|
21
|
+
typeId: "openai.apiKey",
|
|
22
|
+
displayName: "OpenAI API key",
|
|
23
|
+
description: "API key and optional base URL for OpenAI or OpenAI-compatible chat endpoints.",
|
|
24
|
+
publicFields: [
|
|
25
|
+
{
|
|
26
|
+
key: "baseUrl",
|
|
27
|
+
label: "Base URL",
|
|
28
|
+
type: "string",
|
|
29
|
+
placeholder: "https://api.openai.com/v1",
|
|
30
|
+
helpText: "Leave empty to use the default OpenAI API endpoint.",
|
|
31
|
+
},
|
|
32
|
+
],
|
|
33
|
+
secretFields: [{ key: "apiKey", label: "API key", type: "password", required: true }],
|
|
34
|
+
supportedSourceKinds: ["db", "env", "code"],
|
|
35
|
+
},
|
|
36
|
+
createSession: async (args) => {
|
|
37
|
+
const baseUrlRaw = args.publicConfig.baseUrl;
|
|
38
|
+
const baseUrl = typeof baseUrlRaw === "string" && baseUrlRaw.trim() !== "" ? baseUrlRaw.trim() : undefined;
|
|
39
|
+
return {
|
|
40
|
+
apiKey: String(args.material.apiKey ?? ""),
|
|
41
|
+
baseUrl,
|
|
42
|
+
};
|
|
43
|
+
},
|
|
44
|
+
test: async (args) => this.healthTester.test(args),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { injectable, registry } from "@codemation/core";
|
|
2
|
+
import type { Command } from "../../application/bus/Command";
|
|
3
|
+
import type { CommandHandler } from "../../application/bus/CommandHandler";
|
|
4
|
+
import { ApplicationTokens } from "../../applicationTokens";
|
|
5
|
+
|
|
6
|
+
type AbstractType<TInstance> = abstract new (...args: any[]) => TInstance;
|
|
7
|
+
type ConcreteType<TInstance> = new (...args: any[]) => TInstance;
|
|
8
|
+
|
|
9
|
+
export const commandHandlerMetadataKey = Symbol.for("codemation.infrastructure.di.CommandHandler");
|
|
10
|
+
|
|
11
|
+
export class HandlesCommand {
|
|
12
|
+
static forCommand<TCommand extends Command<TResult>, TResult>(commandType: AbstractType<TCommand>): ClassDecorator {
|
|
13
|
+
return (target) => {
|
|
14
|
+
Reflect.defineMetadata(commandHandlerMetadataKey, commandType, target);
|
|
15
|
+
injectable()(target as never);
|
|
16
|
+
registry([
|
|
17
|
+
{
|
|
18
|
+
token: ApplicationTokens.CommandHandler,
|
|
19
|
+
useClass: target as unknown as ConcreteType<CommandHandler<Command<unknown>, unknown>>,
|
|
20
|
+
},
|
|
21
|
+
])(target as never);
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { injectable, registry } from "@codemation/core";
|
|
2
|
+
import type { DomainEvent } from "../../application/bus/DomainEvent";
|
|
3
|
+
import type { DomainEventHandler } from "../../application/bus/DomainEventHandler";
|
|
4
|
+
import { ApplicationTokens } from "../../applicationTokens";
|
|
5
|
+
|
|
6
|
+
type AbstractType<TInstance> = abstract new (...args: any[]) => TInstance;
|
|
7
|
+
type ConcreteType<TInstance> = new (...args: any[]) => TInstance;
|
|
8
|
+
|
|
9
|
+
export const domainEventHandlerMetadataKey = Symbol.for("codemation.infrastructure.di.DomainEventHandler");
|
|
10
|
+
|
|
11
|
+
export class HandlesDomainEvent {
|
|
12
|
+
static for<TEvent extends DomainEvent>(eventType: AbstractType<TEvent>): ClassDecorator {
|
|
13
|
+
return (target) => {
|
|
14
|
+
Reflect.defineMetadata(domainEventHandlerMetadataKey, eventType, target);
|
|
15
|
+
injectable()(target as never);
|
|
16
|
+
registry([
|
|
17
|
+
{
|
|
18
|
+
token: ApplicationTokens.DomainEventHandler,
|
|
19
|
+
useClass: target as unknown as ConcreteType<DomainEventHandler<DomainEvent>>,
|
|
20
|
+
},
|
|
21
|
+
])(target as never);
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { injectable, registry } from "@codemation/core";
|
|
2
|
+
import type { Query } from "../../application/bus/Query";
|
|
3
|
+
import type { QueryHandler } from "../../application/bus/QueryHandler";
|
|
4
|
+
import { ApplicationTokens } from "../../applicationTokens";
|
|
5
|
+
|
|
6
|
+
type AbstractType<TInstance> = abstract new (...args: any[]) => TInstance;
|
|
7
|
+
type ConcreteType<TInstance> = new (...args: any[]) => TInstance;
|
|
8
|
+
|
|
9
|
+
export const queryHandlerMetadataKey = Symbol.for("codemation.infrastructure.di.QueryHandler");
|
|
10
|
+
|
|
11
|
+
export class HandlesQuery {
|
|
12
|
+
static for<TQuery extends Query<TResult>, TResult>(queryType: AbstractType<TQuery>): ClassDecorator {
|
|
13
|
+
return (target) => {
|
|
14
|
+
Reflect.defineMetadata(queryHandlerMetadataKey, queryType, target);
|
|
15
|
+
injectable()(target as never);
|
|
16
|
+
registry([
|
|
17
|
+
{
|
|
18
|
+
token: ApplicationTokens.QueryHandler,
|
|
19
|
+
useClass: target as unknown as ConcreteType<QueryHandler<Query<unknown>, unknown>>,
|
|
20
|
+
},
|
|
21
|
+
])(target as never);
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
}
|