/
inputTransformation.ts
115 lines (96 loc) · 3.47 KB
/
inputTransformation.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
import { DefaultTokenResolver, IResolveContext, Lazy, StringConcat, Token, Tokenization } from 'aws-cdk-lib';
import { IPipe } from './pipe';
import { unquote } from './unquote';
type InputTransformationValue = string | Record<string, any>;
/**
* The inputTemplate that is used to transform the input event payload with unquoted variables
*/
export interface InputTransformationConfig {
/**
* The inputTemplate that is used to transform the input event payload
*/
readonly inputTemplate: string;
}
/**
* Transform or replace the input event payload
*/
export interface IInputTransformation {
/**
* Bind the input transformation to the pipe and returns the inputTemplate string.
*/
bind(pipe: IPipe): InputTransformationConfig;
}
enum TemplateType {
TEXT = 'Text',
OBJECT = 'Object',
}
/**
* Transform or replace the input event payload
*/
export class InputTransformation implements IInputTransformation {
/**
* Creates an InputTransformation from a string.
*/
static fromText(inputTemplate: string): InputTransformation {
return new InputTransformation(inputTemplate, TemplateType.TEXT);
}
/**
* Creates an InputTransformation from a jsonPath expression of the input event.
*/
static fromEventPath(jsonPathExpression: string): InputTransformation {
if (!jsonPathExpression.startsWith('$.')) {
throw new Error('jsonPathExpression start with "$."');
}
const jsonPath = `<${jsonPathExpression}>`;
return new InputTransformation(jsonPath, TemplateType.TEXT);
}
/**
* Creates an InputTransformation from a pipe variable.
*/
static fromObject(inputTemplate: Record<string, any>): InputTransformation {
return new InputTransformation(inputTemplate, TemplateType.OBJECT);
}
private type : TemplateType;
/**
* The inputTemplate that is used to transform the input event payload
*/
private inputTemplate: InputTransformationValue;
private constructor(inputTemplate: InputTransformationValue, type: TemplateType) {
this.type = type;
this.inputTemplate = inputTemplate;
}
public bind(pipe: IPipe): InputTransformationConfig {
if (this.type === 'Text') {
return { inputTemplate: this.inputTemplate as string };
}
const stringifiedJsonWithUnresolvedTokens = pipe.stack.toJsonString(this.inputTemplate);
const resolved = Tokenization.resolve(stringifiedJsonWithUnresolvedTokens, {
scope: pipe,
resolver: new DefaultTokenResolver(new StringConcat()),
});
return { inputTemplate: this.unquoteDynamicInputs(resolved) };
}
private unquoteDynamicInputs(sub: string) {
return Lazy.uncachedString({ produce: (ctx: IResolveContext) => Token.asString(deepUnquote(ctx.resolve(sub))) });
/**
* Removes the quotes from the values that are in the keys array
*
* @param resolved the resolved object containing the dynamic fields with quotes. In cases where a cloudformation intrinsic function is used, the resolved value will be an object.
* @returns the resolved object with the dynamic fields without quotes
*/
function deepUnquote(resolved: any): any {
if (Array.isArray(resolved)) {
return resolved.map(deepUnquote);
}
if (typeof(resolved) === 'object' && resolved !== null) {
for (const [key, value] of Object.entries(resolved)) {
resolved[key] = deepUnquote(value);
}
}
if (typeof resolved === 'string') {
return unquote(resolved);
}
return resolved;
}
}
}