-
Notifications
You must be signed in to change notification settings - Fork 0
/
cfn.ts
92 lines (73 loc) · 2.18 KB
/
cfn.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
import { yamlParse, z } from "./deps.ts";
type RawResource = {
Type: string;
Properties?: unknown | undefined;
};
type CfnGetAtt = {
"Fn::GetAtt": [string, string];
};
type CfnFunction = CfnGetAtt;
type CfnScalar<T> = T | CfnFunction;
export type StateMachineResource = {
Type: "AWS::Serverless::StateMachine";
Properties: {
DefinitionUri: string;
DefinitionSubstitutions?: Record<string, CfnScalar<string>> | undefined;
};
};
type FunctionResource = {
Type: "AWS::Serverless::Function";
};
type ResolvedResource = StateMachineResource | FunctionResource;
export type CfnSchema<T = ResolvedResource> = {
Resources?: Record<string, T> | undefined;
};
const zRawResource: z.Schema<RawResource> = z.object({
Type: z.string(),
Properties: z.unknown().optional(),
});
const zCfnGetAtt: z.Schema<CfnGetAtt> = z.object({
"Fn::GetAtt": z.tuple([z.string(), z.string()]),
});
const zCfnFunction: z.Schema<CfnFunction> = zCfnGetAtt;
function zCfnScalar<T extends z.Schema>(
val: T,
): z.Schema<CfnScalar<z.infer<T>>> {
return z.union([val, zCfnFunction]);
}
const zStateMachineResource: z.Schema<StateMachineResource> = z.object({
Type: z.literal("AWS::Serverless::StateMachine"),
Properties: z.object({
DefinitionUri: z.string(),
DefinitionSubstitutions: z.record(z.string(), zCfnScalar(z.string()))
.optional(),
}),
});
const zFunctionResource: z.Schema<FunctionResource> = z.object({
Type: z.literal("AWS::Serverless::Function"),
});
const zResolvedResource: z.Schema<ResolvedResource> = z.union([
zStateMachineResource,
zFunctionResource,
]);
const zRawCfnSchema: z.Schema<CfnSchema<RawResource>> = z.object({
Resources: z.record(z.string(), zRawResource).optional(),
});
export function parse(text: string): CfnSchema {
const yaml = yamlParse(text);
const parsed = zRawCfnSchema.parse(yaml);
if (typeof parsed.Resources === "undefined") {
return {};
}
const filtered: ReturnType<typeof parse> = {
Resources: {},
};
for (const [k, v] of Object.entries(parsed.Resources)) {
const parsed = zResolvedResource.safeParse(v);
if (!parsed.success) {
continue;
}
filtered.Resources![k] = parsed.data;
}
return filtered;
}