@datapith/cdk4j-diagram 0.4.1

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.
@@ -0,0 +1,330 @@
1
+ const icons = {
2
+ "AWS::Serverless::Function": {
3
+ icon: "mxgraph.aws4.lambda",
4
+ serviceType: "compute",
5
+ },
6
+ "AWS::Serverless::SimpleTable": {
7
+ icon: "mxgraph.aws4.dynamodb",
8
+ serviceType: "database",
9
+ },
10
+ "AWS::Serverless::Api": {
11
+ icon: "mxgraph.aws4.api_gateway",
12
+ serviceType: "networkingcontentdelivery",
13
+ },
14
+ "AWS::Serverless::HttpApi": {
15
+ icon: "mxgraph.aws4.api_gateway",
16
+ serviceType: "networkingcontentdelivery",
17
+ },
18
+ "AWS::Serverless::StateMachine": {
19
+ icon: "mxgraph.aws4.step_functions",
20
+ serviceType: "applicationintegration",
21
+ },
22
+ "AWS::Lambda::Permission": {
23
+ icon: "mxgraph.aws4.policy",
24
+ serviceType: "securityidentitycomplicance",
25
+ },
26
+ "AWS::IAM::Role": {
27
+ icon: "mxgraph.aws4.role",
28
+ serviceType: "securityidentitycomplicance",
29
+ },
30
+ "AWS::SSM::Parameter": {
31
+ icon: "mxgraph.aws4.parameter_store",
32
+ serviceType: "managementgovernance",
33
+ },
34
+ "AWS::Logs::LogGroup": {
35
+ icon: "mxgraph.aws4.cloudwatch",
36
+ serviceType: "managementgovernance",
37
+ },
38
+ "AWS::EC2::Route": {
39
+ icon: "mxgraph.aws4.route_table",
40
+ serviceType: "networkingcontentdelivery",
41
+ },
42
+ "AWS::EC2::RouteTable": {
43
+ icon: "mxgraph.aws4.route_table",
44
+ serviceType: "networkingcontentdelivery",
45
+ },
46
+ "AWS::EC2::SubnetRouteTableAssociation": {
47
+ icon: "mxgraph.aws4.route_table",
48
+ serviceType: "networkingcontentdelivery",
49
+ },
50
+ "AWS::EC2::VPC": {
51
+ icon: "mxgraph.aws4.vpc",
52
+ serviceType: "networkingcontentdelivery",
53
+ },
54
+ "AWS::EC2::NatGateway": {
55
+ icon: "mxgraph.aws4.nat_gateway",
56
+ serviceType: "networkingcontentdelivery",
57
+ },
58
+ "AWS::EC2::EIP": {
59
+ icon: "mxgraph.aws4.elastic_ip_address",
60
+ serviceType: "networkingcontentdelivery",
61
+ },
62
+ "AWS::ApiGateway::RestApi": {
63
+ icon: "mxgraph.aws4.api_gateway",
64
+ serviceType: "networkingcontentdelivery",
65
+ },
66
+ "AWS::ApiGateway::Method": {
67
+ icon: "mxgraph.aws4.api_gateway",
68
+ serviceType: "networkingcontentdelivery",
69
+ },
70
+ "AWS::ApiGateway::Deployment": {
71
+ icon: "mxgraph.aws4.api_gateway",
72
+ serviceType: "networkingcontentdelivery",
73
+ },
74
+ "AWS::ApiGateway::Resource": {
75
+ icon: "mxgraph.aws4.api_gateway",
76
+ serviceType: "networkingcontentdelivery",
77
+ },
78
+ "AWS::ApiGateway::Stage": {
79
+ icon: "mxgraph.aws4.api_gateway",
80
+ serviceType: "networkingcontentdelivery",
81
+ },
82
+ "AWS::ApiGateway::Account": {
83
+ icon: "mxgraph.aws4.api_gateway",
84
+ serviceType: "networkingcontentdelivery",
85
+ },
86
+ "AWS::ApiGateway::Account": {
87
+ icon: "mxgraph.aws4.api_gateway",
88
+ serviceType: "networkingcontentdelivery",
89
+ },
90
+ "AWS::WAF::WebACL": {
91
+ icon: "mxgraph.aws4.waf",
92
+ serviceType: "securityidentitycomplicance",
93
+ },
94
+ "AWS::WAF::WebACLAssociation": {
95
+ icon: "mxgraph.aws4.waf",
96
+ serviceType: "securityidentitycomplicance",
97
+ },
98
+ "AWS::WAFv2::WebACL": {
99
+ icon: "mxgraph.aws4.waf",
100
+ serviceType: "securityidentitycomplicance",
101
+ },
102
+ "AWS::WAFv2::WebACLAssociation": {
103
+ icon: "mxgraph.aws4.waf",
104
+ serviceType: "securityidentitycomplicance",
105
+ },
106
+ "AWS::ApiGatewayV2::Api": {
107
+ icon: "mxgraph.aws4.api_gateway",
108
+ serviceType: "networkingcontentdelivery",
109
+ },
110
+ "AWS::ApiGatewayV2::ApiGatewayManagedOverrides": {
111
+ icon: "mxgraph.aws4.api_gateway",
112
+ serviceType: "networkingcontentdelivery",
113
+ },
114
+ "AWS::ApiGatewayV2::ApiMapping": {
115
+ icon: "mxgraph.aws4.api_gateway",
116
+ serviceType: "networkingcontentdelivery",
117
+ },
118
+ "AWS::ApiGatewayV2::Authorizer": {
119
+ icon: "mxgraph.aws4.api_gateway",
120
+ serviceType: "networkingcontentdelivery",
121
+ },
122
+ "AWS::ApiGatewayV2::Deployment": {
123
+ icon: "mxgraph.aws4.api_gateway",
124
+ serviceType: "networkingcontentdelivery",
125
+ },
126
+ "AWS::ApiGatewayV2::DomainName": {
127
+ icon: "mxgraph.aws4.api_gateway",
128
+ serviceType: "networkingcontentdelivery",
129
+ },
130
+ "AWS::ApiGatewayV2::Integration": {
131
+ icon: "mxgraph.aws4.api_gateway",
132
+ serviceType: "networkingcontentdelivery",
133
+ },
134
+ "AWS::ApiGatewayV2::IntegrationResponse": {
135
+ icon: "mxgraph.aws4.api_gateway",
136
+ serviceType: "networkingcontentdelivery",
137
+ },
138
+ "AWS::ApiGatewayV2::Model": {
139
+ icon: "mxgraph.aws4.api_gateway",
140
+ serviceType: "networkingcontentdelivery",
141
+ },
142
+ "AWS::ApiGatewayV2::Route": {
143
+ icon: "mxgraph.aws4.api_gateway",
144
+ serviceType: "networkingcontentdelivery",
145
+ },
146
+ "AWS::ApiGatewayV2::RouteResponse": {
147
+ icon: "mxgraph.aws4.api_gateway",
148
+ serviceType: "networkingcontentdelivery",
149
+ },
150
+ "AWS::ApiGatewayV2::Stage": {
151
+ icon: "mxgraph.aws4.api_gateway",
152
+ serviceType: "networkingcontentdelivery",
153
+ },
154
+ "AWS::ApiGatewayV2::VpcLink": {
155
+ icon: "mxgraph.aws4.api_gateway",
156
+ serviceType: "networkingcontentdelivery",
157
+ },
158
+ };
159
+
160
+ const colors = {
161
+ analytics: {
162
+ gradientColor: "#945DF2",
163
+ fillColor: "#5A30B5",
164
+ },
165
+ applicationintegration: {
166
+ fillColor: "#BC1356",
167
+ gradientColor: "#F34482",
168
+ },
169
+ blockchain: {
170
+ fillColor: "#D05C17",
171
+ gradientColor: "#F78E04",
172
+ },
173
+ managementgovernance: {
174
+ fillColor: "#BC1356",
175
+ gradientColor: "#F34482",
176
+ },
177
+ compute: {
178
+ fillColor: "#D05C17",
179
+ gradientColor: "#F78E04",
180
+ },
181
+ containers: {
182
+ fillColor: "#D05C17",
183
+ gradientColor: "#F78E04",
184
+ },
185
+ database: {
186
+ fillColor: "#3334B9",
187
+ gradientColor: "#4D72F3",
188
+ },
189
+ networkingcontentdelivery: {
190
+ fillColor: "#5A30B5",
191
+ gradientColor: "#945DF2",
192
+ },
193
+ securityidentitycomplicance: {
194
+ fillColor: "#C7131F",
195
+ gradientColor: "#F54749",
196
+ },
197
+ storage: {
198
+ fillColor: "#277116",
199
+ gradientColor: "#60A337",
200
+ },
201
+ };
202
+
203
+ const serviceTypeMap = {
204
+ Athena: "analytics",
205
+ CloudSearch: "analytics",
206
+ ElasticsearchService: "analytics",
207
+ EMR: "analytics",
208
+ Kinesis: "analytics",
209
+ MSK: "analytics",
210
+ Redshift: "analytics",
211
+ QuickSight: "analytics",
212
+ DataExchange: "analytics",
213
+ DataPipeline: "analytics",
214
+ Glue: "analytics",
215
+ LakeFormation: "analytics",
216
+ StepFunctions: "applicationintegration",
217
+ AppFlow: "applicationintegration",
218
+ EventBridge: "applicationintegration",
219
+ Events: "applicationintegration",
220
+ MQ: "applicationintegration",
221
+ SNS: "applicationintegration",
222
+ SQS: "applicationintegration",
223
+ AppSync: "applicationintegration",
224
+ ManagedBlockchain: "blockchain",
225
+ CloudWatch: "managementgovernance",
226
+ AutoScaling: "managementgovernance",
227
+ Chatbot: "managementgovernance",
228
+ CloudFormation: "managementgovernance",
229
+ CloudTrail: "managementgovernance",
230
+ ComputeOptimizer: "managementgovernance",
231
+ Config: "managementgovernance",
232
+ ControlTower: "managementgovernance",
233
+ ConsoleMobileApplication: "managementgovernance",
234
+ LicenseManager: "managementgovernance",
235
+ OpsWorks: "managementgovernance",
236
+ Organizations: "managementgovernance",
237
+ ServiceCatalog: "managementgovernance",
238
+ SystemsManager: "managementgovernance",
239
+ TrustedAdvisor: "managementgovernance",
240
+ EC2: "compute",
241
+ AutoScaling: "compute",
242
+ Lightsail: "compute",
243
+ Batch: "compute",
244
+ ElasticBeanstalk: "compute",
245
+ Lambda: "compute",
246
+ Outposts: "compute",
247
+ ServerlessApplicationRepository: "compute",
248
+ Wavelength: "compute",
249
+ ElasticContainerRegistry: "containers",
250
+ ECS: "containers",
251
+ EKS: "containers",
252
+ Fargate: "containers",
253
+ Aurora: "database",
254
+ DynamoDB: "database",
255
+ DocumentDB: "database",
256
+ ElastiCache: "database",
257
+ Keyspaces: "database",
258
+ Neptune: "database",
259
+ QuantumLedgerDatabase: "database",
260
+ RDS: "database",
261
+ RDSonVMware: "database",
262
+ Redshift: "database",
263
+ Timestream: "database",
264
+ DatabaseMigrationService: "database",
265
+ VPC: "networkingcontentdelivery",
266
+ APIGateway: "networkingcontentdelivery",
267
+ CloudFront: "networkingcontentdelivery",
268
+ Route53: "networkingcontentdelivery",
269
+ PrivateLink: "networkingcontentdelivery",
270
+ AppMesh: "networkingcontentdelivery",
271
+ CloudMap: "networkingcontentdelivery",
272
+ DirectConnect: "networkingcontentdelivery",
273
+ GlobalAccelerator: "networkingcontentdelivery",
274
+ TransitGateway: "networkingcontentdelivery",
275
+ ElasticLoadBalancing: "networkingcontentdelivery",
276
+ IAM: "securityidentitycomplicance",
277
+ Cognito: "securityidentitycomplicance",
278
+ Detective: "securityidentitycomplicance",
279
+ GuardDuty: "securityidentitycomplicance",
280
+ Inspector: "securityidentitycomplicance",
281
+ Macie: "securityidentitycomplicance",
282
+ Artifact: "securityidentitycomplicance",
283
+ CertificateManager: "securityidentitycomplicance",
284
+ CloudHSM: "securityidentitycomplicance",
285
+ DirectoryService: "securityidentitycomplicance",
286
+ FirewallManager: "securityidentitycomplicance",
287
+ KMS: "securityidentitycomplicance",
288
+ ResourceAccessManager: "securityidentitycomplicance",
289
+ SecretsManager: "securityidentitycomplicance",
290
+ SecurityHub: "securityidentitycomplicance",
291
+ Shield: "securityidentitycomplicance",
292
+ WAF: "securityidentitycomplicance",
293
+ S3: "storage",
294
+ EBS: "storage",
295
+ EFS: "storage",
296
+ Backup: "storage",
297
+ SnowFamily: "storage",
298
+ StorageGateway: "storage",
299
+ };
300
+
301
+ const serviceTranslation = {
302
+ iam: "identity_and_access_management",
303
+ kms: "key_management_service",
304
+ stepfunctions: "step_functions",
305
+ events: "eventbridge",
306
+ logs: "cloudwatch",
307
+ };
308
+
309
+ function getIcon(type) {
310
+ let icon = icons[type];
311
+ if (icon) {
312
+ icon.fillColor = colors[icon.serviceType].fillColor;
313
+ icon.gradientColor = colors[icon.serviceType].gradientColor;
314
+ } else {
315
+ const serviceName = type.split("::")[1];
316
+ const group = serviceTypeMap[serviceName];
317
+ const color = colors[group];
318
+ const translatedName = serviceTranslation[serviceName.toLowerCase()];
319
+ icon = {
320
+ icon: "mxgraph.aws4." + (translatedName || serviceName.toLowerCase()),
321
+ fillColor: color ? color.fillColor : "#aaaaaa",
322
+ gradientColor: color ? color.gradientColor : "#aaaaaa",
323
+ };
324
+ }
325
+ return `outlineConnect=0;fontColor=#B3B3B3;gradientColor=${icon.gradientColor};gradientDirection=north;fillColor=${icon.fillColor};strokeColor=#ffffff;dashed=0;verticalLabelPosition=bottom;verticalAlign=top;align=center;html=1;fontSize=12;fontStyle=0;aspect=fixed;shape=mxgraph.aws4.resourceIcon;resIcon=${icon.icon};`;
326
+ }
327
+
328
+ module.exports = {
329
+ getIcon,
330
+ };
@@ -0,0 +1,186 @@
1
+ const templateCache = require("../shared/templateCache");
2
+
3
+ function createPseudoResources(template, current) {
4
+ current = current || template.Resources;
5
+ for (var k in current) {
6
+ if (current[k] && current[k]["Fn::Join"]) {
7
+ let joinList = current[k]["Fn::Join"][1];
8
+ if (!Array.isArray(joinList)) {
9
+ joinList = [joinList];
10
+ }
11
+ if (
12
+ joinList.filter(
13
+ (p) => typeof p === "object" && (!p.Ref || !p.Ref.startsWith("AWS::"))
14
+ )
15
+ ) {
16
+ return;
17
+ }
18
+ current[k] = (Array.isArray(joinList)
19
+ ? joinList
20
+ .map((p) => {
21
+ if (p[Object.keys(p)[0]] === "object") {
22
+ return "";
23
+ }
24
+ if (Array.isArray(p[Object.keys(p)[0]])) {
25
+ return "[]";
26
+ }
27
+ if (typeof p === "object" && p.Ref && p.Ref.startsWith("AWS::")) {
28
+ return null;
29
+ }
30
+ return typeof p === "object"
31
+ ? p[Object.keys(p)[0]].replace(/::/g, "-")
32
+ : p;
33
+ })
34
+ .filter((p) => p)
35
+ : [joinList]
36
+ ).join(current[k]["Fn::Join"][0]);
37
+ }
38
+ if (typeof current[k] === "object" && current[k] !== null) {
39
+ createPseudoResources(template, current[k]);
40
+ } else if (
41
+ typeof current[k] === "string" &&
42
+ current[k].startsWith("arn:")
43
+ ) {
44
+ current[k] = current[k].replace(/\$\{AWS\:\:(.+?)\}/g, "").toLowerCase();
45
+ if (!current[k]) {
46
+ return;
47
+ }
48
+ const split = current[k].split(":");
49
+ const service = split[2];
50
+ const resourceType = split[5]
51
+ ? split[5].split("/")[0].replace(/[\W_]+/g, "")
52
+ : "";
53
+ const name = `${split[2]} ${split[3]} ${split[4]}\n${split.slice(-1)[0]}`;
54
+ template.Resources[name] = {
55
+ Type: `External resource (aws::${service}::${resourceType})`,
56
+ };
57
+ current[k] = {
58
+ Ref: name,
59
+ };
60
+ }
61
+ }
62
+ }
63
+
64
+ function findAllValues(obj, keyArray, keyName, path) {
65
+ path = path || "$";
66
+ for (const prop of Object.keys(obj)) {
67
+ if (prop === keyName) {
68
+ let values = obj[prop];
69
+ if (Array.isArray(values)) {
70
+ values = obj[prop][instrisicFunctionIndex(prop)];
71
+ }
72
+
73
+ if (!Array.isArray(values)) {
74
+ values = [values];
75
+ }
76
+
77
+ if (prop === "Fn::Sub") {
78
+ const pattern = /\$\{(.+?)\}/g;
79
+ let match;
80
+ const multiValue = [];
81
+ while ((match = pattern.exec(values[0])) != null) {
82
+ multiValue.push([match[1].split(".")[0]]);
83
+ }
84
+ values = multiValue.map((p) => p[0]);
85
+ }
86
+ if (prop === "Fn::ImportValue") {
87
+ const split = typeof values[0] ==="string" && values[0].split(":");
88
+ if (split.length == 2) {
89
+ const stackName = split[0];
90
+ const exportName = split[1];
91
+ const value = templateCache.templates[stackName] ? templateCache.templates[stackName].Outputs[exportName].Value : {"Fn::ImportValue": "Unknown"};
92
+ const intrinsicFunction = Object.keys(value)[0];
93
+ const prefix = stackName === templateCache.rootTemplate ? "root" : stackName;
94
+ values[0] = `${prefix}.${value[intrinsicFunction]}`;
95
+ }
96
+ }
97
+
98
+ values = [values];
99
+
100
+ for (const v of values) {
101
+ const item = {
102
+ key: prop,
103
+ value: v.filter((p) => typeof p === "string" && !p.startsWith("AWS::")),
104
+ path: path.split(".Fn::")[0],
105
+ };
106
+ if (item.value.length) {
107
+ keyArray.push(item);
108
+ }
109
+ }
110
+ }
111
+ if (
112
+ !obj[prop] ||
113
+ typeof obj[prop] !== "object" ||
114
+ typeof obj[prop] === "string" ||
115
+ obj[prop] instanceof String
116
+ ) {
117
+ continue;
118
+ }
119
+
120
+ if (Array.isArray(obj[prop])) {
121
+ obj[prop].forEach((child, i) =>
122
+ findAllValues(child, keyArray, keyName, `${path}.${prop}`)
123
+ );
124
+ } else {
125
+ findAllValues(obj[prop], keyArray, keyName, `${path}.${prop}`);
126
+ }
127
+ }
128
+ }
129
+
130
+ function instrisicFunctionIndex(prop) {
131
+ switch (prop) {
132
+ case "Fn::GetAtt":
133
+ return 0;
134
+ case "Fn::Join":
135
+ return 1;
136
+ }
137
+ return 0;
138
+ }
139
+
140
+ function isJson(str) {
141
+ try {
142
+ JSON.parse(str);
143
+ } catch (e) {
144
+ return false;
145
+ }
146
+ return true;
147
+ }
148
+
149
+ function pathToDescriptor(path, filterConfig) {
150
+ if (filterConfig.edgeMode === "Off") {
151
+ return "";
152
+ }
153
+ if (path.startsWith("$.Properties.Environment")) {
154
+ return "Variable";
155
+ }
156
+
157
+ if (path.startsWith("$.Properties.Policies")) {
158
+ const split = path.split(".");
159
+ return split[3];
160
+ }
161
+
162
+ if (
163
+ path.startsWith(
164
+ "$.Properties.EventInvokeConfig.DestinationConfig.OnFailure"
165
+ )
166
+ ) {
167
+ return "OnFailure";
168
+ }
169
+
170
+ if (
171
+ path.startsWith(
172
+ "$.Properties.EventInvokeConfig.DestinationConfig.OnSuccess"
173
+ )
174
+ ) {
175
+ return "OnSuccess";
176
+ }
177
+
178
+ return path.split(".").slice(-1)[0];
179
+ }
180
+
181
+ module.exports = {
182
+ createPseudoResources,
183
+ findAllValues,
184
+ isJson,
185
+ pathToDescriptor,
186
+ };
@@ -0,0 +1,6 @@
1
+ const templates = {};
2
+ let rootTemplate
3
+ module.exports = {
4
+ templates,
5
+ rootTemplate
6
+ }
@@ -0,0 +1,128 @@
1
+ const fs = require("fs");
2
+ const path = require("path");
3
+ const YAML = require("yaml-cfn");
4
+ const jsonUtil = require("../resources/JsonUtil");
5
+ const cp = require("child_process");
6
+ const templateCache = require("./templateCache");
7
+
8
+ function get(cmd) {
9
+ let templateString = "";
10
+ try {
11
+ if (cmd.templateFile === "template.yaml or cdk.json") {
12
+ cmd.templateFile = "template.yaml";
13
+ }
14
+ templateString = fs.readFileSync(cmd.templateFile);
15
+ } catch {
16
+ try {
17
+ templateString = fs.readFileSync("cdk.json").toString();
18
+ } catch {
19
+ console.log(
20
+ `Can't find ${cmd.templateFile} or cdk.json. Specify location with -t flag, for example 'cfn-dia html -t mytemplate.yaml'`
21
+ );
22
+ process.exit(1);
23
+ }
24
+ }
25
+
26
+ const isJson = jsonUtil.isJson(templateString);
27
+ const parser = isJson ? JSON.parse : YAML.yamlParse;
28
+
29
+ let template = parser(templateString);
30
+ if (template.app) {
31
+ template = fromCDK(cmd);
32
+ }
33
+ templateCache.templates["root"] = template;
34
+ if (!template.Resources) return { isJson, template };
35
+ Object.keys(template.Resources)
36
+ .filter((p) => template.Resources[p].Type === "AWS::CloudFormation::Stack")
37
+ .map((p) => {
38
+ const res = template.Resources[p];
39
+ if (
40
+ !res.StackImport &&
41
+ typeof res.Properties.TemplateURL === "string" &&
42
+ !res.Properties.TemplateURL.startsWith("s3://")
43
+ ) {
44
+ templateString = fs.readFileSync(res.Properties.TemplateURL);
45
+ const isJson = jsonUtil.isJson(templateString);
46
+ const parser = isJson ? JSON.parse : YAML.yamlParse;
47
+ const parsedTemplate = parser(templateString);
48
+ template.Resources[p].Template = parsedTemplate;
49
+ templateCache.templates[p] = parsedTemplate;
50
+ }
51
+ });
52
+ Object.keys(template.Resources)
53
+ .filter((p) => template.Resources[p].Type === "AWS::Serverless::Function")
54
+ .map((functionName) => {
55
+ const res = template.Resources[functionName];
56
+ const events = res.Properties.Events;
57
+ if (events) {
58
+ for (const eventName of Object.keys(events)) {
59
+ const event = events[eventName];
60
+ if (["EventBridgeRule", "CloudWatchEvent"].includes(event.Type)) {
61
+ template.Resources[functionName + eventName] = {
62
+ Type: "AWS::Events::Rule",
63
+ Properties: {
64
+ EventBusName: event.Properties.EventBusName || "default",
65
+ EventPattern: event.Properties.Pattern,
66
+ State: "ENABLED",
67
+ Targets: [{ Arn: { "Fn::GetAtt": [functionName, "Arn"] }, Id: "EventId"}],
68
+ },
69
+ };
70
+ }
71
+ if (["Api"].includes(event.Type)) {
72
+ template.Resources[functionName + eventName] = {
73
+ Type: "AWS::ApiGateway::RestApi",
74
+ Properties: {
75
+ Integration: [{ Arn: { "Fn::GetAtt": [functionName, "Arn"] }, Id: "EventId"}],
76
+ },
77
+ };
78
+ }
79
+ if (["HttpApi"].includes(event.Type)) {
80
+ template.Resources[functionName + eventName] = {
81
+ Type: "AWS::ApiGatewayV2::Api",
82
+ Properties: {
83
+ Integration: [{ Arn: { "Fn::GetAtt": [functionName, "Arn"] }, Id: "EventId"}],
84
+ },
85
+ };
86
+ }
87
+ }
88
+ }
89
+ });
90
+ return { isJson, template };
91
+ }
92
+
93
+ function fromCDK(cmd) {
94
+ if (!cmd.skipSynth) {
95
+ cp.execSync("cdk synth -o " + cmd.cdkOutput);
96
+ }
97
+ const manifestFile = fs.readFileSync(path.join(cmd.cdkOutput, "manifest.json"));
98
+ const treeFile = fs.readFileSync(path.join(cmd.cdkOutput, "tree.json"));
99
+ const manifest = JSON.parse(manifestFile);
100
+ const tree = JSON.parse(treeFile);
101
+ const includeStacks = cmd.stacks && (typeof cmd.stacks !== 'boolean') ? cmd.stacks.split(",").map(p=>p.trim()) : null;
102
+ let stacks = Object.keys(manifest.artifacts).filter((p) => p !== "Tree" && (!includeStacks || includeStacks.includes(p)));
103
+ const parentStack = Object.keys(tree.tree.children).filter((p) => p !== "Tree" && !p.includes(".assets") && (!includeStacks || includeStacks.includes(p)))[0];
104
+ const template = fs.readFileSync(
105
+ path.join(cmd.cdkOutput, `${parentStack}.template.json`)
106
+ );
107
+ const parsedTemplate = JSON.parse(template);
108
+ templateCache.templates[parentStack] = parsedTemplate;
109
+ templateCache.rootTemplate = parentStack;
110
+ stacks = stacks.filter(p => p != parentStack);
111
+ for (const stack of stacks.filter(p => !p.endsWith(".assets"))) {
112
+ const childTemplate = fs.readFileSync(
113
+ path.join(cmd.cdkOutput, `${stack}.template.json`)
114
+ );
115
+ const parsedChildTemplate = JSON.parse(childTemplate);
116
+ parsedTemplate.Resources[stack] = {
117
+ Type: "AWS::CloudFormation::Stack",
118
+ Template: parsedChildTemplate,
119
+ StackImport: true,
120
+ };
121
+ templateCache.templates[stack] = parsedChildTemplate;
122
+ }
123
+ return parsedTemplate;
124
+ }
125
+
126
+ module.exports = {
127
+ get,
128
+ };
@@ -0,0 +1,32 @@
1
+ const path = require("path");
2
+ const fs = require("fs");
3
+
4
+ const templateStr = fs.readFileSync(path.join(__dirname, "..", "template.json"));
5
+ const template = JSON.parse(templateStr.toString());
6
+
7
+ const jsonUtil = require("../../resources/JsonUtil");
8
+
9
+ test("Find Ref", async () => {
10
+ const values = [];
11
+ jsonUtil.findAllValues(template.Resources.Function2.Properties, values, "Ref");
12
+ expect(values.length).toBe(2);
13
+ });
14
+
15
+ test("Find Fn::GetAtt", async () => {
16
+ const values = [];
17
+ jsonUtil.findAllValues(template.Resources.Function2.Properties, values, "Fn::GetAtt");
18
+ console.log(values);
19
+ expect(values.length).toBe(2);
20
+ });
21
+
22
+ test("Find Fn::Sub", async () => {
23
+ const values = [];
24
+ jsonUtil.findAllValues(template.Resources.Function2.Properties, values, "Fn::Sub");
25
+ expect(values.length).toBe(1);
26
+ });
27
+
28
+ // test("Find Ref in nested Join", async () => {
29
+ // const values = [];
30
+ // jsonUtil.findAllValues(template.Resources.Function2.Properties, values, "Fn::Sub");
31
+ // expect(values.length).toBe(1);
32
+ // });