UNPKG

apib2go

Version:

Convert API Blueprint to golang routers

263 lines (220 loc) 7.65 kB
'use strict'; var stripJsonComments = require('strip-json-comments'); var helpers = require('./helpers').helpers; class Api { constructor(title) { this.title = title; this.resourceGroups = []; } } class ResGroup { constructor(title) { this.title = title; this.resources = []; } } class Resource { constructor(title, href, members) { this.title = title; this.href = href; this.members = members; this.transitions = []; } } class ResourceMember { constructor(description, keyType, key, valueType, value) { this.description = description; this.keyType = keyType; this.key = key; this.valueType = valueType; this.value = value; } } class Transition { constructor(title) { this.title = title; this.httpTransactions = []; } } class HttpTransaction { constructor() { } setRequest(req) { this.request = req; } setResponse(resp) { this.response = resp; } } class HttpRequest { constructor(method, requestContent) { this.method = method; this.requestContent = requestContent; } } class HttpResponse { constructor(statusCode, contentType, messageBody) { this.statusCode = statusCode; this.contentType = contentType; this.messageBody = messageBody; } } module.exports = class Accumulator { constructor() { this.currentApi = null; this.currentResGroup = null; this.currentResource = null; this.currentTransition = null; this.currentHttpTx = null; this.currentHttpReq = null; this.currentHttpResp = null; this.apis = []; } handleNode(node) { if (node.element === 'parseResult') { this.handleParseResultNode(node); } else if (node.element === 'category') { if (node.meta.classes.findIndex(c => c === 'api') !== -1) { this.handleApiNode(node); } else if (node.meta.classes.findIndex(c => c === 'resourceGroup') !== -1) { this.handleResourceGroupNode(node); } } else if (node.element === 'resource') { this.handleResourceNode(node); } else if (node.element === 'transition') { this.handleTransitionNode(node); } else if (node.element === 'httpTransaction') { this.handleHttpTransactionNode(node); } else if (node.element === 'httpRequest') { this.handleHttpRequestNode(node); } else if (node.element === 'httpResponse') { this.handleHttpResponseNode(node); } } handleParseResultNode(node) { node.content.forEach(contentNode => { this.handleNode(contentNode); }) } handleApiNode(node) { let prevApi = this.currentApi; this.currentApi = new Api(node.meta.title); this.apis.push(this.currentApi); node.content.forEach(contentNode => { this.handleNode(contentNode); }); this.currentApi = prevApi; } handleResourceGroupNode(node) { let prevResGroup = this.currentResGroup; this.currentResGroup = new ResGroup(node.meta.title); this.currentApi.resourceGroups.push(this.currentResGroup); node.content.forEach(contentNode => { this.handleNode(contentNode); }); this.currentResGroup = prevResGroup; } handleResourceNode(node) { let prevResource = this.currentResource; var members = []; if (node.attributes.hrefVariables) { node.attributes.hrefVariables.content.forEach(contentNode => { members.push(new ResourceMember( contentNode.meta.description, contentNode.content.key.element, contentNode.content.key.content, contentNode.content.value.element, contentNode.content.value.content)) }); } this.currentResource = new Resource(node.meta.title, node.attributes.href, members); this.currentResGroup.resources.push(this.currentResource); node.content.forEach(contentNode => { this.handleNode(contentNode); }); this.currentResource = prevResource; } handleTransitionNode(node) { let prevTransition = this.currentTransition; this.currentTransition = new Transition(node.meta.title); this.currentResource.transitions.push(this.currentTransition); node.content.forEach(contentNode => { this.handleNode(contentNode); }); this.currentTransition = prevTransition; } handleHttpTransactionNode(node) { let prevHttpTx = this.currentHttpTx; this.currentHttpTx = new HttpTransaction(); this.currentTransition.httpTransactions.push(this.currentHttpTx); node.content.forEach(contentNode => { this.handleNode(contentNode); }); this.currentHttpTx = prevHttpTx; } handleHttpRequestNode(node) { let prevHttpReq = this.currentHttpReq; let requestContent = null; if (node.content && node.content.length > 0) { let firstAssetNode = node.content.find(c => c.element === 'asset'); if (!firstAssetNode) { throw new Error("One of the httpRequest.content nodes must be of `element === 'asset'.") } var nodeClass = firstAssetNode.meta.classes[0]; switch (nodeClass) { case 'messageBodySchema': let fieldsMap = this.parseMessageBodySchemaForFieldsMap(firstAssetNode.content); requestContent = fieldsMap; break; case 'messageBody': requestContent = JSON.parse(stripJsonComments(firstAssetNode.content)); break; default: throw new Error("httpRequest.content asset node has unsupported meta.classes[0] value."); } } this.currentHttpReq = new HttpRequest(node.attributes.method, requestContent); this.currentHttpTx.setRequest(this.currentHttpReq); this.currentHttpReq = prevHttpReq; } handleHttpResponseNode(node) { let prevHttpResp = this.currentHttpResp; let contentType = null; if (node.attributes && node.attributes.headers) { node.attributes.headers.content.forEach(contentNode => { if (contentNode.content.key.content == 'Content-Type') { contentType = contentNode.content.value.content; } }); } let messageBody = null; if (node.content) { node.content.forEach(contentNode => { if (contentNode.element == 'asset' && contentNode.meta && contentNode.meta.classes && contentNode.meta.classes.findIndex(c => c === 'messageBody') !== -1) { var contentType = contentNode.attributes.contentType; if (contentType === 'application/json') { messageBody = JSON.parse(stripJsonComments(contentNode.content)); } else { throw new Error(`Http Response ContentType of '${contentType}' is not yet supported`) } } }); } this.currentHttpResp = new HttpResponse(node.attributes.statusCode, contentType, messageBody); this.currentHttpTx.setResponse(this.currentHttpResp); this.currentHttpResp = prevHttpResp; } parseMessageBodySchemaForFieldsMap(schemaText) { let shemaObj = JSON.parse(stripJsonComments(schemaText)); if (shemaObj.type !== 'object') { throw new Error(`JsonSchema of type '${shemaObj.type}' is not supported yet.`); } var fieldMap = {}; //TODO: We do not handle the `shemaObj.required` properties let propertiesMap = shemaObj.properties; for (var propName in propertiesMap) { var propType = propertiesMap[propName].type; fieldMap[propName] = propType; } return fieldMap; } }