UNPKG

10.2 kBJavaScriptView Raw
1var fillRefs, fs, getDescriptions, getSchemas, isAllowedTypeless, mergeAllOf, path, renderCapabilities, renderMessage, renderMessages, renderProperty, schemas,
2 hasProp = {}.hasOwnProperty;
3
4fs = require('fs');
5
6path = require('path');
7
8schemas = null;
9
10getSchemas = function() {
11 var dir, filename, i, jsonFile, len, name, ref, schema;
12 if (!schemas) {
13 schemas = {};
14 dir = './schema/json/';
15 ref = fs.readdirSync(dir);
16 for (i = 0, len = ref.length; i < len; i++) {
17 jsonFile = ref[i];
18 if (jsonFile !== '.' && jsonFile !== '..') {
19 name = jsonFile.split('.')[0];
20 filename = path.join(dir, jsonFile);
21 schema = JSON.parse(fs.readFileSync(filename));
22 schemas[name] = schema;
23 }
24 }
25 }
26 return schemas;
27};
28
29fillRefs = function(obj, baseUrl) {
30 var key, newObj, refKey, refObj, refValue, schemaPath, tv4, value;
31 tv4 = require('../schema/index.js');
32 if (typeof obj !== 'object') {
33 return obj;
34 } else if ((typeof obj) === 'object' && (obj.length != null)) {
35 return obj.map(function(item) {
36 return fillRefs(item, baseUrl);
37 });
38 }
39 newObj = {};
40 for (key in obj) {
41 if (!hasProp.call(obj, key)) continue;
42 value = obj[key];
43 if (key === '$ref') {
44 schemaPath = value;
45 if (schemaPath.indexOf('../') !== -1) {
46 schemaPath = path.resolve(path.dirname(`${baseUrl}${obj.id}`), value);
47 }
48 refObj = fillRefs(tv4.getSchema(schemaPath), baseUrl);
49 for (refKey in refObj) {
50 if (!hasProp.call(refObj, refKey)) continue;
51 refValue = refObj[refKey];
52 newObj[refKey] = refValue;
53 }
54 } else {
55 newObj[key] = fillRefs(value, baseUrl);
56 }
57 }
58 return newObj;
59};
60
61mergeAllOf = function(obj) {
62 var i, key, len, mergeObj, newObj, prop, propName, ref, value;
63 if (!(typeof obj === "object" && (obj.length == null))) {
64 return obj;
65 }
66 newObj = {};
67 for (key in obj) {
68 value = obj[key];
69 if (key === 'allOf') {
70 ref = obj[key];
71 for (i = 0, len = ref.length; i < len; i++) {
72 mergeObj = ref[i];
73 for (propName in mergeObj) {
74 prop = mergeObj[propName];
75 if (newObj[propName] == null) {
76 newObj[propName] = prop;
77 }
78 }
79 }
80 } else if (typeof value === "object" && (value.length == null)) {
81 newObj[key] = mergeAllOf(value);
82 } else {
83 newObj[key] = value;
84 }
85 }
86 return newObj;
87};
88
89// transforms schemas into format better suited to be added to docs
90getDescriptions = function(schemas) {
91 var categories, category, desc, event, i, key, len, message, messages, protocol, protocols, ref, ref1, schema, value;
92 desc = {};
93 protocols = {
94 runtime: ['input', 'output'],
95 graph: ['input'],
96 component: ['input', 'output'],
97 network: ['input', 'output'],
98 trace: ['input', 'output']
99 };
100 for (protocol in protocols) {
101 categories = protocols[protocol];
102 messages = {};
103 desc[protocol] = {
104 title: schemas[protocol].title,
105 description: schemas[protocol].description,
106 messages: messages
107 };
108 for (i = 0, len = categories.length; i < len; i++) {
109 category = categories[i];
110 ref = schemas[protocol][category];
111 for (event in ref) {
112 schema = ref[event];
113 schema = fillRefs(schema, `/${protocol}/`);
114 message = {
115 id: schema.id,
116 description: schema.description
117 };
118 if (schema.allOf != null) {
119 ref1 = schema.allOf[1].properties.payload;
120 //console.log 'sc', schema.allOf[1].properties
121 for (key in ref1) {
122 value = ref1[key];
123 message[key] = value;
124 }
125 }
126 //if event == 'error'
127 // console.log 'm', message
128 messages[event] = mergeAllOf(message);
129 }
130 }
131 }
132 return desc;
133};
134
135isAllowedTypeless = function(name, parent) {
136 if (parent.id === '/shared/port_definition' && name === 'default') {
137 return true;
138 }
139 if (parent.id === '/runtime/input/packet' && name === 'payload') {
140 return true;
141 }
142 if (parent.id === 'input/packet' && name === 'payload') {
143 return true;
144 }
145 if (parent.id === '/runtime/output/packet' && name === 'payload') {
146 return true;
147 }
148 if (parent.id === 'output/packet' && name === 'payload') {
149 return true;
150 }
151 if (parent.id === 'output/packetsent' && name === 'payload') {
152 return true;
153 }
154 return false;
155};
156
157renderProperty = function(name, def, parent) {
158 var classes, description, example, isOptional, ref, ref1, ref2, ref3, ref4, ref5, type;
159 if (!def.description) {
160 throw new Error(`Property ${name} is missing .description`);
161 }
162 if (!isAllowedTypeless(name, parent)) {
163 if (!def.type) {
164 throw new Error(`Property ${name} is missing .type`);
165 }
166 }
167 if (!parent) {
168 throw new Error(`Parent schema not specified for ${name}`);
169 }
170 if (parent.type === 'array') {
171 if (!((ref = parent.items) != null ? (ref1 = ref.required) != null ? ref1.length : void 0 : void 0)) {
172 throw new Error(`.required array not specified for ${name} of ${parent.id} (array)`);
173 }
174 } else {
175 if (((ref2 = parent.required) != null ? ref2.length : void 0) == null) {
176 console.log(JSON.stringify(parent, null, 2));
177 throw new Error(`.required array not specified for ${name} of ${parent.id}`);
178 }
179 }
180 isOptional = (parent.type === 'array' && ((ref3 = parent.required) != null ? ref3.indexOf(name) : void 0) === -1) || ((ref4 = parent.items) != null ? (ref5 = ref4.required) != null ? ref5.indexOf(name) : void 0 : void 0) === -1;
181 classes = "property";
182 if (isOptional) {
183 classes += " optional";
184 }
185 name = `<label class='${classes} name'>${name}</label>`;
186 type = `<label class='${classes} type'>${def.type || 'any'}</label>`;
187 description = `<label class='${classes} description'>${def.description}</label>`;
188 example = "";
189 if (def.example != null) {
190 example = `<code class='${classes} example'>${JSON.stringify(def.example)}</code>`;
191 }
192 return name + type + description + example;
193};
194
195renderMessage = function(messageType, message, protocolName) {
196 var anchorUrl, itemProp, itemPropName, itemSubProp, itemSubPropName, items, line, lines, messageId, messageProp, messagePropName, p, ref, ref1, ref2, ref3, subProp, subPropName;
197 lines = [];
198 p = function(line) {
199 return lines.push(line);
200 };
201 messageId = `${protocolName}-${messageType}`;
202 anchorUrl = '#' + messageId;
203 p(`<h3 id='${messageId}' class='message name'><a href='${anchorUrl}'>${messageType}</a></h3>`);
204 p(`<p>${message.description}</p>`);
205 p("<ul class='message properties'>");
206 ref = message.properties;
207 for (messagePropName in ref) {
208 messageProp = ref[messagePropName];
209 line = `<li>${renderProperty(messagePropName, messageProp, message)}</li>`;
210 items = messageProp.items;
211 if (messageProp.type === 'object' && (messageProp.properties != null)) {
212 p(line);
213 p("<ul class='properties'>");
214 ref1 = messageProp.properties;
215 for (subPropName in ref1) {
216 subProp = ref1[subPropName];
217 p(`<li>${renderProperty(subPropName, subProp, messageProp)}</li>`);
218 }
219 p("</ul>");
220 } else if ((items != null ? items.type : void 0) === 'object') {
221 line += "Each item contains:";
222 p(line);
223 p("<ul class='properties'>");
224 ref2 = items.properties;
225 for (itemPropName in ref2) {
226 itemProp = ref2[itemPropName];
227 if (itemProp.type === 'object') {
228 p(`<li>${renderProperty(itemPropName, itemProp, messageProp)}</li>`);
229 p("<ul class='properties'>");
230 ref3 = itemProp.properties;
231 for (itemSubPropName in ref3) {
232 itemSubProp = ref3[itemSubPropName];
233 p(`<li>${renderProperty(itemSubPropName, itemSubProp, itemProp)}</li>`);
234 }
235 p("</ul>");
236 } else {
237 p(`<li>${renderProperty(itemPropName, itemProp, messageProp)}</li>`);
238 }
239 }
240 p("</ul>");
241 } else {
242 p(line);
243 }
244 }
245 p("</ul>");
246 return lines;
247};
248
249renderCapabilities = function() {
250 var enumDescription, i, j, k, len, len1, len2, lines, messageUrl, name, p, ref, ref1, ref2, schema, tv4;
251 tv4 = require('../schema/index.js');
252 schema = tv4.getSchema('/shared/capabilities');
253 lines = [];
254 p = function(line) {
255 return lines.push(line);
256 };
257 p("<section class='capabilities'>");
258 ref = schema.items._enumDescriptions;
259 for (i = 0, len = ref.length; i < len; i++) {
260 enumDescription = ref[i];
261 p(`<h4 class='capability name'>${enumDescription.name}</h4>`);
262 p(`<p>${enumDescription.description}</p>`);
263 p("<h5 class='capability messages header'>input messages</h5>");
264 p("<ul class='capability messages'>");
265 ref1 = enumDescription.inputs;
266 for (j = 0, len1 = ref1.length; j < len1; j++) {
267 name = ref1[j];
268 messageUrl = "#" + name.replace(':', '-');
269 p(`<li><a href='${messageUrl}'>${name}</a></li>`);
270 }
271 p("</ul>");
272 p("<h5 class='capability messages header'>output messages</h5>");
273 p("<ul class='capability messages'>");
274 ref2 = enumDescription.outputs;
275 for (k = 0, len2 = ref2.length; k < len2; k++) {
276 name = ref2[k];
277 messageUrl = "#" + name.replace(':', '-');
278 p(`<li><a href='${messageUrl}'>${name}</a></li>`);
279 }
280 p("</ul>");
281 }
282 p("</section>");
283 return lines.join('\n');
284};
285
286renderMessages = function() {
287 var descriptions, lines, m, message, messageType, p, protocol, protocolProps, ref;
288 schemas = getSchemas();
289 descriptions = getDescriptions(schemas);
290 lines = [];
291 p = function(line) {
292 return lines.push(line);
293 };
294 for (protocol in descriptions) {
295 protocolProps = descriptions[protocol];
296 p(`<h2 class='protocol name'>${protocolProps.title}</h2>`);
297 p(`<p class='protocol description'>${protocolProps.description}</p>`);
298 ref = protocolProps.messages;
299 for (messageType in ref) {
300 message = ref[messageType];
301 m = renderMessage(messageType, message, protocol);
302 lines = lines.concat(m);
303 }
304 }
305 return lines.join('\n');
306};
307
308module.exports = {
309 renderMessages: renderMessages,
310 renderCapabilities: renderCapabilities,
311 getSchemas: getSchemas
312};