@codemation/host 0.0.5 → 0.0.7

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.
Files changed (109) hide show
  1. package/README.md +3 -3
  2. package/dist/{PrismaMigrationDeployer-B7cHGrXP.js → AppConfigFactory-DWIz2hy-.js} +104 -58
  3. package/dist/AppConfigFactory-DWIz2hy-.js.map +1 -0
  4. package/dist/{client-Yh7-CQud.d.ts → AppConfigFactory-DmHOpg8O.d.ts} +52 -31
  5. package/dist/{CodemationFrontendBootstrapRequest-CNEk-C4D.js → AppContainerFactory-B5eRpvAa.js} +3269 -3374
  6. package/dist/AppContainerFactory-B5eRpvAa.js.map +1 -0
  7. package/dist/{CodemationWhitelabelConfig-DgbjgtrR.d.ts → CodemationAuthConfig-Bh2cCNCI.d.ts} +32 -2
  8. package/dist/{CodemationConfig-XCkSV2dj.d.ts → CodemationConfig-D2ULNkec.d.ts} +53 -49
  9. package/dist/CodemationConfigNormalizer-CBLxXaRV.d.ts +9 -0
  10. package/dist/{CodemationConsumerConfigLoader-scS_RQMy.js → CodemationConsumerConfigLoader-BBzAr6L_.js} +128 -3
  11. package/dist/CodemationConsumerConfigLoader-BBzAr6L_.js.map +1 -0
  12. package/dist/{CodemationConsumerConfigLoader-Dmm2TzAA.d.ts → CodemationConsumerConfigLoader-BLvzcfb7.d.ts} +4 -4
  13. package/dist/CodemationPluginListMerger-B0-e4CJ6.d.ts +391 -0
  14. package/dist/{CodemationPluginListMerger-BNmaoXQL.js → CodemationPluginListMerger-DrVOw9KP.js} +18 -10
  15. package/dist/CodemationPluginListMerger-DrVOw9KP.js.map +1 -0
  16. package/dist/{CredentialServices-DpDpm8mL.d.ts → CredentialServices-BeuMtqYA.d.ts} +3 -3
  17. package/dist/{CredentialServices-BKBGe7l3.js → CredentialServices-DNb3CZwW.js} +3 -3
  18. package/dist/CredentialServices-DNb3CZwW.js.map +1 -0
  19. package/dist/FrontendAppConfig-D50wjj_n.d.ts +27 -0
  20. package/dist/{WorkflowViewContracts-DCLpTn25.d.ts → FrontendAppConfigFactory-Bj-DZNlt.d.ts} +29 -2
  21. package/dist/FrontendAppConfigJsonCodec-1_L7H_Qo.d.ts +20 -0
  22. package/dist/FrontendAppConfigJsonCodec-nOCQI0ag.js +84 -0
  23. package/dist/FrontendAppConfigJsonCodec-nOCQI0ag.js.map +1 -0
  24. package/dist/{LogLevelPolicy-4cq9z0TI.d.ts → LogLevelPolicy-BS_NlAOg.d.ts} +2 -2
  25. package/dist/{ServerLoggerFactory-BRHxIDS7.js → ServerLoggerFactory-BltIIDfQ.js} +4 -129
  26. package/dist/ServerLoggerFactory-BltIIDfQ.js.map +1 -0
  27. package/dist/client.d.ts +5 -3
  28. package/dist/client.js +2 -1
  29. package/dist/client.js.map +1 -1
  30. package/dist/consumer.d.ts +5 -4
  31. package/dist/consumer.js +4 -4
  32. package/dist/credentials.d.ts +4 -4
  33. package/dist/credentials.js +3 -3
  34. package/dist/devServerSidecar.d.ts +1 -1
  35. package/dist/{index-Bs4F1IsC.d.ts → index-CkiptHb-.d.ts} +19 -20
  36. package/dist/index.d.ts +14 -19
  37. package/dist/index.js +12 -11
  38. package/dist/nextServer.d.ts +244 -9
  39. package/dist/nextServer.js +8 -8
  40. package/dist/persistenceServer-CaehMh3M.d.ts +9 -0
  41. package/dist/{persistenceServer-8tcM2S48.js → persistenceServer-DVeWUbc3.js} +2 -2
  42. package/dist/{persistenceServer-8tcM2S48.js.map → persistenceServer-DVeWUbc3.js.map} +1 -1
  43. package/dist/persistenceServer.d.ts +7 -6
  44. package/dist/persistenceServer.js +4 -4
  45. package/dist/{server-Dd65rNm6.js → server-C65z_kqm.js} +47 -17
  46. package/dist/server-C65z_kqm.js.map +1 -0
  47. package/dist/{server-BBdsATju.d.ts → server-Dyo8qh4k.d.ts} +23 -4
  48. package/dist/server.d.ts +12 -9
  49. package/dist/server.js +11 -10
  50. package/package.json +6 -6
  51. package/src/application/commands/WorkflowCommandHandlers.ts +9 -0
  52. package/src/application/dev/BootRuntimeSnapshotHolder.ts +2 -2
  53. package/src/application/dev/BootRuntimeSummary.types.ts +2 -2
  54. package/src/application/queries/WorkflowQueryHandlers.ts +7 -0
  55. package/src/applicationTokens.ts +1 -1
  56. package/src/bootstrap/AppContainerFactory.ts +584 -0
  57. package/src/bootstrap/{PreparedCodemationRuntime.ts → AppContainerLifecycle.ts} +3 -8
  58. package/src/bootstrap/runtime/AppConfigFactory.ts +155 -30
  59. package/src/bootstrap/runtime/DatabaseMigrations.ts +18 -0
  60. package/src/bootstrap/runtime/FrontendRuntime.ts +44 -0
  61. package/src/bootstrap/runtime/WorkerRuntime.ts +55 -0
  62. package/src/client.ts +7 -0
  63. package/src/index.ts +15 -5
  64. package/src/infrastructure/persistence/PrismaMigrationDeployer.ts +2 -2
  65. package/src/infrastructure/persistence/SchedulerPersistenceCompatibilityValidator.ts +2 -2
  66. package/src/infrastructure/scheduler/WorkerRuntimeScheduler.ts +16 -0
  67. package/src/infrastructure/scheduler/bullmq/BullmqNodeExecutionScheduler.ts +47 -0
  68. package/src/infrastructure/scheduler/bullmq/BullmqScheduler.ts +33 -0
  69. package/src/infrastructure/scheduler/bullmq/BullmqWorker.ts +48 -0
  70. package/src/infrastructure/scheduler/bullmq/RedisConnectionOptionsFactory.ts +48 -0
  71. package/src/nextServer.ts +12 -3
  72. package/src/persistenceServer.ts +2 -2
  73. package/src/presentation/config/AppConfig.ts +25 -1
  74. package/src/presentation/frontend/CodemationFrontendAuthSnapshot.ts +14 -0
  75. package/src/presentation/frontend/CodemationFrontendAuthSnapshotFactory.ts +84 -0
  76. package/src/presentation/frontend/CodemationFrontendAuthSnapshotJsonCodec.ts +58 -0
  77. package/src/presentation/frontend/FrontendAppConfig.ts +10 -0
  78. package/src/presentation/frontend/FrontendAppConfigFactory.ts +26 -0
  79. package/src/presentation/frontend/FrontendAppConfigJsonCodec.ts +58 -0
  80. package/src/presentation/http/CodemationServerGatewayFactory.ts +22 -16
  81. package/src/presentation/server/AppConfigLoader.ts +39 -0
  82. package/src/presentation/server/CodemationConsumerAppResolver.ts +2 -2
  83. package/src/presentation/server/CodemationConsumerConfigLoader.ts +3 -2
  84. package/src/server.ts +7 -0
  85. package/vitest.shared.ts +0 -4
  86. package/dist/CodemationConsumerConfigLoader-scS_RQMy.js.map +0 -1
  87. package/dist/CodemationFrontendBootstrapRequest-CNEk-C4D.js.map +0 -1
  88. package/dist/CodemationPluginListMerger-BNmaoXQL.js.map +0 -1
  89. package/dist/CodemationPluginListMerger-BRYqEk0y.d.ts +0 -793
  90. package/dist/CredentialServices-BKBGe7l3.js.map +0 -1
  91. package/dist/PrismaMigrationDeployer-B7cHGrXP.js.map +0 -1
  92. package/dist/ServerLoggerFactory-BRHxIDS7.js.map +0 -1
  93. package/dist/persistenceServer-DPSj_-oU.d.ts +0 -37
  94. package/dist/server-Dd65rNm6.js.map +0 -1
  95. package/src/bootstrap/CodemationContainerFactory.ts +0 -310
  96. package/src/bootstrap/CodemationFrontendBootstrapRequest.ts +0 -16
  97. package/src/bootstrap/CodemationWorkerBootstrapRequest.ts +0 -19
  98. package/src/bootstrap/PreparedCodemationRuntimeFactory.ts +0 -308
  99. package/src/bootstrap/boot/CliRuntimeBootService.ts +0 -27
  100. package/src/bootstrap/boot/FrontendRuntimeBootService.ts +0 -86
  101. package/src/bootstrap/boot/WorkerRuntimeBootService.ts +0 -64
  102. package/src/bootstrap/runtime/ResolvedImplementationSelectionFactory.ts +0 -118
  103. package/src/codemationApplication.ts +0 -311
  104. package/src/infrastructure/credentials/FrameworkBuiltinCredentialTypesRegistrar.ts +0 -21
  105. package/src/infrastructure/persistence/DatabasePersistenceResolver.ts +0 -91
  106. package/src/infrastructure/runtime/WorkerRuntimeScheduler.ts +0 -35
  107. package/src/presentation/config/CodemationApplicationFacade.ts +0 -5
  108. /package/dist/{decorate-B-N_5S4p.js → decorate-B0PP651O.js} +0 -0
  109. /package/dist/{decorateParam-BTcc3KNk.js → decorateParam-DrsXNPuw.js} +0 -0
@@ -0,0 +1,584 @@
1
+ import "reflect-metadata";
2
+
3
+ import type { PGlite } from "@electric-sql/pglite";
4
+ import type { Container } from "@codemation/core";
5
+ import {
6
+ CoreTokens,
7
+ EventPublishingWorkflowExecutionRepository,
8
+ InMemoryRunEventBus,
9
+ instanceCachingFactory,
10
+ SystemClock,
11
+ container as tsyringeContainer,
12
+ type WorkflowDefinition,
13
+ } from "@codemation/core";
14
+ import {
15
+ ConfigDrivenOffloadPolicy,
16
+ DefaultDrivingScheduler,
17
+ DefaultExecutionContextFactory,
18
+ EngineRuntimeRegistrar,
19
+ InMemoryRunDataFactory,
20
+ InlineDrivingScheduler,
21
+ PersistedWorkflowTokenRegistry,
22
+ WorkflowRepositoryWebhookTriggerMatcher,
23
+ } from "@codemation/core/bootstrap";
24
+ import { AIAgentConnectionWorkflowExpander, ConnectionCredentialNodeConfigFactory } from "@codemation/core-nodes";
25
+ import "../application/commands/CredentialCommandHandlers";
26
+ import "../application/commands/UserAccountCommandHandlers";
27
+ import "../application/commands/WorkflowCommandHandlers";
28
+ import "../application/queries/CredentialQueryHandlers";
29
+ import "../application/queries/UserAccountQueryHandlers";
30
+ import "../application/queries/WorkflowQueryHandlers";
31
+ import { OpenAiApiKeyCredentialHealthTester } from "../infrastructure/credentials/OpenAiApiKeyCredentialHealthTester";
32
+ import { OpenAiApiKeyCredentialTypeFactory } from "../infrastructure/credentials/OpenAiApiKeyCredentialTypeFactory";
33
+ import { CodemationPluginRegistrar } from "../infrastructure/config/CodemationPluginRegistrar";
34
+ import { WorkflowRunEventWebsocketRelay } from "../application/websocket/WorkflowRunEventWebsocketRelay";
35
+ import { ApplicationTokens } from "../applicationTokens";
36
+ import type { CredentialType } from "../domain/credentials/CredentialServices";
37
+ import {
38
+ CredentialBindingService,
39
+ CredentialFieldEnvOverlayService,
40
+ CredentialInstanceService,
41
+ CredentialMaterialResolver,
42
+ CredentialRuntimeMaterialService,
43
+ CredentialSecretCipher,
44
+ CredentialSessionServiceImpl,
45
+ CredentialTestService,
46
+ CredentialTypeRegistryImpl,
47
+ } from "../domain/credentials/CredentialServices";
48
+ import { OAuth2ConnectService } from "../domain/credentials/OAuth2ConnectServiceFactory";
49
+ import { OAuth2ProviderRegistry } from "../domain/credentials/OAuth2ProviderRegistry";
50
+ import { WorkflowCredentialNodeResolver } from "../domain/credentials/WorkflowCredentialNodeResolver";
51
+ import { UserAccountService } from "../domain/users/UserAccountServiceRegistry";
52
+ import type { WorkflowDebuggerOverlayRepository } from "../domain/workflows/WorkflowDebuggerOverlayRepository";
53
+ import type { WorkflowDefinitionRepository } from "../domain/workflows/WorkflowDefinitionRepository";
54
+ import { WorkflowActivationPreflight } from "../domain/workflows/WorkflowActivationPreflight";
55
+ import { WorkflowActivationPreflightRules } from "../domain/workflows/WorkflowActivationPreflightRules";
56
+ import { BootRuntimeSnapshotHolder } from "../application/dev/BootRuntimeSnapshotHolder";
57
+ import type { BootRuntimeSummary } from "../application/dev/BootRuntimeSummary.types";
58
+ import { DevBootstrapSummaryAssembler } from "../application/dev/DevBootstrapSummaryAssembler";
59
+ import { WorkflowDefinitionMapper } from "../application/mapping/WorkflowDefinitionMapper";
60
+ import { WorkflowPolicyUiPresentationFactory } from "../application/mapping/WorkflowPolicyUiPresentationFactory";
61
+ import { WorkflowWebsocketServer } from "../presentation/websocket/WorkflowWebsocketServer";
62
+ import { CodemationFrontendAuthSnapshotFactory } from "../presentation/frontend/CodemationFrontendAuthSnapshotFactory";
63
+ import { FrontendAppConfigFactory } from "../presentation/frontend/FrontendAppConfigFactory";
64
+ import { DevBootstrapSummaryHttpRouteHandler } from "../presentation/http/routeHandlers/DevBootstrapSummaryHttpRouteHandler";
65
+ import { WhitelabelLogoHttpRouteHandler } from "../presentation/http/routeHandlers/WhitelabelLogoHttpRouteHandler";
66
+ import { CodemationHonoApiApp } from "../presentation/http/hono/CodemationHonoApiAppFactory";
67
+ import { BinaryHonoApiRouteRegistrar } from "../presentation/http/hono/registrars/BinaryHonoApiRouteRegistrar";
68
+ import { CredentialHonoApiRouteRegistrar } from "../presentation/http/hono/registrars/CredentialHonoApiRouteRegistrar";
69
+ import { DevHonoApiRouteRegistrar } from "../presentation/http/hono/registrars/DevHonoApiRouteRegistrar";
70
+ import { OAuth2HonoApiRouteRegistrar } from "../presentation/http/hono/registrars/OAuth2HonoApiRouteRegistrar";
71
+ import { RunHonoApiRouteRegistrar } from "../presentation/http/hono/registrars/RunHonoApiRouteRegistrar";
72
+ import { UserHonoApiRouteRegistrar } from "../presentation/http/hono/registrars/UserHonoApiRouteRegistrar";
73
+ import { WebhookHonoApiRouteRegistrar } from "../presentation/http/hono/registrars/WebhookHonoApiRouteRegistrar";
74
+ import { WhitelabelHonoApiRouteRegistrar } from "../presentation/http/hono/registrars/WhitelabelHonoApiRouteRegistrar";
75
+ import { WorkflowHonoApiRouteRegistrar } from "../presentation/http/hono/registrars/WorkflowHonoApiRouteRegistrar";
76
+ import { ApiPaths } from "../presentation/http/ApiPaths";
77
+ import { RequestToWebhookItemMapper } from "../infrastructure/webhooks/RequestToWebhookItemMapper";
78
+ import { WebhookEndpointPathValidator } from "../application/workflows/WebhookEndpointPathValidator";
79
+ import { CodemationIdFactory } from "../infrastructure/ids/CodemationIdFactory";
80
+ import { InMemoryCommandBus } from "../infrastructure/di/InMemoryCommandBus";
81
+ import { InMemoryDomainEventBus } from "../infrastructure/di/InMemoryDomainEventBus";
82
+ import { InMemoryQueryBus } from "../infrastructure/di/InMemoryQueryBus";
83
+ import { AuthJsSessionVerifier } from "../infrastructure/auth/AuthJsSessionVerifier";
84
+ import { DevelopmentSessionBypassVerifier } from "../infrastructure/auth/DevelopmentSessionBypassVerifier";
85
+ import {
86
+ InMemoryCredentialStore,
87
+ PrismaCredentialStore,
88
+ } from "../infrastructure/persistence/CredentialPersistenceStore";
89
+ import { InMemoryTriggerSetupStateRepository } from "../infrastructure/persistence/InMemoryTriggerSetupStateRepository";
90
+ import { InMemoryWorkflowActivationRepository } from "../infrastructure/persistence/InMemoryWorkflowActivationRepository";
91
+ import { InMemoryWorkflowDebuggerOverlayRepository } from "../infrastructure/persistence/InMemoryWorkflowDebuggerOverlayRepository";
92
+ import { InMemoryWorkflowRunRepository } from "../infrastructure/persistence/InMemoryWorkflowRunRepository";
93
+ import { PrismaClientFactory } from "../infrastructure/persistence/PrismaClientFactory";
94
+ import { PrismaClient } from "../infrastructure/persistence/generated/prisma-client/client.js";
95
+ import { PrismaTriggerSetupStateRepository } from "../infrastructure/persistence/PrismaTriggerSetupStateRepository";
96
+ import { PrismaWorkflowActivationRepository } from "../infrastructure/persistence/PrismaWorkflowActivationRepository";
97
+ import { PrismaWorkflowDebuggerOverlayRepository } from "../infrastructure/persistence/PrismaWorkflowDebuggerOverlayRepository";
98
+ import { PrismaWorkflowRunRepository } from "../infrastructure/persistence/PrismaWorkflowRunRepository";
99
+ import { RuntimeWorkflowActivationPolicy } from "../infrastructure/persistence/RuntimeWorkflowActivationPolicy";
100
+ import { WorkflowDefinitionRepositoryAdapter } from "../infrastructure/persistence/WorkflowDefinitionRepositoryAdapter";
101
+ import { WorkflowRunRepository as SqlWorkflowRunRepository } from "../infrastructure/persistence/WorkflowRunRepository";
102
+ import { LiveWorkflowRepository } from "../infrastructure/runtime/LiveWorkflowRepository";
103
+ import { LogLevelPolicyFactory, logLevelPolicyFactory } from "../infrastructure/logging/LogLevelPolicyFactory";
104
+ import { ServerLoggerFactory } from "../infrastructure/logging/ServerLoggerFactory";
105
+ import type { AppConfig } from "../presentation/config/AppConfig";
106
+ import { CodemationContainerRegistrationRegistrar } from "./CodemationContainerRegistrationRegistrar";
107
+ import { LocalFilesystemBinaryStorage } from "../infrastructure/binary/LocalFilesystemBinaryStorageRegistry";
108
+ import { InMemoryBinaryStorage } from "@codemation/core/bootstrap";
109
+ import { RedisRunEventBus } from "@codemation/eventbus-redis";
110
+ import { AppContainerLifecycle } from "./AppContainerLifecycle";
111
+ import { DatabaseMigrations } from "./runtime/DatabaseMigrations";
112
+ import { FrontendRuntime } from "./runtime/FrontendRuntime";
113
+ import { WorkerRuntime } from "./runtime/WorkerRuntime";
114
+ import { BullmqScheduler } from "../infrastructure/scheduler/bullmq/BullmqScheduler";
115
+
116
+ type AppContainerInputs = Readonly<{
117
+ appConfig: AppConfig;
118
+ sharedWorkflowWebsocketServer: WorkflowWebsocketServer | null;
119
+ }>;
120
+
121
+ type PrismaOwnership = Readonly<{
122
+ ownedPrismaClient: PrismaClient | null;
123
+ ownedPglite: PGlite | null;
124
+ }>;
125
+
126
+ export class AppContainerFactory {
127
+ private static readonly honoRouteRegistrars = [
128
+ BinaryHonoApiRouteRegistrar,
129
+ CredentialHonoApiRouteRegistrar,
130
+ DevHonoApiRouteRegistrar,
131
+ OAuth2HonoApiRouteRegistrar,
132
+ RunHonoApiRouteRegistrar,
133
+ UserHonoApiRouteRegistrar,
134
+ WebhookHonoApiRouteRegistrar,
135
+ WhitelabelHonoApiRouteRegistrar,
136
+ WorkflowHonoApiRouteRegistrar,
137
+ ] as const;
138
+
139
+ constructor(
140
+ private readonly containerRegistrationRegistrar: CodemationContainerRegistrationRegistrar = new CodemationContainerRegistrationRegistrar(),
141
+ private readonly pluginRegistrar: CodemationPluginRegistrar = new CodemationPluginRegistrar(),
142
+ ) {}
143
+
144
+ async create(inputs: AppContainerInputs): Promise<Container> {
145
+ const container = tsyringeContainer.createChildContainer();
146
+ container.registerInstance(ApplicationTokens.AppConfig, inputs.appConfig);
147
+ this.registerCoreInfrastructure(container, inputs);
148
+ this.registerRepositoriesAndBuses(container);
149
+ this.registerApplicationServicesAndRoutes(container);
150
+ this.registerOperationalInfrastructure(container);
151
+ this.registerConfiguredRegistrations(container, inputs.appConfig);
152
+ const credentialTypes = this.collectCredentialTypes(inputs.appConfig);
153
+ await this.applyPlugins(container, inputs.appConfig, credentialTypes);
154
+ const ownership = await this.registerRuntimeInfrastructure(container, inputs.appConfig);
155
+ this.registerCredentialTypes(container, credentialTypes);
156
+ this.synchronizeLiveWorkflowRepository(container, inputs.appConfig.workflows);
157
+ container.resolve(BootRuntimeSnapshotHolder).set(this.createRuntimeSummary(inputs.appConfig));
158
+ container.registerInstance(
159
+ AppContainerLifecycle,
160
+ new AppContainerLifecycle(container, ownership.ownedPrismaClient, ownership.ownedPglite),
161
+ );
162
+ return container;
163
+ }
164
+
165
+ private collectCredentialTypes(appConfig: AppConfig): Array<CredentialType<any, any, unknown>> {
166
+ const credentialTypes = [...appConfig.credentialTypes];
167
+ const openAiCredentialType = new OpenAiApiKeyCredentialTypeFactory(
168
+ new OpenAiApiKeyCredentialHealthTester(globalThis.fetch),
169
+ ).createCredentialType();
170
+ if (!credentialTypes.some((entry) => entry.definition.typeId === openAiCredentialType.definition.typeId)) {
171
+ credentialTypes.push(openAiCredentialType);
172
+ }
173
+ return credentialTypes;
174
+ }
175
+
176
+ private async applyPlugins(
177
+ container: Container,
178
+ appConfig: AppConfig,
179
+ credentialTypes: Array<CredentialType<any, any, unknown>>,
180
+ ): Promise<void> {
181
+ await this.pluginRegistrar.apply({
182
+ plugins: appConfig.plugins,
183
+ container,
184
+ appConfig,
185
+ registerCredentialType: (type) => {
186
+ if (!credentialTypes.some((entry) => entry.definition.typeId === type.definition.typeId)) {
187
+ credentialTypes.push(type);
188
+ }
189
+ },
190
+ loggerFactory: container.resolve(ApplicationTokens.LoggerFactory),
191
+ });
192
+ }
193
+
194
+ private registerCredentialTypes(
195
+ container: Container,
196
+ credentialTypes: ReadonlyArray<CredentialType<any, any, unknown>>,
197
+ ): void {
198
+ const registry = container.resolve(CredentialTypeRegistryImpl);
199
+ for (const credentialType of credentialTypes) {
200
+ registry.register(credentialType);
201
+ }
202
+ }
203
+
204
+ private registerConfiguredRegistrations(container: Container, appConfig: AppConfig): void {
205
+ if (appConfig.containerRegistrations.length === 0) {
206
+ return;
207
+ }
208
+ this.containerRegistrationRegistrar.apply(container, appConfig.containerRegistrations);
209
+ }
210
+
211
+ private registerCoreInfrastructure(container: Container, inputs: AppContainerInputs): void {
212
+ container.registerInstance(BootRuntimeSnapshotHolder, new BootRuntimeSnapshotHolder());
213
+ container.registerInstance(ApplicationTokens.AppConfig, inputs.appConfig);
214
+ container.registerInstance(ApplicationTokens.CodemationAuthConfig, inputs.appConfig.auth);
215
+ container.registerInstance(ApplicationTokens.CodemationWhitelabelConfig, inputs.appConfig.whitelabel);
216
+ container.registerInstance(ApplicationTokens.WebSocketPort, inputs.appConfig.webSocketPort);
217
+ container.registerInstance(ApplicationTokens.WebSocketBindHost, inputs.appConfig.webSocketBindHost);
218
+ container.registerInstance(CoreTokens.WebhookBasePath, ApiPaths.webhooks());
219
+ container.registerInstance(PersistedWorkflowTokenRegistry, new PersistedWorkflowTokenRegistry());
220
+ container.registerInstance(
221
+ CoreTokens.PersistedWorkflowTokenRegistry,
222
+ container.resolve(PersistedWorkflowTokenRegistry),
223
+ );
224
+ container.register(CredentialTypeRegistryImpl, {
225
+ useFactory: instanceCachingFactory(() => new CredentialTypeRegistryImpl()),
226
+ });
227
+ container.register(CoreTokens.CredentialTypeRegistry, {
228
+ useFactory: instanceCachingFactory((dependencyContainer) =>
229
+ dependencyContainer.resolve(CredentialTypeRegistryImpl),
230
+ ),
231
+ });
232
+ container.register(CodemationIdFactory, { useClass: CodemationIdFactory });
233
+ container.register(CoreTokens.RunIdFactory, {
234
+ useFactory: instanceCachingFactory((dependencyContainer) => dependencyContainer.resolve(CodemationIdFactory)),
235
+ });
236
+ container.register(CoreTokens.ActivationIdFactory, {
237
+ useFactory: instanceCachingFactory((dependencyContainer) => dependencyContainer.resolve(CodemationIdFactory)),
238
+ });
239
+ container.register(CoreTokens.LiveWorkflowRepository, {
240
+ useFactory: instanceCachingFactory(
241
+ () =>
242
+ new LiveWorkflowRepository(
243
+ new AIAgentConnectionWorkflowExpander(new ConnectionCredentialNodeConfigFactory()),
244
+ ),
245
+ ),
246
+ });
247
+ container.register(CoreTokens.WorkflowRepository, {
248
+ useFactory: instanceCachingFactory((dependencyContainer) =>
249
+ dependencyContainer.resolve(CoreTokens.LiveWorkflowRepository),
250
+ ),
251
+ });
252
+ container.registerInstance(CoreTokens.NodeResolver, container);
253
+ const runtimeWorkflowActivationPolicy = new RuntimeWorkflowActivationPolicy();
254
+ container.registerInstance(RuntimeWorkflowActivationPolicy, runtimeWorkflowActivationPolicy);
255
+ container.registerInstance(CoreTokens.WorkflowActivationPolicy, runtimeWorkflowActivationPolicy);
256
+ new EngineRuntimeRegistrar().register(container, {
257
+ resolveEngineExecutionLimits: () => inputs.appConfig.engineExecutionLimits,
258
+ webhookTriggerMatcherProvider: {
259
+ createMatcher: (dependencyContainer) => {
260
+ const webhookRoutingLogger = dependencyContainer
261
+ .resolve(ServerLoggerFactory)
262
+ .create("codemation.webhooks.routing");
263
+ return new WorkflowRepositoryWebhookTriggerMatcher(
264
+ dependencyContainer.resolve(CoreTokens.WorkflowRepository),
265
+ dependencyContainer.resolve(CoreTokens.WorkflowActivationPolicy),
266
+ {
267
+ warn: (message) => webhookRoutingLogger.warn(message),
268
+ info: (message) => webhookRoutingLogger.debug(message),
269
+ },
270
+ );
271
+ },
272
+ },
273
+ triggerRuntimeDiagnosticsProvider: {
274
+ create: (dependencyContainer) => {
275
+ const triggerRuntimeLogger = dependencyContainer
276
+ .resolve(ServerLoggerFactory)
277
+ .create("codemation.engine.triggers");
278
+ return {
279
+ info: (message) => triggerRuntimeLogger.debug(message),
280
+ warn: (message) => triggerRuntimeLogger.warn(message),
281
+ };
282
+ },
283
+ },
284
+ });
285
+ container.registerInstance(LogLevelPolicyFactory, logLevelPolicyFactory);
286
+ container.register(ServerLoggerFactory, { useClass: ServerLoggerFactory });
287
+ container.register(ApplicationTokens.LoggerFactory, {
288
+ useFactory: instanceCachingFactory((dependencyContainer) => dependencyContainer.resolve(ServerLoggerFactory)),
289
+ });
290
+ container.register(ApplicationTokens.PerformanceDiagnosticsLogger, {
291
+ useFactory: instanceCachingFactory((dependencyContainer) =>
292
+ dependencyContainer.resolve(ServerLoggerFactory).createPerformanceDiagnostics("codemation.performance"),
293
+ ),
294
+ });
295
+ container.register(WorkflowWebsocketServer, {
296
+ useFactory: instanceCachingFactory((dependencyContainer) => {
297
+ if (inputs.sharedWorkflowWebsocketServer) {
298
+ return inputs.sharedWorkflowWebsocketServer;
299
+ }
300
+ return new WorkflowWebsocketServer(
301
+ dependencyContainer.resolve(ApplicationTokens.WebSocketPort),
302
+ dependencyContainer.resolve(ApplicationTokens.WebSocketBindHost),
303
+ dependencyContainer.resolve(ServerLoggerFactory).create("codemation-websocket.server"),
304
+ );
305
+ }),
306
+ });
307
+ container.register(PrismaClientFactory, { useClass: PrismaClientFactory });
308
+ container.register(WorkflowPolicyUiPresentationFactory, { useClass: WorkflowPolicyUiPresentationFactory });
309
+ container.register(WorkflowDefinitionMapper, { useClass: WorkflowDefinitionMapper });
310
+ container.register(RequestToWebhookItemMapper, { useClass: RequestToWebhookItemMapper });
311
+ container.register(WebhookEndpointPathValidator, { useClass: WebhookEndpointPathValidator });
312
+ container.register(CredentialSecretCipher, { useClass: CredentialSecretCipher });
313
+ container.register(CredentialMaterialResolver, { useClass: CredentialMaterialResolver });
314
+ container.register(CredentialFieldEnvOverlayService, { useClass: CredentialFieldEnvOverlayService });
315
+ container.register(CredentialRuntimeMaterialService, { useClass: CredentialRuntimeMaterialService });
316
+ container.register(WorkflowCredentialNodeResolver, { useClass: WorkflowCredentialNodeResolver });
317
+ container.register(CredentialInstanceService, { useClass: CredentialInstanceService });
318
+ container.register(CredentialBindingService, { useClass: CredentialBindingService });
319
+ container.register(WorkflowActivationPreflightRules, { useClass: WorkflowActivationPreflightRules });
320
+ container.register(WorkflowActivationPreflight, { useClass: WorkflowActivationPreflight });
321
+ container.register(CredentialTestService, { useClass: CredentialTestService });
322
+ container.register(CredentialSessionServiceImpl, { useClass: CredentialSessionServiceImpl });
323
+ if (!inputs.appConfig.hasConfiguredCredentialSessionServiceRegistration) {
324
+ container.register(CoreTokens.CredentialSessionService, { useToken: CredentialSessionServiceImpl });
325
+ }
326
+ container.register(OAuth2ProviderRegistry, { useClass: OAuth2ProviderRegistry });
327
+ container.register(OAuth2ConnectService, { useClass: OAuth2ConnectService });
328
+ container.register(CodemationFrontendAuthSnapshotFactory, { useClass: CodemationFrontendAuthSnapshotFactory });
329
+ container.register(FrontendAppConfigFactory, { useClass: FrontendAppConfigFactory });
330
+ container.register(DatabaseMigrations, { useClass: DatabaseMigrations });
331
+ container.register(FrontendRuntime, { useClass: FrontendRuntime });
332
+ container.register(WorkerRuntime, { useClass: WorkerRuntime });
333
+ container.register(DevelopmentSessionBypassVerifier, { useClass: DevelopmentSessionBypassVerifier });
334
+ container.register(AuthJsSessionVerifier, {
335
+ useFactory: instanceCachingFactory((dependencyContainer) => {
336
+ const appConfig = dependencyContainer.resolve<AppConfig>(ApplicationTokens.AppConfig);
337
+ return new AuthJsSessionVerifier(appConfig.env.AUTH_SECRET ?? "");
338
+ }),
339
+ });
340
+ container.register(ApplicationTokens.SessionVerifier, {
341
+ useFactory: instanceCachingFactory((dependencyContainer) => {
342
+ const appConfig = dependencyContainer.resolve<AppConfig>(ApplicationTokens.AppConfig);
343
+ const isProduction = appConfig.env.NODE_ENV === "production";
344
+ const authConfig = appConfig.auth;
345
+ if (isProduction && !authConfig) {
346
+ throw new Error("CodemationConfig.auth is required when NODE_ENV is production.");
347
+ }
348
+ if (isProduction && authConfig?.allowUnauthenticatedInDevelopment === true) {
349
+ throw new Error(
350
+ "CodemationAuthConfig.allowUnauthenticatedInDevelopment is not allowed when NODE_ENV is production.",
351
+ );
352
+ }
353
+ const bypassAllowed = !isProduction && authConfig?.allowUnauthenticatedInDevelopment === true;
354
+ if (bypassAllowed) {
355
+ return dependencyContainer.resolve(DevelopmentSessionBypassVerifier);
356
+ }
357
+ const secret = appConfig.env.AUTH_SECRET ?? "";
358
+ if (!secret) {
359
+ throw new Error(
360
+ "AUTH_SECRET is required unless CodemationAuthConfig.allowUnauthenticatedInDevelopment is enabled in a non-production environment.",
361
+ );
362
+ }
363
+ return dependencyContainer.resolve(AuthJsSessionVerifier);
364
+ }),
365
+ });
366
+ container.register(UserAccountService, {
367
+ useFactory: instanceCachingFactory((dependencyContainer) => {
368
+ const appConfig = dependencyContainer.resolve<AppConfig>(ApplicationTokens.AppConfig);
369
+ const prisma = dependencyContainer.isRegistered(PrismaClient, true)
370
+ ? dependencyContainer.resolve(PrismaClient)
371
+ : undefined;
372
+ return new UserAccountService(appConfig.auth, prisma);
373
+ }),
374
+ });
375
+ }
376
+
377
+ private registerRepositoriesAndBuses(container: Container): void {
378
+ container.register(WorkflowDefinitionRepositoryAdapter, { useClass: WorkflowDefinitionRepositoryAdapter });
379
+ container.register(InMemoryWorkflowRunRepository, { useClass: InMemoryWorkflowRunRepository });
380
+ container.register(InMemoryTriggerSetupStateRepository, { useClass: InMemoryTriggerSetupStateRepository });
381
+ container.register(InMemoryCredentialStore, { useClass: InMemoryCredentialStore });
382
+ container.register(SqlWorkflowRunRepository, { useClass: SqlWorkflowRunRepository });
383
+ container.register(InMemoryWorkflowDebuggerOverlayRepository, {
384
+ useClass: InMemoryWorkflowDebuggerOverlayRepository,
385
+ });
386
+ container.register(PrismaTriggerSetupStateRepository, { useClass: PrismaTriggerSetupStateRepository });
387
+ container.register(PrismaWorkflowDebuggerOverlayRepository, { useClass: PrismaWorkflowDebuggerOverlayRepository });
388
+ container.register(PrismaWorkflowActivationRepository, { useClass: PrismaWorkflowActivationRepository });
389
+ container.register(InMemoryWorkflowActivationRepository, { useClass: InMemoryWorkflowActivationRepository });
390
+ container.register(PrismaCredentialStore, { useClass: PrismaCredentialStore });
391
+ container.register(ApplicationTokens.WorkflowDefinitionRepository, {
392
+ useFactory: instanceCachingFactory(
393
+ (dependencyContainer) =>
394
+ dependencyContainer.resolve(WorkflowDefinitionRepositoryAdapter) as unknown as WorkflowDefinitionRepository,
395
+ ),
396
+ });
397
+ container.register(InMemoryQueryBus, { useClass: InMemoryQueryBus });
398
+ container.register(InMemoryCommandBus, { useClass: InMemoryCommandBus });
399
+ container.register(InMemoryDomainEventBus, { useClass: InMemoryDomainEventBus });
400
+ container.register(ApplicationTokens.QueryBus, {
401
+ useFactory: instanceCachingFactory((dependencyContainer) => dependencyContainer.resolve(InMemoryQueryBus)),
402
+ });
403
+ container.register(ApplicationTokens.CommandBus, {
404
+ useFactory: instanceCachingFactory((dependencyContainer) => dependencyContainer.resolve(InMemoryCommandBus)),
405
+ });
406
+ container.register(ApplicationTokens.DomainEventBus, {
407
+ useFactory: instanceCachingFactory((dependencyContainer) => dependencyContainer.resolve(InMemoryDomainEventBus)),
408
+ });
409
+ }
410
+
411
+ private registerApplicationServicesAndRoutes(container: Container): void {
412
+ container.register(DevBootstrapSummaryAssembler, { useClass: DevBootstrapSummaryAssembler });
413
+ container.register(DevBootstrapSummaryHttpRouteHandler, { useClass: DevBootstrapSummaryHttpRouteHandler });
414
+ container.register(WhitelabelLogoHttpRouteHandler, { useClass: WhitelabelLogoHttpRouteHandler });
415
+ for (const registrar of AppContainerFactory.honoRouteRegistrars) {
416
+ container.register(ApplicationTokens.HonoApiRouteRegistrar, { useClass: registrar });
417
+ }
418
+ container.register(CodemationHonoApiApp, { useClass: CodemationHonoApiApp });
419
+ }
420
+
421
+ private registerOperationalInfrastructure(container: Container): void {
422
+ container.register(ApplicationTokens.WorkflowWebsocketPublisher, {
423
+ useFactory: instanceCachingFactory((dependencyContainer) => dependencyContainer.resolve(WorkflowWebsocketServer)),
424
+ });
425
+ container.register(WorkflowRunEventWebsocketRelay, { useClass: WorkflowRunEventWebsocketRelay });
426
+ }
427
+
428
+ private async registerRuntimeInfrastructure(container: Container, appConfig: AppConfig): Promise<PrismaOwnership> {
429
+ const queuePrefix = appConfig.scheduler.queuePrefix ?? appConfig.eventing.queuePrefix ?? "codemation";
430
+ const eventBus =
431
+ appConfig.eventing.kind === "redis"
432
+ ? new RedisRunEventBus(this.requireRedisUrl(appConfig.eventing.redisUrl), queuePrefix)
433
+ : new InMemoryRunEventBus();
434
+ container.registerInstance(CoreTokens.RunEventBus, eventBus);
435
+ const binaryStorage = this.createBinaryStorage(appConfig.repoRoot);
436
+ container.registerInstance(CoreTokens.RunDataFactory, new InMemoryRunDataFactory());
437
+ container.registerInstance(CoreTokens.BinaryStorage, binaryStorage);
438
+ container.registerInstance(CoreTokens.ExecutionContextFactory, new DefaultExecutionContextFactory(binaryStorage));
439
+ container.registerInstance(ApplicationTokens.Clock, new SystemClock());
440
+
441
+ if (appConfig.persistence.kind === "none") {
442
+ const workflowRunRepository = container.resolve(InMemoryWorkflowRunRepository);
443
+ container.registerInstance(
444
+ CoreTokens.WorkflowExecutionRepository,
445
+ new EventPublishingWorkflowExecutionRepository(workflowRunRepository, eventBus),
446
+ );
447
+ container.registerInstance(
448
+ CoreTokens.TriggerSetupStateRepository,
449
+ container.resolve(InMemoryTriggerSetupStateRepository),
450
+ );
451
+ container.registerInstance(ApplicationTokens.WorkflowRunRepository, workflowRunRepository);
452
+ container.registerInstance(
453
+ ApplicationTokens.WorkflowDebuggerOverlayRepository,
454
+ container.resolve(InMemoryWorkflowDebuggerOverlayRepository) as unknown as WorkflowDebuggerOverlayRepository,
455
+ );
456
+ container.registerInstance(
457
+ ApplicationTokens.WorkflowActivationRepository,
458
+ container.resolve(InMemoryWorkflowActivationRepository),
459
+ );
460
+ container.registerInstance(ApplicationTokens.CredentialStore, container.resolve(InMemoryCredentialStore));
461
+ this.registerRuntimeNodeActivationScheduler(container);
462
+ return {
463
+ ownedPrismaClient: null,
464
+ ownedPglite: null,
465
+ };
466
+ }
467
+
468
+ const prismaOwnership = await this.resolvePrismaOwnership(container, appConfig);
469
+ const childContainer = container.createChildContainer();
470
+ childContainer.registerInstance(PrismaClient, prismaOwnership.prismaClient);
471
+ const workflowRunRepository = childContainer.resolve(PrismaWorkflowRunRepository);
472
+ const triggerSetupStateRepository = childContainer.resolve(PrismaTriggerSetupStateRepository);
473
+ const workflowDebuggerOverlayRepository = childContainer.resolve(PrismaWorkflowDebuggerOverlayRepository);
474
+ container.registerInstance(PrismaClient, prismaOwnership.prismaClient);
475
+ container.registerInstance(ApplicationTokens.PrismaClient, prismaOwnership.prismaClient);
476
+ container.registerInstance(
477
+ CoreTokens.WorkflowExecutionRepository,
478
+ new EventPublishingWorkflowExecutionRepository(workflowRunRepository, eventBus),
479
+ );
480
+ container.registerInstance(CoreTokens.TriggerSetupStateRepository, triggerSetupStateRepository);
481
+ container.registerInstance(ApplicationTokens.WorkflowRunRepository, workflowRunRepository);
482
+ container.registerInstance(
483
+ ApplicationTokens.WorkflowDebuggerOverlayRepository,
484
+ workflowDebuggerOverlayRepository as unknown as WorkflowDebuggerOverlayRepository,
485
+ );
486
+ container.registerInstance(
487
+ ApplicationTokens.WorkflowActivationRepository,
488
+ container.resolve(PrismaWorkflowActivationRepository),
489
+ );
490
+ container.registerInstance(ApplicationTokens.CredentialStore, container.resolve(PrismaCredentialStore));
491
+ if (appConfig.scheduler.kind === "bullmq") {
492
+ container.registerInstance(
493
+ ApplicationTokens.WorkerRuntimeScheduler,
494
+ new BullmqScheduler({ url: this.requireRedisUrl(appConfig.scheduler.redisUrl) }, queuePrefix),
495
+ );
496
+ }
497
+ this.registerRuntimeNodeActivationScheduler(container);
498
+ return {
499
+ ownedPrismaClient: prismaOwnership.ownedPrismaClient,
500
+ ownedPglite: prismaOwnership.ownedPglite,
501
+ };
502
+ }
503
+
504
+ private async resolvePrismaOwnership(
505
+ container: Container,
506
+ appConfig: AppConfig,
507
+ ): Promise<
508
+ Readonly<{ prismaClient: PrismaClient; ownedPrismaClient: PrismaClient | null; ownedPglite: PGlite | null }>
509
+ > {
510
+ if (container.isRegistered(PrismaClient, true)) {
511
+ return {
512
+ prismaClient: container.resolve(PrismaClient),
513
+ ownedPrismaClient: null,
514
+ ownedPglite: null,
515
+ };
516
+ }
517
+ const factory = container.resolve(PrismaClientFactory);
518
+ if (appConfig.persistence.kind === "postgresql") {
519
+ const prismaClient = factory.createPostgres(appConfig.persistence.databaseUrl);
520
+ return {
521
+ prismaClient,
522
+ ownedPrismaClient: prismaClient,
523
+ ownedPglite: null,
524
+ };
525
+ }
526
+ if (appConfig.persistence.kind !== "pglite") {
527
+ throw new Error("Unexpected database persistence mode for Prisma.");
528
+ }
529
+ const { prismaClient, pglite } = await factory.createPglite(appConfig.persistence.dataDir);
530
+ return {
531
+ prismaClient,
532
+ ownedPrismaClient: prismaClient,
533
+ ownedPglite: pglite,
534
+ };
535
+ }
536
+
537
+ private registerRuntimeNodeActivationScheduler(container: Container): void {
538
+ container.register(CoreTokens.NodeActivationScheduler, {
539
+ useFactory: instanceCachingFactory((dependencyContainer) => {
540
+ const inlineScheduler = dependencyContainer.resolve(InlineDrivingScheduler);
541
+ if (!dependencyContainer.isRegistered(ApplicationTokens.WorkerRuntimeScheduler, true)) {
542
+ return inlineScheduler;
543
+ }
544
+ return new DefaultDrivingScheduler(
545
+ new ConfigDrivenOffloadPolicy(),
546
+ dependencyContainer.resolve(ApplicationTokens.WorkerRuntimeScheduler),
547
+ inlineScheduler,
548
+ );
549
+ }),
550
+ });
551
+ }
552
+
553
+ private createBinaryStorage(repoRoot: string): InMemoryBinaryStorage | LocalFilesystemBinaryStorage {
554
+ if (!repoRoot) {
555
+ return new InMemoryBinaryStorage();
556
+ }
557
+ return new LocalFilesystemBinaryStorage(`${repoRoot}/.codemation/binary`);
558
+ }
559
+
560
+ private createRuntimeSummary(appConfig: AppConfig): BootRuntimeSummary {
561
+ return {
562
+ databasePersistence: appConfig.persistence,
563
+ eventBusKind: appConfig.eventing.kind,
564
+ queuePrefix: appConfig.scheduler.queuePrefix ?? appConfig.eventing.queuePrefix ?? "codemation",
565
+ schedulerKind: appConfig.scheduler.kind,
566
+ redisUrl: appConfig.scheduler.redisUrl ?? appConfig.eventing.redisUrl,
567
+ };
568
+ }
569
+
570
+ private requireRedisUrl(redisUrl: string | undefined): string {
571
+ if (!redisUrl) {
572
+ throw new Error("Redis-backed runtime requires runtime.eventBus.redisUrl or REDIS_URL.");
573
+ }
574
+ return redisUrl;
575
+ }
576
+
577
+ private synchronizeLiveWorkflowRepository(container: Container, workflows: ReadonlyArray<WorkflowDefinition>): void {
578
+ const liveWorkflowRepository = container.resolve(CoreTokens.LiveWorkflowRepository);
579
+ liveWorkflowRepository.setWorkflows(workflows);
580
+ if (container.isRegistered(WebhookEndpointPathValidator, true)) {
581
+ container.resolve(WebhookEndpointPathValidator).validateAndWarn(workflows);
582
+ }
583
+ }
584
+ }
@@ -1,18 +1,13 @@
1
1
  import type { PGlite } from "@electric-sql/pglite";
2
2
  import type { Container } from "@codemation/core";
3
3
  import { Engine } from "@codemation/core/bootstrap";
4
- import { WorkflowRunEventWebsocketRelay } from "../application/websocket/WorkflowRunEventWebsocketRelay";
5
- import type { BootRuntimeSummary } from "../application/dev/BootRuntimeSummary.types";
6
4
  import type { PrismaClient } from "../infrastructure/persistence/generated/prisma-client/client.js";
5
+ import { WorkflowRunEventWebsocketRelay } from "../application/websocket/WorkflowRunEventWebsocketRelay";
7
6
  import { WorkflowWebsocketServer } from "../presentation/websocket/WorkflowWebsocketServer";
8
- import type { ResolvedImplementationSelection } from "./runtime/ResolvedImplementationSelectionFactory";
9
7
 
10
- export class PreparedCodemationRuntime {
8
+ export class AppContainerLifecycle {
11
9
  constructor(
12
- readonly container: Container,
13
- readonly runtimeSummary: BootRuntimeSummary,
14
- readonly implementationSelection: ResolvedImplementationSelection,
15
- readonly usesProvidedPrismaClientOverride: boolean,
10
+ private readonly container: Container,
16
11
  private readonly ownedPrismaClient: PrismaClient | null,
17
12
  private readonly ownedPglite: PGlite | null,
18
13
  ) {}