@fjall/deploy-core 0.89.4 → 0.89.6

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 (202) hide show
  1. package/LICENSE +50 -21
  2. package/README.md +25 -0
  3. package/dist/.minified +1 -0
  4. package/dist/src/__test-utils__/awsMockHelpers.d.ts +20 -0
  5. package/dist/src/__test-utils__/awsMockHelpers.js +1 -0
  6. package/dist/src/__test-utils__/index.d.ts +1 -0
  7. package/dist/src/__test-utils__/index.js +1 -0
  8. package/dist/src/aws/AwsProvider.d.ts +2 -2
  9. package/dist/src/aws/AwsProvider.js +0 -1
  10. package/dist/src/aws/SimpleAwsProvider.d.ts +2 -3
  11. package/dist/src/aws/SimpleAwsProvider.js +1 -73
  12. package/dist/src/aws/index.d.ts +4 -2
  13. package/dist/src/aws/index.js +1 -3
  14. package/dist/src/aws/organisations/accounts.js +10 -10
  15. package/dist/src/aws/organisations/backup.js +4 -2
  16. package/dist/src/aws/organisations/costAllocation.js +4 -2
  17. package/dist/src/aws/organisations/delegatedAdmin.d.ts +9 -0
  18. package/dist/src/aws/organisations/delegatedAdmin.js +43 -0
  19. package/dist/src/aws/organisations/identityCentre.d.ts +1 -1
  20. package/dist/src/aws/organisations/identityCentre.js +6 -2
  21. package/dist/src/aws/organisations/index.d.ts +4 -3
  22. package/dist/src/aws/organisations/index.js +1 -12
  23. package/dist/src/aws/organisations/ipam.js +4 -2
  24. package/dist/src/aws/organisations/organisation.js +27 -18
  25. package/dist/src/aws/organisations/organisationalUnits.d.ts +26 -6
  26. package/dist/src/aws/organisations/organisationalUnits.js +149 -35
  27. package/dist/src/aws/organisations/policies.js +4 -3
  28. package/dist/src/aws/organisations/ram.js +6 -2
  29. package/dist/src/aws/organisations/serviceAccess.js +12 -6
  30. package/dist/src/aws/organisations/trustedAccess.js +6 -2
  31. package/dist/src/aws/organisations/types.d.ts +23 -1
  32. package/dist/src/aws/organisations/types.js +1 -16
  33. package/dist/src/aws/utils/__tests__/cloudformationTestHelpers.d.ts +6 -0
  34. package/dist/src/aws/utils/__tests__/cloudformationTestHelpers.js +1 -0
  35. package/dist/src/aws/utils/cloudformationEventHelpers.d.ts +48 -0
  36. package/dist/src/aws/utils/cloudformationEventHelpers.js +1 -0
  37. package/dist/src/aws/utils/cloudformationEventTypes.d.ts +45 -0
  38. package/dist/src/aws/utils/cloudformationEventTypes.js +1 -0
  39. package/dist/src/aws/utils/cloudformationEvents.d.ts +8 -54
  40. package/dist/src/aws/utils/cloudformationEvents.js +1 -596
  41. package/dist/src/aws/utils/index.d.ts +5 -0
  42. package/dist/src/aws/utils/index.js +1 -0
  43. package/dist/src/aws/utils/stackStatus.js +1 -90
  44. package/dist/src/events/index.d.ts +13 -0
  45. package/dist/src/events/index.js +1 -0
  46. package/dist/src/index.d.ts +34 -17
  47. package/dist/src/index.js +41 -21
  48. package/dist/src/orchestration/__tests__/cascadeTestHelpers.d.ts +12 -0
  49. package/dist/src/orchestration/__tests__/cascadeTestHelpers.js +78 -0
  50. package/dist/src/orchestration/activeDeploymentGuard.d.ts +10 -0
  51. package/dist/src/orchestration/activeDeploymentGuard.js +39 -0
  52. package/dist/src/orchestration/applicationDeploy.js +46 -224
  53. package/dist/src/orchestration/applicationDeployHelpers.d.ts +39 -0
  54. package/dist/src/orchestration/applicationDeployHelpers.js +223 -0
  55. package/dist/src/orchestration/applicationDestroy.d.ts +14 -0
  56. package/dist/src/orchestration/applicationDestroy.js +131 -0
  57. package/dist/src/orchestration/builders/dockerBuilder.d.ts +17 -0
  58. package/dist/src/orchestration/builders/dockerBuilder.js +98 -0
  59. package/dist/src/orchestration/builders/frameworkRegistry.d.ts +23 -0
  60. package/dist/src/orchestration/builders/frameworkRegistry.js +1 -0
  61. package/dist/src/orchestration/builders/index.d.ts +4 -0
  62. package/dist/src/orchestration/builders/index.js +1 -0
  63. package/dist/src/orchestration/builders/openNextBuilder.d.ts +21 -0
  64. package/dist/src/orchestration/builders/openNextBuilder.js +144 -0
  65. package/dist/src/orchestration/cascadeDestroyHelpers.d.ts +30 -0
  66. package/dist/src/orchestration/cascadeDestroyHelpers.js +1 -0
  67. package/dist/src/orchestration/cascadeHelpers.d.ts +46 -0
  68. package/dist/src/orchestration/cascadeHelpers.js +160 -0
  69. package/dist/src/orchestration/contextHelpers.d.ts +47 -2
  70. package/dist/src/orchestration/contextHelpers.js +94 -1
  71. package/dist/src/orchestration/destroy.d.ts +13 -0
  72. package/dist/src/orchestration/destroy.js +67 -0
  73. package/dist/src/orchestration/detectionPipeline.d.ts +2 -11
  74. package/dist/src/orchestration/detectionPipeline.js +29 -10
  75. package/dist/src/orchestration/dockerBuildHelper.d.ts +10 -0
  76. package/dist/src/orchestration/dockerBuildHelper.js +49 -0
  77. package/dist/src/orchestration/dockerInterface.d.ts +4 -2
  78. package/dist/src/orchestration/index.d.ts +8 -1
  79. package/dist/src/orchestration/index.js +1 -3
  80. package/dist/src/orchestration/manifestSecretParser.d.ts +11 -0
  81. package/dist/src/orchestration/manifestSecretParser.js +1 -0
  82. package/dist/src/orchestration/openNextBuild.d.ts +28 -0
  83. package/dist/src/orchestration/openNextBuild.js +243 -0
  84. package/dist/src/orchestration/organisationDeploy.js +130 -228
  85. package/dist/src/orchestration/organisationDestroy.d.ts +24 -0
  86. package/dist/src/orchestration/organisationDestroy.js +189 -0
  87. package/dist/src/orchestration/organisationSetup.d.ts +6 -4
  88. package/dist/src/orchestration/organisationSetup.js +28 -8
  89. package/dist/src/orchestration/resolveOperation.js +68 -6
  90. package/dist/src/orchestration/serviceFactory.d.ts +4 -0
  91. package/dist/src/orchestration/serviceFactory.js +1 -16
  92. package/dist/src/orchestration/spawnHelpers.d.ts +47 -0
  93. package/dist/src/orchestration/spawnHelpers.js +1 -0
  94. package/dist/src/orchestration/stackCleanup.d.ts +39 -0
  95. package/dist/src/orchestration/stackCleanup.js +1 -0
  96. package/dist/src/orchestration/welcomeImageHelper.d.ts +15 -0
  97. package/dist/src/orchestration/welcomeImageHelper.js +64 -0
  98. package/dist/src/services/application/ApplicationStackService.d.ts +21 -30
  99. package/dist/src/services/application/ApplicationStackService.js +16 -234
  100. package/dist/src/services/application/applicationStackHelpers.d.ts +46 -0
  101. package/dist/src/services/application/applicationStackHelpers.js +248 -0
  102. package/dist/src/services/application/index.d.ts +1 -0
  103. package/dist/src/services/application/index.js +1 -1
  104. package/dist/src/services/index.d.ts +6 -0
  105. package/dist/src/services/index.js +1 -0
  106. package/dist/src/services/infrastructure/CdkArgumentBuilder.js +1 -67
  107. package/dist/src/services/infrastructure/CdkCommandRunner.d.ts +10 -2
  108. package/dist/src/services/infrastructure/CdkCommandRunner.js +18 -15
  109. package/dist/src/services/infrastructure/CdkErrorFormatter.js +16 -194
  110. package/dist/src/services/infrastructure/CdkEventMonitoring.js +1 -41
  111. package/dist/src/services/infrastructure/CdkOutputAnalyser.js +1 -1
  112. package/dist/src/services/infrastructure/CdkOutputParser.js +2 -33
  113. package/dist/src/services/infrastructure/CdkProcessManager.d.ts +5 -0
  114. package/dist/src/services/infrastructure/CdkProcessManager.js +81 -47
  115. package/dist/src/services/infrastructure/CdkService.d.ts +7 -52
  116. package/dist/src/services/infrastructure/CdkService.js +41 -82
  117. package/dist/src/services/infrastructure/CdkServiceTypes.d.ts +50 -0
  118. package/dist/src/services/infrastructure/CdkServiceTypes.js +0 -0
  119. package/dist/src/services/infrastructure/CloudFormationService.js +9 -10
  120. package/dist/src/services/infrastructure/ICdkProcessManager.d.ts +27 -0
  121. package/dist/src/services/infrastructure/ICdkProcessManager.js +1 -0
  122. package/dist/src/services/infrastructure/__tests__/cloudFormationTestHelpers.d.ts +9 -0
  123. package/dist/src/services/infrastructure/__tests__/cloudFormationTestHelpers.js +1 -0
  124. package/dist/src/services/infrastructure/cdkServiceHelpers.d.ts +9 -0
  125. package/dist/src/services/infrastructure/cdkServiceHelpers.js +1 -0
  126. package/dist/src/services/infrastructure/constructMapEnrichment.d.ts +7 -0
  127. package/dist/src/services/infrastructure/constructMapEnrichment.js +1 -0
  128. package/dist/src/services/infrastructure/index.d.ts +3 -1
  129. package/dist/src/services/infrastructure/index.js +1 -7
  130. package/dist/src/services/supporting/TemplateHashService.js +1 -1
  131. package/dist/src/services/supporting/helpers.js +1 -81
  132. package/dist/src/services/supporting/index.js +1 -3
  133. package/dist/src/steps/index.d.ts +1 -0
  134. package/dist/src/steps/index.js +1 -0
  135. package/dist/src/steps/stepRegistry.d.ts +71 -0
  136. package/dist/src/steps/stepRegistry.js +505 -0
  137. package/dist/src/types/FjallState.js +1 -118
  138. package/dist/src/types/ProgressEvent.js +1 -48
  139. package/dist/src/types/application/ApplicationServiceTypes.js +1 -30
  140. package/dist/src/types/application/index.js +1 -1
  141. package/dist/src/types/callbacks.d.ts +76 -4
  142. package/dist/src/types/callbacks.js +0 -1
  143. package/dist/src/types/constants.d.ts +2 -0
  144. package/dist/src/types/constants.js +1 -6
  145. package/dist/src/types/credentials.d.ts +1 -1
  146. package/dist/src/types/credentials.js +0 -1
  147. package/dist/src/types/deployment/DeploymentServiceTypes.d.ts +5 -2
  148. package/dist/src/types/deployment/DeploymentServiceTypes.js +1 -1
  149. package/dist/src/types/deployment/DeploymentTypes.d.ts +1 -0
  150. package/dist/src/types/deployment/DeploymentTypes.js +0 -1
  151. package/dist/src/types/deployment/cloudformation.js +0 -1
  152. package/dist/src/types/deployment/index.d.ts +3 -1
  153. package/dist/src/types/deployment/index.js +1 -1
  154. package/dist/src/types/deployment/parallel.js +1 -10
  155. package/dist/src/types/deploymentEventSchema.d.ts +158 -0
  156. package/dist/src/types/deploymentEventSchema.js +1 -0
  157. package/dist/src/types/detection.d.ts +22 -0
  158. package/dist/src/types/detection.js +1 -0
  159. package/dist/src/types/entitlements.d.ts +31 -0
  160. package/dist/src/types/entitlements.js +0 -0
  161. package/dist/src/types/errors/CdkError.js +1 -20
  162. package/dist/src/types/errors/ServiceError.d.ts +2 -1
  163. package/dist/src/types/errors/ServiceError.js +1 -119
  164. package/dist/src/types/errors/index.d.ts +2 -0
  165. package/dist/src/types/errors/index.js +1 -0
  166. package/dist/src/types/events.d.ts +3 -9
  167. package/dist/src/types/events.js +0 -5
  168. package/dist/src/types/frameworkBuilder.d.ts +96 -0
  169. package/dist/src/types/frameworkBuilder.js +8 -0
  170. package/dist/src/types/index.d.ts +19 -4
  171. package/dist/src/types/index.js +1 -9
  172. package/dist/src/types/operations.d.ts +3 -2
  173. package/dist/src/types/operations.js +1 -285
  174. package/dist/src/types/orgConfig.d.ts +2 -10
  175. package/dist/src/types/orgConfig.js +0 -11
  176. package/dist/src/types/params.d.ts +61 -0
  177. package/dist/src/types/patternDetection.d.ts +14 -16
  178. package/dist/src/types/patternDetection.js +14 -18
  179. package/dist/src/types/patternTypes.d.ts +19 -0
  180. package/dist/src/types/patternTypes.js +1 -0
  181. package/dist/src/types/stepDefinitions.d.ts +163 -0
  182. package/dist/src/types/stepDefinitions.js +98 -0
  183. package/dist/src/types/validation.js +0 -1
  184. package/dist/src/util/dockerfileDetection.d.ts +5 -0
  185. package/dist/src/util/dockerfileDetection.js +1 -0
  186. package/dist/src/util/index.d.ts +4 -3
  187. package/dist/src/util/index.js +1 -3
  188. package/dist/src/util/sequencedCallbacks.d.ts +44 -0
  189. package/dist/src/util/sequencedCallbacks.js +1 -0
  190. package/package.json +49 -8
  191. package/dist/src/aws/utils/CloudFormationFailureAnalyser.d.ts +0 -32
  192. package/dist/src/aws/utils/CloudFormationFailureAnalyser.js +0 -228
  193. package/dist/src/aws/utils/errors.d.ts +0 -26
  194. package/dist/src/aws/utils/errors.js +0 -59
  195. package/dist/src/util/fsHelpers.d.ts +0 -4
  196. package/dist/src/util/fsHelpers.js +0 -16
  197. package/dist/src/util/securityHelpers.d.ts +0 -31
  198. package/dist/src/util/securityHelpers.js +0 -124
  199. package/dist/src/util/singleton.d.ts +0 -2
  200. package/dist/src/util/singleton.js +0 -9
  201. package/dist/src/util/sleep.d.ts +0 -4
  202. package/dist/src/util/sleep.js +0 -4
@@ -1 +1,2 @@
1
1
  export { ApplicationStackService } from "./ApplicationStackService.js";
2
+ export { destroyAllStacks, convertDestroyResultIfNotExists, handleDestroyError } from "./applicationStackHelpers.js";
@@ -1 +1 @@
1
- export { ApplicationStackService } from "./ApplicationStackService.js";
1
+ import{ApplicationStackService as o}from"./ApplicationStackService.js";import{destroyAllStacks as s,convertDestroyResultIfNotExists as c,handleDestroyError as l}from"./applicationStackHelpers.js";export{o as ApplicationStackService,c as convertDestroyResultIfNotExists,s as destroyAllStacks,l as handleDestroyError};
@@ -0,0 +1,6 @@
1
+ export { CdkService, CdkArgumentBuilder, CdkProcessManager, CdkEventMonitor, startStackMonitoring, DEFAULT_DEPLOY_TIMEOUT_MS, isCdkError, formatInfrastructureError, getStructuralHint, getSourceContext, hasCdkDifferences, parseDiffOutput, CloudFormationService, CloudFormationError } from "./infrastructure/index.js";
2
+ export type { CdkContext, CdkOptions, CdkOutput, CheckDifferencesResult, CdkServiceOptions, ICdkProcessManager, DiffDetails, CloudFormationCallbacks } from "./infrastructure/index.js";
3
+ export { TemplateHashService, TemplateHashError, type TemplateComparisonResult } from "./supporting/index.js";
4
+ export { CdkContextBuilder } from "./supporting/index.js";
5
+ export { emitProgress, PROGRESS_MESSAGES, parseBuildPhase, buildStepContextBuildConfig, convertCloudFormationOutputsToRecord, type CloudFormationOutput } from "./supporting/index.js";
6
+ export { ApplicationStackService } from "./application/index.js";
@@ -0,0 +1 @@
1
+ import{CdkService as t,CdkArgumentBuilder as o,CdkProcessManager as i,CdkEventMonitor as a,startStackMonitoring as n,DEFAULT_DEPLOY_TIMEOUT_MS as u,isCdkError as d,formatInfrastructureError as s,getStructuralHint as S,getSourceContext as c,hasCdkDifferences as p,parseDiffOutput as C,CloudFormationService as m,CloudFormationError as f}from"./infrastructure/index.js";import{TemplateHashService as E,TemplateHashError as k}from"./supporting/index.js";import{CdkContextBuilder as g}from"./supporting/index.js";import{emitProgress as M,PROGRESS_MESSAGES as T,parseBuildPhase as O,buildStepContextBuildConfig as P,convertCloudFormationOutputsToRecord as h}from"./supporting/index.js";import{ApplicationStackService as B}from"./application/index.js";export{B as ApplicationStackService,o as CdkArgumentBuilder,g as CdkContextBuilder,a as CdkEventMonitor,i as CdkProcessManager,t as CdkService,f as CloudFormationError,m as CloudFormationService,u as DEFAULT_DEPLOY_TIMEOUT_MS,T as PROGRESS_MESSAGES,k as TemplateHashError,E as TemplateHashService,P as buildStepContextBuildConfig,h as convertCloudFormationOutputsToRecord,M as emitProgress,s as formatInfrastructureError,c as getSourceContext,S as getStructuralHint,p as hasCdkDifferences,d as isCdkError,O as parseBuildPhase,C as parseDiffOutput,n as startStackMonitoring};
@@ -1,67 +1 @@
1
- import { filterDangerousEnvVars } from "../../util/securityHelpers.js";
2
- export class CdkArgumentBuilder {
3
- buildContextArgs(context) {
4
- const args = [];
5
- if (context?.accountId) {
6
- args.push("-c", `accountId=${context.accountId}`);
7
- }
8
- if (context?.environment) {
9
- args.push("-c", `environment=${context.environment}`);
10
- }
11
- if (context?.managedAccount) {
12
- args.push("-c", "managedAccount=true");
13
- }
14
- if (context?.accountName) {
15
- args.push("-c", `accountName=${context.accountName}`);
16
- }
17
- if (context?.imageVersion) {
18
- args.push("-c", `imageVersion=${context.imageVersion}`);
19
- }
20
- if (context?.orgId) {
21
- args.push("-c", `orgId=${context.orgId}`);
22
- }
23
- if (context?.rootId) {
24
- args.push("-c", `rootId=${context.rootId}`);
25
- }
26
- if (context?.managementAccountId) {
27
- args.push("-c", `managementAccountId=${context.managementAccountId}`);
28
- }
29
- if (context?.ipamPoolId) {
30
- args.push("-c", `ipamPoolId=${context.ipamPoolId}`);
31
- }
32
- if (context?.fjallOrgId) {
33
- args.push("-c", `fjallOrgId=${context.fjallOrgId}`);
34
- }
35
- if (context?.orgConfig) {
36
- args.push("-c", `orgConfig=${context.orgConfig}`);
37
- }
38
- return args;
39
- }
40
- injectCascadeCredentials(env, credentials) {
41
- if (credentials) {
42
- env.AWS_ACCESS_KEY_ID = credentials.accessKeyId;
43
- env.AWS_SECRET_ACCESS_KEY = credentials.secretAccessKey;
44
- if (credentials.sessionToken) {
45
- env.AWS_SESSION_TOKEN = credentials.sessionToken;
46
- }
47
- }
48
- }
49
- buildCdkEnv(options) {
50
- const env = {
51
- ...filterDangerousEnvVars(process.env),
52
- CI: "true",
53
- FORCE_COLOR: "0",
54
- CDK_DISABLE_VERSION_CHECK: "1"
55
- };
56
- if (options?.context?.region) {
57
- env.AWS_REGION = options.context.region;
58
- env.AWS_DEFAULT_REGION = options.context.region;
59
- env.CDK_DEFAULT_REGION = options.context.region;
60
- }
61
- if (options?.context?.accountId) {
62
- env.CDK_DEFAULT_ACCOUNT = options.context.accountId;
63
- }
64
- this.injectCascadeCredentials(env, options?.credentials);
65
- return env;
66
- }
67
- }
1
+ import{filterDangerousEnvVars as a}from"@fjall/util";class c{buildContextArgs(i){const r=[];return i?.accountId&&r.push("-c",`accountId=${i.accountId}`),i?.environment&&r.push("-c",`environment=${i.environment}`),i?.managedAccount&&r.push("-c","managedAccount=true"),i?.accountName&&r.push("-c",`accountName=${i.accountName}`),i?.imageVersion&&r.push("-c",`imageVersion=${i.imageVersion}`),i?.orgId&&r.push("-c",`orgId=${i.orgId}`),i?.rootId&&r.push("-c",`rootId=${i.rootId}`),i?.managementAccountId&&r.push("-c",`managementAccountId=${i.managementAccountId}`),i?.ipamPoolId&&r.push("-c",`ipamPoolId=${i.ipamPoolId}`),i?.fjallOrgId&&r.push("-c",`fjallOrgId=${i.fjallOrgId}`),i?.fjallOidcConfigured&&r.push("-c",`fjallOidcConfigured=${i.fjallOidcConfigured}`),i?.orgConfig&&r.push("-c",`orgConfig=${i.orgConfig}`),r}injectCascadeCredentials(i,r){r&&(i.AWS_ACCESS_KEY_ID=r.accessKeyId,i.AWS_SECRET_ACCESS_KEY=r.secretAccessKey,r.sessionToken&&(i.AWS_SESSION_TOKEN=r.sessionToken))}buildCdkEnv(i){const r={...a(process.env),CI:"true",FORCE_COLOR:"0",CDK_DISABLE_VERSION_CHECK:"1"};return i?.context?.region&&(r.AWS_REGION=i.context.region,r.AWS_DEFAULT_REGION=i.context.region,r.CDK_DEFAULT_REGION=i.context.region),i?.context?.accountId&&(r.CDK_DEFAULT_ACCOUNT=i.context.accountId),this.injectCascadeCredentials(r,i?.credentials),r}}export{c as CdkArgumentBuilder};
@@ -1,7 +1,14 @@
1
1
  import type { Result } from "@fjall/generator";
2
2
  import { CdkError } from "../../types/errors/CdkError.js";
3
3
  import { type DiffDetails } from "./CdkOutputParser.js";
4
+ import type { ICdkProcessManager } from "./ICdkProcessManager.js";
4
5
  import type { CdkOptions, CdkOutput } from "./CdkService.js";
6
+ /** Synth is CPU-bound template generation — 5 minutes is generous */
7
+ export declare const SYNTH_TIMEOUT_MS = 300000;
8
+ /** Bootstrap creates a single stack with a handful of resources */
9
+ export declare const BOOTSTRAP_TIMEOUT_MS = 180000;
10
+ /** Import maps existing resources into CDK state — slower than deploy due to resource lookup */
11
+ export declare const IMPORT_TIMEOUT_MS = 1200000;
5
12
  export interface CheckDifferencesResult {
6
13
  hasDifferences: boolean;
7
14
  output?: string;
@@ -9,11 +16,12 @@ export interface CheckDifferencesResult {
9
16
  }
10
17
  /**
11
18
  * Runs low-level CDK CLI commands (synth, deploy, destroy, diff, bootstrap, import).
12
- * Delegates process management to CdkProcessManager.
19
+ * Delegates process management to CdkProcessManager (or any ICdkProcessManager).
13
20
  */
14
21
  export declare class CdkCommandRunner {
15
22
  private processManager;
16
- constructor();
23
+ constructor(processManager: ICdkProcessManager);
24
+ dispose(): void;
17
25
  checkDifferences(path: string, stackName?: string, options?: CdkOptions): Promise<Result<CheckDifferencesResult, CdkError>>;
18
26
  deploy(path: string, stackName?: string, options?: CdkOptions): Promise<Result<CdkOutput, string>>;
19
27
  destroy(path: string, stackName?: string, options?: CdkOptions): Promise<Result<CdkOutput, string>>;
@@ -1,22 +1,21 @@
1
1
  import { tmpdir } from "os";
2
- import { logger } from "@fjall/util";
2
+ import { logger } from "@fjall/util/logger";
3
3
  import { success, failure } from "@fjall/generator";
4
4
  import { CdkError } from "../../types/errors/CdkError.js";
5
5
  import { DEFAULT_REGION } from "../../aws/utils/regions.js";
6
6
  import { isCdkError, formatInfrastructureError } from "./CdkErrorFormatter.js";
7
7
  import { hasCdkDifferences, parseDiffOutput } from "./CdkOutputParser.js";
8
- import { CdkArgumentBuilder } from "./CdkArgumentBuilder.js";
9
- import { CdkProcessManager } from "./CdkProcessManager.js";
10
8
  import { DEFAULT_DEPLOY_TIMEOUT_MS } from "./CdkEventMonitoring.js";
11
9
  import { analyseBootstrapError } from "./CdkOutputAnalyser.js";
12
10
  /** Synth is CPU-bound template generation — 5 minutes is generous */
13
- const SYNTH_TIMEOUT_MS = 300_000;
11
+ export const SYNTH_TIMEOUT_MS = 300_000;
14
12
  /** Bootstrap creates a single stack with a handful of resources */
15
- const BOOTSTRAP_TIMEOUT_MS = 180_000;
13
+ export const BOOTSTRAP_TIMEOUT_MS = 180_000;
16
14
  /** Import maps existing resources into CDK state — slower than deploy due to resource lookup */
17
- const IMPORT_TIMEOUT_MS = 1_200_000;
15
+ export const IMPORT_TIMEOUT_MS = 1_200_000;
18
16
  /** CDK flags used across multiple commands */
19
17
  const CDK_FLAGS = Object.freeze({
18
+ APP: "--app",
20
19
  CI: "--ci",
21
20
  REQUIRE_APPROVAL: "--require-approval",
22
21
  APPROVAL_NEVER: "never",
@@ -26,13 +25,15 @@ const CDK_FLAGS = Object.freeze({
26
25
  });
27
26
  /**
28
27
  * Runs low-level CDK CLI commands (synth, deploy, destroy, diff, bootstrap, import).
29
- * Delegates process management to CdkProcessManager.
28
+ * Delegates process management to CdkProcessManager (or any ICdkProcessManager).
30
29
  */
31
30
  export class CdkCommandRunner {
32
31
  processManager;
33
- constructor() {
34
- const argBuilder = new CdkArgumentBuilder();
35
- this.processManager = new CdkProcessManager(argBuilder);
32
+ constructor(processManager) {
33
+ this.processManager = processManager;
34
+ }
35
+ dispose() {
36
+ this.processManager.dispose();
36
37
  }
37
38
  async checkDifferences(path, stackName, options) {
38
39
  const args = ["diff"];
@@ -50,7 +51,9 @@ export class CdkCommandRunner {
50
51
  const result = await this.processManager.runCdkCommand(path, args, {
51
52
  ...options,
52
53
  // Diff command returns non-zero if differences exist
53
- ignoreExitCode: true
54
+ ignoreExitCode: true,
55
+ // Diff output includes stderr (CDK writes errors there)
56
+ combineOutput: true
54
57
  });
55
58
  if (!result.success) {
56
59
  return failure(new CdkError(formatInfrastructureError(result.error, path), "diff_failed", undefined, undefined, result.error, undefined, false));
@@ -71,10 +74,10 @@ export class CdkCommandRunner {
71
74
  async deploy(path, stackName, options) {
72
75
  const args = ["deploy"];
73
76
  if (options?.appDir) {
74
- args.push("--app", options.appDir);
77
+ args.push(CDK_FLAGS.APP, options.appDir);
75
78
  }
76
79
  else if (options?.useCdkOut) {
77
- args.push("--app", "cdk.out");
80
+ args.push(CDK_FLAGS.APP, "cdk.out");
78
81
  }
79
82
  if (stackName) {
80
83
  args.push(stackName);
@@ -107,10 +110,10 @@ export class CdkCommandRunner {
107
110
  async destroy(path, stackName, options) {
108
111
  const args = ["destroy"];
109
112
  if (options?.appDir) {
110
- args.push("--app", options.appDir);
113
+ args.push(CDK_FLAGS.APP, options.appDir);
111
114
  }
112
115
  else if (options?.useCdkOut) {
113
- args.push("--app", "cdk.out");
116
+ args.push(CDK_FLAGS.APP, "cdk.out");
114
117
  }
115
118
  if (stackName) {
116
119
  args.push(stackName);
@@ -1,194 +1,16 @@
1
- import { readFileSync } from "fs";
2
- import { join } from "path";
3
- const CDK_ERROR_PATTERNS = [
4
- // Authentication and credentials errors
5
- /Unable to locate credentials/i,
6
- /ExpiredToken/i,
7
- /InvalidUserPool/i,
8
- /AccessDenied/i,
9
- /UnauthorizedAccess/i,
10
- /AssumeRoleUnauthorizedAccess/i,
11
- /The security token included in the request is invalid/i,
12
- /Could not assume role/i,
13
- // Bootstrap errors
14
- /This stack uses assets, so the toolkit stack must be deployed/i,
15
- /Has the environment been bootstrapped/i,
16
- /Please run 'cdk bootstrap'/i,
17
- /requires a newer version of the CDK CLI/i,
18
- // Stack not found errors
19
- /Stack .* does not exist/i,
20
- /Unable to resolve AWS account/i,
21
- // General CDK errors
22
- /ENOENT.*cdk\.json/i,
23
- /Cannot find module/i,
24
- /SyntaxError:/i,
25
- /TypeError:/i,
26
- /ReferenceError:/i,
27
- /Error: /i,
28
- // Common failure messages
29
- /❌ .*failed/i,
30
- /\[ERROR\]/i,
31
- /fatal:/i
32
- ];
33
- const STRUCTURAL_HINTS = {
34
- TS1005: "Check for missing or extra brackets, braces, or commas",
35
- TS1135: "Check for mismatched brackets or braces — a common cause is extra `},` or `]` characters",
36
- TS1136: "Check for mismatched braces in object literals",
37
- TS1109: "Check for extra commas or mismatched delimiters",
38
- TS1003: "Check for syntax errors near the indicated position"
39
- };
40
- export function isCdkError(output) {
41
- if (!output)
42
- return false;
43
- return CDK_ERROR_PATTERNS.some((pattern) => pattern.test(output));
44
- }
45
- export function getStructuralHint(tsCode) {
46
- return STRUCTURAL_HINTS[tsCode] ?? null;
47
- }
48
- export function getSourceContext(filePath, lineNumber, contextLines = 1) {
49
- try {
50
- const content = readFileSync(filePath, "utf-8");
51
- const lines = content.split("\n");
52
- const start = Math.max(0, lineNumber - 1 - contextLines);
53
- const end = Math.min(lines.length, lineNumber + contextLines);
54
- const gutterWidth = String(end).length;
55
- const formatted = [];
56
- for (let i = start; i < end; i++) {
57
- const num = String(i + 1).padStart(gutterWidth);
58
- const marker = i === lineNumber - 1 ? ">" : " ";
59
- formatted.push(`${marker} ${num} | ${lines[i]}`);
60
- }
61
- return formatted.join("\n");
62
- }
63
- catch {
64
- // File not readable — skip source context display
65
- return null;
66
- }
67
- }
68
- export function formatInfrastructureError(output, appPath) {
69
- const lines = output.split("\n");
70
- // Handle TypeScript compilation errors
71
- if (output.includes("error TS")) {
72
- const tsErrorRegex = /([\w./-]+\.ts)\((\d+),(\d+)\): error (TS\d+): (.+)/;
73
- const parsed = [];
74
- for (const line of lines) {
75
- const match = line.match(tsErrorRegex);
76
- if (match) {
77
- parsed.push({
78
- file: match[1],
79
- line: parseInt(match[2], 10),
80
- col: parseInt(match[3], 10),
81
- code: match[4],
82
- message: match[5]
83
- });
84
- }
85
- }
86
- if (parsed.length > 0) {
87
- const seen = new Set();
88
- const unique = parsed.filter((e) => {
89
- const key = `${e.file}:${e.line}`;
90
- if (seen.has(key))
91
- return false;
92
- seen.add(key);
93
- return true;
94
- });
95
- const errors = unique.slice(0, 3);
96
- const firstError = errors[0];
97
- const parts = [];
98
- parts.push(`TypeScript compilation failed in ${firstError.file}:\n`);
99
- if (appPath) {
100
- const resolvedPath = join(appPath, firstError.file);
101
- const context = getSourceContext(resolvedPath, firstError.line);
102
- if (context) {
103
- parts.push(context);
104
- parts.push("");
105
- }
106
- }
107
- for (const err of errors) {
108
- parts.push(`Error on line ${err.line}: ${err.message} (${err.code})`);
109
- const hint = getStructuralHint(err.code);
110
- if (hint) {
111
- parts.push(`Hint: ${hint}`);
112
- }
113
- }
114
- return parts.join("\n");
115
- }
116
- }
117
- // Handle multi-line CDK validation errors
118
- const multiLineValidationMatch = output.match(/Validation failed with the following errors:([\s\S]*?)(?=\n\s*at\s|\n\n|$)/);
119
- if (multiLineValidationMatch) {
120
- const errorLines = multiLineValidationMatch[1]
121
- .split("\n")
122
- .map((l) => l.trim())
123
- .filter((l) => l.length > 0);
124
- return `Validation failed with the following errors:\n${errorLines.map((l) => ` ${l}`).join("\n")}`;
125
- }
126
- // Handle CDK ValidationError (e.g., missing asset directories)
127
- const validationMatch = output.match(/ValidationError:\s*(.+?)(?:\n|$)/);
128
- if (validationMatch) {
129
- const detail = validationMatch[1];
130
- const constructMatch = output.match(/at path \[([^\]]+)\] in ([\w.-]+)/);
131
- let formatted = `${detail}`;
132
- if (constructMatch) {
133
- formatted += `\nConstruct: ${constructMatch[1]}`;
134
- }
135
- if (detail.includes("Cannot find asset")) {
136
- const assetPath = detail.match(/at (.+)/)?.[1];
137
- if (assetPath) {
138
- formatted += `\nHint: The build output directory does not exist. Make sure the build step has completed before deploying`;
139
- }
140
- }
141
- return formatted;
142
- }
143
- // Try to extract: file path, code snippet, error type/message
144
- let fileLine = "";
145
- let codeSnippet = "";
146
- let pointer = "";
147
- let errorMessage = "";
148
- for (let i = 0; i < lines.length; i++) {
149
- const line = lines[i];
150
- const fileMatch = line.match(/^(\/[^:]+\.ts):(\d+)/);
151
- if (fileMatch && !fileLine) {
152
- const fullPath = fileMatch[1];
153
- const lineNum = fileMatch[2];
154
- const fileName = fullPath.split("/").pop() || fullPath;
155
- fileLine = `${fileName}:${lineNum}`;
156
- if (i + 1 < lines.length) {
157
- codeSnippet = lines[i + 1];
158
- }
159
- if (i + 2 < lines.length && lines[i + 2].includes("^")) {
160
- pointer = lines[i + 2];
161
- }
162
- }
163
- const errorMatch = line.match(/^(\w*Error):\s*(.+)/);
164
- if (errorMatch && !errorMessage) {
165
- errorMessage = `${errorMatch[1]}: ${errorMatch[2]}`;
166
- }
167
- }
168
- if (fileLine && errorMessage) {
169
- let formatted = `Error in ${fileLine}\n`;
170
- if (codeSnippet) {
171
- formatted += `${codeSnippet}\n`;
172
- }
173
- if (pointer) {
174
- formatted += `${pointer}\n`;
175
- }
176
- formatted += `\n${errorMessage}`;
177
- return formatted;
178
- }
179
- if (errorMessage) {
180
- return errorMessage;
181
- }
182
- // Fallback: return first few meaningful lines, filtering out noise
183
- const meaningfulLines = lines
184
- .filter((l) => l.trim() &&
185
- l.length < 500 &&
186
- !l.includes("at Module.") &&
187
- !l.includes("at Object.") &&
188
- !l.includes("at Function.") &&
189
- !l.includes("node:internal") &&
190
- !l.includes("node_modules/ts-node") &&
191
- !l.includes("node_modules/aws-cdk"))
192
- .slice(0, 5);
193
- return meaningfulLines.join("\n") || output;
194
- }
1
+ import{readFileSync as k}from"fs";import{join as T}from"path";const E=[/Unable to locate credentials/i,/ExpiredToken/i,/InvalidUserPool/i,/AccessDenied/i,/UnauthorizedAccess/i,/AssumeRoleUnauthorizedAccess/i,/The security token included in the request is invalid/i,/Could not assume role/i,/This stack uses assets, so the toolkit stack must be deployed/i,/Has the environment been bootstrapped/i,/Please run 'cdk bootstrap'/i,/requires a newer version of the CDK CLI/i,/Stack .* does not exist/i,/Unable to resolve AWS account/i,/ENOENT.*cdk\.json/i,/Cannot find module/i,/SyntaxError:/i,/TypeError:/i,/ReferenceError:/i,/Error: /i,/❌ .*failed/i,/\[ERROR\]/i,/fatal:/i],x={TS1005:"Check for missing or extra brackets, braces, or commas",TS1135:"Check for mismatched brackets or braces \u2014 a common cause is extra `},` or `]` characters",TS1136:"Check for mismatched braces in object literals",TS1109:"Check for extra commas or mismatched delimiters",TS1003:"Check for syntax errors near the indicated position"};function w(n){return n?E.some(a=>a.test(n)):!1}function C(n){return x[n]??null}function b(n,a,r=1){try{const m=k(n,"utf-8").split(`
2
+ `),f=Math.max(0,a-1-r),u=Math.min(m.length,a+r),p=String(u).length,s=[];for(let h=f;h<u;h++){const e=String(h+1).padStart(p),t=h===a-1?">":" ";s.push(`${t} ${e} | ${m[h]}`)}return s.join(`
3
+ `)}catch{return null}}function M(n,a){const r=n.split(`
4
+ `);if(n.includes("error TS")){const e=/([\w./-]+\.ts)\((\d+),(\d+)\): error (TS\d+): (.+)/,t=[];for(const i of r){const o=i.match(e);o&&t.push({file:o[1],line:parseInt(o[2],10),col:parseInt(o[3],10),code:o[4],message:o[5]})}if(t.length>0){const i=new Set,$=t.filter(c=>{const l=`${c.file}:${c.line}`;return i.has(l)?!1:(i.add(l),!0)}).slice(0,3),g=$[0],d=[];if(d.push(`TypeScript compilation failed in ${g.file}:
5
+ `),a){const c=T(a,g.file),l=b(c,g.line);l&&(d.push(l),d.push(""))}for(const c of $){d.push(`Error on line ${c.line}: ${c.message} (${c.code})`);const l=C(c.code);l&&d.push(`Hint: ${l}`)}return d.join(`
6
+ `)}}const S=n.match(/Validation failed with the following errors:([\s\S]*?)(?=\n\s*at\s|\n\n|$)/);if(S)return`Validation failed with the following errors:
7
+ ${S[1].split(`
8
+ `).map(t=>t.trim()).filter(t=>t.length>0).map(t=>` ${t}`).join(`
9
+ `)}`;const m=n.match(/ValidationError:\s*(.+?)(?:\n|$)/);if(m){const e=m[1],t=n.match(/at path \[([^\]]+)\] in ([\w.-]+)/);let i=`${e}`;return t&&(i+=`
10
+ Construct: ${t[1]}`),e.includes("Cannot find asset")&&e.match(/at (.+)/)?.[1]&&(i+=`
11
+ Hint: The build output directory does not exist. Make sure the build step has completed before deploying`),i}let f="",u="",p="",s="";for(let e=0;e<r.length;e++){const t=r[e],i=t.match(/^(\/[^:]+\.ts):(\d+)/);if(i&&!f){const $=i[1],g=i[2];f=`${$.split("/").pop()||$}:${g}`,e+1<r.length&&(u=r[e+1]),e+2<r.length&&r[e+2].includes("^")&&(p=r[e+2])}const o=t.match(/^(\w*Error):\s*(.+)/);o&&!s&&(s=`${o[1]}: ${o[2]}`)}if(f&&s){let e=`Error in ${f}
12
+ `;return u&&(e+=`${u}
13
+ `),p&&(e+=`${p}
14
+ `),e+=`
15
+ ${s}`,e}return s||r.filter(e=>e.trim()&&e.length<500&&!e.includes("at Module.")&&!e.includes("at Object.")&&!e.includes("at Function.")&&!e.includes("node:internal")&&!e.includes("node_modules/ts-node")&&!e.includes("node_modules/aws-cdk")).slice(0,5).join(`
16
+ `)||n}export{M as formatInfrastructureError,b as getSourceContext,C as getStructuralHint,w as isCdkError};
@@ -1,41 +1 @@
1
- import { logger, getErrorMessage } from "@fjall/util";
2
- import { CloudFormationFailureAnalyser } from "../../aws/utils/CloudFormationFailureAnalyser.js";
3
- /** Deploy/destroy default — CloudFormation stacks can take up to 30 minutes */
4
- export const DEFAULT_DEPLOY_TIMEOUT_MS = 1_800_000;
5
- export function startStackMonitoring(monitor, stackName, onResourceProgress) {
6
- return monitor
7
- .waitForStackComplete(stackName, {
8
- timeout: DEFAULT_DEPLOY_TIMEOUT_MS,
9
- pollInterval: 2000,
10
- onResourceUpdate: onResourceProgress,
11
- onStackComplete: (_success, _message) => {
12
- // Stack deployment completed — no console output per architecture
13
- }
14
- })
15
- .catch((err) => {
16
- logger.debug("CdkService", "Stack monitoring failed", {
17
- error: getErrorMessage(err)
18
- });
19
- return {
20
- success: false,
21
- failureReason: "Monitoring failed"
22
- };
23
- });
24
- }
25
- export class CdkEventMonitor {
26
- eventLogWriterFactory;
27
- constructor(options) {
28
- this.eventLogWriterFactory = options?.eventLogWriterFactory;
29
- }
30
- async createEventMonitor(operation, stackName, region, context, aws) {
31
- const cloudFormationEventsModule = await import("../../aws/utils/cloudformationEvents.js");
32
- const monitor = new cloudFormationEventsModule.CloudFormationEventMonitor(aws, {
33
- failureAnalyser: new CloudFormationFailureAnalyser(),
34
- eventLogWriterFactory: this.eventLogWriterFactory
35
- });
36
- const deploymentId = `${operation}-${Date.now()}`;
37
- const deploymentName = context.target || context.deployType || "deployment";
38
- monitor.enableLogging(deploymentId, stackName, region, deploymentName);
39
- return monitor;
40
- }
41
- }
1
+ import{logger as m}from"@fjall/util/logger";import{getErrorMessage as g}from"@fjall/util";import{CloudFormationFailureAnalyser as u}from"@fjall/util/aws";const p=18e5;function F(n,e,o){return n.waitForStackComplete(e,{timeout:p,pollInterval:2e3,onResourceUpdate:o,onStackComplete:(t,r)=>{}}).catch(t=>(m.debug("CdkService","Stack monitoring failed",{error:g(t)}),{success:!1,failureReason:"Monitoring failed"}))}class f{eventLogWriterFactory;constructor(e){this.eventLogWriterFactory=e?.eventLogWriterFactory}async createEventMonitor(e,o,t,r,i){const c=await import("../../aws/utils/cloudformationEvents.js"),a=new c.CloudFormationEventMonitor(i,{failureAnalyser:new u,eventLogWriterFactory:this.eventLogWriterFactory}),s=`${e}-${Date.now()}`,l=r.target||r.deployType||"deployment";return a.enableLogging(s,o,t,l),a}}export{f as CdkEventMonitor,p as DEFAULT_DEPLOY_TIMEOUT_MS,F as startStackMonitoring};
@@ -1,4 +1,4 @@
1
- import { logger } from "@fjall/util";
1
+ import { logger } from "@fjall/util/logger";
2
2
  import { STACK_NOT_FOUND_PATTERN, CDK_NO_STACKS_MATCH } from "../../aws/utils/cloudformationEvents.js";
3
3
  import { success, failure } from "@fjall/generator";
4
4
  import { formatInfrastructureError } from "./CdkErrorFormatter.js";
@@ -1,33 +1,2 @@
1
- export function hasCdkDifferences(output) {
2
- if (!output)
3
- return false;
4
- // Prefer the summary line: "Number of stacks with differences: 2"
5
- const summaryRegex = /Number of stacks with differences:\s*(\d+)/;
6
- const summaryMatch = output.match(summaryRegex);
7
- if (summaryMatch && summaryMatch[1]) {
8
- const diffCount = parseInt(summaryMatch[1], 10);
9
- if (!isNaN(diffCount)) {
10
- return diffCount > 0;
11
- }
12
- }
13
- // Fallback: if all stacks report "There were no differences" then no changes
14
- const allNoDiff = output
15
- .split("\n")
16
- .filter((l) => l.trim().startsWith("Stack"))
17
- .every((l) => l.includes("There were no differences"));
18
- return !allNoDiff;
19
- }
20
- export function parseDiffOutput(output) {
21
- const details = {
22
- hasSecurityChanges: output.includes("(requires replacement)") ||
23
- output.includes("IAM Statement Changes"),
24
- resourceChanges: 0,
25
- outputChanges: 0,
26
- resources: []
27
- };
28
- const resourceMatches = output.match(/\[\+\]|\[-\]|\[~\]/g);
29
- if (resourceMatches) {
30
- details.resourceChanges = resourceMatches.length;
31
- }
32
- return details;
33
- }
1
+ function c(e){if(!e)return!1;const n=/Number of stacks with differences:\s*(\d+)/,s=e.match(n);if(s&&s[1]){const r=parseInt(s[1],10);if(!isNaN(r))return r>0}return!e.split(`
2
+ `).filter(r=>r.trim().startsWith("Stack")).every(r=>r.includes("There were no differences"))}function a(e){const n={hasSecurityChanges:e.includes("(requires replacement)")||e.includes("IAM Statement Changes"),resourceChanges:0,outputChanges:0,resources:[]},s=e.match(/\[\+\]|\[-\]|\[~\]/g);return s&&(n.resourceChanges=s.length),n}export{c as hasCdkDifferences,a as parseDiffOutput};
@@ -6,9 +6,13 @@ export declare class CdkProcessManager {
6
6
  private runningProcesses;
7
7
  private processCounter;
8
8
  private argBuilder;
9
+ private exitHandler;
10
+ private sigintHandler;
11
+ private sigtermHandler;
9
12
  constructor(argBuilder: CdkArgumentBuilder);
10
13
  forceKillProcess(child: ChildProcess): void;
11
14
  cleanup(): void;
15
+ dispose(): void;
12
16
  runCdkCommandPassthrough(workingDir: string, args: string[], options?: CdkOptions & {
13
17
  ignoreExitCode?: boolean;
14
18
  }): Promise<Result<CdkOutput, string>>;
@@ -16,5 +20,6 @@ export declare class CdkProcessManager {
16
20
  ignoreExitCode?: boolean;
17
21
  skipProjectCheck?: boolean;
18
22
  extraEnv?: Record<string, string>;
23
+ combineOutput?: boolean;
19
24
  }): Promise<Result<CdkOutput, string>>;
20
25
  }