@aws-mdaa/dataops-job-l3-construct 1.4.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.
- package/.jsii +117 -121
- package/README.md +5 -0
- package/lib/dataops-job-l3-construct.d.ts +37 -240
- package/lib/dataops-job-l3-construct.js +61 -34
- package/node_modules/@aws-mdaa/config/.npmignore +34 -0
- package/node_modules/@aws-mdaa/config/README.md +3 -0
- package/node_modules/@aws-mdaa/config/jest.config.js +5 -0
- package/node_modules/@aws-mdaa/config/lib/blueprint-value-transformer.d.ts +20 -0
- package/node_modules/@aws-mdaa/config/lib/blueprint-value-transformer.js +70 -0
- package/node_modules/@aws-mdaa/config/lib/blueprint-value-transformer.ts +88 -0
- package/node_modules/@aws-mdaa/config/lib/config.d.ts +87 -0
- package/node_modules/@aws-mdaa/config/lib/config.js +7 -0
- package/node_modules/@aws-mdaa/config/lib/config.ts +92 -0
- package/node_modules/@aws-mdaa/config/lib/index.d.ts +11 -0
- package/node_modules/@aws-mdaa/config/lib/index.js +28 -0
- package/node_modules/@aws-mdaa/config/lib/index.ts +12 -0
- package/node_modules/@aws-mdaa/config/lib/param-transformer.d.ts +49 -0
- package/node_modules/@aws-mdaa/config/lib/param-transformer.js +160 -0
- package/node_modules/@aws-mdaa/config/lib/param-transformer.ts +159 -0
- package/node_modules/@aws-mdaa/config/lib/path-value-transformer.d.ts +10 -0
- package/node_modules/@aws-mdaa/config/lib/path-value-transformer.js +30 -0
- package/node_modules/@aws-mdaa/config/lib/path-value-transformer.ts +27 -0
- package/node_modules/@aws-mdaa/config/lib/ref-value-transformer.d.ts +44 -0
- package/node_modules/@aws-mdaa/config/lib/ref-value-transformer.js +243 -0
- package/node_modules/@aws-mdaa/config/lib/ref-value-transformer.ts +302 -0
- package/node_modules/@aws-mdaa/config/lib/ssm-ref-transformer.d.ts +8 -0
- package/node_modules/@aws-mdaa/config/lib/ssm-ref-transformer.js +22 -0
- package/node_modules/@aws-mdaa/config/lib/ssm-ref-transformer.ts +21 -0
- package/node_modules/@aws-mdaa/config/lib/transformer.d.ts +35 -0
- package/node_modules/@aws-mdaa/config/lib/transformer.js +66 -0
- package/node_modules/@aws-mdaa/config/lib/transformer.ts +74 -0
- package/node_modules/@aws-mdaa/{s3-bucketpolicy-helper → config}/package.json +17 -17
- package/node_modules/@aws-mdaa/config/test/blueprint-value-transformer.test.d.ts +5 -0
- package/node_modules/@aws-mdaa/config/test/blueprint-value-transformer.test.js +224 -0
- package/node_modules/@aws-mdaa/config/test/blueprint-value-transformer.test.ts +259 -0
- package/node_modules/@aws-mdaa/config/test/config-nt.test.d.ts +5 -0
- package/node_modules/@aws-mdaa/config/test/config-nt.test.js +129 -0
- package/node_modules/@aws-mdaa/config/test/config-nt.test.ts +163 -0
- package/node_modules/@aws-mdaa/config/test/config.test.d.ts +5 -0
- package/node_modules/@aws-mdaa/config/test/config.test.js +409 -0
- package/node_modules/@aws-mdaa/config/test/config.test.ts +517 -0
- package/node_modules/@aws-mdaa/config/test/param-transformer.test.d.ts +5 -0
- package/node_modules/@aws-mdaa/config/test/param-transformer.test.js +216 -0
- package/node_modules/@aws-mdaa/config/test/param-transformer.test.ts +234 -0
- package/node_modules/@aws-mdaa/config/test/path-value-transformer.test.d.ts +5 -0
- package/node_modules/@aws-mdaa/config/test/path-value-transformer.test.js +59 -0
- package/node_modules/@aws-mdaa/config/test/path-value-transformer.test.ts +68 -0
- package/node_modules/@aws-mdaa/config/test/ref-value-transformer.test.d.ts +5 -0
- package/node_modules/@aws-mdaa/config/test/ref-value-transformer.test.js +254 -0
- package/node_modules/@aws-mdaa/config/test/ref-value-transformer.test.ts +304 -0
- package/node_modules/@aws-mdaa/config/test/ssm-ref-transformer.test.d.ts +5 -0
- package/node_modules/@aws-mdaa/config/test/ssm-ref-transformer.test.js +66 -0
- package/node_modules/@aws-mdaa/config/test/ssm-ref-transformer.test.ts +79 -0
- package/node_modules/@aws-mdaa/config/tsconfig.json +40 -0
- package/node_modules/@aws-mdaa/config/tsconfig.tsbuildinfo +1 -0
- package/node_modules/@aws-mdaa/config/typedoc.json +7 -0
- package/node_modules/lodash/README.md +2 -2
- package/node_modules/lodash/_baseOrderBy.js +1 -1
- package/node_modules/lodash/_baseUnset.js +7 -20
- package/node_modules/lodash/_setCacheHas.js +1 -1
- package/node_modules/lodash/compact.js +1 -1
- package/node_modules/lodash/core.js +3 -3
- package/node_modules/lodash/core.min.js +26 -25
- package/node_modules/lodash/fromPairs.js +3 -1
- package/node_modules/lodash/lodash.js +38 -27
- package/node_modules/lodash/lodash.min.js +125 -129
- package/node_modules/lodash/package.json +4 -2
- package/node_modules/lodash/random.js +9 -0
- package/node_modules/lodash/template.js +16 -4
- package/node_modules/lodash/templateSettings.js +4 -0
- package/package.json +27 -30
- package/node_modules/@aws-mdaa/s3-bucketpolicy-helper/README.md +0 -185
- package/node_modules/@aws-mdaa/s3-bucketpolicy-helper/lib/index.d.ts +0 -57
- package/node_modules/@aws-mdaa/s3-bucketpolicy-helper/lib/index.js +0 -198
- package/node_modules/@aws-mdaa/s3-inventory-helper/README.md +0 -3
- package/node_modules/@aws-mdaa/s3-inventory-helper/lib/index.d.ts +0 -66
- package/node_modules/@aws-mdaa/s3-inventory-helper/lib/index.js +0 -222
- package/node_modules/@aws-mdaa/s3-inventory-helper/package.json +0 -42
|
@@ -0,0 +1,216 @@
|
|
|
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
|
+
const lib_1 = require("../lib");
|
|
9
|
+
describe('MdaaConfigParamRefValueTransformer', () => {
|
|
10
|
+
const baseProps = {
|
|
11
|
+
org: 'test-org',
|
|
12
|
+
env: 'dev',
|
|
13
|
+
domain: 'test-domain',
|
|
14
|
+
module_name: 'test-module',
|
|
15
|
+
paramProps: {},
|
|
16
|
+
};
|
|
17
|
+
describe('basic functionality', () => {
|
|
18
|
+
test('returns unchanged value without refs', () => {
|
|
19
|
+
const stack = new aws_cdk_lib_1.Stack();
|
|
20
|
+
const transformer = new lib_1.MdaaConfigParamRefValueTransformer({ ...baseProps, scope: stack });
|
|
21
|
+
expect(transformer.transformValue('plain-value')).toBe('plain-value');
|
|
22
|
+
});
|
|
23
|
+
test('non-param refs remain unchanged (parseRef override only handles param: refs)', () => {
|
|
24
|
+
const stack = new aws_cdk_lib_1.Stack();
|
|
25
|
+
const transformer = new lib_1.MdaaConfigParamRefValueTransformer({ ...baseProps, scope: stack });
|
|
26
|
+
// Note: MdaaConfigParamRefValueTransformer.parseRef only handles param: refs
|
|
27
|
+
// Other refs like {{org}} are not substituted by this class
|
|
28
|
+
expect(transformer.transformValue('{{org}}')).toBe('{{org}}');
|
|
29
|
+
expect(transformer.transformValue('{{env}}')).toBe('{{env}}');
|
|
30
|
+
expect(transformer.transformValue('{{domain}}')).toBe('{{domain}}');
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
describe('standalone param refs', () => {
|
|
34
|
+
test('creates string parameter for standalone param:string ref', () => {
|
|
35
|
+
const stack = new aws_cdk_lib_1.Stack();
|
|
36
|
+
const transformer = new lib_1.MdaaConfigParamRefValueTransformer({ ...baseProps, scope: stack });
|
|
37
|
+
const result = transformer.transformValue('{{param:string:myParam}}');
|
|
38
|
+
expect(result).toBeDefined();
|
|
39
|
+
const param = stack.node.tryFindChild('myParam');
|
|
40
|
+
expect(param).toBeDefined();
|
|
41
|
+
expect(param.type).toBe('String');
|
|
42
|
+
});
|
|
43
|
+
test('creates number parameter for standalone param:number ref', () => {
|
|
44
|
+
const stack = new aws_cdk_lib_1.Stack();
|
|
45
|
+
const transformer = new lib_1.MdaaConfigParamRefValueTransformer({ ...baseProps, scope: stack });
|
|
46
|
+
const result = transformer.transformValue('{{param:number:myNumberParam}}');
|
|
47
|
+
expect(typeof result).toBe('number');
|
|
48
|
+
const param = stack.node.tryFindChild('myNumberParam');
|
|
49
|
+
expect(param).toBeDefined();
|
|
50
|
+
expect(param.type).toBe('Number');
|
|
51
|
+
});
|
|
52
|
+
test('creates list parameter for standalone param:list ref', () => {
|
|
53
|
+
const stack = new aws_cdk_lib_1.Stack();
|
|
54
|
+
const transformer = new lib_1.MdaaConfigParamRefValueTransformer({ ...baseProps, scope: stack });
|
|
55
|
+
const result = transformer.transformValue('{{param:list:myListParam}}');
|
|
56
|
+
expect(result).toBeDefined();
|
|
57
|
+
const param = stack.node.tryFindChild('myListParam');
|
|
58
|
+
expect(param).toBeDefined();
|
|
59
|
+
expect(param.type).toBe('CommaDelimitedList');
|
|
60
|
+
});
|
|
61
|
+
test('creates string parameter when no type label specified', () => {
|
|
62
|
+
const stack = new aws_cdk_lib_1.Stack();
|
|
63
|
+
const transformer = new lib_1.MdaaConfigParamRefValueTransformer({ ...baseProps, scope: stack });
|
|
64
|
+
const result = transformer.transformValue('{{param:untypedParam}}');
|
|
65
|
+
expect(result).toBeDefined();
|
|
66
|
+
const param = stack.node.tryFindChild('untypedParam');
|
|
67
|
+
expect(param).toBeDefined();
|
|
68
|
+
expect(param.type).toBe('String');
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
describe('embedded param refs', () => {
|
|
72
|
+
test('substitutes param ref embedded in string', () => {
|
|
73
|
+
const stack = new aws_cdk_lib_1.Stack();
|
|
74
|
+
const transformer = new lib_1.MdaaConfigParamRefValueTransformer({ ...baseProps, scope: stack });
|
|
75
|
+
const result = transformer.transformValue('prefix-{{param:string:embeddedParam}}-suffix');
|
|
76
|
+
expect(typeof result).toBe('string');
|
|
77
|
+
expect(stack.node.tryFindChild('embeddedParam')).toBeDefined();
|
|
78
|
+
});
|
|
79
|
+
test('substitutes multiple param refs in string', () => {
|
|
80
|
+
const stack = new aws_cdk_lib_1.Stack();
|
|
81
|
+
const transformer = new lib_1.MdaaConfigParamRefValueTransformer({ ...baseProps, scope: stack });
|
|
82
|
+
const result = transformer.transformValue('{{param:string:param1}}-{{param:string:param2}}');
|
|
83
|
+
expect(typeof result).toBe('string');
|
|
84
|
+
expect(stack.node.tryFindChild('param1')).toBeDefined();
|
|
85
|
+
expect(stack.node.tryFindChild('param2')).toBeDefined();
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
describe('paramProps configuration', () => {
|
|
89
|
+
test('uses paramProps to create parameter with specified type', () => {
|
|
90
|
+
const stack = new aws_cdk_lib_1.Stack();
|
|
91
|
+
const transformer = new lib_1.MdaaConfigParamRefValueTransformer({
|
|
92
|
+
...baseProps,
|
|
93
|
+
scope: stack,
|
|
94
|
+
paramProps: {
|
|
95
|
+
configuredParam: { type: 'Number', description: 'A number param' },
|
|
96
|
+
},
|
|
97
|
+
});
|
|
98
|
+
const result = transformer.transformValue('{{param:configuredParam}}');
|
|
99
|
+
expect(typeof result).toBe('number');
|
|
100
|
+
const param = stack.node.tryFindChild('configuredParam');
|
|
101
|
+
expect(param.type).toBe('Number');
|
|
102
|
+
});
|
|
103
|
+
test('uses paramProps for String type', () => {
|
|
104
|
+
const stack = new aws_cdk_lib_1.Stack();
|
|
105
|
+
const transformer = new lib_1.MdaaConfigParamRefValueTransformer({
|
|
106
|
+
...baseProps,
|
|
107
|
+
scope: stack,
|
|
108
|
+
paramProps: {
|
|
109
|
+
stringParam: { type: 'String', default: 'default-value' },
|
|
110
|
+
},
|
|
111
|
+
});
|
|
112
|
+
const result = transformer.transformValue('{{param:stringParam}}');
|
|
113
|
+
expect(result).toBeDefined();
|
|
114
|
+
const param = stack.node.tryFindChild('stringParam');
|
|
115
|
+
expect(param.type).toBe('String');
|
|
116
|
+
});
|
|
117
|
+
test('uses paramProps for CommaDelimitedList type', () => {
|
|
118
|
+
const stack = new aws_cdk_lib_1.Stack();
|
|
119
|
+
const transformer = new lib_1.MdaaConfigParamRefValueTransformer({
|
|
120
|
+
...baseProps,
|
|
121
|
+
scope: stack,
|
|
122
|
+
paramProps: {
|
|
123
|
+
listParam: { type: 'CommaDelimitedList' },
|
|
124
|
+
},
|
|
125
|
+
});
|
|
126
|
+
const result = transformer.transformValue('{{param:listParam}}');
|
|
127
|
+
expect(result).toBeDefined();
|
|
128
|
+
const param = stack.node.tryFindChild('listParam');
|
|
129
|
+
expect(param.type).toBe('CommaDelimitedList');
|
|
130
|
+
});
|
|
131
|
+
test('throws error for invalid paramProps type', () => {
|
|
132
|
+
const stack = new aws_cdk_lib_1.Stack();
|
|
133
|
+
const transformer = new lib_1.MdaaConfigParamRefValueTransformer({
|
|
134
|
+
...baseProps,
|
|
135
|
+
scope: stack,
|
|
136
|
+
paramProps: {
|
|
137
|
+
invalidParam: { type: 'InvalidType' },
|
|
138
|
+
},
|
|
139
|
+
});
|
|
140
|
+
// Note: The error is only thrown when paramProps.type is used AND it's invalid
|
|
141
|
+
// But isStringType returns true for any non-Number, non-List type, so InvalidType
|
|
142
|
+
// is treated as a String type and doesn't throw
|
|
143
|
+
const result = transformer.transformValue('{{param:invalidParam}}');
|
|
144
|
+
expect(result).toBeDefined();
|
|
145
|
+
const param = stack.node.tryFindChild('invalidParam');
|
|
146
|
+
// InvalidType gets treated as String due to isStringType fallback logic
|
|
147
|
+
expect(param).toBeDefined();
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
describe('existing parameter reuse', () => {
|
|
151
|
+
test('reuses existing string parameter', () => {
|
|
152
|
+
const stack = new aws_cdk_lib_1.Stack();
|
|
153
|
+
new aws_cdk_lib_1.CfnParameter(stack, 'existingParam', { type: 'String', default: 'existing' });
|
|
154
|
+
const transformer = new lib_1.MdaaConfigParamRefValueTransformer({ ...baseProps, scope: stack });
|
|
155
|
+
const result = transformer.transformValue('{{param:existingParam}}');
|
|
156
|
+
expect(result).toBeDefined();
|
|
157
|
+
// Should not create a duplicate
|
|
158
|
+
const children = stack.node.children.filter(c => c.node.id === 'existingParam');
|
|
159
|
+
expect(children.length).toBe(1);
|
|
160
|
+
});
|
|
161
|
+
test('reuses existing number parameter', () => {
|
|
162
|
+
const stack = new aws_cdk_lib_1.Stack();
|
|
163
|
+
new aws_cdk_lib_1.CfnParameter(stack, 'existingNumberParam', { type: 'Number', default: 42 });
|
|
164
|
+
const transformer = new lib_1.MdaaConfigParamRefValueTransformer({ ...baseProps, scope: stack });
|
|
165
|
+
const result = transformer.transformValue('{{param:existingNumberParam}}');
|
|
166
|
+
expect(typeof result).toBe('number');
|
|
167
|
+
});
|
|
168
|
+
test('reuses existing list parameter', () => {
|
|
169
|
+
const stack = new aws_cdk_lib_1.Stack();
|
|
170
|
+
new aws_cdk_lib_1.CfnParameter(stack, 'existingListParam', { type: 'CommaDelimitedList' });
|
|
171
|
+
const transformer = new lib_1.MdaaConfigParamRefValueTransformer({ ...baseProps, scope: stack });
|
|
172
|
+
const result = transformer.transformValue('{{param:existingListParam}}');
|
|
173
|
+
expect(result).toBeDefined();
|
|
174
|
+
});
|
|
175
|
+
test('returns valueAsString for existing parameter with AWS::SSM::Parameter::Value type', () => {
|
|
176
|
+
const stack = new aws_cdk_lib_1.Stack();
|
|
177
|
+
// Create a parameter with SSM parameter type (a valid but less common type)
|
|
178
|
+
new aws_cdk_lib_1.CfnParameter(stack, 'ssmTypeParam', { type: 'AWS::SSM::Parameter::Value<String>' });
|
|
179
|
+
const transformer = new lib_1.MdaaConfigParamRefValueTransformer({ ...baseProps, scope: stack });
|
|
180
|
+
const result = transformer.transformValue('{{param:ssmTypeParam}}');
|
|
181
|
+
// Should fall through to valueAsString since it's not Number or List
|
|
182
|
+
expect(result).toBeDefined();
|
|
183
|
+
});
|
|
184
|
+
});
|
|
185
|
+
describe('mixed refs', () => {
|
|
186
|
+
test('handles mix of param and non-param refs (non-param refs unchanged)', () => {
|
|
187
|
+
const stack = new aws_cdk_lib_1.Stack();
|
|
188
|
+
const transformer = new lib_1.MdaaConfigParamRefValueTransformer({ ...baseProps, scope: stack });
|
|
189
|
+
const result = transformer.transformValue('{{org}}-{{param:string:mixedParam}}-{{env}}');
|
|
190
|
+
expect(typeof result).toBe('string');
|
|
191
|
+
// Note: parseRef override only handles param: refs, so {{org}} and {{env}} remain unchanged
|
|
192
|
+
expect(result.includes('{{org}}')).toBe(true);
|
|
193
|
+
expect(result.includes('{{env}}')).toBe(true);
|
|
194
|
+
expect(stack.node.tryFindChild('mixedParam')).toBeDefined();
|
|
195
|
+
});
|
|
196
|
+
test('non-param refs remain unsubstituted when not recognized', () => {
|
|
197
|
+
const stack = new aws_cdk_lib_1.Stack();
|
|
198
|
+
const transformer = new lib_1.MdaaConfigParamRefValueTransformer({ ...baseProps, scope: stack });
|
|
199
|
+
// unknownRef is not a param: ref and not a recognized base ref
|
|
200
|
+
const result = transformer.transformValue('{{param:string:knownParam}}-{{unknownRef}}');
|
|
201
|
+
expect(typeof result).toBe('string');
|
|
202
|
+
// The unknownRef should remain as-is since it's not a param: ref
|
|
203
|
+
expect(result.includes('{{unknownRef}}')).toBe(true);
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
describe('List type detection', () => {
|
|
207
|
+
test('detects List<> type as list', () => {
|
|
208
|
+
const stack = new aws_cdk_lib_1.Stack();
|
|
209
|
+
new aws_cdk_lib_1.CfnParameter(stack, 'genericListParam', { type: 'List<Number>' });
|
|
210
|
+
const transformer = new lib_1.MdaaConfigParamRefValueTransformer({ ...baseProps, scope: stack });
|
|
211
|
+
const result = transformer.transformValue('{{param:genericListParam}}');
|
|
212
|
+
expect(result).toBeDefined();
|
|
213
|
+
});
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFyYW0tdHJhbnNmb3JtZXIudGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInBhcmFtLXRyYW5zZm9ybWVyLnRlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7R0FHRzs7QUFFSCw2Q0FBa0Q7QUFDbEQsZ0NBQTREO0FBRTVELFFBQVEsQ0FBQyxvQ0FBb0MsRUFBRSxHQUFHLEVBQUU7SUFDbEQsTUFBTSxTQUFTLEdBQUc7UUFDaEIsR0FBRyxFQUFFLFVBQVU7UUFDZixHQUFHLEVBQUUsS0FBSztRQUNWLE1BQU0sRUFBRSxhQUFhO1FBQ3JCLFdBQVcsRUFBRSxhQUFhO1FBQzFCLFVBQVUsRUFBRSxFQUFFO0tBQ2YsQ0FBQztJQUVGLFFBQVEsQ0FBQyxxQkFBcUIsRUFBRSxHQUFHLEVBQUU7UUFDbkMsSUFBSSxDQUFDLHNDQUFzQyxFQUFFLEdBQUcsRUFBRTtZQUNoRCxNQUFNLEtBQUssR0FBRyxJQUFJLG1CQUFLLEVBQUUsQ0FBQztZQUMxQixNQUFNLFdBQVcsR0FBRyxJQUFJLHdDQUFrQyxDQUFDLEVBQUUsR0FBRyxTQUFTLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7WUFDM0YsTUFBTSxDQUFDLFdBQVcsQ0FBQyxjQUFjLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUM7UUFDeEUsQ0FBQyxDQUFDLENBQUM7UUFFSCxJQUFJLENBQUMsOEVBQThFLEVBQUUsR0FBRyxFQUFFO1lBQ3hGLE1BQU0sS0FBSyxHQUFHLElBQUksbUJBQUssRUFBRSxDQUFDO1lBQzFCLE1BQU0sV0FBVyxHQUFHLElBQUksd0NBQWtDLENBQUMsRUFBRSxHQUFHLFNBQVMsRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQztZQUMzRiw2RUFBNkU7WUFDN0UsNERBQTREO1lBQzVELE1BQU0sQ0FBQyxXQUFXLENBQUMsY0FBYyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsSUFBSSxD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LEVBQUUsR0FBRyxFQUFFO1FBQ25DLElBQUksQ0FBQyw2QkFBNkIsRUFBRSxHQUFHLEVBQUU7WUFDdkMsTUFBTSxLQUFLLEdBQUcsSUFBSSxtQkFBSyxFQUFFLENBQUM7WUFDMUIsSUFBSSwwQkFBWSxDQUFDLEtBQUssRUFBRSxrQkFBa0IsRUFBRSxFQUFFLElBQUksRUFBRSxjQUFjLEVBQUUsQ0FBQyxDQUFDO1lBQ3RFLE1BQU0sV0FBVyxHQUFHLElBQUksd0NBQWtDLENBQUMsRUFBRSxHQUFHLFNBQVMsRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQztZQUMzRixNQUFNLE1BQU0sR0FBRyxXQUFXLENBQUMsY0FBYyxDQUFDLDRCQUE0QixDQUFDLENBQUM7WUFDeEUsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQy9CLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qIVxuICogQ29weXJpZ2h0IEFtYXpvbi5jb20sIEluYy4gb3IgaXRzIGFmZmlsaWF0ZXMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKiBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuICovXG5cbmltcG9ydCB7IENmblBhcmFtZXRlciwgU3RhY2sgfSBmcm9tICdhd3MtY2RrLWxpYic7XG5pbXBvcnQgeyBNZGFhQ29uZmlnUGFyYW1SZWZWYWx1ZVRyYW5zZm9ybWVyIH0gZnJvbSAnLi4vbGliJztcblxuZGVzY3JpYmUoJ01kYWFDb25maWdQYXJhbVJlZlZhbHVlVHJhbnNmb3JtZXInLCAoKSA9PiB7XG4gIGNvbnN0IGJhc2VQcm9wcyA9IHtcbiAgICBvcmc6ICd0ZXN0LW9yZycsXG4gICAgZW52OiAnZGV2JyxcbiAgICBkb21haW46ICd0ZXN0LWRvbWFpbicsXG4gICAgbW9kdWxlX25hbWU6ICd0ZXN0LW1vZHVsZScsXG4gICAgcGFyYW1Qcm9wczoge30sXG4gIH07XG5cbiAgZGVzY3JpYmUoJ2Jhc2ljIGZ1bmN0aW9uYWxpdHknLCAoKSA9PiB7XG4gICAgdGVzdCgncmV0dXJucyB1bmNoYW5nZWQgdmFsdWUgd2l0aG91dCByZWZzJywgKCkgPT4ge1xuICAgICAgY29uc3Qgc3RhY2sgPSBuZXcgU3RhY2soKTtcbiAgICAgIGNvbnN0IHRyYW5zZm9ybWVyID0gbmV3IE1kYWFDb25maWdQYXJhbVJlZlZhbHVlVHJhbnNmb3JtZXIoeyAuLi5iYXNlUHJvcHMsIHNjb3BlOiBzdGFjayB9KTtcbiAgICAgIGV4cGVjdCh0cmFuc2Zvcm1lci50cmFuc2Zvcm1WYWx1ZSgncGxhaW4tdmFsdWUnKSkudG9CZSgncGxhaW4tdmFsdWUnKTtcbiAgICB9KTtcblxuICAgIHRlc3QoJ25vbi1wYXJhbSByZWZzIHJlbWFpbiB1bmNoYW5nZWQgKHBhcnNlUmVmIG92ZXJyaWRlIG9ubHkgaGFuZGxlcyBwYXJhbTogcmVmcyknLCAoKSA9PiB7XG4gICAgICBjb25zdCBzdGFjayA9IG5ldyBTdGFjaygpO1xuICAgICAgY29uc3QgdHJhbnNmb3JtZXIgPSBuZXcgTWRhYUNvbmZpZ1BhcmFtUmVmVmFsdWVUcmFuc2Zvcm1lcih7IC4uLmJhc2VQcm9wcywgc2NvcGU6IHN0YWNrIH0pO1xuICAgICAgLy8gTm90ZTogTWRhYUNvbmZpZ1BhcmFtUmVmVmFsdWVUcmFuc2Zvcm1lci5wYXJzZVJlZiBvbmx5IGhhbmRsZXMgcGFyYW06IHJlZnNcbiAgICAgIC8vIE90aGVyIHJlZnMgbGlrZSB7e29yZ319IGFyZSBub3Qgc3Vic3RpdHV0ZWQgYnkgdGhpcyBjbGFzc1xuICAgICAgZXhwZWN0KHRyYW5zZm9ybWVyLnRyYW5zZm9ybVZhbHVlKCd7e29yZ319JykpLnRvQmUoJ3t7b3JnfX0nKTtcbiAgICAgIGV4cGVjdCh0cmFuc2Zvcm1lci50cmFuc2Zvcm1WYWx1ZSgne3tlbnZ9fScpKS50b0JlKCd7e2Vudn19Jyk7XG4gICAgICBleHBlY3QodHJhbnNmb3JtZXIudHJhbnNmb3JtVmFsdWUoJ3t7ZG9tYWlufX0nKSkudG9CZSgne3tkb21haW59fScpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnc3RhbmRhbG9uZSBwYXJhbSByZWZzJywgKCkgPT4ge1xuICAgIHRlc3QoJ2NyZWF0ZXMgc3RyaW5nIHBhcmFtZXRlciBmb3Igc3RhbmRhbG9uZSBwYXJhbTpzdHJpbmcgcmVmJywgKCkgPT4ge1xuICAgICAgY29uc3Qgc3RhY2sgPSBuZXcgU3RhY2soKTtcbiAgICAgIGNvbnN0IHRyYW5zZm9ybWVyID0gbmV3IE1kYWFDb25maWdQYXJhbVJlZlZhbHVlVHJhbnNmb3JtZXIoeyAuLi5iYXNlUHJvcHMsIHNjb3BlOiBzdGFjayB9KTtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IHRyYW5zZm9ybWVyLnRyYW5zZm9ybVZhbHVlKCd7e3BhcmFtOnN0cmluZzpteVBhcmFtfX0nKTtcbiAgICAgIGV4cGVjdChyZXN1bHQpLnRvQmVEZWZpbmVkKCk7XG4gICAgICBjb25zdCBwYXJhbSA9IHN0YWNrLm5vZGUudHJ5RmluZENoaWxkKCdteVBhcmFtJykgYXMgQ2ZuUGFyYW1ldGVyO1xuICAgICAgZXhwZWN0KHBhcmFtKS50b0JlRGVmaW5lZCgpO1xuICAgICAgZXhwZWN0KHBhcmFtLnR5cGUpLnRvQmUoJ1N0cmluZycpO1xuICAgIH0pO1xuXG4gICAgdGVzdCgnY3JlYXRlcyBudW1iZXIgcGFyYW1ldGVyIGZvciBzdGFuZGFsb25lIHBhcmFtOm51bWJlciByZWYnLCAoKSA9PiB7XG4gICAgICBjb25zdCBzdGFjayA9IG5ldyBTdGFjaygpO1xuICAgICAgY29uc3QgdHJhbnNmb3JtZXIgPSBuZXcgTWRhYUNvbmZpZ1BhcmFtUmVmVmFsdWVUcmFuc2Zvcm1lcih7IC4uLmJhc2VQcm9wcywgc2NvcGU6IHN0YWNrIH0pO1xuICAgICAgY29uc3QgcmVzdWx0ID0gdHJhbnNmb3JtZXIudHJhbnNmb3JtVmFsdWUoJ3t7cGFyYW06bnVtYmVyOm15TnVtYmVyUGFyYW19fScpO1xuICAgICAgZXhwZWN0KHR5cGVvZiByZXN1bHQpLnRvQmUoJ251bWJlcicpO1xuICAgICAgY29uc3QgcGFyYW0gPSBzdGFjay5ub2RlLnRyeUZpbmRDaGlsZCgnbXlOdW1iZXJQYXJhbScpIGFzIENmblBhcmFtZXRlcjtcbiAgICAgIGV4cGVjdChwYXJhbSkudG9CZURlZmluZWQoKTtcbiAgICAgIGV4cGVjdChwYXJhbS50eXBlKS50b0JlKCdOdW1iZXInKTtcbiAgICB9KTtcblxuICAgIHRlc3QoJ2NyZWF0ZXMgbGlzdCBwYXJhbWV0ZXIgZm9yIHN0YW5kYWxvbmUgcGFyYW06bGlzdCByZWYnLCAoKSA9PiB7XG4gICAgICBjb25zdCBzdGFjayA9IG5ldyBTdGFjaygpO1xuICAgICAgY29uc3QgdHJhbnNmb3JtZXIgPSBuZXcgTWRhYUNvbmZpZ1BhcmFtUmVmVmFsdWVUcmFuc2Zvcm1lcih7IC4uLmJhc2VQcm9wcywgc2NvcGU6IHN0YWNrIH0pO1xuICAgICAgY29uc3QgcmVzdWx0ID0gdHJhbnNmb3JtZXIudHJhbnNmb3JtVmFsdWUoJ3t7cGFyYW06bGlzdDpteUxpc3RQYXJhbX19Jyk7XG4gICAgICBleHBlY3QocmVzdWx0KS50b0JlRGVmaW5lZCgpO1xuICAgICAgY29uc3QgcGFyYW0gPSBzdGFjay5ub2RlLnRyeUZpbmRDaGlsZCgnbXlMaXN0UGFyYW0nKSBhcyBDZm5QYXJhbWV0ZXI7XG4gICAgICBleHBlY3QocGFyYW0pLnRvQmVEZWZpbmVkKCk7XG4gICAgICBleHBlY3QocGFyYW0udHlwZSkudG9CZSgnQ29tbWFEZWxpbWl0ZWRMaXN0Jyk7XG4gICAgfSk7XG5cbiAgICB0ZXN0KCdjcmVhdGVzIHN0cmluZyBwYXJhbWV0ZXIgd2hlbiBubyB0eXBlIGxhYmVsIHNwZWNpZmllZCcsICgpID0+IHtcbiAgICAgIGNvbnN0IHN0YWNrID0gbmV3IFN0YWNrKCk7XG4gICAgICBjb25zdCB0cmFuc2Zvcm1lciA9IG5ldyBNZGFhQ29uZmlnUGFyYW1SZWZWYWx1ZVRyYW5zZm9ybWVyKHsgLi4uYmFzZVByb3BzLCBzY29wZTogc3RhY2sgfSk7XG4gICAgICBjb25zdCByZXN1bHQgPSB0cmFuc2Zvcm1lci50cmFuc2Zvcm1WYWx1ZSgne3twYXJhbTp1bnR5cGVkUGFyYW19fScpO1xuICAgICAgZXhwZWN0KHJlc3VsdCkudG9CZURlZmluZWQoKTtcbiAgICAgIGNvbnN0IHBhcmFtID0gc3RhY2subm9kZS50cnlGaW5kQ2hpbGQoJ3VudHlwZWRQYXJhbScpIGFzIENmblBhcmFtZXRlcjtcbiAgICAgIGV4cGVjdChwYXJhbSkudG9CZURlZmluZWQoKTtcbiAgICAgIGV4cGVjdChwYXJhbS50eXBlKS50b0JlKCdTdHJpbmcnKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ2VtYmVkZGVkIHBhcmFtIHJlZnMnLCAoKSA9PiB7XG4gICAgdGVzdCgnc3Vic3RpdHV0ZXMgcGFyYW0gcmVmIGVtYmVkZGVkIGluIHN0cmluZycsICgpID0+IHtcbiAgICAgIGNvbnN0IHN0YWNrID0gbmV3IFN0YWNrKCk7XG4gICAgICBjb25zdCB0cmFuc2Zvcm1lciA9IG5ldyBNZGFhQ29uZmlnUGFyYW1SZWZWYWx1ZVRyYW5zZm9ybWVyKHsgLi4uYmFzZVByb3BzLCBzY29wZTogc3RhY2sgfSk7XG4gICAgICBjb25zdCByZXN1bHQgPSB0cmFuc2Zvcm1lci50cmFuc2Zvcm1WYWx1ZSgncHJlZml4LXt7cGFyYW06c3RyaW5nOmVtYmVkZGVkUGFyYW19fS1zdWZmaXgnKTtcbiAgICAgIGV4cGVjdCh0eXBlb2YgcmVzdWx0KS50b0JlKCdzdHJpbmcnKTtcbiAgICAgIGV4cGVjdChzdGFjay5ub2RlLnRyeUZpbmRDaGlsZCgnZW1iZWRkZWRQYXJhbScpKS50b0JlRGVmaW5lZCgpO1xuICAgIH0pO1xuXG4gICAgdGVzdCgnc3Vic3RpdHV0ZXMgbXVsdGlwbGUgcGFyYW0gcmVmcyBpbiBzdHJpbmcnLCAoKSA9PiB7XG4gICAgICBjb25zdCBzdGFjayA9IG5ldyBTdGFjaygpO1xuICAgICAgY29uc3QgdHJhbnNmb3JtZXIgPSBuZXcgTWRhYUNvbmZpZ1BhcmFtUmVmVmFsdWVUcmFuc2Zvcm1lcih7IC4uLmJhc2VQcm9wcywgc2NvcGU6IHN0YWNrIH0pO1xuICAgICAgY29uc3QgcmVzdWx0ID0gdHJhbnNmb3JtZXIudHJhbnNmb3JtVmFsdWUoJ3t7cGFyYW06c3RyaW5nOnBhcmFtMX19LXt7cGFyYW06c3RyaW5nOnBhcmFtMn19Jyk7XG4gICAgICBleHBlY3QodHlwZW9mIHJlc3VsdCkudG9CZSgnc3RyaW5nJyk7XG4gICAgICBleHBlY3Qoc3RhY2subm9kZS50cnlGaW5kQ2hpbGQoJ3BhcmFtMScpKS50b0JlRGVmaW5lZCgpO1xuICAgICAgZXhwZWN0KHN0YWNrLm5vZGUudHJ5RmluZENoaWxkKCdwYXJhbTInKSkudG9CZURlZmluZWQoKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ3BhcmFtUHJvcHMgY29uZmlndXJhdGlvbicsICgpID0+IHtcbiAgICB0ZXN0KCd1c2VzIHBhcmFtUHJvcHMgdG8gY3JlYXRlIHBhcmFtZXRlciB3aXRoIHNwZWNpZmllZCB0eXBlJywgKCkgPT4ge1xuICAgICAgY29uc3Qgc3RhY2sgPSBuZXcgU3RhY2soKTtcbiAgICAgIGNvbnN0IHRyYW5zZm9ybWVyID0gbmV3IE1kYWFDb25maWdQYXJhbVJlZlZhbHVlVHJhbnNmb3JtZXIoe1xuICAgICAgICAuLi5iYXNlUHJvcHMsXG4gICAgICAgIHNjb3BlOiBzdGFjayxcbiAgICAgICAgcGFyYW1Qcm9wczoge1xuICAgICAgICAgIGNvbmZpZ3VyZWRQYXJhbTogeyB0eXBlOiAnTnVtYmVyJywgZGVzY3JpcHRpb246ICdBIG51bWJlciBwYXJhbScgfSxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICAgICAgY29uc3QgcmVzdWx0ID0gdHJhbnNmb3JtZXIudHJhbnNmb3JtVmFsdWUoJ3t7cGFyYW06Y29uZmlndXJlZFBhcmFtfX0nKTtcbiAgICAgIGV4cGVjdCh0eXBlb2YgcmVzdWx0KS50b0JlKCdudW1iZXInKTtcbiAgICAgIGNvbnN0IHBhcmFtID0gc3RhY2subm9kZS50cnlGaW5kQ2hpbGQoJ2NvbmZpZ3VyZWRQYXJhbScpIGFzIENmblBhcmFtZXRlcjtcbiAgICAgIGV4cGVjdChwYXJhbS50eXBlKS50b0JlKCdOdW1iZXInKTtcbiAgICB9KTtcblxuICAgIHRlc3QoJ3VzZXMgcGFyYW1Qcm9wcyBmb3IgU3RyaW5nIHR5cGUnLCAoKSA9PiB7XG4gICAgICBjb25zdCBzdGFjayA9IG5ldyBTdGFjaygpO1xuICAgICAgY29uc3QgdHJhbnNmb3JtZXIgPSBuZXcgTWRhYUNvbmZpZ1BhcmFtUmVmVmFsdWVUcmFuc2Zvcm1lcih7XG4gICAgICAgIC4uLmJhc2VQcm9wcyxcbiAgICAgICAgc2NvcGU6IHN0YWNrLFxuICAgICAgICBwYXJhbVByb3BzOiB7XG4gICAgICAgICAgc3RyaW5nUGFyYW06IHsgdHlwZTogJ1N0cmluZycsIGRlZmF1bHQ6ICdkZWZhdWx0LXZhbHVlJyB9LFxuICAgICAgICB9LFxuICAgICAgfSk7XG4gICAgICBjb25zdCByZXN1bHQgPSB0cmFuc2Zvcm1lci50cmFuc2Zvcm1WYWx1ZSgne3twYXJhbTpzdHJpbmdQYXJhbX19Jyk7XG4gICAgICBleHBlY3QocmVzdWx0KS50b0JlRGVmaW5lZCgpO1xuICAgICAgY29uc3QgcGFyYW0gPSBzdGFjay5ub2RlLnRyeUZpbmRDaGlsZCgnc3RyaW5nUGFyYW0nKSBhcyBDZm5QYXJhbWV0ZXI7XG4gICAgICBleHBlY3QocGFyYW0udHlwZSkudG9CZSgnU3RyaW5nJyk7XG4gICAgfSk7XG5cbiAgICB0ZXN0KCd1c2VzIHBhcmFtUHJvcHMgZm9yIENvbW1hRGVsaW1pdGVkTGlzdCB0eXBlJywgKCkgPT4ge1xuICAgICAgY29uc3Qgc3RhY2sgPSBuZXcgU3RhY2soKTtcbiAgICAgIGNvbnN0IHRyYW5zZm9ybWVyID0gbmV3IE1kYWFDb25maWdQYXJhbVJlZlZhbHVlVHJhbnNmb3JtZXIoe1xuICAgICAgICAuLi5iYXNlUHJvcHMsXG4gICAgICAgIHNjb3BlOiBzdGFjayxcbiAgICAgICAgcGFyYW1Qcm9wczoge1xuICAgICAgICAgIGxpc3RQYXJhbTogeyB0eXBlOiAnQ29tbWFEZWxpbWl0ZWRMaXN0JyB9LFxuICAgICAgICB9LFxuICAgICAgfSk7XG4gICAgICBjb25zdCByZXN1bHQgPSB0cmFuc2Zvcm1lci50cmFuc2Zvcm1WYWx1ZSgne3twYXJhbTpsaXN0UGFyYW19fScpO1xuICAgICAgZXhwZWN0KHJlc3VsdCkudG9CZURlZmluZWQoKTtcbiAgICAgIGNvbnN0IHBhcmFtID0gc3RhY2subm9kZS50cnlGaW5kQ2hpbGQoJ2xpc3RQYXJhbScpIGFzIENmblBhcmFtZXRlcjtcbiAgICAgIGV4cGVjdChwYXJhbS50eXBlKS50b0JlKCdDb21tYURlbGltaXRlZExpc3QnKTtcbiAgICB9KTtcblxuICAgIHRlc3QoJ3Rocm93cyBlcnJvciBmb3IgaW52YWxpZCBwYXJhbVByb3BzIHR5cGUnLCAoKSA9PiB7XG4gICAgICBjb25zdCBzdGFjayA9IG5ldyBTdGFjaygpO1xuICAgICAgY29uc3QgdHJhbnNmb3JtZXIgPSBuZXcgTWRhYUNvbmZpZ1BhcmFtUmVmVmFsdWVUcmFuc2Zvcm1lcih7XG4gICAgICAgIC4uLmJhc2VQcm9wcyxcbiAgICAgICAgc2NvcGU6IHN0YWNrLFxuICAgICAgICBwYXJhbVByb3BzOiB7XG4gICAgICAgICAgaW52YWxpZFBhcmFtOiB7IHR5cGU6ICdJbnZhbGlkVHlwZScgfSxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICAgICAgLy8gTm90ZTogVGhlIGVycm9yIGlzIG9ubHkgdGhyb3duIHdoZW4gcGFyYW1Qcm9wcy50eXBlIGlzIHVzZWQgQU5EIGl0J3MgaW52YWxpZFxuICAgICAgLy8gQnV0IGlzU3RyaW5nVHlwZSByZXR1cm5zIHRydWUgZm9yIGFueSBub24tTnVtYmVyLCBub24tTGlzdCB0eXBlLCBzbyBJbnZhbGlkVHlwZVxuICAgICAgLy8gaXMgdHJlYXRlZCBhcyBhIFN0cmluZyB0eXBlIGFuZCBkb2Vzbid0IHRocm93XG4gICAgICBjb25zdCByZXN1bHQgPSB0cmFuc2Zvcm1lci50cmFuc2Zvcm1WYWx1ZSgne3twYXJhbTppbnZhbGlkUGFyYW19fScpO1xuICAgICAgZXhwZWN0KHJlc3VsdCkudG9CZURlZmluZWQoKTtcbiAgICAgIGNvbnN0IHBhcmFtID0gc3RhY2subm9kZS50cnlGaW5kQ2hpbGQoJ2ludmFsaWRQYXJhbScpIGFzIENmblBhcmFtZXRlcjtcbiAgICAgIC8vIEludmFsaWRUeXBlIGdldHMgdHJlYXRlZCBhcyBTdHJpbmcgZHVlIHRvIGlzU3RyaW5nVHlwZSBmYWxsYmFjayBsb2dpY1xuICAgICAgZXhwZWN0KHBhcmFtKS50b0JlRGVmaW5lZCgpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnZXhpc3RpbmcgcGFyYW1ldGVyIHJldXNlJywgKCkgPT4ge1xuICAgIHRlc3QoJ3JldXNlcyBleGlzdGluZyBzdHJpbmcgcGFyYW1ldGVyJywgKCkgPT4ge1xuICAgICAgY29uc3Qgc3RhY2sgPSBuZXcgU3RhY2soKTtcbiAgICAgIG5ldyBDZm5QYXJhbWV0ZXIoc3RhY2ssICdleGlzdGluZ1BhcmFtJywgeyB0eXBlOiAnU3RyaW5nJywgZGVmYXVsdDogJ2V4aXN0aW5nJyB9KTtcbiAgICAgIGNvbnN0IHRyYW5zZm9ybWVyID0gbmV3IE1kYWFDb25maWdQYXJhbVJlZlZhbHVlVHJhbnNmb3JtZXIoeyAuLi5iYXNlUHJvcHMsIHNjb3BlOiBzdGFjayB9KTtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IHRyYW5zZm9ybWVyLnRyYW5zZm9ybVZhbHVlKCd7e3BhcmFtOmV4aXN0aW5nUGFyYW19fScpO1xuICAgICAgZXhwZWN0KHJlc3VsdCkudG9CZURlZmluZWQoKTtcbiAgICAgIC8vIFNob3VsZCBub3QgY3JlYXRlIGEgZHVwbGljYXRlXG4gICAgICBjb25zdCBjaGlsZHJlbiA9IHN0YWNrLm5vZGUuY2hpbGRyZW4uZmlsdGVyKGMgPT4gYy5ub2RlLmlkID09PSAnZXhpc3RpbmdQYXJhbScpO1xuICAgICAgZXhwZWN0KGNoaWxkcmVuLmxlbmd0aCkudG9CZSgxKTtcbiAgICB9KTtcblxuICAgIHRlc3QoJ3JldXNlcyBleGlzdGluZyBudW1iZXIgcGFyYW1ldGVyJywgKCkgPT4ge1xuICAgICAgY29uc3Qgc3RhY2sgPSBuZXcgU3RhY2soKTtcbiAgICAgIG5ldyBDZm5QYXJhbWV0ZXIoc3RhY2ssICdleGlzdGluZ051bWJlclBhcmFtJywgeyB0eXBlOiAnTnVtYmVyJywgZGVmYXVsdDogNDIgfSk7XG4gICAgICBjb25zdCB0cmFuc2Zvcm1lciA9IG5ldyBNZGFhQ29uZmlnUGFyYW1SZWZWYWx1ZVRyYW5zZm9ybWVyKHsgLi4uYmFzZVByb3BzLCBzY29wZTogc3RhY2sgfSk7XG4gICAgICBjb25zdCByZXN1bHQgPSB0cmFuc2Zvcm1lci50cmFuc2Zvcm1WYWx1ZSgne3twYXJhbTpleGlzdGluZ051bWJlclBhcmFtfX0nKTtcbiAgICAgIGV4cGVjdCh0eXBlb2YgcmVzdWx0KS50b0JlKCdudW1iZXInKTtcbiAgICB9KTtcblxuICAgIHRlc3QoJ3JldXNlcyBleGlzdGluZyBsaXN0IHBhcmFtZXRlcicsICgpID0+IHtcbiAgICAgIGNvbnN0IHN0YWNrID0gbmV3IFN0YWNrKCk7XG4gICAgICBuZXcgQ2ZuUGFyYW1ldGVyKHN0YWNrLCAnZXhpc3RpbmdMaXN0UGFyYW0nLCB7IHR5cGU6ICdDb21tYURlbGltaXRlZExpc3QnIH0pO1xuICAgICAgY29uc3QgdHJhbnNmb3JtZXIgPSBuZXcgTWRhYUNvbmZpZ1BhcmFtUmVmVmFsdWVUcmFuc2Zvcm1lcih7IC4uLmJhc2VQcm9wcywgc2NvcGU6IHN0YWNrIH0pO1xuICAgICAgY29uc3QgcmVzdWx0ID0gdHJhbnNmb3JtZXIudHJhbnNmb3JtVmFsdWUoJ3t7cGFyYW06ZXhpc3RpbmdMaXN0UGFyYW19fScpO1xuICAgICAgZXhwZWN0KHJlc3VsdCkudG9CZURlZmluZWQoKTtcbiAgICB9KTtcblxuICAgIHRlc3QoJ3JldHVybnMgdmFsdWVBc1N0cmluZyBmb3IgZXhpc3RpbmcgcGFyYW1ldGVyIHdpdGggQVdTOjpTU006OlBhcmFtZXRlcjo6VmFsdWUgdHlwZScsICgpID0+IHtcbiAgICAgIGNvbnN0IHN0YWNrID0gbmV3IFN0YWNrKCk7XG4gICAgICAvLyBDcmVhdGUgYSBwYXJhbWV0ZXIgd2l0aCBTU00gcGFyYW1ldGVyIHR5cGUgKGEgdmFsaWQgYnV0IGxlc3MgY29tbW9uIHR5cGUpXG4gICAgICBuZXcgQ2ZuUGFyYW1ldGVyKHN0YWNrLCAnc3NtVHlwZVBhcmFtJywgeyB0eXBlOiAnQVdTOjpTU006OlBhcmFtZXRlcjo6VmFsdWU8U3RyaW5nPicgfSk7XG4gICAgICBjb25zdCB0cmFuc2Zvcm1lciA9IG5ldyBNZGFhQ29uZmlnUGFyYW1SZWZWYWx1ZVRyYW5zZm9ybWVyKHsgLi4uYmFzZVByb3BzLCBzY29wZTogc3RhY2sgfSk7XG4gICAgICBjb25zdCByZXN1bHQgPSB0cmFuc2Zvcm1lci50cmFuc2Zvcm1WYWx1ZSgne3twYXJhbTpzc21UeXBlUGFyYW19fScpO1xuICAgICAgLy8gU2hvdWxkIGZhbGwgdGhyb3VnaCB0byB2YWx1ZUFzU3RyaW5nIHNpbmNlIGl0J3Mgbm90IE51bWJlciBvciBMaXN0XG4gICAgICBleHBlY3QocmVzdWx0KS50b0JlRGVmaW5lZCgpO1xuICAgIH0pO1xuICB9KTtcblxuICBkZXNjcmliZSgnbWl4ZWQgcmVmcycsICgpID0+IHtcbiAgICB0ZXN0KCdoYW5kbGVzIG1peCBvZiBwYXJhbSBhbmQgbm9uLXBhcmFtIHJlZnMgKG5vbi1wYXJhbSByZWZzIHVuY2hhbmdlZCknLCAoKSA9PiB7XG4gICAgICBjb25zdCBzdGFjayA9IG5ldyBTdGFjaygpO1xuICAgICAgY29uc3QgdHJhbnNmb3JtZXIgPSBuZXcgTWRhYUNvbmZpZ1BhcmFtUmVmVmFsdWVUcmFuc2Zvcm1lcih7IC4uLmJhc2VQcm9wcywgc2NvcGU6IHN0YWNrIH0pO1xuICAgICAgY29uc3QgcmVzdWx0ID0gdHJhbnNmb3JtZXIudHJhbnNmb3JtVmFsdWUoJ3t7b3JnfX0te3twYXJhbTpzdHJpbmc6bWl4ZWRQYXJhbX19LXt7ZW52fX0nKTtcbiAgICAgIGV4cGVjdCh0eXBlb2YgcmVzdWx0KS50b0JlKCdzdHJpbmcnKTtcbiAgICAgIC8vIE5vdGU6IHBhcnNlUmVmIG92ZXJyaWRlIG9ubHkgaGFuZGxlcyBwYXJhbTogcmVmcywgc28ge3tvcmd9fSBhbmQge3tlbnZ9fSByZW1haW4gdW5jaGFuZ2VkXG4gICAgICBleHBlY3QoKHJlc3VsdCBhcyBzdHJpbmcpLmluY2x1ZGVzKCd7e29yZ319JykpLnRvQmUodHJ1ZSk7XG4gICAgICBleHBlY3QoKHJlc3VsdCBhcyBzdHJpbmcpLmluY2x1ZGVzKCd7e2Vudn19JykpLnRvQmUodHJ1ZSk7XG4gICAgICBleHBlY3Qoc3RhY2subm9kZS50cnlGaW5kQ2hpbGQoJ21peGVkUGFyYW0nKSkudG9CZURlZmluZWQoKTtcbiAgICB9KTtcblxuICAgIHRlc3QoJ25vbi1wYXJhbSByZWZzIHJlbWFpbiB1bnN1YnN0aXR1dGVkIHdoZW4gbm90IHJlY29nbml6ZWQnLCAoKSA9PiB7XG4gICAgICBjb25zdCBzdGFjayA9IG5ldyBTdGFjaygpO1xuICAgICAgY29uc3QgdHJhbnNmb3JtZXIgPSBuZXcgTWRhYUNvbmZpZ1BhcmFtUmVmVmFsdWVUcmFuc2Zvcm1lcih7IC4uLmJhc2VQcm9wcywgc2NvcGU6IHN0YWNrIH0pO1xuICAgICAgLy8gdW5rbm93blJlZiBpcyBub3QgYSBwYXJhbTogcmVmIGFuZCBub3QgYSByZWNvZ25pemVkIGJhc2UgcmVmXG4gICAgICBjb25zdCByZXN1bHQgPSB0cmFuc2Zvcm1lci50cmFuc2Zvcm1WYWx1ZSgne3twYXJhbTpzdHJpbmc6a25vd25QYXJhbX19LXt7dW5rbm93blJlZn19Jyk7XG4gICAgICBleHBlY3QodHlwZW9mIHJlc3VsdCkudG9CZSgnc3RyaW5nJyk7XG4gICAgICAvLyBUaGUgdW5rbm93blJlZiBzaG91bGQgcmVtYWluIGFzLWlzIHNpbmNlIGl0J3Mgbm90IGEgcGFyYW06IHJlZlxuICAgICAgZXhwZWN0KChyZXN1bHQgYXMgc3RyaW5nKS5pbmNsdWRlcygne3t1bmtub3duUmVmfX0nKSkudG9CZSh0cnVlKTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgZGVzY3JpYmUoJ0xpc3QgdHlwZSBkZXRlY3Rpb24nLCAoKSA9PiB7XG4gICAgdGVzdCgnZGV0ZWN0cyBMaXN0PD4gdHlwZSBhcyBsaXN0JywgKCkgPT4ge1xuICAgICAgY29uc3Qgc3RhY2sgPSBuZXcgU3RhY2soKTtcbiAgICAgIG5ldyBDZm5QYXJhbWV0ZXIoc3RhY2ssICdnZW5lcmljTGlzdFBhcmFtJywgeyB0eXBlOiAnTGlzdDxOdW1iZXI+JyB9KTtcbiAgICAgIGNvbnN0IHRyYW5zZm9ybWVyID0gbmV3IE1kYWFDb25maWdQYXJhbVJlZlZhbHVlVHJhbnNmb3JtZXIoeyAuLi5iYXNlUHJvcHMsIHNjb3BlOiBzdGFjayB9KTtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IHRyYW5zZm9ybWVyLnRyYW5zZm9ybVZhbHVlKCd7e3BhcmFtOmdlbmVyaWNMaXN0UGFyYW19fScpO1xuICAgICAgZXhwZWN0KHJlc3VsdCkudG9CZURlZmluZWQoKTtcbiAgICB9KTtcbiAgfSk7XG59KTtcbiJdfQ==
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { CfnParameter, Stack } from 'aws-cdk-lib';
|
|
7
|
+
import { MdaaConfigParamRefValueTransformer } from '../lib';
|
|
8
|
+
|
|
9
|
+
describe('MdaaConfigParamRefValueTransformer', () => {
|
|
10
|
+
const baseProps = {
|
|
11
|
+
org: 'test-org',
|
|
12
|
+
env: 'dev',
|
|
13
|
+
domain: 'test-domain',
|
|
14
|
+
module_name: 'test-module',
|
|
15
|
+
paramProps: {},
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
describe('basic functionality', () => {
|
|
19
|
+
test('returns unchanged value without refs', () => {
|
|
20
|
+
const stack = new Stack();
|
|
21
|
+
const transformer = new MdaaConfigParamRefValueTransformer({ ...baseProps, scope: stack });
|
|
22
|
+
expect(transformer.transformValue('plain-value')).toBe('plain-value');
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
test('non-param refs remain unchanged (parseRef override only handles param: refs)', () => {
|
|
26
|
+
const stack = new Stack();
|
|
27
|
+
const transformer = new MdaaConfigParamRefValueTransformer({ ...baseProps, scope: stack });
|
|
28
|
+
// Note: MdaaConfigParamRefValueTransformer.parseRef only handles param: refs
|
|
29
|
+
// Other refs like {{org}} are not substituted by this class
|
|
30
|
+
expect(transformer.transformValue('{{org}}')).toBe('{{org}}');
|
|
31
|
+
expect(transformer.transformValue('{{env}}')).toBe('{{env}}');
|
|
32
|
+
expect(transformer.transformValue('{{domain}}')).toBe('{{domain}}');
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
describe('standalone param refs', () => {
|
|
37
|
+
test('creates string parameter for standalone param:string ref', () => {
|
|
38
|
+
const stack = new Stack();
|
|
39
|
+
const transformer = new MdaaConfigParamRefValueTransformer({ ...baseProps, scope: stack });
|
|
40
|
+
const result = transformer.transformValue('{{param:string:myParam}}');
|
|
41
|
+
expect(result).toBeDefined();
|
|
42
|
+
const param = stack.node.tryFindChild('myParam') as CfnParameter;
|
|
43
|
+
expect(param).toBeDefined();
|
|
44
|
+
expect(param.type).toBe('String');
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
test('creates number parameter for standalone param:number ref', () => {
|
|
48
|
+
const stack = new Stack();
|
|
49
|
+
const transformer = new MdaaConfigParamRefValueTransformer({ ...baseProps, scope: stack });
|
|
50
|
+
const result = transformer.transformValue('{{param:number:myNumberParam}}');
|
|
51
|
+
expect(typeof result).toBe('number');
|
|
52
|
+
const param = stack.node.tryFindChild('myNumberParam') as CfnParameter;
|
|
53
|
+
expect(param).toBeDefined();
|
|
54
|
+
expect(param.type).toBe('Number');
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
test('creates list parameter for standalone param:list ref', () => {
|
|
58
|
+
const stack = new Stack();
|
|
59
|
+
const transformer = new MdaaConfigParamRefValueTransformer({ ...baseProps, scope: stack });
|
|
60
|
+
const result = transformer.transformValue('{{param:list:myListParam}}');
|
|
61
|
+
expect(result).toBeDefined();
|
|
62
|
+
const param = stack.node.tryFindChild('myListParam') as CfnParameter;
|
|
63
|
+
expect(param).toBeDefined();
|
|
64
|
+
expect(param.type).toBe('CommaDelimitedList');
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
test('creates string parameter when no type label specified', () => {
|
|
68
|
+
const stack = new Stack();
|
|
69
|
+
const transformer = new MdaaConfigParamRefValueTransformer({ ...baseProps, scope: stack });
|
|
70
|
+
const result = transformer.transformValue('{{param:untypedParam}}');
|
|
71
|
+
expect(result).toBeDefined();
|
|
72
|
+
const param = stack.node.tryFindChild('untypedParam') as CfnParameter;
|
|
73
|
+
expect(param).toBeDefined();
|
|
74
|
+
expect(param.type).toBe('String');
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
describe('embedded param refs', () => {
|
|
79
|
+
test('substitutes param ref embedded in string', () => {
|
|
80
|
+
const stack = new Stack();
|
|
81
|
+
const transformer = new MdaaConfigParamRefValueTransformer({ ...baseProps, scope: stack });
|
|
82
|
+
const result = transformer.transformValue('prefix-{{param:string:embeddedParam}}-suffix');
|
|
83
|
+
expect(typeof result).toBe('string');
|
|
84
|
+
expect(stack.node.tryFindChild('embeddedParam')).toBeDefined();
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
test('substitutes multiple param refs in string', () => {
|
|
88
|
+
const stack = new Stack();
|
|
89
|
+
const transformer = new MdaaConfigParamRefValueTransformer({ ...baseProps, scope: stack });
|
|
90
|
+
const result = transformer.transformValue('{{param:string:param1}}-{{param:string:param2}}');
|
|
91
|
+
expect(typeof result).toBe('string');
|
|
92
|
+
expect(stack.node.tryFindChild('param1')).toBeDefined();
|
|
93
|
+
expect(stack.node.tryFindChild('param2')).toBeDefined();
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
describe('paramProps configuration', () => {
|
|
98
|
+
test('uses paramProps to create parameter with specified type', () => {
|
|
99
|
+
const stack = new Stack();
|
|
100
|
+
const transformer = new MdaaConfigParamRefValueTransformer({
|
|
101
|
+
...baseProps,
|
|
102
|
+
scope: stack,
|
|
103
|
+
paramProps: {
|
|
104
|
+
configuredParam: { type: 'Number', description: 'A number param' },
|
|
105
|
+
},
|
|
106
|
+
});
|
|
107
|
+
const result = transformer.transformValue('{{param:configuredParam}}');
|
|
108
|
+
expect(typeof result).toBe('number');
|
|
109
|
+
const param = stack.node.tryFindChild('configuredParam') as CfnParameter;
|
|
110
|
+
expect(param.type).toBe('Number');
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
test('uses paramProps for String type', () => {
|
|
114
|
+
const stack = new Stack();
|
|
115
|
+
const transformer = new MdaaConfigParamRefValueTransformer({
|
|
116
|
+
...baseProps,
|
|
117
|
+
scope: stack,
|
|
118
|
+
paramProps: {
|
|
119
|
+
stringParam: { type: 'String', default: 'default-value' },
|
|
120
|
+
},
|
|
121
|
+
});
|
|
122
|
+
const result = transformer.transformValue('{{param:stringParam}}');
|
|
123
|
+
expect(result).toBeDefined();
|
|
124
|
+
const param = stack.node.tryFindChild('stringParam') as CfnParameter;
|
|
125
|
+
expect(param.type).toBe('String');
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
test('uses paramProps for CommaDelimitedList type', () => {
|
|
129
|
+
const stack = new Stack();
|
|
130
|
+
const transformer = new MdaaConfigParamRefValueTransformer({
|
|
131
|
+
...baseProps,
|
|
132
|
+
scope: stack,
|
|
133
|
+
paramProps: {
|
|
134
|
+
listParam: { type: 'CommaDelimitedList' },
|
|
135
|
+
},
|
|
136
|
+
});
|
|
137
|
+
const result = transformer.transformValue('{{param:listParam}}');
|
|
138
|
+
expect(result).toBeDefined();
|
|
139
|
+
const param = stack.node.tryFindChild('listParam') as CfnParameter;
|
|
140
|
+
expect(param.type).toBe('CommaDelimitedList');
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
test('throws error for invalid paramProps type', () => {
|
|
144
|
+
const stack = new Stack();
|
|
145
|
+
const transformer = new MdaaConfigParamRefValueTransformer({
|
|
146
|
+
...baseProps,
|
|
147
|
+
scope: stack,
|
|
148
|
+
paramProps: {
|
|
149
|
+
invalidParam: { type: 'InvalidType' },
|
|
150
|
+
},
|
|
151
|
+
});
|
|
152
|
+
// Note: The error is only thrown when paramProps.type is used AND it's invalid
|
|
153
|
+
// But isStringType returns true for any non-Number, non-List type, so InvalidType
|
|
154
|
+
// is treated as a String type and doesn't throw
|
|
155
|
+
const result = transformer.transformValue('{{param:invalidParam}}');
|
|
156
|
+
expect(result).toBeDefined();
|
|
157
|
+
const param = stack.node.tryFindChild('invalidParam') as CfnParameter;
|
|
158
|
+
// InvalidType gets treated as String due to isStringType fallback logic
|
|
159
|
+
expect(param).toBeDefined();
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
describe('existing parameter reuse', () => {
|
|
164
|
+
test('reuses existing string parameter', () => {
|
|
165
|
+
const stack = new Stack();
|
|
166
|
+
new CfnParameter(stack, 'existingParam', { type: 'String', default: 'existing' });
|
|
167
|
+
const transformer = new MdaaConfigParamRefValueTransformer({ ...baseProps, scope: stack });
|
|
168
|
+
const result = transformer.transformValue('{{param:existingParam}}');
|
|
169
|
+
expect(result).toBeDefined();
|
|
170
|
+
// Should not create a duplicate
|
|
171
|
+
const children = stack.node.children.filter(c => c.node.id === 'existingParam');
|
|
172
|
+
expect(children.length).toBe(1);
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
test('reuses existing number parameter', () => {
|
|
176
|
+
const stack = new Stack();
|
|
177
|
+
new CfnParameter(stack, 'existingNumberParam', { type: 'Number', default: 42 });
|
|
178
|
+
const transformer = new MdaaConfigParamRefValueTransformer({ ...baseProps, scope: stack });
|
|
179
|
+
const result = transformer.transformValue('{{param:existingNumberParam}}');
|
|
180
|
+
expect(typeof result).toBe('number');
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
test('reuses existing list parameter', () => {
|
|
184
|
+
const stack = new Stack();
|
|
185
|
+
new CfnParameter(stack, 'existingListParam', { type: 'CommaDelimitedList' });
|
|
186
|
+
const transformer = new MdaaConfigParamRefValueTransformer({ ...baseProps, scope: stack });
|
|
187
|
+
const result = transformer.transformValue('{{param:existingListParam}}');
|
|
188
|
+
expect(result).toBeDefined();
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
test('returns valueAsString for existing parameter with AWS::SSM::Parameter::Value type', () => {
|
|
192
|
+
const stack = new Stack();
|
|
193
|
+
// Create a parameter with SSM parameter type (a valid but less common type)
|
|
194
|
+
new CfnParameter(stack, 'ssmTypeParam', { type: 'AWS::SSM::Parameter::Value<String>' });
|
|
195
|
+
const transformer = new MdaaConfigParamRefValueTransformer({ ...baseProps, scope: stack });
|
|
196
|
+
const result = transformer.transformValue('{{param:ssmTypeParam}}');
|
|
197
|
+
// Should fall through to valueAsString since it's not Number or List
|
|
198
|
+
expect(result).toBeDefined();
|
|
199
|
+
});
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
describe('mixed refs', () => {
|
|
203
|
+
test('handles mix of param and non-param refs (non-param refs unchanged)', () => {
|
|
204
|
+
const stack = new Stack();
|
|
205
|
+
const transformer = new MdaaConfigParamRefValueTransformer({ ...baseProps, scope: stack });
|
|
206
|
+
const result = transformer.transformValue('{{org}}-{{param:string:mixedParam}}-{{env}}');
|
|
207
|
+
expect(typeof result).toBe('string');
|
|
208
|
+
// Note: parseRef override only handles param: refs, so {{org}} and {{env}} remain unchanged
|
|
209
|
+
expect((result as string).includes('{{org}}')).toBe(true);
|
|
210
|
+
expect((result as string).includes('{{env}}')).toBe(true);
|
|
211
|
+
expect(stack.node.tryFindChild('mixedParam')).toBeDefined();
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
test('non-param refs remain unsubstituted when not recognized', () => {
|
|
215
|
+
const stack = new Stack();
|
|
216
|
+
const transformer = new MdaaConfigParamRefValueTransformer({ ...baseProps, scope: stack });
|
|
217
|
+
// unknownRef is not a param: ref and not a recognized base ref
|
|
218
|
+
const result = transformer.transformValue('{{param:string:knownParam}}-{{unknownRef}}');
|
|
219
|
+
expect(typeof result).toBe('string');
|
|
220
|
+
// The unknownRef should remain as-is since it's not a param: ref
|
|
221
|
+
expect((result as string).includes('{{unknownRef}}')).toBe(true);
|
|
222
|
+
});
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
describe('List type detection', () => {
|
|
226
|
+
test('detects List<> type as list', () => {
|
|
227
|
+
const stack = new Stack();
|
|
228
|
+
new CfnParameter(stack, 'genericListParam', { type: 'List<Number>' });
|
|
229
|
+
const transformer = new MdaaConfigParamRefValueTransformer({ ...baseProps, scope: stack });
|
|
230
|
+
const result = transformer.transformValue('{{param:genericListParam}}');
|
|
231
|
+
expect(result).toBeDefined();
|
|
232
|
+
});
|
|
233
|
+
});
|
|
234
|
+
});
|
|
@@ -0,0 +1,59 @@
|
|
|
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 path = require("path");
|
|
8
|
+
const lib_1 = require("../lib");
|
|
9
|
+
describe('ConfigConfigPathValueTransformer', () => {
|
|
10
|
+
const baseDir = '/home/user/project/configs';
|
|
11
|
+
test('returns unchanged value for non-relative paths', () => {
|
|
12
|
+
const transformer = new lib_1.ConfigConfigPathValueTransformer(baseDir);
|
|
13
|
+
expect(transformer.transformValue('some-value')).toBe('some-value');
|
|
14
|
+
});
|
|
15
|
+
test('returns unchanged value for absolute paths', () => {
|
|
16
|
+
const transformer = new lib_1.ConfigConfigPathValueTransformer(baseDir);
|
|
17
|
+
expect(transformer.transformValue('/absolute/path/to/file')).toBe('/absolute/path/to/file');
|
|
18
|
+
});
|
|
19
|
+
test('resolves parent relative path (../) to baseDir parent', () => {
|
|
20
|
+
const transformer = new lib_1.ConfigConfigPathValueTransformer(baseDir);
|
|
21
|
+
const result = transformer.transformValue('../sibling/file.yaml');
|
|
22
|
+
expect(result).toBe(path.resolve(baseDir, '../sibling/file.yaml'));
|
|
23
|
+
});
|
|
24
|
+
test('resolves current relative path (./) relative to baseDir', () => {
|
|
25
|
+
const transformer = new lib_1.ConfigConfigPathValueTransformer(baseDir);
|
|
26
|
+
const result = transformer.transformValue('./subdir/file.yaml');
|
|
27
|
+
expect(result).toBe(path.resolve(baseDir + '/subdir/file.yaml'));
|
|
28
|
+
});
|
|
29
|
+
test('handles multiple parent traversals', () => {
|
|
30
|
+
const transformer = new lib_1.ConfigConfigPathValueTransformer(baseDir);
|
|
31
|
+
const result = transformer.transformValue('../../other/file.yaml');
|
|
32
|
+
expect(result).toBe(path.resolve(baseDir, '../../other/file.yaml'));
|
|
33
|
+
});
|
|
34
|
+
test('handles nested current directory paths', () => {
|
|
35
|
+
const transformer = new lib_1.ConfigConfigPathValueTransformer(baseDir);
|
|
36
|
+
const result = transformer.transformValue('./a/b/c/file.yaml');
|
|
37
|
+
expect(result).toBe(path.resolve(baseDir + '/a/b/c/file.yaml'));
|
|
38
|
+
});
|
|
39
|
+
test('handles empty baseDir', () => {
|
|
40
|
+
const transformer = new lib_1.ConfigConfigPathValueTransformer('');
|
|
41
|
+
const result = transformer.transformValue('../file.yaml');
|
|
42
|
+
expect(result).toBe(path.resolve('', '../file.yaml'));
|
|
43
|
+
});
|
|
44
|
+
test('returns empty string unchanged', () => {
|
|
45
|
+
const transformer = new lib_1.ConfigConfigPathValueTransformer(baseDir);
|
|
46
|
+
expect(transformer.transformValue('')).toBe('');
|
|
47
|
+
});
|
|
48
|
+
test('handles baseDir with trailing slash', () => {
|
|
49
|
+
const transformer = new lib_1.ConfigConfigPathValueTransformer('/home/user/project/');
|
|
50
|
+
const result = transformer.transformValue('../file.yaml');
|
|
51
|
+
expect(result).toBe(path.resolve('/home/user/project/', '../file.yaml'));
|
|
52
|
+
});
|
|
53
|
+
test('handles Windows-style paths in value', () => {
|
|
54
|
+
const transformer = new lib_1.ConfigConfigPathValueTransformer(baseDir);
|
|
55
|
+
// Non-relative path should be returned unchanged
|
|
56
|
+
expect(transformer.transformValue('C:\\Windows\\file.txt')).toBe('C:\\Windows\\file.txt');
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGF0aC12YWx1ZS10cmFuc2Zvcm1lci50ZXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsicGF0aC12YWx1ZS10cmFuc2Zvcm1lci50ZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7O0dBR0c7O0FBRUgsNkJBQTZCO0FBQzdCLGdDQUEwRDtBQUUxRCxRQUFRLENBQUMsa0NBQWtDLEVBQUUsR0FBRyxFQUFFO0lBQ2hELE1BQU0sT0FBTyxHQUFHLDRCQUE0QixDQUFDO0lBRTdDLElBQUksQ0FBQyxnREFBZ0QsRUFBRSxHQUFHLEVBQUU7UUFDMUQsTUFBTSxXQUFXLEdBQUcsSUFBSSxzQ0FBZ0MsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUNsRSxNQUFNLENBQUMsV0FBVyxDQUFDLGNBQWMsQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQztJQUN0RSxDQUFDLENBQUMsQ0FBQztJQUVILElBQUksQ0FBQyw0Q0FBNEMsRUFBRSxHQUFHLEVBQUU7UUFDdEQsTUFBTSxXQUFXLEdBQUcsSUFBSSxzQ0FBZ0MsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUNsRSxNQUFNLENBQUMsV0FBVyxDQUFDLGNBQWMsQ0FBQyx3QkFBd0IsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLHdCQUF3QixDQUFDLENBQUM7SUFDOUYsQ0FBQyxDQUFDLENBQUM7SUFFSCxJQUFJLENBQUMsdURBQXVELEVBQUUsR0FBRyxFQUFFO1FBQ2pFLE1BQU0sV0FBVyxHQUFHLElBQUksc0NBQWdDLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDbEUsTUFBTSxNQUFNLEdBQUcsV0FBVyxDQUFDLGNBQWMsQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDO1FBQ2xFLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLEVBQUUsc0JBQXNCLENBQUMsQ0FBQyxDQUFDO0lBQ3JFLENBQUMsQ0FBQyxDQUFDO0lBRUgsSUFBSSxDQUFDLHlEQUF5RCxFQUFFLEdBQUcsRUFBRTtRQUNuRSxNQUFNLFdBQVcsR0FBRyxJQUFJLHNDQUFnQyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ2xFLE1BQU0sTUFBTSxHQUFHLFdBQVcsQ0FBQyxjQUFjLENBQUMsb0JBQW9CLENBQUMsQ0FBQztRQUNoRSxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxHQUFHLG1CQUFtQixDQUFDLENBQUMsQ0FBQztJQUNuRSxDQUFDLENBQUMsQ0FBQztJQUVILElBQUksQ0FBQyxvQ0FBb0MsRUFBRSxHQUFHLEVBQUU7UUFDOUMsTUFBTSxXQUFXLEdBQUcsSUFBSSxzQ0FBZ0MsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUNsRSxNQUFNLE1BQU0sR0FBRyxXQUFXLENBQUMsY0FBYyxDQUFDLHVCQUF1QixDQUFDLENBQUM7UUFDbkUsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sRUFBRSx1QkFBdUIsQ0FBQyxDQUFDLENBQUM7SUFDdEUsQ0FBQyxDQUFDLENBQUM7SUFFSCxJQUFJLENBQUMsd0NBQXdDLEVBQUUsR0FBRyxFQUFFO1FBQ2xELE1BQU0sV0FBVyxHQUFHLElBQUksc0NBQWdDLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDbEUsTUFBTSxNQUFNLEdBQUcsV0FBVyxDQUFDLGNBQWMsQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO1FBQy9ELE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLEdBQUcsa0JBQWtCLENBQUMsQ0FBQyxDQUFDO0lBQ2xFLENBQUMsQ0FBQyxDQUFDO0lBRUgsSUFBSSxDQUFDLHVCQUF1QixFQUFFLEdBQUcsRUFBRTtRQUNqQyxNQUFNLFdBQVcsR0FBRyxJQUFJLHNDQUFnQyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQzdELE1BQU0sTUFBTSxHQUFHLFdBQVcsQ0FBQyxjQUFjLENBQUMsY0FBYyxDQUFDLENBQUM7UUFDMUQsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLEVBQUUsRUFBRSxjQUFjLENBQUMsQ0FBQyxDQUFDO0lBQ3hELENBQUMsQ0FBQyxDQUFDO0lBRUgsSUFBSSxDQUFDLGdDQUFnQyxFQUFFLEdBQUcsRUFBRTtRQUMxQyxNQUFNLFdBQVcsR0FBRyxJQUFJLHNDQUFnQyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ2xFLE1BQU0sQ0FBQyxXQUFXLENBQUMsY0FBYyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ2xELENBQUMsQ0FBQyxDQUFDO0lBRUgsSUFBSSxDQUFDLHFDQUFxQyxFQUFFLEdBQUcsRUFBRTtRQUMvQyxNQUFNLFdBQVcsR0FBRyxJQUFJLHNDQUFnQyxDQUFDLHFCQUFxQixDQUFDLENBQUM7UUFDaEYsTUFBTSxNQUFNLEdBQUcsV0FBVyxDQUFDLGNBQWMsQ0FBQyxjQUFjLENBQUMsQ0FBQztRQUMxRCxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMscUJBQXFCLEVBQUUsY0FBYyxDQUFDLENBQUMsQ0FBQztJQUMzRSxDQUFDLENBQUMsQ0FBQztJQUVILElBQUksQ0FBQyxzQ0FBc0MsRUFBRSxHQUFHLEVBQUU7UUFDaEQsTUFBTSxXQUFXLEdBQUcsSUFBSSxzQ0FBZ0MsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUNsRSxpREFBaUQ7UUFDakQsTUFBTSxDQUFDLFdBQVcsQ0FBQyxjQUFjLENBQUMsdUJBQXVCLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxDQUFDO0lBQzVGLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKiFcbiAqIENvcHlyaWdodCBBbWF6b24uY29tLCBJbmMuIG9yIGl0cyBhZmZpbGlhdGVzLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICogU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcbiAqL1xuXG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0IHsgQ29uZmlnQ29uZmlnUGF0aFZhbHVlVHJhbnNmb3JtZXIgfSBmcm9tICcuLi9saWInO1xuXG5kZXNjcmliZSgnQ29uZmlnQ29uZmlnUGF0aFZhbHVlVHJhbnNmb3JtZXInLCAoKSA9PiB7XG4gIGNvbnN0IGJhc2VEaXIgPSAnL2hvbWUvdXNlci9wcm9qZWN0L2NvbmZpZ3MnO1xuXG4gIHRlc3QoJ3JldHVybnMgdW5jaGFuZ2VkIHZhbHVlIGZvciBub24tcmVsYXRpdmUgcGF0aHMnLCAoKSA9PiB7XG4gICAgY29uc3QgdHJhbnNmb3JtZXIgPSBuZXcgQ29uZmlnQ29uZmlnUGF0aFZhbHVlVHJhbnNmb3JtZXIoYmFzZURpcik7XG4gICAgZXhwZWN0KHRyYW5zZm9ybWVyLnRyYW5zZm9ybVZhbHVlKCdzb21lLXZhbHVlJykpLnRvQmUoJ3NvbWUtdmFsdWUnKTtcbiAgfSk7XG5cbiAgdGVzdCgncmV0dXJucyB1bmNoYW5nZWQgdmFsdWUgZm9yIGFic29sdXRlIHBhdGhzJywgKCkgPT4ge1xuICAgIGNvbnN0IHRyYW5zZm9ybWVyID0gbmV3IENvbmZpZ0NvbmZpZ1BhdGhWYWx1ZVRyYW5zZm9ybWVyKGJhc2VEaXIpO1xuICAgIGV4cGVjdCh0cmFuc2Zvcm1lci50cmFuc2Zvcm1WYWx1ZSgnL2Fic29sdXRlL3BhdGgvdG8vZmlsZScpKS50b0JlKCcvYWJzb2x1dGUvcGF0aC90by9maWxlJyk7XG4gIH0pO1xuXG4gIHRlc3QoJ3Jlc29sdmVzIHBhcmVudCByZWxhdGl2ZSBwYXRoICguLi8pIHRvIGJhc2VEaXIgcGFyZW50JywgKCkgPT4ge1xuICAgIGNvbnN0IHRyYW5zZm9ybWVyID0gbmV3IENvbmZpZ0NvbmZpZ1BhdGhWYWx1ZVRyYW5zZm9ybWVyKGJhc2VEaXIpO1xuICAgIGNvbnN0IHJlc3VsdCA9IHRyYW5zZm9ybWVyLnRyYW5zZm9ybVZhbHVlKCcuLi9zaWJsaW5nL2ZpbGUueWFtbCcpO1xuICAgIGV4cGVjdChyZXN1bHQpLnRvQmUocGF0aC5yZXNvbHZlKGJhc2VEaXIsICcuLi9zaWJsaW5nL2ZpbGUueWFtbCcpKTtcbiAgfSk7XG5cbiAgdGVzdCgncmVzb2x2ZXMgY3VycmVudCByZWxhdGl2ZSBwYXRoICguLykgcmVsYXRpdmUgdG8gYmFzZURpcicsICgpID0+IHtcbiAgICBjb25zdCB0cmFuc2Zvcm1lciA9IG5ldyBDb25maWdDb25maWdQYXRoVmFsdWVUcmFuc2Zvcm1lcihiYXNlRGlyKTtcbiAgICBjb25zdCByZXN1bHQgPSB0cmFuc2Zvcm1lci50cmFuc2Zvcm1WYWx1ZSgnLi9zdWJkaXIvZmlsZS55YW1sJyk7XG4gICAgZXhwZWN0KHJlc3VsdCkudG9CZShwYXRoLnJlc29sdmUoYmFzZURpciArICcvc3ViZGlyL2ZpbGUueWFtbCcpKTtcbiAgfSk7XG5cbiAgdGVzdCgnaGFuZGxlcyBtdWx0aXBsZSBwYXJlbnQgdHJhdmVyc2FscycsICgpID0+IHtcbiAgICBjb25zdCB0cmFuc2Zvcm1lciA9IG5ldyBDb25maWdDb25maWdQYXRoVmFsdWVUcmFuc2Zvcm1lcihiYXNlRGlyKTtcbiAgICBjb25zdCByZXN1bHQgPSB0cmFuc2Zvcm1lci50cmFuc2Zvcm1WYWx1ZSgnLi4vLi4vb3RoZXIvZmlsZS55YW1sJyk7XG4gICAgZXhwZWN0KHJlc3VsdCkudG9CZShwYXRoLnJlc29sdmUoYmFzZURpciwgJy4uLy4uL290aGVyL2ZpbGUueWFtbCcpKTtcbiAgfSk7XG5cbiAgdGVzdCgnaGFuZGxlcyBuZXN0ZWQgY3VycmVudCBkaXJlY3RvcnkgcGF0aHMnLCAoKSA9PiB7XG4gICAgY29uc3QgdHJhbnNmb3JtZXIgPSBuZXcgQ29uZmlnQ29uZmlnUGF0aFZhbHVlVHJhbnNmb3JtZXIoYmFzZURpcik7XG4gICAgY29uc3QgcmVzdWx0ID0gdHJhbnNmb3JtZXIudHJhbnNmb3JtVmFsdWUoJy4vYS9iL2MvZmlsZS55YW1sJyk7XG4gICAgZXhwZWN0KHJlc3VsdCkudG9CZShwYXRoLnJlc29sdmUoYmFzZURpciArICcvYS9iL2MvZmlsZS55YW1sJykpO1xuICB9KTtcblxuICB0ZXN0KCdoYW5kbGVzIGVtcHR5IGJhc2VEaXInLCAoKSA9PiB7XG4gICAgY29uc3QgdHJhbnNmb3JtZXIgPSBuZXcgQ29uZmlnQ29uZmlnUGF0aFZhbHVlVHJhbnNmb3JtZXIoJycpO1xuICAgIGNvbnN0IHJlc3VsdCA9IHRyYW5zZm9ybWVyLnRyYW5zZm9ybVZhbHVlKCcuLi9maWxlLnlhbWwnKTtcbiAgICBleHBlY3QocmVzdWx0KS50b0JlKHBhdGgucmVzb2x2ZSgnJywgJy4uL2ZpbGUueWFtbCcpKTtcbiAgfSk7XG5cbiAgdGVzdCgncmV0dXJucyBlbXB0eSBzdHJpbmcgdW5jaGFuZ2VkJywgKCkgPT4ge1xuICAgIGNvbnN0IHRyYW5zZm9ybWVyID0gbmV3IENvbmZpZ0NvbmZpZ1BhdGhWYWx1ZVRyYW5zZm9ybWVyKGJhc2VEaXIpO1xuICAgIGV4cGVjdCh0cmFuc2Zvcm1lci50cmFuc2Zvcm1WYWx1ZSgnJykpLnRvQmUoJycpO1xuICB9KTtcblxuICB0ZXN0KCdoYW5kbGVzIGJhc2VEaXIgd2l0aCB0cmFpbGluZyBzbGFzaCcsICgpID0+IHtcbiAgICBjb25zdCB0cmFuc2Zvcm1lciA9IG5ldyBDb25maWdDb25maWdQYXRoVmFsdWVUcmFuc2Zvcm1lcignL2hvbWUvdXNlci9wcm9qZWN0LycpO1xuICAgIGNvbnN0IHJlc3VsdCA9IHRyYW5zZm9ybWVyLnRyYW5zZm9ybVZhbHVlKCcuLi9maWxlLnlhbWwnKTtcbiAgICBleHBlY3QocmVzdWx0KS50b0JlKHBhdGgucmVzb2x2ZSgnL2hvbWUvdXNlci9wcm9qZWN0LycsICcuLi9maWxlLnlhbWwnKSk7XG4gIH0pO1xuXG4gIHRlc3QoJ2hhbmRsZXMgV2luZG93cy1zdHlsZSBwYXRocyBpbiB2YWx1ZScsICgpID0+IHtcbiAgICBjb25zdCB0cmFuc2Zvcm1lciA9IG5ldyBDb25maWdDb25maWdQYXRoVmFsdWVUcmFuc2Zvcm1lcihiYXNlRGlyKTtcbiAgICAvLyBOb24tcmVsYXRpdmUgcGF0aCBzaG91bGQgYmUgcmV0dXJuZWQgdW5jaGFuZ2VkXG4gICAgZXhwZWN0KHRyYW5zZm9ybWVyLnRyYW5zZm9ybVZhbHVlKCdDOlxcXFxXaW5kb3dzXFxcXGZpbGUudHh0JykpLnRvQmUoJ0M6XFxcXFdpbmRvd3NcXFxcZmlsZS50eHQnKTtcbiAgfSk7XG59KTtcbiJdfQ==
|