1 |
|
2 | (function() {
|
3 | var CFN_FUNCS, INDENT, checkForParams, convertArray, convertCondition, convertFunction, convertJson, convertMapping, convertObj, convertOutput, convertParam, convertResource, convertToArgs, convertToCoffin, convertTopLevel, createForwardDeclrations, escapeString, fs, indent, isFunction, paramNames;
|
4 |
|
5 | fs = require("fs");
|
6 |
|
7 | paramNames = [];
|
8 |
|
9 | INDENT = " ";
|
10 |
|
11 | convertToArgs = function(string) {
|
12 | return string.replace("[", "").replace("]", "").replace(/\n$/, "");
|
13 | };
|
14 |
|
15 | CFN_FUNCS = {
|
16 | "Fn::Base64": function(obj, level, parentIsObj) {
|
17 | return "@Base64(" + (convertJson(obj["Fn::Base64"], level, parentIsObj)) + ")";
|
18 | },
|
19 | "Fn::FindInMap": function(obj, level, parentIsObj) {
|
20 | var string;
|
21 | string = convertJson(obj["Fn::FindInMap"], level, parentIsObj);
|
22 | return "@FindInMap(" + (convertToArgs(string)) + ")";
|
23 | },
|
24 | "Fn::GetAtt": function(obj, level, parentIsObj) {
|
25 | var string;
|
26 | string = convertJson(obj["Fn::GetAtt"], level, parentIsObj);
|
27 | return "@GetAtt(" + (convertToArgs(string)) + ")";
|
28 | },
|
29 | "Fn::GetAZs": function(obj, level, parentIsObj) {
|
30 | return "@GetAZs(" + (convertJson(obj["Fn::GetAZs"], level, parentIsObj)) + ")";
|
31 | },
|
32 | "Fn::Join": function(obj, level, parentIsObj) {
|
33 | var join, string;
|
34 | join = obj["Fn::Join"];
|
35 | string = convertJson(join[1], level, parentIsObj);
|
36 | return "@Join(\"" + (escapeString(join[0])) + "\", " + (string.replace(/\n$/, "")) + ")";
|
37 | },
|
38 | "Ref": function(obj) {
|
39 | if (paramNames.indexOf(obj.Ref) > -1) {
|
40 | return "@Params." + obj.Ref;
|
41 | } else if (obj.Ref === "AWS::Region") {
|
42 | return "@Region";
|
43 | } else if (obj.Ref === "AWS::StackName") {
|
44 | return "@StackName";
|
45 | } else {
|
46 | return "@Resources." + obj.Ref;
|
47 | }
|
48 | }
|
49 | };
|
50 |
|
51 | indent = function(text, times) {
|
52 | var front, i, j, ref;
|
53 | front = "";
|
54 | for (i = j = 0, ref = times; 0 <= ref ? j <= ref : j >= ref; i = 0 <= ref ? ++j : --j) {
|
55 | front += INDENT;
|
56 | }
|
57 | return front + text;
|
58 | };
|
59 |
|
60 | convertArray = function(arr, level, parentIsArray) {
|
61 | var addNewline, end, i, j, len, output, val;
|
62 | if (level == null) {
|
63 | level = 0;
|
64 | }
|
65 | if (arr.length > 5 || typeof arr[0] === "object") {
|
66 | addNewline = true;
|
67 | } else {
|
68 | addNewline = false;
|
69 | }
|
70 | output = "[";
|
71 | if (addNewline) {
|
72 | output += "\n";
|
73 | }
|
74 | i = arr.length;
|
75 | for (j = 0, len = arr.length; j < len; j++) {
|
76 | val = arr[j];
|
77 | if (addNewline) {
|
78 | output += indent((convertJson(val, level + 1, true)) + "\n", level);
|
79 | } else {
|
80 | if (--i) {
|
81 | output += (convertJson(val, level)) + ", ";
|
82 | } else {
|
83 | output += convertJson(val, level);
|
84 | }
|
85 | }
|
86 | }
|
87 | end = "]\n";
|
88 | if (parentIsArray) {
|
89 | end = "]";
|
90 | }
|
91 | if (addNewline) {
|
92 | end = indent(end, level - 1);
|
93 | }
|
94 | output += end;
|
95 | return output;
|
96 | };
|
97 |
|
98 | isFunction = function(obj) {
|
99 | var fun, j, len, ref;
|
100 | ref = Object.keys(CFN_FUNCS);
|
101 | for (j = 0, len = ref.length; j < len; j++) {
|
102 | fun = ref[j];
|
103 | if (obj[fun]) {
|
104 | return true;
|
105 | }
|
106 | }
|
107 | return false;
|
108 | };
|
109 |
|
110 | convertFunction = function(obj, level, parentIsObj) {
|
111 | var cfn, fun, output;
|
112 | output = null;
|
113 | for (cfn in CFN_FUNCS) {
|
114 | fun = CFN_FUNCS[cfn];
|
115 | if (obj[cfn]) {
|
116 | output = fun(obj, level, parentIsObj);
|
117 | }
|
118 | }
|
119 | return output;
|
120 | };
|
121 |
|
122 | convertObj = function(obj, level, parentIsObj) {
|
123 | var key, keyLength, output, val;
|
124 | if (level == null) {
|
125 | level = 0;
|
126 | }
|
127 | if (isFunction(obj)) {
|
128 | return indent(convertFunction(obj, level, parentIsObj));
|
129 | }
|
130 | if (parentIsObj) {
|
131 | output = "\n";
|
132 | } else {
|
133 | output = "";
|
134 | }
|
135 | keyLength = Object.keys(obj).length;
|
136 | for (key in obj) {
|
137 | val = obj[key];
|
138 | if (key.match(/\W/)) {
|
139 | key = "\"" + key + "\"";
|
140 | }
|
141 | output += indent(key + " : " + (convertJson(val, level + 1, true)), level);
|
142 | if (--keyLength) {
|
143 | output += "\n";
|
144 | }
|
145 | }
|
146 | return output;
|
147 | };
|
148 |
|
149 | escapeString = function(string) {
|
150 | return string.replace("\n", "\\n").replace(/'/g, "\\'").replace(/"/g, '\\"');
|
151 | };
|
152 |
|
153 | convertJson = function(obj, level, parentIsObj) {
|
154 | if (level == null) {
|
155 | level = 0;
|
156 | }
|
157 | if (Array.isArray(obj)) {
|
158 | return convertArray(obj, level, parentIsObj);
|
159 | } else if (typeof obj === "object") {
|
160 | return convertObj(obj, level, parentIsObj);
|
161 | } else if (typeof obj === "string") {
|
162 | return "\"" + (escapeString(obj)) + "\"";
|
163 | } else if (typeof obj === "number") {
|
164 | return obj;
|
165 | }
|
166 | };
|
167 |
|
168 | checkForParams = function(obj) {
|
169 | if (obj && Object.keys(obj).length) {
|
170 | return true;
|
171 | } else {
|
172 | return false;
|
173 | }
|
174 | };
|
175 |
|
176 | convertParam = function(name, val) {
|
177 | var output;
|
178 | if (!val.Type) {
|
179 | throw new Error("type is required for Param " + name);
|
180 | }
|
181 | paramNames.push(name);
|
182 | output = null;
|
183 | if (val.Description) {
|
184 | output = "@Param." + val.Type + " \"" + name + "\", \"" + val.Description + "\"";
|
185 | } else {
|
186 | output = "@Param." + val.Type + " \"" + name + "\"";
|
187 | }
|
188 | delete val.Type;
|
189 | delete val.Description;
|
190 | if (checkForParams(val)) {
|
191 | output += ",\n";
|
192 | output += convertJson(val);
|
193 | }
|
194 | return output + "\n\n";
|
195 | };
|
196 |
|
197 | convertMapping = function(name, val) {
|
198 | var output;
|
199 | output = "@Mapping \"" + name + "\",\n";
|
200 | output += convertJson(val);
|
201 | return output + "\n\n";
|
202 | };
|
203 |
|
204 | convertResource = function(name, val) {
|
205 | var output;
|
206 | if (!val.Type) {
|
207 | throw new Error("missing type for resource with " + name);
|
208 | }
|
209 | output = "@" + (val.Type.replace(/::/g, ".")) + " \"" + name + "\"";
|
210 | if (val.Metadata) {
|
211 | delete val.Type;
|
212 | if (checkForParams(val)) {
|
213 | output += ",\n";
|
214 | output += convertJson(val);
|
215 | }
|
216 | } else {
|
217 | if (checkForParams(val.Properties)) {
|
218 | output += ",\n";
|
219 | output += convertJson(val.Properties);
|
220 | }
|
221 | }
|
222 | return output + "\n\n";
|
223 | };
|
224 |
|
225 | convertOutput = function(name, val) {
|
226 | var output;
|
227 | if (!val.Value) {
|
228 | throw new Error("missing value for output with " + name);
|
229 | }
|
230 | if (val.Description) {
|
231 | output = "@Output \"" + name + "\", \"" + val.Description + "\",\n";
|
232 | } else {
|
233 | output = "@Output \"" + name + "\",\n";
|
234 | }
|
235 | output += convertJson(val.Value);
|
236 | return output + "\n\n";
|
237 | };
|
238 |
|
239 | convertCondition = function(name, intrinsicfn) {
|
240 | var output;
|
241 | if (!intrinsicfn) {
|
242 | throw new Error("missing intrinsicfn for condition with " + name);
|
243 | }
|
244 | output = "@Condition \"" + name + "\",";
|
245 | output += convertJson(intrinsicfn);
|
246 | return output + "\n\n";
|
247 | };
|
248 |
|
249 | convertTopLevel = function(params, converter) {
|
250 | var name, output, val;
|
251 | output = "";
|
252 | for (name in params) {
|
253 | val = params[name];
|
254 | output += converter(name, val);
|
255 | }
|
256 | return output;
|
257 | };
|
258 |
|
259 | createForwardDeclrations = function(resources) {
|
260 | var output, res, val;
|
261 | output = "";
|
262 | for (res in resources) {
|
263 | val = resources[res];
|
264 | output += "@DeclareResource(\"" + res + "\")\n";
|
265 | }
|
266 | return output;
|
267 | };
|
268 |
|
269 | convertToCoffin = function(templateObj) {
|
270 | var key, output, val;
|
271 | output = "";
|
272 | output += createForwardDeclrations(templateObj.Resources);
|
273 | for (key in templateObj) {
|
274 | val = templateObj[key];
|
275 | switch (key) {
|
276 | case "AWSTemplateFormatVersion":
|
277 | break;
|
278 | case "Description":
|
279 | output += "@Description \"" + val + "\"\n\n";
|
280 | break;
|
281 | case "Parameters":
|
282 | output += convertTopLevel(val, convertParam);
|
283 | break;
|
284 | case "Mappings":
|
285 | output += convertTopLevel(val, convertMapping);
|
286 | break;
|
287 | case "Resources":
|
288 | output += convertTopLevel(val, convertResource);
|
289 | break;
|
290 | case "Outputs":
|
291 | output += convertTopLevel(val, convertOutput);
|
292 | break;
|
293 | case "Conditions":
|
294 | output += convertTopLevel(val, convertCondition);
|
295 | break;
|
296 | default:
|
297 | console.log("don't have key " + key);
|
298 | }
|
299 | }
|
300 | return output;
|
301 | };
|
302 |
|
303 | module.exports = convertToCoffin;
|
304 |
|
305 | }).call(this);
|