@codemation/host 0.0.5 → 0.0.11

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 (132) 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 +11 -6
  51. package/prisma/migrations/20260315063514_init/migration.sql +16 -16
  52. package/prisma/migrations/20260316090000_workflow_debugger_overlay/migration.sql +9 -9
  53. package/prisma/migrations/20260317120000_trigger_state_store/migration.sql +3 -3
  54. package/prisma/migrations/20260317153000_trigger_setup_state/migration.sql +8 -8
  55. package/prisma/migrations/20260318110000_credentials_v2/migration.sql +49 -49
  56. package/prisma/migrations/20260319110000_credential_oauth2_material/migration.sql +28 -28
  57. package/prisma/migrations/20260319200000_codemation_auth_tables/migration.sql +56 -56
  58. package/prisma/migrations/20260320140000_user_invites_account_status/migration.sql +20 -20
  59. package/prisma/migrations/20260325120000_workflow_activation/migration.sql +8 -8
  60. package/prisma/migrations/migration_lock.toml +3 -3
  61. package/prisma/schema.prisma +179 -179
  62. package/prisma.config.ts +15 -2
  63. package/src/application/commands/WorkflowCommandHandlers.ts +9 -0
  64. package/src/application/dev/BootRuntimeSnapshotHolder.ts +2 -2
  65. package/src/application/dev/BootRuntimeSummary.types.ts +2 -2
  66. package/src/application/queries/WorkflowQueryHandlers.ts +7 -0
  67. package/src/applicationTokens.ts +1 -1
  68. package/src/bootstrap/AppContainerFactory.ts +584 -0
  69. package/src/bootstrap/{PreparedCodemationRuntime.ts → AppContainerLifecycle.ts} +3 -8
  70. package/src/bootstrap/runtime/AppConfigFactory.ts +155 -30
  71. package/src/bootstrap/runtime/DatabaseMigrations.ts +18 -0
  72. package/src/bootstrap/runtime/FrontendRuntime.ts +44 -0
  73. package/src/bootstrap/runtime/WorkerRuntime.ts +55 -0
  74. package/src/client.ts +7 -0
  75. package/src/index.ts +15 -5
  76. package/src/infrastructure/persistence/PrismaMigrationDeployer.ts +2 -2
  77. package/src/infrastructure/persistence/SchedulerPersistenceCompatibilityValidator.ts +2 -2
  78. package/src/infrastructure/scheduler/WorkerRuntimeScheduler.ts +16 -0
  79. package/src/infrastructure/scheduler/bullmq/BullmqNodeExecutionScheduler.ts +47 -0
  80. package/src/infrastructure/scheduler/bullmq/BullmqScheduler.ts +33 -0
  81. package/src/infrastructure/scheduler/bullmq/BullmqWorker.ts +48 -0
  82. package/src/infrastructure/scheduler/bullmq/RedisConnectionOptionsFactory.ts +48 -0
  83. package/src/nextServer.ts +12 -3
  84. package/src/persistenceServer.ts +2 -2
  85. package/src/presentation/config/AppConfig.ts +25 -1
  86. package/src/presentation/frontend/CodemationFrontendAuthSnapshot.ts +14 -0
  87. package/src/presentation/frontend/CodemationFrontendAuthSnapshotFactory.ts +84 -0
  88. package/src/presentation/frontend/CodemationFrontendAuthSnapshotJsonCodec.ts +58 -0
  89. package/src/presentation/frontend/FrontendAppConfig.ts +10 -0
  90. package/src/presentation/frontend/FrontendAppConfigFactory.ts +26 -0
  91. package/src/presentation/frontend/FrontendAppConfigJsonCodec.ts +58 -0
  92. package/src/presentation/http/CodemationServerGatewayFactory.ts +22 -16
  93. package/src/presentation/server/AppConfigLoader.ts +39 -0
  94. package/src/presentation/server/CodemationConsumerAppResolver.ts +2 -2
  95. package/src/presentation/server/CodemationConsumerConfigLoader.ts +3 -2
  96. package/src/server.ts +7 -0
  97. package/vitest.shared.ts +0 -4
  98. package/dist/CodemationConsumerConfigLoader-scS_RQMy.js.map +0 -1
  99. package/dist/CodemationFrontendBootstrapRequest-CNEk-C4D.js.map +0 -1
  100. package/dist/CodemationPluginListMerger-BNmaoXQL.js.map +0 -1
  101. package/dist/CodemationPluginListMerger-BRYqEk0y.d.ts +0 -793
  102. package/dist/CredentialServices-BKBGe7l3.js.map +0 -1
  103. package/dist/PrismaMigrationDeployer-B7cHGrXP.js.map +0 -1
  104. package/dist/ServerLoggerFactory-BRHxIDS7.js.map +0 -1
  105. package/dist/persistenceServer-DPSj_-oU.d.ts +0 -37
  106. package/dist/server-Dd65rNm6.js.map +0 -1
  107. package/src/bootstrap/CodemationContainerFactory.ts +0 -310
  108. package/src/bootstrap/CodemationFrontendBootstrapRequest.ts +0 -16
  109. package/src/bootstrap/CodemationWorkerBootstrapRequest.ts +0 -19
  110. package/src/bootstrap/PreparedCodemationRuntimeFactory.ts +0 -308
  111. package/src/bootstrap/boot/CliRuntimeBootService.ts +0 -27
  112. package/src/bootstrap/boot/FrontendRuntimeBootService.ts +0 -86
  113. package/src/bootstrap/boot/WorkerRuntimeBootService.ts +0 -64
  114. package/src/bootstrap/runtime/ResolvedImplementationSelectionFactory.ts +0 -118
  115. package/src/codemationApplication.ts +0 -311
  116. package/src/infrastructure/credentials/FrameworkBuiltinCredentialTypesRegistrar.ts +0 -21
  117. package/src/infrastructure/persistence/DatabasePersistenceResolver.ts +0 -91
  118. package/src/infrastructure/persistence/generated/prisma/client.d.ts +0 -1
  119. package/src/infrastructure/persistence/generated/prisma/default.d.ts +0 -1
  120. package/src/infrastructure/persistence/generated/prisma/edge.d.ts +0 -1
  121. package/src/infrastructure/persistence/generated/prisma/index.d.ts +0 -4766
  122. package/src/infrastructure/persistence/generated/prisma/package.json +0 -144
  123. package/src/infrastructure/persistence/generated/prisma/query_compiler_fast_bg.wasm +0 -0
  124. package/src/infrastructure/persistence/generated/prisma/runtime/client.d.ts +0 -3358
  125. package/src/infrastructure/persistence/generated/prisma/runtime/index-browser.d.ts +0 -90
  126. package/src/infrastructure/persistence/generated/prisma/schema.prisma +0 -35
  127. package/src/infrastructure/persistence/generated/prisma/wasm-edge-light-loader.mjs +0 -5
  128. package/src/infrastructure/persistence/generated/prisma/wasm-worker-loader.mjs +0 -5
  129. package/src/infrastructure/runtime/WorkerRuntimeScheduler.ts +0 -35
  130. package/src/presentation/config/CodemationApplicationFacade.ts +0 -5
  131. /package/dist/{decorate-B-N_5S4p.js → decorate-B0PP651O.js} +0 -0
  132. /package/dist/{decorateParam-BTcc3KNk.js → decorateParam-DrsXNPuw.js} +0 -0
@@ -1,308 +0,0 @@
1
- import type { PGlite } from "@electric-sql/pglite";
2
- import path from "node:path";
3
- import type {
4
- Container,
5
- RunEventBus,
6
- TriggerSetupStateRepository,
7
- WorkflowExecutionRepository,
8
- } from "@codemation/core";
9
- import {
10
- CoreTokens,
11
- EventPublishingWorkflowExecutionRepository,
12
- InMemoryRunEventBus,
13
- instanceCachingFactory,
14
- SystemClock,
15
- } from "@codemation/core";
16
- import {
17
- ConfigDrivenOffloadPolicy,
18
- DefaultDrivingScheduler,
19
- DefaultExecutionContextFactory,
20
- InlineDrivingScheduler,
21
- InMemoryBinaryStorage,
22
- InMemoryRunDataFactory,
23
- } from "@codemation/core/bootstrap";
24
- import { RedisRunEventBus } from "@codemation/eventbus-redis";
25
- import type { BootRuntimeSummary } from "../application/dev/BootRuntimeSummary.types";
26
- import { BootRuntimeSnapshotHolder } from "../application/dev/BootRuntimeSnapshotHolder";
27
- import { ApplicationTokens } from "../applicationTokens";
28
- import { UserAccountService } from "../domain/users/UserAccountServiceRegistry";
29
- import type { WorkflowRunRepository } from "../domain/runs/WorkflowRunRepository";
30
- import type { WorkflowDebuggerOverlayRepository } from "../domain/workflows/WorkflowDebuggerOverlayRepository";
31
- import type { CodemationAuthConfig } from "../presentation/config/CodemationAuthConfig";
32
- import type { CodemationApplicationRuntimeConfig } from "../presentation/config/CodemationConfig";
33
- import type { CodemationWhitelabelConfig } from "../presentation/config/CodemationWhitelabelConfig";
34
- import { CredentialSessionServiceImpl } from "../domain/credentials/CredentialServices";
35
- import { LocalFilesystemBinaryStorage } from "../infrastructure/binary/LocalFilesystemBinaryStorageRegistry";
36
- import {
37
- InMemoryCredentialStore,
38
- PrismaCredentialStore,
39
- } from "../infrastructure/persistence/CredentialPersistenceStore";
40
- import { InMemoryTriggerSetupStateRepository } from "../infrastructure/persistence/InMemoryTriggerSetupStateRepository";
41
- import { InMemoryWorkflowActivationRepository } from "../infrastructure/persistence/InMemoryWorkflowActivationRepository";
42
- import { InMemoryWorkflowDebuggerOverlayRepository } from "../infrastructure/persistence/InMemoryWorkflowDebuggerOverlayRepository";
43
- import { InMemoryWorkflowRunRepository } from "../infrastructure/persistence/InMemoryWorkflowRunRepository";
44
- import { PrismaClientFactory } from "../infrastructure/persistence/PrismaClientFactory";
45
- import { PrismaClient } from "../infrastructure/persistence/generated/prisma-client/client.js";
46
- import { PrismaTriggerSetupStateRepository } from "../infrastructure/persistence/PrismaTriggerSetupStateRepository";
47
- import { PrismaWorkflowActivationRepository } from "../infrastructure/persistence/PrismaWorkflowActivationRepository";
48
- import { PrismaWorkflowDebuggerOverlayRepository } from "../infrastructure/persistence/PrismaWorkflowDebuggerOverlayRepository";
49
- import { PrismaWorkflowRunRepository } from "../infrastructure/persistence/PrismaWorkflowRunRepository";
50
- import type { ResolvedDatabasePersistence } from "../infrastructure/persistence/DatabasePersistenceResolver";
51
- import { AppConfigFactory } from "./runtime/AppConfigFactory";
52
- import type { ResolvedImplementationSelection } from "./runtime/ResolvedImplementationSelectionFactory";
53
- import { ResolvedImplementationSelectionFactory } from "./runtime/ResolvedImplementationSelectionFactory";
54
- import { PreparedCodemationRuntime } from "./PreparedCodemationRuntime";
55
- import type { AppConfig } from "../presentation/config/AppConfig";
56
-
57
- type PrismaClientResolution = Readonly<{
58
- prismaClient: PrismaClient;
59
- ownedPrismaClient?: PrismaClient;
60
- ownedPglite?: PGlite;
61
- }>;
62
-
63
- type PreparedRuntimePersistence = Readonly<{
64
- workflowExecutionRepository: WorkflowExecutionRepository;
65
- triggerSetupStateRepository: TriggerSetupStateRepository;
66
- workflowRunRepository?: WorkflowRunRepository;
67
- workflowDebuggerOverlayRepository: WorkflowDebuggerOverlayRepository;
68
- prismaClient?: PrismaClient;
69
- ownedPrismaClient?: PrismaClient;
70
- ownedPglite?: PGlite;
71
- }>;
72
-
73
- export class PreparedCodemationRuntimeFactory {
74
- constructor(
75
- private readonly implementationSelectionFactory: ResolvedImplementationSelectionFactory = new ResolvedImplementationSelectionFactory(),
76
- private readonly appConfigFactory: AppConfigFactory = new AppConfigFactory(),
77
- ) {}
78
-
79
- async prepare(
80
- args: Readonly<{
81
- container: Container;
82
- repoRoot: string;
83
- consumerRoot: string;
84
- env: NodeJS.ProcessEnv;
85
- workflowSources: ReadonlyArray<string>;
86
- runtimeConfig: CodemationApplicationRuntimeConfig;
87
- applicationAuthConfig: CodemationAuthConfig | undefined;
88
- whitelabelConfig: CodemationWhitelabelConfig;
89
- hasConfiguredCredentialSessionServiceRegistration: boolean;
90
- }>,
91
- ): Promise<PreparedCodemationRuntime> {
92
- const usesProvidedPrismaClientOverride = this.hasProvidedPrismaClientOverride(args.container);
93
- const implementationSelection = this.implementationSelectionFactory.resolve({
94
- consumerRoot: args.consumerRoot,
95
- env: args.env,
96
- runtimeConfig: args.runtimeConfig,
97
- });
98
- const runtimeSummary = this.createRuntimeSummary(implementationSelection);
99
- args.container.resolve(BootRuntimeSnapshotHolder).set(runtimeSummary);
100
- const eventBus = this.createRunEventBus(implementationSelection);
101
- const persistence = await this.createRunPersistence(args.container, implementationSelection, eventBus);
102
- const binaryStorage = this.createBinaryStorage(args.repoRoot);
103
- const appConfig: AppConfig = this.appConfigFactory.create({
104
- repoRoot: args.repoRoot,
105
- consumerRoot: args.consumerRoot,
106
- env: args.env,
107
- workflowSources: args.workflowSources,
108
- runtimeConfig: args.runtimeConfig,
109
- authConfig: args.applicationAuthConfig,
110
- whitelabelConfig: args.whitelabelConfig,
111
- });
112
-
113
- args.container.registerInstance(CoreTokens.RunEventBus, eventBus);
114
- args.container.registerInstance(CoreTokens.WorkflowExecutionRepository, persistence.workflowExecutionRepository);
115
- args.container.registerInstance(CoreTokens.TriggerSetupStateRepository, persistence.triggerSetupStateRepository);
116
- args.container.registerInstance(CoreTokens.RunDataFactory, new InMemoryRunDataFactory());
117
- args.container.registerInstance(CoreTokens.BinaryStorage, binaryStorage);
118
- args.container.registerInstance(
119
- CoreTokens.ExecutionContextFactory,
120
- new DefaultExecutionContextFactory(binaryStorage),
121
- );
122
- args.container.registerInstance(ApplicationTokens.AppConfig, appConfig);
123
- args.container.registerInstance(ApplicationTokens.Clock, new SystemClock());
124
- args.container.registerInstance(ApplicationTokens.CodemationAuthConfig, args.applicationAuthConfig);
125
- args.container.registerInstance(ApplicationTokens.CodemationWhitelabelConfig, args.whitelabelConfig);
126
- args.container.registerInstance(ApplicationTokens.WebSocketPort, this.resolveWebSocketPort(args.env));
127
- args.container.registerInstance(ApplicationTokens.WebSocketBindHost, args.env.CODEMATION_WS_BIND_HOST ?? "0.0.0.0");
128
- args.container.register(UserAccountService, {
129
- useFactory: instanceCachingFactory((dependencyContainer) => {
130
- const prismaClient = dependencyContainer.isRegistered(PrismaClient, true)
131
- ? dependencyContainer.resolve(PrismaClient)
132
- : undefined;
133
- return new UserAccountService(
134
- dependencyContainer.resolve(ApplicationTokens.CodemationAuthConfig),
135
- prismaClient,
136
- );
137
- }),
138
- });
139
- args.container.registerInstance(
140
- ApplicationTokens.WorkflowDebuggerOverlayRepository,
141
- persistence.workflowDebuggerOverlayRepository,
142
- );
143
- if (persistence.workflowRunRepository) {
144
- args.container.registerInstance(ApplicationTokens.WorkflowRunRepository, persistence.workflowRunRepository);
145
- }
146
- if (persistence.prismaClient) {
147
- args.container.registerInstance(PrismaClient, persistence.prismaClient);
148
- args.container.registerInstance(ApplicationTokens.PrismaClient, persistence.prismaClient);
149
- }
150
- const workflowActivationRepository = persistence.prismaClient
151
- ? args.container.resolve(PrismaWorkflowActivationRepository)
152
- : args.container.resolve(InMemoryWorkflowActivationRepository);
153
- args.container.registerInstance(ApplicationTokens.WorkflowActivationRepository, workflowActivationRepository);
154
- if (implementationSelection.databasePersistence.kind !== "none") {
155
- args.container.registerInstance(ApplicationTokens.CredentialStore, args.container.resolve(PrismaCredentialStore));
156
- } else {
157
- args.container.registerInstance(
158
- ApplicationTokens.CredentialStore,
159
- args.container.resolve(InMemoryCredentialStore),
160
- );
161
- }
162
- if (!args.hasConfiguredCredentialSessionServiceRegistration) {
163
- args.container.register(CoreTokens.CredentialSessionService, {
164
- useFactory: instanceCachingFactory((dependencyContainer) =>
165
- dependencyContainer.resolve(CredentialSessionServiceImpl),
166
- ),
167
- });
168
- }
169
- if (implementationSelection.workerRuntimeScheduler) {
170
- args.container.registerInstance(
171
- ApplicationTokens.WorkerRuntimeScheduler,
172
- implementationSelection.workerRuntimeScheduler,
173
- );
174
- }
175
- this.registerRuntimeNodeActivationScheduler(args.container);
176
-
177
- return new PreparedCodemationRuntime(
178
- args.container,
179
- runtimeSummary,
180
- implementationSelection,
181
- usesProvidedPrismaClientOverride,
182
- persistence.ownedPrismaClient ?? null,
183
- persistence.ownedPglite ?? null,
184
- );
185
- }
186
-
187
- private createRuntimeSummary(selection: ResolvedImplementationSelection): BootRuntimeSummary {
188
- return {
189
- databasePersistence: selection.databasePersistence,
190
- eventBusKind: selection.eventBusKind,
191
- queuePrefix: selection.queuePrefix,
192
- schedulerKind: selection.schedulerKind,
193
- redisUrl: selection.redisUrl,
194
- };
195
- }
196
-
197
- private createRunEventBus(selection: ResolvedImplementationSelection): RunEventBus {
198
- if (selection.eventBusKind === "redis") {
199
- return new RedisRunEventBus(this.requireRedisUrl(selection.redisUrl), selection.queuePrefix);
200
- }
201
- return new InMemoryRunEventBus();
202
- }
203
-
204
- private async createRunPersistence(
205
- container: Container,
206
- selection: ResolvedImplementationSelection,
207
- eventBus: RunEventBus,
208
- ): Promise<PreparedRuntimePersistence> {
209
- if (selection.databasePersistence.kind === "none") {
210
- const workflowRunRepository = container.resolve(InMemoryWorkflowRunRepository);
211
- return {
212
- workflowRunRepository,
213
- triggerSetupStateRepository: container.resolve(InMemoryTriggerSetupStateRepository),
214
- workflowDebuggerOverlayRepository: container.resolve(InMemoryWorkflowDebuggerOverlayRepository),
215
- workflowExecutionRepository: new EventPublishingWorkflowExecutionRepository(workflowRunRepository, eventBus),
216
- };
217
- }
218
- const prismaClientResolution = await this.resolveInjectedOrOwnedPrismaClient(
219
- container,
220
- selection.databasePersistence,
221
- );
222
- const childContainer = container.createChildContainer();
223
- childContainer.registerInstance(PrismaClient, prismaClientResolution.prismaClient);
224
- const workflowRunRepository = childContainer.resolve(PrismaWorkflowRunRepository);
225
- const triggerSetupStateRepository = childContainer.resolve(PrismaTriggerSetupStateRepository);
226
- const workflowDebuggerOverlayRepository = childContainer.resolve(PrismaWorkflowDebuggerOverlayRepository);
227
- return {
228
- prismaClient: prismaClientResolution.prismaClient,
229
- ownedPrismaClient: prismaClientResolution.ownedPrismaClient,
230
- ownedPglite: prismaClientResolution.ownedPglite,
231
- workflowRunRepository,
232
- triggerSetupStateRepository,
233
- workflowDebuggerOverlayRepository,
234
- workflowExecutionRepository: new EventPublishingWorkflowExecutionRepository(workflowRunRepository, eventBus),
235
- };
236
- }
237
-
238
- private hasProvidedPrismaClientOverride(container: Container): boolean {
239
- return container.isRegistered(PrismaClient, true);
240
- }
241
-
242
- private async resolveInjectedOrOwnedPrismaClient(
243
- container: Container,
244
- persistence: Exclude<ResolvedDatabasePersistence, Readonly<{ kind: "none" }>>,
245
- ): Promise<PrismaClientResolution> {
246
- if (this.hasProvidedPrismaClientOverride(container)) {
247
- return {
248
- prismaClient: container.resolve(PrismaClient),
249
- };
250
- }
251
- const factory = container.resolve(PrismaClientFactory);
252
- if (persistence.kind === "postgresql") {
253
- const prismaClient = factory.createPostgres(persistence.databaseUrl);
254
- return {
255
- prismaClient,
256
- ownedPrismaClient: prismaClient,
257
- };
258
- }
259
- if (persistence.kind !== "pglite") {
260
- throw new Error("Unexpected database persistence mode for Prisma.");
261
- }
262
- const { prismaClient, pglite } = await factory.createPglite(persistence.dataDir);
263
- return {
264
- prismaClient,
265
- ownedPrismaClient: prismaClient,
266
- ownedPglite: pglite,
267
- };
268
- }
269
-
270
- private registerRuntimeNodeActivationScheduler(container: Container): void {
271
- container.register(CoreTokens.NodeActivationScheduler, {
272
- useFactory: instanceCachingFactory((dependencyContainer) => {
273
- const inlineScheduler = dependencyContainer.resolve(InlineDrivingScheduler);
274
- if (!dependencyContainer.isRegistered(ApplicationTokens.WorkerRuntimeScheduler, true)) {
275
- return inlineScheduler;
276
- }
277
- return new DefaultDrivingScheduler(
278
- new ConfigDrivenOffloadPolicy(),
279
- dependencyContainer.resolve(ApplicationTokens.WorkerRuntimeScheduler),
280
- inlineScheduler,
281
- );
282
- }),
283
- });
284
- }
285
-
286
- private createBinaryStorage(repoRoot: string): InMemoryBinaryStorage | LocalFilesystemBinaryStorage {
287
- if (!repoRoot) {
288
- return new InMemoryBinaryStorage();
289
- }
290
- return new LocalFilesystemBinaryStorage(path.join(repoRoot, ".codemation", "binary"));
291
- }
292
-
293
- private requireRedisUrl(redisUrl: string | undefined): string {
294
- if (!redisUrl) {
295
- throw new Error("Redis-backed runtime requires runtime.eventBus.redisUrl or REDIS_URL.");
296
- }
297
- return redisUrl;
298
- }
299
-
300
- private resolveWebSocketPort(env: Readonly<NodeJS.ProcessEnv>): number {
301
- const rawPort = env.CODEMATION_WS_PORT ?? env.VITE_CODEMATION_WS_PORT;
302
- const parsedPort = Number(rawPort);
303
- if (Number.isInteger(parsedPort) && parsedPort > 0) {
304
- return parsedPort;
305
- }
306
- return 3001;
307
- }
308
- }
@@ -1,27 +0,0 @@
1
- import { PrismaMigrationDeployer } from "../../infrastructure/persistence/PrismaMigrationDeployer";
2
- import { RuntimeWorkflowActivationPolicy } from "../../infrastructure/persistence/RuntimeWorkflowActivationPolicy";
3
- import { ApplicationTokens } from "../../applicationTokens";
4
- import { PreparedCodemationRuntime } from "../PreparedCodemationRuntime";
5
-
6
- export class CliRuntimeBootService {
7
- async boot(args: Readonly<{ preparedRuntime: PreparedCodemationRuntime }>): Promise<void> {
8
- await this.applyDatabaseMigrations(args.preparedRuntime);
9
- await args.preparedRuntime.container
10
- .resolve(RuntimeWorkflowActivationPolicy)
11
- .hydrateFromRepository(args.preparedRuntime.container.resolve(ApplicationTokens.WorkflowActivationRepository));
12
- }
13
-
14
- private async applyDatabaseMigrations(preparedRuntime: PreparedCodemationRuntime): Promise<void> {
15
- const appConfig = preparedRuntime.container.resolve(ApplicationTokens.AppConfig);
16
- if (
17
- preparedRuntime.implementationSelection.databasePersistence.kind === "none" ||
18
- preparedRuntime.usesProvidedPrismaClientOverride ||
19
- appConfig.env.CODEMATION_SKIP_STARTUP_MIGRATIONS === "true"
20
- ) {
21
- return;
22
- }
23
- await preparedRuntime.container
24
- .resolve(PrismaMigrationDeployer)
25
- .deployPersistence(preparedRuntime.implementationSelection.databasePersistence, appConfig.env);
26
- }
27
- }
@@ -1,86 +0,0 @@
1
- import { CoreTokens } from "@codemation/core";
2
- import { instanceCachingFactory } from "@codemation/core";
3
- import { Engine } from "@codemation/core/bootstrap";
4
- import { PrismaMigrationDeployer } from "../../infrastructure/persistence/PrismaMigrationDeployer";
5
- import { RuntimeWorkflowActivationPolicy } from "../../infrastructure/persistence/RuntimeWorkflowActivationPolicy";
6
- import { DevelopmentSessionBypassVerifier } from "../../infrastructure/auth/DevelopmentSessionBypassVerifier";
7
- import { AuthJsSessionVerifier } from "../../infrastructure/auth/AuthJsSessionVerifier";
8
- import { ApplicationTokens } from "../../applicationTokens";
9
- import { WorkflowRunEventWebsocketRelay } from "../../application/websocket/WorkflowRunEventWebsocketRelay";
10
- import { ApiPaths } from "../../presentation/http/ApiPaths";
11
- import { WorkflowWebsocketServer } from "../../presentation/websocket/WorkflowWebsocketServer";
12
- import { PreparedCodemationRuntime } from "../PreparedCodemationRuntime";
13
-
14
- export class FrontendRuntimeBootService {
15
- async boot(
16
- args: Readonly<{
17
- preparedRuntime: PreparedCodemationRuntime;
18
- skipPresentationServers?: boolean;
19
- }>,
20
- ): Promise<void> {
21
- await this.applyDatabaseMigrations(args.preparedRuntime);
22
- await this.hydrateWorkflowActivationPolicy(args.preparedRuntime);
23
- this.registerSessionVerification(args.preparedRuntime);
24
- args.preparedRuntime.container.registerInstance(CoreTokens.WebhookBasePath, ApiPaths.webhooks());
25
- if (args.skipPresentationServers === true) {
26
- return;
27
- }
28
- const workflowRepository = args.preparedRuntime.container.resolve(CoreTokens.WorkflowRepository);
29
- await args.preparedRuntime.container.resolve(Engine).start([...workflowRepository.list()]);
30
- await args.preparedRuntime.container.resolve(WorkflowWebsocketServer).start();
31
- await args.preparedRuntime.container.resolve(WorkflowRunEventWebsocketRelay).start();
32
- }
33
-
34
- private async applyDatabaseMigrations(preparedRuntime: PreparedCodemationRuntime): Promise<void> {
35
- const appConfig = preparedRuntime.container.resolve(ApplicationTokens.AppConfig);
36
- if (
37
- preparedRuntime.implementationSelection.databasePersistence.kind === "none" ||
38
- preparedRuntime.usesProvidedPrismaClientOverride ||
39
- appConfig.env.CODEMATION_SKIP_STARTUP_MIGRATIONS === "true"
40
- ) {
41
- return;
42
- }
43
- await preparedRuntime.container
44
- .resolve(PrismaMigrationDeployer)
45
- .deployPersistence(preparedRuntime.implementationSelection.databasePersistence, appConfig.env);
46
- }
47
-
48
- private async hydrateWorkflowActivationPolicy(preparedRuntime: PreparedCodemationRuntime): Promise<void> {
49
- await preparedRuntime.container
50
- .resolve(RuntimeWorkflowActivationPolicy)
51
- .hydrateFromRepository(preparedRuntime.container.resolve(ApplicationTokens.WorkflowActivationRepository));
52
- }
53
-
54
- private registerSessionVerification(preparedRuntime: PreparedCodemationRuntime): void {
55
- const appConfig = preparedRuntime.container.resolve(ApplicationTokens.AppConfig);
56
- const env = appConfig.env;
57
- const authConfig = appConfig.auth;
58
- const isProduction = env.NODE_ENV === "production";
59
- if (isProduction && !authConfig) {
60
- throw new Error("CodemationConfig.auth is required when NODE_ENV is production.");
61
- }
62
- if (isProduction && authConfig?.allowUnauthenticatedInDevelopment === true) {
63
- throw new Error(
64
- "CodemationAuthConfig.allowUnauthenticatedInDevelopment is not allowed when NODE_ENV is production.",
65
- );
66
- }
67
- const bypassAllowed = !isProduction && authConfig?.allowUnauthenticatedInDevelopment === true;
68
- if (bypassAllowed) {
69
- preparedRuntime.container.register(ApplicationTokens.SessionVerifier, {
70
- useFactory: instanceCachingFactory((dependencyContainer) =>
71
- dependencyContainer.resolve(DevelopmentSessionBypassVerifier),
72
- ),
73
- });
74
- return;
75
- }
76
- const secret = env.AUTH_SECRET ?? "";
77
- if (!secret) {
78
- throw new Error(
79
- "AUTH_SECRET is required unless CodemationAuthConfig.allowUnauthenticatedInDevelopment is enabled in a non-production environment.",
80
- );
81
- }
82
- preparedRuntime.container.register(ApplicationTokens.SessionVerifier, {
83
- useFactory: instanceCachingFactory((dependencyContainer) => dependencyContainer.resolve(AuthJsSessionVerifier)),
84
- });
85
- }
86
- }
@@ -1,64 +0,0 @@
1
- import { CoreTokens } from "@codemation/core";
2
- import { Engine } from "@codemation/core/bootstrap";
3
- import type { WorkerRuntimeHandle } from "../../infrastructure/runtime/WorkerRuntimeScheduler";
4
- import { PrismaMigrationDeployer } from "../../infrastructure/persistence/PrismaMigrationDeployer";
5
- import { RuntimeWorkflowActivationPolicy } from "../../infrastructure/persistence/RuntimeWorkflowActivationPolicy";
6
- import { ApplicationTokens } from "../../applicationTokens";
7
- import { ApiPaths } from "../../presentation/http/ApiPaths";
8
- import { PreparedCodemationRuntime } from "../PreparedCodemationRuntime";
9
-
10
- export class WorkerRuntimeBootService {
11
- async boot(
12
- args: Readonly<{
13
- preparedRuntime: PreparedCodemationRuntime;
14
- queues: ReadonlyArray<string>;
15
- }>,
16
- ): Promise<Readonly<{ stop: () => Promise<void> }>> {
17
- await this.applyDatabaseMigrations(args.preparedRuntime);
18
- await args.preparedRuntime.container
19
- .resolve(RuntimeWorkflowActivationPolicy)
20
- .hydrateFromRepository(args.preparedRuntime.container.resolve(ApplicationTokens.WorkflowActivationRepository));
21
- args.preparedRuntime.container.registerInstance(CoreTokens.WebhookBasePath, ApiPaths.webhooks());
22
- if (!args.preparedRuntime.container.isRegistered(ApplicationTokens.WorkerRuntimeScheduler, true)) {
23
- throw new Error("Worker mode requires a BullMQ scheduler backed by a Redis event bus.");
24
- }
25
- const workflows = args.preparedRuntime.container.resolve(CoreTokens.WorkflowRepository).list();
26
- const engine = args.preparedRuntime.container.resolve(Engine);
27
- await engine.start([...workflows]);
28
- const workflowsById = new Map(workflows.map((workflow) => [workflow.id, workflow] as const));
29
- const scheduler = args.preparedRuntime.container.resolve(ApplicationTokens.WorkerRuntimeScheduler);
30
- const executionLimitsPolicy = args.preparedRuntime.container.resolve(CoreTokens.EngineExecutionLimitsPolicy);
31
- const worker: WorkerRuntimeHandle = scheduler.createWorker({
32
- queues: args.queues,
33
- workflowsById,
34
- nodeResolver: args.preparedRuntime.container.resolve(CoreTokens.NodeResolver),
35
- credentialSessions: args.preparedRuntime.container.resolve(CoreTokens.CredentialSessionService),
36
- workflowExecutionRepository: args.preparedRuntime.container.resolve(CoreTokens.WorkflowExecutionRepository),
37
- continuation: engine,
38
- binaryStorage: args.preparedRuntime.container.resolve(CoreTokens.BinaryStorage),
39
- workflows: args.preparedRuntime.container.resolve(CoreTokens.WorkflowRunnerService),
40
- executionLimitsPolicy,
41
- });
42
- return {
43
- stop: async () => {
44
- await worker.stop();
45
- await scheduler.close();
46
- await args.preparedRuntime.stop({ stopWebsocketServer: false });
47
- },
48
- };
49
- }
50
-
51
- private async applyDatabaseMigrations(preparedRuntime: PreparedCodemationRuntime): Promise<void> {
52
- const appConfig = preparedRuntime.container.resolve(ApplicationTokens.AppConfig);
53
- if (
54
- preparedRuntime.implementationSelection.databasePersistence.kind === "none" ||
55
- preparedRuntime.usesProvidedPrismaClientOverride ||
56
- appConfig.env.CODEMATION_SKIP_STARTUP_MIGRATIONS === "true"
57
- ) {
58
- return;
59
- }
60
- await preparedRuntime.container
61
- .resolve(PrismaMigrationDeployer)
62
- .deployPersistence(preparedRuntime.implementationSelection.databasePersistence, appConfig.env);
63
- }
64
- }
@@ -1,118 +0,0 @@
1
- import { BullmqScheduler } from "@codemation/queue-bullmq";
2
- import type { WorkerRuntimeScheduler } from "../../infrastructure/runtime/WorkerRuntimeScheduler";
3
- import type { ResolvedDatabasePersistence } from "../../infrastructure/persistence/DatabasePersistenceResolver";
4
- import { DatabasePersistenceResolver } from "../../infrastructure/persistence/DatabasePersistenceResolver";
5
- import { SchedulerPersistenceCompatibilityValidator } from "../../infrastructure/persistence/SchedulerPersistenceCompatibilityValidator";
6
- import type {
7
- CodemationApplicationRuntimeConfig,
8
- CodemationEventBusKind,
9
- CodemationSchedulerKind,
10
- } from "../../presentation/config/CodemationConfig";
11
-
12
- export type ResolvedImplementationSelection = Readonly<{
13
- databasePersistence: ResolvedDatabasePersistence;
14
- eventBusKind: CodemationEventBusKind;
15
- queuePrefix: string;
16
- redisUrl?: string;
17
- schedulerKind: CodemationSchedulerKind;
18
- workerRuntimeScheduler?: WorkerRuntimeScheduler;
19
- }>;
20
-
21
- export class ResolvedImplementationSelectionFactory {
22
- constructor(
23
- private readonly databasePersistenceResolver: DatabasePersistenceResolver = new DatabasePersistenceResolver(),
24
- private readonly schedulerPersistenceCompatibilityValidator: SchedulerPersistenceCompatibilityValidator = new SchedulerPersistenceCompatibilityValidator(),
25
- ) {}
26
-
27
- resolve(
28
- args: Readonly<{
29
- consumerRoot: string;
30
- runtimeConfig: CodemationApplicationRuntimeConfig;
31
- env: Readonly<NodeJS.ProcessEnv>;
32
- }>,
33
- ): ResolvedImplementationSelection {
34
- const databasePersistence = this.databasePersistenceResolver.resolve({
35
- runtimeConfig: args.runtimeConfig,
36
- env: args.env,
37
- consumerRoot: args.consumerRoot,
38
- });
39
- const redisUrl = args.runtimeConfig.eventBus?.redisUrl ?? args.env.REDIS_URL;
40
- const schedulerKind = this.resolveSchedulerKind(args.runtimeConfig, args.env, redisUrl);
41
- const eventBusKind = this.resolveEventBusKind(args.runtimeConfig, args.env, schedulerKind, redisUrl);
42
- const queuePrefix =
43
- args.runtimeConfig.scheduler?.queuePrefix ??
44
- args.runtimeConfig.eventBus?.queuePrefix ??
45
- args.env.QUEUE_PREFIX ??
46
- "codemation";
47
- if (schedulerKind === "bullmq" && eventBusKind !== "redis") {
48
- throw new Error(
49
- "BullMQ scheduling requires a Redis event bus so worker events can be forwarded to connected clients.",
50
- );
51
- }
52
- if (eventBusKind === "redis" && !redisUrl) {
53
- throw new Error("Redis event bus requires runtime.eventBus.redisUrl or REDIS_URL.");
54
- }
55
- this.schedulerPersistenceCompatibilityValidator.validate({ schedulerKind, persistence: databasePersistence });
56
- const workerRuntimeScheduler =
57
- schedulerKind === "bullmq"
58
- ? new BullmqScheduler({ url: this.requireRedisUrl(redisUrl) }, queuePrefix)
59
- : undefined;
60
- return {
61
- databasePersistence,
62
- eventBusKind,
63
- queuePrefix,
64
- redisUrl,
65
- schedulerKind,
66
- workerRuntimeScheduler,
67
- };
68
- }
69
-
70
- private resolveSchedulerKind(
71
- runtimeConfig: CodemationApplicationRuntimeConfig,
72
- env: Readonly<NodeJS.ProcessEnv>,
73
- redisUrl: string | undefined,
74
- ): CodemationSchedulerKind {
75
- const configuredKind = runtimeConfig.scheduler?.kind ?? this.readSchedulerKind(env.CODEMATION_SCHEDULER);
76
- if (configuredKind) {
77
- return configuredKind;
78
- }
79
- return redisUrl ? "bullmq" : "local";
80
- }
81
-
82
- private resolveEventBusKind(
83
- runtimeConfig: CodemationApplicationRuntimeConfig,
84
- env: Readonly<NodeJS.ProcessEnv>,
85
- schedulerKind: CodemationSchedulerKind,
86
- redisUrl: string | undefined,
87
- ): CodemationEventBusKind {
88
- const configuredKind = runtimeConfig.eventBus?.kind ?? this.readEventBusKind(env.CODEMATION_EVENT_BUS);
89
- if (configuredKind) {
90
- return configuredKind;
91
- }
92
- if (schedulerKind === "bullmq") {
93
- return "redis";
94
- }
95
- return redisUrl ? "redis" : "memory";
96
- }
97
-
98
- private readSchedulerKind(value: string | undefined): CodemationSchedulerKind | undefined {
99
- if (value === "local" || value === "bullmq") {
100
- return value;
101
- }
102
- return undefined;
103
- }
104
-
105
- private readEventBusKind(value: string | undefined): CodemationEventBusKind | undefined {
106
- if (value === "memory" || value === "redis") {
107
- return value;
108
- }
109
- return undefined;
110
- }
111
-
112
- private requireRedisUrl(redisUrl: string | undefined): string {
113
- if (!redisUrl) {
114
- throw new Error("Redis-backed runtime requires runtime.eventBus.redisUrl or REDIS_URL.");
115
- }
116
- return redisUrl;
117
- }
118
- }