@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,14 +1,36 @@
1
- import type { CodemationDatabaseConfig, CodemationEventBusKind, CodemationSchedulerKind } from "./CodemationConfig";
1
+ import type { AnyCredentialType, WorkflowDefinition } from "@codemation/core";
2
+ import type { CodemationContainerRegistration } from "../../bootstrap/CodemationContainerRegistration";
3
+ import type { CodemationPlugin } from "./CodemationPlugin";
4
+ import type {
5
+ CodemationDatabaseConfig,
6
+ CodemationEngineExecutionLimitsConfig,
7
+ CodemationEventBusKind,
8
+ CodemationSchedulerKind,
9
+ } from "./CodemationConfig";
10
+ import type { CodemationLogConfig } from "./CodemationLogConfig";
2
11
  import type { CodemationAuthConfig } from "./CodemationAuthConfig";
3
12
  import type { CodemationWhitelabelConfig } from "./CodemationWhitelabelConfig";
4
13
 
14
+ export type AppPersistenceConfig =
15
+ | Readonly<{ kind: "none" }>
16
+ | Readonly<{ kind: "postgresql"; databaseUrl: string }>
17
+ | Readonly<{ kind: "pglite"; dataDir: string }>;
18
+
5
19
  export interface AppConfig {
6
20
  readonly consumerRoot: string;
7
21
  readonly repoRoot: string;
8
22
  readonly env: Readonly<NodeJS.ProcessEnv>;
9
23
  readonly workflowSources: ReadonlyArray<string>;
24
+ readonly workflows: ReadonlyArray<WorkflowDefinition>;
25
+ readonly containerRegistrations: ReadonlyArray<CodemationContainerRegistration<unknown>>;
26
+ readonly credentialTypes: ReadonlyArray<AnyCredentialType>;
27
+ readonly plugins: ReadonlyArray<CodemationPlugin>;
28
+ readonly hasConfiguredCredentialSessionServiceRegistration: boolean;
29
+ readonly log?: CodemationLogConfig;
30
+ readonly engineExecutionLimits?: CodemationEngineExecutionLimitsConfig;
10
31
  readonly databaseUrl?: string;
11
32
  readonly database?: CodemationDatabaseConfig;
33
+ readonly persistence: AppPersistenceConfig;
12
34
  readonly scheduler: Readonly<{
13
35
  kind: CodemationSchedulerKind;
14
36
  queuePrefix?: string;
@@ -22,4 +44,6 @@ export interface AppConfig {
22
44
  }>;
23
45
  readonly auth?: CodemationAuthConfig;
24
46
  readonly whitelabel: CodemationWhitelabelConfig;
47
+ readonly webSocketPort: number;
48
+ readonly webSocketBindHost: string;
25
49
  }
@@ -0,0 +1,14 @@
1
+ import type { CodemationAuthConfig } from "../config/CodemationAuthConfig";
2
+
3
+ export type CodemationFrontendAuthProviderSnapshot = Readonly<{
4
+ id: string;
5
+ name: string;
6
+ }>;
7
+
8
+ export type CodemationFrontendAuthSnapshot = Readonly<{
9
+ config: CodemationAuthConfig | undefined;
10
+ credentialsEnabled: boolean;
11
+ oauthProviders: ReadonlyArray<CodemationFrontendAuthProviderSnapshot>;
12
+ secret: string | null;
13
+ uiAuthEnabled: boolean;
14
+ }>;
@@ -0,0 +1,84 @@
1
+ import { injectable } from "@codemation/core";
2
+
3
+ import type { AppConfig } from "../config/AppConfig";
4
+ import type {
5
+ CodemationAuthConfig,
6
+ CodemationAuthOAuthProviderConfig,
7
+ CodemationAuthOidcProviderConfig,
8
+ } from "../config/CodemationAuthConfig";
9
+
10
+ import type {
11
+ CodemationFrontendAuthProviderSnapshot,
12
+ CodemationFrontendAuthSnapshot,
13
+ } from "./CodemationFrontendAuthSnapshot";
14
+
15
+ @injectable()
16
+ export class CodemationFrontendAuthSnapshotFactory {
17
+ createFromAppConfig(appConfig: AppConfig): CodemationFrontendAuthSnapshot {
18
+ return this.createFromResolvedInputs({
19
+ authConfig: appConfig.auth,
20
+ env: appConfig.env,
21
+ uiAuthEnabled: this.resolveUiAuthEnabled(appConfig.auth, appConfig.env),
22
+ });
23
+ }
24
+
25
+ createFromResolvedInputs(
26
+ args: Readonly<{
27
+ authConfig: CodemationAuthConfig | undefined;
28
+ env: NodeJS.ProcessEnv;
29
+ uiAuthEnabled: boolean;
30
+ }>,
31
+ ): CodemationFrontendAuthSnapshot {
32
+ return {
33
+ config: args.authConfig,
34
+ credentialsEnabled: args.authConfig?.kind === "local",
35
+ oauthProviders: this.createOauthProviders(args.authConfig),
36
+ secret: this.resolveAuthSecret(args.env),
37
+ uiAuthEnabled: args.uiAuthEnabled,
38
+ };
39
+ }
40
+
41
+ private resolveUiAuthEnabled(authConfig: CodemationAuthConfig | undefined, env: NodeJS.ProcessEnv): boolean {
42
+ return !(env.NODE_ENV !== "production" && authConfig?.allowUnauthenticatedInDevelopment === true);
43
+ }
44
+
45
+ private resolveAuthSecret(env: NodeJS.ProcessEnv): string | null {
46
+ const secret =
47
+ env.AUTH_SECRET?.trim() ||
48
+ (env.NODE_ENV === "development" ? "codemation-dev-auth-secret-not-for-production" : undefined);
49
+ return secret && secret.trim().length > 0 ? secret : null;
50
+ }
51
+
52
+ private createOauthProviders(
53
+ authConfig: CodemationAuthConfig | undefined,
54
+ ): ReadonlyArray<CodemationFrontendAuthProviderSnapshot> {
55
+ if (!authConfig) {
56
+ return [];
57
+ }
58
+ const providers: CodemationFrontendAuthProviderSnapshot[] = [];
59
+ for (const provider of authConfig.oauth ?? []) {
60
+ providers.push(this.createOAuthProvider(provider));
61
+ }
62
+ for (const provider of authConfig.oidc ?? []) {
63
+ providers.push(this.createOidcProvider(provider));
64
+ }
65
+ return providers;
66
+ }
67
+
68
+ private createOAuthProvider(provider: CodemationAuthOAuthProviderConfig): CodemationFrontendAuthProviderSnapshot {
69
+ if (provider.provider === "google") {
70
+ return { id: "google", name: "Google" };
71
+ }
72
+ if (provider.provider === "github") {
73
+ return { id: "github", name: "GitHub" };
74
+ }
75
+ return { id: "microsoft-entra-id", name: "Microsoft" };
76
+ }
77
+
78
+ private createOidcProvider(provider: CodemationAuthOidcProviderConfig): CodemationFrontendAuthProviderSnapshot {
79
+ return {
80
+ id: provider.id,
81
+ name: provider.id,
82
+ };
83
+ }
84
+ }
@@ -0,0 +1,58 @@
1
+ import type { CodemationAuthConfig } from "../config/CodemationAuthConfig";
2
+
3
+ import type {
4
+ CodemationFrontendAuthProviderSnapshot,
5
+ CodemationFrontendAuthSnapshot,
6
+ } from "./CodemationFrontendAuthSnapshot";
7
+
8
+ export class CodemationFrontendAuthSnapshotJsonCodec {
9
+ serialize(snapshot: CodemationFrontendAuthSnapshot): string {
10
+ return JSON.stringify(snapshot);
11
+ }
12
+
13
+ deserialize(serialized: string | undefined): CodemationFrontendAuthSnapshot | null {
14
+ if (!serialized || serialized.trim().length === 0) {
15
+ return null;
16
+ }
17
+ try {
18
+ const parsed = JSON.parse(serialized) as Partial<CodemationFrontendAuthSnapshot> | null;
19
+ if (!parsed || typeof parsed !== "object") {
20
+ return null;
21
+ }
22
+ return {
23
+ config: this.resolveAuthConfig(parsed.config),
24
+ credentialsEnabled: parsed.credentialsEnabled === true,
25
+ oauthProviders: this.resolveOauthProviders(parsed.oauthProviders),
26
+ secret: typeof parsed.secret === "string" && parsed.secret.trim().length > 0 ? parsed.secret : null,
27
+ uiAuthEnabled: parsed.uiAuthEnabled !== false,
28
+ };
29
+ } catch {
30
+ return null;
31
+ }
32
+ }
33
+
34
+ private resolveAuthConfig(value: unknown): CodemationAuthConfig | undefined {
35
+ return value && typeof value === "object" ? (value as CodemationAuthConfig) : undefined;
36
+ }
37
+
38
+ private resolveOauthProviders(value: unknown): ReadonlyArray<CodemationFrontendAuthProviderSnapshot> {
39
+ if (!Array.isArray(value)) {
40
+ return [];
41
+ }
42
+ return value.flatMap((entry) => {
43
+ if (!entry || typeof entry !== "object") {
44
+ return [];
45
+ }
46
+ const provider = entry as Partial<CodemationFrontendAuthProviderSnapshot>;
47
+ if (typeof provider.id !== "string" || typeof provider.name !== "string") {
48
+ return [];
49
+ }
50
+ return [
51
+ {
52
+ id: provider.id,
53
+ name: provider.name,
54
+ },
55
+ ];
56
+ });
57
+ }
58
+ }
@@ -0,0 +1,10 @@
1
+ import type { CodemationFrontendAuthSnapshot } from "./CodemationFrontendAuthSnapshot";
2
+
3
+ /**
4
+ * Frontend-safe projection of host app configuration for packaged Next UI and SSR.
5
+ */
6
+ export type FrontendAppConfig = Readonly<{
7
+ auth: CodemationFrontendAuthSnapshot;
8
+ productName: string;
9
+ logoUrl: string | null;
10
+ }>;
@@ -0,0 +1,26 @@
1
+ import { inject, injectable } from "@codemation/core";
2
+ import { ApplicationTokens } from "../../applicationTokens";
3
+ import type { AppConfig } from "../config/AppConfig";
4
+ import { ApiPaths } from "../http/ApiPaths";
5
+ import type { FrontendAppConfig } from "./FrontendAppConfig";
6
+ import { CodemationFrontendAuthSnapshotFactory } from "./CodemationFrontendAuthSnapshotFactory";
7
+
8
+ @injectable()
9
+ export class FrontendAppConfigFactory {
10
+ constructor(
11
+ @inject(ApplicationTokens.AppConfig)
12
+ private readonly appConfig: AppConfig,
13
+ @inject(CodemationFrontendAuthSnapshotFactory)
14
+ private readonly authSnapshotFactory: CodemationFrontendAuthSnapshotFactory,
15
+ ) {}
16
+
17
+ create(): FrontendAppConfig {
18
+ const rawProductName = this.appConfig.whitelabel.productName?.trim();
19
+ const rawLogoPath = this.appConfig.whitelabel.logoPath?.trim();
20
+ return {
21
+ auth: this.authSnapshotFactory.createFromAppConfig(this.appConfig),
22
+ productName: rawProductName && rawProductName.length > 0 ? rawProductName : "Codemation",
23
+ logoUrl: rawLogoPath && rawLogoPath.length > 0 ? ApiPaths.whitelabelLogo() : null,
24
+ };
25
+ }
26
+ }
@@ -0,0 +1,58 @@
1
+ import type { CodemationAuthConfig } from "../config/CodemationAuthConfig";
2
+ import type { FrontendAppConfig } from "./FrontendAppConfig";
3
+ import type { CodemationFrontendAuthProviderSnapshot } from "./CodemationFrontendAuthSnapshot";
4
+
5
+ export class FrontendAppConfigJsonCodec {
6
+ serialize(config: FrontendAppConfig): string {
7
+ return JSON.stringify(config);
8
+ }
9
+
10
+ deserialize(serialized: string | undefined): FrontendAppConfig | null {
11
+ if (!serialized || serialized.trim().length === 0) {
12
+ return null;
13
+ }
14
+ try {
15
+ const parsed = JSON.parse(serialized) as Partial<FrontendAppConfig> | null;
16
+ if (!parsed || typeof parsed !== "object" || !parsed.auth || typeof parsed.auth !== "object") {
17
+ return null;
18
+ }
19
+ return {
20
+ auth: {
21
+ config: this.resolveAuthConfig(parsed.auth.config),
22
+ credentialsEnabled: parsed.auth.credentialsEnabled === true,
23
+ oauthProviders: this.resolveOauthProviders(parsed.auth.oauthProviders),
24
+ secret:
25
+ typeof parsed.auth.secret === "string" && parsed.auth.secret.trim().length > 0 ? parsed.auth.secret : null,
26
+ uiAuthEnabled: parsed.auth.uiAuthEnabled !== false,
27
+ },
28
+ productName:
29
+ typeof parsed.productName === "string" && parsed.productName.trim().length > 0
30
+ ? parsed.productName
31
+ : "Codemation",
32
+ logoUrl: typeof parsed.logoUrl === "string" && parsed.logoUrl.trim().length > 0 ? parsed.logoUrl : null,
33
+ };
34
+ } catch {
35
+ return null;
36
+ }
37
+ }
38
+
39
+ private resolveAuthConfig(value: unknown): CodemationAuthConfig | undefined {
40
+ return value && typeof value === "object" ? (value as CodemationAuthConfig) : undefined;
41
+ }
42
+
43
+ private resolveOauthProviders(value: unknown): ReadonlyArray<CodemationFrontendAuthProviderSnapshot> {
44
+ if (!Array.isArray(value)) {
45
+ return [];
46
+ }
47
+ return value.flatMap((entry) => {
48
+ if (!entry || typeof entry !== "object") {
49
+ return [];
50
+ }
51
+ const provider = entry as Partial<CodemationFrontendAuthProviderSnapshot>;
52
+ if (typeof provider.id !== "string" || typeof provider.name !== "string") {
53
+ return [];
54
+ }
55
+ return [{ id: provider.id, name: provider.name }];
56
+ });
57
+ }
58
+ }
@@ -6,14 +6,16 @@ import { WorkflowDefinitionMapper } from "../../application/mapping/WorkflowDefi
6
6
  import { GetWorkflowDetailQuery } from "../../application/queries/GetWorkflowDetailQuery";
7
7
  import { GetWorkflowSummariesQuery } from "../../application/queries/GetWorkflowSummariesQuery";
8
8
  import { ApplicationTokens } from "../../applicationTokens";
9
- import { CodemationApplication } from "../../codemationApplication";
10
- import { CodemationBootstrapRequest } from "../../bootstrap/CodemationBootstrapRequest";
11
- import { CodemationFrontendBootstrapRequest } from "../../bootstrap/CodemationFrontendBootstrapRequest";
9
+ import { AppContainerFactory } from "../../bootstrap/AppContainerFactory";
10
+ import { AppContainerLifecycle } from "../../bootstrap/AppContainerLifecycle";
11
+ import { FrontendRuntime } from "../../bootstrap/runtime/FrontendRuntime";
12
+ import { AppConfigFactory } from "../../bootstrap/runtime/AppConfigFactory";
12
13
  import type { CodemationConfig } from "../config/CodemationConfig";
14
+ import { CodemationConfigNormalizer } from "../config/CodemationConfigNormalizer";
13
15
  import { CodemationHonoApiApp } from "./hono/CodemationHonoApiAppFactory";
14
16
 
15
17
  type ServerGatewayContext = Readonly<{
16
- application: CodemationApplication;
18
+ container: import("@codemation/core").Container;
17
19
  httpApi: CodemationHonoApiApp;
18
20
  queryBus: QueryBus;
19
21
  workflowDefinitionMapper: WorkflowDefinitionMapper;
@@ -44,7 +46,7 @@ export class CodemationServerGateway {
44
46
  return;
45
47
  }
46
48
  CodemationServerGateway.contextsByConfig.delete(this.config as object);
47
- await (await cachedContext).application.stop();
49
+ await (await cachedContext).container.resolve(AppContainerLifecycle).stop();
48
50
  }
49
51
 
50
52
  async loadWorkflowSummaries(): Promise<ReadonlyArray<WorkflowSummary>> {
@@ -74,22 +76,26 @@ export class CodemationServerGateway {
74
76
 
75
77
  private async createContext(): Promise<ServerGatewayContext> {
76
78
  const repoRoot = this.detectWorkspaceRoot(this.consumerRoot);
77
- const bootstrapRequest = new CodemationBootstrapRequest({
79
+ // This gateway is the config/env boundary that materializes AppConfig from raw inputs.
80
+ // eslint-disable-next-line no-restricted-properties
81
+ const env = this.env ?? process.env;
82
+ const appConfig = new AppConfigFactory().create({
78
83
  repoRoot,
79
84
  consumerRoot: this.consumerRoot,
80
- env: this.env,
85
+ env,
86
+ config: new CodemationConfigNormalizer().normalize(this.config),
81
87
  workflowSources: this.resolveWorkflowSources(),
82
88
  });
83
- const application = new CodemationApplication();
84
- application.useConfig(this.config);
85
- await application.applyPlugins(bootstrapRequest);
86
- await application.prepareContainer(bootstrapRequest);
87
- await application.bootFrontend(new CodemationFrontendBootstrapRequest({ bootstrap: bootstrapRequest }));
89
+ const container = await new AppContainerFactory().create({
90
+ appConfig,
91
+ sharedWorkflowWebsocketServer: null,
92
+ });
93
+ await container.resolve(FrontendRuntime).start();
88
94
  return {
89
- application,
90
- httpApi: application.getContainer().resolve(CodemationHonoApiApp),
91
- queryBus: application.getContainer().resolve(ApplicationTokens.QueryBus),
92
- workflowDefinitionMapper: application.getContainer().resolve(WorkflowDefinitionMapper),
95
+ container,
96
+ httpApi: container.resolve(CodemationHonoApiApp),
97
+ queryBus: container.resolve(ApplicationTokens.QueryBus),
98
+ workflowDefinitionMapper: container.resolve(WorkflowDefinitionMapper),
93
99
  };
94
100
  }
95
101
 
@@ -0,0 +1,39 @@
1
+ import type { AppConfig } from "../config/AppConfig";
2
+ import { CodemationConsumerConfigLoader } from "./CodemationConsumerConfigLoader";
3
+ import { AppConfigFactory } from "../../bootstrap/runtime/AppConfigFactory";
4
+
5
+ export type AppConfigLoadResult = Readonly<{
6
+ appConfig: AppConfig;
7
+ bootstrapSource: string | null;
8
+ }>;
9
+
10
+ export class AppConfigLoader {
11
+ constructor(
12
+ private readonly consumerConfigLoader: CodemationConsumerConfigLoader = new CodemationConsumerConfigLoader(),
13
+ private readonly appConfigFactory: AppConfigFactory = new AppConfigFactory(),
14
+ ) {}
15
+
16
+ async load(
17
+ args: Readonly<{
18
+ consumerRoot: string;
19
+ repoRoot: string;
20
+ env: NodeJS.ProcessEnv;
21
+ configPathOverride?: string;
22
+ }>,
23
+ ): Promise<AppConfigLoadResult> {
24
+ const resolution = await this.consumerConfigLoader.load({
25
+ consumerRoot: args.consumerRoot,
26
+ configPathOverride: args.configPathOverride,
27
+ });
28
+ return {
29
+ appConfig: this.appConfigFactory.create({
30
+ repoRoot: args.repoRoot,
31
+ consumerRoot: args.consumerRoot,
32
+ env: args.env,
33
+ config: resolution.config,
34
+ workflowSources: resolution.workflowSources,
35
+ }),
36
+ bootstrapSource: resolution.bootstrapSource,
37
+ };
38
+ }
39
+ }
@@ -1,12 +1,12 @@
1
1
  import type { WorkflowDefinition } from "@codemation/core";
2
- import type { CodemationConfig } from "../config/CodemationConfig";
3
2
  import { CodemationConfigNormalizer } from "../config/CodemationConfigNormalizer";
3
+ import type { NormalizedCodemationConfig } from "../config/CodemationConfigNormalizer";
4
4
  import { CodemationConsumerConfigExportsResolver } from "./CodemationConsumerConfigExportsResolver";
5
5
  import { DiscoveredWorkflowsEmptyMessageFactory } from "./DiscoveredWorkflowsEmptyMessageFactory";
6
6
  import { WorkflowDefinitionExportsResolver } from "./WorkflowDefinitionExportsResolver";
7
7
 
8
8
  export type CodemationConsumerApp = Readonly<{
9
- config: CodemationConfig;
9
+ config: NormalizedCodemationConfig;
10
10
  workflowSources: ReadonlyArray<string>;
11
11
  }>;
12
12
 
@@ -6,6 +6,7 @@ import type { NamespacedUnregister } from "tsx/esm/api";
6
6
  import { register } from "tsx/esm/api";
7
7
  import type { CodemationConfig } from "../config/CodemationConfig";
8
8
  import { CodemationConfigNormalizer } from "../config/CodemationConfigNormalizer";
9
+ import type { NormalizedCodemationConfig } from "../config/CodemationConfigNormalizer";
9
10
  import { logLevelPolicyFactory } from "../../infrastructure/logging/LogLevelPolicyFactory";
10
11
  import { ServerLoggerFactory } from "../../infrastructure/logging/ServerLoggerFactory";
11
12
  import { DiscoveredWorkflowsEmptyMessageFactory } from "./DiscoveredWorkflowsEmptyMessageFactory";
@@ -15,7 +16,7 @@ import { WorkflowDiscoveryPathSegmentsComputer } from "./WorkflowDiscoveryPathSe
15
16
  import { WorkflowModulePathFinder } from "./WorkflowModulePathFinder";
16
17
 
17
18
  export type CodemationConsumerConfigResolution = Readonly<{
18
- config: CodemationConfig;
19
+ config: NormalizedCodemationConfig;
19
20
  bootstrapSource: string | null;
20
21
  workflowSources: ReadonlyArray<string>;
21
22
  }>;
@@ -66,7 +67,7 @@ export class CodemationConsumerConfigLoader {
66
67
  await this.loadDiscoveredWorkflows(args.consumerRoot, config, workflowSources),
67
68
  );
68
69
  phaseMs("loadDiscoveredWorkflows");
69
- const resolvedConfig: CodemationConfig = {
70
+ const resolvedConfig: NormalizedCodemationConfig = {
70
71
  ...config,
71
72
  workflows,
72
73
  };
package/src/server.ts CHANGED
@@ -3,9 +3,16 @@ export { ApiPaths } from "./presentation/http/ApiPaths";
3
3
  export { CodemationServerGateway } from "./presentation/http/CodemationServerGatewayFactory";
4
4
  export { CodemationConsumerAppResolver } from "./presentation/server/CodemationConsumerAppResolver";
5
5
  export type { CodemationConsumerApp } from "./presentation/server/CodemationConsumerAppResolver";
6
+ export { AppConfigLoader } from "./presentation/server/AppConfigLoader";
7
+ export type { AppConfigLoadResult } from "./presentation/server/AppConfigLoader";
6
8
  export { CodemationConsumerConfigLoader } from "./presentation/server/CodemationConsumerConfigLoader";
7
9
  export type { CodemationConsumerConfigResolution } from "./presentation/server/CodemationConsumerConfigLoader";
8
10
  export { CodemationPluginDiscovery } from "./presentation/server/CodemationPluginDiscovery";
11
+ export { CodemationFrontendAuthSnapshotFactory } from "./presentation/frontend/CodemationFrontendAuthSnapshotFactory";
12
+ export { CodemationFrontendAuthSnapshotJsonCodec } from "./presentation/frontend/CodemationFrontendAuthSnapshotJsonCodec";
13
+ export { FrontendAppConfigFactory } from "./presentation/frontend/FrontendAppConfigFactory";
14
+ export { FrontendAppConfigJsonCodec } from "./presentation/frontend/FrontendAppConfigJsonCodec";
15
+ export type { FrontendAppConfig } from "./presentation/frontend/FrontendAppConfig";
9
16
  export type {
10
17
  CodemationDiscoveredPluginPackage,
11
18
  CodemationResolvedPluginPackage,
package/vitest.shared.ts CHANGED
@@ -21,10 +21,6 @@ export const hostVitestSharedConfig = {
21
21
  },
22
22
  { find: "@codemation/host", replacement: path.resolve(import.meta.dirname, "./src/index.ts") },
23
23
  { find: "@codemation/core-nodes", replacement: path.resolve(import.meta.dirname, "../core-nodes/src/index.ts") },
24
- {
25
- find: "@codemation/queue-bullmq",
26
- replacement: path.resolve(import.meta.dirname, "../queue-bullmq/src/index.ts"),
27
- },
28
24
  {
29
25
  find: "@codemation/eventbus-redis",
30
26
  replacement: path.resolve(import.meta.dirname, "../eventbus-redis/src/index.ts"),
@@ -1 +0,0 @@
1
- {"version":3,"file":"CodemationConsumerConfigLoader-scS_RQMy.js","names":["workflows: WorkflowDefinition[]","workflowModulePaths: string[]","bestRoot: string | null","resolvedConfig: CodemationConfig"],"sources":["../src/presentation/server/CodemationConsumerConfigExportsResolver.ts","../src/presentation/server/DiscoveredWorkflowsEmptyMessageFactory.ts","../src/presentation/server/WorkflowDefinitionExportsResolver.ts","../src/presentation/server/CodemationConsumerAppResolver.ts","../src/presentation/server/WorkflowModulePathFinder.ts","../src/presentation/server/WorkflowDiscoveryPathSegmentsComputer.ts","../src/presentation/server/CodemationConsumerConfigLoader.ts"],"sourcesContent":["import type { CodemationConfig } from \"../config/CodemationConfig\";\n\nexport class CodemationConsumerConfigExportsResolver {\n resolveConfig(moduleExports: Readonly<Record<string, unknown>>): CodemationConfig | null {\n const defaultExport = moduleExports.default;\n if (this.isConfig(defaultExport)) {\n return defaultExport;\n }\n const namedConfig = moduleExports.codemationHost ?? moduleExports.config;\n if (this.isConfig(namedConfig)) {\n return namedConfig;\n }\n return null;\n }\n\n private isConfig(value: unknown): value is CodemationConfig {\n if (!value || typeof value !== \"object\") {\n return false;\n }\n return (\n \"app\" in value ||\n \"register\" in value ||\n \"credentials\" in value ||\n \"runtime\" in value ||\n \"workflows\" in value ||\n \"workflowDiscovery\" in value ||\n \"plugins\" in value ||\n \"whitelabel\" in value ||\n \"auth\" in value ||\n \"log\" in value\n );\n }\n}\n","export class DiscoveredWorkflowsEmptyMessageFactory {\n create(discoveredPaths: ReadonlyArray<string>): string {\n const lines = discoveredPaths.map((p) => ` - ${p}`).join(\"\\n\");\n return [\n `Discovered ${discoveredPaths.length} file(s) under workflow discovery, but none export a WorkflowDefinition.`,\n lines,\n \"\",\n \"Move shared helpers outside the discovery directories (for example src/lib), or export at least one object with id, name, nodes, and edges from a workflow module.\",\n ].join(\"\\n\");\n }\n}\n","import type { WorkflowDefinition } from \"@codemation/core\";\n\n/**\n * Collects exported values that match the {@link WorkflowDefinition} shape.\n * Other exports (helpers, constants, type-only re-exports) are ignored.\n */\nexport class WorkflowDefinitionExportsResolver {\n resolve(moduleExports: Readonly<Record<string, unknown>>): ReadonlyArray<WorkflowDefinition> {\n const workflows: WorkflowDefinition[] = [];\n for (const exportedValue of Object.values(moduleExports)) {\n if (this.isWorkflowDefinition(exportedValue)) {\n workflows.push(exportedValue);\n }\n }\n return workflows;\n }\n\n private isWorkflowDefinition(value: unknown): value is WorkflowDefinition {\n if (!value || typeof value !== \"object\") {\n return false;\n }\n return \"id\" in value && \"name\" in value && \"nodes\" in value && \"edges\" in value;\n }\n}\n","import type { WorkflowDefinition } from \"@codemation/core\";\nimport type { CodemationConfig } from \"../config/CodemationConfig\";\nimport { CodemationConfigNormalizer } from \"../config/CodemationConfigNormalizer\";\nimport { CodemationConsumerConfigExportsResolver } from \"./CodemationConsumerConfigExportsResolver\";\nimport { DiscoveredWorkflowsEmptyMessageFactory } from \"./DiscoveredWorkflowsEmptyMessageFactory\";\nimport { WorkflowDefinitionExportsResolver } from \"./WorkflowDefinitionExportsResolver\";\n\nexport type CodemationConsumerApp = Readonly<{\n config: CodemationConfig;\n workflowSources: ReadonlyArray<string>;\n}>;\n\nexport class CodemationConsumerAppResolver {\n private readonly configExportsResolver = new CodemationConsumerConfigExportsResolver();\n private readonly configNormalizer = new CodemationConfigNormalizer();\n private readonly workflowDefinitionExportsResolver = new WorkflowDefinitionExportsResolver();\n private readonly discoveredWorkflowsEmptyMessageFactory = new DiscoveredWorkflowsEmptyMessageFactory();\n\n resolve(\n args: Readonly<{\n configModule: Readonly<Record<string, unknown>>;\n workflowModules: ReadonlyArray<Readonly<Record<string, unknown>>>;\n workflowSourcePaths: ReadonlyArray<string>;\n workflowDiscoveryPathSegmentsList?: ReadonlyArray<readonly string[]>;\n }>,\n ): CodemationConsumerApp {\n const rawConfig = this.configExportsResolver.resolveConfig(args.configModule);\n if (!rawConfig) {\n throw new Error(\"Consumer app module does not export a Codemation config object.\");\n }\n const config = this.configNormalizer.normalize(rawConfig);\n const discoveredWorkflows = this.resolveDiscoveredWorkflows(\n args.workflowModules,\n args.workflowSourcePaths,\n args.workflowDiscoveryPathSegmentsList,\n );\n return {\n config: {\n ...config,\n workflows: this.mergeWorkflows(config.workflows ?? [], discoveredWorkflows),\n },\n workflowSources: args.workflowSourcePaths,\n };\n }\n\n private resolveDiscoveredWorkflows(\n workflowModules: ReadonlyArray<Readonly<Record<string, unknown>>>,\n workflowSourcePaths: ReadonlyArray<string>,\n workflowDiscoveryPathSegmentsList: ReadonlyArray<readonly string[]> | undefined,\n ): ReadonlyArray<WorkflowDefinition> {\n const workflowsById = new Map<string, WorkflowDefinition>();\n workflowModules.forEach((workflowModule: Readonly<Record<string, unknown>>, index: number) => {\n const pathSegments = workflowDiscoveryPathSegmentsList?.[index];\n const workflows = this.workflowDefinitionExportsResolver.resolve(workflowModule);\n workflows.forEach((workflow: WorkflowDefinition) => {\n const enriched =\n pathSegments && pathSegments.length > 0\n ? ({ ...workflow, discoveryPathSegments: pathSegments } satisfies WorkflowDefinition)\n : workflow;\n workflowsById.set(workflow.id, enriched);\n });\n });\n if (workflowsById.size === 0 && workflowSourcePaths.length > 0) {\n throw new Error(this.discoveredWorkflowsEmptyMessageFactory.create(workflowSourcePaths));\n }\n return [...workflowsById.values()];\n }\n\n private mergeWorkflows(\n configuredWorkflows: ReadonlyArray<WorkflowDefinition>,\n discoveredWorkflows: ReadonlyArray<WorkflowDefinition>,\n ): ReadonlyArray<WorkflowDefinition> {\n const workflowsById = new Map<string, WorkflowDefinition>();\n for (const workflow of discoveredWorkflows) {\n workflowsById.set(workflow.id, workflow);\n }\n for (const workflow of configuredWorkflows) {\n workflowsById.set(workflow.id, workflow);\n }\n return [...workflowsById.values()];\n }\n}\n","import { readdir } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nexport class WorkflowModulePathFinder {\n static readonly defaultWorkflowDirectories = [\"src/workflows\", \"workflows\"] as const;\n private readonly workflowExtensions = new Set([\".ts\", \".js\", \".mts\", \".mjs\"]);\n\n async discoverModulePaths(\n args: Readonly<{\n consumerRoot: string;\n workflowDirectories: ReadonlyArray<string> | undefined;\n exists: (absolutePath: string) => Promise<boolean>;\n }>,\n ): Promise<ReadonlyArray<string>> {\n const directories = args.workflowDirectories ?? WorkflowModulePathFinder.defaultWorkflowDirectories;\n const workflowModulePaths: string[] = [];\n for (const directory of directories) {\n const absoluteDirectory = path.resolve(args.consumerRoot, directory);\n if (!(await args.exists(absoluteDirectory))) {\n continue;\n }\n workflowModulePaths.push(...(await this.collectWorkflowModulePaths(absoluteDirectory)));\n }\n return workflowModulePaths;\n }\n\n private async collectWorkflowModulePaths(directoryPath: string): Promise<ReadonlyArray<string>> {\n const entries = await readdir(directoryPath, { withFileTypes: true });\n const workflowModulePaths: string[] = [];\n for (const entry of entries) {\n const entryPath = path.resolve(directoryPath, entry.name);\n if (entry.isDirectory()) {\n workflowModulePaths.push(...(await this.collectWorkflowModulePaths(entryPath)));\n continue;\n }\n if (this.isWorkflowModulePath(entryPath)) {\n workflowModulePaths.push(entryPath);\n }\n }\n return workflowModulePaths;\n }\n\n private isWorkflowModulePath(modulePath: string): boolean {\n const extension = path.extname(modulePath);\n return this.workflowExtensions.has(extension) && !modulePath.endsWith(\".d.ts\");\n }\n}\n","import path from \"node:path\";\n\nimport { WorkflowModulePathFinder } from \"./WorkflowModulePathFinder\";\n\nexport class WorkflowDiscoveryPathSegmentsComputer {\n compute(\n args: Readonly<{\n consumerRoot: string;\n workflowDiscoveryDirectories: ReadonlyArray<string>;\n absoluteWorkflowModulePath: string;\n }>,\n ): readonly string[] | undefined {\n const normalizedConsumer = path.resolve(args.consumerRoot);\n const normalizedWorkflowPath = path.resolve(args.absoluteWorkflowModulePath);\n const directories =\n args.workflowDiscoveryDirectories.length > 0\n ? args.workflowDiscoveryDirectories\n : [...WorkflowModulePathFinder.defaultWorkflowDirectories];\n\n let bestRoot: string | null = null;\n for (const directory of directories) {\n const absoluteDirectory = path.resolve(normalizedConsumer, directory);\n const isPrefix =\n normalizedWorkflowPath === absoluteDirectory ||\n normalizedWorkflowPath.startsWith(`${absoluteDirectory}${path.sep}`);\n if (!isPrefix) {\n continue;\n }\n if (!bestRoot || absoluteDirectory.length > bestRoot.length) {\n bestRoot = absoluteDirectory;\n }\n }\n if (!bestRoot) {\n return undefined;\n }\n const relative = path.relative(bestRoot, normalizedWorkflowPath);\n if (relative.startsWith(\"..\") || path.isAbsolute(relative)) {\n return undefined;\n }\n if (relative.length === 0) {\n return undefined;\n }\n const parts = relative.split(path.sep).filter((segment) => segment.length > 0);\n if (parts.length === 0) {\n return undefined;\n }\n const lastIndex = parts.length - 1;\n const last = parts[lastIndex] ?? \"\";\n const ext = path.extname(last);\n parts[lastIndex] = ext ? last.slice(0, -ext.length) : last;\n return parts;\n }\n}\n","import type { WorkflowDefinition } from \"@codemation/core\";\nimport { access, stat } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport type { NamespacedUnregister } from \"tsx/esm/api\";\nimport { register } from \"tsx/esm/api\";\nimport type { CodemationConfig } from \"../config/CodemationConfig\";\nimport { CodemationConfigNormalizer } from \"../config/CodemationConfigNormalizer\";\nimport { logLevelPolicyFactory } from \"../../infrastructure/logging/LogLevelPolicyFactory\";\nimport { ServerLoggerFactory } from \"../../infrastructure/logging/ServerLoggerFactory\";\nimport { DiscoveredWorkflowsEmptyMessageFactory } from \"./DiscoveredWorkflowsEmptyMessageFactory\";\nimport { CodemationConsumerConfigExportsResolver } from \"./CodemationConsumerConfigExportsResolver\";\nimport { WorkflowDefinitionExportsResolver } from \"./WorkflowDefinitionExportsResolver\";\nimport { WorkflowDiscoveryPathSegmentsComputer } from \"./WorkflowDiscoveryPathSegmentsComputer\";\nimport { WorkflowModulePathFinder } from \"./WorkflowModulePathFinder\";\n\nexport type CodemationConsumerConfigResolution = Readonly<{\n config: CodemationConfig;\n bootstrapSource: string | null;\n workflowSources: ReadonlyArray<string>;\n}>;\n\nexport class CodemationConsumerConfigLoader {\n private static readonly importerRegistrationsByTsconfig = new Map<string, NamespacedUnregister>();\n private readonly configExportsResolver = new CodemationConsumerConfigExportsResolver();\n private readonly configNormalizer = new CodemationConfigNormalizer();\n private readonly workflowModulePathFinder = new WorkflowModulePathFinder();\n private readonly workflowDefinitionExportsResolver = new WorkflowDefinitionExportsResolver();\n private readonly discoveredWorkflowsEmptyMessageFactory = new DiscoveredWorkflowsEmptyMessageFactory();\n private readonly pathSegmentsComputer = new WorkflowDiscoveryPathSegmentsComputer();\n private readonly performanceDiagnosticsLogger = new ServerLoggerFactory(\n logLevelPolicyFactory,\n ).createPerformanceDiagnostics(\"codemation-config-loader.timing\");\n\n async load(\n args: Readonly<{ consumerRoot: string; configPathOverride?: string }>,\n ): Promise<CodemationConsumerConfigResolution> {\n const loadStarted = performance.now();\n let mark = loadStarted;\n const phaseMs = (label: string): void => {\n const now = performance.now();\n const delta = now - mark;\n mark = now;\n this.performanceDiagnosticsLogger.info(\n `load.${label} +${delta.toFixed(1)}ms (cumulative ${(now - loadStarted).toFixed(1)}ms)`,\n );\n };\n const bootstrapSource = await this.resolveConfigPath(args.consumerRoot, args.configPathOverride);\n phaseMs(\"resolveConfigPath\");\n if (!bootstrapSource) {\n throw new Error(\n 'Codemation config not found. Expected \"codemation.config.ts\" in the consumer project root or \"src/\".',\n );\n }\n const moduleExports = await this.importModule(bootstrapSource);\n phaseMs(\"importConfigModule\");\n const rawConfig = this.configExportsResolver.resolveConfig(moduleExports);\n if (!rawConfig) {\n throw new Error(`Config file does not export a Codemation config object: ${bootstrapSource}`);\n }\n const config = this.configNormalizer.normalize(rawConfig);\n const workflowSources = await this.resolveWorkflowSources(args.consumerRoot, config);\n phaseMs(\"resolveWorkflowSources\");\n const workflows = this.mergeWorkflows(\n config.workflows ?? [],\n await this.loadDiscoveredWorkflows(args.consumerRoot, config, workflowSources),\n );\n phaseMs(\"loadDiscoveredWorkflows\");\n const resolvedConfig: CodemationConfig = {\n ...config,\n workflows,\n };\n logLevelPolicyFactory.create().applyCodemationLogConfig(resolvedConfig.log);\n return {\n config: resolvedConfig,\n bootstrapSource,\n workflowSources,\n };\n }\n\n private async resolveConfigPath(\n consumerRoot: string,\n configPathOverride: string | undefined,\n ): Promise<string | null> {\n if (configPathOverride) {\n const explicitPath = path.isAbsolute(configPathOverride)\n ? configPathOverride\n : path.resolve(consumerRoot, configPathOverride);\n if (!(await this.exists(explicitPath))) {\n throw new Error(`Config file not found: ${explicitPath}`);\n }\n return explicitPath;\n }\n for (const candidate of this.getConventionCandidates(consumerRoot)) {\n if (await this.exists(candidate)) {\n return candidate;\n }\n }\n return null;\n }\n\n private getConventionCandidates(consumerRoot: string): ReadonlyArray<string> {\n return [\n path.resolve(consumerRoot, \"codemation.config.ts\"),\n path.resolve(consumerRoot, \"codemation.config.js\"),\n path.resolve(consumerRoot, \"src\", \"codemation.config.ts\"),\n path.resolve(consumerRoot, \"src\", \"codemation.config.js\"),\n ];\n }\n\n private async resolveWorkflowSources(consumerRoot: string, config: CodemationConfig): Promise<ReadonlyArray<string>> {\n if ((config.workflowDiscovery?.directories?.length ?? 0) === 0) {\n return [];\n }\n const discoveredPaths = await this.workflowModulePathFinder.discoverModulePaths({\n consumerRoot,\n workflowDirectories: config.workflowDiscovery?.directories,\n exists: (absolutePath) => this.exists(absolutePath),\n });\n return [...discoveredPaths].sort((left: string, right: string) => left.localeCompare(right));\n }\n\n private async loadDiscoveredWorkflows(\n consumerRoot: string,\n config: CodemationConfig,\n workflowSources: ReadonlyArray<string>,\n ): Promise<ReadonlyArray<WorkflowDefinition>> {\n const workflowDiscoveryDirectories = config.workflowDiscovery?.directories ?? [];\n const workflowsById = new Map<string, WorkflowDefinition>();\n const loadedWorkflowModules = await Promise.all(\n workflowSources.map(async (workflowSource: string) => ({\n workflowSource,\n segments: this.pathSegmentsComputer.compute({\n consumerRoot,\n workflowDiscoveryDirectories,\n absoluteWorkflowModulePath: workflowSource,\n }),\n moduleExports: await this.importModule(workflowSource),\n })),\n );\n for (const loadedWorkflowModule of loadedWorkflowModules) {\n for (const workflow of this.workflowDefinitionExportsResolver.resolve(loadedWorkflowModule.moduleExports)) {\n const enriched =\n loadedWorkflowModule.segments && loadedWorkflowModule.segments.length > 0\n ? ({ ...workflow, discoveryPathSegments: loadedWorkflowModule.segments } satisfies WorkflowDefinition)\n : workflow;\n workflowsById.set(workflow.id, enriched);\n }\n }\n if (workflowsById.size === 0 && workflowSources.length > 0) {\n throw new Error(this.discoveredWorkflowsEmptyMessageFactory.create(workflowSources));\n }\n return [...workflowsById.values()];\n }\n\n private mergeWorkflows(\n configuredWorkflows: ReadonlyArray<WorkflowDefinition>,\n discoveredWorkflows: ReadonlyArray<WorkflowDefinition>,\n ): ReadonlyArray<WorkflowDefinition> {\n const workflowsById = new Map<string, WorkflowDefinition>();\n for (const workflow of discoveredWorkflows) {\n workflowsById.set(workflow.id, workflow);\n }\n for (const workflow of configuredWorkflows) {\n workflowsById.set(workflow.id, workflow);\n }\n return [...workflowsById.values()];\n }\n\n private async importModule(modulePath: string): Promise<Record<string, unknown>> {\n if (this.shouldUseNativeRuntimeImport()) {\n return await this.importModuleWithNativeRuntime(modulePath);\n }\n const tsconfigPath = await this.resolveTsconfigPath(modulePath);\n const importSpecifier = await this.createImportSpecifier(modulePath);\n for (let attempt = 0; attempt < 3; attempt += 1) {\n try {\n const importedModule = await this.getOrCreateImporter(tsconfigPath).import(importSpecifier, import.meta.url);\n return importedModule as Record<string, unknown>;\n } catch (error) {\n if (!this.isStoppedTransformServiceError(error) || attempt === 2) {\n throw error;\n }\n await this.resetImporter(tsconfigPath);\n }\n }\n throw new Error(`Failed to import consumer module after retries: ${modulePath}`);\n }\n\n private async importModuleWithNativeRuntime(modulePath: string): Promise<Record<string, unknown>> {\n const importedModule = await import(await this.createImportSpecifier(modulePath));\n return importedModule as Record<string, unknown>;\n }\n\n private async resolveTsconfigPath(modulePath: string): Promise<string | false> {\n const overridePath = process.env.CODEMATION_TSCONFIG_PATH;\n if (overridePath && (await this.exists(overridePath))) {\n return overridePath;\n }\n const discoveredPath = await this.findNearestTsconfig(modulePath);\n return discoveredPath ?? false;\n }\n\n private getOrCreateImporter(tsconfigPath: string | false): NamespacedUnregister {\n const cacheKey = tsconfigPath || \"default\";\n const existingImporter = CodemationConsumerConfigLoader.importerRegistrationsByTsconfig.get(cacheKey);\n if (existingImporter) {\n return existingImporter;\n }\n const nextImporter = register({\n namespace: this.toNamespace(cacheKey),\n tsconfig: tsconfigPath,\n });\n CodemationConsumerConfigLoader.importerRegistrationsByTsconfig.set(cacheKey, nextImporter);\n return nextImporter;\n }\n\n private async resetImporter(tsconfigPath: string | false): Promise<void> {\n const cacheKey = tsconfigPath || \"default\";\n const existingImporter = CodemationConsumerConfigLoader.importerRegistrationsByTsconfig.get(cacheKey);\n if (!existingImporter) {\n return;\n }\n CodemationConsumerConfigLoader.importerRegistrationsByTsconfig.delete(cacheKey);\n await existingImporter.unregister().catch(() => null);\n }\n\n private toNamespace(cacheKey: string): string {\n return `codemation_consumer_${cacheKey.replace(/[^a-zA-Z0-9_-]+/g, \"_\")}`;\n }\n\n private async findNearestTsconfig(modulePath: string): Promise<string | null> {\n let currentDirectory = path.dirname(modulePath);\n while (true) {\n const candidate = path.resolve(currentDirectory, \"tsconfig.json\");\n if (await this.exists(candidate)) {\n return candidate;\n }\n const parentDirectory = path.dirname(currentDirectory);\n if (parentDirectory === currentDirectory) {\n return null;\n }\n currentDirectory = parentDirectory;\n }\n }\n\n private async createImportSpecifier(modulePath: string): Promise<string> {\n const moduleUrl = pathToFileURL(modulePath);\n const moduleStats = await stat(modulePath);\n moduleUrl.searchParams.set(\"t\", String(moduleStats.mtimeMs));\n return moduleUrl.href;\n }\n\n private shouldUseNativeRuntimeImport(): boolean {\n return process.env.CODEMATION_TS_RUNTIME === \"ts-node\";\n }\n\n private isStoppedTransformServiceError(error: unknown): boolean {\n return error instanceof Error && error.message.includes(\"The service is no longer running\");\n }\n\n private async exists(filePath: string): Promise<boolean> {\n try {\n await access(filePath);\n return true;\n } catch {\n return false;\n }\n }\n}\n"],"mappings":"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"}