@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/shell.ts ADDED
@@ -0,0 +1,168 @@
1
+ import * as child_process from 'child_process';
2
+ import * as fs from 'fs';
3
+ import * as path from 'path';
4
+ import { TestContext } from './integ-test';
5
+ import { TemporaryDirectoryContext } from './with-temporary-directory';
6
+
7
+ /**
8
+ * A shell command that does what you want
9
+ *
10
+ * Is platform-aware, handles errors nicely.
11
+ */
12
+ export async function shell(command: string[], options: ShellOptions = {}): Promise<string> {
13
+ if (options.modEnv && options.env) {
14
+ throw new Error('Use either env or modEnv but not both');
15
+ }
16
+
17
+ const outputs = new Set(options.outputs);
18
+ const writeToOutputs = (x: string) => {
19
+ for (const outputStream of outputs) {
20
+ outputStream.write(x);
21
+ }
22
+ };
23
+
24
+ // Always output the command
25
+ writeToOutputs(`💻 ${command.join(' ')}\n`);
26
+ const show = options.show ?? 'always';
27
+
28
+ if (process.env.VERBOSE) {
29
+ outputs.add(process.stdout);
30
+ }
31
+
32
+ const env = options.env ?? (options.modEnv ? { ...process.env, ...options.modEnv } : process.env);
33
+
34
+ const child = child_process.spawn(command[0], command.slice(1), {
35
+ ...options,
36
+ env,
37
+ // Need this for Windows where we want .cmd and .bat to be found as well.
38
+ shell: true,
39
+ stdio: ['ignore', 'pipe', 'pipe'],
40
+ });
41
+
42
+ return new Promise<string>((resolve, reject) => {
43
+ const stdout = new Array<Buffer>();
44
+ const stderr = new Array<Buffer>();
45
+
46
+ child.stdout!.on('data', chunk => {
47
+ if (show === 'always') {
48
+ writeToOutputs(chunk);
49
+ }
50
+ stdout.push(chunk);
51
+ });
52
+
53
+ child.stderr!.on('data', chunk => {
54
+ if (show === 'always') {
55
+ writeToOutputs(chunk);
56
+ }
57
+ if (options.captureStderr ?? true) {
58
+ stderr.push(chunk);
59
+ }
60
+ });
61
+
62
+ child.once('error', reject);
63
+
64
+ child.once('close', code => {
65
+ const stderrOutput = Buffer.concat(stderr).toString('utf-8');
66
+ const stdoutOutput = Buffer.concat(stdout).toString('utf-8');
67
+ const out = (options.onlyStderr ? stderrOutput : stdoutOutput + stderrOutput).trim();
68
+ if (code === 0 || options.allowErrExit) {
69
+ resolve(out);
70
+ } else {
71
+ if (show === 'error') {
72
+ writeToOutputs(`${out}\n`);
73
+ }
74
+ reject(new Error(`'${command.join(' ')}' exited with error code ${code}.`));
75
+ }
76
+ });
77
+ });
78
+ }
79
+
80
+ export interface ShellOptions extends child_process.SpawnOptions {
81
+ /**
82
+ * Properties to add to 'env'
83
+ */
84
+ readonly modEnv?: Record<string, string>;
85
+
86
+ /**
87
+ * Don't fail when exiting with an error
88
+ *
89
+ * @default false
90
+ */
91
+ readonly allowErrExit?: boolean;
92
+
93
+ /**
94
+ * Whether to capture stderr
95
+ *
96
+ * @default true
97
+ */
98
+ readonly captureStderr?: boolean;
99
+
100
+ /**
101
+ * Pass output here
102
+ */
103
+ readonly outputs?: NodeJS.WritableStream[];
104
+
105
+ /**
106
+ * Only return stderr. For example, this is used to validate
107
+ * that when CI=true, all logs are sent to stdout.
108
+ *
109
+ * @default false
110
+ */
111
+ readonly onlyStderr?: boolean;
112
+
113
+ /**
114
+ * Don't log to stdout
115
+ *
116
+ * @default always
117
+ */
118
+ readonly show?: 'always' | 'never' | 'error';
119
+ }
120
+
121
+ export class ShellHelper {
122
+ public static fromContext(context: TestContext & TemporaryDirectoryContext) {
123
+ return new ShellHelper(context.integTestDir, context.output);
124
+ }
125
+
126
+ constructor(
127
+ private readonly _cwd: string,
128
+ private readonly _output: NodeJS.WritableStream) { }
129
+
130
+ public async shell(command: string[], options: Omit<ShellOptions, 'cwd' | 'outputs'> = {}): Promise<string> {
131
+ return shell(command, {
132
+ outputs: [this._output],
133
+ cwd: this._cwd,
134
+ ...options,
135
+ });
136
+ }
137
+ }
138
+
139
+ /**
140
+ * rm -rf reimplementation, don't want to depend on an NPM package for this
141
+ */
142
+ export function rimraf(fsPath: string) {
143
+ try {
144
+ const isDir = fs.lstatSync(fsPath).isDirectory();
145
+
146
+ if (isDir) {
147
+ for (const file of fs.readdirSync(fsPath)) {
148
+ rimraf(path.join(fsPath, file));
149
+ }
150
+ fs.rmdirSync(fsPath);
151
+ } else {
152
+ fs.unlinkSync(fsPath);
153
+ }
154
+ } catch (e: any) {
155
+ // We will survive ENOENT
156
+ if (e.code !== 'ENOENT') { throw e; }
157
+ }
158
+ }
159
+
160
+ export function addToShellPath(x: string) {
161
+ const parts = process.env.PATH?.split(':') ?? [];
162
+
163
+ if (!parts.includes(x)) {
164
+ parts.unshift(x);
165
+ }
166
+
167
+ process.env.PATH = parts.join(':');
168
+ }
@@ -0,0 +1,44 @@
1
+ export declare class TestRepository {
2
+ readonly repositoryName: string;
3
+ static readonly DEFAULT_DOMAIN = "test-cdk";
4
+ static newRandom(): Promise<TestRepository>;
5
+ static newWithName(name: string): Promise<TestRepository>;
6
+ static existing(repositoryName: string): TestRepository;
7
+ /**
8
+ * Garbage collect repositories
9
+ */
10
+ static gc(): Promise<void>;
11
+ readonly npmUpstream = "npm-upstream";
12
+ readonly pypiUpstream = "pypi-upstream";
13
+ readonly nugetUpstream = "nuget-upstream";
14
+ readonly mavenUpstream = "maven-upstream";
15
+ readonly domain = "test-cdk";
16
+ private readonly codeArtifact;
17
+ private _loginInformation;
18
+ private constructor();
19
+ prepare(): Promise<void>;
20
+ loginInformation(): Promise<LoginInformation>;
21
+ delete(): Promise<void>;
22
+ /**
23
+ * List all packages and mark them as "allow upstream versions".
24
+ *
25
+ * If we don't do this and we publish `foo@2.3.4-rc.0`, then we can't
26
+ * download `foo@2.3.0` anymore because by default CodeArtifact will
27
+ * block different versions from the same package.
28
+ */
29
+ markAllUpstreamAllow(): Promise<void>;
30
+ private ensureDomain;
31
+ private ensureUpstreams;
32
+ private ensureRepository;
33
+ private domainExists;
34
+ private repositoryExists;
35
+ private listPackages;
36
+ }
37
+ export interface LoginInformation {
38
+ readonly authToken: string;
39
+ readonly repositoryName: string;
40
+ readonly npmEndpoint: string;
41
+ readonly mavenEndpoint: string;
42
+ readonly nugetEndpoint: string;
43
+ readonly pypiEndpoint: string;
44
+ }
@@ -0,0 +1,281 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TestRepository = void 0;
4
+ const client_codeartifact_1 = require("@aws-sdk/client-codeartifact");
5
+ const aws_1 = require("../aws");
6
+ const COLLECT_BY_TAG = 'collect-by';
7
+ const REPO_LIFETIME_MS = 24 * 3600 * 1000; // One day
8
+ class TestRepository {
9
+ static async newRandom() {
10
+ const qualifier = Math.random()
11
+ .toString(36)
12
+ .replace(/[^a-z0-9]+/g, '');
13
+ const repo = new TestRepository(`test-${qualifier}`);
14
+ await repo.prepare();
15
+ return repo;
16
+ }
17
+ static async newWithName(name) {
18
+ const repo = new TestRepository(name);
19
+ await repo.prepare();
20
+ return repo;
21
+ }
22
+ static existing(repositoryName) {
23
+ return new TestRepository(repositoryName);
24
+ }
25
+ /**
26
+ * Garbage collect repositories
27
+ */
28
+ static async gc() {
29
+ var _a, _b;
30
+ if (!(await TestRepository.existing('*dummy*').domainExists())) {
31
+ return;
32
+ }
33
+ const codeArtifact = new client_codeartifact_1.CodeartifactClient();
34
+ let nextToken;
35
+ do {
36
+ const page = await codeArtifact.send(new client_codeartifact_1.ListRepositoriesCommand({
37
+ nextToken: nextToken,
38
+ }));
39
+ for (const repo of (_a = page.repositories) !== null && _a !== void 0 ? _a : []) {
40
+ const tags = await codeArtifact.send(new client_codeartifact_1.ListTagsForResourceCommand({
41
+ resourceArn: repo.arn,
42
+ }));
43
+ const collectable = (_b = tags === null || tags === void 0 ? void 0 : tags.tags) === null || _b === void 0 ? void 0 : _b.find((t) => t.key === COLLECT_BY_TAG && Number(t.value) < Date.now());
44
+ if (collectable) {
45
+ // eslint-disable-next-line no-console
46
+ console.log('Deleting', repo.name);
47
+ await codeArtifact.send(new client_codeartifact_1.DeleteRepositoryCommand({
48
+ domain: repo.domainName,
49
+ repository: repo.name,
50
+ }));
51
+ }
52
+ }
53
+ nextToken = page.nextToken;
54
+ } while (nextToken);
55
+ }
56
+ constructor(repositoryName) {
57
+ this.repositoryName = repositoryName;
58
+ this.npmUpstream = 'npm-upstream';
59
+ this.pypiUpstream = 'pypi-upstream';
60
+ this.nugetUpstream = 'nuget-upstream';
61
+ this.mavenUpstream = 'maven-upstream';
62
+ this.domain = TestRepository.DEFAULT_DOMAIN;
63
+ this.codeArtifact = new client_codeartifact_1.CodeartifactClient();
64
+ }
65
+ async prepare() {
66
+ await this.ensureDomain();
67
+ await this.ensureUpstreams();
68
+ await this.ensureRepository(this.repositoryName, {
69
+ description: 'Testing repository',
70
+ upstreams: [this.npmUpstream, this.pypiUpstream, this.nugetUpstream, this.mavenUpstream],
71
+ tags: {
72
+ [COLLECT_BY_TAG]: `${Date.now() + REPO_LIFETIME_MS}`,
73
+ },
74
+ });
75
+ }
76
+ async loginInformation() {
77
+ if (this._loginInformation) {
78
+ return this._loginInformation;
79
+ }
80
+ this._loginInformation = {
81
+ authToken: (await this.codeArtifact.send(new client_codeartifact_1.GetAuthorizationTokenCommand({
82
+ domain: this.domain,
83
+ durationSeconds: 12 * 3600,
84
+ }))).authorizationToken,
85
+ repositoryName: this.repositoryName,
86
+ npmEndpoint: (await this.codeArtifact.send(new client_codeartifact_1.GetRepositoryEndpointCommand({
87
+ domain: this.domain,
88
+ repository: this.repositoryName,
89
+ format: 'npm',
90
+ }))).repositoryEndpoint,
91
+ mavenEndpoint: (await this.codeArtifact.send(new client_codeartifact_1.GetRepositoryEndpointCommand({
92
+ domain: this.domain,
93
+ repository: this.repositoryName,
94
+ format: 'maven',
95
+ }))).repositoryEndpoint,
96
+ nugetEndpoint: (await this.codeArtifact.send(new client_codeartifact_1.GetRepositoryEndpointCommand({
97
+ domain: this.domain,
98
+ repository: this.repositoryName,
99
+ format: 'nuget',
100
+ }))).repositoryEndpoint,
101
+ pypiEndpoint: (await this.codeArtifact.send(new client_codeartifact_1.GetRepositoryEndpointCommand({
102
+ domain: this.domain,
103
+ repository: this.repositoryName,
104
+ format: 'pypi',
105
+ }))).repositoryEndpoint,
106
+ };
107
+ return this._loginInformation;
108
+ }
109
+ async delete() {
110
+ try {
111
+ await this.codeArtifact.send(new client_codeartifact_1.DeleteRepositoryCommand({
112
+ domain: this.domain,
113
+ repository: this.repositoryName,
114
+ }));
115
+ // eslint-disable-next-line no-console
116
+ console.log('Deleted', this.repositoryName);
117
+ }
118
+ catch (e) {
119
+ if (e.name !== 'ResourceNotFoundException') {
120
+ throw e;
121
+ }
122
+ // Okay
123
+ }
124
+ }
125
+ /**
126
+ * List all packages and mark them as "allow upstream versions".
127
+ *
128
+ * If we don't do this and we publish `foo@2.3.4-rc.0`, then we can't
129
+ * download `foo@2.3.0` anymore because by default CodeArtifact will
130
+ * block different versions from the same package.
131
+ */
132
+ async markAllUpstreamAllow() {
133
+ for await (const pkg of this.listPackages({ upstream: 'BLOCK' })) {
134
+ await retryThrottled(() => this.codeArtifact.send(new client_codeartifact_1.PutPackageOriginConfigurationCommand({
135
+ domain: this.domain,
136
+ repository: this.repositoryName,
137
+ format: pkg.format,
138
+ package: pkg.package,
139
+ namespace: pkg.namespace,
140
+ restrictions: {
141
+ publish: 'ALLOW',
142
+ upstream: 'ALLOW',
143
+ },
144
+ })));
145
+ }
146
+ }
147
+ async ensureDomain() {
148
+ if (await this.domainExists()) {
149
+ return;
150
+ }
151
+ await this.codeArtifact.send(new client_codeartifact_1.CreateDomainCommand({
152
+ domain: this.domain,
153
+ tags: [{ key: 'testing', value: 'true' }],
154
+ }));
155
+ }
156
+ async ensureUpstreams() {
157
+ await this.ensureRepository(this.npmUpstream, {
158
+ description: 'The upstream repository for NPM',
159
+ external: 'public:npmjs',
160
+ });
161
+ await this.ensureRepository(this.mavenUpstream, {
162
+ description: 'The upstream repository for Maven',
163
+ external: 'public:maven-central',
164
+ });
165
+ await this.ensureRepository(this.nugetUpstream, {
166
+ description: 'The upstream repository for NuGet',
167
+ external: 'public:nuget-org',
168
+ });
169
+ await this.ensureRepository(this.pypiUpstream, {
170
+ description: 'The upstream repository for PyPI',
171
+ external: 'public:pypi',
172
+ });
173
+ }
174
+ async ensureRepository(name, options) {
175
+ var _a;
176
+ if (await this.repositoryExists(name)) {
177
+ return;
178
+ }
179
+ await this.codeArtifact.send(new client_codeartifact_1.CreateRepositoryCommand({
180
+ domain: this.domain,
181
+ repository: name,
182
+ description: options === null || options === void 0 ? void 0 : options.description,
183
+ upstreams: (_a = options === null || options === void 0 ? void 0 : options.upstreams) === null || _a === void 0 ? void 0 : _a.map((repositoryName) => ({ repositoryName })),
184
+ tags: (options === null || options === void 0 ? void 0 : options.tags) ? Object.entries(options.tags).map(([key, value]) => ({ key, value })) : undefined,
185
+ }));
186
+ if (options === null || options === void 0 ? void 0 : options.external) {
187
+ const externalConnection = options.external;
188
+ await retry(() => this.codeArtifact.send(new client_codeartifact_1.AssociateExternalConnectionCommand({
189
+ domain: this.domain,
190
+ repository: name,
191
+ externalConnection,
192
+ })));
193
+ }
194
+ }
195
+ async domainExists() {
196
+ try {
197
+ await this.codeArtifact.send(new client_codeartifact_1.DescribeDomainCommand({ domain: this.domain }));
198
+ return true;
199
+ }
200
+ catch (e) {
201
+ if (e.name !== 'ResourceNotFoundException') {
202
+ throw e;
203
+ }
204
+ return false;
205
+ }
206
+ }
207
+ async repositoryExists(name) {
208
+ try {
209
+ await this.codeArtifact.send(new client_codeartifact_1.DescribeRepositoryCommand({ domain: this.domain, repository: name }));
210
+ return true;
211
+ }
212
+ catch (e) {
213
+ if (e.name !== 'ResourceNotFoundException') {
214
+ throw e;
215
+ }
216
+ return false;
217
+ }
218
+ }
219
+ async *listPackages(filter = {}) {
220
+ var _a;
221
+ let response = await retryThrottled(() => this.codeArtifact.send(new client_codeartifact_1.ListPackagesCommand({
222
+ domain: this.domain,
223
+ repository: this.repositoryName,
224
+ ...filter,
225
+ })));
226
+ while (true) {
227
+ for (const p of (_a = response.packages) !== null && _a !== void 0 ? _a : []) {
228
+ yield p;
229
+ }
230
+ if (!response.nextToken) {
231
+ break;
232
+ }
233
+ response = await retryThrottled(() => this.codeArtifact.send(new client_codeartifact_1.ListPackagesCommand({
234
+ domain: this.domain,
235
+ repository: this.repositoryName,
236
+ ...filter,
237
+ nextToken: response.nextToken,
238
+ })));
239
+ }
240
+ }
241
+ }
242
+ exports.TestRepository = TestRepository;
243
+ TestRepository.DEFAULT_DOMAIN = 'test-cdk';
244
+ async function retry(block) {
245
+ let attempts = 3;
246
+ while (true) {
247
+ try {
248
+ return await block();
249
+ }
250
+ catch (e) {
251
+ if (attempts-- === 0) {
252
+ throw e;
253
+ }
254
+ // eslint-disable-next-line no-console
255
+ console.debug(e.message);
256
+ await (0, aws_1.sleep)(500);
257
+ }
258
+ }
259
+ }
260
+ async function retryThrottled(block) {
261
+ let time = 100;
262
+ let attempts = 15;
263
+ while (true) {
264
+ try {
265
+ return await block();
266
+ }
267
+ catch (e) {
268
+ // eslint-disable-next-line no-console
269
+ console.debug(e.message);
270
+ if (e.name !== 'ThrottlingException') {
271
+ throw e;
272
+ }
273
+ if (attempts-- === 0) {
274
+ throw e;
275
+ }
276
+ await (0, aws_1.sleep)(Math.floor(Math.random() * time));
277
+ time *= 2;
278
+ }
279
+ }
280
+ }
281
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29kZWFydGlmYWN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiY29kZWFydGlmYWN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLHNFQWVzQztBQUN0QyxnQ0FBK0I7QUFFL0IsTUFBTSxjQUFjLEdBQUcsWUFBWSxDQUFDO0FBQ3BDLE1BQU0sZ0JBQWdCLEdBQUcsRUFBRSxHQUFHLElBQUksR0FBRyxJQUFJLENBQUMsQ0FBQyxVQUFVO0FBRXJELE1BQWEsY0FBYztJQUdsQixNQUFNLENBQUMsS0FBSyxDQUFDLFNBQVM7UUFDM0IsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLE1BQU0sRUFBRTthQUM1QixRQUFRLENBQUMsRUFBRSxDQUFDO2FBQ1osT0FBTyxDQUFDLGFBQWEsRUFBRSxFQUFFLENBQUMsQ0FBQztRQUU5QixNQUFNLElBQUksR0FBRyxJQUFJLGNBQWMsQ0FBQyxRQUFRLFNBQVMsRUFBRSxDQUFDLENBQUM7UUFDckQsTUFBTSxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDckIsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRU0sTUFBTSxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsSUFBWTtRQUMxQyxNQUFNLElBQUksR0FBRyxJQUFJLGNBQWMsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN0QyxNQUFNLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUNyQixPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFTSxNQUFNLENBQUMsUUFBUSxDQUFDLGNBQXNCO1FBQzNDLE9BQU8sSUFBSSxjQUFjLENBQUMsY0FBYyxDQUFDLENBQUM7SUFDNUMsQ0FBQztJQUVEOztPQUVHO0lBQ0ksTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFFOztRQUNwQixJQUFJLENBQUMsQ0FBQyxNQUFNLGNBQWMsQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDLENBQUMsWUFBWSxFQUFFLENBQUMsRUFBRSxDQUFDO1lBQy9ELE9BQU87UUFDVCxDQUFD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SSxDQUFDO1lBQ0gsT0FBTyxNQUFNLEtBQUssRUFBRSxDQUFDO1FBQ3ZCLENBQUM7UUFBQyxPQUFPLENBQU0sRUFBRSxDQUFDO1lBQ2hCLHNDQUFzQztZQUN0QyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUN6QixJQUFJLENBQUMsQ0FBQyxJQUFJLEtBQUsscUJBQXFCLEVBQUUsQ0FBQztnQkFDckMsTUFBTSxDQUFDLENBQUM7WUFDVixDQUFDO1lBQ0QsSUFBSSxRQUFRLEVBQUUsS0FBSyxDQUFDLEVBQUUsQ0FBQztnQkFDckIsTUFBTSxDQUFDLENBQUM7WUFDVixDQUFDO1lBQ0QsTUFBTSxJQUFBLFdBQUssRUFBQyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDO1lBQzlDLElBQUksSUFBSSxDQUFDLENBQUM7UUFDWixDQUFDO0lBQ0gsQ0FBQztBQUNILENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBBc3NvY2lhdGVFeHRlcm5hbENvbm5lY3Rpb25Db21tYW5kLFxuICBDb2RlYXJ0aWZhY3RDbGllbnQsXG4gIENyZWF0ZURvbWFpbkNvbW1hbmQsXG4gIENyZWF0ZVJlcG9zaXRvcnlDb21tYW5kLFxuICBEZWxldGVSZXBvc2l0b3J5Q29tbWFuZCxcbiAgRGVzY3JpYmVEb21haW5Db21tYW5kLFxuICBEZXNjcmliZVJlcG9zaXRvcnlDb21tYW5kLFxuICBHZXRBdXRob3JpemF0aW9uVG9rZW5Db21tYW5kLFxuICBHZXRSZXBvc2l0b3J5RW5kcG9pbnRDb21tYW5kLFxuICBMaXN0UGFja2FnZXNDb21tYW5kLFxuICBMaXN0UGFja2FnZXNSZXF1ZXN0LFxuICBMaXN0UmVwb3NpdG9yaWVzQ29tbWFuZCxcbiAgTGlzdFRhZ3NGb3JSZXNvdXJjZUNvbW1hbmQsXG4gIFB1dFBhY2thZ2VPcmlnaW5Db25maWd1cmF0aW9uQ29tbWFuZCxcbn0gZnJvbSAnQGF3cy1zZGsvY2xpZW50LWNvZGVhcnRpZmFjdCc7XG5pbXBvcnQgeyBzbGVlcCB9IGZyb20gJy4uL2F3cyc7XG5cbmNvbnN0IENPTExFQ1RfQllfVEFHID0gJ2NvbGxlY3QtYnknO1xuY29uc3QgUkVQT19MSUZFVElNRV9NUyA9IDI0ICogMzYwMCAqIDEwMDA7IC8vIE9uZSBkYXlcblxuZXhwb3J0IGNsYXNzIFRlc3RSZXBvc2l0b3J5IHtcbiAgcHVibGljIHN0YXRpYyByZWFkb25seSBERUZBVUxUX0RPTUFJTiA9ICd0ZXN0LWNkayc7XG5cbiAgcHVibGljIHN0YXRpYyBhc3luYyBuZXdSYW5kb20oKSB7XG4gICAgY29uc3QgcXVhbGlmaWVyID0gTWF0aC5yYW5kb20oKVxuICAgICAgLnRvU3RyaW5nKDM2KVxuICAgICAgLnJlcGxhY2UoL1teYS16MC05XSsvZywgJycpO1xuXG4gICAgY29uc3QgcmVwbyA9IG5ldyBUZXN0UmVwb3NpdG9yeShgdGVzdC0ke3F1YWxpZmllcn1gKTtcbiAgICBhd2FpdCByZXBvLnByZXBhcmUoKTtcbiAgICByZXR1cm4gcmVwbztcbiAgfVxuXG4gIHB1YmxpYyBzdGF0aWMgYXN5bmMgbmV3V2l0aE5hbWUobmFtZTogc3RyaW5nKSB7XG4gICAgY29uc3QgcmVwbyA9IG5ldyBUZXN0UmVwb3NpdG9yeShuYW1lKTtcbiAgICBhd2FpdCByZXBvLnByZXBhcmUoKTtcbiAgICByZXR1cm4gcmVwbztcbiAgfVxuXG4gIHB1YmxpYyBzdGF0aWMgZXhpc3RpbmcocmVwb3NpdG9yeU5hbWU6IHN0cmluZykge1xuICAgIHJldHVybiBuZXcgVGVzdFJlcG9zaXRvcnkocmVwb3NpdG9yeU5hbWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdhcmJhZ2UgY29sbGVjdCByZXBvc2l0b3JpZXNcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgYXN5bmMgZ2MoKSB7XG4gICAgaWYgKCEoYXdhaXQgVGVzdFJlcG9zaXRvcnkuZXhpc3RpbmcoJypkdW1teSonKS5kb21haW5FeGlzdHMoKSkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBjb2RlQXJ0aWZhY3QgPSBuZXcgQ29kZWFydGlmYWN0Q2xpZW50KCk7XG5cbiAgICBsZXQgbmV4dFRva2VuOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gICAgZG8ge1xuICAgICAgY29uc3QgcGFnZSA9IGF3YWl0IGNvZGVBcnRpZmFjdC5zZW5kKFxuICAgICAgICBuZXcgTGlzdFJlcG9zaXRvcmllc0NvbW1hbmQoe1xuICAgICAgICAgIG5leHRUb2tlbjogbmV4dFRva2VuLFxuICAgICAgICB9KSxcbiAgICAgICk7XG5cbiAgICAgIGZvciAoY29uc3QgcmVwbyBvZiBwYWdlLnJlcG9zaXRvcmllcyA/PyBbXSkge1xuICAgICAgICBjb25zdCB0YWdzID0gYXdhaXQgY29kZUFydGlmYWN0LnNlbmQoXG4gICAgICAgICAgbmV3IExpc3RUYWdzRm9yUmVzb3VyY2VDb21tYW5kKHtcbiAgICAgICAgICAgIHJlc291cmNlQXJuOiByZXBvLmFybiEsXG4gICAgICAgICAgfSksXG4gICAgICAgICk7XG4gICAgICAgIGNvbnN0IGNvbGxlY3RhYmxlID0gdGFncz8udGFncz8uZmluZCgodCkgPT4gdC5rZXkgPT09IENPTExFQ1RfQllfVEFHICYmIE51bWJlcih0LnZhbHVlKSA8IERhdGUubm93KCkpO1xuICAgICAgICBpZiAoY29sbGVjdGFibGUpIHtcbiAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxuICAgICAgICAgIGNvbnNvbGUubG9nKCdEZWxldGluZycsIHJlcG8ubmFtZSk7XG4gICAgICAgICAgYXdhaXQgY29kZUFydGlmYWN0LnNlbmQoXG4gICAgICAgICAgICBuZXcgRGVsZXRlUmVwb3NpdG9yeUNvbW1hbmQoe1xuICAgICAgICAgICAgICBkb21haW46IHJlcG8uZG9tYWluTmFtZSEsXG4gICAgICAgICAgICAgIHJlcG9zaXRvcnk6IHJlcG8ubmFtZSEsXG4gICAgICAgICAgICB9KSxcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIG5leHRUb2tlbiA9IHBhZ2UubmV4dFRva2VuO1xuICAgIH0gd2hpbGUgKG5leHRUb2tlbik7XG4gIH1cblxuICBwdWJsaWMgcmVhZG9ubHkgbnBtVXBzdHJlYW0gPSAnbnBtLXVwc3RyZWFtJztcbiAgcHVibGljIHJlYWRvbmx5IHB5cGlVcHN0cmVhbSA9ICdweXBpLXVwc3RyZWFtJztcbiAgcHVibGljIHJlYWRvbmx5IG51Z2V0VXBzdHJlYW0gPSAnbnVnZXQtdXBzdHJlYW0nO1xuICBwdWJsaWMgcmVhZG9ubHkgbWF2ZW5VcHN0cmVhbSA9ICdtYXZlbi11cHN0cmVhbSc7XG4gIHB1YmxpYyByZWFkb25seSBkb21haW4gPSBUZXN0UmVwb3NpdG9yeS5ERUZBVUxUX0RPTUFJTjtcblxuICBwcml2YXRlIHJlYWRvbmx5IGNvZGVBcnRpZmFjdCA9IG5ldyBDb2RlYXJ0aWZhY3RDbGllbnQoKTtcblxuICBwcml2YXRlIF9sb2dpbkluZm9ybWF0aW9uOiBMb2dpbkluZm9ybWF0aW9uIHwgdW5kZWZpbmVkO1xuXG4gIHByaXZhdGUgY29uc3RydWN0b3IocHVibGljIHJlYWRvbmx5IHJlcG9zaXRvcnlOYW1lOiBzdHJpbmcpIHt9XG5cbiAgcHVibGljIGFzeW5jIHByZXBhcmUoKSB7XG4gICAgYXdhaXQgdGhpcy5lbnN1cmVEb21haW4oKTtcbiAgICBhd2FpdCB0aGlzLmVuc3VyZVVwc3RyZWFtcygpO1xuXG4gICAgYXdhaXQgdGhpcy5lbnN1cmVSZXBvc2l0b3J5KHRoaXMucmVwb3NpdG9yeU5hbWUsIHtcbiAgICAgIGRlc2NyaXB0aW9uOiAnVGVzdGluZyByZXBvc2l0b3J5JyxcbiAgICAgIHVwc3RyZWFtczogW3RoaXMubnBtVXBzdHJlYW0sIHRoaXMucHlwaVVwc3RyZWFtLCB0aGlzLm51Z2V0VXBzdHJlYW0sIHRoaXMubWF2ZW5VcHN0cmVhbV0sXG4gICAgICB0YWdzOiB7XG4gICAgICAgIFtDT0xMRUNUX0JZX1RBR106IGAke0RhdGUubm93KCkgKyBSRVBPX0xJRkVUSU1FX01TfWAsXG4gICAgICB9LFxuICAgIH0pO1xuICB9XG5cbiAgcHVibGljIGFzeW5jIGxvZ2luSW5mb3JtYXRpb24oKTogUHJvbWlzZTxMb2dpbkluZm9ybWF0aW9uPiB7XG4gICAgaWYgKHRoaXMuX2xvZ2luSW5mb3JtYXRpb24pIHtcbiAgICAgIHJldHVybiB0aGlzLl9sb2dpbkluZm9ybWF0aW9uO1xuICAgIH1cblxuICAgIHRoaXMuX2xvZ2luSW5mb3JtYXRpb24gPSB7XG4gICAgICBhdXRoVG9rZW46IChcbiAgICAgICAgYXdhaXQgdGhpcy5jb2RlQXJ0aWZhY3Quc2VuZChcbiAgICAgICAgICBuZXcgR2V0QXV0aG9yaXphdGlvblRva2VuQ29tbWFuZCh7XG4gICAgICAgICAgICBkb21haW46IHRoaXMuZG9tYWluLFxuICAgICAgICAgICAgZHVyYXRpb25TZWNvbmRzOiAxMiAqIDM2MDAsXG4gICAgICAgICAgfSksXG4gICAgICAgIClcbiAgICAgICkuYXV0aG9yaXphdGlvblRva2VuISxcbiAgICAgIHJlcG9zaXRvcnlOYW1lOiB0aGlzLnJlcG9zaXRvcnlOYW1lLFxuXG4gICAgICBucG1FbmRwb2ludDogKFxuICAgICAgICBhd2FpdCB0aGlzLmNvZGVBcnRpZmFjdC5zZW5kKFxuICAgICAgICAgIG5ldyBHZXRSZXBvc2l0b3J5RW5kcG9pbnRDb21tYW5kKHtcbiAgICAgICAgICAgIGRvbWFpbjogdGhpcy5kb21haW4sXG4gICAgICAgICAgICByZXBvc2l0b3J5OiB0aGlzLnJlcG9zaXRvcnlOYW1lLFxuICAgICAgICAgICAgZm9ybWF0OiAnbnBtJyxcbiAgICAgICAgICB9KSxcbiAgICAgICAgKVxuICAgICAgKS5yZXBvc2l0b3J5RW5kcG9pbnQhLFxuXG4gICAgICBtYXZlbkVuZHBvaW50OiAoXG4gICAgICAgIGF3YWl0IHRoaXMuY29kZUFydGlmYWN0LnNlbmQoXG4gICAgICAgICAgbmV3IEdldFJlcG9zaXRvcnlFbmRwb2ludENvbW1hbmQoe1xuICAgICAgICAgICAgZG9tYWluOiB0aGlzLmRvbWFpbixcbiAgICAgICAgICAgIHJlcG9zaXRvcnk6IHRoaXMucmVwb3NpdG9yeU5hbWUsXG4gICAgICAgICAgICBmb3JtYXQ6ICdtYXZlbicsXG4gICAgICAgICAgfSksXG4gICAgICAgIClcbiAgICAgICkucmVwb3NpdG9yeUVuZHBvaW50ISxcblxuICAgICAgbnVnZXRFbmRwb2ludDogKFxuICAgICAgICBhd2FpdCB0aGlzLmNvZGVBcnRpZmFjdC5zZW5kKFxuICAgICAgICAgIG5ldyBHZXRSZXBvc2l0b3J5RW5kcG9pbnRDb21tYW5kKHtcbiAgICAgICAgICAgIGRvbWFpbjogdGhpcy5kb21haW4sXG4gICAgICAgICAgICByZXBvc2l0b3J5OiB0aGlzLnJlcG9zaXRvcnlOYW1lLFxuICAgICAgICAgICAgZm9ybWF0OiAnbnVnZXQnLFxuICAgICAgICAgIH0pLFxuICAgICAgICApXG4gICAgICApLnJlcG9zaXRvcnlFbmRwb2ludCEsXG5cbiAgICAgIHB5cGlFbmRwb2ludDogKFxuICAgICAgICBhd2FpdCB0aGlzLmNvZGVBcnRpZmFjdC5zZW5kKFxuICAgICAgICAgIG5ldyBHZXRSZXBvc2l0b3J5RW5kcG9pbnRDb21tYW5kKHtcbiAgICAgICAgICAgIGRvbWFpbjogdGhpcy5kb21haW4sXG4gICAgICAgICAgICByZXBvc2l0b3J5OiB0aGlzLnJlcG9zaXRvcnlOYW1lLFxuICAgICAgICAgICAgZm9ybWF0OiAncHlwaScsXG4gICAgICAgICAgfSksXG4gICAgICAgIClcbiAgICAgICkucmVwb3NpdG9yeUVuZHBvaW50ISxcbiAgICB9O1xuICAgIHJldHVybiB0aGlzLl9sb2dpbkluZm9ybWF0aW9uO1xuICB9XG5cbiAgcHVibGljIGFzeW5jIGRlbGV0ZSgpIHtcbiAgICB0cnkge1xuICAgICAgYXdhaXQgdGhpcy5jb2RlQXJ0aWZhY3Quc2VuZChcbiAgICAgICAgbmV3IERlbGV0ZVJlcG9zaXRvcnlDb21tYW5kKHtcbiAgICAgICAgICBkb21haW46IHRoaXMuZG9tYWluLFxuICAgICAgICAgIHJlcG9zaXRvcnk6IHRoaXMucmVwb3NpdG9yeU5hbWUsXG4gICAgICAgIH0pLFxuICAgICAgKTtcblxuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICAgIGNvbnNvbGUubG9nKCdEZWxldGVkJywgdGhpcy5yZXBvc2l0b3J5TmFtZSk7XG4gICAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgICBpZiAoZS5uYW1lICE9PSAnUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbicpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICAgIC8vIE9rYXlcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogTGlzdCBhbGwgcGFja2FnZXMgYW5kIG1hcmsgdGhlbSBhcyBcImFsbG93IHVwc3RyZWFtIHZlcnNpb25zXCIuXG4gICAqXG4gICAqIElmIHdlIGRvbid0IGRvIHRoaXMgYW5kIHdlIHB1Ymxpc2ggYGZvb0AyLjMuNC1yYy4wYCwgdGhlbiB3ZSBjYW4ndFxuICAgKiBkb3dubG9hZCBgZm9vQDIuMy4wYCBhbnltb3JlIGJlY2F1c2UgYnkgZGVmYXVsdCBDb2RlQXJ0aWZhY3Qgd2lsbFxuICAgKiBibG9jayBkaWZmZXJlbnQgdmVyc2lvbnMgZnJvbSB0aGUgc2FtZSBwYWNrYWdlLlxuICAgKi9cbiAgcHVibGljIGFzeW5jIG1hcmtBbGxVcHN0cmVhbUFsbG93KCkge1xuICAgIGZvciBhd2FpdCAoY29uc3QgcGtnIG9mIHRoaXMubGlzdFBhY2thZ2VzKHsgdXBzdHJlYW06ICdCTE9DSycgfSkpIHtcbiAgICAgIGF3YWl0IHJldHJ5VGhyb3R0bGVkKCgpID0+XG4gICAgICAgIHRoaXMuY29kZUFydGlmYWN0LnNlbmQoXG4gICAgICAgICAgbmV3IFB1dFBhY2thZ2VPcmlnaW5Db25maWd1cmF0aW9uQ29tbWFuZCh7XG4gICAgICAgICAgICBkb21haW46IHRoaXMuZG9tYWluLFxuICAgICAgICAgICAgcmVwb3NpdG9yeTogdGhpcy5yZXBvc2l0b3J5TmFtZSxcblxuICAgICAgICAgICAgZm9ybWF0OiBwa2cuZm9ybWF0ISxcbiAgICAgICAgICAgIHBhY2thZ2U6IHBrZy5wYWNrYWdlISxcbiAgICAgICAgICAgIG5hbWVzcGFjZTogcGtnLm5hbWVzcGFjZSEsXG4gICAgICAgICAgICByZXN0cmljdGlvbnM6IHtcbiAgICAgICAgICAgICAgcHVibGlzaDogJ0FMTE9XJyxcbiAgICAgICAgICAgICAgdXBzdHJlYW06ICdBTExPVycsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH0pLFxuICAgICAgICApLFxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGVuc3VyZURvbWFpbigpIHtcbiAgICBpZiAoYXdhaXQgdGhpcy5kb21haW5FeGlzdHMoKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBhd2FpdCB0aGlzLmNvZGVBcnRpZmFjdC5zZW5kKFxuICAgICAgbmV3IENyZWF0ZURvbWFpbkNvbW1hbmQoe1xuICAgICAgICBkb21haW46IHRoaXMuZG9tYWluLFxuICAgICAgICB0YWdzOiBbeyBrZXk6ICd0ZXN0aW5nJywgdmFsdWU6ICd0cnVlJyB9XSxcbiAgICAgIH0pLFxuICAgICk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGVuc3VyZVVwc3RyZWFtcygpIHtcbiAgICBhd2FpdCB0aGlzLmVuc3VyZVJlcG9zaXRvcnkodGhpcy5ucG1VcHN0cmVhbSwge1xuICAgICAgZGVzY3JpcHRpb246ICdUaGUgdXBzdHJlYW0gcmVwb3NpdG9yeSBmb3IgTlBNJyxcbiAgICAgIGV4dGVybmFsOiAncHVibGljOm5wbWpzJyxcbiAgICB9KTtcbiAgICBhd2FpdCB0aGlzLmVuc3VyZVJlcG9zaXRvcnkodGhpcy5tYXZlblVwc3RyZWFtLCB7XG4gICAgICBkZXNjcmlwdGlvbjogJ1RoZSB1cHN0cmVhbSByZXBvc2l0b3J5IGZvciBNYXZlbicsXG4gICAgICBleHRlcm5hbDogJ3B1YmxpYzptYXZlbi1jZW50cmFsJyxcbiAgICB9KTtcbiAgICBhd2FpdCB0aGlzLmVuc3VyZVJlcG9zaXRvcnkodGhpcy5udWdldFVwc3RyZWFtLCB7XG4gICAgICBkZXNjcmlwdGlvbjogJ1RoZSB1cHN0cmVhbSByZXBvc2l0b3J5IGZvciBOdUdldCcsXG4gICAgICBleHRlcm5hbDogJ3B1YmxpYzpudWdldC1vcmcnLFxuICAgIH0pO1xuICAgIGF3YWl0IHRoaXMuZW5zdXJlUmVwb3NpdG9yeSh0aGlzLnB5cGlVcHN0cmVhbSwge1xuICAgICAgZGVzY3JpcHRpb246ICdUaGUgdXBzdHJlYW0gcmVwb3NpdG9yeSBmb3IgUHlQSScsXG4gICAgICBleHRlcm5hbDogJ3B1YmxpYzpweXBpJyxcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgZW5zdXJlUmVwb3NpdG9yeShcbiAgICBuYW1lOiBzdHJpbmcsXG4gICAgb3B0aW9ucz86IHtcbiAgICAgIHJlYWRvbmx5IGRlc2NyaXB0aW9uPzogc3RyaW5nO1xuICAgICAgcmVhZG9ubHkgZXh0ZXJuYWw/OiBzdHJpbmc7XG4gICAgICByZWFkb25seSB1cHN0cmVhbXM/OiBzdHJpbmdbXTtcbiAgICAgIHJlYWRvbmx5IHRhZ3M/OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+O1xuICAgIH0sXG4gICkge1xuICAgIGlmIChhd2FpdCB0aGlzLnJlcG9zaXRvcnlFeGlzdHMobmFtZSkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBhd2FpdCB0aGlzLmNvZGVBcnRpZmFjdC5zZW5kKFxuICAgICAgbmV3IENyZWF0ZVJlcG9zaXRvcnlDb21tYW5kKHtcbiAgICAgICAgZG9tYWluOiB0aGlzLmRvbWFpbixcbiAgICAgICAgcmVwb3NpdG9yeTogbmFtZSxcbiAgICAgICAgZGVzY3JpcHRpb246IG9wdGlvbnM/LmRlc2NyaXB0aW9uLFxuICAgICAgICB1cHN0cmVhbXM6IG9wdGlvbnM/LnVwc3RyZWFtcz8ubWFwKChyZXBvc2l0b3J5TmFtZSkgPT4gKHsgcmVwb3NpdG9yeU5hbWUgfSkpLFxuICAgICAgICB0YWdzOiBvcHRpb25zPy50YWdzID8gT2JqZWN0LmVudHJpZXMob3B0aW9ucy50YWdzKS5tYXAoKFtrZXksIHZhbHVlXSkgPT4gKHsga2V5LCB2YWx1ZSB9KSkgOiB1bmRlZmluZWQsXG4gICAgICB9KSxcbiAgICApO1xuXG4gICAgaWYgKG9wdGlvbnM/LmV4dGVybmFsKSB7XG4gICAgICBjb25zdCBleHRlcm5hbENvbm5lY3Rpb24gPSBvcHRpb25zLmV4dGVybmFsO1xuICAgICAgYXdhaXQgcmV0cnkoKCkgPT5cbiAgICAgICAgdGhpcy5jb2RlQXJ0aWZhY3Quc2VuZChcbiAgICAgICAgICBuZXcgQXNzb2NpYXRlRXh0ZXJuYWxDb25uZWN0aW9uQ29tbWFuZCh7XG4gICAgICAgICAgICBkb21haW46IHRoaXMuZG9tYWluLFxuICAgICAgICAgICAgcmVwb3NpdG9yeTogbmFtZSxcbiAgICAgICAgICAgIGV4dGVybmFsQ29ubmVjdGlvbixcbiAgICAgICAgICB9KSxcbiAgICAgICAgKSxcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBkb21haW5FeGlzdHMoKSB7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHRoaXMuY29kZUFydGlmYWN0LnNlbmQobmV3IERlc2NyaWJlRG9tYWluQ29tbWFuZCh7IGRvbWFpbjogdGhpcy5kb21haW4gfSkpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgICBpZiAoZS5uYW1lICE9PSAnUmVzb3VyY2VOb3RGb3VuZEV4Y2VwdGlvbicpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHJlcG9zaXRvcnlFeGlzdHMobmFtZTogc3RyaW5nKSB7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHRoaXMuY29kZUFydGlmYWN0LnNlbmQobmV3IERlc2NyaWJlUmVwb3NpdG9yeUNvbW1hbmQoeyBkb21haW46IHRoaXMuZG9tYWluLCByZXBvc2l0b3J5OiBuYW1lIH0pKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH0gY2F0Y2ggKGU6IGFueSkge1xuICAgICAgaWYgKGUubmFtZSAhPT0gJ1Jlc291cmNlTm90Rm91bmRFeGNlcHRpb24nKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyAqbGlzdFBhY2thZ2VzKGZpbHRlcjogUGljazxMaXN0UGFja2FnZXNSZXF1ZXN0LCAndXBzdHJlYW0nIHwgJ3B1Ymxpc2gnIHwgJ2Zvcm1hdCc+ID0ge30pIHtcbiAgICBsZXQgcmVzcG9uc2UgPSBhd2FpdCByZXRyeVRocm90dGxlZCgoKSA9PlxuICAgICAgdGhpcy5jb2RlQXJ0aWZhY3Quc2VuZChcbiAgICAgICAgbmV3IExpc3RQYWNrYWdlc0NvbW1hbmQoe1xuICAgICAgICAgIGRvbWFpbjogdGhpcy5kb21haW4sXG4gICAgICAgICAgcmVwb3NpdG9yeTogdGhpcy5yZXBvc2l0b3J5TmFtZSxcbiAgICAgICAgICAuLi5maWx0ZXIsXG4gICAgICAgIH0pLFxuICAgICAgKSxcbiAgICApO1xuXG4gICAgd2hpbGUgKHRydWUpIHtcbiAgICAgIGZvciAoY29uc3QgcCBvZiByZXNwb25zZS5wYWNrYWdlcyA/PyBbXSkge1xuICAgICAgICB5aWVsZCBwO1xuICAgICAgfVxuXG4gICAgICBpZiAoIXJlc3BvbnNlLm5leHRUb2tlbikge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cblxuICAgICAgcmVzcG9uc2UgPSBhd2FpdCByZXRyeVRocm90dGxlZCgoKSA9PlxuICAgICAgICB0aGlzLmNvZGVBcnRpZmFjdC5zZW5kKFxuICAgICAgICAgIG5ldyBMaXN0UGFja2FnZXNDb21tYW5kKHtcbiAgICAgICAgICAgIGRvbWFpbjogdGhpcy5kb21haW4sXG4gICAgICAgICAgICByZXBvc2l0b3J5OiB0aGlzLnJlcG9zaXRvcnlOYW1lLFxuICAgICAgICAgICAgLi4uZmlsdGVyLFxuICAgICAgICAgICAgbmV4dFRva2VuOiByZXNwb25zZS5uZXh0VG9rZW4sXG4gICAgICAgICAgfSksXG4gICAgICAgICksXG4gICAgICApO1xuICAgIH1cbiAgfVxufVxuXG5hc3luYyBmdW5jdGlvbiByZXRyeTxBPihibG9jazogKCkgPT4gUHJvbWlzZTxBPikge1xuICBsZXQgYXR0ZW1wdHMgPSAzO1xuICB3aGlsZSAodHJ1ZSkge1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gYXdhaXQgYmxvY2soKTtcbiAgICB9IGNhdGNoIChlOiBhbnkpIHtcbiAgICAgIGlmIChhdHRlbXB0cy0tID09PSAwKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxuICAgICAgY29uc29sZS5kZWJ1ZyhlLm1lc3NhZ2UpO1xuICAgICAgYXdhaXQgc2xlZXAoNTAwKTtcbiAgICB9XG4gIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gcmV0cnlUaHJvdHRsZWQ8QT4oYmxvY2s6ICgpID0+IFByb21pc2U8QT4pIHtcbiAgbGV0IHRpbWUgPSAxMDA7XG4gIGxldCBhdHRlbXB0cyA9IDE1O1xuICB3aGlsZSAodHJ1ZSkge1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gYXdhaXQgYmxvY2soKTtcbiAgICB9IGNhdGNoIChlOiBhbnkpIHtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgICBjb25zb2xlLmRlYnVnKGUubWVzc2FnZSk7XG4gICAgICBpZiAoZS5uYW1lICE9PSAnVGhyb3R0bGluZ0V4Y2VwdGlvbicpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICAgIGlmIChhdHRlbXB0cy0tID09PSAwKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgICBhd2FpdCBzbGVlcChNYXRoLmZsb29yKE1hdGgucmFuZG9tKCkgKiB0aW1lKSk7XG4gICAgICB0aW1lICo9IDI7XG4gICAgfVxuICB9XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgTG9naW5JbmZvcm1hdGlvbiB7XG4gIHJlYWRvbmx5IGF1dGhUb2tlbjogc3RyaW5nO1xuICByZWFkb25seSByZXBvc2l0b3J5TmFtZTogc3RyaW5nO1xuICByZWFkb25seSBucG1FbmRwb2ludDogc3RyaW5nO1xuICByZWFkb25seSBtYXZlbkVuZHBvaW50OiBzdHJpbmc7XG4gIHJlYWRvbmx5IG51Z2V0RW5kcG9pbnQ6IHN0cmluZztcbiAgcmVhZG9ubHkgcHlwaUVuZHBvaW50OiBzdHJpbmc7XG59XG4iXX0=