@aws-mdaa/dataops-job-l3-construct 1.5.0 → 1.6.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 (90) hide show
  1. package/.jsii +38 -28
  2. package/README.md +5 -0
  3. package/lib/dataops-job-l3-construct.d.ts +8 -1
  4. package/lib/dataops-job-l3-construct.js +40 -13
  5. package/node_modules/@aws-mdaa/config/README.md +3 -0
  6. package/node_modules/@aws-mdaa/config/lib/blueprint-value-transformer.d.ts +20 -0
  7. package/node_modules/@aws-mdaa/config/lib/blueprint-value-transformer.js +70 -0
  8. package/node_modules/@aws-mdaa/config/lib/blueprint-value-transformer.ts +88 -0
  9. package/node_modules/@aws-mdaa/config/lib/config.d.ts +87 -0
  10. package/node_modules/@aws-mdaa/config/lib/config.js +7 -0
  11. package/node_modules/@aws-mdaa/config/lib/config.ts +92 -0
  12. package/node_modules/@aws-mdaa/config/lib/index.d.ts +11 -0
  13. package/node_modules/@aws-mdaa/config/lib/index.js +28 -0
  14. package/node_modules/@aws-mdaa/config/lib/index.ts +12 -0
  15. package/node_modules/@aws-mdaa/config/lib/param-transformer.d.ts +49 -0
  16. package/node_modules/@aws-mdaa/config/lib/param-transformer.js +160 -0
  17. package/node_modules/@aws-mdaa/config/lib/param-transformer.ts +159 -0
  18. package/node_modules/@aws-mdaa/config/lib/path-value-transformer.d.ts +10 -0
  19. package/node_modules/@aws-mdaa/config/lib/path-value-transformer.js +30 -0
  20. package/node_modules/@aws-mdaa/config/lib/path-value-transformer.ts +27 -0
  21. package/node_modules/@aws-mdaa/config/lib/ref-value-transformer.d.ts +44 -0
  22. package/node_modules/@aws-mdaa/config/lib/ref-value-transformer.js +243 -0
  23. package/node_modules/@aws-mdaa/config/lib/ref-value-transformer.ts +302 -0
  24. package/node_modules/@aws-mdaa/config/lib/ssm-ref-transformer.d.ts +8 -0
  25. package/node_modules/@aws-mdaa/config/lib/ssm-ref-transformer.js +22 -0
  26. package/node_modules/@aws-mdaa/config/lib/ssm-ref-transformer.ts +21 -0
  27. package/node_modules/@aws-mdaa/config/lib/transformer.d.ts +35 -0
  28. package/node_modules/@aws-mdaa/config/lib/transformer.js +66 -0
  29. package/node_modules/@aws-mdaa/config/lib/transformer.ts +74 -0
  30. package/node_modules/@aws-mdaa/config/package.json +42 -0
  31. package/node_modules/@aws-mdaa/config/test/blueprint-value-transformer.test.js +224 -0
  32. package/node_modules/@aws-mdaa/config/test/blueprint-value-transformer.test.ts +259 -0
  33. package/node_modules/@aws-mdaa/config/test/config-nt.test.d.ts +5 -0
  34. package/node_modules/@aws-mdaa/config/test/config-nt.test.js +129 -0
  35. package/node_modules/@aws-mdaa/config/test/config-nt.test.ts +163 -0
  36. package/node_modules/@aws-mdaa/config/test/config.test.d.ts +5 -0
  37. package/node_modules/@aws-mdaa/config/test/config.test.js +409 -0
  38. package/node_modules/@aws-mdaa/config/test/config.test.ts +517 -0
  39. package/node_modules/@aws-mdaa/config/test/param-transformer.test.d.ts +5 -0
  40. package/node_modules/@aws-mdaa/config/test/param-transformer.test.js +216 -0
  41. package/node_modules/@aws-mdaa/config/test/param-transformer.test.ts +234 -0
  42. package/node_modules/@aws-mdaa/config/test/path-value-transformer.test.d.ts +5 -0
  43. package/node_modules/@aws-mdaa/config/test/path-value-transformer.test.js +59 -0
  44. package/node_modules/@aws-mdaa/config/test/path-value-transformer.test.ts +68 -0
  45. package/node_modules/@aws-mdaa/config/test/ref-value-transformer.test.d.ts +5 -0
  46. package/node_modules/@aws-mdaa/config/test/ref-value-transformer.test.js +254 -0
  47. package/node_modules/@aws-mdaa/config/test/ref-value-transformer.test.ts +304 -0
  48. package/node_modules/@aws-mdaa/config/test/ssm-ref-transformer.test.d.ts +5 -0
  49. package/node_modules/@aws-mdaa/config/test/ssm-ref-transformer.test.js +66 -0
  50. package/node_modules/@aws-mdaa/config/test/ssm-ref-transformer.test.ts +79 -0
  51. package/node_modules/@aws-mdaa/config/tsconfig.tsbuildinfo +1 -0
  52. package/node_modules/lodash/README.md +2 -2
  53. package/node_modules/lodash/_baseOrderBy.js +1 -1
  54. package/node_modules/lodash/_baseUnset.js +7 -20
  55. package/node_modules/lodash/_setCacheHas.js +1 -1
  56. package/node_modules/lodash/compact.js +1 -1
  57. package/node_modules/lodash/core.js +3 -3
  58. package/node_modules/lodash/core.min.js +26 -25
  59. package/node_modules/lodash/fromPairs.js +3 -1
  60. package/node_modules/lodash/lodash.js +38 -27
  61. package/node_modules/lodash/lodash.min.js +125 -129
  62. package/node_modules/lodash/package.json +4 -2
  63. package/node_modules/lodash/random.js +9 -0
  64. package/node_modules/lodash/template.js +16 -4
  65. package/node_modules/lodash/templateSettings.js +4 -0
  66. package/package.json +27 -32
  67. package/node_modules/@aws-mdaa/s3-bucketpolicy-helper/README.md +0 -185
  68. package/node_modules/@aws-mdaa/s3-bucketpolicy-helper/lib/index.d.ts +0 -57
  69. package/node_modules/@aws-mdaa/s3-bucketpolicy-helper/lib/index.js +0 -198
  70. package/node_modules/@aws-mdaa/s3-bucketpolicy-helper/lib/index.ts +0 -241
  71. package/node_modules/@aws-mdaa/s3-bucketpolicy-helper/package.json +0 -44
  72. package/node_modules/@aws-mdaa/s3-bucketpolicy-helper/test/bucketpolicy-helper.test.js +0 -200
  73. package/node_modules/@aws-mdaa/s3-bucketpolicy-helper/test/bucketpolicy-helper.test.ts +0 -215
  74. package/node_modules/@aws-mdaa/s3-bucketpolicy-helper/tsconfig.tsbuildinfo +0 -1
  75. package/node_modules/@aws-mdaa/s3-inventory-helper/.npmignore +0 -34
  76. package/node_modules/@aws-mdaa/s3-inventory-helper/README.md +0 -3
  77. package/node_modules/@aws-mdaa/s3-inventory-helper/jest.config.js +0 -5
  78. package/node_modules/@aws-mdaa/s3-inventory-helper/lib/index.d.ts +0 -48
  79. package/node_modules/@aws-mdaa/s3-inventory-helper/lib/index.js +0 -213
  80. package/node_modules/@aws-mdaa/s3-inventory-helper/lib/index.ts +0 -241
  81. package/node_modules/@aws-mdaa/s3-inventory-helper/package.json +0 -44
  82. package/node_modules/@aws-mdaa/s3-inventory-helper/test/TODO +0 -0
  83. package/node_modules/@aws-mdaa/s3-inventory-helper/tsconfig.json +0 -40
  84. package/node_modules/@aws-mdaa/s3-inventory-helper/tsconfig.tsbuildinfo +0 -1
  85. package/node_modules/@aws-mdaa/s3-inventory-helper/typedoc.json +0 -7
  86. /package/node_modules/@aws-mdaa/{s3-bucketpolicy-helper → config}/.npmignore +0 -0
  87. /package/node_modules/@aws-mdaa/{s3-bucketpolicy-helper → config}/jest.config.js +0 -0
  88. /package/node_modules/@aws-mdaa/{s3-bucketpolicy-helper/test/bucketpolicy-helper.test.d.ts → config/test/blueprint-value-transformer.test.d.ts} +0 -0
  89. /package/node_modules/@aws-mdaa/{s3-bucketpolicy-helper → config}/tsconfig.json +0 -0
  90. /package/node_modules/@aws-mdaa/{s3-bucketpolicy-helper → config}/typedoc.json +0 -0
@@ -0,0 +1,409 @@
1
+ "use strict";
2
+ /*!
3
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ const aws_cdk_lib_1 = require("aws-cdk-lib");
8
+ // nosemgrep
9
+ const path = require("path");
10
+ const lib_1 = require("../lib");
11
+ const console = require("console");
12
+ const naming_1 = require("@aws-mdaa/naming");
13
+ class TestKeyTransformer {
14
+ transformValue(value, contextPath) {
15
+ console.log(`Transforming ${contextPath}:${value} -> "transformedValue"`);
16
+ return 'transformedKey';
17
+ }
18
+ }
19
+ class TestValueTransformer {
20
+ transformValue(value, contextPath) {
21
+ console.log(`Transforming ${contextPath}:${value} -> "transformedValue"`);
22
+ return 'transformedValue';
23
+ }
24
+ }
25
+ describe('Test MdaaConfigKeyTransformer', () => {
26
+ describe('Test transformConfigObject', () => {
27
+ const testConfigObj = {
28
+ testString: 'testing',
29
+ };
30
+ const transformedConfig = new lib_1.MdaaConfigTransformer(new TestValueTransformer(), new TestKeyTransformer()).transformConfig(testConfigObj);
31
+ test('String Transformation', () => {
32
+ expect(transformedConfig['transformedKey']).toBe('transformedValue');
33
+ });
34
+ });
35
+ });
36
+ describe('Test MdaaConfigValueTransformer', () => {
37
+ describe('Test transformConfigObject', () => {
38
+ const testConfigObj = {
39
+ testString: 'testing',
40
+ testNumber: 123,
41
+ testObj: {
42
+ testObjString: 'testing',
43
+ },
44
+ testArray: ['testing1', 'testing2'],
45
+ };
46
+ const transformedConfig = new lib_1.MdaaConfigTransformer(new TestValueTransformer()).transformConfig(testConfigObj);
47
+ test('String Transformation', () => {
48
+ expect(transformedConfig['testString']).toBe('transformedValue');
49
+ });
50
+ test('Number Transformation', () => {
51
+ expect(transformedConfig['testNumber']).toBe(123);
52
+ });
53
+ test('Child Object String Transformation', () => {
54
+ expect(transformedConfig['testObj']['testObjString']).toBe('transformedValue');
55
+ });
56
+ test('Child Array String Transformation', () => {
57
+ expect(transformedConfig['testArray'][0]).toBe('transformedValue');
58
+ expect(transformedConfig['testArray'][1]).toBe('transformedValue');
59
+ });
60
+ });
61
+ describe('Test transformConfigArray', () => {
62
+ const testArray = [
63
+ 'testing1',
64
+ 'testing2',
65
+ {
66
+ testingobj: 'testingobjvalue',
67
+ },
68
+ ['testingchild1', 'testingchild2'],
69
+ 123,
70
+ ];
71
+ const transformedConfig = new lib_1.MdaaConfigTransformer(new TestValueTransformer()).transformConfigArray('/', testArray);
72
+ describe('Array String Transformation', () => {
73
+ test('Array String values', () => {
74
+ expect(transformedConfig[0]).toBe('transformedValue');
75
+ expect(transformedConfig[1]).toBe('transformedValue');
76
+ });
77
+ test('Array child object values', () => {
78
+ expect(transformedConfig[2]['testingobj']).toBe('transformedValue');
79
+ });
80
+ test('Array child array values', () => {
81
+ expect(transformedConfig[3][0]).toBe('transformedValue');
82
+ expect(transformedConfig[3][1]).toBe('transformedValue');
83
+ });
84
+ test('Array number values', () => {
85
+ expect(transformedConfig[4]).toBe(123);
86
+ });
87
+ });
88
+ });
89
+ });
90
+ describe('Test MdaaConfigRefValueTransformer', () => {
91
+ // Helper function that mimics CLI encoding (copied from packages/cli/lib/utils.ts)
92
+ // This documents the encoding contract that the decoder must handle
93
+ function encodeContextValue(contextValue) {
94
+ let encodedContextValue;
95
+ if (contextValue instanceof Array) {
96
+ encodedContextValue = `"list:${JSON.stringify(contextValue)}"`;
97
+ }
98
+ else if (contextValue instanceof Object) {
99
+ encodedContextValue = `"obj:${JSON.stringify(contextValue)}"`;
100
+ }
101
+ else if (typeof contextValue === 'string') {
102
+ encodedContextValue = contextValue;
103
+ }
104
+ else if (typeof contextValue === 'boolean') {
105
+ encodedContextValue = contextValue ? 'true' : 'false';
106
+ }
107
+ else {
108
+ throw Error(`Don't know how to handle type ${contextValue}`);
109
+ }
110
+ return encodedContextValue;
111
+ }
112
+ const testContextObj = {
113
+ testingkey: 'testingobjval',
114
+ };
115
+ const testContextList = ['val1', 'val2', 'val3'];
116
+ const context = {
117
+ org: 'testorg',
118
+ domain: 'testdomain',
119
+ env: 'testenv',
120
+ module_name: 'testmodule',
121
+ test_context_obj: encodeContextValue(testContextObj),
122
+ test_context_name: 'test_context_value',
123
+ test_context_list: encodeContextValue(testContextList),
124
+ };
125
+ const testApp = new aws_cdk_lib_1.App({ context: context });
126
+ const testStack = new aws_cdk_lib_1.Stack(testApp, 'testStack');
127
+ const namingProps = {
128
+ cdkNode: new aws_cdk_lib_1.App().node,
129
+ org: 'test-org',
130
+ env: 'test-env',
131
+ domain: 'test-domain',
132
+ moduleName: 'test-module',
133
+ };
134
+ const naming = new naming_1.MdaaDefaultResourceNaming(namingProps);
135
+ const transformerProps = {
136
+ naming: naming,
137
+ org: 'testorg',
138
+ domain: 'testdomain',
139
+ env: 'testenv',
140
+ module_name: 'testmodule',
141
+ scope: testStack,
142
+ };
143
+ const serviceCatalogConfig = {
144
+ portfolio_arn: 'dummy-portfolio-arn',
145
+ portfolio_bucket_name: 'test-bucket',
146
+ owner: 'owner',
147
+ name: 'test product name',
148
+ launch_role_name: 'dummy-launch-role',
149
+ parameters: {
150
+ number_param: {
151
+ props: {
152
+ type: 'Number',
153
+ description: 'Sample number parameter',
154
+ default: 10,
155
+ },
156
+ },
157
+ string_param: {
158
+ props: {
159
+ type: 'String',
160
+ description: 'Sample string parameter',
161
+ default: 'default_string',
162
+ },
163
+ },
164
+ list_param: {
165
+ props: {
166
+ type: 'CommaDelimitedList',
167
+ description: 'Sample list parameter',
168
+ default: 'sample,list,of,strings',
169
+ },
170
+ },
171
+ },
172
+ };
173
+ test('Nested', () => {
174
+ const transformedValue = new lib_1.MdaaConfigRefValueTransformer(transformerProps).transformValue('testing{{resolve:ssm:/{{org}}/{{domain}}/{{env}}/{{module_name}}}}testing');
175
+ expect(transformedValue).toMatch(/testing\${Token\[TOKEN.\d+]}testing/);
176
+ });
177
+ test('MultiRef', () => {
178
+ const transformedValue = new lib_1.MdaaConfigRefValueTransformer(transformerProps).transformValue('multi-{{org}}-{{domain}}-{{env}}');
179
+ expect(transformedValue).toBe('multi-testorg-testdomain-testenv');
180
+ });
181
+ test('No Ref', () => {
182
+ const transformedValue = new lib_1.MdaaConfigRefValueTransformer(transformerProps).transformValue('noref');
183
+ expect(transformedValue).toBe('noref');
184
+ });
185
+ test('Env Var', () => {
186
+ process.env['TEST_VAR'] = 'testval';
187
+ const transformedValue = new lib_1.MdaaConfigRefValueTransformer(transformerProps).transformValue('{{env_var:TEST_VAR}}');
188
+ expect(transformedValue).toBe('testval');
189
+ });
190
+ test('MissingContext', () => {
191
+ expect(() => new lib_1.MdaaConfigRefValueTransformer(transformerProps).transformValue('{{context:missing}}')).toThrow();
192
+ });
193
+ test('Context Obj - Naked Reference', () => {
194
+ const transformedValue = new lib_1.MdaaConfigRefValueTransformer(transformerProps).transformValue('{{context:test_context_obj}}');
195
+ // Naked reference should return the actual object
196
+ expect(transformedValue).toEqual(testContextObj);
197
+ });
198
+ test('Context Obj - Embedded Reference Should Error', () => {
199
+ // Embedding an object in a string should throw an error
200
+ expect(() => {
201
+ new lib_1.MdaaConfigRefValueTransformer(transformerProps).transformValue('prefix-{{context:test_context_obj}}');
202
+ }).toThrow(/Cannot embed array or object context value in string/);
203
+ });
204
+ test('Context List - Naked Reference', () => {
205
+ const transformedValue = new lib_1.MdaaConfigRefValueTransformer(transformerProps).transformValue('{{context:test_context_list}}');
206
+ // Naked reference should return the actual array
207
+ expect(transformedValue).toEqual(testContextList);
208
+ });
209
+ test('Context List - Embedded Reference Should Error', () => {
210
+ // Embedding an array in a string should throw an error
211
+ expect(() => {
212
+ new lib_1.MdaaConfigRefValueTransformer(transformerProps).transformValue('prefix-{{context:test_context_list}}');
213
+ }).toThrow(/Cannot embed array or object context value in string/);
214
+ });
215
+ test('Resolve ssm ref', () => {
216
+ const transformedValue = new lib_1.MdaaConfigRefValueTransformer(transformerProps).transformValue('testing{{resolve:ssm:/test/param/path}}testing');
217
+ expect(transformedValue).toMatch(/testing\${Token\[TOKEN.\d+]}testing/);
218
+ });
219
+ test('Resolve ssm non ref', () => {
220
+ const transformedValue = new lib_1.MdaaConfigRefValueTransformer(transformerProps).transformValue('testing{{resolve:nonssm}}testing');
221
+ expect(transformedValue).toBe('testing{{resolve:nonssm}}testing');
222
+ });
223
+ test('Context', () => {
224
+ const transformedValue = new lib_1.MdaaConfigRefValueTransformer(transformerProps).transformValue('testing{{context:test_context_name}}testing');
225
+ expect(transformedValue).toBe('testingtest_context_valuetesting');
226
+ });
227
+ test('ContextOrg', () => {
228
+ const transformedValue = new lib_1.MdaaConfigRefValueTransformer(transformerProps).transformValue('testing{{context:org}}testing');
229
+ expect(transformedValue).toBe('testingtestorgtesting');
230
+ });
231
+ test('OrgRef', () => {
232
+ const transformedValue = new lib_1.MdaaConfigRefValueTransformer(transformerProps).transformValue('{{org}}');
233
+ expect(transformedValue).toBe('testorg');
234
+ });
235
+ const paramTransformerProps = {
236
+ ...transformerProps,
237
+ paramProps: Object.fromEntries(Object.entries(serviceCatalogConfig.parameters || {}).map(([paramName, props]) => {
238
+ return [paramName, props.props];
239
+ })),
240
+ };
241
+ test('Param', () => {
242
+ const transformedValue = new lib_1.MdaaConfigParamRefValueTransformer(paramTransformerProps).transformValue('{{param:paramname}}');
243
+ expect(transformedValue).toMatch(/\${Token\[TOKEN.\d+]}/);
244
+ });
245
+ test('ParamNotInServiceCatalogConfig', () => {
246
+ const transformedValue = new lib_1.MdaaConfigParamRefValueTransformer(paramTransformerProps).transformValue('{{param:parameter_not_in_sc_config}}');
247
+ expect(transformedValue).toMatch(/\${Token\[TOKEN.\d+]}/);
248
+ });
249
+ test('StringParamInServiceCatalogConfig', () => {
250
+ const transformedValue = new lib_1.MdaaConfigParamRefValueTransformer(paramTransformerProps).transformValue('{{param:string_param}}');
251
+ expect(transformedValue).toMatch(/\${Token\[TOKEN.\d+]}/);
252
+ });
253
+ test('NumberParamInServiceCatalogConfig', () => {
254
+ const transformedValue = new lib_1.MdaaConfigParamRefValueTransformer(paramTransformerProps).transformValue('{{param:number_param}}');
255
+ expect(typeof transformedValue).toBe('number');
256
+ });
257
+ test('ListParamInServiceCatalogConfig', () => {
258
+ const transformedValue = new lib_1.MdaaConfigParamRefValueTransformer(paramTransformerProps).transformValue('{{param:list_param}}');
259
+ expect(transformedValue).toMatch(/#{Token\[TOKEN.\d+]}/);
260
+ });
261
+ test('StringParamAnnotation', () => {
262
+ const transformedValue = new lib_1.MdaaConfigParamRefValueTransformer(paramTransformerProps).transformValue('{{param:string:string_param}}');
263
+ expect(transformedValue).toMatch(/\${Token\[TOKEN.\d+]}/);
264
+ });
265
+ test('NumberParamAnnotation', () => {
266
+ const transformedValue = new lib_1.MdaaConfigParamRefValueTransformer(paramTransformerProps).transformValue('{{param:number:number_param}}');
267
+ expect(typeof transformedValue).toBe('number');
268
+ });
269
+ test('ListParamAnnotation', () => {
270
+ const transformedValue = new lib_1.MdaaConfigParamRefValueTransformer(paramTransformerProps).transformValue('{{param:list:list_param}}');
271
+ expect(transformedValue).toMatch(/#{Token\[TOKEN.\d+]}/);
272
+ });
273
+ test('PrefixedNumberParam', () => {
274
+ const transformedValue = new lib_1.MdaaConfigParamRefValueTransformer(paramTransformerProps).transformValue('testing{{param:number:number_param}}');
275
+ expect(transformedValue).toMatch(/^testing-\d+(\.\d+)?(e\+\d+)?$/);
276
+ });
277
+ test('PrefixedListParam', () => {
278
+ const transformedValue = new lib_1.MdaaConfigParamRefValueTransformer(paramTransformerProps).transformValue('testing{{param:list:list_param}}');
279
+ expect(transformedValue).toMatch(/testing#{Token\[TOKEN.\d+]}/);
280
+ });
281
+ test('NestedResolutionWithinNumberParam', () => {
282
+ const transformedValue = new lib_1.MdaaConfigParamRefValueTransformer(paramTransformerProps).transformValue('{{param:number:{{org}}_param}}');
283
+ expect(typeof transformedValue).toBe('number');
284
+ });
285
+ test('Partition', () => {
286
+ const transformedValue = new lib_1.MdaaConfigRefValueTransformer(transformerProps).transformValue('{{partition}}');
287
+ expect(transformedValue).toMatch(/\${Token\[AWS.Partition.\d+]}/);
288
+ });
289
+ test('Region', () => {
290
+ const transformedValue = new lib_1.MdaaConfigRefValueTransformer(transformerProps).transformValue('{{region}}');
291
+ expect(transformedValue).toMatch(/\${Token\[AWS.Region.\d+]}/);
292
+ });
293
+ test('Account', () => {
294
+ const transformedValue = new lib_1.MdaaConfigRefValueTransformer(transformerProps).transformValue('{{account}}');
295
+ expect(transformedValue).toMatch(/\${Token\[AWS.AccountId.\d+]}/);
296
+ });
297
+ test('Module Name', () => {
298
+ const transformedValue = new lib_1.MdaaConfigRefValueTransformer(transformerProps).transformValue('{{module_name}}');
299
+ expect(transformedValue).toBe('testmodule');
300
+ });
301
+ // Additional test cases for better coverage
302
+ test('Naked SSM Reference', () => {
303
+ const transformedValue = new lib_1.MdaaConfigRefValueTransformer(transformerProps).transformValue('{{resolve:ssm:/test/param/path}}');
304
+ expect(transformedValue).toMatch(/\${Token\[TOKEN.\d+]}/);
305
+ });
306
+ test('Naked Env Var', () => {
307
+ process.env['NAKED_TEST_VAR'] = 'naked_testval';
308
+ const transformedValue = new lib_1.MdaaConfigRefValueTransformer(transformerProps).transformValue('{{env_var:NAKED_TEST_VAR}}');
309
+ expect(transformedValue).toBe('naked_testval');
310
+ });
311
+ test('Missing Env Var - Embedded', () => {
312
+ delete process.env['MISSING_VAR'];
313
+ const transformedValue = new lib_1.MdaaConfigRefValueTransformer(transformerProps).transformValue('prefix-{{env_var:MISSING_VAR}}-suffix');
314
+ // Should leave the reference as-is when env var is undefined
315
+ expect(transformedValue).toBe('prefix-{{env_var:MISSING_VAR}}-suffix');
316
+ });
317
+ test('Missing Env Var - Naked Reference', () => {
318
+ delete process.env['MISSING_VAR_NAKED'];
319
+ const transformedValue = new lib_1.MdaaConfigRefValueTransformer(transformerProps).transformValue('{{env_var:MISSING_VAR_NAKED}}');
320
+ // Should return the original string for naked reference with undefined env var
321
+ expect(transformedValue).toBe('{{env_var:MISSING_VAR_NAKED}}');
322
+ });
323
+ test('Nested Context Array in SSM Path Should Error', () => {
324
+ expect(() => {
325
+ new lib_1.MdaaConfigRefValueTransformer(transformerProps).transformValue('{{resolve:ssm:/{{context:test_context_list}}/path}}');
326
+ }).toThrow(/Cannot embed array or object context value in string/);
327
+ });
328
+ test('Nested Context Object in String Should Error', () => {
329
+ expect(() => {
330
+ new lib_1.MdaaConfigRefValueTransformer(transformerProps).transformValue('prefix-{{resolve:ssm:/{{context:test_context_obj}}/path}}');
331
+ }).toThrow(/Cannot embed array or object context value in string/);
332
+ });
333
+ test('Boolean Context Value', () => {
334
+ const contextWithBool = {
335
+ ...context,
336
+ bool_value: 'true', // Encoded as string
337
+ };
338
+ const appWithBool = new aws_cdk_lib_1.App({ context: contextWithBool });
339
+ const stackWithBool = new aws_cdk_lib_1.Stack(appWithBool, 'testStackBool');
340
+ const propsWithBool = { ...transformerProps, scope: stackWithBool };
341
+ const transformedValue = new lib_1.MdaaConfigRefValueTransformer(propsWithBool).transformValue('{{context:bool_value}}');
342
+ expect(transformedValue).toBe('true');
343
+ });
344
+ test('Nested Object Context', () => {
345
+ const nestedObj = {
346
+ outer: {
347
+ inner: 'value',
348
+ },
349
+ };
350
+ const contextWithNested = {
351
+ ...context,
352
+ nested_obj: encodeContextValue(nestedObj),
353
+ };
354
+ const appWithNested = new aws_cdk_lib_1.App({ context: contextWithNested });
355
+ const stackWithNested = new aws_cdk_lib_1.Stack(appWithNested, 'testStackNested');
356
+ const propsWithNested = { ...transformerProps, scope: stackWithNested };
357
+ const transformedValue = new lib_1.MdaaConfigRefValueTransformer(propsWithNested).transformValue('{{context:nested_obj}}');
358
+ expect(transformedValue).toEqual(nestedObj);
359
+ });
360
+ test('Array with Mixed Types Context', () => {
361
+ const mixedArray = ['string', 123, true, { key: 'value' }];
362
+ const contextWithMixed = {
363
+ ...context,
364
+ mixed_array: encodeContextValue(mixedArray),
365
+ };
366
+ const appWithMixed = new aws_cdk_lib_1.App({ context: contextWithMixed });
367
+ const stackWithMixed = new aws_cdk_lib_1.Stack(appWithMixed, 'testStackMixed');
368
+ const propsWithMixed = { ...transformerProps, scope: stackWithMixed };
369
+ const transformedValue = new lib_1.MdaaConfigRefValueTransformer(propsWithMixed).transformValue('{{context:mixed_array}}');
370
+ expect(transformedValue).toEqual(mixedArray);
371
+ });
372
+ });
373
+ describe('Test MdaaConfigSSMValueTransformer', () => {
374
+ test('Non ssm:', () => {
375
+ const transformedValue = new lib_1.MdaaConfigSSMValueTransformer().transformValue('testvalue', 'testPath');
376
+ expect(transformedValue).toBe('testvalue');
377
+ });
378
+ test('Naked ssm:', () => {
379
+ const transformedValue = new lib_1.MdaaConfigSSMValueTransformer().transformValue('ssm:testSSMParamPath', 'testPath');
380
+ expect(transformedValue).toBe('{{resolve:ssm:testSSMParamPath}}');
381
+ });
382
+ test('Ignored SSM: Action', () => {
383
+ const transformedValue = new lib_1.MdaaConfigSSMValueTransformer().transformValue('ssm:GetParameter', 'policyDocument/Statement/Action');
384
+ expect(transformedValue).toBe('ssm:GetParameter');
385
+ });
386
+ });
387
+ describe('Test ConfigConfigPathValueTransformer', () => {
388
+ test('Non relative', () => {
389
+ const transformedValue = new lib_1.ConfigConfigPathValueTransformer('testBaseDir').transformValue('testNonRelative');
390
+ expect(transformedValue).toBe('testNonRelative');
391
+ });
392
+ test('Relative', () => {
393
+ const transformedValue = new lib_1.ConfigConfigPathValueTransformer('testBaseDir').transformValue('./relative');
394
+ expect(transformedValue).toBe(path.resolve('./relative'.replace(/^\./, 'testBaseDir')));
395
+ });
396
+ test('Parent Relative', () => {
397
+ const transformedValue = new lib_1.ConfigConfigPathValueTransformer('testBaseDir').transformValue('../relative-parent');
398
+ expect(transformedValue).toBe(path.resolve('./relative-parent'));
399
+ });
400
+ test('Parent Sub folder Relative', () => {
401
+ const transformedValue = new lib_1.ConfigConfigPathValueTransformer('testBaseDir').transformValue('../app/code');
402
+ expect(transformedValue).toBe(path.resolve('./app/code'));
403
+ });
404
+ test('Grandparent folder Relative', () => {
405
+ const transformedValue = new lib_1.ConfigConfigPathValueTransformer('testBaseDir').transformValue('../../mdaa-naming');
406
+ expect(transformedValue).toBe(path.resolve('../mdaa-naming'));
407
+ });
408
+ });
409
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZmlnLnRlc3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJjb25maWcudGVzdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7OztHQUdHOztBQUVILDZDQUF5QztBQUN6QyxZQUFZO0FBQ1osNkJBQTZCO0FBQzdCLGdDQVdnQjtBQUNoQixtQ0FBbUM7QUFDbkMsNkNBQXVGO0FBRXZGLE1BQU0sa0JBQWtCO0lBQ2YsY0FBYyxDQUFDLEtBQWEsRUFBRSxXQUFnQztRQUNuRSxPQUFPLENBQUMsR0FBRyxDQUFDLGdCQUFnQixXQUFXLElBQUksS0FBSyx3QkFBd0IsQ0FBQyxDQUFDO1FBQzFFLE9BQU8sZ0JBQWdCLENBQUM7SUFDMUIsQ0FBQztDQUNGO0FBRUQsTUFBTSxvQkFBb0I7SUFDakIsY0FBYyxDQUFDLEtBQWEsRUFBRSxXQUFnQztRQUNuRSxPQUFPLENBQUMsR0FBRyxDQUFDLGdCQUFnQixXQUFXLElBQUksS0FBSyx3QkFBd0IsQ0FBQyxDQUFDO1FBQzFFLE9BQU8sa0JBQWtCLENBQUM7SUFDNUIsQ0FBQztDQUNGO0FBQ0QsUUFBUSxDQUFDLCtCQUErQixFQUFFLEdBQUcsRUFBRTtJQUM3QyxRQUFRLENBQUMsNEJBQTRCLEVBQUUsR0FBRyxFQUFFO1FBQzFDLE1BQU0sYUFBYSxHQUFHO1lBQ3BCLFVBQVUsRUFBRSxTQUFTO1NBQ3RCLENBQUM7UUFDRixNQUFNLGlCQUFpQixHQUFHLElBQUksMkJBQXFCLENBQ2pELElBQUksb0JBQW9CLEVBQUUsRUFDMUIsSUFBSSxrQkFBa0IsRUFBRSxDQUN6QixDQUFDLGVBQWUsQ0FBQyxhQUFhLENBQUMsQ0FBQztRQUVqQyxJQUFJLENBQUMsdUJBQXVCLEVBQUUsR0FBRyxFQUFFO1lBQ2pDLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLGtCQUFrQixDQUFDLENBQUM7UUFDdkUsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztB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LENBQUM7SUFDMUYsQ0FBQyxDQUFDLENBQUM7SUFFSCxJQUFJLENBQUMsaUJBQWlCLEVBQUUsR0FBRyxFQUFFO1FBQzNCLE1BQU0sZ0JBQWdCLEdBQUcsSUFBSSxzQ0FBZ0MsQ0FBQyxhQUFhLENBQUMsQ0FBQyxjQUFjLENBQUMsb0JBQW9CLENBQUMsQ0FBQztRQUNsSCxNQUFNLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDLENBQUM7SUFDbkUsQ0FBQyxDQUFDLENBQUM7SUFFSCxJQUFJLENBQUMsNEJBQTRCLEVBQUUsR0FBRyxFQUFFO1FBQ3RDLE1BQU0sZ0JBQWdCLEdBQUcsSUFBSSxzQ0FBZ0MsQ0FBQyxhQUFhLENBQUMsQ0FBQyxjQUFjLENBQUMsYUFBYSxDQUFDLENBQUM7UUFDM0csTUFBTSxDQUFDLGdCQUFnQixDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQztJQUM1RCxDQUFDLENBQUMsQ0FBQztJQUVILElBQUksQ0FBQyw2QkFBNkIsRUFBRSxHQUFHLEVBQUU7UUFDdkMsTUFBTSxnQkFBZ0IsR0FBRyxJQUFJLHNDQUFnQyxDQUFDLGFBQWEsQ0FBQyxDQUFDLGNBQWMsQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO1FBQ2pILE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLGdCQUFnQixDQUFDLENBQUMsQ0FBQztJQUNoRSxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyohXG4gKiBDb3B5cmlnaHQgQW1hem9uLmNvbSwgSW5jLiBvciBpdHMgYWZmaWxpYXRlcy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG4gKi9cblxuaW1wb3J0IHsgQXBwLCBTdGFjayB9IGZyb20gJ2F3cy1jZGstbGliJztcbi8vIG5vc2VtZ3JlcFxuaW1wb3J0ICogYXMgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCB7XG4gIE1kYWFDb25maWdSZWZWYWx1ZVRyYW5zZm9ybWVyLFxuICBNZGFhQ29uZmlnU1NNVmFsdWVUcmFuc2Zvcm1lcixcbiAgTWRhYUNvbmZpZ1RyYW5zZm9ybWVyLFxuICBDb25maWdDb25maWdQYXRoVmFsdWVUcmFuc2Zvcm1lcixcbiAgTWRhYVNlcnZpY2VDYXRhbG9nUHJvZHVjdENvbmZpZyxcbiAgSU1kYWFDb25maWdWYWx1ZVRyYW5zZm9ybWVyLFxuICBNZGFhQ29uZmlnUGFyYW1SZWZWYWx1ZVRyYW5zZm9ybWVyLFxuICBNZGFhQ29uZmlnUmVmVmFsdWVUcmFuc2Zvcm1lclByb3BzLFxuICBNZGFhQ29uZmlnUGFyYW1SZWZWYWx1ZVRyYW5zZm9ybWVyUHJvcHMsXG4gIENvbmZpZ3VyYXRpb25FbGVtZW50LFxufSBmcm9tICcuLi9saWInO1xuaW1wb3J0ICogYXMgY29uc29sZSBmcm9tICdjb25zb2xlJztcbmltcG9ydCB7IE1kYWFEZWZhdWx0UmVzb3VyY2VOYW1pbmcsIE1kYWFSZXNvdXJjZU5hbWluZ0NvbmZpZyB9IGZyb20gJ0Bhd3MtbWRhYS9uYW1pbmcnO1xuXG5jbGFzcyBUZXN0S2V5VHJhbnNmb3JtZXIgaW1wbGVtZW50cyBJTWRhYUNvbmZpZ1ZhbHVlVHJhbnNmb3JtZXIge1xuICBwdWJsaWMgdHJhbnNmb3JtVmFsdWUodmFsdWU6IHN0cmluZywgY29udGV4dFBhdGg/OiBzdHJpbmcgfCB1bmRlZmluZWQpOiBzdHJpbmcge1xuICAgIGNvbnNvbGUubG9nKGBUcmFuc2Zvcm1pbmcgJHtjb250ZXh0UGF0aH06JHt2YWx1ZX0gLT4gXCJ0cmFuc2Zvcm1lZFZhbHVlXCJgKTtcbiAgICByZXR1cm4gJ3RyYW5zZm9ybWVkS2V5JztcbiAgfVxufVxuXG5jbGFzcyBUZXN0VmFsdWVUcmFuc2Zvcm1lciBpbXBsZW1lbnRzIElNZGFhQ29uZmlnVmFsdWVUcmFuc2Zvcm1lciB7XG4gIHB1YmxpYyB0cmFuc2Zvcm1WYWx1ZSh2YWx1ZTogc3RyaW5nLCBjb250ZXh0UGF0aD86IHN0cmluZyB8IHVuZGVmaW5lZCk6IHN0cmluZyB7XG4gICAgY29uc29sZS5sb2coYFRyYW5zZm9ybWluZyAke2NvbnRleHRQYXRofToke3ZhbHVlfSAtPiBcInRyYW5zZm9ybWVkVmFsdWVcImApO1xuICAgIHJldHVybiAndHJhbnNmb3JtZWRWYWx1ZSc7XG4gIH1cbn1cbmRlc2NyaWJlKCdUZXN0IE1kYWFDb25maWdLZXlUcmFuc2Zvcm1lcicsICgpID0+IHtcbiAgZGVzY3JpYmUoJ1Rlc3QgdHJhbnNmb3JtQ29uZmlnT2JqZWN0JywgKCkgPT4ge1xuICAgIGNvbnN0IHRlc3RDb25maWdPYmogPSB7XG4gICAgICB0ZXN0U3RyaW5nOiAndGVzdGluZycsXG4gICAgfTtcbiAgICBjb25zdCB0cmFuc2Zvcm1lZENvbmZpZyA9IG5ldyBNZGFhQ29uZmlnVHJhbnNmb3JtZXIoXG4gICAgICBuZXcgVGVzdFZhbHVlVHJhbnNmb3JtZXIoKSxcbiAgICAgIG5ldyBUZXN0S2V5VHJhbnNmb3JtZXIoKSxcbiAgICApLnRyYW5zZm9ybUNvbmZpZyh0ZXN0Q29uZmlnT2JqKTtcblxuICAgIHRlc3QoJ1N0cmluZyBUcmFuc2Zvcm1hdGlvbicsICgpID0+IHtcbiAgICAgIGV4cGVjdCh0cmFuc2Zvcm1lZENvbmZpZ1sndHJhbnNmb3JtZWRLZXknXSkudG9CZSgndHJhbnNmb3JtZWRWYWx1ZScpO1xuICAgIH0pO1xuICB9KTtcbn0pO1xuZGVzY3JpYmUoJ1Rlc3QgTWRhYUNvbmZpZ1ZhbHVlVHJhbnNmb3JtZXInLCAoKSA9PiB7XG4gIGRlc2NyaWJlKCdUZXN0IHRyYW5zZm9ybUNvbmZpZ09iamVjdCcsICgpID0+IHtcbiAgICBjb25zdCB0ZXN0Q29uZmlnT2JqID0ge1xuICAgICAgdGVzdFN0cmluZzogJ3Rlc3RpbmcnLFxuICAgICAgdGVzdE51bWJlcjogMTIzLFxuICAgICAgdGVzdE9iajoge1xuICAgICAgICB0ZXN0T2JqU3RyaW5nOiAndGVzdGluZycsXG4gICAgICB9LFxuICAgICAgdGVzdEFycmF5OiBbJ3Rlc3RpbmcxJywgJ3Rlc3RpbmcyJ10sXG4gICAgfTtcbiAgICBjb25zdCB0cmFuc2Zvcm1lZENvbmZpZyA9IG5ldyBNZGFhQ29uZmlnVHJhbnNmb3JtZXIobmV3IFRlc3RWYWx1ZVRyYW5zZm9ybWVyKCkpLnRyYW5zZm9ybUNvbmZpZyh0ZXN0Q29uZmlnT2JqKTtcblxuICAgIHRlc3QoJ1N0cmluZyBUcmFuc2Zvcm1hdGlvbicsICgpID0+IHtcbiAgICAgIGV4cGVjdCh0cmFuc2Zvcm1lZENvbmZpZ1sndGVzdFN0cmluZyddKS50b0JlKCd0cmFuc2Zvcm1lZFZhbHVlJyk7XG4gICAgfSk7XG4gICAgdGVzdCgnTnVtYmVyIFRyYW5zZm9ybWF0aW9uJywgKCkgPT4ge1xuICAgICAgZXhwZWN0KHRyYW5zZm9ybWVkQ29uZmlnWyd0ZXN0TnVtYmVyJ10pLnRvQmUoMTIzKTtcbiAgICB9KTtcbiAgICB0ZXN0KCdDaGlsZCBPYmplY3QgU3RyaW5nIFRyYW5zZm9ybWF0aW9uJywgKCkgPT4ge1xuICAgICAgZXhwZWN0KCh0cmFuc2Zvcm1lZENvbmZpZ1sndGVzdE9iaiddIGFzIENvbmZpZ3VyYXRpb25FbGVtZW50KVsndGVzdE9ialN0cmluZyddKS50b0JlKCd0cmFuc2Zvcm1lZFZhbHVlJyk7XG4gICAgfSk7XG4gICAgdGVzdCgnQ2hpbGQgQXJyYXkgU3RyaW5nIFRyYW5zZm9ybWF0aW9uJywgKCkgPT4ge1xuICAgICAgZXhwZWN0KCh0cmFuc2Zvcm1lZENvbmZpZ1sndGVzdEFycmF5J10gYXMgdW5rbm93bltdKVswXSkudG9CZSgndHJhbnNmb3JtZWRWYWx1ZScpO1xuICAgICAgZXhwZWN0KCh0cmFuc2Zvcm1lZENvbmZpZ1sndGVzdEFycmF5J10gYXMgdW5rbm93bltdKVsxXSkudG9CZSgndHJhbnNmb3JtZWRWYWx1ZScpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnVGVzdCB0cmFuc2Zvcm1Db25maWdBcnJheScsICgpID0+IHtcbiAgICBjb25zdCB0ZXN0QXJyYXkgPSBbXG4gICAgICAndGVzdGluZzEnLFxuICAgICAgJ3Rlc3RpbmcyJyxcbiAgICAgIHtcbiAgICAgICAgdGVzdGluZ29iajogJ3Rlc3RpbmdvYmp2YWx1ZScsXG4gICAgICB9LFxuICAgICAgWyd0ZXN0aW5nY2hpbGQxJywgJ3Rlc3RpbmdjaGlsZDInXSxcbiAgICAgIDEyMyxcbiAgICBdO1xuICAgIGNvbnN0IHRyYW5zZm9ybWVkQ29uZmlnID0gbmV3IE1kYWFDb25maWdUcmFuc2Zvcm1lcihuZXcgVGVzdFZhbHVlVHJhbnNmb3JtZXIoKSkudHJhbnNmb3JtQ29uZmlnQXJyYXkoXG4gICAgICAnLycsXG4gICAgICB0ZXN0QXJyYXksXG4gICAgKTtcbiAgICBkZXNjcmliZSgnQXJyYXkgU3RyaW5nIFRyYW5zZm9ybWF0aW9uJywgKCkgPT4ge1xuICAgICAgdGVzdCgnQXJyYXkgU3RyaW5nIHZhbHVlcycsICgpID0+IHtcbiAgICAgICAgZXhwZWN0KHRyYW5zZm9ybWVkQ29uZmlnWzBdKS50b0JlKCd0cmFuc2Zvcm1lZFZhbHVlJyk7XG4gICAgICAgIGV4cGVjdCh0cmFuc2Zvcm1lZENvbmZpZ1sxXSkudG9CZSgndHJhbnNmb3JtZWRWYWx1ZScpO1xuICAgICAgfSk7XG4gICAgICB0ZXN0KCdBcnJheSBjaGlsZCBvYmplY3QgdmFsdWVzJywgKCkgPT4ge1xuICAgICAgICBleHBlY3QoKHRyYW5zZm9ybWVkQ29uZmlnWzJdIGFzIENvbmZpZ3VyYXRpb25FbGVtZW50KVsndGVzdGluZ29iaiddKS50b0JlKCd0cmFuc2Zvcm1lZFZhbHVlJyk7XG4gICAgICB9KTtcbiAgICAgIHRlc3QoJ0FycmF5IGNoaWxkIGFycmF5IHZhbHVlcycsICgpID0+IHtcbiAgICAgICAgZXhwZWN0KCh0cmFuc2Zvcm1lZENvbmZpZ1szXSBhcyBDb25maWd1cmF0aW9uRWxlbWVudClbMF0pLnRvQmUoJ3RyYW5zZm9ybWVkVmFsdWUnKTtcbiAgICAgICAgZXhwZWN0KCh0cmFuc2Zvcm1lZENvbmZpZ1szXSBhcyBDb25maWd1cmF0aW9uRWxlbWVudClbMV0pLnRvQmUoJ3RyYW5zZm9ybWVkVmFsdWUnKTtcbiAgICAgIH0pO1xuICAgICAgdGVzdCgnQXJyYXkgbnVtYmVyIHZhbHVlcycsICgpID0+IHtcbiAgICAgICAgZXhwZWN0KHRyYW5zZm9ybWVkQ29uZmlnWzRdKS50b0JlKDEyMyk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfSk7XG59KTtcbmRlc2NyaWJlKCdUZXN0IE1kYWFDb25maWdSZWZWYWx1ZVRyYW5zZm9ybWVyJywgKCkgPT4ge1xuICAvLyBIZWxwZXIgZnVuY3Rpb24gdGhhdCBtaW1pY3MgQ0xJIGVuY29kaW5nIChjb3BpZWQgZnJvbSBwYWNrYWdlcy9jbGkvbGliL3V0aWxzLnRzKVxuICAvLyBUaGlzIGRvY3VtZW50cyB0aGUgZW5jb2RpbmcgY29udHJhY3QgdGhhdCB0aGUgZGVjb2RlciBtdXN0IGhhbmRsZVxuICBmdW5jdGlvbiBlbmNvZGVDb250ZXh0VmFsdWUoY29udGV4dFZhbHVlOiB1bmtub3duKTogc3RyaW5nIHtcbiAgICBsZXQgZW5jb2RlZENvbnRleHRWYWx1ZTogc3RyaW5nO1xuICAgIGlmIChjb250ZXh0VmFsdWUgaW5zdGFuY2VvZiBBcnJheSkge1xuICAgICAgZW5jb2RlZENvbnRleHRWYWx1ZSA9IGBcImxpc3Q6JHtKU09OLnN0cmluZ2lmeShjb250ZXh0VmFsdWUpfVwiYDtcbiAgICB9IGVsc2UgaWYgKGNvbnRleHRWYWx1ZSBpbnN0YW5jZW9mIE9iamVjdCkge1xuICAgICAgZW5jb2RlZENvbnRleHRWYWx1ZSA9IGBcIm9iajoke0pTT04uc3RyaW5naWZ5KGNvbnRleHRWYWx1ZSl9XCJgO1xuICAgIH0gZWxzZSBpZiAodHlwZW9mIGNvbnRleHRWYWx1ZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIGVuY29kZWRDb250ZXh0VmFsdWUgPSBjb250ZXh0VmFsdWU7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgY29udGV4dFZhbHVlID09PSAnYm9vbGVhbicpIHtcbiAgICAgIGVuY29kZWRDb250ZXh0VmFsdWUgPSBjb250ZXh0VmFsdWUgPyAndHJ1ZScgOiAnZmFsc2UnO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBFcnJvcihgRG9uJ3Qga25vdyBob3cgdG8gaGFuZGxlIHR5cGUgJHtjb250ZXh0VmFsdWV9YCk7XG4gICAgfVxuICAgIHJldHVybiBlbmNvZGVkQ29udGV4dFZhbHVlO1xuICB9XG5cbiAgY29uc3QgdGVzdENvbnRleHRPYmogPSB7XG4gICAgdGVzdGluZ2tleTogJ3Rlc3RpbmdvYmp2YWwnLFxuICB9O1xuICBjb25zdCB0ZXN0Q29udGV4dExpc3QgPSBbJ3ZhbDEnLCAndmFsMicsICd2YWwzJ107XG4gIGNvbnN0IGNvbnRleHQgPSB7XG4gICAgb3JnOiAndGVzdG9yZycsXG4gICAgZG9tYWluOiAndGVzdGRvbWFpbicsXG4gICAgZW52OiAndGVzdGVudicsXG4gICAgbW9kdWxlX25hbWU6ICd0ZXN0bW9kdWxlJyxcbiAgICB0ZXN0X2NvbnRleHRfb2JqOiBlbmNvZGVDb250ZXh0VmFsdWUodGVzdENvbnRleHRPYmopLFxuICAgIHRlc3RfY29udGV4dF9uYW1lOiAndGVzdF9jb250ZXh0X3ZhbHVlJyxcbiAgICB0ZXN0X2NvbnRleHRfbGlzdDogZW5jb2RlQ29udGV4dFZhbHVlKHRlc3RDb250ZXh0TGlzdCksXG4gIH07XG4gIGNvbnN0IHRlc3RBcHAgPSBuZXcgQXBwKHsgY29udGV4dDogY29udGV4dCB9KTtcbiAgY29uc3QgdGVzdFN0YWNrID0gbmV3IFN0YWNrKHRlc3RBcHAsICd0ZXN0U3RhY2snKTtcbiAgY29uc3QgbmFtaW5nUHJvcHM6IE1kYWFSZXNvdXJjZU5hbWluZ0NvbmZpZyA9IHtcbiAgICBjZGtOb2RlOiBuZXcgQXBwKCkubm9kZSxcbiAgICBvcmc6ICd0ZXN0LW9yZycsXG4gICAgZW52OiAndGVzdC1lbnYnLFxuICAgIGRvbWFpbjogJ3Rlc3QtZG9tYWluJyxcbiAgICBtb2R1bGVOYW1lOiAndGVzdC1tb2R1bGUnLFxuICB9O1xuXG4gIGNvbnN0IG5hbWluZyA9IG5ldyBNZGFhRGVmYXVsdFJlc291cmNlTmFtaW5nKG5hbWluZ1Byb3BzKTtcblxuICBjb25zdCB0cmFuc2Zvcm1lclByb3BzOiBNZGFhQ29uZmlnUmVmVmFsdWVUcmFuc2Zvcm1lclByb3BzID0ge1xuICAgIG5hbWluZzogbmFtaW5nLFxuICAgIG9yZzogJ3Rlc3RvcmcnLFxuICAgIGRvbWFpbjogJ3Rlc3Rkb21haW4nLFxuICAgIGVudjogJ3Rlc3RlbnYnLFxuICAgIG1vZHVsZV9uYW1lOiAndGVzdG1vZHVsZScsXG4gICAgc2NvcGU6IHRlc3RTdGFjayxcbiAgfTtcblxuICBjb25zdCBzZXJ2aWNlQ2F0YWxvZ0NvbmZpZzogTWRhYVNlcnZpY2VDYXRhbG9nUHJvZHVjdENvbmZpZyA9IHtcbiAgICBwb3J0Zm9saW9fYXJuOiAnZHVtbXktcG9ydGZvbGlvLWFybicsXG4gICAgcG9ydGZvbGlvX2J1Y2tldF9uYW1lOiAndGVzdC1idWNrZXQnLFxuICAgIG93bmVyOiAnb3duZXInLFxuICAgIG5hbWU6ICd0ZXN0IHByb2R1Y3QgbmFtZScsXG4gICAgbGF1bmNoX3JvbGVfbmFtZTogJ2R1bW15LWxhdW5jaC1yb2xlJyxcbiAgICBwYXJhbWV0ZXJzOiB7XG4gICAgICBudW1iZXJfcGFyYW06IHtcbiAgICAgICAgcHJvcHM6IHtcbiAgICAgICAgICB0eXBlOiAnTnVtYmVyJyxcbiAgICAgICAgICBkZXNjcmlwdGlvbjogJ1NhbXBsZSBudW1iZXIgcGFyYW1ldGVyJyxcbiAgICAgICAgICBkZWZhdWx0OiAxMCxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgICBzdHJpbmdfcGFyYW06IHtcbiAgICAgICAgcHJvcHM6IHtcbiAgICAgICAgICB0eXBlOiAnU3RyaW5nJyxcbiAgICAgICAgICBkZXNjcmlwdGlvbjogJ1NhbXBsZSBzdHJpbmcgcGFyYW1ldGVyJyxcbiAgICAgICAgICBkZWZhdWx0OiAnZGVmYXVsdF9zdHJpbmcnLFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICAgIGxpc3RfcGFyYW06IHtcbiAgICAgICAgcHJvcHM6IHtcbiAgICAgICAgICB0eXBlOiAnQ29tbWFEZWxpbWl0ZWRMaXN0JyxcbiAgICAgICAgICBkZXNjcmlwdGlvbjogJ1NhbXBsZSBsaXN0IHBhcmFtZXRlcicsXG4gICAgICAgICAgZGVmYXVsdDogJ3NhbXBsZSxsaXN0LG9mLHN0cmluZ3MnLFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICB9LFxuICB9O1xuICB0ZXN0KCdOZXN0ZWQnLCAoKSA9PiB7XG4gICAgY29uc3QgdHJhbnNmb3JtZWRWYWx1ZSA9IG5ldyBNZGFhQ29uZmlnUmVmVmFsdWVUcmFuc2Zvcm1lcih0cmFuc2Zvcm1lclByb3BzKS50cmFuc2Zvcm1WYWx1ZShcbiAgICAgICd0ZXN0aW5ne3tyZXNvbHZlOnNzbTove3tvcmd9fS97e2RvbWFpbn19L3t7ZW52fX0ve3ttb2R1bGVfbmFtZX19fX10ZXN0aW5nJyxcbiAgICApO1xuICAgIGV4cGVjdCh0cmFuc2Zvcm1lZFZhbHVlKS50b01hdGNoKC90ZXN0aW5nXFwke1Rva2VuXFxbVE9LRU4uXFxkK119dGVzdGluZy8pO1xuICB9KTtcbiAgdGVzdCgnTXVsdGlSZWYnLCAoKSA9PiB7XG4gICAgY29uc3QgdHJhbnNmb3JtZWRWYWx1ZSA9IG5ldyBNZGFhQ29uZmlnUmVmVmFsdWVUcmFuc2Zvcm1lcih0cmFuc2Zvcm1lclByb3BzKS50cmFuc2Zvcm1WYWx1ZShcbiAgICAgICdtdWx0aS17e29yZ319LXt7ZG9tYWlufX0te3tlbnZ9fScsXG4gICAgKTtcbiAgICBleHBlY3QodHJhbnNmb3JtZWRWYWx1ZSkudG9CZSgnbXVsdGktdGVzdG9yZy10ZXN0ZG9tYWluLXRlc3RlbnYnKTtcbiAgfSk7XG4gIHRlc3QoJ05vIFJlZicsICgpID0+IHtcbiAgICBjb25zdCB0cmFuc2Zvcm1lZFZhbHVlID0gbmV3IE1kYWFDb25maWdSZWZWYWx1ZVRyYW5zZm9ybWVyKHRyYW5zZm9ybWVyUHJvcHMpLnRyYW5zZm9ybVZhbHVlKCdub3JlZicpO1xuICAgIGV4cGVjdCh0cmFuc2Zvcm1lZFZhbHVlKS50b0JlKCdub3JlZicpO1xuICB9KTtcblxuICB0ZXN0KCdFbnYgVmFyJywgKCkgPT4ge1xuICAgIHByb2Nlc3MuZW52WydURVNUX1ZBUiddID0gJ3Rlc3R2YWwnO1xuICAgIGNvbnN0IHRyYW5zZm9ybWVkVmFsdWUgPSBuZXcgTWRhYUNvbmZpZ1JlZlZhbHVlVHJhbnNmb3JtZXIodHJhbnNmb3JtZXJQcm9wcykudHJhbnNmb3JtVmFsdWUoJ3t7ZW52X3ZhcjpURVNUX1ZBUn19Jyk7XG4gICAgZXhwZWN0KHRyYW5zZm9ybWVkVmFsdWUpLnRvQmUoJ3Rlc3R2YWwnKTtcbiAgfSk7XG5cbiAgdGVzdCgnTWlzc2luZ0NvbnRleHQnLCAoKSA9PiB7XG4gICAgZXhwZWN0KCgpID0+IG5ldyBNZGFhQ29uZmlnUmVmVmFsdWVUcmFuc2Zvcm1lcih0cmFuc2Zvcm1lclByb3BzKS50cmFuc2Zvcm1WYWx1ZSgne3tjb250ZXh0Om1pc3Npbmd9fScpKS50b1Rocm93KCk7XG4gIH0pO1xuXG4gIHRlc3QoJ0NvbnRleHQgT2JqIC0gTmFrZWQgUmVmZXJlbmNlJywgKCkgPT4ge1xuICAgIGNvbnN0IHRyYW5zZm9ybWVkVmFsdWUgPSBuZXcgTWRhYUNvbmZpZ1JlZlZhbHVlVHJhbnNmb3JtZXIodHJhbnNmb3JtZXJQcm9wcykudHJhbnNmb3JtVmFsdWUoXG4gICAgICAne3tjb250ZXh0OnRlc3RfY29udGV4dF9vYmp9fScsXG4gICAgKTtcbiAgICAvLyBOYWtlZCByZWZlcmVuY2Ugc2hvdWxkIHJldHVybiB0aGUgYWN0dWFsIG9iamVjdFxuICAgIGV4cGVjdCh0cmFuc2Zvcm1lZFZhbHVlKS50b0VxdWFsKHRlc3RDb250ZXh0T2JqKTtcbiAgfSk7XG5cbiAgdGVzdCgnQ29udGV4dCBPYmogLSBFbWJlZGRlZCBSZWZlcmVuY2UgU2hvdWxkIEVycm9yJywgKCkgPT4ge1xuICAgIC8vIEVtYmVkZGluZyBhbiBvYmplY3QgaW4gYSBzdHJpbmcgc2hvdWxkIHRocm93IGFuIGVycm9yXG4gICAgZXhwZWN0KCgpID0+IHtcbiAgICAgIG5ldyBNZGFhQ29uZmlnUmVmVmFsdWVUcmFuc2Zvcm1lcih0cmFuc2Zvcm1lclByb3BzKS50cmFuc2Zvcm1WYWx1ZSgncHJlZml4LXt7Y29udGV4dDp0ZXN0X2NvbnRleHRfb2JqfX0nKTtcbiAgICB9KS50b1Rocm93KC9DYW5ub3QgZW1iZWQgYXJyYXkgb3Igb2JqZWN0IGNvbnRleHQgdmFsdWUgaW4gc3RyaW5nLyk7XG4gIH0pO1xuXG4gIHRlc3QoJ0NvbnRleHQgTGlzdCAtIE5ha2VkIFJlZmVyZW5jZScsICgpID0+IHtcbiAgICBjb25zdCB0cmFuc2Zvcm1lZFZhbHVlID0gbmV3IE1kYWFDb25maWdSZWZWYWx1ZVRyYW5zZm9ybWVyKHRyYW5zZm9ybWVyUHJvcHMpLnRyYW5zZm9ybVZhbHVlKFxuICAgICAgJ3t7Y29udGV4dDp0ZXN0X2NvbnRleHRfbGlzdH19JyxcbiAgICApO1xuICAgIC8vIE5ha2VkIHJlZmVyZW5jZSBzaG91bGQgcmV0dXJuIHRoZSBhY3R1YWwgYXJyYXlcbiAgICBleHBlY3QodHJhbnNmb3JtZWRWYWx1ZSkudG9FcXVhbCh0ZXN0Q29udGV4dExpc3QpO1xuICB9KTtcblxuICB0ZXN0KCdDb250ZXh0IExpc3QgLSBFbWJlZGRlZCBSZWZlcmVuY2UgU2hvdWxkIEVycm9yJywgKCkgPT4ge1xuICAgIC8vIEVtYmVkZGluZyBhbiBhcnJheSBpbiBhIHN0cmluZyBzaG91bGQgdGhyb3cgYW4gZXJyb3JcbiAgICBleHBlY3QoKCkgPT4ge1xuICAgICAgbmV3IE1kYWFDb25maWdSZWZWYWx1ZVRyYW5zZm9ybWVyKHRyYW5zZm9ybWVyUHJvcHMpLnRyYW5zZm9ybVZhbHVlKCdwcmVmaXgte3tjb250ZXh0OnRlc3RfY29udGV4dF9saXN0fX0nKTtcbiAgICB9KS50b1Rocm93KC9DYW5ub3QgZW1iZWQgYXJyYXkgb3Igb2JqZWN0IGNvbnRleHQgdmFsdWUgaW4gc3RyaW5nLyk7XG4gIH0pO1xuXG4gIHRlc3QoJ1Jlc29sdmUgc3NtIHJlZicsICgpID0+IHtcbiAgICBjb25zdCB0cmFuc2Zvcm1lZFZhbHVlID0gbmV3IE1kYWFDb25maWdSZWZWYWx1ZVRyYW5zZm9ybWVyKHRyYW5zZm9ybWVyUHJvcHMpLnRyYW5zZm9ybVZhbHVlKFxuICAgICAgJ3Rlc3Rpbmd7e3Jlc29sdmU6c3NtOi90ZXN0L3BhcmFtL3BhdGh9fXRlc3RpbmcnLFxuICAgICk7XG4gICAgZXhwZWN0KHRyYW5zZm9ybWVkVmFsdWUpLnRvTWF0Y2goL3Rlc3RpbmdcXCR7VG9rZW5cXFtUT0tFTi5cXGQrXX10ZXN0aW5nLyk7XG4gIH0pO1xuICB0ZXN0KCdSZXNvbHZlIHNzbSBub24gcmVmJywgKCkgPT4ge1xuICAgIGNvbnN0IHRyYW5zZm9ybWVkVmFsdWUgPSBuZXcgTWRhYUNvbmZpZ1JlZlZhbHVlVHJhbnNmb3JtZXIodHJhbnNmb3JtZXJQcm9wcykudHJhbnNmb3JtVmFsdWUoXG4gICAgICAndGVzdGluZ3t7cmVzb2x2ZTpub25zc219fXRlc3RpbmcnLFxuICAgICk7XG4gICAgZXhwZWN0KHRyYW5zZm9ybWVkVmFsdWUpLnRvQmUoJ3Rlc3Rpbmd7e3Jlc29sdmU6bm9uc3NtfX10ZXN0aW5nJyk7XG4gIH0pO1xuICB0ZXN0KCdDb250ZXh0JywgKCkgPT4ge1xuICAgIGNvbnN0IHRyYW5zZm9ybWVkVmFsdWUgPSBuZXcgTWRhYUNvbmZpZ1JlZlZhbHVlVHJhbnNmb3JtZXIodHJhbnNmb3JtZXJQcm9wcykudHJhbnNmb3JtVmFsdWUoXG4gICAgICAndGVzdGluZ3t7Y29udGV4dDp0ZXN0X2NvbnRleHRfbmFtZX19dGVzdGluZycsXG4gICAgKTtcbiAgICBleHBlY3QodHJhbnNmb3JtZWRWYWx1ZSkudG9CZSgndGVzdGluZ3Rlc3RfY29udGV4dF92YWx1ZXRlc3RpbmcnKTtcbiAgfSk7XG4gIHRlc3QoJ0NvbnRleHRPcmcnLCAoKSA9PiB7XG4gICAgY29uc3QgdHJhbnNmb3JtZWRWYWx1ZSA9IG5ldyBNZGFhQ29uZmlnUmVmVmFsdWVUcmFuc2Zvcm1lcih0cmFuc2Zvcm1lclByb3BzKS50cmFuc2Zvcm1WYWx1ZShcbiAgICAgICd0ZXN0aW5ne3tjb250ZXh0Om9yZ319dGVzdGluZycsXG4gICAgKTtcbiAgICBleHBlY3QodHJhbnNmb3JtZWRWYWx1ZSkudG9CZSgndGVzdGluZ3Rlc3Rvcmd0ZXN0aW5nJyk7XG4gIH0pO1xuICB0ZXN0KCdPcmdSZWYnLCAoKSA9PiB7XG4gICAgY29uc3QgdHJhbnNmb3JtZWRWYWx1ZSA9IG5ldyBNZGFhQ29uZmlnUmVmVmFsdWVUcmFuc2Zvcm1lcih0cmFuc2Zvcm1lclByb3BzKS50cmFuc2Zvcm1WYWx1ZSgne3tvcmd9fScpO1xuICAgIGV4cGVjdCh0cmFuc2Zvcm1lZFZhbHVlKS50b0JlKCd0ZXN0b3JnJyk7XG4gIH0pO1xuXG4gIGNvbnN0IHBhcmFtVHJhbnNmb3JtZXJQcm9wczogTWRhYUNvbmZpZ1BhcmFtUmVmVmFsdWVUcmFuc2Zvcm1lclByb3BzID0ge1xuICAgIC4uLnRyYW5zZm9ybWVyUHJvcHMsXG4gICAgcGFyYW1Qcm9wczogT2JqZWN0LmZyb21FbnRyaWVzKFxuICAgICAgT2JqZWN0LmVudHJpZXMoc2VydmljZUNhdGFsb2dDb25maWcucGFyYW1ldGVycyB8fCB7fSkubWFwKChbcGFyYW1OYW1lLCBwcm9wc10pID0+IHtcbiAgICAgICAgcmV0dXJuIFtwYXJhbU5hbWUsIHByb3BzLnByb3BzXTtcbiAgICAgIH0pLFxuICAgICksXG4gIH07XG4gIHRlc3QoJ1BhcmFtJywgKCkgPT4ge1xuICAgIGNvbnN0IHRyYW5zZm9ybWVkVmFsdWUgPSBuZXcgTWRhYUNvbmZpZ1BhcmFtUmVmVmFsdWVUcmFuc2Zvcm1lcihwYXJhbVRyYW5zZm9ybWVyUHJvcHMpLnRyYW5zZm9ybVZhbHVlKFxuICAgICAgJ3t7cGFyYW06cGFyYW1uYW1lfX0nLFxuICAgICk7XG4gICAgZXhwZWN0KHRyYW5zZm9ybWVkVmFsdWUpLnRvTWF0Y2goL1xcJHtUb2tlblxcW1RPS0VOLlxcZCtdfS8pO1xuICB9KTtcblxuICB0ZXN0KCdQYXJhbU5vdEluU2VydmljZUNhdGFsb2dDb25maWcnLCAoKSA9PiB7XG4gICAgY29uc3QgdHJhbnNmb3JtZWRWYWx1ZSA9IG5ldyBNZGFhQ29uZmlnUGFyYW1SZWZWYWx1ZVRyYW5zZm9ybWVyKHBhcmFtVHJhbnNmb3JtZXJQcm9wcykudHJhbnNmb3JtVmFsdWUoXG4gICAgICAne3twYXJhbTpwYXJhbWV0ZXJfbm90X2luX3NjX2NvbmZpZ319JyxcbiAgICApO1xuICAgIGV4cGVjdCh0cmFuc2Zvcm1lZFZhbHVlKS50b01hdGNoKC9cXCR7VG9rZW5cXFtUT0tFTi5cXGQrXX0vKTtcbiAgfSk7XG4gIHRlc3QoJ1N0cmluZ1BhcmFtSW5TZXJ2aWNlQ2F0YWxvZ0NvbmZpZycsICgpID0+IHtcbiAgICBjb25zdCB0cmFuc2Zvcm1lZFZhbHVlID0gbmV3IE1kYWFDb25maWdQYXJhbVJlZlZhbHVlVHJhbnNmb3JtZXIocGFyYW1UcmFuc2Zvcm1lclByb3BzKS50cmFuc2Zvcm1WYWx1ZShcbiAgICAgICd7e3BhcmFtOnN0cmluZ19wYXJhbX19JyxcbiAgICApO1xuICAgIGV4cGVjdCh0cmFuc2Zvcm1lZFZhbHVlKS50b01hdGNoKC9cXCR7VG9rZW5cXFtUT0tFTi5cXGQrXX0vKTtcbiAgfSk7XG5cbiAgdGVzdCgnTnVtYmVyUGFyYW1JblNlcnZpY2VDYXRhbG9nQ29uZmlnJywgKCkgPT4ge1xuICAgIGNvbnN0IHRyYW5zZm9ybWVkVmFsdWUgPSBuZXcgTWRhYUNvbmZpZ1BhcmFtUmVmVmFsdWVUcmFuc2Zvcm1lcihwYXJhbVRyYW5zZm9ybWVyUHJvcHMpLnRyYW5zZm9ybVZhbHVlKFxuICAgICAgJ3t7cGFyYW06bnVtYmVyX3BhcmFtfX0nLFxuICAgICk7XG4gICAgZXhwZWN0KHR5cGVvZiB0cmFuc2Zvcm1lZFZhbHVlKS50b0JlKCdudW1iZXInKTtcbiAgfSk7XG4gIHRlc3QoJ0xpc3RQYXJhbUluU2VydmljZUNhdGFsb2dDb25maWcnLCAoKSA9PiB7XG4gICAgY29uc3QgdHJhbnNmb3JtZWRWYWx1ZSA9IG5ldyBNZGFhQ29uZmlnUGFyYW1SZWZWYWx1ZVRyYW5zZm9ybWVyKHBhcmFtVHJhbnNmb3JtZXJQcm9wcykudHJhbnNmb3JtVmFsdWUoXG4gICAgICAne3twYXJhbTpsaXN0X3BhcmFtfX0nLFxuICAgICk7XG4gICAgZXhwZWN0KHRyYW5zZm9ybWVkVmFsdWUpLnRvTWF0Y2goLyN7VG9rZW5cXFtUT0tFTi5cXGQrXX0vKTtcbiAgfSk7XG4gIHRlc3QoJ1N0cmluZ1BhcmFtQW5ub3RhdGlvbicsICgpID0+IHtcbiAgICBjb25zdCB0cmFuc2Zvcm1lZFZhbHVlID0gbmV3IE1kYWFDb25maWdQYXJhbVJlZlZhbHVlVHJhbnNmb3JtZXIocGFyYW1UcmFuc2Zvcm1lclByb3BzKS50cmFuc2Zvcm1WYWx1ZShcbiAgICAgICd7e3BhcmFtOnN0cmluZzpzdHJpbmdfcGFyYW19fScsXG4gICAgKTtcbiAgICBleHBlY3QodHJhbnNmb3JtZWRWYWx1ZSkudG9NYXRjaCgvXFwke1Rva2VuXFxbVE9LRU4uXFxkK119Lyk7XG4gIH0pO1xuICB0ZXN0KCdOdW1iZXJQYXJhbUFubm90YXRpb24nLCAoKSA9PiB7XG4gICAgY29uc3QgdHJhbnNmb3JtZWRWYWx1ZSA9IG5ldyBNZGFhQ29uZmlnUGFyYW1SZWZWYWx1ZVRyYW5zZm9ybWVyKHBhcmFtVHJhbnNmb3JtZXJQcm9wcykudHJhbnNmb3JtVmFsdWUoXG4gICAgICAne3twYXJhbTpudW1iZXI6bnVtYmVyX3BhcmFtfX0nLFxuICAgICk7XG4gICAgZXhwZWN0KHR5cGVvZiB0cmFuc2Zvcm1lZFZhbHVlKS50b0JlKCdudW1iZXInKTtcbiAgfSk7XG4gIHRlc3QoJ0xpc3RQYXJhbUFubm90YXRpb24nLCAoKSA9PiB7XG4gICAgY29uc3QgdHJhbnNmb3JtZWRWYWx1ZSA9IG5ldyBNZGFhQ29uZmlnUGFyYW1SZWZWYWx1ZVRyYW5zZm9ybWVyKHBhcmFtVHJhbnNmb3JtZXJQcm9wcykudHJhbnNmb3JtVmFsdWUoXG4gICAgICAne3twYXJhbTpsaXN0Omxpc3RfcGFyYW19fScsXG4gICAgKTtcbiAgICBleHBlY3QodHJhbnNmb3JtZWRWYWx1ZSkudG9NYXRjaCgvI3tUb2tlblxcW1RPS0VOLlxcZCtdfS8pO1xuICB9KTtcbiAgdGVzdCgnUHJlZml4ZWROdW1iZXJQYXJhbScsICgpID0+IHtcbiAgICBjb25zdCB0cmFuc2Zvcm1lZFZhbHVlID0gbmV3IE1kYWFDb25maWdQYXJhbVJlZlZhbHVlVHJhbnNmb3JtZXIocGFyYW1UcmFuc2Zvcm1lclByb3BzKS50cmFuc2Zvcm1WYWx1ZShcbiAgICAgICd0ZXN0aW5ne3twYXJhbTpudW1iZXI6bnVtYmVyX3BhcmFtfX0nLFxuICAgICk7XG4gICAgZXhwZWN0KHRyYW5zZm9ybWVkVmFsdWUpLnRvTWF0Y2goL150ZXN0aW5nLVxcZCsoXFwuXFxkKyk/KGVcXCtcXGQrKT8kLyk7XG4gIH0pO1xuICB0ZXN0KCdQcmVmaXhlZExpc3RQYXJhbScsICgpID0+IHtcbiAgICBjb25zdCB0cmFuc2Zvcm1lZFZhbHVlID0gbmV3IE1kYWFDb25maWdQYXJhbVJlZlZhbHVlVHJhbnNmb3JtZXIocGFyYW1UcmFuc2Zvcm1lclByb3BzKS50cmFuc2Zvcm1WYWx1ZShcbiAgICAgICd0ZXN0aW5ne3twYXJhbTpsaXN0Omxpc3RfcGFyYW19fScsXG4gICAgKTtcbiAgICBleHBlY3QodHJhbnNmb3JtZWRWYWx1ZSkudG9NYXRjaCgvdGVzdGluZyN7VG9rZW5cXFtUT0tFTi5cXGQrXX0vKTtcbiAgfSk7XG4gIHRlc3QoJ05lc3RlZFJlc29sdXRpb25XaXRoaW5OdW1iZXJQYXJhbScsICgpID0+IHtcbiAgICBjb25zdCB0cmFuc2Zvcm1lZFZhbHVlID0gbmV3IE1kYWFDb25maWdQYXJhbVJlZlZhbHVlVHJhbnNmb3JtZXIocGFyYW1UcmFuc2Zvcm1lclByb3BzKS50cmFuc2Zvcm1WYWx1ZShcbiAgICAgICd7e3BhcmFtOm51bWJlcjp7e29yZ319X3BhcmFtfX0nLFxuICAgICk7XG4gICAgZXhwZWN0KHR5cGVvZiB0cmFuc2Zvcm1lZFZhbHVlKS50b0JlKCdudW1iZXInKTtcbiAgfSk7XG5cbiAgdGVzdCgnUGFydGl0aW9uJywgKCkgPT4ge1xuICAgIGNvbnN0IHRyYW5zZm9ybWVkVmFsdWUgPSBuZXcgTWRhYUNvbmZpZ1JlZlZhbHVlVHJhbnNmb3JtZXIodHJhbnNmb3JtZXJQcm9wcykudHJhbnNmb3JtVmFsdWUoJ3t7cGFydGl0aW9ufX0nKTtcbiAgICBleHBlY3QodHJhbnNmb3JtZWRWYWx1ZSkudG9NYXRjaCgvXFwke1Rva2VuXFxbQVdTLlBhcnRpdGlvbi5cXGQrXX0vKTtcbiAgfSk7XG4gIHRlc3QoJ1JlZ2lvbicsICgpID0+IHtcbiAgICBjb25zdCB0cmFuc2Zvcm1lZFZhbHVlID0gbmV3IE1kYWFDb25maWdSZWZWYWx1ZVRyYW5zZm9ybWVyKHRyYW5zZm9ybWVyUHJvcHMpLnRyYW5zZm9ybVZhbHVlKCd7e3JlZ2lvbn19Jyk7XG4gICAgZXhwZWN0KHRyYW5zZm9ybWVkVmFsdWUpLnRvTWF0Y2goL1xcJHtUb2tlblxcW0FXUy5SZWdpb24uXFxkK119Lyk7XG4gIH0pO1xuXG4gIHRlc3QoJ0FjY291bnQnLCAoKSA9PiB7XG4gICAgY29uc3QgdHJhbnNmb3JtZWRWYWx1ZSA9IG5ldyBNZGFhQ29uZmlnUmVmVmFsdWVUcmFuc2Zvcm1lcih0cmFuc2Zvcm1lclByb3BzKS50cmFuc2Zvcm1WYWx1ZSgne3thY2NvdW50fX0nKTtcbiAgICBleHBlY3QodHJhbnNmb3JtZWRWYWx1ZSkudG9NYXRjaCgvXFwke1Rva2VuXFxbQVdTLkFjY291bnRJZC5cXGQrXX0vKTtcbiAgfSk7XG4gIHRlc3QoJ01vZHVsZSBOYW1lJywgKCkgPT4ge1xuICAgIGNvbnN0IHRyYW5zZm9ybWVkVmFsdWUgPSBuZXcgTWRhYUNvbmZpZ1JlZlZhbHVlVHJhbnNmb3JtZXIodHJhbnNmb3JtZXJQcm9wcykudHJhbnNmb3JtVmFsdWUoJ3t7bW9kdWxlX25hbWV9fScpO1xuICAgIGV4cGVjdCh0cmFuc2Zvcm1lZFZhbHVlKS50b0JlKCd0ZXN0bW9kdWxlJyk7XG4gIH0pO1xuXG4gIC8vIEFkZGl0aW9uYWwgdGVzdCBjYXNlcyBmb3IgYmV0dGVyIGNvdmVyYWdlXG5cbiAgdGVzdCgnTmFrZWQgU1NNIFJlZmVyZW5jZScsICgpID0+IHtcbiAgICBjb25zdCB0cmFuc2Zvcm1lZFZhbHVlID0gbmV3IE1kYWFDb25maWdSZWZWYWx1ZVRyYW5zZm9ybWVyKHRyYW5zZm9ybWVyUHJvcHMpLnRyYW5zZm9ybVZhbHVlKFxuICAgICAgJ3t7cmVzb2x2ZTpzc206L3Rlc3QvcGFyYW0vcGF0aH19JyxcbiAgICApO1xuICAgIGV4cGVjdCh0cmFuc2Zvcm1lZFZhbHVlKS50b01hdGNoKC9cXCR7VG9rZW5cXFtUT0tFTi5cXGQrXX0vKTtcbiAgfSk7XG5cbiAgdGVzdCgnTmFrZWQgRW52IFZhcicsICgpID0+IHtcbiAgICBwcm9jZXNzLmVudlsnTkFLRURfVEVTVF9WQVInXSA9ICduYWtlZF90ZXN0dmFsJztcbiAgICBjb25zdCB0cmFuc2Zvcm1lZFZhbHVlID0gbmV3IE1kYWFDb25maWdSZWZWYWx1ZVRyYW5zZm9ybWVyKHRyYW5zZm9ybWVyUHJvcHMpLnRyYW5zZm9ybVZhbHVlKFxuICAgICAgJ3t7ZW52X3ZhcjpOQUtFRF9URVNUX1ZBUn19JyxcbiAgICApO1xuICAgIGV4cGVjdCh0cmFuc2Zvcm1lZFZhbHVlKS50b0JlKCduYWtlZF90ZXN0dmFsJyk7XG4gIH0pO1xuXG4gIHRlc3QoJ01pc3NpbmcgRW52IFZhciAtIEVtYmVkZGVkJywgKCkgPT4ge1xuICAgIGRlbGV0ZSBwcm9jZXNzLmVudlsnTUlTU0lOR19WQVInXTtcbiAgICBjb25zdCB0cmFuc2Zvcm1lZFZhbHVlID0gbmV3IE1kYWFDb25maWdSZWZWYWx1ZVRyYW5zZm9ybWVyKHRyYW5zZm9ybWVyUHJvcHMpLnRyYW5zZm9ybVZhbHVlKFxuICAgICAgJ3ByZWZpeC17e2Vudl92YXI6TUlTU0lOR19WQVJ9fS1zdWZmaXgnLFxuICAgICk7XG4gICAgLy8gU2hvdWxkIGxlYXZlIHRoZSByZWZlcmVuY2UgYXMtaXMgd2hlbiBlbnYgdmFyIGlzIHVuZGVmaW5lZFxuICAgIGV4cGVjdCh0cmFuc2Zvcm1lZFZhbHVlKS50b0JlKCdwcmVmaXgte3tlbnZfdmFyOk1JU1NJTkdfVkFSfX0tc3VmZml4Jyk7XG4gIH0pO1xuXG4gIHRlc3QoJ01pc3NpbmcgRW52IFZhciAtIE5ha2VkIFJlZmVyZW5jZScsICgpID0+IHtcbiAgICBkZWxldGUgcHJvY2Vzcy5lbnZbJ01JU1NJTkdfVkFSX05BS0VEJ107XG4gICAgY29uc3QgdHJhbnNmb3JtZWRWYWx1ZSA9IG5ldyBNZGFhQ29uZmlnUmVmVmFsdWVUcmFuc2Zvcm1lcih0cmFuc2Zvcm1lclByb3BzKS50cmFuc2Zvcm1WYWx1ZShcbiAgICAgICd7e2Vudl92YXI6TUlTU0lOR19WQVJfTkFLRUR9fScsXG4gICAgKTtcbiAgICAvLyBTaG91bGQgcmV0dXJuIHRoZSBvcmlnaW5hbCBzdHJpbmcgZm9yIG5ha2VkIHJlZmVyZW5jZSB3aXRoIHVuZGVmaW5lZCBlbnYgdmFyXG4gICAgZXhwZWN0KHRyYW5zZm9ybWVkVmFsdWUpLnRvQmUoJ3t7ZW52X3ZhcjpNSVNTSU5HX1ZBUl9OQUtFRH19Jyk7XG4gIH0pO1xuXG4gIHRlc3QoJ05lc3RlZCBDb250ZXh0IEFycmF5IGluIFNTTSBQYXRoIFNob3VsZCBFcnJvcicsICgpID0+IHtcbiAgICBleHBlY3QoKCkgPT4ge1xuICAgICAgbmV3IE1kYWFDb25maWdSZWZWYWx1ZVRyYW5zZm9ybWVyKHRyYW5zZm9ybWVyUHJvcHMpLnRyYW5zZm9ybVZhbHVlKFxuICAgICAgICAne3tyZXNvbHZlOnNzbTove3tjb250ZXh0OnRlc3RfY29udGV4dF9saXN0fX0vcGF0aH19JyxcbiAgICAgICk7XG4gICAgfSkudG9UaHJvdygvQ2Fubm90IGVtYmVkIGFycmF5IG9yIG9iamVjdCBjb250ZXh0IHZhbHVlIGluIHN0cmluZy8pO1xuICB9KTtcblxuICB0ZXN0KCdOZXN0ZWQgQ29udGV4dCBPYmplY3QgaW4gU3RyaW5nIFNob3VsZCBFcnJvcicsICgpID0+IHtcbiAgICBleHBlY3QoKCkgPT4ge1xuICAgICAgbmV3IE1kYWFDb25maWdSZWZWYWx1ZVRyYW5zZm9ybWVyKHRyYW5zZm9ybWVyUHJvcHMpLnRyYW5zZm9ybVZhbHVlKFxuICAgICAgICAncHJlZml4LXt7cmVzb2x2ZTpzc206L3t7Y29udGV4dDp0ZXN0X2NvbnRleHRfb2JqfX0vcGF0aH19JyxcbiAgICAgICk7XG4gICAgfSkudG9UaHJvdygvQ2Fubm90IGVtYmVkIGFycmF5IG9yIG9iamVjdCBjb250ZXh0IHZhbHVlIGluIHN0cmluZy8pO1xuICB9KTtcblxuICB0ZXN0KCdCb29sZWFuIENvbnRleHQgVmFsdWUnLCAoKSA9PiB7XG4gICAgY29uc3QgY29udGV4dFdpdGhCb29sID0ge1xuICAgICAgLi4uY29udGV4dCxcbiAgICAgIGJvb2xfdmFsdWU6ICd0cnVlJywgLy8gRW5jb2RlZCBhcyBzdHJpbmdcbiAgICB9O1xuICAgIGNvbnN0IGFwcFdpdGhCb29sID0gbmV3IEFwcCh7IGNvbnRleHQ6IGNvbnRleHRXaXRoQm9vbCB9KTtcbiAgICBjb25zdCBzdGFja1dpdGhCb29sID0gbmV3IFN0YWNrKGFwcFdpdGhCb29sLCAndGVzdFN0YWNrQm9vbCcpO1xuICAgIGNvbnN0IHByb3BzV2l0aEJvb2wgPSB7IC4uLnRyYW5zZm9ybWVyUHJvcHMsIHNjb3BlOiBzdGFja1dpdGhCb29sIH07XG5cbiAgICBjb25zdCB0cmFuc2Zvcm1lZFZhbHVlID0gbmV3IE1kYWFDb25maWdSZWZWYWx1ZVRyYW5zZm9ybWVyKHByb3BzV2l0aEJvb2wpLnRyYW5zZm9ybVZhbHVlKCd7e2NvbnRleHQ6Ym9vbF92YWx1ZX19Jyk7XG4gICAgZXhwZWN0KHRyYW5zZm9ybWVkVmFsdWUpLnRvQmUoJ3RydWUnKTtcbiAgfSk7XG5cbiAgdGVzdCgnTmVzdGVkIE9iamVjdCBDb250ZXh0JywgKCkgPT4ge1xuICAgIGNvbnN0IG5lc3RlZE9iaiA9IHtcbiAgICAgIG91dGVyOiB7XG4gICAgICAgIGlubmVyOiAndmFsdWUnLFxuICAgICAgfSxcbiAgICB9O1xuICAgIGNvbnN0IGNvbnRleHRXaXRoTmVzdGVkID0ge1xuICAgICAgLi4uY29udGV4dCxcbiAgICAgIG5lc3RlZF9vYmo6IGVuY29kZUNvbnRleHRWYWx1ZShuZXN0ZWRPYmopLFxuICAgIH07XG4gICAgY29uc3QgYXBwV2l0aE5lc3RlZCA9IG5ldyBBcHAoeyBjb250ZXh0OiBjb250ZXh0V2l0aE5lc3RlZCB9KTtcbiAgICBjb25zdCBzdGFja1dpdGhOZXN0ZWQgPSBuZXcgU3RhY2soYXBwV2l0aE5lc3RlZCwgJ3Rlc3RTdGFja05lc3RlZCcpO1xuICAgIGNvbnN0IHByb3BzV2l0aE5lc3RlZCA9IHsgLi4udHJhbnNmb3JtZXJQcm9wcywgc2NvcGU6IHN0YWNrV2l0aE5lc3RlZCB9O1xuXG4gICAgY29uc3QgdHJhbnNmb3JtZWRWYWx1ZSA9IG5ldyBNZGFhQ29uZmlnUmVmVmFsdWVUcmFuc2Zvcm1lcihwcm9wc1dpdGhOZXN0ZWQpLnRyYW5zZm9ybVZhbHVlKFxuICAgICAgJ3t7Y29udGV4dDpuZXN0ZWRfb2JqfX0nLFxuICAgICk7XG4gICAgZXhwZWN0KHRyYW5zZm9ybWVkVmFsdWUpLnRvRXF1YWwobmVzdGVkT2JqKTtcbiAgfSk7XG5cbiAgdGVzdCgnQXJyYXkgd2l0aCBNaXhlZCBUeXBlcyBDb250ZXh0JywgKCkgPT4ge1xuICAgIGNvbnN0IG1peGVkQXJyYXkgPSBbJ3N0cmluZycsIDEyMywgdHJ1ZSwgeyBrZXk6ICd2YWx1ZScgfV07XG4gICAgY29uc3QgY29udGV4dFdpdGhNaXhlZCA9IHtcbiAgICAgIC4uLmNvbnRleHQsXG4gICAgICBtaXhlZF9hcnJheTogZW5jb2RlQ29udGV4dFZhbHVlKG1peGVkQXJyYXkpLFxuICAgIH07XG4gICAgY29uc3QgYXBwV2l0aE1peGVkID0gbmV3IEFwcCh7IGNvbnRleHQ6IGNvbnRleHRXaXRoTWl4ZWQgfSk7XG4gICAgY29uc3Qgc3RhY2tXaXRoTWl4ZWQgPSBuZXcgU3RhY2soYXBwV2l0aE1peGVkLCAndGVzdFN0YWNrTWl4ZWQnKTtcbiAgICBjb25zdCBwcm9wc1dpdGhNaXhlZCA9IHsgLi4udHJhbnNmb3JtZXJQcm9wcywgc2NvcGU6IHN0YWNrV2l0aE1peGVkIH07XG5cbiAgICBjb25zdCB0cmFuc2Zvcm1lZFZhbHVlID0gbmV3IE1kYWFDb25maWdSZWZWYWx1ZVRyYW5zZm9ybWVyKHByb3BzV2l0aE1peGVkKS50cmFuc2Zvcm1WYWx1ZShcbiAgICAgICd7e2NvbnRleHQ6bWl4ZWRfYXJyYXl9fScsXG4gICAgKTtcbiAgICBleHBlY3QodHJhbnNmb3JtZWRWYWx1ZSkudG9FcXVhbChtaXhlZEFycmF5KTtcbiAgfSk7XG59KTtcblxuZGVzY3JpYmUoJ1Rlc3QgTWRhYUNvbmZpZ1NTTVZhbHVlVHJhbnNmb3JtZXInLCAoKSA9PiB7XG4gIHRlc3QoJ05vbiBzc206JywgKCkgPT4ge1xuICAgIGNvbnN0IHRyYW5zZm9ybWVkVmFsdWUgPSBuZXcgTWRhYUNvbmZpZ1NTTVZhbHVlVHJhbnNmb3JtZXIoKS50cmFuc2Zvcm1WYWx1ZSgndGVzdHZhbHVlJywgJ3Rlc3RQYXRoJyk7XG4gICAgZXhwZWN0KHRyYW5zZm9ybWVkVmFsdWUpLnRvQmUoJ3Rlc3R2YWx1ZScpO1xuICB9KTtcbiAgdGVzdCgnTmFrZWQgc3NtOicsICgpID0+IHtcbiAgICBjb25zdCB0cmFuc2Zvcm1lZFZhbHVlID0gbmV3IE1kYWFDb25maWdTU01WYWx1ZVRyYW5zZm9ybWVyKCkudHJhbnNmb3JtVmFsdWUoJ3NzbTp0ZXN0U1NNUGFyYW1QYXRoJywgJ3Rlc3RQYXRoJyk7XG4gICAgZXhwZWN0KHRyYW5zZm9ybWVkVmFsdWUpLnRvQmUoJ3t7cmVzb2x2ZTpzc206dGVzdFNTTVBhcmFtUGF0aH19Jyk7XG4gIH0pO1xuICB0ZXN0KCdJZ25vcmVkIFNTTTogQWN0aW9uJywgKCkgPT4ge1xuICAgIGNvbnN0IHRyYW5zZm9ybWVkVmFsdWUgPSBuZXcgTWRhYUNvbmZpZ1NTTVZhbHVlVHJhbnNmb3JtZXIoKS50cmFuc2Zvcm1WYWx1ZShcbiAgICAgICdzc206R2V0UGFyYW1ldGVyJyxcbiAgICAgICdwb2xpY3lEb2N1bWVudC9TdGF0ZW1lbnQvQWN0aW9uJyxcbiAgICApO1xuICAgIGV4cGVjdCh0cmFuc2Zvcm1lZFZhbHVlKS50b0JlKCdzc206R2V0UGFyYW1ldGVyJyk7XG4gIH0pO1xufSk7XG5kZXNjcmliZSgnVGVzdCBDb25maWdDb25maWdQYXRoVmFsdWVUcmFuc2Zvcm1lcicsICgpID0+IHtcbiAgdGVzdCgnTm9uIHJlbGF0aXZlJywgKCkgPT4ge1xuICAgIGNvbnN0IHRyYW5zZm9ybWVkVmFsdWUgPSBuZXcgQ29uZmlnQ29uZmlnUGF0aFZhbHVlVHJhbnNmb3JtZXIoJ3Rlc3RCYXNlRGlyJykudHJhbnNmb3JtVmFsdWUoJ3Rlc3ROb25SZWxhdGl2ZScpO1xuICAgIGV4cGVjdCh0cmFuc2Zvcm1lZFZhbHVlKS50b0JlKCd0ZXN0Tm9uUmVsYXRpdmUnKTtcbiAgfSk7XG4gIHRlc3QoJ1JlbGF0aXZlJywgKCkgPT4ge1xuICAgIGNvbnN0IHRyYW5zZm9ybWVkVmFsdWUgPSBuZXcgQ29uZmlnQ29uZmlnUGF0aFZhbHVlVHJhbnNmb3JtZXIoJ3Rlc3RCYXNlRGlyJykudHJhbnNmb3JtVmFsdWUoJy4vcmVsYXRpdmUnKTtcbiAgICBleHBlY3QodHJhbnNmb3JtZWRWYWx1ZSkudG9CZShwYXRoLnJlc29sdmUoJy4vcmVsYXRpdmUnLnJlcGxhY2UoL15cXC4vLCAndGVzdEJhc2VEaXInKSkpO1xuICB9KTtcblxuICB0ZXN0KCdQYXJlbnQgUmVsYXRpdmUnLCAoKSA9PiB7XG4gICAgY29uc3QgdHJhbnNmb3JtZWRWYWx1ZSA9IG5ldyBDb25maWdDb25maWdQYXRoVmFsdWVUcmFuc2Zvcm1lcigndGVzdEJhc2VEaXInKS50cmFuc2Zvcm1WYWx1ZSgnLi4vcmVsYXRpdmUtcGFyZW50Jyk7XG4gICAgZXhwZWN0KHRyYW5zZm9ybWVkVmFsdWUpLnRvQmUocGF0aC5yZXNvbHZlKCcuL3JlbGF0aXZlLXBhcmVudCcpKTtcbiAgfSk7XG5cbiAgdGVzdCgnUGFyZW50IFN1YiBmb2xkZXIgUmVsYXRpdmUnLCAoKSA9PiB7XG4gICAgY29uc3QgdHJhbnNmb3JtZWRWYWx1ZSA9IG5ldyBDb25maWdDb25maWdQYXRoVmFsdWVUcmFuc2Zvcm1lcigndGVzdEJhc2VEaXInKS50cmFuc2Zvcm1WYWx1ZSgnLi4vYXBwL2NvZGUnKTtcbiAgICBleHBlY3QodHJhbnNmb3JtZWRWYWx1ZSkudG9CZShwYXRoLnJlc29sdmUoJy4vYXBwL2NvZGUnKSk7XG4gIH0pO1xuXG4gIHRlc3QoJ0dyYW5kcGFyZW50IGZvbGRlciBSZWxhdGl2ZScsICgpID0+IHtcbiAgICBjb25zdCB0cmFuc2Zvcm1lZFZhbHVlID0gbmV3IENvbmZpZ0NvbmZpZ1BhdGhWYWx1ZVRyYW5zZm9ybWVyKCd0ZXN0QmFzZURpcicpLnRyYW5zZm9ybVZhbHVlKCcuLi8uLi9tZGFhLW5hbWluZycpO1xuICAgIGV4cGVjdCh0cmFuc2Zvcm1lZFZhbHVlKS50b0JlKHBhdGgucmVzb2x2ZSgnLi4vbWRhYS1uYW1pbmcnKSk7XG4gIH0pO1xufSk7XG4iXX0=