@aws-cdk-testing/cli-integ 0.0.0

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 (257) hide show
  1. package/.eslintrc.js +9 -0
  2. package/LICENSE +202 -0
  3. package/NOTICE +16 -0
  4. package/README.md +205 -0
  5. package/bin/apply-patches +22 -0
  6. package/bin/download-and-run-old-tests +52 -0
  7. package/bin/query-github +2 -0
  8. package/bin/query-github.d.ts +1 -0
  9. package/bin/query-github.js +54 -0
  10. package/bin/query-github.ts +56 -0
  11. package/bin/run-suite +2 -0
  12. package/bin/run-suite.d.ts +1 -0
  13. package/bin/run-suite.js +131 -0
  14. package/bin/run-suite.ts +140 -0
  15. package/bin/stage-distribution +2 -0
  16. package/bin/stage-distribution.d.ts +1 -0
  17. package/bin/stage-distribution.js +217 -0
  18. package/bin/stage-distribution.ts +267 -0
  19. package/bin/test-root +2 -0
  20. package/bin/test-root.d.ts +1 -0
  21. package/bin/test-root.js +6 -0
  22. package/bin/test-root.ts +3 -0
  23. package/entrypoints/test-cli-regression-against-current-code.sh +11 -0
  24. package/entrypoints/test-cli-regression-against-latest-release.sh +11 -0
  25. package/entrypoints/test-cli-regression.bash +83 -0
  26. package/entrypoints/test.sh +12 -0
  27. package/lib/aws.d.ts +51 -0
  28. package/lib/aws.js +206 -0
  29. package/lib/aws.ts +263 -0
  30. package/lib/corking.d.ts +12 -0
  31. package/lib/corking.js +35 -0
  32. package/lib/corking.ts +33 -0
  33. package/lib/eventually.d.ts +20 -0
  34. package/lib/eventually.js +34 -0
  35. package/lib/eventually.ts +42 -0
  36. package/lib/files.d.ts +15 -0
  37. package/lib/files.js +80 -0
  38. package/lib/files.ts +80 -0
  39. package/lib/github.d.ts +4 -0
  40. package/lib/github.js +43 -0
  41. package/lib/github.ts +43 -0
  42. package/lib/index.d.ts +13 -0
  43. package/lib/index.js +30 -0
  44. package/lib/index.ts +13 -0
  45. package/lib/integ-test.d.ts +10 -0
  46. package/lib/integ-test.js +70 -0
  47. package/lib/integ-test.ts +81 -0
  48. package/lib/lists.d.ts +1 -0
  49. package/lib/lists.js +11 -0
  50. package/lib/lists.ts +9 -0
  51. package/lib/memoize.d.ts +6 -0
  52. package/lib/memoize.js +18 -0
  53. package/lib/memoize.ts +14 -0
  54. package/lib/npm.d.ts +8 -0
  55. package/lib/npm.js +38 -0
  56. package/lib/npm.ts +41 -0
  57. package/lib/package-sources/release-source.d.ts +23 -0
  58. package/lib/package-sources/release-source.js +71 -0
  59. package/lib/package-sources/release-source.ts +81 -0
  60. package/lib/package-sources/repo-source.d.ts +30 -0
  61. package/lib/package-sources/repo-source.js +97 -0
  62. package/lib/package-sources/repo-source.ts +111 -0
  63. package/lib/package-sources/repo-tools/npm +2 -0
  64. package/lib/package-sources/repo-tools/npm.d.ts +1 -0
  65. package/lib/package-sources/repo-tools/npm.js +43 -0
  66. package/lib/package-sources/repo-tools/npm.ts +48 -0
  67. package/lib/package-sources/source.d.ts +28 -0
  68. package/lib/package-sources/source.js +3 -0
  69. package/lib/package-sources/source.ts +35 -0
  70. package/lib/package-sources/subprocess.d.ts +3 -0
  71. package/lib/package-sources/subprocess.js +17 -0
  72. package/lib/package-sources/subprocess.ts +15 -0
  73. package/lib/resource-pool.d.ts +50 -0
  74. package/lib/resource-pool.js +117 -0
  75. package/lib/resource-pool.ts +140 -0
  76. package/lib/resources.d.ts +1 -0
  77. package/lib/resources.js +6 -0
  78. package/lib/resources.ts +4 -0
  79. package/lib/shell.d.ts +56 -0
  80. package/lib/shell.js +123 -0
  81. package/lib/shell.ts +168 -0
  82. package/lib/staging/codeartifact.d.ts +44 -0
  83. package/lib/staging/codeartifact.js +281 -0
  84. package/lib/staging/codeartifact.ts +387 -0
  85. package/lib/staging/maven.d.ts +5 -0
  86. package/lib/staging/maven.js +91 -0
  87. package/lib/staging/maven.ts +95 -0
  88. package/lib/staging/npm.d.ts +4 -0
  89. package/lib/staging/npm.js +55 -0
  90. package/lib/staging/npm.ts +62 -0
  91. package/lib/staging/nuget.d.ts +4 -0
  92. package/lib/staging/nuget.js +69 -0
  93. package/lib/staging/nuget.ts +75 -0
  94. package/lib/staging/parallel-shell.d.ts +5 -0
  95. package/lib/staging/parallel-shell.js +45 -0
  96. package/lib/staging/parallel-shell.ts +51 -0
  97. package/lib/staging/pypi.d.ts +4 -0
  98. package/lib/staging/pypi.js +48 -0
  99. package/lib/staging/pypi.ts +50 -0
  100. package/lib/staging/usage-dir.d.ts +31 -0
  101. package/lib/staging/usage-dir.js +87 -0
  102. package/lib/staging/usage-dir.ts +99 -0
  103. package/lib/with-aws.d.ts +14 -0
  104. package/lib/with-aws.js +60 -0
  105. package/lib/with-aws.ts +67 -0
  106. package/lib/with-cdk-app.d.ts +210 -0
  107. package/lib/with-cdk-app.js +539 -0
  108. package/lib/with-cdk-app.ts +742 -0
  109. package/lib/with-cli-lib.d.ts +17 -0
  110. package/lib/with-cli-lib.js +123 -0
  111. package/lib/with-cli-lib.ts +134 -0
  112. package/lib/with-packages.d.ts +5 -0
  113. package/lib/with-packages.js +13 -0
  114. package/lib/with-packages.ts +15 -0
  115. package/lib/with-sam.d.ts +33 -0
  116. package/lib/with-sam.js +258 -0
  117. package/lib/with-sam.ts +288 -0
  118. package/lib/with-temporary-directory.d.ts +5 -0
  119. package/lib/with-temporary-directory.js +31 -0
  120. package/lib/with-temporary-directory.ts +35 -0
  121. package/lib/with-timeout.d.ts +19 -0
  122. package/lib/with-timeout.js +34 -0
  123. package/lib/with-timeout.ts +33 -0
  124. package/lib/xpmutex.d.ts +43 -0
  125. package/lib/xpmutex.js +207 -0
  126. package/lib/xpmutex.ts +218 -0
  127. package/package.json +111 -0
  128. package/resources/bootstrap-templates/session-tags.all-roles-deny-all.yaml +703 -0
  129. package/resources/bootstrap-templates/session-tags.deploy-role-deny-sqs.yaml +700 -0
  130. package/resources/cdk-apps/app/app.js +926 -0
  131. package/resources/cdk-apps/app/appsync.hotswap.graphql +3 -0
  132. package/resources/cdk-apps/app/cdk.json +7 -0
  133. package/resources/cdk-apps/app/docker/Dockerfile +2 -0
  134. package/resources/cdk-apps/app/docker/Dockerfile.Custom +2 -0
  135. package/resources/cdk-apps/app/lambda/index.js +4 -0
  136. package/resources/cdk-apps/app/lambda/response.json +3 -0
  137. package/resources/cdk-apps/app/nested-stack.js +65 -0
  138. package/resources/cdk-apps/cfn-include-app/cdk.json +4 -0
  139. package/resources/cdk-apps/cfn-include-app/cfn-include-app.js +21 -0
  140. package/resources/cdk-apps/cfn-include-app/example-template.json +13 -0
  141. package/resources/cdk-apps/rollback-test-app/app.js +110 -0
  142. package/resources/cdk-apps/rollback-test-app/cdk.json +7 -0
  143. package/resources/cdk-apps/sam_cdk_integ_app/bin/test-app.js +11 -0
  144. package/resources/cdk-apps/sam_cdk_integ_app/cdk.json +6 -0
  145. package/resources/cdk-apps/sam_cdk_integ_app/lib/nested-stack.js +19 -0
  146. package/resources/cdk-apps/sam_cdk_integ_app/lib/test-stack.js +134 -0
  147. package/resources/cdk-apps/sam_cdk_integ_app/src/docker/DockerImageFunctionConstruct/.no-packagejson-validator +0 -0
  148. package/resources/cdk-apps/sam_cdk_integ_app/src/docker/DockerImageFunctionConstruct/Dockerfile +9 -0
  149. package/resources/cdk-apps/sam_cdk_integ_app/src/docker/DockerImageFunctionConstruct/app.js +22 -0
  150. package/resources/cdk-apps/sam_cdk_integ_app/src/docker/DockerImageFunctionConstruct/package.json +18 -0
  151. package/resources/cdk-apps/sam_cdk_integ_app/src/go/GoFunctionConstruct/go.mod +5 -0
  152. package/resources/cdk-apps/sam_cdk_integ_app/src/go/GoFunctionConstruct/go.sum +17 -0
  153. package/resources/cdk-apps/sam_cdk_integ_app/src/go/GoFunctionConstruct/main.go +17 -0
  154. package/resources/cdk-apps/sam_cdk_integ_app/src/nodejs/NodeJsFunctionConstruct/.no-packagejson-validator +0 -0
  155. package/resources/cdk-apps/sam_cdk_integ_app/src/nodejs/NodeJsFunctionConstruct/app.ts +16 -0
  156. package/resources/cdk-apps/sam_cdk_integ_app/src/nodejs/NodeJsFunctionConstruct/package-lock.json +12 -0
  157. package/resources/cdk-apps/sam_cdk_integ_app/src/nodejs/NodeJsFunctionConstruct/package.json +5 -0
  158. package/resources/cdk-apps/sam_cdk_integ_app/src/python/Function/app.py +15 -0
  159. package/resources/cdk-apps/sam_cdk_integ_app/src/python/Function/requirements.txt +1 -0
  160. package/resources/cdk-apps/sam_cdk_integ_app/src/python/Layer/layer_version_dependency.py +5 -0
  161. package/resources/cdk-apps/sam_cdk_integ_app/src/python/Layer/requirements.txt +1 -0
  162. package/resources/cdk-apps/sam_cdk_integ_app/src/rest-api-definition.yaml +12 -0
  163. package/resources/cdk-apps/simple-app/app.js +26 -0
  164. package/resources/cdk-apps/simple-app/cdk.json +7 -0
  165. package/resources/cli-regression-patches/v1.119.0/NOTES.md +5 -0
  166. package/resources/cli-regression-patches/v1.119.0/cli.integtest.js +659 -0
  167. package/resources/cli-regression-patches/v1.130.0/NOTES.md +12 -0
  168. package/resources/cli-regression-patches/v1.130.0/app/app.js +378 -0
  169. package/resources/cli-regression-patches/v1.130.0/bootstrapping.integtest.js +220 -0
  170. package/resources/cli-regression-patches/v1.44.0/NOTES.md +18 -0
  171. package/resources/cli-regression-patches/v1.44.0/bootstrapping.integtest.js +126 -0
  172. package/resources/cli-regression-patches/v1.44.0/test.sh +26 -0
  173. package/resources/cli-regression-patches/v1.61.1/NOTES.md +2 -0
  174. package/resources/cli-regression-patches/v1.61.1/skip-tests.txt +16 -0
  175. package/resources/cli-regression-patches/v1.62.0/NOTES.md +2 -0
  176. package/resources/cli-regression-patches/v1.62.0/aws-helpers.js +245 -0
  177. package/resources/cli-regression-patches/v1.63.0/NOTES.md +1 -0
  178. package/resources/cli-regression-patches/v1.63.0/skip-tests.txt +7 -0
  179. package/resources/cli-regression-patches/v1.64.0/NOTES.md +3 -0
  180. package/resources/cli-regression-patches/v1.64.0/cdk-helpers.js +325 -0
  181. package/resources/cli-regression-patches/v1.64.0/cli.integtest.js +599 -0
  182. package/resources/cli-regression-patches/v1.64.1/NOTES.md +3 -0
  183. package/resources/cli-regression-patches/v1.64.1/cdk-helpers.js +324 -0
  184. package/resources/cli-regression-patches/v1.64.1/cli.integtest.js +599 -0
  185. package/resources/cli-regression-patches/v1.67.0/NOTES.md +2 -0
  186. package/resources/cli-regression-patches/v1.67.0/cdk-helpers.js +331 -0
  187. package/resources/cli-regression-patches/v2.130.0/NOTES.md +1 -0
  188. package/resources/cli-regression-patches/v2.130.0/node_modules/@aws-cdk-testing/cli-integ/resources/cdk-apps/sam_cdk_integ_app/lib/nested-stack.js +19 -0
  189. package/resources/cli-regression-patches/v2.130.0/node_modules/@aws-cdk-testing/cli-integ/resources/cdk-apps/sam_cdk_integ_app/lib/test-stack.js +134 -0
  190. package/resources/cli-regression-patches/v2.130.0/skip-tests.txt +5 -0
  191. package/resources/cli-regression-patches/v2.132.0/NOTES.md +1 -0
  192. package/resources/cli-regression-patches/v2.132.0/skip-tests.txt +4 -0
  193. package/resources/cli-regression-patches/v2.142.0/NOTES.md +1 -0
  194. package/resources/cli-regression-patches/v2.142.0/skip-tests.txt +4 -0
  195. package/resources/cli-regression-patches/v2.160.0/skip-tests.txt +2 -0
  196. package/resources/cli-regression-patches/v2.161.0/NOTES.md +1 -0
  197. package/resources/cli-regression-patches/v2.161.0/skip-tests.txt +5 -0
  198. package/resources/cli-regression-patches/v2.166.0/NOTES.md +1 -0
  199. package/resources/cli-regression-patches/v2.166.0/skip-tests.txt +2 -0
  200. package/resources/cloud-assemblies/0.36.0/InitStack.template.json +1 -0
  201. package/resources/cloud-assemblies/0.36.0/cdk.out +1 -0
  202. package/resources/cloud-assemblies/0.36.0/manifest.json +19 -0
  203. package/resources/cloud-assemblies/1.10.0-lookup-default-vpc/InitStack.template.json +2 -0
  204. package/resources/cloud-assemblies/1.10.0-lookup-default-vpc/cdk.out +1 -0
  205. package/resources/cloud-assemblies/1.10.0-lookup-default-vpc/manifest.json.js +37 -0
  206. package/resources/cloud-assemblies/1.10.0-request-azs/InitStack.template.json +2 -0
  207. package/resources/cloud-assemblies/1.10.0-request-azs/cdk.out +1 -0
  208. package/resources/cloud-assemblies/1.10.0-request-azs/manifest.json.js +34 -0
  209. package/resources/integ.jest.config.js +25 -0
  210. package/resources/templates/sqs-template.json +36 -0
  211. package/skip-tests.txt +8 -0
  212. package/tests/cli-integ-tests/README.md +47 -0
  213. package/tests/cli-integ-tests/bootstrapping.integtest.d.ts +1 -0
  214. package/tests/cli-integ-tests/bootstrapping.integtest.js +412 -0
  215. package/tests/cli-integ-tests/bootstrapping.integtest.ts +493 -0
  216. package/tests/cli-integ-tests/cli-lib.integtest.d.ts +1 -0
  217. package/tests/cli-integ-tests/cli-lib.integtest.js +62 -0
  218. package/tests/cli-integ-tests/cli-lib.integtest.ts +90 -0
  219. package/tests/cli-integ-tests/cli.integtest.d.ts +1 -0
  220. package/tests/cli-integ-tests/cli.integtest.js +2104 -0
  221. package/tests/cli-integ-tests/cli.integtest.ts +2874 -0
  222. package/tests/cli-integ-tests/garbage-collection.integtest.d.ts +1 -0
  223. package/tests/cli-integ-tests/garbage-collection.integtest.js +314 -0
  224. package/tests/cli-integ-tests/garbage-collection.integtest.ts +392 -0
  225. package/tests/init-csharp/init-csharp.integtest.d.ts +1 -0
  226. package/tests/init-csharp/init-csharp.integtest.js +14 -0
  227. package/tests/init-csharp/init-csharp.integtest.ts +15 -0
  228. package/tests/init-fsharp/init-fsharp.integtest.d.ts +1 -0
  229. package/tests/init-fsharp/init-fsharp.integtest.js +14 -0
  230. package/tests/init-fsharp/init-fsharp.integtest.ts +15 -0
  231. package/tests/init-go/init-go.integtest.d.ts +1 -0
  232. package/tests/init-go/init-go.integtest.js +21 -0
  233. package/tests/init-go/init-go.integtest.ts +23 -0
  234. package/tests/init-java/init-java.integtest.d.ts +1 -0
  235. package/tests/init-java/init-java.integtest.js +14 -0
  236. package/tests/init-java/init-java.integtest.ts +14 -0
  237. package/tests/init-javascript/init-javascript.integtest.d.ts +1 -0
  238. package/tests/init-javascript/init-javascript.integtest.js +53 -0
  239. package/tests/init-javascript/init-javascript.integtest.ts +59 -0
  240. package/tests/init-python/init-python.integtest.d.ts +1 -0
  241. package/tests/init-python/init-python.integtest.js +19 -0
  242. package/tests/init-python/init-python.integtest.ts +20 -0
  243. package/tests/init-typescript-app/init-typescript-app.integtest.d.ts +1 -0
  244. package/tests/init-typescript-app/init-typescript-app.integtest.js +54 -0
  245. package/tests/init-typescript-app/init-typescript-app.integtest.ts +66 -0
  246. package/tests/init-typescript-lib/init-typescript-lib.integtest.d.ts +1 -0
  247. package/tests/init-typescript-lib/init-typescript-lib.integtest.js +13 -0
  248. package/tests/init-typescript-lib/init-typescript-lib.integtest.ts +13 -0
  249. package/tests/tool-integrations/amplify.integtest.d.ts +1 -0
  250. package/tests/tool-integrations/amplify.integtest.js +39 -0
  251. package/tests/tool-integrations/amplify.integtest.ts +43 -0
  252. package/tests/tool-integrations/with-tool-context.d.ts +9 -0
  253. package/tests/tool-integrations/with-tool-context.js +13 -0
  254. package/tests/tool-integrations/with-tool-context.ts +14 -0
  255. package/tests/uberpackage/uberpackage.integtest.d.ts +1 -0
  256. package/tests/uberpackage/uberpackage.integtest.js +11 -0
  257. package/tests/uberpackage/uberpackage.integtest.ts +11 -0
package/lib/aws.js ADDED
@@ -0,0 +1,206 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AwsClients = void 0;
4
+ exports.isStackMissingError = isStackMissingError;
5
+ exports.isBucketMissingError = isBucketMissingError;
6
+ exports.retry = retry;
7
+ exports.outputFromStack = outputFromStack;
8
+ exports.sleep = sleep;
9
+ const client_cloudformation_1 = require("@aws-sdk/client-cloudformation");
10
+ const client_ecr_1 = require("@aws-sdk/client-ecr");
11
+ const client_ecs_1 = require("@aws-sdk/client-ecs");
12
+ const client_iam_1 = require("@aws-sdk/client-iam");
13
+ const client_lambda_1 = require("@aws-sdk/client-lambda");
14
+ const client_s3_1 = require("@aws-sdk/client-s3");
15
+ const client_sns_1 = require("@aws-sdk/client-sns");
16
+ const client_sso_1 = require("@aws-sdk/client-sso");
17
+ const client_sts_1 = require("@aws-sdk/client-sts");
18
+ const credential_providers_1 = require("@aws-sdk/credential-providers");
19
+ const util_retry_1 = require("@smithy/util-retry");
20
+ class AwsClients {
21
+ static async default(output) {
22
+ var _a, _b;
23
+ const region = (_b = (_a = process.env.AWS_REGION) !== null && _a !== void 0 ? _a : process.env.AWS_DEFAULT_REGION) !== null && _b !== void 0 ? _b : 'us-east-1';
24
+ return AwsClients.forRegion(region, output);
25
+ }
26
+ static async forRegion(region, output) {
27
+ return new AwsClients(region, output);
28
+ }
29
+ constructor(region, output) {
30
+ this.region = region;
31
+ this.output = output;
32
+ this.config = {
33
+ credentials: chainableCredentials(this.region),
34
+ region: this.region,
35
+ retryStrategy: new util_retry_1.ConfiguredRetryStrategy(9, (attempt) => attempt ** 500),
36
+ };
37
+ this.cloudFormation = new client_cloudformation_1.CloudFormationClient(this.config);
38
+ this.s3 = new client_s3_1.S3Client(this.config);
39
+ this.ecr = new client_ecr_1.ECRClient(this.config);
40
+ this.ecs = new client_ecs_1.ECSClient(this.config);
41
+ this.sso = new client_sso_1.SSOClient(this.config);
42
+ this.sns = new client_sns_1.SNSClient(this.config);
43
+ this.iam = new client_iam_1.IAMClient(this.config);
44
+ this.lambda = new client_lambda_1.LambdaClient(this.config);
45
+ this.sts = new client_sts_1.STSClient(this.config);
46
+ }
47
+ async account() {
48
+ // Reduce # of retries, we use this as a circuit breaker for detecting no-config
49
+ const stsClient = new client_sts_1.STSClient({
50
+ credentials: this.config.credentials,
51
+ region: this.config.region,
52
+ maxAttempts: 2,
53
+ });
54
+ return (await stsClient.send(new client_sts_1.GetCallerIdentityCommand({}))).Account;
55
+ }
56
+ async deleteStacks(...stackNames) {
57
+ if (stackNames.length === 0) {
58
+ return;
59
+ }
60
+ // We purposely do all stacks serially, because they've been ordered
61
+ // to do the bootstrap stack last.
62
+ for (const stackName of stackNames) {
63
+ await this.cloudFormation.send(new client_cloudformation_1.UpdateTerminationProtectionCommand({
64
+ EnableTerminationProtection: false,
65
+ StackName: stackName,
66
+ }));
67
+ await this.cloudFormation.send(new client_cloudformation_1.DeleteStackCommand({
68
+ StackName: stackName,
69
+ }));
70
+ await retry(this.output, `Deleting ${stackName}`, retry.forSeconds(600), async () => {
71
+ const status = await this.stackStatus(stackName);
72
+ if (status !== undefined && status.endsWith('_FAILED')) {
73
+ throw retry.abort(new Error(`'${stackName}' is in state '${status}'`));
74
+ }
75
+ if (status !== undefined) {
76
+ throw new Error(`Delete of '${stackName}' not complete yet, status: '${status}'`);
77
+ }
78
+ });
79
+ }
80
+ }
81
+ async stackStatus(stackName) {
82
+ var _a;
83
+ try {
84
+ return (_a = (await this.cloudFormation.send(new client_cloudformation_1.DescribeStacksCommand({
85
+ StackName: stackName,
86
+ }))).Stacks) === null || _a === void 0 ? void 0 : _a[0].StackStatus;
87
+ }
88
+ catch (e) {
89
+ if (isStackMissingError(e)) {
90
+ return undefined;
91
+ }
92
+ throw e;
93
+ }
94
+ }
95
+ async emptyBucket(bucketName, options) {
96
+ const objects = await this.s3.send(new client_s3_1.ListObjectVersionsCommand({
97
+ Bucket: bucketName,
98
+ }));
99
+ const deletes = [...(objects.Versions || []), ...(objects.DeleteMarkers || [])].reduce((acc, obj) => {
100
+ if (typeof obj.VersionId !== 'undefined' && typeof obj.Key !== 'undefined') {
101
+ acc.push({ Key: obj.Key, VersionId: obj.VersionId });
102
+ }
103
+ else if (typeof obj.Key !== 'undefined') {
104
+ acc.push({ Key: obj.Key });
105
+ }
106
+ return acc;
107
+ }, []);
108
+ if (deletes.length === 0) {
109
+ return Promise.resolve();
110
+ }
111
+ return this.s3.send(new client_s3_1.DeleteObjectsCommand({
112
+ Bucket: bucketName,
113
+ Delete: {
114
+ Objects: deletes,
115
+ Quiet: false,
116
+ },
117
+ BypassGovernanceRetention: (options === null || options === void 0 ? void 0 : options.bypassGovernance) ? true : undefined,
118
+ }));
119
+ }
120
+ async deleteImageRepository(repositoryName) {
121
+ await this.ecr.send(new client_ecr_1.DeleteRepositoryCommand({
122
+ repositoryName: repositoryName,
123
+ force: true,
124
+ }));
125
+ }
126
+ async deleteBucket(bucketName) {
127
+ try {
128
+ await this.emptyBucket(bucketName);
129
+ await this.s3.send(new client_s3_1.DeleteBucketCommand({
130
+ Bucket: bucketName,
131
+ }));
132
+ }
133
+ catch (e) {
134
+ if (isBucketMissingError(e)) {
135
+ return;
136
+ }
137
+ throw e;
138
+ }
139
+ }
140
+ }
141
+ exports.AwsClients = AwsClients;
142
+ function isStackMissingError(e) {
143
+ return e.message.indexOf('does not exist') > -1;
144
+ }
145
+ function isBucketMissingError(e) {
146
+ return e.message.indexOf('does not exist') > -1;
147
+ }
148
+ /**
149
+ * Retry an async operation until a deadline is hit.
150
+ *
151
+ * Use `retry.forSeconds()` to construct a deadline relative to right now.
152
+ *
153
+ * Exceptions will cause the operation to retry. Use `retry.abort` to annotate an exception
154
+ * to stop the retry and end in a failure.
155
+ */
156
+ async function retry(output, operation, deadline, block) {
157
+ let i = 0;
158
+ output.write(`💈 ${operation}\n`);
159
+ while (true) {
160
+ try {
161
+ i++;
162
+ const ret = await block();
163
+ output.write(`💈 ${operation}: succeeded after ${i} attempts\n`);
164
+ return ret;
165
+ }
166
+ catch (e) {
167
+ if (e.abort || Date.now() > deadline.getTime()) {
168
+ throw new Error(`${operation}: did not succeed after ${i} attempts: ${e}`);
169
+ }
170
+ output.write(`⏳ ${operation} (${e.message})\n`);
171
+ await sleep(5000);
172
+ }
173
+ }
174
+ }
175
+ /**
176
+ * Make a deadline for the `retry` function relative to the current time.
177
+ */
178
+ retry.forSeconds = (seconds) => {
179
+ return new Date(Date.now() + seconds * 1000);
180
+ };
181
+ /**
182
+ * Annotate an error to stop the retrying
183
+ */
184
+ retry.abort = (e) => {
185
+ e.abort = true;
186
+ return e;
187
+ };
188
+ function outputFromStack(key, stack) {
189
+ var _a, _b;
190
+ return (_b = ((_a = stack.Outputs) !== null && _a !== void 0 ? _a : []).find((o) => o.OutputKey === key)) === null || _b === void 0 ? void 0 : _b.OutputValue;
191
+ }
192
+ async function sleep(ms) {
193
+ return new Promise((ok) => setTimeout(ok, ms));
194
+ }
195
+ function chainableCredentials(region) {
196
+ if (process.env.CODEBUILD_BUILD_ARN && process.env.AWS_PROFILE) {
197
+ // in codebuild we must assume the role that the cdk uses
198
+ // otherwise credentials will just be picked up by the normal sdk
199
+ // heuristics and expire after an hour.
200
+ return (0, credential_providers_1.fromIni)({
201
+ clientConfig: { region },
202
+ });
203
+ }
204
+ return undefined;
205
+ }
206
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXdzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiYXdzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQTRMQSxrREFFQztBQUVELG9EQUVDO0FBVUQsc0JBc0JDO0FBaUJELDBDQUVDO0FBRUQsc0JBRUM7QUF6UEQsMEVBTXdDO0FBQ3hDLG9EQUF5RTtBQUN6RSxvREFBZ0Q7QUFDaEQsb0RBQWdEO0FBQ2hELDBEQUFzRDtBQUN0RCxrREFNNEI7QUFDNUIsb0RBQWdEO0FBQ2hELG9EQUFnRDtBQUNoRCxvREFBMEU7QUFDMUUsd0VBQXdEO0FBRXhELG1EQUE2RDtBQU83RCxNQUFhLFVBQVU7SUFDZCxNQUFNLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxNQUE2Qjs7UUFDdkQsTUFBTSxNQUFNLEdBQUcsTUFBQSxNQUFBLE9BQU8sQ0FBQyxHQUFHLENBQUMsVUFBVSxtQ0FBSSxPQUFPLENBQUMsR0FBRyxDQUFDLGtCQUFrQixtQ0FBSSxXQUFXLENBQUM7UUFDdkYsT0FBTyxVQUFVLENBQUMsU0FBUyxDQUFDLE1BQU0sRUFBRSxNQUFNLENBQUMsQ0FBQztJQUM5QyxDQUFDO0lBRU0sTUFBTSxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsTUFBYyxFQUFFLE1BQTZCO1FBQ3pFLE9BQU8sSUFBSSxVQUFVLENBQUMsTUFBTSxFQUFFLE1BQU0sQ0FBQyxDQUFDO0lBQ3hDLENBQUM7SUFjRCxZQUE0QixNQUFjLEVBQW1CLE1BQTZCO1FBQTlELFdBQU0sR0FBTixNQUFNLENBQVE7UUFBbUIsV0FBTSxHQUFOLE1BQU0sQ0FBdUI7UUFDeEYsSUFBSSxDQUFDLE1BQU0sR0FBRztZQUNaLFdBQVcsRUFBRSxvQkFBb0IsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDO1lBQzlDLE1BQU0sRUFBRSxJQUFJLENBQUMsTUFBTTtZQUNuQixhQUFhLEVBQUUsSUFBSSxvQ0FBdUIsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxPQUFlLEVBQUUsRUFBRSxDQUFDLE9BQU8sSUFBSSxH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UUFDakUsdUNBQXVDO1FBQ3ZDLE9BQU8sSUFBQSw4QkFBTyxFQUFDO1lBQ2IsWUFBWSxFQUFFLEVBQUUsTUFBTSxFQUFFO1NBQ3pCLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRCxPQUFPLFNBQVMsQ0FBQztBQUNuQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQ2xvdWRGb3JtYXRpb25DbGllbnQsXG4gIERlbGV0ZVN0YWNrQ29tbWFuZCxcbiAgRGVzY3JpYmVTdGFja3NDb21tYW5kLFxuICBVcGRhdGVUZXJtaW5hdGlvblByb3RlY3Rpb25Db21tYW5kLFxuICB0eXBlIFN0YWNrLFxufSBmcm9tICdAYXdzLXNkay9jbGllbnQtY2xvdWRmb3JtYXRpb24nO1xuaW1wb3J0IHsgRGVsZXRlUmVwb3NpdG9yeUNvbW1hbmQsIEVDUkNsaWVudCB9IGZyb20gJ0Bhd3Mtc2RrL2NsaWVudC1lY3InO1xuaW1wb3J0IHsgRUNTQ2xpZW50IH0gZnJvbSAnQGF3cy1zZGsvY2xpZW50LWVjcyc7XG5pbXBvcnQgeyBJQU1DbGllbnQgfSBmcm9tICdAYXdzLXNkay9jbGllbnQtaWFtJztcbmltcG9ydCB7IExhbWJkYUNsaWVudCB9IGZyb20gJ0Bhd3Mtc2RrL2NsaWVudC1sYW1iZGEnO1xuaW1wb3J0IHtcbiAgUzNDbGllbnQsXG4gIERlbGV0ZU9iamVjdHNDb21tYW5kLFxuICBMaXN0T2JqZWN0VmVyc2lvbnNDb21tYW5kLFxuICB0eXBlIE9iamVjdElkZW50aWZpZXIsXG4gIERlbGV0ZUJ1Y2tldENvbW1hbmQsXG59IGZyb20gJ0Bhd3Mtc2RrL2NsaWVudC1zMyc7XG5pbXBvcnQgeyBTTlNDbGllbnQgfSBmcm9tICdAYXdzLXNkay9jbGllbnQtc25zJztcbmltcG9ydCB7IFNTT0NsaWVudCB9IGZyb20gJ0Bhd3Mtc2RrL2NsaWVudC1zc28nO1xuaW1wb3J0IHsgU1RTQ2xpZW50LCBHZXRDYWxsZXJJZGVudGl0eUNvbW1hbmQgfSBmcm9tICdAYXdzLXNkay9jbGllbnQtc3RzJztcbmltcG9ydCB7IGZyb21JbmkgfSBmcm9tICdAYXdzLXNkay9jcmVkZW50aWFsLXByb3ZpZGVycyc7XG5pbXBvcnQgdHlwZSB7IEF3c0NyZWRlbnRpYWxJZGVudGl0eVByb3ZpZGVyIH0gZnJvbSAnQHNtaXRoeS90eXBlcyc7XG5pbXBvcnQgeyBDb25maWd1cmVkUmV0cnlTdHJhdGVneSB9IGZyb20gJ0BzbWl0aHkvdXRpbC1yZXRyeSc7XG5pbnRlcmZhY2UgQ2xpZW50Q29uZmlnIHtcbiAgcmVhZG9ubHkgY3JlZGVudGlhbHM/OiBBd3NDcmVkZW50aWFsSWRlbnRpdHlQcm92aWRlcjtcbiAgcmVhZG9ubHkgcmVnaW9uOiBzdHJpbmc7XG4gIHJlYWRvbmx5IHJldHJ5U3RyYXRlZ3k6IENvbmZpZ3VyZWRSZXRyeVN0cmF0ZWd5O1xufVxuXG5leHBvcnQgY2xhc3MgQXdzQ2xpZW50cyB7XG4gIHB1YmxpYyBzdGF0aWMgYXN5bmMgZGVmYXVsdChvdXRwdXQ6IE5vZGVKUy5Xcml0YWJsZVN0cmVhbSkge1xuICAgIGNvbnN0IHJlZ2lvbiA9IHByb2Nlc3MuZW52LkFXU19SRUdJT04gPz8gcHJvY2Vzcy5lbnYuQVdTX0RFRkFVTFRfUkVHSU9OID8/ICd1cy1lYXN0LTEnO1xuICAgIHJldHVybiBBd3NDbGllbnRzLmZvclJlZ2lvbihyZWdpb24sIG91dHB1dCk7XG4gIH1cblxuICBwdWJsaWMgc3RhdGljIGFzeW5jIGZvclJlZ2lvbihyZWdpb246IHN0cmluZywgb3V0cHV0OiBOb2RlSlMuV3JpdGFibGVTdHJlYW0pIHtcbiAgICByZXR1cm4gbmV3IEF3c0NsaWVudHMocmVnaW9uLCBvdXRwdXQpO1xuICB9XG5cbiAgcHJpdmF0ZSByZWFkb25seSBjb25maWc6IENsaWVudENvbmZpZztcblxuICBwdWJsaWMgcmVhZG9ubHkgY2xvdWRGb3JtYXRpb246IENsb3VkRm9ybWF0aW9uQ2xpZW50O1xuICBwdWJsaWMgcmVhZG9ubHkgczM6IFMzQ2xpZW50O1xuICBwdWJsaWMgcmVhZG9ubHkgZWNyOiBFQ1JDbGllbnQ7XG4gIHB1YmxpYyByZWFkb25seSBlY3M6IEVDU0NsaWVudDtcbiAgcHVibGljIHJlYWRvbmx5IHNzbzogU1NPQ2xpZW50O1xuICBwdWJsaWMgcmVhZG9ubHkgc25zOiBTTlNDbGllbnQ7XG4gIHB1YmxpYyByZWFkb25seSBpYW06IElBTUNsaWVudDtcbiAgcHVibGljIHJlYWRvbmx5IGxhbWJkYTogTGFtYmRhQ2xpZW50O1xuICBwdWJsaWMgcmVhZG9ubHkgc3RzOiBTVFNDbGllbnQ7XG5cbiAgY29uc3RydWN0b3IocHVibGljIHJlYWRvbmx5IHJlZ2lvbjogc3RyaW5nLCBwcml2YXRlIHJlYWRvbmx5IG91dHB1dDogTm9kZUpTLldyaXRhYmxlU3RyZWFtKSB7XG4gICAgdGhpcy5jb25maWcgPSB7XG4gICAgICBjcmVkZW50aWFsczogY2hhaW5hYmxlQ3JlZGVudGlhbHModGhpcy5yZWdpb24pLFxuICAgICAgcmVnaW9uOiB0aGlzLnJlZ2lvbixcbiAgICAgIHJldHJ5U3RyYXRlZ3k6IG5ldyBDb25maWd1cmVkUmV0cnlTdHJhdGVneSg5LCAoYXR0ZW1wdDogbnVtYmVyKSA9PiBhdHRlbXB0ICoqIDUwMCksXG4gICAgfTtcbiAgICB0aGlzLmNsb3VkRm9ybWF0aW9uID0gbmV3IENsb3VkRm9ybWF0aW9uQ2xpZW50KHRoaXMuY29uZmlnKTtcbiAgICB0aGlzLnMzID0gbmV3IFMzQ2xpZW50KHRoaXMuY29uZmlnKTtcbiAgICB0aGlzLmVjciA9IG5ldyBFQ1JDbGllbnQodGhpcy5jb25maWcpO1xuICAgIHRoaXMuZWNzID0gbmV3IEVDU0NsaWVudCh0aGlzLmNvbmZpZyk7XG4gICAgdGhpcy5zc28gPSBuZXcgU1NPQ2xpZW50KHRoaXMuY29uZmlnKTtcbiAgICB0aGlzLnNucyA9IG5ldyBTTlNDbGllbnQodGhpcy5jb25maWcpO1xuICAgIHRoaXMuaWFtID0gbmV3IElBTUNsaWVudCh0aGlzLmNvbmZpZyk7XG4gICAgdGhpcy5sYW1iZGEgPSBuZXcgTGFtYmRhQ2xpZW50KHRoaXMuY29uZmlnKTtcbiAgICB0aGlzLnN0cyA9IG5ldyBTVFNDbGllbnQodGhpcy5jb25maWcpO1xuICB9XG5cbiAgcHVibGljIGFzeW5jIGFjY291bnQoKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICAvLyBSZWR1Y2UgIyBvZiByZXRyaWVzLCB3ZSB1c2UgdGhpcyBhcyBhIGNpcmN1aXQgYnJlYWtlciBmb3IgZGV0ZWN0aW5nIG5vLWNvbmZpZ1xuICAgIGNvbnN0IHN0c0NsaWVudCA9IG5ldyBTVFNDbGllbnQoe1xuICAgICAgY3JlZGVudGlhbHM6IHRoaXMuY29uZmlnLmNyZWRlbnRpYWxzLFxuICAgICAgcmVnaW9uOiB0aGlzLmNvbmZpZy5yZWdpb24sXG4gICAgICBtYXhBdHRlbXB0czogMixcbiAgICB9KTtcblxuICAgIHJldHVybiAoYXdhaXQgc3RzQ2xpZW50LnNlbmQobmV3IEdldENhbGxlcklkZW50aXR5Q29tbWFuZCh7fSkpKS5BY2NvdW50ITtcbiAgfVxuXG4gIHB1YmxpYyBhc3luYyBkZWxldGVTdGFja3MoLi4uc3RhY2tOYW1lczogc3RyaW5nW10pIHtcbiAgICBpZiAoc3RhY2tOYW1lcy5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBXZSBwdXJwb3NlbHkgZG8gYWxsIHN0YWNrcyBzZXJpYWxseSwgYmVjYXVzZSB0aGV5J3ZlIGJlZW4gb3JkZXJlZFxuICAgIC8vIHRvIGRvIHRoZSBib290c3RyYXAgc3RhY2sgbGFzdC5cbiAgICBmb3IgKGNvbnN0IHN0YWNrTmFtZSBvZiBzdGFja05hbWVzKSB7XG4gICAgICBhd2FpdCB0aGlzLmNsb3VkRm9ybWF0aW9uLnNlbmQoXG4gICAgICAgIG5ldyBVcGRhdGVUZXJtaW5hdGlvblByb3RlY3Rpb25Db21tYW5kKHtcbiAgICAgICAgICBFbmFibGVUZXJtaW5hdGlvblByb3RlY3Rpb246IGZhbHNlLFxuICAgICAgICAgIFN0YWNrTmFtZTogc3RhY2tOYW1lLFxuICAgICAgICB9KSxcbiAgICAgICk7XG4gICAgICBhd2FpdCB0aGlzLmNsb3VkRm9ybWF0aW9uLnNlbmQoXG4gICAgICAgIG5ldyBEZWxldGVTdGFja0NvbW1hbmQoe1xuICAgICAgICAgIFN0YWNrTmFtZTogc3RhY2tOYW1lLFxuICAgICAgICB9KSxcbiAgICAgICk7XG5cbiAgICAgIGF3YWl0IHJldHJ5KHRoaXMub3V0cHV0LCBgRGVsZXRpbmcgJHtzdGFja05hbWV9YCwgcmV0cnkuZm9yU2Vjb25kcyg2MDApLCBhc3luYyAoKSA9PiB7XG4gICAgICAgIGNvbnN0IHN0YXR1cyA9IGF3YWl0IHRoaXMuc3RhY2tTdGF0dXMoc3RhY2tOYW1lKTtcbiAgICAgICAgaWYgKHN0YXR1cyAhPT0gdW5kZWZpbmVkICYmIHN0YXR1cy5lbmRzV2l0aCgnX0ZBSUxFRCcpKSB7XG4gICAgICAgICAgdGhyb3cgcmV0cnkuYWJvcnQobmV3IEVycm9yKGAnJHtzdGFja05hbWV9JyBpcyBpbiBzdGF0ZSAnJHtzdGF0dXN9J2ApKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoc3RhdHVzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYERlbGV0ZSBvZiAnJHtzdGFja05hbWV9JyBub3QgY29tcGxldGUgeWV0LCBzdGF0dXM6ICcke3N0YXR1c30nYCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBhc3luYyBzdGFja1N0YXR1cyhzdGFja05hbWU6IHN0cmluZyk6IFByb21pc2U8c3RyaW5nIHwgdW5kZWZpbmVkPiB7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiAoXG4gICAgICAgIGF3YWl0IHRoaXMuY2xvdWRGb3JtYXRpb24uc2VuZChcbiAgICAgICAgICBuZXcgRGVzY3JpYmVTdGFja3NDb21tYW5kKHtcbiAgICAgICAgICAgIFN0YWNrTmFtZTogc3RhY2tOYW1lLFxuICAgICAgICAgIH0pLFxuICAgICAgICApXG4gICAgICApLlN0YWNrcz8uWzBdLlN0YWNrU3RhdHVzO1xuICAgIH0gY2F0Y2ggKGU6IGFueSkge1xuICAgICAgaWYgKGlzU3RhY2tNaXNzaW5nRXJyb3IoZSkpIHtcbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgIH1cbiAgICAgIHRocm93IGU7XG4gICAgfVxuICB9XG5cbiAgcHVibGljIGFzeW5jIGVtcHR5QnVja2V0KGJ1Y2tldE5hbWU6IHN0cmluZywgb3B0aW9ucz86IHsgYnlwYXNzR292ZXJuYW5jZT86IGJvb2xlYW4gfSkge1xuICAgIGNvbnN0IG9iamVjdHMgPSBhd2FpdCB0aGlzLnMzLnNlbmQoXG4gICAgICBuZXcgTGlzdE9iamVjdFZlcnNpb25zQ29tbWFuZCh7XG4gICAgICAgIEJ1Y2tldDogYnVja2V0TmFtZSxcbiAgICAgIH0pLFxuICAgICk7XG5cbiAgICBjb25zdCBkZWxldGVzID0gWy4uLihvYmplY3RzLlZlcnNpb25zIHx8IFtdKSwgLi4uKG9iamVjdHMuRGVsZXRlTWFya2VycyB8fCBbXSldLnJlZHVjZSgoYWNjLCBvYmopID0+IHtcbiAgICAgIGlmICh0eXBlb2Ygb2JqLlZlcnNpb25JZCAhPT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mIG9iai5LZXkgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIGFjYy5wdXNoKHsgS2V5OiBvYmouS2V5LCBWZXJzaW9uSWQ6IG9iai5WZXJzaW9uSWQgfSk7XG4gICAgICB9IGVsc2UgaWYgKHR5cGVvZiBvYmouS2V5ICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICBhY2MucHVzaCh7IEtleTogb2JqLktleSB9KTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBhY2M7XG4gICAgfSwgW10gYXMgT2JqZWN0SWRlbnRpZmllcltdKTtcblxuICAgIGlmIChkZWxldGVzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLnMzLnNlbmQoXG4gICAgICBuZXcgRGVsZXRlT2JqZWN0c0NvbW1hbmQoe1xuICAgICAgICBCdWNrZXQ6IGJ1Y2tldE5hbWUsXG4gICAgICAgIERlbGV0ZToge1xuICAgICAgICAgIE9iamVjdHM6IGRlbGV0ZXMsXG4gICAgICAgICAgUXVpZXQ6IGZhbHNlLFxuICAgICAgICB9LFxuICAgICAgICBCeXBhc3NHb3Zlcm5hbmNlUmV0ZW50aW9uOiBvcHRpb25zPy5ieXBhc3NHb3Zlcm5hbmNlID8gdHJ1ZSA6IHVuZGVmaW5lZCxcbiAgICAgIH0pLFxuICAgICk7XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgZGVsZXRlSW1hZ2VSZXBvc2l0b3J5KHJlcG9zaXRvcnlOYW1lOiBzdHJpbmcpIHtcbiAgICBhd2FpdCB0aGlzLmVjci5zZW5kKFxuICAgICAgbmV3IERlbGV0ZVJlcG9zaXRvcnlDb21tYW5kKHtcbiAgICAgICAgcmVwb3NpdG9yeU5hbWU6IHJlcG9zaXRvcnlOYW1lLFxuICAgICAgICBmb3JjZTogdHJ1ZSxcbiAgICAgIH0pLFxuICAgICk7XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgZGVsZXRlQnVja2V0KGJ1Y2tldE5hbWU6IHN0cmluZykge1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLmVtcHR5QnVja2V0KGJ1Y2tldE5hbWUpO1xuXG4gICAgICBhd2FpdCB0aGlzLnMzLnNlbmQoXG4gICAgICAgIG5ldyBEZWxldGVCdWNrZXRDb21tYW5kKHtcbiAgICAgICAgICBCdWNrZXQ6IGJ1Y2tldE5hbWUsXG4gICAgICAgIH0pLFxuICAgICAgKTtcbiAgICB9IGNhdGNoIChlOiBhbnkpIHtcbiAgICAgIGlmIChpc0J1Y2tldE1pc3NpbmdFcnJvcihlKSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICB0aHJvdyBlO1xuICAgIH1cbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNTdGFja01pc3NpbmdFcnJvcihlOiBFcnJvcikge1xuICByZXR1cm4gZS5tZXNzYWdlLmluZGV4T2YoJ2RvZXMgbm90IGV4aXN0JykgPiAtMTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzQnVja2V0TWlzc2luZ0Vycm9yKGU6IEVycm9yKSB7XG4gIHJldHVybiBlLm1lc3NhZ2UuaW5kZXhPZignZG9lcyBub3QgZXhpc3QnKSA+IC0xO1xufVxuXG4vKipcbiAqIFJldHJ5IGFuIGFzeW5jIG9wZXJhdGlvbiB1bnRpbCBhIGRlYWRsaW5lIGlzIGhpdC5cbiAqXG4gKiBVc2UgYHJldHJ5LmZvclNlY29uZHMoKWAgdG8gY29uc3RydWN0IGEgZGVhZGxpbmUgcmVsYXRpdmUgdG8gcmlnaHQgbm93LlxuICpcbiAqIEV4Y2VwdGlvbnMgd2lsbCBjYXVzZSB0aGUgb3BlcmF0aW9uIHRvIHJldHJ5LiBVc2UgYHJldHJ5LmFib3J0YCB0byBhbm5vdGF0ZSBhbiBleGNlcHRpb25cbiAqIHRvIHN0b3AgdGhlIHJldHJ5IGFuZCBlbmQgaW4gYSBmYWlsdXJlLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmV0cnk8QT4oXG4gIG91dHB1dDogTm9kZUpTLldyaXRhYmxlU3RyZWFtLFxuICBvcGVyYXRpb246IHN0cmluZyxcbiAgZGVhZGxpbmU6IERhdGUsXG4gIGJsb2NrOiAoKSA9PiBQcm9taXNlPEE+LFxuKTogUHJvbWlzZTxBPiB7XG4gIGxldCBpID0gMDtcbiAgb3V0cHV0LndyaXRlKGDwn5KIICR7b3BlcmF0aW9ufVxcbmApO1xuICB3aGlsZSAodHJ1ZSkge1xuICAgIHRyeSB7XG4gICAgICBpKys7XG4gICAgICBjb25zdCByZXQgPSBhd2FpdCBibG9jaygpO1xuICAgICAgb3V0cHV0LndyaXRlKGDwn5KIICR7b3BlcmF0aW9ufTogc3VjY2VlZGVkIGFmdGVyICR7aX0gYXR0ZW1wdHNcXG5gKTtcbiAgICAgIHJldHVybiByZXQ7XG4gICAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgICBpZiAoZS5hYm9ydCB8fCBEYXRlLm5vdygpID4gZGVhZGxpbmUuZ2V0VGltZSgpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgJHtvcGVyYXRpb259OiBkaWQgbm90IHN1Y2NlZWQgYWZ0ZXIgJHtpfSBhdHRlbXB0czogJHtlfWApO1xuICAgICAgfVxuICAgICAgb3V0cHV0LndyaXRlKGDij7MgJHtvcGVyYXRpb259ICgke2UubWVzc2FnZX0pXFxuYCk7XG4gICAgICBhd2FpdCBzbGVlcCg1MDAwKTtcbiAgICB9XG4gIH1cbn1cblxuLyoqXG4gKiBNYWtlIGEgZGVhZGxpbmUgZm9yIHRoZSBgcmV0cnlgIGZ1bmN0aW9uIHJlbGF0aXZlIHRvIHRoZSBjdXJyZW50IHRpbWUuXG4gKi9cbnJldHJ5LmZvclNlY29uZHMgPSAoc2Vjb25kczogbnVtYmVyKTogRGF0ZSA9PiB7XG4gIHJldHVybiBuZXcgRGF0ZShEYXRlLm5vdygpICsgc2Vjb25kcyAqIDEwMDApO1xufTtcblxuLyoqXG4gKiBBbm5vdGF0ZSBhbiBlcnJvciB0byBzdG9wIHRoZSByZXRyeWluZ1xuICovXG5yZXRyeS5hYm9ydCA9IChlOiBFcnJvcik6IEVycm9yID0+IHtcbiAgKGUgYXMgYW55KS5hYm9ydCA9IHRydWU7XG4gIHJldHVybiBlO1xufTtcblxuZXhwb3J0IGZ1bmN0aW9uIG91dHB1dEZyb21TdGFjayhrZXk6IHN0cmluZywgc3RhY2s6IFN0YWNrKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgcmV0dXJuIChzdGFjay5PdXRwdXRzID8/IFtdKS5maW5kKChvKSA9PiBvLk91dHB1dEtleSA9PT0ga2V5KT8uT3V0cHV0VmFsdWU7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzbGVlcChtczogbnVtYmVyKSB7XG4gIHJldHVybiBuZXcgUHJvbWlzZSgob2spID0+IHNldFRpbWVvdXQob2ssIG1zKSk7XG59XG5cbmZ1bmN0aW9uIGNoYWluYWJsZUNyZWRlbnRpYWxzKHJlZ2lvbjogc3RyaW5nKTogQXdzQ3JlZGVudGlhbElkZW50aXR5UHJvdmlkZXIgfCB1bmRlZmluZWQge1xuICBpZiAocHJvY2Vzcy5lbnYuQ09ERUJVSUxEX0JVSUxEX0FSTiAmJiBwcm9jZXNzLmVudi5BV1NfUFJPRklMRSkge1xuICAgIC8vIGluIGNvZGVidWlsZCB3ZSBtdXN0IGFzc3VtZSB0aGUgcm9sZSB0aGF0IHRoZSBjZGsgdXNlc1xuICAgIC8vIG90aGVyd2lzZSBjcmVkZW50aWFscyB3aWxsIGp1c3QgYmUgcGlja2VkIHVwIGJ5IHRoZSBub3JtYWwgc2RrXG4gICAgLy8gaGV1cmlzdGljcyBhbmQgZXhwaXJlIGFmdGVyIGFuIGhvdXIuXG4gICAgcmV0dXJuIGZyb21Jbmkoe1xuICAgICAgY2xpZW50Q29uZmlnOiB7IHJlZ2lvbiB9LFxuICAgIH0pO1xuICB9XG5cbiAgcmV0dXJuIHVuZGVmaW5lZDtcbn1cbiJdfQ==
package/lib/aws.ts ADDED
@@ -0,0 +1,263 @@
1
+ import {
2
+ CloudFormationClient,
3
+ DeleteStackCommand,
4
+ DescribeStacksCommand,
5
+ UpdateTerminationProtectionCommand,
6
+ type Stack,
7
+ } from '@aws-sdk/client-cloudformation';
8
+ import { DeleteRepositoryCommand, ECRClient } from '@aws-sdk/client-ecr';
9
+ import { ECSClient } from '@aws-sdk/client-ecs';
10
+ import { IAMClient } from '@aws-sdk/client-iam';
11
+ import { LambdaClient } from '@aws-sdk/client-lambda';
12
+ import {
13
+ S3Client,
14
+ DeleteObjectsCommand,
15
+ ListObjectVersionsCommand,
16
+ type ObjectIdentifier,
17
+ DeleteBucketCommand,
18
+ } from '@aws-sdk/client-s3';
19
+ import { SNSClient } from '@aws-sdk/client-sns';
20
+ import { SSOClient } from '@aws-sdk/client-sso';
21
+ import { STSClient, GetCallerIdentityCommand } from '@aws-sdk/client-sts';
22
+ import { fromIni } from '@aws-sdk/credential-providers';
23
+ import type { AwsCredentialIdentityProvider } from '@smithy/types';
24
+ import { ConfiguredRetryStrategy } from '@smithy/util-retry';
25
+ interface ClientConfig {
26
+ readonly credentials?: AwsCredentialIdentityProvider;
27
+ readonly region: string;
28
+ readonly retryStrategy: ConfiguredRetryStrategy;
29
+ }
30
+
31
+ export class AwsClients {
32
+ public static async default(output: NodeJS.WritableStream) {
33
+ const region = process.env.AWS_REGION ?? process.env.AWS_DEFAULT_REGION ?? 'us-east-1';
34
+ return AwsClients.forRegion(region, output);
35
+ }
36
+
37
+ public static async forRegion(region: string, output: NodeJS.WritableStream) {
38
+ return new AwsClients(region, output);
39
+ }
40
+
41
+ private readonly config: ClientConfig;
42
+
43
+ public readonly cloudFormation: CloudFormationClient;
44
+ public readonly s3: S3Client;
45
+ public readonly ecr: ECRClient;
46
+ public readonly ecs: ECSClient;
47
+ public readonly sso: SSOClient;
48
+ public readonly sns: SNSClient;
49
+ public readonly iam: IAMClient;
50
+ public readonly lambda: LambdaClient;
51
+ public readonly sts: STSClient;
52
+
53
+ constructor(public readonly region: string, private readonly output: NodeJS.WritableStream) {
54
+ this.config = {
55
+ credentials: chainableCredentials(this.region),
56
+ region: this.region,
57
+ retryStrategy: new ConfiguredRetryStrategy(9, (attempt: number) => attempt ** 500),
58
+ };
59
+ this.cloudFormation = new CloudFormationClient(this.config);
60
+ this.s3 = new S3Client(this.config);
61
+ this.ecr = new ECRClient(this.config);
62
+ this.ecs = new ECSClient(this.config);
63
+ this.sso = new SSOClient(this.config);
64
+ this.sns = new SNSClient(this.config);
65
+ this.iam = new IAMClient(this.config);
66
+ this.lambda = new LambdaClient(this.config);
67
+ this.sts = new STSClient(this.config);
68
+ }
69
+
70
+ public async account(): Promise<string> {
71
+ // Reduce # of retries, we use this as a circuit breaker for detecting no-config
72
+ const stsClient = new STSClient({
73
+ credentials: this.config.credentials,
74
+ region: this.config.region,
75
+ maxAttempts: 2,
76
+ });
77
+
78
+ return (await stsClient.send(new GetCallerIdentityCommand({}))).Account!;
79
+ }
80
+
81
+ public async deleteStacks(...stackNames: string[]) {
82
+ if (stackNames.length === 0) {
83
+ return;
84
+ }
85
+
86
+ // We purposely do all stacks serially, because they've been ordered
87
+ // to do the bootstrap stack last.
88
+ for (const stackName of stackNames) {
89
+ await this.cloudFormation.send(
90
+ new UpdateTerminationProtectionCommand({
91
+ EnableTerminationProtection: false,
92
+ StackName: stackName,
93
+ }),
94
+ );
95
+ await this.cloudFormation.send(
96
+ new DeleteStackCommand({
97
+ StackName: stackName,
98
+ }),
99
+ );
100
+
101
+ await retry(this.output, `Deleting ${stackName}`, retry.forSeconds(600), async () => {
102
+ const status = await this.stackStatus(stackName);
103
+ if (status !== undefined && status.endsWith('_FAILED')) {
104
+ throw retry.abort(new Error(`'${stackName}' is in state '${status}'`));
105
+ }
106
+ if (status !== undefined) {
107
+ throw new Error(`Delete of '${stackName}' not complete yet, status: '${status}'`);
108
+ }
109
+ });
110
+ }
111
+ }
112
+
113
+ public async stackStatus(stackName: string): Promise<string | undefined> {
114
+ try {
115
+ return (
116
+ await this.cloudFormation.send(
117
+ new DescribeStacksCommand({
118
+ StackName: stackName,
119
+ }),
120
+ )
121
+ ).Stacks?.[0].StackStatus;
122
+ } catch (e: any) {
123
+ if (isStackMissingError(e)) {
124
+ return undefined;
125
+ }
126
+ throw e;
127
+ }
128
+ }
129
+
130
+ public async emptyBucket(bucketName: string, options?: { bypassGovernance?: boolean }) {
131
+ const objects = await this.s3.send(
132
+ new ListObjectVersionsCommand({
133
+ Bucket: bucketName,
134
+ }),
135
+ );
136
+
137
+ const deletes = [...(objects.Versions || []), ...(objects.DeleteMarkers || [])].reduce((acc, obj) => {
138
+ if (typeof obj.VersionId !== 'undefined' && typeof obj.Key !== 'undefined') {
139
+ acc.push({ Key: obj.Key, VersionId: obj.VersionId });
140
+ } else if (typeof obj.Key !== 'undefined') {
141
+ acc.push({ Key: obj.Key });
142
+ }
143
+ return acc;
144
+ }, [] as ObjectIdentifier[]);
145
+
146
+ if (deletes.length === 0) {
147
+ return Promise.resolve();
148
+ }
149
+
150
+ return this.s3.send(
151
+ new DeleteObjectsCommand({
152
+ Bucket: bucketName,
153
+ Delete: {
154
+ Objects: deletes,
155
+ Quiet: false,
156
+ },
157
+ BypassGovernanceRetention: options?.bypassGovernance ? true : undefined,
158
+ }),
159
+ );
160
+ }
161
+
162
+ public async deleteImageRepository(repositoryName: string) {
163
+ await this.ecr.send(
164
+ new DeleteRepositoryCommand({
165
+ repositoryName: repositoryName,
166
+ force: true,
167
+ }),
168
+ );
169
+ }
170
+
171
+ public async deleteBucket(bucketName: string) {
172
+ try {
173
+ await this.emptyBucket(bucketName);
174
+
175
+ await this.s3.send(
176
+ new DeleteBucketCommand({
177
+ Bucket: bucketName,
178
+ }),
179
+ );
180
+ } catch (e: any) {
181
+ if (isBucketMissingError(e)) {
182
+ return;
183
+ }
184
+ throw e;
185
+ }
186
+ }
187
+ }
188
+
189
+ export function isStackMissingError(e: Error) {
190
+ return e.message.indexOf('does not exist') > -1;
191
+ }
192
+
193
+ export function isBucketMissingError(e: Error) {
194
+ return e.message.indexOf('does not exist') > -1;
195
+ }
196
+
197
+ /**
198
+ * Retry an async operation until a deadline is hit.
199
+ *
200
+ * Use `retry.forSeconds()` to construct a deadline relative to right now.
201
+ *
202
+ * Exceptions will cause the operation to retry. Use `retry.abort` to annotate an exception
203
+ * to stop the retry and end in a failure.
204
+ */
205
+ export async function retry<A>(
206
+ output: NodeJS.WritableStream,
207
+ operation: string,
208
+ deadline: Date,
209
+ block: () => Promise<A>,
210
+ ): Promise<A> {
211
+ let i = 0;
212
+ output.write(`💈 ${operation}\n`);
213
+ while (true) {
214
+ try {
215
+ i++;
216
+ const ret = await block();
217
+ output.write(`💈 ${operation}: succeeded after ${i} attempts\n`);
218
+ return ret;
219
+ } catch (e: any) {
220
+ if (e.abort || Date.now() > deadline.getTime()) {
221
+ throw new Error(`${operation}: did not succeed after ${i} attempts: ${e}`);
222
+ }
223
+ output.write(`⏳ ${operation} (${e.message})\n`);
224
+ await sleep(5000);
225
+ }
226
+ }
227
+ }
228
+
229
+ /**
230
+ * Make a deadline for the `retry` function relative to the current time.
231
+ */
232
+ retry.forSeconds = (seconds: number): Date => {
233
+ return new Date(Date.now() + seconds * 1000);
234
+ };
235
+
236
+ /**
237
+ * Annotate an error to stop the retrying
238
+ */
239
+ retry.abort = (e: Error): Error => {
240
+ (e as any).abort = true;
241
+ return e;
242
+ };
243
+
244
+ export function outputFromStack(key: string, stack: Stack): string | undefined {
245
+ return (stack.Outputs ?? []).find((o) => o.OutputKey === key)?.OutputValue;
246
+ }
247
+
248
+ export async function sleep(ms: number) {
249
+ return new Promise((ok) => setTimeout(ok, ms));
250
+ }
251
+
252
+ function chainableCredentials(region: string): AwsCredentialIdentityProvider | undefined {
253
+ if (process.env.CODEBUILD_BUILD_ARN && process.env.AWS_PROFILE) {
254
+ // in codebuild we must assume the role that the cdk uses
255
+ // otherwise credentials will just be picked up by the normal sdk
256
+ // heuristics and expire after an hour.
257
+ return fromIni({
258
+ clientConfig: { region },
259
+ });
260
+ }
261
+
262
+ return undefined;
263
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Routines for corking stdout and stderr
3
+ */
4
+ import * as stream from 'stream';
5
+ export declare class MemoryStream extends stream.Writable {
6
+ private parts;
7
+ _write(chunk: Buffer, _encoding: string, callback: (error?: Error | null) => void): void;
8
+ buffer(): Buffer;
9
+ clear(): void;
10
+ flushTo(strm: NodeJS.WritableStream): Promise<void>;
11
+ toString(): string;
12
+ }
package/lib/corking.js ADDED
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MemoryStream = void 0;
4
+ /**
5
+ * Routines for corking stdout and stderr
6
+ */
7
+ const stream = require("stream");
8
+ class MemoryStream extends stream.Writable {
9
+ constructor() {
10
+ super(...arguments);
11
+ this.parts = new Array();
12
+ }
13
+ _write(chunk, _encoding, callback) {
14
+ this.parts.push(chunk);
15
+ callback();
16
+ }
17
+ buffer() {
18
+ return Buffer.concat(this.parts);
19
+ }
20
+ clear() {
21
+ this.parts.splice(0, this.parts.length);
22
+ }
23
+ async flushTo(strm) {
24
+ const flushed = strm.write(this.buffer());
25
+ if (!flushed) {
26
+ return new Promise(ok => strm.once('drain', ok));
27
+ }
28
+ return;
29
+ }
30
+ toString() {
31
+ return this.buffer().toString();
32
+ }
33
+ }
34
+ exports.MemoryStream = MemoryStream;
35
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29ya2luZy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImNvcmtpbmcudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUE7O0dBRUc7QUFDSCxpQ0FBaUM7QUFFakMsTUFBYSxZQUFhLFNBQVEsTUFBTSxDQUFDLFFBQVE7SUFBakQ7O1FBQ1UsVUFBSyxHQUFHLElBQUksS0FBSyxFQUFVLENBQUM7SUEwQnRDLENBQUM7SUF4QlEsTUFBTSxDQUFDLEtBQWEsRUFBRSxTQUFpQixFQUFFLFFBQXdDO1FBQ3RGLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ3ZCLFFBQVEsRUFBRSxDQUFDO0lBQ2IsQ0FBQztJQUVNLE1BQU07UUFDWCxPQUFPLE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ25DLENBQUM7SUFFTSxLQUFLO1FBQ1YsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDMUMsQ0FBQztJQUVNLEtBQUssQ0FBQyxPQUFPLENBQUMsSUFBMkI7UUFDOUMsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQztRQUMxQyxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDYixPQUFPLElBQUksT0FBTyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUNuRCxDQUFDO1FBQ0QsT0FBTztJQUNULENBQUM7SUFFTSxRQUFRO1FBQ2IsT0FBTyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUMsUUFBUSxFQUFFLENBQUM7SUFDbEMsQ0FBQztDQUNGO0FBM0JELG9DQTJCQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogUm91dGluZXMgZm9yIGNvcmtpbmcgc3Rkb3V0IGFuZCBzdGRlcnJcbiAqL1xuaW1wb3J0ICogYXMgc3RyZWFtIGZyb20gJ3N0cmVhbSc7XG5cbmV4cG9ydCBjbGFzcyBNZW1vcnlTdHJlYW0gZXh0ZW5kcyBzdHJlYW0uV3JpdGFibGUge1xuICBwcml2YXRlIHBhcnRzID0gbmV3IEFycmF5PEJ1ZmZlcj4oKTtcblxuICBwdWJsaWMgX3dyaXRlKGNodW5rOiBCdWZmZXIsIF9lbmNvZGluZzogc3RyaW5nLCBjYWxsYmFjazogKGVycm9yPzogRXJyb3IgfCBudWxsKSA9PiB2b2lkKTogdm9pZCB7XG4gICAgdGhpcy5wYXJ0cy5wdXNoKGNodW5rKTtcbiAgICBjYWxsYmFjaygpO1xuICB9XG5cbiAgcHVibGljIGJ1ZmZlcigpIHtcbiAgICByZXR1cm4gQnVmZmVyLmNvbmNhdCh0aGlzLnBhcnRzKTtcbiAgfVxuXG4gIHB1YmxpYyBjbGVhcigpIHtcbiAgICB0aGlzLnBhcnRzLnNwbGljZSgwLCB0aGlzLnBhcnRzLmxlbmd0aCk7XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgZmx1c2hUbyhzdHJtOiBOb2RlSlMuV3JpdGFibGVTdHJlYW0pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBmbHVzaGVkID0gc3RybS53cml0ZSh0aGlzLmJ1ZmZlcigpKTtcbiAgICBpZiAoIWZsdXNoZWQpIHtcbiAgICAgIHJldHVybiBuZXcgUHJvbWlzZShvayA9PiBzdHJtLm9uY2UoJ2RyYWluJywgb2spKTtcbiAgICB9XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgcHVibGljIHRvU3RyaW5nKCkge1xuICAgIHJldHVybiB0aGlzLmJ1ZmZlcigpLnRvU3RyaW5nKCk7XG4gIH1cbn1cbiJdfQ==
package/lib/corking.ts ADDED
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Routines for corking stdout and stderr
3
+ */
4
+ import * as stream from 'stream';
5
+
6
+ export class MemoryStream extends stream.Writable {
7
+ private parts = new Array<Buffer>();
8
+
9
+ public _write(chunk: Buffer, _encoding: string, callback: (error?: Error | null) => void): void {
10
+ this.parts.push(chunk);
11
+ callback();
12
+ }
13
+
14
+ public buffer() {
15
+ return Buffer.concat(this.parts);
16
+ }
17
+
18
+ public clear() {
19
+ this.parts.splice(0, this.parts.length);
20
+ }
21
+
22
+ public async flushTo(strm: NodeJS.WritableStream): Promise<void> {
23
+ const flushed = strm.write(this.buffer());
24
+ if (!flushed) {
25
+ return new Promise(ok => strm.once('drain', ok));
26
+ }
27
+ return;
28
+ }
29
+
30
+ public toString() {
31
+ return this.buffer().toString();
32
+ }
33
+ }
@@ -0,0 +1,20 @@
1
+ /**
2
+ * @param maxAttempts the maximum number of attempts
3
+ * @param interval interval in milliseconds to observe between attempts
4
+ */
5
+ export type EventuallyOptions = {
6
+ maxAttempts?: number;
7
+ interval?: number;
8
+ };
9
+ /**
10
+ * Runs a function on an interval until the maximum number of attempts has
11
+ * been reached.
12
+ *
13
+ * Default interval = 1000 milliseconds
14
+ * Default maxAttempts = 10
15
+ *
16
+ * @param fn function to run
17
+ * @param options EventuallyOptions
18
+ */
19
+ declare const eventually: <T>(call: () => Promise<T>, options?: EventuallyOptions) => Promise<T>;
20
+ export default eventually;
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
4
+ const DEFAULT_INTERVAL = 1000;
5
+ const DEFAULT_MAX_ATTEMPTS = 10;
6
+ /**
7
+ * Runs a function on an interval until the maximum number of attempts has
8
+ * been reached.
9
+ *
10
+ * Default interval = 1000 milliseconds
11
+ * Default maxAttempts = 10
12
+ *
13
+ * @param fn function to run
14
+ * @param options EventuallyOptions
15
+ */
16
+ const eventually = async (call, options) => {
17
+ const opts = {
18
+ interval: (options === null || options === void 0 ? void 0 : options.interval) ? options.interval : DEFAULT_INTERVAL,
19
+ maxAttempts: (options === null || options === void 0 ? void 0 : options.maxAttempts) ? options.maxAttempts : DEFAULT_MAX_ATTEMPTS,
20
+ };
21
+ while (opts.maxAttempts-- >= 0) {
22
+ try {
23
+ return await call();
24
+ }
25
+ catch (err) {
26
+ if (opts.maxAttempts <= 0)
27
+ throw err;
28
+ }
29
+ await wait(opts.interval);
30
+ }
31
+ throw new Error('An unexpected error has occurred.');
32
+ };
33
+ exports.default = eventually;
34
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXZlbnR1YWxseS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImV2ZW50dWFsbHkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFTQSxNQUFNLElBQUksR0FBRyxDQUFDLEVBQVUsRUFBaUIsRUFBRSxDQUFDLElBQUksT0FBTyxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxVQUFVLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7QUFDOUYsTUFBTSxnQkFBZ0IsR0FBRyxJQUFJLENBQUM7QUFDOUIsTUFBTSxvQkFBb0IsR0FBRyxFQUFFLENBQUM7QUFFaEM7Ozs7Ozs7OztHQVNHO0FBQ0gsTUFBTSxVQUFVLEdBQUcsS0FBSyxFQUFLLElBQXNCLEVBQUUsT0FBMkIsRUFBYyxFQUFFO0lBQzlGLE1BQU0sSUFBSSxHQUFHO1FBQ1gsUUFBUSxFQUFFLENBQUEsT0FBTyxhQUFQLE9BQU8sdUJBQVAsT0FBTyxDQUFFLFFBQVEsRUFBQyxDQUFDLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsZ0JBQWdCO1FBQ2pFLFdBQVcsRUFBRSxDQUFBLE9BQU8sYUFBUCxPQUFPLHVCQUFQLE9BQU8sQ0FBRSxXQUFXLEVBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLG9CQUFvQjtLQUMvRSxDQUFDO0lBRUYsT0FBTyxJQUFJLENBQUMsV0FBVyxFQUFFLElBQUksQ0FBQyxFQUFFLENBQUM7UUFDL0IsSUFBSSxDQUFDO1lBQ0gsT0FBTyxNQUFNLElBQUksRUFBRSxDQUFDO1FBQ3RCLENBQUM7UUFBQyxPQUFPLEdBQUcsRUFBRSxDQUFDO1lBQ2IsSUFBSSxJQUFJLENBQUMsV0FBVyxJQUFJLENBQUM7Z0JBQUUsTUFBTSxHQUFHLENBQUM7UUFDdkMsQ0FBQztRQUNELE1BQU0sSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUM1QixDQUFDO0lBRUQsTUFBTSxJQUFJLEtBQUssQ0FBQyxtQ0FBbUMsQ0FBQyxDQUFDO0FBQ3ZELENBQUMsQ0FBQztBQUVGLGtCQUFlLFVBQVUsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQHBhcmFtIG1heEF0dGVtcHRzIHRoZSBtYXhpbXVtIG51bWJlciBvZiBhdHRlbXB0c1xuICogQHBhcmFtIGludGVydmFsIGludGVydmFsIGluIG1pbGxpc2Vjb25kcyB0byBvYnNlcnZlIGJldHdlZW4gYXR0ZW1wdHNcbiAqL1xuZXhwb3J0IHR5cGUgRXZlbnR1YWxseU9wdGlvbnMgPSB7XG4gIG1heEF0dGVtcHRzPzogbnVtYmVyO1xuICBpbnRlcnZhbD86IG51bWJlcjtcbn07XG5cbmNvbnN0IHdhaXQgPSAobXM6IG51bWJlcik6IFByb21pc2U8dm9pZD4gPT4gbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHNldFRpbWVvdXQocmVzb2x2ZSwgbXMpKTtcbmNvbnN0IERFRkFVTFRfSU5URVJWQUwgPSAxMDAwO1xuY29uc3QgREVGQVVMVF9NQVhfQVRURU1QVFMgPSAxMDtcblxuLyoqXG4gKiBSdW5zIGEgZnVuY3Rpb24gb24gYW4gaW50ZXJ2YWwgdW50aWwgdGhlIG1heGltdW0gbnVtYmVyIG9mIGF0dGVtcHRzIGhhc1xuICogYmVlbiByZWFjaGVkLlxuICpcbiAqIERlZmF1bHQgaW50ZXJ2YWwgPSAxMDAwIG1pbGxpc2Vjb25kc1xuICogRGVmYXVsdCBtYXhBdHRlbXB0cyA9IDEwXG4gKlxuICogQHBhcmFtIGZuIGZ1bmN0aW9uIHRvIHJ1blxuICogQHBhcmFtIG9wdGlvbnMgRXZlbnR1YWxseU9wdGlvbnNcbiAqL1xuY29uc3QgZXZlbnR1YWxseSA9IGFzeW5jIDxUPihjYWxsOiAoKSA9PiBQcm9taXNlPFQ+LCBvcHRpb25zPzogRXZlbnR1YWxseU9wdGlvbnMpOiBQcm9taXNlPFQ+ID0+IHtcbiAgY29uc3Qgb3B0cyA9IHtcbiAgICBpbnRlcnZhbDogb3B0aW9ucz8uaW50ZXJ2YWwgPyBvcHRpb25zLmludGVydmFsIDogREVGQVVMVF9JTlRFUlZBTCxcbiAgICBtYXhBdHRlbXB0czogb3B0aW9ucz8ubWF4QXR0ZW1wdHMgPyBvcHRpb25zLm1heEF0dGVtcHRzIDogREVGQVVMVF9NQVhfQVRURU1QVFMsXG4gIH07XG5cbiAgd2hpbGUgKG9wdHMubWF4QXR0ZW1wdHMtLSA+PSAwKSB7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiBhd2FpdCBjYWxsKCk7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBpZiAob3B0cy5tYXhBdHRlbXB0cyA8PSAwKSB0aHJvdyBlcnI7XG4gICAgfVxuICAgIGF3YWl0IHdhaXQob3B0cy5pbnRlcnZhbCk7XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoJ0FuIHVuZXhwZWN0ZWQgZXJyb3IgaGFzIG9jY3VycmVkLicpO1xufTtcblxuZXhwb3J0IGRlZmF1bHQgZXZlbnR1YWxseTtcbiJdfQ==